Verilog Chapter9 Testbench and Verification
Verilog Chapter9 Testbench and Verification
LECTURE
Subject: VERILOG
Hardware Design Language
Chapter9: Testbench and Verification
3
CAD flow reminder
Pre-synthesis Design Specification
verification:
Behavior Description
Pre-synthesis verification
Post-synthesis verification
Physical layout
Chip 4
CAD flow reminder (Cont’d)
Function verification with input waveform:
5
CAD flow reminder (Cont’d)
Function verification with testbench:
6
CAD flow reminder (Cont’d)
Function verification with testbench:
7
Structure of a testbench
•Structure1
8
Structure of a testbench (Cont’d)
•Structure1 (Cont’d)
9
Structure of a testbench (Cont’d)
•Structure1 (Cont’d)
10
Structure of a testbench (Cont’d)
•Structure1 (Cont’d)
11
Structure of a testbench (Cont’d)
•Structure2
module testbench;
parameter declaration This part is same to Verilog
declaration such as the signal RTL programming in the
previous pages
(reg [7:0] dat, … and so on)
design module instances
always sentence Used for generating clock
signals and other signals
initial sentence
definition of function
Used to give initial value to the
definition of task
signals and to create signals
endmodule in time sequence
12
Structure of a testbench (Cont’d)
•Structure2 (Cont’d)
D_FF example:
13
Structure of a testbench (Cont’d)
•Structure2 (Cont’d)
`timescale 1ns/1ps
module stimulus;
reg din, clock;
reg exp;
wire dout;
parameter clk_cycle = 20;
// Instance DFF
dff instance_1 (.d(din), .clk(clock), .q(dout));
// Clock generator
always
begin
#(clk_cycle/2) clock = ~clock;
$display( "Time at %5f. DIN: [%b] DO=[%b]", $realtime, din, dout);
end
14
Structure of a testbench (Cont’d)
•Structure2 (Cont’d)
// Input waveform and Expected output
initial
begin
clock = 1'b0;
din = 1'b0; //Compare output
fork always @(negedge clock)
#6 din = 1'b1; begin
#11 exp = 1'b1; if (dout !== exp)
#26 din = 1'b0; $display( "FAIL: %5f -
#31 exp = 1'b0; output=[%b] Exp=[%b]", $realtime, dout, exp);
#46 din = 1'b1; else
#51 exp = 1'b1; $display( "PASS: %5f -
#66 din = 1'b0; output=[%b] Exp=[%b]", $realtime, dout, exp);
#71 exp = 1'b0; end
#100 $finish; endmodule
join
end 15
Test vectors definition
To do test, you must have the state transition matrix of your logic. You
have to apply data which causes all the possible transition of the state.
state ….
input INTL ST1 ST2
in1 no- ST2 ST3 ….
op
If you have not prepared a
in2 ST1 ST3 state transition matrix, write it.
in3 ST2
…. ….
17
Test vectors definition (Cont’d)
How to select typical and corner cases.
What data can check corner cases depend on the logic to handle them.
However, we have to have a good sensitivity to tell what kind of data may
be critical for various logic.
Example
For 1-bit control input data which is supposed to be 1 several times for
certain period of time,
Input sequence: 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, … may be typical input,
1, 1, 1, 1, 1, 1, 1, 1, … may be corner case input.
18
Test vectors definition (Cont’d)
Suppose testing logic which calculate average of four 4-bit positive integers.
4-bit output average must be rounded.
If we prepare the following data for testing, is it effective for finding bugs?
Question: For the logic below, we got output average 3, for the input a1=4,
a2=2, a3=3, and a4=3. The result is looks OK. However what kind of bugs may
exist in the logic. Imagine!!!
a1
reslt_sum
+
a2
divide
+ average
a3 by 4 rounding
+
a4
21
Test vectors definition (Cont’d)
A sample answer.
a1=4
6 reslt_sum
+
a2=2
divide
+ average
a3=3 by 4 rounding 3
2
+
a4=3
a1=4
6 reslt_sum
+
a2=2
divide
+ average
a3=3 by 4 rounding 3
2
+
a4=3 6
22
Test vectors definition (Cont’d)
a1=4
6 reslt_sum
+
a2=2
divide
+ average
a3=3 by 4 rounding 3
2
+
a4=3 6
Therefore the following method is the most terrible way to fix bigs.
Never do this way.
What’s wrong??
Run simulation
Yes, my code is OK,
yes no
because the simulation Looks OK???
result says “it is OK”
24
This is not true.
Test vectors definition (Cont’d)
Do not think
“my code is correct, because
the simulation result is OK”
25
Test vectors definition (Cont’d)
Check if code and state
transition matrix is identical.
If not, correct code
yes no
initial
$monitor(
"select=%b in0=%b in1=%b out=%b, expected out=%b time=%d",
s, a, b, f, expected, $time);
endmodule // testmux
28
Example2
module multiplexor4_1(out, in1, in2, in3, in4, cntrl1, cntrl2);
output out;
input in1, in2, in3, in4, cntrl1, cntrl2;
reg out;
29
Example2 (Cont’d)
module muxstimulus (IN1, IN2, IN3, IN4, CNTRL1, CNTRL2, OUT);
output IN1, IN2, IN3, IN4, CNTRL1, CNTRL2;
input OUT;
reg IN1, IN2, IN3, IN4, CNTRL1, CNTRL2;
initial
begin
{CNTRL1, CNTRL2}=2’b00; {IN1, IN2, IN3, IN4} = 4’b1010; expected=1;
#10 {CNTRL1, CNTRL2}=2’b01; {IN1, IN2, IN3, IN4} = 4’b1010; expected=0;
#10 {CNTRL1, CNTRL2}=2’b10; {IN1, IN2, IN3, IN4} = 4’b1010; expected=1;
#10 {CNTRL1, CNTRL2}=2’b11; {IN1, IN2, IN3, IN4} = 4’b1010; expected=0;
end
initial
begin
$display("Initial arbitrary values");
#0 $display("input1 = %b, input2 = %b, input3 = %b, input4 = %b, control1 = %b,
control2 = %b, output = %b, expected output = %b, time = %d\n",
IN1, IN2, IN3, IN4, CNTRL1, CNTRL2, OUT, expected, $time);
end
endmodule
30
Example2 (Cont’d)
muxstimulus stim
(.IN1(a), .IN2(b), .IN3(c), .IN4(d), .CNTRL1(s1), .CNTRL2(s2), .OUT(f));
multiplexor4_1 mux
(.in1(a), .in2(b), .in3(c), .in4(d), .cntrl1(s1), .cntrl2(s2), .out(f));
endmodule
31
Example3
Input Output
D7 D6 D5 D4 D3 D2 D1 D0 A2 A1 A0
0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 1 0 0 0 1 0
0 0 0 0 1 0 0 0 0 1 1
0 0 0 1 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0 1 0 1
0 1 0 0 0 0 0 0 1 1 0
1 0 0 0 0 0 0 0 1 1 1
32
Example3 (Cont’d)
module encoder8_3( encoder_out , enable, encoder_in );
output[2:0] encoder_out;
input enable;
input[7:0] encoder_in;
reg[2:0] encoder_out; Sensitivity list.
always @ (enable or encoder_in)
begin
if (enable)
Simple behavioral code using the
case ( encoder_in )
8'b00000001 : encoder_out = 3'b000; case statement.
8'b00000010 : encoder_out = 3'b001;
8'b00000100 : encoder_out = 3'b010;
8'b00001000 : encoder_out = 3'b011;
8'b00010000 : encoder_out = 3'b100;
8'b00100000 : encoder_out = 3'b101;
8'b01000000 : encoder_out = 3'b110;
8'b10000000 : encoder_out = 3'b111;
default : $display("Check input bits.");
endcase
end
endmodule
33
Example3 (Cont’d)
module stimulus;
wire[2:0] encoder_out;
reg enable;
reg[7:0] encoder_in;
reg [2:0] expected;
encoder8_3 enc( encoder_out, enable, encoder_in );
initial
begin
enable = 1; encoder_in = 8'b00000010, expected = 3’b001;
#1 $display("enable = %b, encoder_in = %b, encoder_out = %b, expected_out =
%b", enable, encoder_in, encoder_out, expected);
#1 enable = 0; encoder_in = 8'b00000001; expected = 3’b001;
#1 $display("enable = %b, encoder_in = %b, encoder_out = %b, expected_out =
%b ", enable, encoder_in, encoder_out, expected);
#1 enable = 1; encoder_in = 8'b00000001; expected = 3’b000;
#1 $display("enable = %b, encoder_in = %b, encoder_out = %b, expected_out =
%b ", enable, encoder_in, encoder_out, expected);
#1 $finish;
end
34
endmodule
Example4
• Let’s have a look on a module named “priority” and its stimulus named “priority_sti”
priority.v:
module priority (A, P, F);
//Function definition
// Parameter definition
function [log2N:0] priority;
parameter N = 8;
parameter log2N = 3; input [N-1:0] A;
// Input/Output definition reg F;
input [N-1:0] A; //Input Vector integer I;
output [log2N-1:0] P; // High Priority Index begin
output F; // Found a one? F = 1'b0;
// Register definition priority = {3'b0, F};
reg [log2N-1:0] P; for (I=0; I<N; I=I+1)
reg F; if (A[I]) begin
always @(A) begin F = 1'b1;
{P, F} <= priority(A); priority = {I, F};// Override
end
previous
//index
end
end
endfunction
endmodule
35
Example4 (Cont’d)
priority_sti.v:
`timescale 1ns/1ps
module stimulus;
reg [7:0] Input;
wire [2:0] Priority;
wire Found_one;
// Instance
priority priority_inst (Input, Priority, Found_one);
// Begin test
initial begin
test_pri(8'b01100100, 6, 1);
test_pri(8'b01100100, 6, 0);
test_pri(8'b01100100, 7, 1);
test_pri(8'b01100100, 7, 0);
test_pri(8'b00010010, 4, 0);
test_pri(8'b00010010, 4, 1);
test_pri(8'b00010010, 3, 0);
test_pri(8'b00010010, 3, 1);
end
36
Example4 (Cont’d)
// Task definition
task test_pri;
input [7:0] in;
input [2:0] pri;
input f;
begin
#5 Input = in;
#1;
if((pri !== Priority)||(f !== Found_one))
$display("FAIL at time %0d, Input=%b, Priority=%d,
Priority_exp=%d, Found_one=%b, Found_one_exp=%b\n",$time,in, Priority, pri, Found_one,
f);
else
$display("PASS at time %0d, Input=%b, Priority=%d,
Priority_exp=%d, Found_one=%b, Found_one_exp=%b\n",$time,in, Priority, pri, Found_one,
f);
End
endtask
endmodule
37
Example5
38
Example5 (Cont’d)
Parameters that may be set
when the module is instantiated.
endmodule
39
Example5 (Cont’d)
module testGenerator (A, B, greaterNotLess, result);
output [15:0] A, B;
output greaterNotLess;
input result;
parameter del = 5; Module that generates test vectors for
reg [15:0] A, B; the comparator and checks correctness
reg greaterNotLess; of output.
task check;
input shouldBe;
begin
if (result != shouldBe)
$display("Error! %d %s %d, result = %b", A, greaterNotLess?">":"<",
B, result);
end
endtask
40
Example5 (Cont’d)
initial begin // produce test data, check results
A = 16'h1234;
B = 16'b0001001000110100; // 16’h1234
greaterNotLess = 0;
#del check(0); Task call
B = 0;
greaterNotLess = 1;
#del check(1);
A = 1;
greaterNotLess = 0;
#del check(0);
$finish;
end
endmodule
41
Example5 (Cont’d)
module system;
wire greaterNotLess; // sense of comparison
wire [15:0] A, B; // comparand values - 16 bit
wire result; // comparison result
// Module instances
testGenerator tg (A, B, greaterNotLess, result);
comparator #(16, 2) comp (result, A, B, greaterNotLess);
endmodule
42
Example6
Divide-by-3 clock reducer. The input to the module is a reference clock,
and the output is a clock signal which has a pulse every three cycles of
the reference clock. The pulse width should be the same for both clocks.
43
Example6 (Cont’d)
44
Example6 (Cont’d)
45
Example6 (Cont’d)
module system;
wire slowClk, clk; // two clocks
// Module instances
divideBy3 d3 (.outClk(slowClk), .inClk(clk)); // clock divider
clkGen #(10) cg (clk); // clock generator
initial begin
$monitor ($stime, " clk: %b slowClk: %b", clk, slowClk);
#150 $finish;
end
endmodule
46
Example7
Implement a shift and count register. A data value is shifted in on every clock cycle,
on the rising edge, and the oldest value is shifted out. The shift register is fifo.
Count the number of ones which are present in the shift register. The counter
should be 32 bits wide (admitedly, this is overkill). The depth of the shift register
should be parameterized.
The module ports are:
data input (1 bit), clock (1 bit), data output (1 bit), counter (32 bits).
47
Example7 (Cont’d)
module shiftAndCount (bitOut, count, dataIn, clk);
parameter width = 8;
output bitOut; // data shifted out
output [31:0] count; // count of ones
input dataIn, clk; // inputs
integer count; // the counter
reg bitOut; // temporary
reg [width-1:0] lastBits; // shift register
49
Example7 (Cont’d)
50
Example7 (Cont’d)
module testGenerator (dataBit, delayedBit, count, clk);
output dataBit;
input delayedBit;
input [31:0] count;
input clk;
reg dataBit; Module generates test vectors and
checks result.
initial begin // produce test data, check results
$monitor($time," dataBit: %b delayedBit: %b", dataBit, delayedBit);
emitBits(0, 1); // take care of first cycle
emitBits('b10010, 5);
check(0, 2);
emitBits('b101101, 6);
check(0, 5);
emitBits('b01, 2);
check(1, 5);
$stop;
end
Tasks: emitBits, check
51
Example7 (Cont’d)
task emitBits; // helper task to emit n bits
input [7:0] bits, n; // task inputs
begin
repeat (n) begin // assume clk is at negedge
dataBit = bits[0]; // take just the low order bit
bits = bits >> 1;
@(negedge clk) ;
end // leave at negative edge
end
endtask
task check;
input bit;
input [31:0] shouldBe;
begin
if (delayedBit != bit)
$display($time," delayed bit is %b but should be %b",
Task definitions.
delayedBit, bit);
if (count != shouldBe)
$display($time," Count is %d but should be %d",
count, shouldBe);
end
endtask
endmodule
52
Example7 (Cont’d)
module system;
wire data, clk; // nets to connect up the pieces
wire delayedData; // data out of the fifo
wire [31:0] nOnes; // number of ones contained in fifo
// Module instances
shiftAndCount SandC (delayedData, nOnes, data, clk); // shift register
clkGen #(10) cg (clk); // generate the clock
testGenerator tg (data, delayedData, nOnes, clk); // create data, check result
endmodule
53
Example8
4-bit adder. It takes two 4-bit operands, inA and inB, and produces
a 4-bit result, sum, and a 1-bit carry. It is composed of four
1-bit adders, each of which has a carry in as well as the two operand inputs
t1
t2
t3
Full 1-bit adder
54
Example8 (Cont’d)
55
Example8 (Cont’d)
56
Example8 (Cont’d)
module adderTest (A, B, sum, carry);
output [3:0] A, B;
input [3:0] sum;
input carry;
reg [3:0] A, B;
integer i, j;
initial begin Module generates test vectors.
$monitor ("A: %d B: %d sum: %d carry: %d", A, B, sum, carry);
for (i=0; i<16; i=i+1)
for (j=0; j<16; j=j+1)
begin
A = i;
B = j;
#1 ;
end
$finish;
end
endmodule
57
Example8 (Cont’d)
module ex2_1;
wire [3:0] sum, inA, inB;
wire carry;
Stimulus.
58
Example9
D Dbar X
a2 Z
r1 r3 Q
n1
clk clkbar
a1
r2 n2
Y
clear a3 cbar
Clocked D-latch, exactly as in clockedD_latch.v with a clear wire added
Q1
D Q
Master D-latch Slave D-latch
Qbar
clkbar
clk
Master-slave design D-flipflop
clear 59
Example9 (Cont’d)
// Clocked D-latch as in clockedD_latch.v with a clear signal added
module clockedD_latch(Q, Qbar, D, clk, clear);
output Q, Qbar;
input D, clk, clear;
wire X, Y, Z, clkbar, Dbar, cbar;
output q, qbar;
input d, clk, clear;
wire q1;
initial
begin
clear = 0;
#2 d = 0;
#0 $display(" time = %d, clk= %b, d = %b, q= %b\n", $time, clk, d, q);
#4 d = 1;
#0 $display(" time = %d, clk= %b, d = %b, q= %b\n", $time, clk, d, q);
#2 d = 0;
#0 $display(" time = %d, clk= %b, d = %b, q= %b\n", $time, clk, d, q);
#4 d = 1;
#0 $display(" time = %d, clk= %b, d = %b, q= %b\n", $time, clk, d, q);
#10 d = 0;
#0 $display(" time = %d, clk= %b, d = %b, q= %b\n", $time, clk, d, q);
end
initial
begin
#100 $finish;
end
endmodule
Explain output!
61
Example10
q0 q1 q2 q3
q q q q
clock T_FF T_FF T_FF T_FF
tff0 tff1 tff2 tff3
clear
62
Example10 (Cont’d)
endmodule
63
Example10 (Cont’d)
module stimulus;
reg CLOCK, CLEAR;
wire [3:0] Q;
initial
$monitor($time, " Count Q = %b Clear= %b", Q[3:0],CLEAR);
65
Timing check
• Using Timing Check:
To verify the timing characteristics of your design, you
can invoke the following timing check system tasks in
specify blocks:
$hold(<clk_event>, <data_event>, <hold_limit>{,
<notifier>});
$period(<clk_event>, <period_limit> {, <notifier>});
$setup(<data_event>, <clk_event>, <setup_limit>{,
<notifier>});
$skew(<clk_1>, <clk_2>, <skew_limit> {, <notifier>});
$width(<edge_clk>, <min_limit> {,<threshold>{,
<notifier>}});
…
66
Timing check (Cont’d)
• $hold
The $hold system task determines whether a data
signal remains stable for a minimum specified time after
a transition in an enabling signal, such as a clock signal
that latches data in a memory.
The $hold system task has the following syntax:
$hold(<clk_event>, <data_event>,
<hold_limit> {, <notifier>});
The following example illustrates how to use the $hold
system task:
specify
specparam hold_param=11;
$hold( posedge clk, data, hold_param );
$hold( posedge clk, data, hold_param, flag ) ;
endspecify
67
Timing check (Cont’d)
• $setup
The $setup system task determines whether a data signal remains stable
before a transition in an enabling signal, such as a clock signal that latches
data in memory.
In the following example, the $setup system task reports a violation if the
interval from <data_event> to <clk_event> is less than <setup_limit> (10).
The second specification of the $setup system task uses an option notifier,
flag, to indicate a timing violation.
specify
specparam setup_param=10;
$setup( data, posedge clock, setup_param ) ;
$setup( data, posedge clock, setup_param, flag ) ;
endspecify
68
Timing check (Cont’d)
• $width
The $width system task specifies the duration of signal levels from one clock
edge to the opposite clock edge. A violation occurs when signals are too close
together. If you use edge specifiers, all edges must be of the same direction.
The following example shows how to use the $width system task to report a
violation if the interval from <edge_clk> (negedge clr) to the implicit
<data_event> (posedge clr) is less than <min_limit> (which is 12).
specify
specparam width_param=12;
$width( negedge clr, width_param ) ;
$width( negedge clr, width_param, 0, flag ) ;
endspecify
69
Timing check - Example
dff.v:
module dff (D, Q, CLK);
input D;
input CLK;
output Q;
reg Q1;
wire Q = Q1;
always @(posedge CLK)
Q1 <= D;
specify
specparam t_setup = 5;
specparam t_acc = 10;
specparam t_pwh = 20;
specparam t_pwl = 20;
$setup( D, posedge CLK, t_rise_setup);
$width(edge[01,x1]CLK,t_pwl);
$width(edge[10,1x]CLK,t_pwh);
(CLK => Q) = t_acc;
endspecify
endmodule
70
Timing check – Example (Cont’d)
dff_sti.v:
`timescale 1ns/1ps
module stimulus;
reg din, clock;
reg exp;
wire dout;
parameter clk_cycle = 60;
// Instance DFF
dff instance_1 (.D(din), .), .Q(dout));
// Clock generator
always
begin
#(clk_cycle/2) clock = ~clock;
end
71
Timing check – Example (Cont’d)
// Input waveform and Expected output
initial
begin
clock = 1'b0;
din = 1'b0;
fork
#24 din = 1'b1;
#41 exp = 1'b1;
#84 din = 1'b0;
#101 exp = 1'b0;
#144 din = 1'b1;
#161 exp = 1'b1;
#206 din = 1'b0;
#221 exp = 1'b0;
#250 $finish;
join
72
end
Timing check – Example (Cont’d)
//Compare output
always @(exp)
begin
if (dout !== exp)
$display( "FAIL: %5f - Output=[%b] Exp=[%b]", $realtime, dout, exp);
else
$display( "PASS: %5f - Output=[%b] Exp=[%b]", $realtime, dout, exp);
end
endmodule
73