In short: Icarus Verilog compiles your RTL and testbench with iverilog, runs the result with vvp, and dumps a VCD file you open in GTKWave; internally it is an event-driven simulator that follows the same scheduling regions (active, inactive, non-blocking update) that Synopsys VCS, Cadence Xcelium and Siemens Questa implement.
Why Icarus Verilog is worth learning
Icarus Verilog (iverilog) is a free, open-source compiler and simulator that supports most of IEEE 1364-2005 and a growing slice of SystemVerilog (IEEE 1800). It costs nothing, installs in a minute on Linux, macOS or Windows, and runs in CI containers with no licence server. For FPGA learners that matters: you can validate a design before ever opening a vendor tool. If you are new to the platform itself, start with what an FPGA is, then come back here.
Key fact: Icarus is a simulator, not a synthesiser. A design that simulates cleanly can still fail synthesis, and the reverse is also true, so treat it as the first gate, not the last.
The three-step flow: compile, run, view
Unlike GUI simulators that hide the steps, Icarus exposes them. iverilog parses and elaborates the sources and writes a vvp assembly file. vvp is the runtime that executes it. Your testbench decides what is recorded, using $dumpfile and $dumpvars. GTKWave then reads the dump.
A minimal counter testbench shows the whole loop:
`timescale 1ns/1ps
module tb;
reg clk = 0, rst = 1;
wire [3:0] q;
counter dut(.clk(clk), .rst(rst), .q(q));
always #5 clk = ~clk; // 100 MHz
initial begin
$dumpfile("wave.vcd");
$dumpvars(0, tb);
#22 rst = 0;
#100 $finish;
end
endmodule
iverilog -g2012 -Wall -o sim.vvp tb.v counter.v
vvp sim.vvp
gtkwave wave.vcd
Always pass -Wall: it flags implicit nets and port-width mismatches that otherwise silently produce x values. The -g2012 flag enables SystemVerilog syntax. Note the timescale directive: without it, delays are in default units and your 10 ns clock may display as 10 s of nothing useful. Also revisit reg versus wire if the compiler complains about driving a net from a procedural block.
Key fact: $dumpvars(0, tb) dumps every signal below tb. Level 0 means unlimited depth; on a large SoC that file can reach gigabytes, so dump selectively, or use vvp sim.vvp -fst for the compact FST format.
How Icarus maps to the standard event model
Verilog simulation is discrete-event: the kernel keeps a queue of time slots, and in each slot it works through ordered regions until no events remain, then advances time. This is defined in the language standard, which is why the same RTL gives the same cycle-level behaviour on Icarus, VCS, Xcelium and Questa.
Icarus implements this as follows. Each always and initial block becomes a thread in vvp. A thread runs until it hits a delay or an event wait, then sleeps on the scheduler. A blocking assignment updates its target immediately within the thread. A non-blocking assignment queues an update that vvp applies only after the active and inactive queues drain, which is exactly the NBA region. That is why a flop written as q <= q + 1 reads the old value of q in every other block triggered by the same clock edge. The full reasoning is in blocking versus non-blocking assignments.
The bigger SystemVerilog scheduler has extra regions (observed, reactive, re-NBA, postponed) for assertions and program blocks. Icarus supports only a subset of these, so assertion-heavy, UVM-style verification still belongs on a commercial tool.
Watch it happen: a counter ticking
Reading waveforms like an engineer
In GTKWave, drag signals from the hierarchy tree into the signal pane, set the radix to hex or decimal, and use the marker to measure edge-to-edge time. Three habits save hours:
- Look for X first. Red or labelled
xafter reset means an uninitialised register or an undriven input. Count how many cycles reset is held. - Check the clock period. With
#5 clk = ~clkand a 1 ns / 1 ps timescale you get a 10 ns period. Measuring it confirms the timescale took effect. - Save a .gtkw file so signal selection and radix survive each re-run.
| Tool | Type | Typical use |
|---|---|---|
| Icarus Verilog | Event-driven, open source | Learning, small blocks, CI regressions |
| Verilator | Cycle-based, compiles to C++ | Fast RTL models, 2-state only |
| VCS / Xcelium / Questa | Event-driven, commercial | Full SystemVerilog, UVM, gate-level with SDF |
Common pitfalls and how to avoid them
- Race at time zero. If two initial blocks both touch a signal at t=0, order is undefined. Drive testbench inputs away from the clock edge, for example on the falling edge.
- No $finish. A free-running clock keeps the queue non-empty forever, so vvp never exits.
- Wrong top module. With several uncalled modules, name the root:
iverilog -s tb. - Bit-width surprises. Mixed widths are padded or truncated quietly; see sign extension in Verilog for the signed case.
- Gate-level limits. Icarus can read SDF annotation only in a limited way, so post-layout timing sign-off should use a commercial simulator alongside PrimeTime or Tempus.
Key fact: If a result differs between Icarus and VCS, suspect a race in your code first. A correct, race-free design behaves identically on both.
Want guided practice on flows like this? ChipXpert's VLSI training programs pair simulation labs with real tool flows.
Ready to go from first simulation to a working FPGA design? Explore the hands-on CourseTron courses and build testbenches with mentor feedback.
FAQ
Does Icarus Verilog support SystemVerilog?
Partly. With -g2012 it handles many synthesizable constructs, logic types, interfaces in basic form and some assertions, but not full UVM or constrained-random classes.
Why is my VCD file empty?
Usually $dumpvars runs after the signals stop changing, or the dump call sits in a module that is not the root. Place it in an initial block at time zero in the top-level testbench.
Can I use GTKWave with FST instead of VCD?
Yes. Run vvp sim.vvp -fst; GTKWave opens the smaller, faster FST file directly.
Is Icarus accurate enough for FPGA work?
For functional RTL verification, yes. Timing closure is a separate job done in the vendor tools; see the Xilinx versus Intel FPGA comparison for those flows.