Note
由於 Quartus 的 VWF 仿真只能仿真很短的時間,而且 Vivado 仿真的時候也需要添加激勵信號,因此需要編寫 testbench 文件進行激勵仿真。
Testbench 文件結構#
編寫 testbench 的目的是為了測試 module 的功能、性能是否符合設計的預期。驗證設計的功能包括以下步驟:
- 產生合適的激勵波形:該激勵通常要覆蓋被測 HDL 模塊所有可能產生的輸入狀態;
- 將產生的激勵信號加入到 DUT 中並觀察其響應:即將 DUT 模塊例化的 Testbench 中,運行仿真測試;
- 將輸出的響應與期望值比較。
Testbench 的結構一般模塊如下:
``
module Test_bench_name();
// 01:信號或變量聲明定義
// --邏輯設計中輸入對應 reg 型
// --邏輯設計中輸出對應 wire 型
// 02:使用 ini[ti](https://bbs.elecfans.com/group_715)al 或 always 語句產生激勵
// 03:例化待測試DUT模塊
// 04:監控和比較輸出響應
endmodule
代碼示例#
時鐘激勵輸入示例#
/*----------------------------------------------------------------
時鐘激勵產生方法一:50%佔空比時鐘
----------------------------------------------------------------*/
parameter ClockPeriod=10; //參數化時鐘週期
initial
begin
clk_i=0;
forever#(ClockPeriod/2) clk_i = ~clk_i;
end
/*----------------------------------------------------------------
時鐘激勵產生方法二:50%佔空比時鐘
----------------------------------------------------------------*/
initial
begin
clk_i=0;
end
always #(ClockPeriod/2) clk_i=~clk_i;
/*----------------------------------------------------------------
時鐘激勵產生方法三:產生固定數量的時鐘脈衝
----------------------------------------------------------------*/
parameter ClockPeriod=10; //參數化時鐘週期
initial
begin
clk_i=0;
repeat(6)
#(ClockPeriod/2) clk_i=~clk_i;
end
/*----------------------------------------------------------------
時鐘激勵產生方法四:產生非佔空比為 50%的時鐘
----------------------------------------------------------------*/
parameter ClockPeriod=10; //參數化時鐘週期
initial
begin
clk_i=0;
forever
begin
#((ClockPeriod/2)-2) clk_i=0;
#((ClockPeriod/2)+2) clk_i=1;
end
end
復位激勵輸入示例#
/*----------------------------------------------------------------
復位信號產生方法一:異步復位
----------------------------------------------------------------*/
initial
begin
[rs](https://www.elecfans.com/tags/rs/)t_n_i=1;
#100; rst_n_i=0;
#100; rst_n_i=1;
end
/*----------------------------------------------------------------
復位信號產生方法二:同步復位
----------------------------------------------------------------*/
initial
begin
rst_n_i=1; clk_i = 0;
@(negedge clk_i)
rst_n_i=0;
#100; //固定時間復位
repeat(10) @(negedge clk_i); //固定週期數復位
@(negedge clk_i)
rst_n_i=1;
end
always #5 clk_i=~clk_i;
/*----------------------------------------------------------------
復位信號產生方法三:復位任務封裝
----------------------------------------------------------------*/
task reset;
input [31:0] reset_time; //復位時間可調,輸入復位時間
RST_ING=0; //復位方式可調,低電平或高電平
begin
rst_n=RST_ING; //復位中
#reset_time; //復位時間
rst_n_i=~RST_ING; //撤銷復位,復位結束
end
endtask
仿真控制語句和系統任務描述#
``
/*----------------------------------------------------------------
仿真控制語句及系統任務描述
----------------------------------------------------------------*/
$stop // 停止運行仿真,modelsim 中可繼續仿真
$stop(n) //帶參數系統任務,根據參數 0,1或2不同,輸出仿真信息
$finish //結束運行仿真,不可繼續仿真
$finish(n) //帶參數系統任務,根據參數 0,1或2不同,輸出仿真信息
//0:不輸出任何信息
//1:輸出當前仿真時刻和位置
//2:輸出當前仿真時刻、位置和仿真過程中用到的 memory 以及 CPU 時間的統計
$random //產生隨機數
$random % n //產生範圍-n 到 n 之間的隨機數
{$random} % n //產生範圍 0 到 n 之間的隨機數
/*----------------------------------------------------------------
文本讀取#
/*----------------------------------------------------------------
文本輸入方式:$readmemb/$readmemh
----------------------------------------------------------------*/
$readmemb/$readmemh("<數據文件名>",<存儲器名>);
$readmemb/$readmemh("<數據文件名>",<存儲器名>,<起始地址>);
$readmemb/$readmemh("<數據文件名>",<存儲器名>,<起始地址>,<結束地址>);
$readmemb:/*讀取二進制數據,讀取文件內容只能包含:空白位置,註釋行,二進制數
數據中不能包含位寬說明和格式說明,每個數字必須是二進制數字。*/
$readmemh:/*讀取十六進制數據,讀取文件內容只能包含:空白位置,註釋行,十六進制數
數據中不能包含位寬說明和格式說明,每個數字必須是十六進制數字。*/