Aller au contenu principal

Verilog Simulation on Linux with VS Code, Icarus Verilog & GTKWave

A practical guide to writing, compiling, and simulating Verilog HDL on Linux using free, lightweight tools — no expensive EDA software required.


Table of Contents


Prerequisites

  • A Linux system (Ubuntu/Debian, Fedora, Arch, etc.)
  • VS Code installed (download here)
  • Basic familiarity with the terminal

Installation

Install Icarus Verilog (the compiler/simulator) and GTKWave (the waveform viewer) via your package manager.

Ubuntu / Debian:

sudo apt update
sudo apt install iverilog gtkwave

Fedora:

sudo dnf install iverilog gtkwave

Arch Linux:

sudo pacman -S iverilog gtkwave

Verify the installation:

iverilog -v
gtkwave --version

Setting Up VS Code

Install the following extensions for a proper HDL editing experience:

1. Verilog-HDL/SystemVerilog (syntax highlighting + linting)

Open the Extensions panel (Ctrl+Shift+X) and search for:

  • Verilog-HDL/SystemVerilog/Bluespec SystemVerilog by mshr-h

2. (Optional) TerosHDL

A more full-featured HDL extension with documentation generation and tool integration. Search for TerosHDL in the Extensions panel.

Configure Linting (optional)

To enable real-time linting with iverilog, add this to your VS Code settings.json (Ctrl+Shift+POpen User Settings JSON):

{
"verilog.linting.linter": "iverilog",
"verilog.linting.iverilog.arguments": "-Wall"
}

Project Structure

A clean project layout to follow:

my_project/
├── src/
│ └── my_module.v # Your design files
├── tb/
│ └── tb_my_module.v # Your testbenches
├── sim/
│ └── wave.vcd # Generated waveform files (auto-created)
└── .vscode/
└── tasks.json # Build/run tasks

Writing Your First Module

Create src/my_module.v. Here's a simple 4-bit counter as an example:

// src/my_module.v
module counter (
input wire clk,
input wire rst,
output reg [3:0] count
);

always @(posedge clk or posedge rst) begin
if (rst)
count <= 4'b0000;
else
count <= count + 1;
end

endmodule

Writing a Testbench

Create tb/tb_my_module.v. The testbench instantiates your module, drives inputs, and dumps signals to a .vcd waveform file.

// tb/tb_my_module.v
`timescale 1ns / 1ps

module tb_counter;

// Inputs (driven by testbench)
reg clk;
reg rst;

// Outputs (observed from DUT)
wire [3:0] count;

// Instantiate the Device Under Test (DUT)
counter uut (
.clk (clk),
.rst (rst),
.count (count)
);

// Clock generator: toggle every 5ns → 100MHz clock
initial clk = 0;
always #5 clk = ~clk;

// Stimulus
initial begin
// Set up waveform dumping
$dumpfile("sim/wave.vcd");
$dumpvars(0, tb_counter);

// Apply reset
rst = 1;
#20;
rst = 0;

// Run for 200ns then stop
#200;
$display("Simulation complete.");
$finish;
end

// Monitor output in terminal
initial begin
$monitor("Time=%0t | rst=%b | count=%d", $time, rst, count);
end

endmodule

Key points:

  • $dumpfile and $dumpvars enable waveform recording — always include these.
  • $monitor prints signal changes to the terminal automatically.
  • $finish stops the simulation cleanly.

Compiling and Running the Simulation

Step 1 — Create the sim output directory

mkdir -p sim

Step 2 — Compile with iverilog

iverilog -o sim/counter_sim src/my_module.v tb/tb_my_module.v
FlagMeaning
-o sim/counter_simOutput executable name
src/my_module.vDesign source file(s)
tb/tb_my_module.vTestbench file

You can add -Wall for warnings:

iverilog -Wall -o sim/counter_sim src/my_module.v tb/tb_my_module.v

Step 3 — Run the simulation

vvp sim/counter_sim

Expected terminal output:

Time=0 | rst=1 | count=0
Time=20000 | rst=0 | count=0
Time=25000 | rst=0 | count=1
Time=35000 | rst=0 | count=2
...
Simulation complete.

The file sim/wave.vcd is now generated and ready for viewing.


Viewing Waveforms in GTKWave

Launch GTKWave with your waveform file:

gtkwave sim/wave.vcd &

Adding signals to the viewer

  1. In the SST (Signal Search Tree) panel on the left, expand tb_counter.
  2. Select the signals you want (e.g., clk, rst, count).
  3. Click Append to add them to the wave view.
  4. Press Ctrl+Shift+F or click the zoom-to-fit button to see the full waveform.

Saving your signal layout

Go to File → Write Save File to save your GTKWave layout as a .gtkw file. Next time, open it directly:

gtkwave sim/wave.vcd sim/layout.gtkw &

Automating with VS Code Tasks

Instead of typing compile/run commands every time, wire them up as VS Code tasks.

Create .vscode/tasks.json:

{
"version": "2.0.0",
"tasks": [
{
"label": "Compile Verilog",
"type": "shell",
"command": "iverilog -Wall -o sim/counter_sim src/my_module.v tb/tb_my_module.v",
"group": "build",
"problemMatcher": []
},
{
"label": "Run Simulation",
"type": "shell",
"command": "vvp sim/counter_sim",
"group": "test",
"dependsOn": "Compile Verilog",
"problemMatcher": []
},
{
"label": "Open GTKWave",
"type": "shell",
"command": "gtkwave sim/wave.vcd &",
"group": "test",
"problemMatcher": []
},
{
"label": "Build and Simulate",
"dependsOn": ["Compile Verilog", "Run Simulation"],
"dependsOrder": "sequence",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": []
}
]
}

Running tasks:

  • Ctrl+Shift+B — runs the default build task (Build and Simulate)
  • Ctrl+Shift+PTasks: Run Task — pick any task from the list

Tips and Common Errors

Common Errors

unknown module type You forgot to include a source file in the iverilog command. Make sure all .v files are listed.

warning: macro ... undefined Add `timescale 1ns/1ps at the top of your testbench.

sim/wave.vcd not created Make sure the sim/ directory exists before running (mkdir -p sim), and that $dumpfile path matches.

GTKWave shows no signals You need to add signals manually via the SST panel — they don't appear automatically.


Useful iverilog Flags

FlagDescription
-WallEnable all warnings
-g2012Use SystemVerilog 2012 standard
-I <dir>Add an include directory
-D <macro>Define a preprocessor macro

Workflow Summary

Write .v files in VS Code

iverilog → compiles to executable

vvp → runs simulation, prints $monitor output, writes .vcd

gtkwave → visualize waveforms

Going Further

  • Verilator — compiles Verilog to C++ for much faster simulation of large designs
  • Yosys — open-source synthesis tool, pairs well with iverilog for a full open-source RTL flow
  • SymbiYosys — formal verification on top of Yosys
  • OpenLane — full open-source ASIC flow if you want to go all the way to layout