# Testbench
## 簡介
> * Testbench 主要用來測試我們所實作的 module 功能是否正確,藉由設定要輸入給電路的信號線,再將信號線連接給目前要測的 module ,並連接 module 的 output port,即可觀察 output port 的 value 變化。[color=#f2abc5]
> * 下面將會以 comparator 的 testbench 作為範例,並介紹應該注意的地方。
---
:::info
```
下面是我們想要驗證的 comparator module。
```
```verilog=
module comparator( A, B, gt, lt, eq );
input A, B;
output gt, lt, eq;
assign gt = (A>B) ? 1'b1 : 1'b0 ;
assign lt = (A<B) ? 1'b1 : 1'b0 ;
assign eq = (A==B) ? 1'b1 : 1'b0 ;
endmodule
```
:::
:::success
```
測試 comparator 是否正確的 testbench
```
```verilog=
`timescale 1ns / 1ps
module tb_cmp;
reg A, B;
wire gt, lt, eq;
comparator cmp_test(.A(A), .(B)B, .gt(gt), .(lt)lt, .eq(eq));
initial begin
#2 A = 1'b0; B = 1'b0;
#2 $display("A=%b, B=%b, gt=%b, lt=%b, eq=%b\n",A ,B ,gt ,lt ,eq);
#2 A = 1'b1; B = 1'b0;
#2 $display("A=%b, B=%b, gt=%b, lt=%b, eq=%b\n",A ,B ,gt ,lt ,eq);
#2 A = 1'b0; B = 1'b1;
#2 $display("A=%b, B=%b, gt=%b, lt=%b, eq=%b\n",A ,B ,gt ,lt ,eq);
#2 A = 1'b1; B = 1'b1;
#2 $display("A=%b, B=%b, gt=%b, lt=%b, eq=%b\n",A ,B ,gt ,lt ,eq);
end
endmodule
module tb_cmp2;
reg A, B;
wire gt, lt, eq;
integer i, j;
comparator cmp_test(.A(A), .(B)B, .gt(gt), .(lt)lt, .eq(eq));
initial begin
#20 $display("--------------------\n");
A = 1'b1 ; B =1'b1 ;
for(i = 0 ; i < 2 ; i = i+1 )begin
A = A+1'b1 ;
for( j = 0 ; j < 2 ; j = j+1)begin
B = B+1'b1 ;
#2 $display("A=%b, B=%b, gt=%b, lt=%b, eq=%b\n",A ,B ,gt ,lt ,eq);
end
end
end
endmodule
```
結果顯示 :
![](https://i.imgur.com/ItkuzDO.png)
:::
> * 首先,我們必須先了解 testbench 的架構圖。由下面 testbench 的示意圖,我們注意到 testbench 是沒有 input 和 output 的。所以,當我們想要寫一個 testbench 的 module 時,應是像下面程式碼一樣的型式。
> ```verilog=
> module tb_cmp;
>
> ... ...
> ... ...
>
> endmodule
> ```
> * 示意圖 :
> ![](https://i.imgur.com/8oZB2rR.png)
> * 接下來,我們將會從一開始一步步地介紹程式碼。
> * 我們會從最上方的 Timescale 看到最後的 $finish :
>
```verilog
`timescale 1ns/1ps
```
> * Timescale (上方程式碼):
> - 1ns / 1ps <=> 時間單位 / 精準度。
> 1. 時間單位,假設當 cyc = 10,代表一個 clock cycle time 為 10 個 ns 。
> 2. 精準度,代表最低可以設多少時間。
當精準度為 1ps,代表最低可以設 0.001 ns。
```verilog
Example :
parameter delay = 10;
#(2) A = 1'b0; B = 1'b0;
#(delay) ...
```
> * `#` Delay :hatched_chick: :
> - 使用語法為,#(number)。
> - `#`表示延遲時間,比方說,`#20`代表我們想要讓程式碼 delay 20ns。(因為我們 timescale 設定 1 時間單位為 1ns。)
> - 也可以使用`#(parameter)`,方便檢視與更改。
```verilog
comparator cmp_test(A, B, gt, lt, eq);
```
> * module connection :
> 請參考 [module connection](https://hackmd.io/KYQ2GYE4DYBMFYC0AOEB2ATIgLM+XkElYAjTbAYw2gAZYR4g)。
```verilog
$display("A=%b, B=%b, gt=%b, lt=%b, eq=%b\n",A ,B ,gt ,lt ,eq);
```
>
> * $display :
> * 用法相似於 c 語言的 printf 。
> * 好處是可以直接明白地看到接入及輸出的值,但輸入一次只能印一次。所以,如果要抓好變動的話,可以與時間搭配著一起印,便可清楚知道程式碼跑到哪,輸出為何。
> * [Display 參考資料](http://verilog.renerta.com/source/vrg00013.htm)
> * integer type 簡介 :
> * 通常用於 for loop 中,不太常使用。所以僅連結到外部,提供大家參考。
> * [integer type 參考資料](http://www.cnblogs.com/oomusou/archive/2008/05/27/verilog_integer.html)
> * for loop 簡介 :
> * for loop ==只能在 block 中使用== ( always block / initial block)。
> * ==實作上不建議同學使用==,可能會發生錯誤。建議同學若要使用 for loop 僅在 testbench 使用就好。
> * 另外,repeat (number) begin ... statement ... end
> 也可以做到 for loop 效果。
> * [for loop 參考資料](https://puremonkey2010.blogspot.tw/2013/11/verilog-tutorial-always-ifelse-case-for.html)
> * [repeat 參考資料](http://electrosofts.com/verilog/loop_statements.html)
> * [asic-world 迴圈介紹 ](http://www.asic-world.com/verilog/verilog_one_day2.html)
> * initial block :
> - 請參考[描述電路的三種層次](https://hackmd.io/GYDgRghsYCxgtGAjHeMAmIBMiQE4R4l0SA2ABgHYkBjGmGoA)。
> * $time :
> * 從程式開始跑到目前所經過的時間。
> * 可用時間與輸入訊號、輸出訊號同步印出,檢查是否在適當地時間點輸出出正確的值。
> * $finish :
> * 結束程式。
---
## ==LAB2 更新部分==
> * sdf :
> 這次 LAB 我們會使用到 Design vision 的工具,且合成出程式檔。但我們仍然要確認它的正確性,因此,我們需要在我們的 Tb 中微調,如以下範例:(也可以參考助教提供的 Testbench)
:::success
==加入並連結 sdf,並且注意要使用上面的 module instance name !==
![](https://i.imgur.com/K51bNbs.png)
:::
## ==LAB3 更新部分==
> 利用此行模擬 clk 週期行為。
>
![](https://i.imgur.com/rujP2IW.png)
>主要增加下圖中的 40, 42, 44行,因為這次使用 nWave 工具,需要將 fsdb 檔(波形檔)存起來。
>
![](https://i.imgur.com/pwcAHOC.png)
# [Home Page:hatched_chick: ](https://hackmd.io/s/BkYeCF5Og)