Loading header...

Verilog Simulation: Verilator, Icarus Verilog, and GTKWave

Open-source Verilog simulation usually starts with three tools: Icarus Verilog for lightweight event-driven simulation, Verilator for fast linting and compiled simulation, and GTKWave for waveform inspection. Each tool answers a different question.

Learning Objectives

By the end of this lesson, you should be able to:

  • choose Icarus Verilog or Verilator for a beginner simulation task;
  • compile and run a small testbench from the command line;
  • generate a VCD waveform and open it in GTKWave;
  • use simulator warnings as design feedback;
  • explain why simulation complements, but does not replace, synthesis and timing analysis.

Tool Roles

  • Icarus Verilog: simple Verilog/SystemVerilog event simulation; friendly for classic HDL testbenches.
  • Verilator: fast linting and compiled simulation; very strong warnings and best with synthesizable-style SystemVerilog.
  • GTKWave: VCD/FST waveform viewing; useful for debugging but not a pass/fail method.

Use Icarus when you want the shortest path from top.v and top_tb.v to a runnable simulation. Use Verilator when you want stronger linting, speed, and CI-friendly checks.

Icarus Verilog Flow

Given:

rtl/counter4.v
tb/counter4_tb.v

Compile and run:

iverilog -g2012 -Wall -o build/counter4_tb.vvp rtl/counter4.v tb/counter4_tb.v
vvp build/counter4_tb.vvp

-g2012 enables SystemVerilog-era syntax support. -Wall enables useful warnings. The output file is a simulation program run by vvp.

VCD Waveform Dump

Add this block to the testbench:

initial begin
    $dumpfile("build/counter4.vcd");
    $dumpvars(0, counter4_tb);
end

Then run:

gtkwave build/counter4.vcd

Add only the important signals first: clock, reset, input controls, state, outputs, and any failing internal register. Too many signals can hide the timing relationship you need.

Verilator Flow

For a SystemVerilog testbench that Verilator can compile directly:

verilator --binary -j 0 -Wall --trace rtl/counter4.sv tb/counter4_tb.sv
./obj_dir/Vcounter4_tb

Typical meanings:

Option Meaning
--binary Build a runnable simulator executable
-j 0 Use available CPU threads
-Wall Enable broad warnings
--trace Enable waveform tracing when the testbench requests it

Verilator is strict. Treat warnings about width, latch inference, unused signals, incomplete cases, and blocking/nonblocking style as review comments.

Minimal Self-Checking Testbench

`timescale 1ns/1ps

module counter4_tb;
    reg clk = 0;
    reg rst = 1;
    reg en  = 0;
    wire [3:0] count;

    counter4 dut (
        .clk(clk),
        .rst(rst),
        .en(en),
        .count(count)
    );

    always #5 clk = ~clk;

    initial begin
        $dumpfile("build/counter4.vcd");
        $dumpvars(0, counter4_tb);

        repeat (2) @(posedge clk);
        rst <= 0;
        en  <= 1;

        repeat (3) @(posedge clk);
        #1;
        if (count !== 4'd3) begin
            $display("FAIL: count expected 3, got %0d", count);
            $finish;
        end

        en <= 0;
        repeat (2) @(posedge clk);
        #1;
        if (count !== 4'd3) begin
            $display("FAIL: enable hold expected 3, got %0d", count);
            $finish;
        end

        $display("PASS: counter4");
        $finish;
    end
endmodule

Use four-state comparisons such as !== in testbenches when you want X or Z to fail the test instead of silently matching.

Simulation Timing Sketch

title "Verilog counter simulation"
time start=0 end=70 unit=ns divisions=7

CLK: square label="clk" low=0 high=1 duty=50 cycles=7 unit=logic color=#2563eb
RST: pulse label="rst" low=0 high=1 at=0 width=20 unit=logic color=#dc2626
EN: pulse label="en" low=0 high=1 at=22 width=30 unit=logic color=#7c3aed
COUNT: sawtooth label="count when enabled" min=0 max=3 cycles=1 unit=count color=#16a34a

marker RELEASE at=20 label="reset off"
marker HOLD at=52 label="en low"

This waveform is explanatory. The actual VCD is the authority for your simulation.

Worked Example: Choosing A Tool

For a first counter testbench, Icarus is often enough:

iverilog -g2012 -Wall -o build/counter4_tb.vvp rtl/counter4.v tb/counter4_tb.v
vvp build/counter4_tb.vvp

For a CI check that should reject questionable RTL style, add Verilator:

verilator --lint-only -Wall rtl/counter4.v

That pairing is useful: Icarus proves the testbench behavior, while Verilator highlights synthesizable coding issues before they become toolchain surprises.

Practical Checks

Before trusting a simulation:

  • the command starts from a clean build directory;
  • the intended top testbench is selected;
  • the testbench prints PASS only after all checks run;
  • failures return a nonzero status in scripts;
  • warnings are reviewed, not ignored;
  • the waveform file timestamp matches the latest run;
  • synthesis and timing are still run after simulation.

Common Mistakes

  • Compiling files in the wrong order when modules are generated or included.
  • Forgetting $finish, leaving automation stuck.
  • Checking only that a VCD exists.
  • Ignoring width warnings that later change synthesis behavior.
  • Driving inputs on the same active edge where the DUT samples them.
  • Assuming Verilator and Icarus support identical language subsets and timing semantics.

Summary

Icarus Verilog is a simple event-driven simulator, Verilator is a fast and strict compiled simulator/linter, and GTKWave helps inspect timing after a failure. A solid beginner flow uses simulator checks for pass/fail, waveforms for debugging, and synthesis plus timing analysis for hardware readiness.

Next: GHDL and VHDL Simulation.

Further Reading

Mind Map

mindmap root((Verilog Simulation)) Core run HDL before board checks decide pass waves explain failures warnings matter Icarus iverilog compile vvp run event simulation beginner friendly Verilator lint only binary sim fast compiled model strict warnings GTKWave open VCD inspect clk rst en narrow window debug not proof Checks PASS after assertions nonzero failure fresh VCD synthesis later Mistakes no finish wrong top width ignored waveform only