# 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)