Getting Started

A Basic Verilog testbench

Before introducing Verilator let`s first describe a simple testbench with Verilog.

In a new file src/hello_tb.v enter the following:

module hello_tb;

  reg clk;

  parameter N_CYCLES = 20;
  parameter PULSE_WIDTH = 5;
  integer j;

  initial begin
   clk <= 0;
   for (j=0; j<N_CYCLES; j = j + 1)
      #PULSE_WIDTH clk <= ~clk;
  end

  always @(posedge clk) begin
    $display("tick");
  end

endmodule

This module only drives a clock signal which can be used to test a digital system. You can compile and run this module with iverilog for example:

You should see the following output:

The system under test is very simple as our main focus at this stage is to study how parts of this setup can be written with C++.

Building Systems with Verilator

The example above uses the square symbol (#) to implement pulses. Verilog code that shall be translated to C++ (or "verilated" code) would not be able to process these delays in Verilog. Therefore let's remove the clock generator from Verilog. It will be addressed later in C++.

To make the system under test a bit more interesting, we can add a counting action: To track the variables with digital waveforms, the Verilog dumpfile and dumpvar tasks are inserted. The resulting module is:

The next step is to setup the C++ code that drives this device under test (or DUT).

In Verilator, clocks can be generated with C++ or with SystemC. One possiblity to drive the module is as follows:

To compile with SystemC and C++, we can use CMake with this CMakeLists.txt build definition:

Now compile all with:

You should be able to run the example and see:

Besides the console output of clock ticks, you should have a waveform file which can be loaded with gitkwave:

You should be able to see 20 clock cycles and the resulting count value.

A counter varation

We can make the system under test a bit more interesting. First instead of having all structures defined in one module (which is unlikely in a real project), you can add a top module as follows:

You see already that we added a new signal to control the module reset. Also the top module can be a good place to define conditiions on when to finish the simulation.

This reset could be driven from the testbench as follows

Last updated

Was this helpful?