Simulating Verilog the Right Way¶
Simulating verilog in an effective manner can be a challenging task. The verilog language provides a few structures for allowing the HDL designer to describe a small testbench effectively - but is rather inadequate for complex designs. Such shortcomings become extremely painful in large complex design such as verifying and pipelining and Out of Order CPU.
Verilator to the Rescue¶
Verilator allows you to compile your Verilog source into C++ code. Suddenly, anything that you can do with C++/C, you can do with your RTL. For example, if you have RTL that has video output, you can use verilator to display that video output within your windowing system via the X Windowing System for example.
Also, the last time I checked, verilator was the fastest verilog simulator on the market.
Simulating with Verilator¶
Simulating with verilator directly by writing C++ can quickly become tiring for large designs. While C++ is a much better language for describing simulations, describing multi port hardware accesses with C++ syntax is a bit unpleasant. To help combat this, it is possible to use verilator to simulate hardware written in Chisel HDL or Spinal HDL as verilator is integrated as a simulation backend in both Spinal and Chisel HDL.
Building and Running Your Testbench¶
While you can write your testbench in Chisel or Spinal and invoke verilator as a backend(the easier way of doing things), you may have verilog source code you have already written that you wish to test.
Dan Gisselquist has a good tutorial on how to use verilator. Compiling with verilator has changed a little since his tutorial was written, in particular, to build your verilog into C++, you will probably need to do the following:
1 2 3
top is the name of the top module in your verilog source. Verilator will automatically generate a makefile for you too. Invoking this makefile will build an executable that will simulate your design. You can also have verilator spit out a VCD. To build your executable, you do something along the lines of:
Here is a testbench i wrote a while back for verilator. The complete source is not shown below, but just enough to give you an idea of how verilator works.
For this particular testbench, I was simulating a RISCV core that printed its status to a UART device.
Snippet from main.cpp¶
1 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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64