Skip to content

Latest commit

 

History

History
87 lines (68 loc) · 3.84 KB

0050-2020-08-03.md

File metadata and controls

87 lines (68 loc) · 3.84 KB

3 Aug 2020

Previous journal: Next journal:
0049-2020-08-02.md 0051-2020-08-04.md

Verilator

Let's built event-driven simulation models, in C++, from Verilog, using Verilator!

The goal: Use vgasim to display a simulation of my VGA controller. Optionally see if we can sneak in actual user interaction that generates signals ad-hoc.

This might depend on Linux?

  • vgasim is designed for GTK+.
  • Other screen-based rendering is designed for SDL2.

nand2tetris might also be worth another look.

There is actually another project called "VgaSim" which apparently is an alpha that displays a screen based on a raw text file of signal inputs. Might be good enough for me, for now. Looks like it's available for Windows and maybe Linux? https://sourceforge.net/projects/vgasim/files/1.0.0%20alpha/ - I had a look at the source, and it's pretty primitive, but easy to understand.

I will try installing Verilator for macOS first. There is a Homebrew package for it, apparently:

 brew info verilator
verilator: stable 4.038 (bottled), HEAD
Verilog simulator
https://www.veripool.org/wiki/verilator
Not installed
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/verilator.rb
License: LGPL-3.0
==> Options
--HEAD
    Install HEAD version

4.038 seems to be the latest version at the time of writing, released 2020-07-11.

Doing brew install verilator seemed to work fine and now I have:

$ verilator --version
Verilator 4.038 2020-07-11 rev v4.036-114-g0cd4a57ad

Tutorial time: See Gisselquist Technology's "Taking a New Look at Verilator" article.

There is a very clear example of how to get started – Example C++ Execution – and I followed it:

  1. Create our.v -- the module under test.
  2. Create sim_main.cpp -- test bench, utilising Verilator to drive the simulation.
  3. Run: verilator -Wall --cc our.v --exe --build sim_main.cpp
  4. This seems to have run Clang to produce a bunch of output files in obj_dir. The nature of these files is described here. Main thing is that it creates our executable: obj_dir/Vour
  5. Run obj_dir/Vour:
    $ obj_dir/Vour 
    Hello World
    - our.v:2: Verilog $finish
    
  6. Can build again at any time by doing:
    cd obj_dir; make -f Vour.mk ; cd ..

Things learned

  • Test bench can manipulate/use signals exposed by the module under test. For example, this test bench (testing a module called module, hence Vmodule) toggles the i_clk input signal:
    #include <stdlib.h>
    #include "Vmodule.h"
    #include "verilated.h"
    
    int main(int argc, char **argv) {
        // Initialize Verilators variables
        Verilated::commandArgs(argc, argv);
    
        // Create an instance of our module under test
        Vmodule *tb = new Vmodule;
    
        // Tick the clock until we are done
        while(!Verilated::gotFinish()) {
            tb->i_clk = 1;
            tb->eval();
            tb->i_clk = 0;
            tb->eval();
        } exit(EXIT_SUCCESS);
    }
  • Verilator will stop simulation when it encounters $finish or when you hit CTRL+C.