Chapter 15 Introduction to Verilog Testbenches Objectives In

Chapter 15: Introduction to Verilog Testbenches Objectives In this section, you will learn about designing a testbench: § Creating clocks § Including files § Strategic use of tasks and concurrent statements § Controlling and observing the design § Reporting warnings and errors

The Simulation Environment This is a simplified picture of the overall simulation environment. This section concentrates on testbench development strategies. design source file input: stimulus, response model libraries testbench source compile simulator file output: test pats, reports

Creating Clocks Example 1 You can define the clock in either the design or its testbench. You can define the clock either behaviorally or structurally. Here are examples of a symmetric clock: clk 0 10 reg clk; always begin #10 clk = 1; #10 clk = 0; end reg start; nand #10 (clk, start); initial begin start = 0; #10 start = 1; end 30 50

Creating Clocks Example 2 Here are examples of a symmetric clock with delayed startup: clk 0 reg clk; initial begin #20 clk = 1; forever begin #10 clk = 0; #10 clk = 1; end reg start; nand #10 (clk, start); initial begin #10 start = 0; #10 start = 1; end 20 40 60

Creating Clocks Example 3 Here are examples of an asymmetric clock with delayed startup: clk 0 reg clk; initial begin #20 clk = 1; forever begin #5 clk = 0; #15 clk = 1; end reg start; nand #(15, 5) (clk, start); initial begin #5 start = 0; #15 start = 1; end 20 40 60

Designing Your Testbench You can make your testbench as simple or as comolex as you want. A comolex testbench would perform response berifivation “on-the-fly”. simple testbench contro design l sophisticated testbench control observ e design

Using Include Files Use `include files to ensure project-wide consistency of common source. //defines. inc `timescale 1 ns / 10 ps `define PERIOD 20 `define TIMEOUT 10000000 `include “defines. inc” module clkgen (clk); output clk; reg clk; always begin #(`PERIOD/2) clk = 0; #(`PERIOD/2) clk = 1; end initial begin #(`TIMEOUT) $display(“TIMEOUT ERROR”); $finish; endmodule

Using Verilog Tasks Use Verilog tasks in your testbench to encapsulate repeated operations. clk data_valid data_read task cpu_read; begin #30 data_valid = 1; wait (data_read = = 1); #20 cpu_data = data_in; wait (data_read = = 0); #20 cpu_data = 8`hzz; #30 data_valid = 0; endtask

Using Concurrent Statements Use fork-join blocks in your testbench to concurrently activate parallel tasks. monitor fork join initialize in execute module inline_tb; //declare variables //instantiate designs initial begin initialize_design; fork monitor_data; monitor_error; monitor_timeout; run_test; join endmodule

Applying Stimulus Some common stimulus application techniques include: § In-line stimulus, applied from an initial block § Stimulus applied from a loop or always block § Stimulus applied from an array of vectors or integers § Stimulus that is recorded during one simulation and played back in another simulation

In-Line Stimulus In-line stimulus has the following characteristics: § You list the variables only when their values change § You can easily define complex timing relationships between signals § The testbench can become very long for tests of real designs module inline_tb; wire [7: 0] results; reg [7: 0] data_bus, addr; DUT u 1 (results, data_bus, addr); initial fork #10 addr = 8`h 01; #10 data_bus = 8`h 23; #20 data_bus = 8`h 45; #30 addr = 8`h 67; #30 data_bus = 8`h 89; #40 data_bus = 8`h. AB; #45 $finish; join endmodule

Stimulus From Loops Stimulus applied from a loop has the following characteristics: § For each iteration you assign a new stimulus vector § The timing relationships between signals are regular in nature § The testbench is compact module loop_tb; wrie [7: 0] response; reg [7: 0] stimulus; reg clk; integer i; DUT u 1 (response, stimulus); inititial clk = 0; always begin #10 clk = 1; #10 clk = 0; end initial begin for (i = 0; i <= 255; i=i + 1) @(negedge clk) stimulus = i; #20 $finish; endmodule

