You need to sign in and enrol to submit exercises.
Simple testbenches
Objectives
This exercise will introduce basic concepts of SystemVerilog as design language:
Using a simple testbench for simulation
Instructions
Simple testbenches
The purpose of a simple testbench is to aid in simulation by generating test input, not necessarily automated testing.
The testbench creates a clock signal, generates reset and feeds some input into the DUT - it does the same thing that the .do file in the previous example, but is more useful and easier to maintain.
An initial procedure is often used for input generation
The procedure runs a sequence of input values and stops the simulation when done
Delays are not always synthesizable in SystemVerilog, but they are very useful in input generation
Delays can be declared with @, # or ##
@ should be familiar by now - It waits for a condition to be true
@ posedge(clk) // Wait for the rising edge of signal clk
# specifies a delay in time units, usually defaulting to nanoseconds if timescale is not specified
always #5 clk =! clk; // Generates a clock with 10ns cycle
## specifies a delay in clock cycles.
This requires that the model has a clock signal specified as its input so it doesn't work in testbenches that generate the clock!
##2 data_in = 0'hFF; // After 2 cycles set data_in to 0xFF
The DUT can be instantiated in the testbench with the syntax:
When the signal names in testbench and DUT match, all you need is to declare:
module_name instance_name (.*);
for example:
adder_synch DUT (.*);
Can you see some dangers in doing it like this?
When your synchronous adder design is ready and compiles successfully, it's time to simulate it. To support simulation, create a simple testbench that feeds some input to the module.
Create a new file and declare a new module adder_synch_tb. This module should not have any input or output ports.
Declare the data_width_g parameter as localparam, as the parameter is internal to the testbench
Add the signals to be fed to the DUT as variables of type logic
Generate the clock in an always procedure and add initial procedures for reset and input generation
Add a sequence of input values by utilizing delays
Tip: you may use repeat(n) loop and randomize the signals with $urandom
When the input sequence is finished, stop the simulation with
$finish;
Connect your adder to the testbench
After writing your testbench, run the simulation
Compile as usual and simulate the design with:
$ vsim -voptargs=+acc adder_synch_tb
Remember to compile both your design and the testbench with vlog
Add the signals to the waveform window and run the simulation
When asked if you really want to finish, answer no. Answering yes will quit the simulator
You may automate the start of the simulation and adding waves by making a .do file
The -voptargs=+acc switch turns optimization off, so the signals won't be optimized away from the wave window
(Helpful?) Tips / good practices / conventions
Between sessions you lose the "sourced" paths so if you get an error that the run script cannot find the compiler/simulator run the sourcing script as before
Always comment what you're doing in the code! Commenting in SystemVerilog works as in C/C++ i.e. // or /* ... */
Remember to indent the code and use descriptive variable/class names (as in the given code package or some other sensible way..), readibility is nice.
SystemVerilog resources:
SystemVerilog standard: doc/IEEE-1800-2012.pdf
Exercise returns
Commit your changes to Git and insert your SSH clone url here. Your repository should at least contain files: