Menu

Verilog $dumpfile and $dumpvars: Producing VCD Waveforms

How to add VCD waveform output to a testbench - $dumpfile, $dumpvars, scope selection, and how to view the resulting file in GTKWave or the browser editor.

This page includes runnable editors - edit, run, and see output instantly.

The Waveform You Actually Want

$display prints text. That's fine for a quick sanity check, but the moment you're debugging a counter with a timing issue or a state machine that's stuck, you want a picture: signals drawn as voltages over time, scrollable, zoomable, with a cursor you can drop on any transition.

That picture is a VCD file - "value change dump", a text format the IEEE standardized in the original Verilog spec. Every modern simulator can write one; every modern waveform viewer can read one. The cost of producing one is two lines in your testbench.

The Two Lines

Inside an initial block - usually the same one that holds your stimulus - add:

$dumpfile("dump.vcd");
$dumpvars(0, test);
  • $dumpfile names the output file. Pass any path; if it has no directory it lands in the simulator's working directory.
  • $dumpvars(0, test) says "record every signal in the test scope and every sub-scope, recursively, with unlimited depth".

That's the whole setup. Run the simulation and you'll have a dump.vcd you can open in GTKWave or the browser editor's Waveform tab.

A Complete Example

Run it. The Waveform tab now shows three signals - clk, reset, count - drawn over the full simulation time. You can drop a cursor on any point and read the signal values at that time. You can drag-zoom to inspect a single clock cycle.

What $dumpvars's First Argument Does

$dumpvars(depth, scope) walks scope and every sub-instance it contains, recording signals up to depth levels deep. The depth values:

  • 0 - unlimited. Every signal in scope and every nested sub-module gets recorded.
  • 1 - only signals directly declared in scope. Sub-modules are not recorded.
  • 2 - scope plus one level of sub-module.
  • N - scope plus N-1 levels of sub-modules.

In practice, $dumpvars(0, test) is what almost every testbench uses. Capturing everything is cheap (VCDs only store transitions, not steady states) and you don't want to discover mid-debug that the signal you need wasn't dumped.

If you have a really large design and the VCD is too big, you can selectively dump:

$dumpvars(0, dut.inner_module);     // just the interesting sub-module
$dumpvars(0, dut.regs);             // just the register file

You can call $dumpvars multiple times to accumulate scopes.

Dumping Specific Signals

$dumpvars can also take a list of specific signals instead of a whole scope:

$dumpvars(0, test.clk, test.reset, dut.count);

This records only those three signals. Useful when the design is enormous and you only care about a handful of signals. For small designs, dumping everything is simpler.

Controlling the Dump Mid-Simulation

Two more tasks pair with $dumpvars:

  • $dumpoff - pause dumping. No further changes go into the VCD.
  • $dumpon - resume dumping.
initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, test);

    // ... interesting region ...

    #1000 $dumpoff;
    // ... long boring region we don't want in the VCD ...
    #5000 $dumpon;

    // ... another interesting region ...
end

That's how you skip past the boring "running for a million cycles" part of a long test without producing a 5GB VCD file.

Viewing the Result

Two main ways:

In the Browser Editor

The editor on this page renders VCDs inline. Run the simulation; switch to the Waveform tab; the signals appear with their hierarchy on the left and a draggable cursor on the right. Click anywhere on a trace to drop the cursor; it shows the signal values at that time as little pills next to each signal name.

In GTKWave

If you ran the simulation locally (iverilog -o sim test.v then vvp sim), open the resulting VCD with:

gtkwave dump.vcd

GTKWave loads the file, presents the scope tree on the left, and waits for you to drag signals into the waveform area on the right. Right-click on a multi-bit signal to change the display format (binary, hex, decimal, analog). Use the search box at the bottom to jump to specific times or signal transitions.

Common Patterns

A Tiny Testbench Helper

Most testbench files start with this exact block. You can keep it short by combining everything in one initial:

initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, test);

    // ... stimulus ...

    $finish;
end

Conditional Dumping

In a test environment where you only want VCD output for failing tests:

initial begin
    if (DUMP_VCD) begin
        $dumpfile("dump.vcd");
        $dumpvars(0, test);
    end
    // ... stimulus ...
end

DUMP_VCD would be a parameter you set from the command line or define depending on the test mode. Saves disk space in regression suites.

Memory Dumps

Memories (unpacked arrays) aren't dumped by $dumpvars by default - they can be enormous. Use $dumpvars(0, dut.memory) explicitly if you want them, or $dumpmem in some simulators.

Common Mistakes

Empty VCD file. You forgot $dumpfile or $dumpvars, or the simulation called $finish before any signal changed. Run for at least a few time units past the setup.

Signals missing from the waveform. The scope you passed didn't include them. $dumpvars(0, dut) records only what's inside dut; if your testbench drives signals at the test level, those won't appear. Always dump from the testbench scope: $dumpvars(0, test).

VCD file is huge. A long simulation with rapidly-changing wide signals produces a lot of VCD lines. Three fixes: dump a narrower scope, use $dumpoff/$dumpon around the boring parts, or switch to a more compact format like FST (which iverilog and GTKWave both support with -fst flags).

What Comes Next

The last doc in this chapter - Timescale and Delays - explains the \timescaledirective and how#delay` actually maps to wall-clock time. After that you've completed the docs end-to-end.

Frequently Asked Questions

What is a VCD file in Verilog?

VCD stands for Value Change Dump - a text format for recording every signal transition during simulation. The simulator writes the initial value of each signal at time 0, then every change with its timestamp. Waveform viewers like GTKWave read the file and render it as a graphical timing diagram you can scroll and zoom.

How do I generate a VCD file in Verilog?

Add two system tasks inside an initial block in your testbench: $dumpfile("dump.vcd"); names the output file, and $dumpvars(0, top_module); records every signal in top_module and below. After simulation finishes, you'll have a dump.vcd file you can open in any waveform viewer.

What does $dumpvars(0, ...) mean in Verilog?

$dumpvars(depth, instance) records signals starting at instance and recursing depth levels deep. $dumpvars(0, test) means 'all signals in the test scope and every sub-scope, recursively' - depth 0 is special and means unlimited. $dumpvars(1, test) would record only signals directly in test, not in any instantiated sub-modules.

Why is my VCD file empty in Verilog?

Three likely causes: you didn't call $dumpfile/$dumpvars at all; the simulation hit $finish before any signals changed (run for at least a few time units past the dump call); or the scope you passed to $dumpvars doesn't match the actual hierarchy. A minimal working sequence is $dumpfile("dump.vcd"); $dumpvars(0, test); #10; $finish;.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED