Skip to content

Verilog with Icarus

This tutorial shows how to generate waveforms from Verilog using Icarus Verilog and view them in NovyWave.

Ubuntu/Debian:

Terminal window
sudo apt-get install iverilog

macOS:

Terminal window
brew install icarus-verilog

Windows: Download from Icarus Verilog website

Create counter.v — an 8-bit counter with enable and overflow detection:

module counter (
input wire clk,
input wire reset,
input wire enable,
output reg [7:0] count,
output reg overflow
);
always @(posedge clk or posedge reset) begin
if (reset) begin
count <= 8'b0;
overflow <= 1'b0;
end else if (enable) begin
if (count == 8'hFF) begin
count <= 8'b0;
overflow <= 1'b1;
end else begin
count <= count + 1'b1;
overflow <= 1'b0;
end
end
end
endmodule

Create counter_tb.v:

`timescale 1ns/1ps
module counter_tb;
parameter CLK_PERIOD = 10;
reg clk;
reg reset;
reg enable;
wire [7:0] count;
wire overflow;
counter uut (
.clk(clk),
.reset(reset),
.enable(enable),
.count(count),
.overflow(overflow)
);
// Clock generation
initial begin
clk = 0;
forever #(CLK_PERIOD/2) clk = ~clk;
end
// VCD dump for waveform viewing
initial begin
$dumpfile("counter.vcd");
$dumpvars(0, counter_tb);
end
// Stimulus
initial begin
// Initial reset
reset = 1;
enable = 0;
#50;
// Release reset, enable counting
reset = 0;
enable = 1;
#300;
// Disable counting briefly
enable = 0;
#50;
// Resume counting
enable = 1;
#200;
// Apply reset while counting
reset = 1;
#30;
reset = 0;
#200;
// Continue until overflow
#3000;
$finish;
end
endmodule
Terminal window
# Compile the design
iverilog -o counter_sim counter.v counter_tb.v
# Run simulation
vvp counter_sim

This creates counter.vcd with all signal transitions.

  1. Open NovyWave
  2. Click Load Files
  3. Select counter.vcd
  4. Click Load

The file appears in Files & Scopes:

counter.vcd (0-3830ns)
└── counter_tb
└── uut
  1. Click the checkbox next to counter_tb
  2. In the Variables panel, click clk, reset, enable, count, and overflow
  3. Press R for full view
  4. Zoom in with W to see the reset release at 50ns
  5. Use Shift+E to jump between counter transitions
  6. Change count format to UInt to see decimal values
initial begin
$dumpfile("output.vcd");
$dumpvars(0, testbench_name); // Dump all signals
end
initial begin
$dumpfile("output.vcd");
$dumpvars(1, testbench_name); // Only top level
$dumpvars(0, testbench_name.dut); // All signals in dut
end
initial begin
$dumpfile("output.vcd");
$dumpvars(0, testbench_name);
#1000;
$dumpoff; // Stop dumping
#500;
$dumpon; // Resume dumping
end

For better performance with large designs, use Verilator with FST output:

#include "verilated_fst_c.h"
int main() {
Verilated::traceEverOn(true);
VerilatedFstC* tfp = new VerilatedFstC;
top->trace(tfp, 99);
tfp->open("output.fst");
// ... simulation loop ...
tfp->close();
}

FST files are 10-100x smaller and faster to load in NovyWave.

Ensure $dumpfile and $dumpvars are called before signals change. Check that the simulation runs to completion (look for $finish).

Verify the module hierarchy in the $dumpvars call. Use depth 0 to dump all signals: $dumpvars(0, top_module).

Use selective dumping with $dumpvars(0, specific_module), use $dumpoff/$dumpon to skip uninteresting periods, or consider FST format with Verilator.