A Value Change Dump (VCD) file is a plain-text file that contains header information, variable definitions and the value changes of every recorded variable. It is not created automatically: the testbench creates and controls it with a set of VCD system tasks, which decide the file name, which signals are recorded, and during which part of the simulation.

9 min read | Beginner Level

What You'll Learn

  • How to name the VCD file with $dumpfile and select signals with $dumpvars
  • How the level argument of $dumpvars controls how deep into the hierarchy signals are recorded
  • How to pause, resume, checkpoint and limit a dump with $dumpoff, $dumpon, $dumpall and $dumplimit
  • Common mistakes that produce an empty, incomplete or oversized VCD file
TaskPurpose
$dumpfileSets the name of the VCD file
$dumpvarsSelects the variables to record and starts the dump
$dumpoff / $dumponPauses and resumes the dump
$dumpallWrites the current value of every selected variable
$dumplimitSets the maximum size of the VCD file in bytes
$dumpflushWrites buffered data to the file immediately

$dumpfile

$dumpfile specifies the name of the file into which the dump is written. If it is not called, the simulator uses the default name dump.vcd.


$dumpfile(<filename>);

module tb;
  initial begin
    $dumpfile("wave1.vcd");     // Dumps into "wave1.vcd"
    // Without this call, the dump goes into the default file "dump.vcd"
  end
endmodule

$dumpfile must be called before $dumpvars, and only once per simulation: a single simulation writes a single VCD file.

$dumpvars

$dumpvars selects which variables are recorded in the file, and starts the dump. It can be called several times, from different places in the code, to add more signals, but all calls must happen at the same simulation time, before the dump starts.


$dumpvars(levels, [list_of_modules_or_variables]);

Called without arguments, $dumpvars records every variable in the whole design. Otherwise, the first argument is the number of hierarchy levels to record below each module listed in the second argument:

  • 0 means the listed module and all module instances below it, however deep
  • 1 means only the variables of the listed module itself
  • N means the listed module and the instances up to N - 1 levels below it

module tb;
  initial begin
    $dumpvars (0);        // Dumps all variables from all module instances
    $dumpvars (0, tb);    // Dumps all variables within module 'tb' and in all sub-modules
    $dumpvars (1, tb);    // Dumps all variables within module 'tb', not in any sub-modules
    $dumpvars (0, tb.ram_ctrl, tb.alu2.a);  // Dumps all variables in 'tb.ram_ctrl' and in all its sub-modules, and the variable 'tb.alu2.a' in module 'alu2'
  end
endmodule

These four lines are alternatives, shown together for comparison; a real testbench would use the one that fits. For a design where tb contains an instance u_dut, which in turn contains an instance u_fifo, the level argument selects:

Calltbtb.u_duttb.u_dut.u_fifo
$dumpvars(1, tb);YesNoNo
$dumpvars(2, tb);YesYesNo
$dumpvars(0, tb);YesYesYes
$dumpvars(1, tb.u_dut);NoYesNo

The level argument only applies to module instances. When a variable such as tb.alu2.a is listed, exactly that variable is recorded, whatever the level.

The dump does not start at the exact moment $dumpvars is called, but at the end of the current time step. The first values written are therefore the values after all assignments of that time step.

Quick Check

Using the hierarchy from the table above, which call records the variables of u_fifo and nothing else?

Show Answer

$dumpvars(1, tb.u_dut.u_fifo);. The scope is u_fifo itself, and level 1 restricts the dump to that module, without any instances below it.

$dumpon, $dumpoff

Recording every change of every signal makes a simulation slower and the VCD file larger. $dumpoff pauses the dump, and $dumpon resumes it, so that only the interesting part of a long simulation is recorded.


`timescale 1ns/1ns

module tb;
  initial begin
    $dumpvars;

    #100  $dumpoff;     // Stop dump of all vars at 100ns
    #2000 $dumpon;      // Resume dump of all vars at 2100ns (100 + 2000)
  end
endmodule

When $dumpoff is called, every selected variable is written to the file as x, and no further changes are recorded. A waveform viewer then shows the paused interval as unknown, so it cannot be mistaken for a period where nothing changed. When $dumpon is called, the current value of every selected variable is written, and recording continues normally.

$dumpall

$dumpall writes a checkpoint into the file: the current value of every selected variable, whether it has changed or not.


$dumpall;

Normally, a viewer must read the file from the start to know the value of a signal that changed long ago. A checkpoint every so often lets it find all values close to the point you want to look at.

$dumplimit

$dumplimit sets the maximum size of the VCD file in bytes. When the file reaches that size, dumping stops, and a comment is added to the file to show that the limit was reached.


module tb;
  initial begin
    $dumplimit(1048576);      // Dump 1MB limit
  end
endmodule

A related task, $dumpflush, empties the simulator's write buffer into the file immediately. It is useful when you want to open the file in a viewer while the simulation is still running, or before a simulation that might crash.

Synthesis result: None. All VCD tasks are simulation-only and are ignored by synthesis. They are placed in testbenches, never in the design.

A Complete Example

The testbench below records a small counter, pauses the dump for a while, and resumes it:


`timescale 1ns/1ns

