編寫高效率的testbench_第1頁
編寫高效率的testbench_第2頁
編寫高效率的testbench_第3頁
編寫高效率的testbench_第4頁
編寫高效率的testbench_第5頁
已閱讀5頁,還剩11頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、Writing Efficient Testbenches編寫高效的測試設計(testbenches)原文作者:Mujtaba Hamid注:一個設計的測試驗證是非常重要的。有效的測試可以助我們快速的完成或改善設計。Testbenches建議編寫有效的測試代碼來通過軟件實現可靠的驗證。無意中發現,順手譯為中文,以備將來方便。也貼給沒有找到更好中文版本的同道人。Testbenches本意應該是測試平臺更合理,但是在中文中閱讀起來很不舒服。所以本文中有時譯為“測試設計”,“測試代碼”,有時干脆是“測試”。摘要:應用筆記為HDL驗證設計的新手,或者是沒有豐富的測試設計經驗的邏輯設計者而編寫。測試設計

2、是驗證HDL設計的主要手段。本應用筆記為創建或準備和構建有效的測試設計提供準則。它也提供一個為任何設計開發自較驗測的測試設計的一個代數方法。涉及的所有設計文件可以從以下的站點獲得:PC: 簡介:由于設計的規模越來越大也越來越復雜,數字設計的驗證已經成為一個日益困難和繁瑣的任務。驗證工程師們依靠一些驗證工具和方法來應付這個挑戰。對于幾百萬門的大型設計,工程師們一般使用一套形式驗證(formal verification)工具。然而對于一些小型的設計,設計工程師常常發現用帶有testbench的HDL仿真器就可以很好地進行驗證。Testbench已經成為一個驗證高級語言(HLL -High-Lev

3、el Language) 設計的標準方法。通常testbench完成如下的任務:1. 實例化需要測試的設計(DUT);2. 通過對DUT模型加載測試向量來仿真設計;3. 將輸出結果到終端或波形窗口中加以視覺檢視;4. 另外,將實際結果和預期結果進行比較。通常testbench用工業標準的VHDL或Verilog硬件描述語言來編寫。Testbench調用功能設計,然后進行仿真。復雜的testbench完成一些附加的功能例如它們包含一些邏輯來選擇產生合適的設計激勵或比較實際結果和預期結果。后續的章節描述了一個仔細構建的testbench的結構,并且提供了一個自動比較實際結果與預期結果的進行自我檢查

4、的testbench例子。圖1給出了一個如上所描述步驟的標準HDL驗證流程。由于testbench使用VHDL或Verilog來描述,testbench的驗證過程可以根據不同的平臺或不同的軟件工具實現。由于VHDL或Verilog是公開的通用標準,使用VHDL或Verilog編寫的testbench以后也可以毫無困難地重用(reuse)。圖1使用Testbench的HDL驗證流程構建TestbenchTestbench用VHDL或Verilog來編寫。由于testbench只用來進行仿真,它們沒有那些適用于綜合的RTL語言子集的語法約束限制,而是所有的行為結構都可以使用。因而testbench

5、可以編寫的更為通用,使得它們可以更容易維護。所有testbench包含了如表1的基本程序段。正如上面所提到的,testbench通常包含附加功能,如在終端上可視的結果和內建的錯誤檢測。表1 testbench的基本程序段下面的例子介紹testbench中經常使用的結構。產生時鐘信號使用系統時鐘的時序邏輯設計必須產生時鐘。時鐘信號在VHDL或Verilog中可以很容易地實現。以下是VHDL和Verilog的時鐘發生示例。VHDL:- Declare a clock period constant.Constant ClockPeriod : TIME := 10 ns;- Clock Gener

6、ation method 1:Clock = not Clock after ClockPeriod / 2;- Clock Generation method 2:GENERATE CLOCK: processbeginwait for (ClockPeriod / 2)Clock = 1;wait for (ClockPeriod / 2)Clock = 0;end process;Verilog:/ Declare a clock period constant.Parameter ClockPeriod = 10;/ Clock Generation method 1:initial

