小弟花了兩個晚上的成果……
在大型FPGA的設(shè)計過程中,往往是采用的從上至下的混合設(shè)計方法,既是先
由頂層設(shè)計工程師將一個工程進(jìn)行整體的規(guī)劃布局,在畫好原理圖后,將原理圖
的各個部分(小的模塊)交由其他的工程師去完成,分別調(diào)試仿真成功之后,再
由頂層工程師相當(dāng)于是對工程進(jìn)行組裝,整體調(diào)試,驗(yàn)證設(shè)想。
那么在分由各個工程師完成的部分,不同的工程師可能用的不是同一種設(shè)計
方法,也可能不是同一種設(shè)計語言,那么頂層工程師就要對所有的不同的設(shè)計文
件進(jìn)行組裝,也就是設(shè)置自己的文件為編譯的頂層文件(相當(dāng)于是C語言里面的
main函數(shù)),然后以這個頂層文件為基準(zhǔn)進(jìn)行編譯(相當(dāng)于C語言里面main中的函
數(shù)調(diào)用),調(diào)用的模塊也可以不是同一種語言或者方法設(shè)計的,這樣就是實(shí)現(xiàn)了
在FPGA工程設(shè)計過程中在不同的組合方法,使得設(shè)計的效率提高。
具體的實(shí)現(xiàn)混合設(shè)計有幾種方法,其中一個是將設(shè)計的小模塊實(shí)例化,做成
一個實(shí)體,這個我還沒有試驗(yàn)過;第二種就是將寫好的代碼進(jìn)行圖元化,然后在頂層文件中調(diào)用這些圖元,組成你需要的邏輯功能電路。
小弟我用了第二種混合設(shè)計的方法,弄了一個很簡單的東西,VHDL語言寫的是BCD譯碼的數(shù)碼管顯示電路,verilog HDL寫的是按鍵消抖以及檢測按鍵的電路,然后分別對兩個文件進(jìn)行圖元化(File--Create/update--Create symbol files for current file),最后頂層的schematic file中調(diào)用這兩個圖元,連接即可,最后把這個.bdf文件設(shè)置為頂層文件,編譯配置即可。
按鍵代碼如下:
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; //復(fù)位信號,低電平有效
input sw1_n,sw2_n,sw3_n,sw4_n,sw5_n,sw6_n,sw7_n,sw8_n; //獨(dú)立按鍵
output led; //發(fā)光二極管,由按鍵控制,按下則置fan
wire [7:0] led; //最后是送到數(shù)碼管顯示的output端口
//全部做的是二級緩存結(jié)構(gòu)----------------------------------//
reg [7:0] key_rst;
always @(posedge clk or negedge rst_n)
if(!rst_n) //異步復(fù)位
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;
//兩次采集的值不同則產(chǎn)生一個時鐘周期的高脈沖//
wire [7:0] key_an = key_rst_r & (~key_rst);
//--------------------------------------------------//
reg [19:0] cnt; //計數(shù)寄存器
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;
//當(dāng)寄存器low_sw由1變成0時,led_ctrl的值變?yōu)楦撸S持一個時鐘周期//
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 //按鍵發(fā)生變化時LED做亮滅翻轉(zhuǎn)
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翻轉(zhuǎn)輸出
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譯碼,數(shù)碼管顯示電路代碼:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity shumaguan_prj is --實(shí)體申明
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'; ---數(shù)碼管的片選打開
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;
最后連接圖如下:
