【VHDL設計—數字系統驗證】最新Testbench仿真教程

文章目錄

一、Testbench基本結構

二、常用產生激勵描述方式

三、產生復位信號的幾種方式

四、常用的Verilog調試語句

1、兩種調試信息打印語句——$display、$monitor

2、timescales

3、force與release

4、assign/deassign

測試練習

t1.v 代碼

tb_t1.v 代碼

仿真結果與分析

Testbench仿真詳細操作步驟

步驟一、找到並運行modelsim.exe

步驟二、新建工程

步驟三、添加源程序t1.v並編譯

步驟四、新建tb_t1.v,編寫代碼並編譯 

步驟五、Start Simulation開啓仿真並運行


一、Testbench基本結構

通常,Testbench沒有輸入與輸出端口,應包括信號或變量定義、產生激勵波形語句、例化設計模塊以及監控和比較響應輸出語句。

module test_bench;   
    //信號或變量定義聲明
    //使用initial或always語句來產生激勵波形
    //例化設計模塊
    //監控和比較輸出響應
endmodule

二、常用產生激勵描述方式

(1)產生時鐘的幾種方式

  1. initial,產生佔空比爲50%的時鐘
    initial
        begin
            clk = 0;
            #delay;
            forever
            #(period/2) clk = ~ clk;
        end
    
  2. always,產生佔空比爲50%的時鐘
    initial
    	clk = 0;
    always
    	#(period/2) clk = ~ clk;
    
  3. repeat,產生確定數目的時鐘脈衝
    initial
        begin
            clk = 0;
            repeat(6)
            #(period/2) clk = ~ clk;
        end
    
  4. 產生佔空比非50%的時鐘
    initial
    	clk = 0;
    always
        begin
            # 3  clk = ~ clk;
            # 2  clk = ~ clk;
        end
    

三、產生復位信號的幾種方式

  1. 異步復位
    initial
        begin
            rst = 1; 
            #100;            
            rst = 0;
            #500;
            rst = 1;
        end
    
  2. 同步復位1
    initial
        begin
    	    rst = 1; 
    	    @(negedge clk);  //等待時鐘下降沿          
    	    rst = 0;
    	    #30;
    	    @(negedge clk);  //等待時鐘下降沿
    	    rst = 1;
        end
    
  3. 同步復位2
    initial
        begin
    	    rst = 1; 
    	    @(negedge clk);  	     //等待時鐘下降沿          
    	    repeat(3) @(negedge clk);  //經過3個時鐘下降沿
    	    rst = 1;
        end
    

四、常用的Verilog調試語句

1、兩種調試信息打印語句——$display、$monitor

/*在終端上打印信號的ASCII值*/
initial begin
	$timeformat (-9,1, “ns”,12);           //設置輸出時鐘格式
	$display(“stime clk rst pause ms_h ms_l s_h s_l m_h m_l”); //顯示輸入的字符串
	$monitor(“%t %b %b %b %b %b %b %b %b”,    //設置輸出信號格式
$realtime,clock,reset,pause,ms_h,ms_l,s_h,s_l,m_h,m_l);     //指定輸出的信號
end
  • $display:將函數內部雙引號中的字符串輸出在終端上,而$monitor則不同,它的輸出是事件驅動的

上例代碼中,$monitor信號列表中$realtime信號的變化會觸發終端顯示事件的發生,每次$monitor的觸發將會把信號列表中的信號值顯示在終端中。

  • $monitor:語句中的“%”用於定義信號列表中信號的輸出格式。

例如,%t將信號按照時間格式輸出,%b將信號按照二進制格式輸出。另外Verilog HDL語言還提供了其它的輸出格式,比如%h:十六進制、%d:十進制、%o:八進制等。

add wave  -hex /pulse_out_top_inst/Act_x   //Act_x的波形數據將會以十六進制的方式顯示

add wave  -decimal /pulse_out_top_inst/Act_y  //Act_y的波形數據將會以十進制的方式顯示

2、timescales

'timescale 1ns/1ps                 //度量參考爲1ns,精度爲1ps

