一、testbench基本結構
通常,testbench沒有輸入與輸出端口,應包括信號或變量定義、產生激勵波形語句、例化設計模塊以及監控和比較響應輸出語句。
module test_bench;
//信號或變量定義聲明
//使用initial或always語句來產生激勵波形
//例化設計模塊
//監控和比較輸出響應
endmodule
二、常用產生激勵描述方式
(1)產生時鐘的幾種方式
- initial,產生佔空比爲50%的時鐘
initial begin clk = 0; #delay; forever #(period/2) clk = ~ clk; end
- always,產生佔空比爲50%的時鐘
initial clk = 0; always #(period/2) clk = ~ clk;
- repeat,產生確定數目的時鐘脈衝
initial begin clk = 0; repeat(6) #(period/2) clk = ~ clk; end
- 產生佔空比非50%的時鐘
initial clk = 0; always begin #3 clk = ~ clk; #2 clk = ~ clk; end
(2)產生復位信號的幾種方式
- 異步復位
initial begin rst = 1; #100; rst = 0; #500; rst = 1; end
- 同步復位①
initial begin rst = 1; @(negedge clk); //等待時鐘下降沿 rst = 0; #30; @(negedge clk); //等待時鐘下降沿 rst = 1; end
- 同步復位②
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
force與release語句可以用來強制對執行過程中的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型信號賦值。它們常常用來設置輸入值。