Vous êtes sur la page 1sur 23

1

Self checking testbench


Kerul modi Shaunak patel Meetanshi Gor

Advantages
Speeds up verification and results in early tape out of the chip. Less man power is required, by which the over all cost of the project will be low. Environment can be reusable. Easy tracking of verification progress(functional coverage). Developing self checking testbench is very interesting.

What is self checking??


Self-checking means that the testbench is capable of generating its own valid output for each set of stimuli without the user having to explicitly enter it. Instead of relying solely on visual inspection of waveforms ,Verilog test benchs can actually do inspection for you - this is called a selfchecking testbench

The basic Testbench

1. A device under test, called a DUT. This is what your testbench is testing.

2. A set of stimulus for your DUT. This can be simple, or complex.


3. A monitor, which captures or analyzes the output of your DUT. 4. You need to connect the inputs of the DUT to the testbench. 5. You need to connect the outputs of the DUT to the testbench.

Simple testbench
module mux_tb(); wire c; reg a,b,s; mux m1(c, a, b, s) ; initial begin a=1'b0; b=1'b0; s=1'b0; #5 a=1'b1; #5 s=1'b1; #5 $finish; // The $finish call ends simulation. end initial begin $dumpfile("mux_tb.dump"); $dumpvars (0,mux_tb); end endmodule

Structured Verilog Test Benches


A more complex, self checking test bench may contain some, or all, of the following items: 1. Parameter definitions 2. Preprocessor Directives 3. The timescale directive 4. Include Statements 5. DUT Input regs 6. DUT Output wires 7. DUT Instantiation 8. Generating Test Vectors 9. Debug output 10. Self checking

Parameter definition
Parameterize items in your test bench - this makes it much easier for you and others to read and understand your testbench Commonly parameterized items are as follows.

1.Clock period 2. finish time 3. control words 4. data widths

Insert parameter
module mux_tb(); parameter finishtime= 5 ; wire c; reg a,b,s; mux m1(c, a, b, s) ; initial begin a=1'b0; b=1'b0; s=1'b0; #5 a=1'b1; #5 s=1'b1; #finishtime $finish; // The $finish call ends simulation.

Preprocessor Directives
A preprocessor directive works in a very similar fashion to a parameter. It is essentially a variable that gets replaced when encountered. It is typically used for variables you want GLOBAL to all modules . cver mux_tb.v +define+DELAY=10

10

Insert preprocessor directive


`define DELAY 5 module mux_tb(); parameter finishtime= 5 ; wire c; reg a,b,s; mux m1(c, a, b, s) ; initial begin a=1'b0; b=1'b0; s=1'b0; #`DELAY a=1'b1; #`DELAY s=1'b1; #finishtime $finish; // The $finish call ends simulation. end initial begin $dumpfile("mux_tb.dump"); $dumpvars (0,mux_tb); end endmodule

:timescale:

`timescale 10ns/100ps; #5.46734 i=1; 5.46834*10=54.6834 Resolution is 0.1ns Delay will be 54.6 but verilog rounded this delay to 54.7

12

Timescale directive
`timescale 10ns/1ps ; module tim(); reg i; initial begin i=0; #7.7212; i=1; $display("STATEMENT 1 :: time is ",$time); end endmodul Output: STATEMENT 1 :: time is 8

13

`timescale 10ns/1ps; module try; reg i; initial begin i=0; #7.7212; i=1; $display("STATEMENT 1 :: delay for %0t",$time ); $display("STATEMENT 2 :: delay for %0t",$realtime); end endmodule output:

STATEMENT 1 :: delay for 80000 STATEMENT 2 :: delay for 77212

14

Include statements
Include statements are similar to C style include statements. They allow a another file to be a part of the current file. They are commonly used to include a file with the timescale directive. They can also be used outside of testbenches, often for global constants.

15

Insert include statement


`include "fa.v"; //or `include pathname;
module carry_ripp(sum,cout,a,b); output [3:0] sum; output cout; input [3:0] a,b; wire c0,c1,c2; fa h1(sum[0],c0,a[0],b[0],0); fa h2(sum[1],c1,a[1],b[1],c0); fa h3(sum[2],c2,a[2],b[2],c1); fa h4(sum[3],cout,a[3],b[3],c2); endmodule

16

DUT Input regs & output wires


Because use of procedural style verilog to create testbench, any variable you assign data to, you must use a REG type to do so. This is why the inputs to your DUT, will be REGs. The output from the DUT needs to be connected to something, for this you'll want to use wires. Instance your output wires together. Since you are not assigning the data to the outputs inside the procedural block, the outputs can be assigned to wires and not registers (REGs).

17

DUT Instantiation
Connecting by ordered list mux m1(c, a, b, s); Connecting by port names mux m1(.c(c), .a(a), .b(b), .select(s)); Named ports do not depend on the port order , depends only on port name. It's a more portable way of instantiating modules. Now the local variable s, is connected to the port select inside the module. the named port

18

Generating Test Vectors


`include "globals.v" module mux_tb(); parameter finishtime= 5 ; integer N; wire c; reg [2:0] test_vectors; // 3-bit wide test vector mux m1(.c(c), .a(test_vectors[2]), .b(test_vectors[1]), .select(test_vectors[0])); initial begin test_vectors = 3b000; end initial begin for(N=0; N<7; N=N+1) #`DELAY test_vectors = test_vectors + 1; #finishtime // after finishtime expires $display ("Time is - %d",$time); $finish; end endmodule

everything below will printout

19

Debug output
`include "globals.v" module mux_tb(); parameter finishtime= 5 ; integer N; wire c; reg [2:0] test_vectors; // 3-bit wide test vector mux m1(.c(c), .a(test_vectors[2]), .b(test_vectors[1]), .select(test_vectors[0])); initial begin // initialize all variables $monitor ("TIME = %d, test_vectors= %b, c= %b", $time, test_vectors, c); test_vectors = 3b000; end initial begin for(N=0; N<7; N=N+1) #`DELAY test_vectors = test_vectors + 1; #finishtime // everything below will printout after finishtime expires $display ("Time is - %d",$time); $finish; end endmodule

20

The output of this testbench will be: TIME = 0, test_vectors= 000, c= 0 TIME = 5, test_vectors= 001, c= 0 TIME = 10, test_vectors= 010, c= 1 TIME = 15, test_vectors= 011, c= 0 TIME = 20, test_vectors= 100, c= 0 TIME = 25, test_vectors= 101, c= 1 TIME = 30, test_vectors= 110, c= 1 TIME = 35, test_vectors= 111, c= 1

21

Self-checking
it would be better if the test-bench could check itself and let us know if any test case has failed. At the top level testbench this is always preferred so that the waveforms do not have to be viewed.

Example of sequence detector

1 0 10110 1

S0
000

S1
001

S2
010

S3
011

S4
100

0 0

0/1

23

THANK YOU

Vous aimerez peut-être aussi