VHDL與Verilog硬件描述語言在數字電路的設計中使用的非常普遍,無論是哪種語言,仿真都是必不可少的。而且隨著設計復雜度的提高,仿真工具的重要性就越來越凸顯出來。在一些小的設計中,用TestBench來進行仿真是一個很不錯的選擇。VHDL與Verilog語言的語法規則不同,它們的TestBench的具體寫法也不同,但是應包含的基本結構大體相似,在VHDL的仿真文件中應包含以下幾點:實體和結構體聲明、信號聲明、頂層設計實例化、提供激勵;Verilog的仿真文件應包括:模塊聲明、信號聲明、頂層設計實例化、提供激勵。大致思想都是相似的。
簡單的說,TestBench就是一種驗證手段,從軟件層面對設計的硬件電路進行仿真。具體來講,一般是在你的仿真文件里,產生激勵信號,作用于被仿真的設計文件DUT(Design Under Test),產生相應的輸出,然后根據輸出信號檢驗設計的電路是否存在問題或者存在哪些問題。
下面以FPGA板中驅動流水燈的一段程序為例,簡單介紹一下兩種語言的TestBench的編寫。
1 module led_run(clk,rst,led); 2 input clk,rst; 3 output reg [7:0] led; 4 reg [25:0] clk_cnt; 5 reg clk_tmp; 6 reg [3:0] temp; 7 8 always@(posedge clk or negedge rst) 9 begin 10 if(!rst) 11 begin 12 clk_cnt<=26'd0; 13 clk_tmp<=1'b1; 14 end 15 else 16 begin 17 if(clk_cnt==26'b11111111111111111111111111) 18 begin 19 clk_cnt<=26'd0; 20 clk_tmp<=~clk_tmp; 21 end 22 else 23 clk_cnt<=clk_cnt+1'b1; 24 end 25 end 26 27 always@(posedge clk_tmp or negedge rst) 28 begin 29 if(!rst) 30 temp<=4'd15; 31 else 32 temp<=temp+1'b1; 33 end 34 35 always@(temp) 36 begin 37 case(temp) 38 4'd0 :led<=8'b11111110; 39 4'd1 :led<=8'b11111100; 40 4'd2 :led<=8'b11111000; 41 4'd3 :led<=8'b11110000; 42 4'd4 :led<=8'b11100000; 43 4'd5 :led<=8'b11000000; 44 4'd6 :led<=8'b10000000; 45 4'd7 :led<=8'b00000000; 46 4'd8 :led<=8'b00000001; 47 4'd9 :led<=8'b00000011; 48 4'd10:led<=8'b00000111; 49 4'd11:led<=8'b00001111; 50 4'd12:led<=8'b00011111; 51 4'd13:led<=8'b00111111; 52 4'd14:led<=8'b01111111; 53 4'd15:led<=8'b11111111; 54 default:; 55 endcase 56 end 57 58 endmodule
上面是一段流水燈的代碼,控制8位流水燈依次點亮,再依次熄滅。第一個always語句完成分頻功能,第二個always語句用于計數,共16個值,第三個always語句根據計數的值選擇LED燈的狀態。其中clk、rst分別為時鐘和復位信號,led為驅動流水燈的輸出信號。接下來針對這一設計編寫其TestBench文件。
1 /************TestBench*************/ 2 module tb_led_run; 3 reg clk,rst; 4 wire led; 5 6 initial 7 begin 8 rst=1; 9 #30 rst=0; 10 #40 rst=1; 11 end 12 13 initial 14 begin 15 clk=1; 16 forever #20 clk=~clk; 17 end 18 19 led_run led1(.clk(clk),.rst(rst),.led(led)); 20 endmodule
由于只需要時鐘和復位信號即可,故在其仿真文件并不復雜,建立測試模塊,進行信號聲明,在兩個initial中分別提供clk和rst信號,最后進行例化。當然注意一點,在仿真時要把分頻模塊去掉,或者將分頻系數改小,否則仿真時不容易觀察波形。下面是在Modelsim中仿真得到的波形(分頻模塊改為2分頻)。
總結起來,Verilog的TestBench有著相對固定的寫法:
module test_bench; 端口聲明語句 initial begin 產生時鐘信號 end initial begin 提供激勵源 end 例化語句 endmodule
最主要的是在initial語句中進行激勵的生成,這要根據具體的設計來分析。
下面對比介紹VHDL語言TestBench的寫法。同樣的功能,驅動流水燈,VHDL的程序如下:
1 LIBRARY IEEE; 2 USE IEEE.STD_LOGIC_1164.ALL; 3 USE IEEE.STD_LOGIC_UNSIGNED.ALL; 4 5 ENTITY led_run IS 6 PORT(clk:in std_logic; 7 rst:in std_logic; 8 led:out std_logic_vector(7 downto 0):="11111111" ); 9 END led_run; 10 11 ARCHITECTURE arc_led_run OF led_run IS 12 signal temp:std_logic_vector(3 downto 0); 13 signal clk_cnt:std_logic_vector(25 downto 0); 14 signal clk_tmp:std_logic:='1'; 15 BEGIN 16 divider:PROCESS(clk,rst) 17 BEGIN 18 if(rst='0') then 19 clk_cnt<="00000000000000000000000000"; 20 elsif(clk'event and clk='1') then 21 clk_cnt<=clk_cnt+1; 22 if(clk_cnt="11111111111111111111111111") then 23 clk_cnt<="00000000000000000000000000"; 24 clk_tmp<=NOT clk_tmp; 25 end if; 26 end if; 27 END PROCESS; 28 29 PROCESS(clk_tmp,rst) 30 BEGIN 31 if(rst='0') then 32 temp<="1111"; --all the led off 33 elsif(clk_tmp'event and clk_tmp='1') then 34 temp<=temp+1; 35 end if; 36 END PROCESS; 37 38 PROCESS(temp) 39 BEGIN 40 case temp is 41 when"0000"=>led<="11111110"; 42 when"0001"=>led<="11111100"; 43 when"0010"=>led<="11111000"; 44 when"0011"=>led<="11110000"; 45 when"0100"=>led<="11100000"; 46 when"0101"=>led<="11000000"; 47 when"0110"=>led<="10000000"; 48 when"0111"=>led<="00000000"; 49 when"1000"=>led<="00000001"; 50 when"1001"=>led<="00000011"; 51 when"1010"=>led<="00000111"; 52 when"1011"=>led<="00001111"; 53 when"1100"=>led<="00011111"; 54 when"1101"=>led<="00111111"; 55 when"1110"=>led<="01111111"; 56 when"1111"=>led<="11111111"; 57 when others=>NULL; 58 end case; 59 END PROCESS; 60 61 END arc_led_run;
根據語法要求,首先聲明庫,接著定義實體和結構體。在結構體中用三個進程(PROCESS)分別實現分頻、計數、流水燈狀態分配的功能,功能相當于上面Verilog程序中的三個always語句。接下來寫TestBench文件:
1 ---------------TestBench----------------- 2 LIBRARY IEEE; 3 USE IEEE.STD_LOGIC_1164.ALL; 4 5 6 ENTITY tb_led_run IS --空實體 7 END tb_led_run; 8 9 10 ARCHITECTURE arc_tb_led_run OF tb_led_run IS --結構體 11 12 COMPONENT led_run IS --元件聲明 13 PORT(clk:in std_logic; 14 rst:in std_logic; 15 led:out std_logic_vector(7 downto 0)); 16 END COMPONENT; 17 18 signal clk,rst:std_logic; 19 signal led:std_logic_vector(7 downto 0); 20 constant clk_period:time:=5 ns; 21 22 BEGIN 23 24 DUT:led_run PORT MAP(clk=>clk,rst=>rst,led=>led); --元件例化 25 26 clk_gen:PROCESS 27 BEGIN 28 clk<='1'; 29 wait for clk_period/2; 30 clk<='0'; 31 wait for clk_period/2; 32 END PROCESS; 33 34 tb:PROCESS 35 BEGIN 36 rst<='0'; 37 wait for 12 ns; 38 rst<='1'; 39 wait; 40 END PROCESS; 41 42 END arc_tb_led_run;
在這個TestBench中同樣只需要提供clk和rst信號,分別在兩個進程實現,Modelsim中的仿真結果如下(同樣在仿真的時候將分頻系數改為2):
總結一下,VHDL的TestBench寫法也有相對固定的格式:
View Code
相對與Verilog語言來說,VHDL的TestBench除了自身的庫聲明以及Entity和Architecture之外,還需要進行元件的聲明,即將被測試的設計聲明為一個元件,然后對其例化。在激勵的產生方面與Verilog思路相同。
從上面的程序可以看出,Verilog語言相對比較隨意一些,從C語言編程中繼承了多種操作符和結構;而VHDL的語法則比較嚴謹,有固定的格式。但在功能的實現上二者大同小異。比如Verilog中的always語句,在VHDL中可以找到PROCESS與之對應,當然更多的是不同。兩種語言均可在不同的抽象層次對電路進行描述:系統級、算法級、寄存器傳輸級、邏輯門級和開關電路級,但是VHDL更擅長系統級,而Verilog更方便底層描述。在學習硬件描述語言的時候不妨對比學習一下,相信會對電路設計的理解更加深一層。
審核編輯:湯梓紅
-
FPGA
+關注
關注
1629文章
21736瀏覽量
603385 -
仿真
+關注
關注
50文章
4082瀏覽量
133607 -
Verilog
+關注
關注
28文章
1351瀏覽量
110100 -
vhdl
+關注
關注
30文章
817瀏覽量
128137 -
數字電路
+關注
關注
193文章
1605瀏覽量
80622
原文標題:VHDL與Verilog硬件描述語言TestBench的編寫
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論