Simulation Software

Just for Windows Users

Just for MacOS Users

Software for All

  • Python3
    • WSL/Linux: sudo apt install python3
    • MacOS: brew install python3
  • Pip3
    • WSL/Linux: sudo apt install python3-pip
    • MacOS: brew install python3-pip
    • pip3 install --upgrade --user fusesoc
    • You might have to add pip’s local packages to path. "~/.local/bin"
    • WSL/Linux:
      • Download Icarus for Linux
      • Extract the "iverilog" folder to "~/Utils/iverilog". (Open \\wsl$ in Explorer.)
      • Add "~/Utils/iverilog/bin" to path. (Add export PATH=$PATH:~/Utils/iverilog/bin to the file "~/.bashrc".)
      • Run chmod +x ~/Utils/iverilog/bin/* ~/Utils/iverilog/lib/ivl/* to make iverilog runnable.
    • MacOS: brew install icarus-verilog
    • Ensure you have installed version ≥11.0 with iverilog -v
    • WSL/Linux: sudo apt install gtkwave
    • MacOS:
      • Run the following commands
        • brew tap homebrew/cask
        • brew install gtkwave --cask
        • sudo cpan install Switch
        • perl -V:'installsitelib'
      • If the previous command prints something like "/usr/local/Cellar/perl/...", then Switch must be coppied to the correct location in "/Library/Perl/5.*/" with sudo cp /usr/local/Cellar/perl/5.*/lib/perl5/site_perl/5.*/ /Library/Perl/5.*/
      • You should now be able to run /Applications/
      • Add "/Applications/" to path.

Download this Verilog project template, and run make view to ensure everything was installed correctly. It should simulate the Verilog and open the waves in GTKWave.



Verilog is a hardware description language (HDL). Just as markup languages such as HTML and Markdown are not programming languages, HDLs are not programming languages. HDLs describe register-transfer level (RTL) circuits that can be either simulated or synthesized. In this class, we will be writing RTL in Verilog; we will be simulating the design in Icarus Verilog and synthesizing the design with Yosys.

There are lots of “good” Verilog resources already available. Skim this if you have any questions on syntax: Verilog In One Day. If you want to see the circuit that will be generated by Verilog, use DigitalJS Online.

Note, we will actually be using SystemVerilog for this project. SystemVerilog gives you extra functionality that Verilog does not. (SystemVerilog is to Verilog as C++ is to C.) You can still refer to vanilla Verilog guides because everything will carry to SystemVerilog. However, not all tools support all SystemVerilog features, so make sure a feature is supported before using it. To use SystemVerilog, make sure your filename extensions are “.sv”.

Combinational Logic

To implement combinational logic in Verilog, you must use assign or always_comb.

Notice that you can use C-like functionality such as integer arithmetic, for loops, if-else statements, and more.

However, Icarus Verilog will often mistakenly simulate unsynthesizable Verilog. This class will try to only cover best practices for writing Verilog, but Icarus is so forgiving that you may accidentally write something that works in simulation, but not in synthesis. For example, every modified value in an always_comb block must have a default value; if it does not, Yosys will infer a latch, which is unsupported. If you are ever unsure about what you wrote, test it with DigitalJS Online.

Flip Flops

To implement flip flops in Verilog, you must use always_ff @ (posedge clk) or always_ff @ (negedge clk). For best practice, you should add a reset to every register. Non-blocking assignment <= must be used to signify that all assignments happen as soon as a clock pulse occurs. There should be no combinational logic inside an always_ff block, otherwise synthesis tools will have trouble deciphering what logic should be treated as a clock or reset.

Verilog Testbench

To test a design, you need to simulate a test for it. You do this by creating a testbench. A testbench should have:

  1. A testbench module with no inputs
  2. An instantiation of the module you are testing
  3. An initial block with $finish; at the end.
  4. An dump file of all the nets by doing $dumpfile("dump.fst"); $dumpvars;
  5. Changes in the inputs and checks on the outputs, separated by a delay statement: #1.

For example, in the following code, the resulting outputs of the full adder are verified for all 8 possible inputs.

You can also open the dump file in GTKWave, which will display all the nets at every point in time. To run this on the Verilog template, do make view.