7、beginClock = 0;forever Clock = #(ClockPeriod / 2) Clock;end/ Clock Generation method 2:always #(ClockPeriod / 2) Clock = Clock;提供激勵信號為了獲得testbench的驗證結果,激勵必須作用于DUT。在testbench中使用的并行激勵塊提供必要的激勵。激勵的產生可以采用兩個方法:絕對時間激勵和相對時間激勵。在第一個方法里,仿真變量相對于仿真時間零點進行詳細描述。相對而言,相對時間激勵提供初始值,然后等待一個事件來重新觸發激勵。根據設計者的需要,兩種方法可以在testb

8、ench中同時使用。下面的程序段是絕對時間激勵的例子。initial beginreset = 1;load = 0;cout_updn = 0;#100 reset = 0;#20 load = 1;#20 count_updn = 1;end下面的程序段是相對時間激勵的例子。always (posedge clock)tb_count = tb_count + 1;initial beginif(tb_count = 5)beginreset = 1;load = 0;count_updn = 0;endelsebegin reset = 0;load = 1;count_updn = 1

9、;endendinitial begin if(count = 1100) begincount_updn = 0;$display(“Terminal count Reached,now counting down”); endendVerilog的initial塊與文件中的其他initial塊是同時執行。然而,在每一個initial塊中,事件是按照書寫的順序執行的。這說明在每一個并行塊中的激勵序列從序仿真時間零點開始。為了代碼有更好的可讀性和更方便的可維護性,應采用多個塊來分割復雜的測試激勵。顯示結果在Verilog中可以非常方便地使用系統函數$display()和$monitor()顯示

10、結果。VHDL沒有等效的顯示指令,它提供了std_textio標準文本輸入輸出程序包。它允許文件的i/o重定向到顯示終端窗口(作為這個技術的示例,參看下面的自較驗查驗證設計)下面是verilog示例,它將在終端屏幕上顯示一些值。/ pipes the ASCII results to the terminal or text editorinitial begin$timeformat(-9,1,ns,12);$display( Time Clk Rst Ld SftRg Data Sel);$monitor(%t %b %b %b %b %b %b, $realtime,clock, res

11、et, load, shiftreg, data, sel);end系統函數$display在終端屏幕上輸出引用的附加說明文字(“?!保?。系統函數$monitor操作不同。因為它的輸出是事件驅動的。例中的變量$realtime(由用戶賦值到當前的仿真時間)用于觸發信號列表中值的顯示。信號表由變量$realtime開始,跟隨其他將要顯示的信號名(clock, reset, load等)。以%開始的關鍵字包含一個格式描述的表,用來控制如何格式化顯示信號列表中的每個信號的值。格式列表是位置確定的。每個格式說明有序地與信號列表中的信號順序相關。比如%t說明規定了$realtime的值是時間格式。并且第

12、一個%b說明符格式化clock的值是二進制形式。Verilog提供附加的格式說明,比如%h用于說明十六進制,%d說明十進制,%c說明顯示為八進制。圖2說明格式顯示結果圖2仿真結果簡單的testbench簡單的testbench實例化用戶設計,然后提供相應的激勵。測試輸出被圖形化顯示在仿真器的波形窗口里或者作為文本發送到用戶的終端或者是管道輸出文本。以下是一個簡單的用Verilog實現的設計,它實現了一個移位寄存器的功能。module shift_reg (clock, reset, load, sel, data, shiftreg);input clock;input reset;input

13、 load;input 1:0 sel;input 4:0 data;output 4:0 shiftreg;reg 4:0 shiftreg;always (posedge clock)beginif (reset)shiftreg = 0;else if (load)shiftreg = data;elsecase (sel)2b00 : shiftreg = shiftreg;2b01 : shiftreg = shiftreg 1;default : shiftreg = shiftreg;endcaseendendmodule以下是簡單的testbench,示例移位寄存器設計的例子v

14、erilog描述。module testbench; / declare testbench namereg clock;reg load;reg reset; / declaration of signalswire 4:0 shiftreg;reg 4:0 data;reg 1:0 sel;/ instantiation of the shift_reg design belowshift_reg dut(.clock (clock),.load (load),.reset (reset),.shiftreg (shiftreg),.data (data),.sel (sel);/this

15、 process block sets up the free running clockinitial beginclock = 0;forever #50 clock = clock;endinitial begin/ this process block specifies the stimulus.reset = 1;data = 5b00000;load = 0; sel = 2b00;#200reset = 0;load = 1;#200data = 5b00001;#100sel = 2b01;load = 0;#200sel = 2b10;#1000 $stop;endinit

16、ial begin/ this process block pipes the ASCII results to the/terminal or text editor$timeformat(-9,1,ns,12);$display( Time Clk Rst Ld SftRg Data Sel);$monitor(%t %b %b %b %b %b %b, $realtime,clock, reset, load, shiftreg, data, sel);endendmodule以上的testbench實例化設計,設置時鐘,提供激勵信號。所有的進程塊在仿真時間零點開始。英鎊標記(#)說明下

17、一個激勵作用前的延遲。$stop命令使仿真器停止測試仿真(所有測試設計中都應該包含一個停止命令)。最后,$monitor語句返回ascII格式的結果到屏幕或者管道輸出到一個文本編輯器。自動驗證推薦自動實現測試結果的驗證,尤其是對于較大的設計來說。自動化減少了檢查設計是否正確所要求的時間,也使人可能的犯錯最少。一般有以下幾種常用的自動測試驗證的方法:1、數據庫比較(database comparison)。首先,要創建一個包含預期輸出的數據庫文件。然后,仿真輸出被捕獲并與預期輸出數據庫文件中參考的向量比較。然而,因為從輸出到輸入文件指針沒有提供,是這種方法的一個缺點,使得跟蹤一個導致錯誤輸出的原

18、因比較困難。2、波形比較(waveform comparison)。波形比較可以自動或是手動的運行。自動的方法使用一個測試比較器來比較預期輸出波形與測試輸出波形。3、自我檢查測試平臺(self-checking testbenches)。一個自我檢查testbench檢查預期的結果與運行時間的實際結果,并不是在仿真結束以后。因為有用的錯誤跟蹤信息可以內建在一個測試設計中,用來說明哪些地方設計有誤,調試時間可以非常明顯地縮短。自我檢查testbenches自我檢查testbench通過在一個測試文檔中放置一系列的預期向量表來實現。運行時按定義好的時間間隔將這些向量與實際仿真結果進行比較。如果實際

19、結果與預期結果匹配,仿真成功。如果結果不匹配,則報告兩者的差異。對于同步設計,實現自我檢查testbench會更簡單一些,因為與實現的結果相比較可以在時鐘沿或每個幾個時鐘進行。比較的方法基于設計本身的特性。比如一個存儲器讀寫的testbench在每次數據寫入后者讀出時進行檢查。在自我檢查的testbench中,預期輸出與實際輸出在一定的時間間隔比較以便提供自動的錯誤檢查。這個技術在小到中型的設計中非常好。但是,因為當設計復雜后,可能的輸出組合成指數倍的增長,為一個大型設計編寫一個自我檢查的testbench是非常困難和非常費時的。以下是一個用Verilog描述的簡單的自我檢查的testbenc

20、h例子:下述的設計實例中,預期的結果被詳細說明。后面的代碼,兩種結果被比較,比較的結果被返回終端。如果沒有錯誤,一個“end of good simulation”消息會顯示。如果失配發生,根據期望與實際值的失配情況,錯誤會被相應報告。timescale 1 ns / 1 psmodule test_sc;reg tbreset, tbstrtstop;reg tbclk;wire 6:0 onesout, tensout;wire 9:0 tbtenthsout;parameter cycles = 25;reg 9:0 Data_in_t 0:cycles;/ / Instantiatio

21、n of the Design/ /stopwatch UUT (.CLK (tbclk), .RESET (tbreset), .STRTSTOP (tbstrtstop),.ONESOUT (onesout), .TENSOUT (tensout), .TENTHSOUT (tbtenthsout);wire 4:0 tbonesout, tbtensout;assign tbtensout = led2hex(tensout);assign tbonesout = led2hex(onesout);/EXPECTED RESULTS/initial beginData_in_t1 =10

22、b1111111110;Data_in_t2 =10b1111111101;Data_in_t3 =10b1111111011;Data_in_t4 =10b1111110111;Data_in_t5 =10b1111101111;Data_in_t6 =10b1111011111;Data_in_t7 =10b1110111111;Data_in_t8 =10b1101111111;Data_in_t9 =10b1011111111;Data_in_t10=10b0111111111;Data_in_t11=10b1111111110;Data_in_t12=10b1111111110;Da

23、ta_in_t13=10b1111111101;Data_in_t14=10b1111111011;Data_in_t15=10b1111110111;Data_in_t16=10b1111101111;Data_in_t17=10b1111011111;Data_in_t18=10b1110111111;Data_in_t19=10b1101111111;Data_in_t20=10b1011111111;Data_in_t21=10b0111111111;Data_in_t22=10b1111111110;Data_in_t23=10b1111111110;Data_in_t24=10b1

24、111111101;Data_in_t25=10b1111111011;endreg GSR;initial beginGSR = 1;/ / Wait till Global Reset Finished/ /#100 GSR = 0;end/ / Create the clock/ /initial begintbclk = 0;/ Wait till Global Reset Finished, then cycle clock#100 forever #60 tbclk = tbclk;endinitial begin/ / Initialize All Input Ports/ /t

25、breset = 1;tbstrtstop = 1;/ / Apply Design Stimulus/ /#240 tbreset = 0;tbstrtstop = 0;#5000 tbstrtstop = 1;#8125 tbstrtstop = 0;#500 tbstrtstop = 1;#875 tbreset = 1;#375 tbreset = 0;#700 tbstrtstop = 0;#550 tbstrtstop = 1;/ / simulation must be halted inside an initial statement/ / #100000 $stop;end

26、integer i,errors;/ Block below compares the expected vs. actual results/ at every negative clock edge./always (posedge tbclk)beginif (tbstrtstop)begini = 0;errors = 0;endelsebeginfor (i = 1; i 1)$display(%0d ERROR! See log above for details.,errors);else$display(ERROR! See log above for details.);#1

27、00 $stop;endendendmodule如果仿真成功,下圖的信息就會在顯示終端上顯示:圖3 verilog示例驗證編寫testbench的準則本節羅列一些編寫testbench的準則。正如規劃一個電路設計可以幫助得到更好的電路性能,規劃好的testbench可以提高仿真驗證的效率。在編寫testbench前要了解仿真器雖然通用仿真工具兼容HDL工業標準,但標準并沒有重點強調跟仿真相關的一些主題。不同的仿真器有不同的特點、功能和執行效率。對我們而言要全面了解Active-HDL這個工具。-基于事件vs基于周期的仿真仿真器使用基于事件或基于周期的仿真方法?;谑录姆抡嫫?,當輸入,信號,或

28、是門改變了值,來確定仿真器事件的時間。在一個基于事件的仿真器中,一個延時值可以附加在門電路或是電路網絡上來構建最優的時序仿真?;谥芷诘姆抡嫫髅嫦蛲皆O計。這類工具優化組合邏輯,在時鐘沿分析結果。這個功能使得基于周期的仿真器比基于事件的仿真器更快更有效。-確定事件時間基于事件的仿真器提供商使用不同的運算法則來確定仿真事件。所以,根據仿真器用來確定的運算法則不同,同一個仿真時間的事件被確定為不同的次序(根據在每個事件之間插入的delta延時)。為避免對運算法則的依賴和確保正確的結果,一個事件驅動測試應該詳細描述明確的激勵順序。-避免使用無限循環當一個事件添加到基于事件的仿真器,cpu和內存的使用

29、就增加了,仿真過程就會變慢。除非是評價testbench,無限循環不應該使用來作為設計的激勵。一般地,只有時鐘被描述成一個無限循環(如forever循環)。-細分激勵到邏輯模塊 在測試中,所有initial塊(verilog)并行執行。如果無關的激勵被分離到獨立的塊中,測試激勵的順序會變得更容易實現和檢查。因為每個并行的塊相關于仿真時間的零點開始執行,對于分離的塊傳遞激勵更容易。使用分離激勵塊使得testbench的建立,維護和升級更加容易。-避免顯示并不重要的數據大型設計的測試可能包含10萬以上的事件或匿名信號。顯示大量的仿真數據會相當地降低仿真的速度。高級測試技術根據任務和過程細分激勵模塊

30、在創建一個大的testbench時,激勵將會被分割使得代碼清晰而易于修改。Task塊可以被用來分割信號。在下面例子中的testbench用于一個SDRAM控制器的測試。設計包括重復的激勵模塊,testbench通過不同的task來劃分測試激勵。這些task稍后被調用來進行獨立塊的功能的測試仿真。task addr_wr; 地址寫input 31 : 0 address;begindata_addr_n = 0;we_rn = 1;ad = address;endendtasktask data_wr; 數據寫input 31 : 0 data_in;begindata_addr_n = 1;w

31、e_rn = 1;ad = data_in;endendtasktask addr_rd; 地址讀input 31 : 0 address;begindata_addr_n = 0;we_rn = 0;ad = address;endendtasktask data_rd; 數據讀input 31 : 0 data_in;begindata_addr_n = 1;we_rn = 0;ad = data_in;endendtasktask nop; 空操作begindata_addr_n = 1;we_rn = 0;ad = hi_z;endendtask這些任務描述設計功能的獨立單元:地址的讀

32、寫,數據的讀寫,或者空操作。當這些task描述完成后,這些task可以在testbench中被調用。如下所示:Initial beginnop ; / Nop#( 86* CYCLE +1); addr_wr (32h20340400); / Precharge, loadController MR#(CYCLE); data_wr (32h0704a076); / value for Controller MR#(CYCLE); nop ; / Nop#(5 * CYCLE); addr_wr (32h38000000); / Auto Refresh#(CYCLE); data_wr (3

33、2h00000000); /#(CYCLE); nop ; / Nopend細分激勵到獨立的任務使得激勵很容易實現,也使得代碼的可讀性更好。在仿真時控制雙向信號多數設計使用雙向信號,在testbench中必須區別對待雙向信號和單向信號。雙向總線由testbench控制,雙向總線的值可以通過數據頂層信號來訪問。以下是一個雙向總線示例。module bidir_infer (DATA, READ_WRITE);input READ_WRITE ;inout 1:0 DATA ;reg 1:0 LATCH_OUT ;always (READ_WRITE or DATA)beginif (READ_W

34、RITE = 1)寫LATCH_OUT = DATA;endassign DATA = (READ_WRITE = 1) ? 2bZ : LATCH_OUT;endmoduleVerilog testbench可以如下描述:module test_bidir_ver;reg read_writet;reg 1:0 data_in;wire 1:0 datat, data_out;bidir_infer uut (datat, read_writet);assign datat = (read_writet = 1) ? data_in : 2bZ;assign data_out = (read

35、_writet = 0) ? datat : 2bZ;initial beginread_writet = 1;data_in = 11;#50 read_writet = 0;endendmodule在這些測試設計中,data_in信號提供激勵到設計中的雙向DATA數據信號,data_out信號讀取該DATA數據信號.Verilog中有用的語法結構其他有用的Verilog語法結構,如 $monitor, $display, 及$time,在前面的verilog測試示例中論述過,這一節說明另外的可以在測試設計中使用的verilog語句結構。force/releaseforce/release語

36、句可以用來跨越進程對一個寄存器或一個wire網絡的賦值。這個結構一般用于強制特定的設計行為。一旦一個強制值釋放,這個信號保持它的狀態直到新的值被進程賦值。以下是force/release語句的用法。module testbench;.initial beginreset = 1;force DataOut = 101;#25 reset = 0;#25 release DataOut;.endendmoduleassign/deassignassign/deassign語句與force/release相類似,但是assign/deassign只用于設計中的寄存器。他們一般用于設置輸入值。就象一個force語句,assign語句覆蓋進程語句的賦值。以下是一個assign/deassign語句的用法。modu

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論