原创 FPGA学习笔记__混合设计方法

2011-3-17 20:01 2579 10 10 分类: FPGA/CPLD
小弟花了两个晚上的成果……

 


    在大型FPGA的设计过程中,往往是采用的从上至下的混合设计方法,既是先



由顶层设计工程师将一个工程进行整体的规划布局,在画好原理图后,将原理图



的各个部分(小的模块)交由其他的工程师去完成,分别调试仿真成功之后,再



由顶层工程师相当于是对工程进行组装,整体调试,验证设想。


 


    那么在分由各个工程师完成的部分,不同的工程师可能用的不是同一种设计



方法,也可能不是同一种设计语言,那么顶层工程师就要对所有的不同的设计文



件进行组装,也就是设置自己的文件为编译的顶层文件(相当于是C语言里面的



main函数),然后以这个顶层文件为基准进行编译(相当于C语言里面main中的函



数调用),调用的模块也可以不是同一种语言或者方法设计的,这样就是实现了



在FPGA工程设计过程中在不同的组合方法,使得设计的效率提高。


 


    具体的实现混合设计有几种方法,其中一个是将设计的小模块实例化,做成



一个实体,这个我还没有试验过;第二种就是将写好的代码进行图元化,然后在顶层文件中调用这些图元,组成你需要的逻辑功能电路。


 


小弟我用了第二种混合设计的方法,弄了一个很简单的东西,VHDL语言写的是BCD译码的数码管显示电路,verilog HDL写的是按键消抖以及检测按键的电路,然后分别对两个文件进行图元化(File--Create/update--Create
symbol files for current file),最后顶层的schematic file中调用这两个图元,连接即可,最后把这个.bdf文件设置为顶层文件,编译配置即可。


按键代码如下:


module
key_delay_prj3(


                         clk,rst_n,


                         sw1_n,sw2_n,sw3_n,sw4_n,sw5_n,sw6_n,sw7_n,sw8_n,


                         led


                         );


input clk; //主时钟信号,20MHZ


input rst_n;    //复位信号,低电平有效


input
sw1_n,sw2_n,sw3_n,sw4_n,sw5_n,sw6_n,sw7_n,sw8_n;   //独立按键


output  led;  //发光二极管,由按键控制,按下则置fan


wire [7:0] led;      //最后是送到数码管显示的output端口


 


//全部做的是二级缓存结构----------------------------------//


reg [7:0]
key_rst;


 


always @(posedge
clk or negedge rst_n)


  if(!rst_n)     //异步复位


        key_rst <= 8'b11111111;


  else key_rst <=
{sw1_n,sw2_n,sw3_n,sw4_n,sw5_n,sw6_n,sw7_n,sw8_n};


//------------------------------------------------------//         


reg [7:0]
key_rst_r;//每个时钟周期的上升沿将key_rst的值锁存到key_rst_r中


 


always @(posedge
clk or negedge rst_n)


  if(!rst_n)


        key_rst_r <= 8'b11111111;


  else


        key_rst_r <= key_rst;


       


//两次采集的值不同则产生一个时钟周期的高脉冲//


wire [7:0]
key_an = key_rst_r & (~key_rst);


 


//--------------------------------------------------//


reg [19:0] cnt;     //计数寄存器


 


always @(posedge
clk or negedge rst_n)


  if(!rst_n) 
cnt <= 20'd0;


  else if(key_an)  cnt <= 20'd0;


  else cnt <= cnt + 1'b1;


//-------------------------------------------------//


reg [7:0]
low_sw;


 


always @(posedge
clk or negedge rst_n)


  if(!rst_n)


        low_sw <= 8'b11111111;


  else if(cnt == 20'd1000000)  //每隔20ms锁存一次按键的值


        low_sw <=
{sw1_n,sw2_n,sw3_n,sw4_n,sw5_n,sw6_n,sw7_n,sw8_n};


       


//每个时钟周期的上升沿将low_sw的值锁存到low_sw_r中//          


reg [7:0]
low_sw_r;


 


always @(posedge
clk or negedge rst_n)


  if(!rst_n)


        low_sw_r <= 8'b11111111;


  else


        low_sw_r <= low_sw;


       


//当寄存器low_sw由1变成0时,led_ctrl的值变为高,维持一个时钟周期//


wire [7:0]
led_ctrl = low_sw_r[7:0] & (~low_sw[7:0]);


 


reg [7:0] d;


 


always @(posedge
clk or negedge rst_n)


  if(!rst_n) begin


        d <= 8'b00000000;


        end


  else begin         //按键发生变化时LED做亮灭翻转


        if(led_ctrl[0]) d[0] <= ~d[0];


        if(led_ctrl[1]) d[1] <= ~d[1];


        if(led_ctrl[2]) d[2] <= ~d[2];


        if(led_ctrl[3]) d[3] <= ~d[3];


        if(led_ctrl[4]) d[4] <= ~d[4];


        if(led_ctrl[5]) d[5] <= ~d[5];


        if(led_ctrl[6]) d[6] <= ~d[6];


        if(led_ctrl[7]) d[7] <= ~d[7];


         end


       


assign led[0] =
d[0] ? 1'b1 : 1'b0; //LED翻转输出


assign led[1] =
d[1] ? 1'b1 : 1'b0;


assign led[2] =
d[2] ? 1'b1 : 1'b0;


assign led[3] =
d[3] ? 1'b1 : 1'b0;


assign led[4] =
d[4] ? 1'b1 : 1'b0;


assign led[5] =
d[5] ? 1'b1 : 1'b0;


assign led[6] =
d[6] ? 1'b1 : 1'b0;


assign led[7] =
d[7] ? 1'b1 : 1'b0;


 


endmodule


 


BCD译码,数码管显示电路代码:


library ieee;


use
ieee.std_logic_1164.all;


use
ieee.std_logic_unsigned.all;


use
ieee.std_logic_arith.all;    


 


entity
shumaguan_prj is         --实体申明


port(


  clk:in std_logic;


  led_cs:out std_logic;


  key_in:in std_logic_vector(7 downto 0);


  disp 
:out std_logic_vector(7 downto 0)


  );


end
shumaguan_prj;


 


architecture rtl
of shumaguan_prj is


 


signal
key_in_buf:std_logic_vector(7 downto 0);---定义一个缓冲器


signal
disp_buf:  std_logic_vector(7 downto 0);---定义一个缓冲器


 


begin


key_in_buf <=
key_in;


 


disp <=
disp_buf;


 


led_cs <=
'1'; ---数码管的片选打开


process(clk)


begin


  if rising_edge(clk)  then


             case key_in_buf is


                              when
"00000001" => disp_buf<="11111001";--按键s1显示1


                              when
"00000010" => disp_buf    <=
"10100100";   --按键s2显示2


                   when "00000100"
=> disp_buf    <=
"10110000";


                   when "00001000"
=> disp_buf    <=
"10011001";


                   when "00010000"
=> disp_buf    <=
"10010010";


                   when "00100110"
=> disp_buf    <=
"10000010";


                   when "01000000"
=> disp_buf    <=
"11111000";


                   when "10000000"
=> disp_buf    <=
"10000000";                            


                   when others => disp_buf
<="11111111";


             end case;


  end if;  


end process;


end rtl;


最后连接图如下:e57e50e6-07cf-4f16-983e-075058b2c587.jpg


文章评论0条评论)

登录后参与讨论
我要评论
0
10
关闭 站长推荐上一条 /2 下一条