writing a test bench in verilog
DESCRIPTION
Writing a Test Bench in Verilog. Writing a Test Bench. A test bench is an HDL program used for applying stimulus to an HDL design in order to test it and observe its response during simulation. - PowerPoint PPT PresentationTRANSCRIPT
A test bench is an HDL program used for applying stimulus to an HDL design in order to test it and observe its response during simulation.
In addition to the always statement, test benches use the initial statement to provide a stimulus to the circuit under test.
The always statement executes repeatedly in a loop. The initial statement executes only once starting from simulation time=0 and may continue with any operations that are delayed by a given number of units as specified by the symbol #.
A stimulus module is an HDL program that has the following form.module testname
Declare local reg and wire identifiersInstantiate the design module under test.Generate stimulus using initial and always statementsDisplay the output response.
endmodule A test module typically has no inputs or outputs. The signals that are applied as inputs to the design
module for simulation are declared in the stimulus module as local reg data type.
The outputs of the design module that are displayed for testing are declared in the stimulus model as local wire data type.
The module under test is then instantiated using the local identifiers.
The stimulus model generates inputs for the design module by declaring identifiers TA and TB as reg data type, and checks the output of the design unit with the wire identifier TC. The local identifiers are then used to instantiate the design module under test.
The response to the stimulus generated by the initial and always blocks will appear at the output of the simulator as timing diagrams.
It is also possible to display numerical outputs using Verilog system tasks.◦ $display – display one-time value of variables or strings
with end-of-line return,◦ $write – same $display but without going to next line.◦ $monitor – display variables whenever a value changes
during simulation run.◦ $time – displays simulation time◦ $finish – terminates the simulation
The syntax for $display,$write and $monitor is of the formTask-name (format-specification, argument list);E.g. $display(%d %b %b, C,A,B);
$display(“time = %0d A = %b B=%b”,$time,A,B);
//Dataflow description of 2-to-1-line multiplexer
module mux2x1_df (A,B,select,OUT);
input A,B,select;
output OUT;
assign OUT = select ? A : B;
endmodule
//Stimulus for mux2x1_dfmodule testmux; reg TA,TB,TS; //inputs for mux wire Y; //output from mux mux2x1_bh mx (TA,TB,TS,Y); // instantiate mux initial begin $monitor(”select=%b A=%b B=%b OUT=%b",TS,TA,TB,Y); TS = 1; TA = 0; TB = 1; #10 TA = 1; TB = 0; #10 TS = 0; #10 TA = 0; TB = 1; endendmodule
Design Module
A B Out
0 0 0
0 1 0
1 0 0
1 1 1
Truth Table
A
B
OUT
0
0
0
0
1
0
1
0
0
1
1
1
0 ns 20 ns 40 ns 60 ns 80 ns
Design Module
Test Bench
A
in
Y
module and_2in (A, B, Out);
input A, B;output Out;
wire Out;
assign Out = A & B;
endmodule
`include “and_2in.v”`timescale 1ns/10psmodule and_2in_tb;
reg A, in;wire Y;
and_2in a1(.A(A),.B(in),.Out(Y));
initialbegin
A=0; in=0;#20;A=0; in=1;#20;A=1; in=0;#20;A=1; in=1;#40;$stop;$finish;
end
endmodule
D
clk
Q
Q_n
reset_n
Design Module
Test Bench
D Clk reset_n Q Q_n
1 1 0 0 1
1 0 0 0 1
1 1 1 1 0
0 0 1 1 0
0 1 1 0 1
1 0 1 0 1
D
clk
Q
Q_n
reset_n
Design Module
TestBench
in
out
outbar
clock
reset
module dff (D, reset_n, clk, Q, Q_n);input D, clk, reset_n;output Q, Q_n; reg Q, Q_n;
always @ (posedge clk or negedge reset_n)begin
end
if(reset_n == 0)begin
Q <= 0;Q_n<=1;
endelsebegin
Q <= D;Q_n <= !D;
end
`include “dff.v”`timescale 1ns/10psmodule dff_tb;reg in, clock, reset;wire out, outbar;dff d1(.D(in),
.reset_n(reset),
.clk(clock),
.Q(out),
.Q_n(outbar));
initialbegin
in =0; reset =0; clock =0;#10;reset =1; #5;in=1;#10;in=0;#40;$stop;
endalways #10 clock = ~clock;
endmodule
Reset the counter asynchronously through active low global reset reset_n
reset the count when the count has reached value max_count
Advance the counter through active high enable signal
reset_n
max_count[7:0]
enable
clk
count[7:0]
assign reset_count = (count == max_count);/* Generates the signal reset_count
which resets the counter when the count reaches value of input max_count */
assign cnt_next = count +1;// Preincrement the value of count
always @ (posedge clk or negedge reset_n)begin
if(reset_n ==0)count <= 8’d0;
else if(reset_count == 1)count <= 8’d0;
else if(enable ==1)count <= cnt_next;
else count <= count;
end
`include “counter.v”`timescale 1ns/10psmodule counter_tb;reg reset_n, clk, enable;reg[7:0] max_count;wire[7:0] count;
counter c1(.reset_n(reset_n),.clk(clk),.enable(enable),.max_count(max_count),.count(count)
);
initial begin
reset_n =0; clk =0; enable =0; max_count =100;#25;reset_n =1; enable =1;#5000;$stop;
endalways #10 clock =~ clock;endmodule
Loads data set_data into the register when load signal is high
Shifts data when shift signal is high Can perform both right and left shift
operations rl_n signal indicates whether to shift right or
left. A high value shifts right and a low value shifts left.
data_valid is high whenever data is valid and eoc is asserted when transfer is complete
reset_n
clk
rl_n
shift
load
set_data[15:0]data_out
data_valid
eoc
always @ (posedge clk or negedge reset_n)begin
if(reset_n == 0)begin
data_out<=0; data_valid<=0; eoc <=0;sr <=0; cnt_reg <=0;
endelse if(load ==1)begin
sr<= set_data; cnt_reg <=16;data_out<=0; data_valid<=0; eoc <=0;
end
else if ((shift==1) && (cnt_reg !=0))begin
sr <= rl_n ? (sr >> 1) : (sr <<1);data_out <= rl_n ? sr[0] : sr[15]; cnt_reg <= cnt_reg -1;data_valid <=1; eoc<=0;
end
else if ((shift==1) && (cnt_reg ==0))begin
sr <=sr; cnt_reg <=cnt_reg;data_out<=0; data_valid<=0; eoc <=1;
end
elsebegin
sr <=sr; cnt_reg <=cnt_reg;data_out<=data_out; data_valid<=data_valid; eoc <=eoc;
end
module parallel_serial_tb ;reg reset_n, load, shift, rl_n, clk;reg[15:0] set_data;wire data_out, data_valid, eoc;
parallel_serial p1(.reset_n(reset_n), .load(load), .shift(shift), .rl_n(rl_n), .clk(clk), . set_data(set_data),.data_out(data_out), .data_valid(data_valid), .eoc(eoc) );
initialbegin
reset_n =0;load=0; shift=0;rl_n=0; clk=0;set_data=0;#25;reset_n =1; set_data = 16’hAAAA; load =1;#20;load =0; shift =1;#400;shift =0;#20;rl_n =1; load=1;#20;shift=1;#500;$stop;
endalways #10 clk = ~clk;endmodule