module counter (input clk, rstn, output reg [3:0] count);
  always @(posedge clk or negedge rstn)
    if (!rstn) count <= 0;
    else       count <= count + 1;
endmodule

module tb;
  reg        clk  = 0;
  reg        rstn = 0;
  wire [3:0] count;

  counter u_cnt (.clk(clk), .rstn(rstn), .count(count));

  always #5 clk = ~clk;

  initial begin
    $dumpfile ("counter.vcd");
    $dumpvars (0, tb);         // tb and the counter instance

    #12  rstn = 1;
    #50  $dumpoff;             // Pause at 62 ns
    #100 $dumpon;              // Resume at 162 ns
    #30  $finish;              // End at 192 ns
  end
endmodule

Opened in a waveform viewer, counter.vcd shows clk, rstn and count in both tb and tb.u_cnt. The counter is visible counting up from 12 ns to 62 ns. From 62 ns to 162 ns, every signal is shown as x, because the dump was paused. From 162 ns until the end at 192 ns, the waveform continues with the real values, and count has moved on by the number of clock edges that occurred during the pause.

Quick Check

In the complete example, what would change in the VCD file if $dumpvars (0, tb); were replaced by $dumpvars (1, tb);?

Show Answer

Only the variables of tb itself would be recorded: clk, rstn and count as seen in tb. The scope tb.u_cnt would not appear in the file. The waveform would look the same here, because the counter has no internal signals beyond its ports, but in a real design the internal signals would be missing.

Dumping Only Around a Failure

A failing test in a regression may run for hours before the error occurs. Rerunning it with a full dump would take much longer and produce a huge file. Instead, engineers note the failure time from the log and rerun with $dumpoff at the start and $dumpon shortly before the failure, often controlled by a plusarg such as +dump_start=..., so that only the window around the bug is recorded.

Protecting Shared Disks

Regressions run hundreds of tests in parallel, all writing to shared storage. A single test that accidentally dumps a whole chip for its full length can fill the disk and break every other job. Setting a $dumplimit in the common testbench code puts an upper bound on how much any one test can write.

Common Beginner Mistakes

Mistake #1: Calling $dumpfile after $dumpvars

Wrong: $dumpvars(0, tb); $dumpfile("wave.vcd");
Right: $dumpfile("wave.vcd"); $dumpvars(0, tb);

Why? $dumpvars starts the dump, so the file name must already be known. Called afterwards, $dumpfile is ignored or reported as an error, and the dump goes into the default dump.vcd.

Mistake #2: Using level 1 and expecting submodules

Wrong: $dumpvars(1, tb);, then looking for signals inside the DUT
Right: $dumpvars(0, tb);, or list the DUT scope explicitly

Why? Level 1 records only the variables of tb itself. The DUT ports appear through the testbench signals connected to them, but none of the internal signals of the DUT are recorded.

Mistake #3: Using SystemVerilog time literals in Verilog delays

Wrong: #100ns $dumpoff;
Right: #100 $dumpoff; with `timescale 1ns/1ns

Why? Delays with a unit, such as 100ns, are a SystemVerilog feature. In Verilog, a delay is a plain number in the module's time unit, set by `timescale.

Mistake #4: Reading the paused interval as real data

Wrong: Concluding that a signal was unknown between $dumpoff and $dumpon
Right: Treat that interval as "not recorded"

Why? $dumpoff writes x for every variable on purpose, to mark the gap. The design itself had normal values during that time.

Practice Exercise

Challenge: Record Only a Window

A testbench runs for 10 us with `timescale 1ns/1ns. Write an initial block that writes the dump to window.vcd, records everything in tb and below, but only from 4000 ns to 4500 ns, and limits the file to 10 MB.

Hint

$dumpvars starts the dump immediately, so turn it off at time 0 and back on at 4000 ns. Delays add up: the second delay is counted from the end of the first.

Solution

initial begin
  $dumpfile  ("window.vcd");
  $dumplimit (10 * 1024 * 1024);   // 10 MB
  $dumpvars  (0, tb);
  $dumpoff;                        // Nothing recorded from time 0
  #4000 $dumpon;                   // Start recording at 4000 ns
  #500  $dumpoff;                  // Stop again at 4500 ns
end

The file contains the variable definitions, a short section of x values at time 0, the real values from 4000 ns to 4500 ns, and x values again from 4500 ns on. The simulation itself still runs for the full 10 us; only the recording is limited.

Summary

In this tutorial, you learned:

  • $dumpfile names the VCD file, with dump.vcd as the default, and must come before $dumpvars
  • $dumpvars(levels, scopes) selects what is recorded: level 0 means everything below a scope, level 1 only the scope itself
  • The dump starts at the end of the time step in which $dumpvars is called
  • $dumpoff and $dumpon pause and resume recording, with paused intervals shown as x
  • $dumpall writes a checkpoint of all values, $dumplimit caps the file size and $dumpflush writes buffered data
  • All VCD tasks are simulation-only and belong in the testbench
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5