module testbench;
	…
    initial 
        begin
            #10 rst = 1;    //10個仿真時間延時,相當於10x1ns=10ns的仿真時間
	…
        end
    initial 
        begin
            //display語句將在每一個仿真推進布進中執行,也就是1ps執行一次
            $display (''%d, rst = %b"m $time, rst);
        end
endmodule
'timescale    reference_time / precision

其中,reference_time是單位時間的度量,precision決定了仿真的推進延遲精度,同時也要設置仿真的推進步進單位。

# 是延遲的意思,而#號後面的數字是延遲的數量,延遲的單位由`timescale控制

比如有:當代碼指定`timescale 1ns/1ps,那麼,#10就是延遲10ns的意思

PS:在同步時序數字邏輯電路的verilog代碼中,是不能加入“#”進行延遲,這不是代碼編寫階段能決定的。

3、force與release

module	testbench;
	...
	initial begin
		rst = 1;           //在仿真時間零點將rst賦值1
		force data = 101;   //在仿真時間零點強制使data爲101,並保持
		#30 rst = 0;      //在仿真絕對時間30將rst賦值0
		#50 release data;  //在仿真絕對時間80釋放
		...              //data值將保持直到下一個對它的賦值語句
		end
endmodule

forcerelease語句可以用來強制對執行過程中的reg或wire型信號量賦值。

這兩條語句共同完成一個強制賦值的過程。當一個被force的信號被release以後,這個信號將會保持當時的狀態直到下一個賦值語句產生爲止。

4、assign/deassign

module	testbench;
	...
	initial 
        begin
            rst = 1;           //在仿真時間零點將rst賦值1
            force data = 101;
            #30 rst = 0;        //在仿真絕對時間30將rst賦值0
            #30 release data;
            ...
		end
	initial 
        begin
		#20 assign rst = 1;  //此條語句覆蓋之前的賦值語句(即絕對時間零點的賦值)
		#30 rst = 0;        //絕對時間50對rst賦值0
		#50 release rst;     //絕對時間100釋放rst信號
endmodule

PS:assign/deassign語句與force/release語句相類似,不過assign/deassign語句只能對設計中的reg型信號賦值。它們常常用來設置輸入值。

 

測試練習

針對下面源程序,編寫testbench程序,並進行測試仿真。

  • t1.v 代碼

module t1(a,b,c,d,s1,s0,y);
	input a,b,c,d;
	input s0,s1;
	output y;
	reg y=0; //這裏要賦初值,不然仿真時就看不到y的輸出結果了
	always@(a,b,c,d,s1,s0)
		begin 
			case({s1,s0})
				2'b00: y<=a; // s1_s0 = 00時,y=a(這裏的下劃線指s1和s0間的拼接符)
				2'b01: y<=b; // s1_s0 = 01時,y=b
				2'b10: y<=c; // s1_s0 = 10時,y=c
				2'b11: y<=d; // s1_s0 = 11時,y=d
				default: y<=a; // 其他情況,y=a
			endcase
		end
endmodule

  • tb_t1.v 代碼

`timescale 1ns/1ps

module tb_t1();
  reg va,vb,vc,vd,s1,s0;
  t1 T1(.a(va),.b(vb),.c(vc),.d(vd),.s1(s1),.s0(s0));

  initial 
    begin
      va=0;
      vb=1;
      vc=0;
      vd=1;
    end
  
  initial 
    begin
      s1=0;
      #10 s1=1;
      #1 s1=0;
      #15 s1=1;
      #1 s1=0;
      #20 s1=1;
      #1 s1=0;
      #10 s1=1;
      #1 s1=0;
      #30 s1=1;
      #1 s1=0;
    end
  
  initial 
    begin
      s0=0;
      #18 s0=1;
      #1 s0=0;
      #8 s0=1;
      #1 s0=0;
      #30 s0=1;
      #1 s0=0;
      #40 s0=1;
      #1 s0=0;
    end
  
endmodule      

  • 仿真結果與分析

仿真前的波形時序圖分析(這裏,a即va,b即vb,c即vc,d即vd)

 

modelsim實際仿真結果

 

Testbench仿真詳細教程

步驟一、找到並運行modelsim.exe

如果安裝時Quartus II-12採用的是安裝程序默認的安裝目錄,modelsim.exe位置就在下面的目錄中,搜索的另一快捷方法如下。

C:\altera\14.0\modelsim_ase\win32aloem

只需複製上面的路徑,粘貼到Windows資源管理器的地址欄裏,就可以找到modelsim.exe了,如下圖: 

Windows資源管理器地址欄中輸入C:\altera\14.0\modelsim_ase\win32aloem

如果上面的方法不管用,建議使用Windows10自帶的搜索工具來搜索,如下圖:

Windows10自帶搜索工具—>搜索modelsim.exe

當然,如果你有Everything或者Listary這些強一點搜索軟件,也可以使用它們來搜索modelsim.exe,如何使用它們搜索這裏我就略過了。

 

  • 步驟二、新建工程

標題
標題

 

步驟三、添加源程序t1.v並編譯;

Add Existing File:添加現有文件

 

點擊Browse瀏覽並查找t1.v

 

找到並打開編寫好的t1.v文件

 

打開好編寫好的t1.v文件後,還要點擊OK

 

編譯tb_t1.v

 

調試信息顯示successful即爲編譯成功

 

步驟四、新建tb_t1.v,編寫代碼並編譯 

新建文件

 

新建文件名爲tb_t1.v

 

編寫tb_t1.v

 

編譯tb_t1.v

 

successful,tb_t1.v已經編譯成功

 

步驟五、Start Simulation開啓仿真並運行

以上兩個.v編譯無誤之後,執行主菜單中的Simulate的“Start Simulation”命令,打開開始仿真對話框,如下圖1,選擇頂層模塊中的tb_t1.v,如下圖2所示。

圖1

 

圖2

 

“sim”窗口視圖裏,右鍵“T1”--->"Add Wave"添加波形信號,如下圖。

sim視圖窗口!!!

 

添加波形注意窗口視圖是“sim”!!!

"Add Wave"之後,此時即可在新彈出的Wave窗口中看到已添加的全部信號,如此就不用我們一個一個add wave了,如下圖。

 

Add Wave之後的Wave視圖窗口

 

單擊工具欄中的下圖中圈起來的圖標,就能看見Testbench仿真的最終結果了。

點擊該圖標,即可運行仿真

 

剛出來的仿真結果,波形的尺度太大,導致看起來不對勁(但是請注意:這不代表仿真運行失敗)。

剛出來的仿真結果

 

其實,尺度給放大了,我們調小就行了,那怎麼快速調小呢?很簡單,點擊下圖中放大鏡工具條中圈起來的圖標,這樣就可以縮小波形尺度,從而看到我們理想的波形了,如下圖。

放大鏡工具條

 

縮小波形尺度後,仿真顯示的波形正常顯示在我們眼前了

 


PS:有一步可能你們會遇到問題,那就是Start Simulation之後work模塊裏面看不到tb_t1.v,從而進行不了仿真,這個我也遇見過,

仿真步驟中可能會遇到的問題

 

如遇到問題,評論區下或者私信回覆我哦!我會盡快回復的,(#^.^#)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章