我們利用 Verilog 完成電路設計後
必須要測試這個電路的所有功能和輸出是否和預期符合
因此我們可以撰寫 testbench 來去測試該電路模組的功能
本篇會假設事前已經完成了一個電路設計
(以下簡稱 DUT,Design Under Test,顧名思義就是待測試的電路設計)
所以主要會著重在 testbench 的撰寫來去測試這個 DUT
假設這是我的 DUT
(lab02.v)
module lab02(clk, A, B, C);
input clk, A;
output B, C;
reg B, C;
always@(posedge clk) begin
B <= A;
C <= B;
end
endmodule
然後在同個資料夾底下新建檔案 tb.v
步驟大概分為以下
- 先打上預期的 延遲時間單位 / 波型時間單位
- 似新建 Verilog 模組的撰寫,但注意 ( ) 內無需加入 parameter
- 將原本的 input 訊號線宣告為 reg,output 訊號線宣告為 wire
- 加入 DUT Module,並各自連接上在此模組對應宣告的 reg 和 wire 線
- 設定你想要的波型
1. 先打上預期的
延遲時間單位 / 波型時間單位
這邊可以自己設計想要的
舉個例子來說
`timescale 1ns / 100ps
(1 ns) 波型時間單位是什麼意思應該很好懂
就是你在跑模擬波型圖時,間隔一個時間單位會是多久
(100 ps) 延遲時間單位則是設定波型時
會利用例如 #1 讓某個訊號線在延遲一個時間單位後做對應動作
而這個 #1 所代表的時間單位即是你的延遲時間單位
2. 似新建 Verilog 模組的撰寫,但注意 ( ) 內無需加入 parameter
`timescale 1ns / 100ps
module tb();
endmodule
3. 將原本的 input 訊號線宣告為 reg,output 訊號線宣告為 wire
從 DUT 的宣告,可以知道 input 有 clk 和 A,output 則是 B 和 C
`timescale 1ns / 100ps
module tb();
reg clk, A; //input
wire B,C; //output
endmodule
4. 加入 DUT Module,並各自連接上在此模組對應宣告的 reg 和 wire 線
`timescale 1ns / 100ps
module tb();
reg clk, A; //input
wire B,C; //output
lab02 module1(.clk(clk), .A(A), .B(B), .C(C));
endmodule
5. 設定你想要的波型
主要會用到的有 initial 和 always
initial 就是初始化時用的
用法為 initial begin 初始化動作 end
例如
`timescale 1ns / 100ps
module tb();
reg clk, A; //input
wire B,C; //output
lab02 module1(.clk(clk), .A(A), .B(B), .C(C));
initial begin
clk <= 1'b0;
A <= 1'b0;
end
endmodule
即表示 clk 和 A 在初始時會被設定為 0
always 則是在每延遲指定時間單位時,執行指定之事件
用法為 always #延遲時間單位 執行事件;
`timescale 1ns / 100ps
module tb();
reg clk, A; //input
wire B,C; //output
lab02 module1(.clk(clk), .A(A), .B(B), .C(C));
initial begin
clk <= 1'b0;
A <= 1'b0;
end
always #2 A = ~ A;
always #1 clk = ~clk;
endmodule
即表示每經過 2 個延遲時間單位 (根據上面的設定即是 2 * 100ps = 200 ps)
A 會反轉
而每經過 1 個延遲時間單位 (即為 100 ps)
clk 會反轉
到這邊大致就完成了!
但這邊在額外介紹 $monitor()
()裡面就類似 C 的撰寫方式
即可在指定時間監控你想要觀察的數值
例如下方
`timescale 1ns / 100ps
module tb();
reg clk, A; //input
wire B,C; //output
lab02 module1(.clk(clk), .A(A), .B(B), .C(C));
initial begin
clk <= 1'b0;
A <= 1'b0;
end
always #2 A = ~ A;
always #1 clk = ~clk;
initial begin
$monitor("simtime = %g, A =%b, B =%b, C =%b", $time, A, B, C);
end
endmodule
當然前面也可以加上 #2 (#2 monitor(...))
就會變成在經過 2 個延遲時間單位後
輸出這段字串
ref:
How to write a testbench in Verilog?
留言
張貼留言