Stimulus From Arrays Stimulus applied from an array has the following characteristics: § You can load the stimulus from a data file directly into the array § For each iteration you read a new stimulus vector from the array module array_tb; wire [7: 0] response; reg [7: 0] stimulus, stim_array[0: 15]; integer i; DUT u 1 (response, stimulus); initial begin $readmemb(“datafile”, stim_array); for (i = 0; i <= 15; i = i + 1); #20 stimulus = stim_array[i]; #20 $finish; endmodule

Vector Capture and Playback You can capture manufacturing test vectors at the boundary of a device model. parameter period = 20 wire [7: 0] response; reg [7: 0] stimulus; DUT u 1 (response, stimulus); always apply (stimulus); always verify (response); task capture_tb; integer MCDR, MCDS; begin MCDR = $fopen(“response. dat”); if (!MCDR) $finish; MCDS = $fopen(“stimulus. dat”); if (!MCDS) $finish; forever @(posedge clk) #(period - 1) begin $fdisplayb (MCDR, “ %b”, response); $fdisplayb (MCDS, “ %b”, stimulus); end endtask

Vector Capture and Playback You can play back the saved stimulus and response vectors. parameter MAX_VECTOR = 255; wire [7: 0] response; reg [7: 0] stimulus, stim_array[0: 255], resp_arry[0: 255]; DUT u 1 (response, stimulus); task playback_tb; integer MCDR, MCDS, i; begin $readmemb(“response. dat”, resp_array); $readmemb(“stimulus. dat”, stim_array); @(negedge clk) //synchronize to inactive clock stimulus = stim_array[0]; //apply 1 st stimulus for (i = 0; i <=MAX_VECTOR; i = i + 1) @(negedge clk) begin if (response != = resp_array[i]) begin //check response $display(“ERROR: response is %b, should be %b”, response, resp_array[i], “n. TEST FALLED”); $finish; end if (i = = MAX_VECTOR) begin $display(“TEST PASSED”); $finish; end stimulus = stim_array[i + 1]; //apply next stimulus end endtask

Forcing Stimulus You can make two types of procedural continuous assignments: § You can assign and deassign a register assign <lvalue> = <expression> This overrides any procedural assignment to the register initial begin #10 assign top. dut. fsm 1. state_reg = `init_state; #20 deassign top. dut. fsm 1. state_reg; end § You can force and release a register or net This overrides all drivers of the signal initial begin #10 force top. dut. counter. scan_reg. q = 0; #20 release top. dut. counter. scan_reg. q; end

Reporting Warnings and Errors Use file output system tasks to report errors and warnings. A more sophisticated testbench would: § Report an error to a centralized error handler § Modify the test flow, depending upon the errors encountered § Maintain error statistics, and report them at the end of the test task par_err_task; forever @(posedge par_err) err_handle_task (`NONFATAL, `PARITY); endtask cor_err_task; forever @(posedge cor_err) err_handle_task (`NONFATAL, `CORRECTABLE); endtask

Summary In this section, you learned about designing a testbench: § Creating clocks § Including files § Strategic use of tasks and concurrent statements § Controlling and observing the design § Reporting warnings and errors

Review 1. 2. 3. 4. 5. What are some characteristics of a sophisticated testbench? For what purpose might you define a Verilog task in your testbench? What is the difference between a begin-end block and a fork-join block? How can you efficienly generate regular stimulus? What data type would you use to read stimulus from a file?

About Lab 8 This lab is in two parts. The objective of the first part is to use behavioral constructs to model a small combinational Arithmetic Logic Unit (ALU). In this part, you will: § Model an ALU at the behavioral level § Test the ALU with the proveded testbench The objective of the second part is to create a model of a 5 -bit counter using Verilog behavioral constructs. In this part, you will: § Model a 5 -bit counter at the behavioral level § Write a testbench for your xounter design
- Slides: 20