zenghao616的个人空间 https://www.eechina.com/space-uid-25996.html [收藏] [复制] [RSS]

博客

FPGA混合设计方法

已有 1797 次阅读2011-3-17 19:58 |

小弟花了两个晚上的成果……

 

    在大型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;

最后连接图如下:

路过

鸡蛋

鲜花

握手

雷人

全部作者的其他最新博客

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

关于我们  -  服务条款  -  使用指南  -  站点地图  -  友情链接  -  联系我们
电子工程网 © 版权所有   京ICP备16069177号 | 京公网安备11010502021702
返回顶部