ECAD and Architecture Practical Classes
Verilog Tutorial Part 4 - Simulation and Test Benches
Test Benches
A test bench is used to intatiate a design and provide inputs. For
example, the following test bench can be used to test the timer
module from the previous page. This test bench will generate
the clk
and rst
signals, and output
the t
signal generated.
The following test bench uses several simulation only System Verilog commands including:
initial
used to initialise registers in a particular sequential order. Note the use of blocking assignment on registers that only makes sense in simulation.$dumpfile
and$dumpvars
functions tell the simulator where to store a simulation trace and what variables to dump to the trace file.#20
and#100
are examples of simulation delays in terms of simulation time steps.- Simulation functions:
$finish
to end the simulation,$display
to print output similar to printf() in C, and$time
which is a variable that returns the current simulation time step. always @(posedge clk)
is used to sequence output on the positive edge of the clock.- In simulation the
always
statement can have an arbitrarity long sensitivity list. For example, we could usedalways @(clock or t) $display(t)
to display the value oft
wheneverclock
(either edge) ort
change. This use ofalways
is useful in simulation but cannot be synthesised (i.e. we cannot produce a circuit for it).
module tb_timer( output logic clk, // generated clock output logic rst, // generated reset output [63:0] t // test output ); initial begin $dumpfile("tb_timer_trace.vcd"); // dump signal changes $dumpvars(); // dump all variables in this module clk = 1; // value of clk at simulation step 0 rst = 1; // value of rst at simulation step 0 #20 rst = 0; // wait 20 simulation steps and then lower rst #100 $finish(); // wait 100 simulation steps, then call $finish() to stop end // invert the clock every 5 simulation steps always #5 clk = !clk; // initatiate the design under test (DUT) timer dut(.clk(clk), .rst(rst), .t(t)); // every negative edge of the clock, output the status always @(posedge clk) $display("sim_time=%4d t=%4d", $time, t); endmodule
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Installing a simulator
See the Setup page for access to tools.
Ensure that you have Verilator version 5 or higher by running: verilator --version
Run a simulation
Make a directory to store your simulation, and it in put two files
called timer.sv
(contents copied from the code on the
Tutorial 3 page) and tb_timer.sv
with the test bench code above.
Then execute: verilator --binary --trace tb_timer.sv
This will generate C++ based simulation models of the tb_timer
and will also pull in the timer
module since tb_timer instantiates it. Generated files can be found in the obj_dir/
directory including the executable simulation obj_dir/Vtb_timer
.
Now run the simulation: ./obj_dir/Vtb_timer
The simulation output should be similar to:
sim_time= 0 t= 0 sim_time= 10 t= 0 sim_time= 20 t= 0 sim_time= 30 t= 1 sim_time= 40 t= 2 sim_time= 50 t= 3 sim_time= 60 t= 4 sim_time= 70 t= 5 sim_time= 80 t= 6 sim_time= 90 t= 7 sim_time= 100 t= 8 sim_time= 110 t= 9 - tb_timer.sv:11: Verilog $finish sim_time= 120 t= 10 - S i m u l a t i o n R e p o r t: Verilator 5.036 2025-04-27 - Verilator: $finish at 125ps; walltime 0.000 s; speed 163.399 ns/s - Verilator: cpu 0.001 s on 1 threads; alloced 0 MB
Viewing Waveforms
The test bench also produced a trace file tb_timer_trace.vcd
in Value Change Dump (VCD) format.
We can now use a waveform viewer to display the information in the VCD file. See the Setup tab for waveform viewer installation and how to use them.
In the figure below you'll see the clock (clk
) signal oscillating, the reset signal (rst
) start high and then go low after two clock ticks. The t
output then starts counting up every clock cycle after reset. Click on the image below if you need to see a larger version.
