Application Note: Test Benches £ⅫL|NX° Writing Efficient Testbenches Author: Mujtaba Hamid XAPP199(v10)June11,2001 Summary This application note is written for logic designers who are new to HDL verification flows, and who do not have extensive testbench-writing experience Testbenches are the primary means of verifying HDL designs. This application note provides guidelines for laying out and constructing efficient testbenches. It also provides an algorithm to develop a self-checking testbench for any design All design files for this application note are available on the FTP site at PC: ftp: //ftp. xilinx. com/pub/applications/xapp/xapp199 zip UNIX: ftp: //ftp. xilinx. com/pub/applications/xapp/xapp199targz Introduction Due to increases in design size and complexity, digital design verification has become an increasingly difficult and laborious task. To meet this challenge, verification engineers rely on several verification tools and methods. For large, multi-million gate designs, engineers typically use a suite of formal verification tools. However, for smaller designs, design engineers usually find that HDL simulators with testbenches work best Testbenches have become the standard method to verify HLL(High-Level Language)designs Typically, testbenches perform the following tasks Instantiate the design under test(DUT) Stimulate the dUT by applying test vectors to the model Output results to a terminal or waveform window for visual inspection Optionally compare actual results to expected results Typically, testbenches are written in the industry-standard VHDL or Verilog hardware description languages. Testbenches invoke the functional design, then stimulate it. Complex testbenches perform additional functions-for example, they contain logic to determine the proper design stimulus for the design or to compare actual to expected results The remaining sections of this note describe the structure of a well-composed testbench, and provide an example of a self-checking testbench-one that automates the comparison of actual to expected testbench results Figure 1 shows a standard HDL verification flow which follows the steps outlined above Since testbenches are written in VHDL or Verilog, testbench verification flows can be ported across platforms and vendor tools. Also, since VHDL and Verilog are standard non-proprietary a2000XilinxInc.AllrightsreservedAllXilinxtrademarksregisteredtrademarkspatentsanddisclaimersareaslistedathttpllwww.xilinx.comllegalhtm All other trademarks and registered trademarks are the property of their respective owners. All specifications are sut XAPP199(v10)June11,2001 www.xilinx.com 1-800-255-7778
XAPP199 (v1.0) June 11, 2001 www.xilinx.com 1 1-800-255-7778 © 2000 Xilinx, Inc. All rights reserved. All Xilinx trademarks, registered trademarks, patents, and disclaimers are as listed at http://www.xilinx.com/legal.htm. All other trademarks and registered trademarks are the property of their respective owners. All specifications are subject to change without notice. Summary This application note is written for logic designers who are new to HDL verification flows, and who do not have extensive testbench-writing experience. Testbenches are the primary means of verifying HDL designs. This application note provides guidelines for laying out and constructing efficient testbenches. It also provides an algorithm to develop a self-checking testbench for any design. All design files for this application note are available on the FTP site at: PC: ftp://ftp.xilinx.com/pub/applications/xapp/xapp199.zip UNIX: ftp://ftp.xilinx.com/pub/applications/xapp/xapp199.tar.gz Introduction Due to increases in design size and complexity, digital design verification has become an increasingly difficult and laborious task. To meet this challenge, verification engineers rely on several verification tools and methods. For large, multi-million gate designs, engineers typically use a suite of formal verification tools. However, for smaller designs, design engineers usually find that HDL simulators with testbenches work best. Testbenches have become the standard method to verify HLL (High-Level Language) designs. Typically, testbenches perform the following tasks: • Instantiate the design under test (DUT) • Stimulate the DUT by applying test vectors to the model • Output results to a terminal or waveform window for visual inspection • Optionally compare actual results to expected results Typically, testbenches are written in the industry-standard VHDL or Verilog hardware description languages. Testbenches invoke the functional design, then stimulate it. Complex testbenches perform additional functions—for example, they contain logic to determine the proper design stimulus for the design or to compare actual to expected results. The remaining sections of this note describe the structure of a well-composed testbench, and provide an example of a self-checking testbench—one that automates the comparison of actual to expected testbench results. Figure 1 shows a standard HDL verification flow which follows the steps outlined above. Since testbenches are written in VHDL or Verilog, testbench verification flows can be ported across platforms and vendor tools. Also, since VHDL and Verilog are standard non-proprietary Application Note: Test Benches XAPP199 (v1.0) June 11, 2001 Writing Efficient Testbenches Author: Mujtaba Hamid R
£ⅫNX° Writing Efficient Testbenches languages, verification suites written in VHDL or Verilog can be reused in future designs Testbench Verification Flow Testbench Displays values Testbench Instantiates Design on Terminal and Provides stimulus Design Under Test Verify Result (DUT) on Waveform Testbench Checks for Correctness XAPP199_01042 Figure 1: HDL Verification Flow Using Testbenches Constructing Testbenches can be written in VHDL or Verilog. Since testbenches are used for simulation only, Testbenches they are not limited by semantic constraints that apply to rtl language subsets used in synthesis. Instead, all behavioral constructs can be used. Thus, testbenches can be written more generically, making them easier to maintain All testbenches contain the basic sections shown in Table 1. As mentioned above. testbenches typically contain additional functionality as well, such as the visual display of results on a terminal and built-in error detection Table 1: Sections Common to Testbenches VHDL Verilog Entity and Architecture Declaration Module declaration Signal Declaration Signal declaration Instantiation of Top-level Design Instantiation of Top-level Design Provide stimulus Provide stimulus The following examples show some constructs used frequently in testbenches Generating Clock Signa Designs that use system clocks to sequence logic must generate a clock Iterative clocks can easily be implemented in both VHDL and verilog source code. The following are VHDL and Verilog examples of clock generation: VHDL iod constant Constant ClockPeriod: TIME =10 ns Clock Generation method 1 clock < not clock after clockPeriod /2 Clock Generation method 2 GENERATE CLOCK: process www.xilinx.com XAPP199(v1.0)June11,2001 1-800-255-7778
2 www.xilinx.com XAPP199 (v1.0) June 11, 2001 1-800-255-7778 Writing Efficient Testbenches R languages, verification suites written in VHDL or Verilog can be reused in future designs without difficulty. Constructing Testbenches Testbenches can be written in VHDL or Verilog. Since testbenches are used for simulation only, they are not limited by semantic constraints that apply to RTL language subsets used in synthesis. Instead, all behavioral constructs can be used. Thus, testbenches can be written more generically, making them easier to maintain. All testbenches contain the basic sections shown in Table 1. As mentioned, above, testbenches typically contain additional functionality as well, such as the visual display of results on a terminal and built-in error detection. The following examples show some constructs used frequently in testbenches.: Generating Clock Signals Designs that use system clocks to sequence logic must generate a clock. Iterative clocks can easily be implemented in both VHDL and Verilog source code. The following are VHDL and Verilog examples of clock generation: VHDL: -- Declare a clock period constant. Constant ClockPeriod : TIME := 10 ns; -- Clock Generation method 1: Clock <= not Clock after ClockPeriod / 2; -- Clock Generation method 2: GENERATE CLOCK: process begin Figure 1: HDL Verification Flow Using Testbenches Testbench Verification Flow Testbench Instantiates Design and Provides Stimulus Design Under Test (DUT) Testbench Displays Values on Terminal Verify Result on Waveform Testbench Checks for Correctness XAPP199_01_042001 Table 1: Sections Common to Testbenches VHDL Verilog Entity and Architecture Declaration Module Declaration Signal Declaration Signal Declaration Instantiation of Top-level Design Instantiation of Top-level Design Provide Stimulus Provide Stimulus
Writing Efficient Testbenches £ⅫL|NX C1ock<=1′; wait for (clockPeriod / 2) end processi // Declare a clock period constant Parameter ClockPeriod =10: / clock Generation method 1 initial begin end / clock Generation method 2 initial begin always #(clockPeriod /2)clock = -clocki Providing stimulus To obtain testbench verification results, stimulus must be provided to the DUT. Concurrent stimulus blocks are used in testbenches to provide the necessary stimuli. Two methods are employed: absolute-time stimulus and relative-time stimulus In the first method, simulation values are specified relative to simulation time zero. By comparison, relative-time stimulus supplies initial values, then waits for an event before retriggering the stimulus. Both methods can be combined in a testbench, according to the designer's needs Table 2 and Table 3 provide examples of absolute-time and relative-time stimuli, respectively, in VHDL and Verilog source code Table 2: Absolute Time Stimulus Example VHDL-ABSOLUTE TIME Verilog-ABSOLUTE TIME Mainstimulus: process begin initial begin Reset<=1′; Load<=′0′ Count UpDn <=0 wait for 100 ns #100 Reset =0 Reset<=0′; #20 Load 1 wait for 20 ns: #20 Count UpDn =li Load <=/1 end wait for 20 nsi end process; XAPP199(v10)June11,2001 www.xilinx.com 1-800-255-7778
Writing Efficient Testbenches XAPP199 (v1.0) June 11, 2001 www.xilinx.com 3 1-800-255-7778 R wait 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 begin forever Clock = #(ClockPeriod / 2) ~ Clock; end // Clock Generation method 2: initial begin always #(ClockPeriod / 2) Clock = ~Clock; end Providing Stimulus To obtain testbench verification results, stimulus must be provided to the DUT. Concurrent stimulus blocks are used in testbenches to provide the necessary stimuli. Two methods are employed: absolute-time stimulus and relative-time stimulus. In the first method, simulation values are specified relative to simulation time zero. By comparison, relative-time stimulus supplies initial values, then waits for an event before retriggering the stimulus. Both methods can be combined in a testbench, according to the designer’s needs. Table 2 and Table 3 provide examples of absolute-time and relative-time stimuli, respectively, in VHDL and Verilog source code. Table 2: Absolute Time Stimulus Example VHDL-ABSOLUTE TIME Verilog-ABSOLUTE TIME MainStimulus: process begin Reset <= ’1’; Load <= ’0’; Count_UpDn <= ’0’; wait for 100 ns; Reset <= ’0’; wait for 20 ns; Load <= ’1’; wait for 20 ns; Count_UpDn <= ’1’; end process; initial begin Reset = 1; Load = 0; Count_UpDn = 0; #100 Reset = 0; #20 Load = 1; #20 Count_UpDn = 1; end
£ⅫNX° Writing Efficient Testbenches e Time Stimulus Example VHDL-RELATIVE TIME Verilog- RELATIVE TIME Process (Clock) lways @(posedge clock Begin TB Count < TB Count 1 If rising edge(Clock)then initial begin TB Count < TB Count 1; f (TB Count <= 5) d g end process Secondstimulus: process begin oad =0: if(TB Count <=5) then Count upDn Reset Count upDn<=0′ begin Else Reset =07 Reset < Load<=1′; t UpDn Count upDn end process end Finalstimulus: process begin initial begin 1100")then Count UpDn <='0'i Count UpDn <=0; report "Terminal Count Display("Terminal Count d nd i end process end VHDL process blocks and verilog initial blocks are executed concurrently along with other process and initial blocks in the file. However, within each(process or initial) block, events are concurrent block at simulation time zero. Multiple blocks should be used to break up complex stimulus sequences into more readable and maintainable cod Display ing Results Displaying results is facilitated in Verilog by the Display and Monitor keywords. Altho VHDL does not have equivalent display-specific commands, it provides the std textio package, which allows file I/O redirection to the display terminal window (for an example of this technique see Self-Checking Testbenches, below) The following is a Verilog example in which values are displayed on the terminal screen // pipes the ASCII results to the terminal or text editor initial begin Monitor("暑t悬b旨b暑bb各b各b",$rea1time, lock, reset, load, shiftreg, data, sel) The Display keyword outputs quoted parenthetical text(. )to the terminal window. The Smonitor keyword works differently, since its output is event-driven. In the example, the Realtime variable(assigned by the user to the current simulation time) is used to trigger the display of values in the signal list. The signal list starts with the Realtime variable, and is followed by the names of other signals whose values are to be displayed(clock, reset, load, and others). The beginning" %keywords comprise a list of format specifiers, used to control ho each signal value in the signal list is formatted for display. The format list is positional-each format specifier is sequentially associated with a successive signal name in the signal list. For example, the %t specifier formats the displayed Realtime value in time format, and the first %b www.xilinx.com XAPP199(v1.0)June11,2001 1-800-255-7778
4 www.xilinx.com XAPP199 (v1.0) June 11, 2001 1-800-255-7778 Writing Efficient Testbenches R VHDL process blocks and Verilog initial blocks are executed concurrently along with other process and initial blocks in the file. However, within each (process or initial) block, events are scheduled sequentially, in the order written. This means that stimulus sequences begin in each concurrent block at simulation time zero. Multiple blocks should be used to break up complex stimulus sequences into more readable and maintainable code. Displaying Results Displaying results is facilitated in Verilog by the $display and $monitor keywords. Although VHDL does not have equivalent display-specific commands, it provides the std_textio package, which allows file I/O redirection to the display terminal window (for an example of this technique, see Self-Checking Testbenches, below). The following is a Verilog example in which values are displayed on the terminal screen: // pipes the ASCII results to the terminal or text editor initial begin $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); end The $display keyword outputs quoted parenthetical text (“...”) to the terminal window. The $monitor keyword works differently, since its output is event-driven. In the example, the $realtime variable (assigned by the user to the current simulation time) is used to trigger the display of values in the signal list. The signal list starts with the $realtime variable, and is followed by the names of other signals whose values are to be displayed (clock, reset, load, and others). The beginning “%” keywords comprise a list of format specifiers, used to control how each signal value in the signal list is formatted for display. The format list is positional—each format specifier is sequentially associated with a successive signal name in the signal list. For example, the %t specifier formats the displayed $realtime value in time format, and the first %b Table 3: Relative Time Stimulus Example VHDL-RELATIVE TIME Verilog-RELATIVE TIME Process (Clock) Begin If rising_edge(Clock) then TB_Count <= TB_Count + 1; end if; end process; SecondStimulus: process begin if (TB_Count <= 5) then Reset <= ’1’; Load <= ’0’; Count_UpDn <= ’0’; Else Reset <= ’0’; Load <= ‘1’; Count_UpDn <= ‘1’; end process; FinalStimulus: process begin if (Count = "1100") then Count_UpDn <= '0'; report "Terminal Count Reached, now counting down." end if; end process; always @ (posedge clock) TB_Count <= TB_Count + 1; initial begin if (TB_Count <= 5) begin Reset = 1; Load = 0; Count _UpDn = 0; end else begin Reset = 0; Load = 1; Count_UpDn = 1; end end initial begin if (Count == 1100) begin Count_UpDn <= 0; $display("Terminal Count Reached, now counting down."); end end
Writing Efficient Testbenches £ⅫL|NX specifier formats the clock value in binary format. Verilog provides additional format-specifiers for example, %h is used for hexadecimal, %d for decimal, and %o for octal formats(consult a Verilog reference for a complete list of keywords and format specifiers) The formatted display results are shown in Figure 2 M ModelSin还E53d 口区 File Edit Design View Run Macro Options wi sG曲岛!群「100图系|刊 VSIM 11> run 200 ns Time Clk Rst Ld sftRg Data Sel #00ns010ww0000 500s110000000000000 1000ns01000000000000 1500ns1100000000 SIM 12> Now. 200 ns Delta: 2 sim: /testbench igure 2: Simulation Results Echoed to Terminal Simple Simple testbenches instantiate the user design then provide stimuli to it. Testbench output is Testbenches displayed graphically on the simulator's waveform window or as text sent to the users terminal r to a piped text file Below is a simple Verilog design representing a shift register module shift reg (clock, reset, load, sel, data, shiftreg) input clock, Input reset input load t[1:0]se1 input [4: 0] data output [4:0] shiftreg ys @(posedge clock) begin if (reset) shifty else if (load) shiftreg data (se1) 2 b00: shiftreg shiftreg 2′b01: shift hift 1 default shiftreg shiftreg endcase The following simple testbench examples instantiate the shift register design ilog Exampl module testbench; / declare testbench name eg cloc eg load XAPP199(v10)June11,2001 www.xilinx.com 1-800-255-7778
Writing Efficient Testbenches XAPP199 (v1.0) June 11, 2001 www.xilinx.com 5 1-800-255-7778 R specifier formats the clock value in binary format. Verilog provides additional format-specifiers, for example, %h is used for hexadecimal, %d for decimal, and %o for octal formats (consult a Verilog reference for a complete list of keywords and format specifiers). The formatted display results are shown in Figure 2. Simple Testbenches Simple testbenches instantiate the user design, then provide stimuli to it. Testbench output is displayed graphically on the simulator's waveform window or as text sent to the user’s terminal or to a piped text file. Below is a simple Verilog design representing a shift register: module shift_reg (clock, reset, load, sel, data, shiftreg); input clock; input reset; input load; input [1:0] sel; input [4:0] data; output [4:0] shiftreg; reg [4:0] shiftreg; always @ (posedge clock) begin if (reset) shiftreg = 0; else if (load) shiftreg = data; else case (sel) 2’b00 : shiftreg = shiftreg; 2’b01 : shiftreg = shiftreg > 1; default : shiftreg = shiftreg; endcase end endmodule The following simple testbench examples instantiate the shift register design. Verilog Example: module testbench; // declare testbench name reg clock; reg load; Figure 2: Simulation Results Echoed to Terminal
£ⅫNX° Writing Efficient Testbenches reg reset / declaration of signals wire [4: 0] shiftregi reg [4:01 datai reg [1: 0] sel // instantiation of the shift reg design below shift reg dut( clock (clock) load (load) reset (reset) shiftreg (shiftreg e1(se1)) //this process block sets up the free running clock tial b lock =0 #50 clock clock end initial begin// this process block specifies the stimulus reset = 1i dat 5′b00000 load se1=2′b00; #200 data=5′b00001 oad = 0: #200 2′b10 #1000 ssto d initial begin// this process block pipes the ASCII results to the Stimeformat(-9, l,ns",12)i Sdisplay (" Time clk Rst Ld SftRg Data Sel")i Monitor("暑t悬b各b暑b暑b暑b各b",Srea1time clock, reset, load, shiftreg, data, sel) dimodule The testbench, above, instantiates the design, sets up the clock, then provides the stimuli. All process blocks start at simulation time zero and are concurrent. The pound sign(#) specifies the delay before the next stimulus is applied. The Sstop command instructs the simulator to stop testbench simulation(all testbenches should contain a stop command). Finally, the Smonitor statement echoes the results in ASCll format to the screen or a piped text editor. Following is a VHDL testbench that instantiates and provides stimulus to the verilog shift VHDL Example: library IEEe entity testbench is end entity testbench architecture test reg of testbench is t re www.xilinx.com XAPP199(v1.0)June11,2001 1-800-255-7778
6 www.xilinx.com XAPP199 (v1.0) June 11, 2001 1-800-255-7778 Writing Efficient Testbenches R reg reset; // declaration of signals wire [4:0] shiftreg; reg [4:0] data; reg [1:0] sel; // instantiation of the shift_reg design below shift_reg dut(.clock (clock), .load (load), .reset (reset), .shiftreg (shiftreg), .data (data), .sel (sel)); //this process block sets up the free running clock initial begin clock = 0; forever #50 clock = ~clock; end initial begin// this process block specifies the stimulus. reset = 1; data = 5’b00000; load = 0; sel = 2’b00; #200 reset = 0; load = 1; #200 data = 5’b00001; #100 sel = 2’b01; load = 0; #200 sel = 2’b10; #1000 $stop; end initial 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); end endmodule The testbench, above, instantiates the design, sets up the clock, then provides the stimuli. All process blocks start at simulation time zero and are concurrent. The pound sign (#) specifies the delay before the next stimulus is applied. The $stop command instructs the simulator to stop testbench simulation (all testbenches should contain a stop command). Finally, the $monitor statement echoes the results in ASCII format to the screen or a piped text editor. Following is a VHDL testbench that instantiates and provides stimulus to the Verilog shift register design above. VHDL Example: library IEEE; use IEEE.std_logic_1164.all; entity testbench is end entity testbench; architecture test_reg of testbench is component shift_reg is
Writing Efficient Testbenches £ⅫL|NX port (clock in std logici reset in st d: in std logici sel in std logic vector (1 downto 0) d logic hiftreg out std logic vector(4 downto 0)) nd componenti signal clock, reset, load: std logic signal shiftreg, data: std logic vector(4 downto 0) constant ClockPeriod: TIME 50 ns n UUT shift reg port map (clock = clock, reset = reset, load = load, data = dat shiftreg = shiftreg)i process begin clock < not clock after (clockPeriod / 2) end process process begin data<="00000 it for 200 nsi reset<=!0′ data<="00001 wait for 100 nsi se1<="01 1oad<=!0′ 1<="10"; it for 1000 hitecture test r The VHDL testbench above is similar in functionality to the Verilog testbench shown previously, with the exception of a command to echo the output to the terminal In VHDL, the std textio package is used to display information to the terminal, and this will be covered in the next section Automatic g the verification of testbench results is recommended, particularly for large Verification utomation reduces the time required to check a design for correctness, and human error Several methods are commonly used to automate testbench verification Database Comparisons. First, a database file containing expected output(a"golden vector" file)is created. Then, simulation outputs are captured and compared to the reference vectors in the golden vector file( the unix diff utility can be used to compare the ASCll database files). However, since pointers from output to input files are not provided, a disadvantage of this method is the difficulty of tracing an incorrect output to the source of the error 2. Waveform Comparison Waveform comparisons can be performed automatically or manually. The automatic method employs a testbench comparator to compare a golden waveform against the testbench output waveform. The Xilinx HDL Bencher tool can be XAPP199(v10)June11,2001 www.xilinx.com 1-800-255-7778
Writing Efficient Testbenches XAPP199 (v1.0) June 11, 2001 www.xilinx.com 7 1-800-255-7778 R port (clock : in std_logic; reset : in std_logic; load : in std_logic; sel : in std_logic_vector(1 downto 0); data : in std_logic_vector(4 downto 0); shiftreg : out std_logic_vector(4 downto 0)); end component; signal clock, reset, load: std_logic; signal shiftreg, data: std_logic_vector(4 downto 0); signal sel: std_logic_vector(1 downto 0); constant ClockPeriod : TIME := 50 ns; begin UUT : shift_reg port map (clock => clock, reset => reset, load => load, data => data, shiftreg => shiftreg); process begin clock <= not clock after (ClockPeriod / 2); end process; process begin reset <= ’1’; data <= "00000"; load <= ’0’; set <= "00"; wait for 200 ns; reset <= ’0’; load <= ’1’; wait for 200 ns; data <= "00001"; wait for 100 ns; sel <= "01"; load <= ’0’; wait for 200 ns; sel <= "10"; wait for 1000 ns; end process; end architecture test_reg; The VHDL testbench above is similar in functionality to the Verilog testbench shown previously, with the exception of a command to echo the output to the terminal. In VHDL, the std_textio package is used to display information to the terminal, and this will be covered in the next section. Automatic Verification Automating the verification of testbench results is recommended, particularly for larger designs. Automation reduces the time required to check a design for correctness, and minimizes human error. Several methods are commonly used to automate testbench verification: 1. Database Comparisons. First, a database file containing expected output (a “golden vector” file) is created. Then, simulation outputs are captured and compared to the reference vectors in the golden vector file (the unix diff utility can be used to compare the ASCII database files). However, since pointers from output to input files are not provided, a disadvantage of this method is the difficulty of tracing an incorrect output to the source of the error. 2. Waveform Comparison. Waveform comparisons can be performed automatically or manually. The automatic method employs a testbench comparator to compare a golden waveform against the testbench output waveform. The Xilinx HDL Bencher tool can be
£ⅫNX° Writing Efficient Testbenches used to perform automatic waveform comparisons(for HDL Bencher information, go to http://www.xilinx.com/products/software/statecad/index.htm 3. Self-Checking Testbenches. A self-checking testbench checks expected results against actual results at run time not at the end of simulation. since useful error-tracking nformation can be built into the testbench to show where a design fails, debugging time is significantly shortened. Further information on self-checking testbenches is provided in the next section Self-Checking Self-checking testbenches are implemented by placing a series of expected vectors in a Testbenches testbench file. These vectors are compared at defined run-time intervals to actual simulation results If actual results match expected results, the simulation succeeds. If results do not match expectations, the testbench reports the discrepancies Implementing self-checking testbenches is simpler for synchronous designs since expected and actual results can be compared at a clock edge or after every "n"clock cycles. Comparison methods also depend on the nature of the design. For example, a testbench for memory w/O should check results each time new data is written to or read from a memory location. Similarly, if a design uses a significant number of combinatorial blocks, combinatorial delays must be taken into account when expected results are specified In a self-checking testbench, expected outputs are compared to actual outputs at regular run time intervals to provide automatic error checking. This technique works fine in small to mid size designs. However, since possible output combinations increase exponentially with design complexity, writing a self-checking testbench for a large design is much more difficult and time Below are examples of simple, self-checking testbenches written in Verilog and VHDL: Verilog Example Following the instantiation of the design, expected results are specified. Later in the code, expected and actual results are compared, and the results are echoed to the terminal. If there are no mismatches, an"end of good simulation" message is displayed. If a mismatch occurs, an error is reported along with the mismatched expected and actual values timescale 1 ns 1 ps module test reg threset, tbstrtstop ire [6:01 onesout, tensout parameter cycles =25 reg [9: 0] Data in t [0: cycles]i /////y Instantiation of the Design ///////1 stopwatch UUT ( ClK (bclk),. RESET (tbreset),. sTRTSToP (tbstrtstop) ONESOUT (onesout),. TENSOUT (tensout),. TENTHSOUT(tbtenthsout)) e[4: 0 tbonesout, tbtensout assign thtensout led2hex(tensout ssign tbonesout led2hex(onesout) ///1 EXPECTED RESULTS /////1yyy initial begin Data in t[1]=10′b1111111110; ata in t[2]=10′b1111111101 Data_int[3]=10′b111111011 t[4]=10′b1111110 www.xilinx.com XAPP199(v1.0)June11,2001 1-800-255-7778
8 www.xilinx.com XAPP199 (v1.0) June 11, 2001 1-800-255-7778 Writing Efficient Testbenches R used to perform automatic waveform comparisons (for HDL Bencher information, go to: http://www.xilinx.com/products/software/statecad/index.htm) 3. Self-Checking Testbenches. A self-checking testbench checks expected results against actual results at run time, not at the end of simulation. Since useful error-tracking information can be built into the testbench to show where a design fails, debugging time is significantly shortened. Further information on self-checking testbenches is provided in the next section Self-Checking Testbenches Self-checking testbenches are implemented by placing a series of expected vectors in a testbench file. These vectors are compared at defined run-time intervals to actual simulation results. If actual results match expected results, the simulation succeeds. If results do not match expectations, the testbench reports the discrepancies. Implementing self-checking testbenches is simpler for synchronous designs since expected and actual results can be compared at a clock edge or after every “n” clock cycles. Comparison methods also depend on the nature of the design. For example, a testbench for memory I/O should check results each time new data is written to or read from a memory location. Similarly, if a design uses a significant number of combinatorial blocks, combinatorial delays must be taken into account when expected results are specified. In a self-checking testbench, expected outputs are compared to actual outputs at regular runtime intervals to provide automatic error checking. This technique works fine in small to midsize designs. However, since possible output combinations increase exponentially with design complexity, writing a self-checking testbench for a large design is much more difficult and time consuming. Below are examples of simple, self-checking testbenches written in Verilog and VHDL: Verilog Example Following the instantiation of the design, expected results are specified. Later in the code, expected and actual results are compared, and the results are echoed to the terminal. If there are no mismatches, an “end of good simulation” message is displayed. If a mismatch occurs, an error is reported along with the mismatched expected and actual values. ‘timescale 1 ns / 1 ps module 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]; // ///////////////////////////// // Instantiation 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 begin Data_in_t[1] =10’b1111111110; Data_in_t[2] =10’b1111111101; Data_in_t[3] =10’b1111111011; Data_in_t[4] =10’b1111110111;
Writing Efficient Testbenches £ⅫL|NX Data in t[5]=10′b1111101111; Data in t[6]=10′b1111011111 Data in t[7]=10′b1110111111; Data in t[8]=10′b1101111111 Data in t[10]=10′b0111111111 Data in t[11]=10′b1111111110; Data in t[12]=10′b1111111110 Data in t[13]=10′b1111111101; t[14]=10′b1111111011 Data in t[15]=10′b1111110111 Data in t[16]=10′b1111101111 Data_int[17]=10′b1111011111 Data in t[18]=10′b1110111111 t[19]=10′b1101111111 Data in t[20]=10′b1011111111 Data in t[21]=10′b0111111111; Data in t[22]=10′b1111111110 Data in t[23]=10′b1111111110 Data in t[24]=10′b1111111101 Data in t[25]=10′b1111111011 ign glbl GSR= GS initial begin GSR =1 / Wait till Global Reset Finished / Create the clock ial begin bclk 7/ Wait till Global Reset Finished, then cycle clock #100 forever #60 bclk bclk itial begin //////1 // Initialize All Input Ports tb 1 //////1 // Apply Design stimulus #240tb #5000 tbstrtstop #8125 tbstrtstop =0 #875tb #700 tbstrtstop 0 XAPP199(v10)June11,2001 www.xilinx.com 1-800-255-7778
Writing Efficient Testbenches XAPP199 (v1.0) June 11, 2001 www.xilinx.com 9 1-800-255-7778 R Data_in_t[5] =10’b1111101111; Data_in_t[6] =10’b1111011111; Data_in_t[7] =10’b1110111111; Data_in_t[8] =10’b1101111111; Data_in_t[9] =10’b1011111111; Data_in_t[10]=10’b0111111111; Data_in_t[11]=10’b1111111110; Data_in_t[12]=10’b1111111110; Data_in_t[13]=10’b1111111101; Data_in_t[14]=10’b1111111011; Data_in_t[15]=10’b1111110111; Data_in_t[16]=10’b1111101111; Data_in_t[17]=10’b1111011111; Data_in_t[18]=10’b1110111111; Data_in_t[19]=10’b1101111111; Data_in_t[20]=10’b1011111111; Data_in_t[21]=10’b0111111111; Data_in_t[22]=10’b1111111110; Data_in_t[23]=10’b1111111110; Data_in_t[24]=10’b1111111101; Data_in_t[25]=10’b1111111011; end reg GSR; assign glbl.GSR = GSR; initial begin GSR = 1; // /////////////////////////////// // Wait till Global Reset Finished // /////////////////////////////// #100 GSR = 0; end // //////////////// // Create the clock // //////////////// initial begin tbclk = 0; // Wait till Global Reset Finished, then cycle clock #100 forever #60 tbclk = ~tbclk; end initial begin // ////////////////////////// // Initialize All Input Ports // ////////////////////////// tbreset = 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;
£ⅫNX° Writing Efficient Testbenches #550 tbstrtstop 1 / simulation must be halted inside an initial statement //#100000$stop; end integer errors //1 // Block below compares the expected vs. actual results // at every negative clock edge /////1/11/ @(posedge bclk begi f (thstrtstop) begin errors =01 for (i=l; i 1) Sdisplay ("0d ERROR! See log above for details. ",errors)i Sdisplay("ERROR! See log above for details. ")i #100 sstop; endmodul This simple, self-checking testbench design can be ported to any test case-of course, expected-output values and signal names must be modified for reuse. If a check is not needed at each clock edge, the for- loop can be modified as needed www.xilinx.com XAPP199(v1.0)June11,2001 1-800-255-7778
10 www.xilinx.com XAPP199 (v1.0) June 11, 2001 1-800-255-7778 Writing Efficient Testbenches R #550 tbstrtstop = 1; // ///////////////////////////////////////////////////// // simulation must be halted inside an initial statement // ///////////////////////////////////////////////////// // #100000 $stop; end integer i,errors; /////////////////////////////////////////////////////////////////// /////////////// // Block below compares the expected vs. actual results // at every negative clock edge. /////////////////////////////////////////////////////////////////// /////////////// always @ (posedge tbclk) begin if (tbstrtstop) begin i = 0; errors = 0; end else begin for (i = 1; i 1) $display("%0d ERROR! See log above for details.",errors); else $display("ERROR! See log above for details."); #100 $stop; end end endmodule This simple, self-checking testbench design can be ported to any test case—of course, expected-output values and signal names must be modified for reuse. If a check is not needed at each clock edge, the for-loop can be modified as needed