Exercise - Simulation flow
Overview
Verification is one of the most critical aspects of IC Design. Typical verification flows would compare an implementation of your circuit, either as HDL source code in SystemVerilog or a mapped gate-level netlist in Verilog (which we will cover in a later exercise against a golden-model which represents the correct behavior of the circuit. The verification would take stimuli vectors (that represent inputs), apply them to the circuit under test and collect the corresponding outputs. These will be compared to the expected responses from the golden model, and any discrepancies will be noted in a report.
While developing testbenches is not directly part of this lecture series, we will make use of existing verification setups extensively.
Most of the work will be based on Verilator, a leading open-source tool for hardware simulation. Verilator converts Verilog code into an executable binary. We will use Verilator for RTL simulation exclusively.
Goals of this exercise
- Get practical experience in running the RTL simulation flow using Verilator
- Learn the testbench template we will be using throughout the exercise
- Get familiar with post-layout simulation using back-annotation and understand the additional steps required as well as learn the additional constraints.
- Experience tracing siumulation errors to their sources
- You should be able to re-run existing testbenches for given projects to ensure that any changes to the SoC did not introduce bugs.
In this exercise, we will explore the practical application of Verilator, a leading open-source tool for hardware simulation. Verilator converts Verilog code into an executable binary. Our focus will be on simulating a digital design and testbench written in SystemVerilog using Verilator’s relatively new support for timing constructs. We will learn:
- how to translate a SystemVerilog design into an executable binary using Verilator.
- how to specify signals to track in the wave and how to run a simulation.
- how to debug the simulation results using wave forms.
About the style
We will use a number of different styles to identify different types of actions as shown below:
Student Task
Actions that require you to select a specific menu will be shown like the following: menu → sub-menu → sub-sub-menu
Whenever there is an option or a tab that can be found in the current view/menu we will use a BUTTON to indicate such an option.
Throughout the exercise you will be asked to enter certain commands using the command-line.
sh> command to be entered on the Linux command line
Note: there are many reasons for using a command-line. Some functionality can not not be accessed through GUI commands, and in some cases, using the command-line will be much faster. Most importantly, things you enter on the command-line can be converted into a script and executed repeatedly.
Getting Started
Student Task 1
- Start by copying the example files into your directory by issuing the command
sh > source /home/efcl_004fs24/ex03_simulation/install.sh sh > cd ex03_simulation/croc-soc
Starting from this exercise, we are using a small microcontroller design based around the Ibex RISC-V core (CV32E20). This simpler design still captures most of the complexity of Basilisk while cutting down tool runtime to an acceptable level.
Croc SoC
Croc SoC is designed as a streamlined, efficient microcontroller system based on the RISC-V architecture, utilizing a parameterizable SystemVerilog codebase. Unlike Basilisk, our Linux-capable AXI-4-based systems previously explored, Croc focuses on simplicity and reduced overhead by using the OBI (Open Bus Interface) protocol for on-chip interconnect. This choice of interconnect facilitates easier understanding and modification for educational purposes, while still supporting essential microcontroller functionalities.
The system includes two banks of SRAM, dividing instruction and data memory. This separation enhances performance by allowing simultaneous access to instructions and data, reducing bottlenecks. Croc SoC supports programming and on-chip debugging over a standard JTAG interface, enabled by the RISC-V debug module.
We heavily rely on a source and dependency management tool called Bender. The Croc SoC only consists of three simple RTL files.
croc_pkg.sv
: contains the parameters and definitions of the SoCcroc_soc.sv
: wraps our parameteric SentryCore system frameworkcroc_chip.sv
: defines the chip-level design including the ASIC pads.
As you can see, the bulk of the code is currently not present and needs to be fetched using Bender.
Student Task 2
- Prepare the RTL code by typing:
sh > make hw-all
- Have a look at the checked-out project, try to identify the instantiation of the SRAM banks. How many words does each SRAM hold? Hint: most of the source code is stored in
.bender/git/
checkouts.
- Identify the instance path and name of the
bootrom
used in Croc.
Bender can be used to create a file-list (flist) defining all the projects RTL files and their corresponding include directories and defines.
Student Task 3
- Create the
croc.f
flist file required by Verilator in a later stage by calling:
sh > make sim-all
Verilog Compilation
Simulating a design with Verilator happens in three stages: the design is first translated to either SystemC or C++, it is then compiled to an executable binary on the host PC, and finally the binary is run.
Student Task 4
- Verilate and compile the testbench and the Croc SoC to a binary by running:
sh > make sim-all sh > verilator-5.020 verilator -f croc.f --top tb_croc_soc -Wno-fatal --binary --timing --autoflush
- While the design is being translated, have a look at the testbench located in
test/tb_croc_soc.sv
. To understand the testbench, consider the`ifndef VERILATOR
blocks and ignore the‘else
block. What is the testbench doing?
- Now have a look at the
‘else
block. Verilator unfortunately does not understand our JTAG driver yet. For this exercise today, we have run the testbench using a commercial simulator and dumped the required JTGA stimuli and expected responses in a file. Verilator only applies these stimuli and checks the responses.
Running a Simulation and Selecting Signals of Interest
Student Task 5
- Run the simulation now by typing:
sh > ./obj_dir/Vtb_croc_soc
- What does the simulation output?
- Change a few values in the
jtag_test.svh
file after line 17 and rerun the simulation. Does the output change?
- Change the values back to their original state for the next part of the simulation to work.
Without specifying anything else, Verilator only prints calls to stdout present in the RTL. This is great to get a pass/fail result from the simulation, but it is not sufficient to judge how or why a test is failing.
If we want to understand why a circuit is misbehaving, we need to look at the waves (how the signals in our design behave over time).
Student Task 6
- We now have to enable tracing support in our Verilator model by adding the following arguments to the Verilator call.
--trace --trace-structs
- Uncomment the tracing-related code in the testbench. This code specifies the trace file location, the module or signals to trace, and ensures the file is properly written at the end of the simulation.
- Rerun the simulation. A file called
croc.vcd
should have appeared. How large is the file? Have a look at it’s content, can you understand how the information is stored?
Simulation traces can be stored in human-readable value change dump (VCD) files. These files store the initial state of every simulation value traced and the time and state of their changes. Long simulations of large designs can lead to very large VCD files (order of 100 GiB).
Verilator has multiple options to trade off VCD file space and simulation visibility. The -trace-depth 1
option for example can be reduced to limit the tracing to the top-level signals.
GTKWave
GTKWave is a hand tool to visualize many trace files, among them VCD files. We use it now to explore the simulation trace of the Croc SoC.
Student Task 6
- Open the VCD file using GTKWave
sh > gtkwave croc.vcd
- Locate the instance of the bootrom and add its signals to the wave view.
- At which time is the bootrom accessed?
- Which address is being read? Which value is returned?
You are done with this Exercise.
Discuss your experience with assistants and collegues or continue to explore Verilator and the provided design on your own.
The VLSI pages are part of the open source VLSI design course offered by the Integrated Systems Laboratory of ETH Zürich, by Luca Benini and Frank K. Gürkaynak. See full list of contributors.