A Value Change Dump (VCD) file is a plain-text (ASCII) file that records how the values of selected signals change during a simulation. The format is defined in the Verilog standard, IEEE 1364, so every Verilog simulator can write it and every waveform viewer can read it. Its main purpose is to let you look at, and analyze, how variables changed over time after the simulation has finished.

The simulator writes a VCD file while it runs, adding an entry every time a recorded signal changes value. A waveform viewer then reads the file and draws each signal as a trace over time, which is how most simulation debugging is done.

9 min read | Beginner Level

What You'll Learn

  • The two types of VCD files and what each one records
  • The three sections of a VCD file: header, variable definitions and value changes
  • How to read scalar, vector and real value changes in a VCD file
  • Common mistakes that produce empty, huge or misleading VCD files

VCD Types

A VCD file only contains the variables that were selected with the VCD system tasks, such as $dumpvars. There are two types of VCD files:

TypeRecordsCreated with
Four-state VCDChanges between the four values 0, 1, x and z, without strength information$dumpfile, $dumpvars and related tasks
Extended VCDChanges in all states, including drive strength and the direction of each port$dumpports and related tasks

The four-state format is the one used for everyday debugging, and the rest of this article describes it. Extended VCD records ports only, with more detail per value, and is mostly used to capture the activity at the boundary of a block so it can be replayed or compared.

VCD Structure

A VCD file has three main sections, always in this order:

  1. Header section: information about the file, such as the date and the timescale
  2. Variable definitions: the list of recorded signals, organized by hierarchy, each with a short identifier code
  3. Value change section: the actual data, as a list of time stamps followed by the signals that changed at each time

Every piece of information in the first two sections is written as a keyword that starts with $ and ends with $end.

Header Section

The header holds information about the file itself: when it was created, which tool created it, and which timescale the time stamps use.

KeywordDescription
$commentInserts a comment in the VCD file
$dateIndicates the date on which the VCD file was generated
$enddefinitionsMarks the end of the file's header section
$timescaleSpecifies what timescale was used for the simulation
$versionIndicates which version of the VCD writer was used to produce the VCD file
$date April 11, 2021 10:05:41
$end
$version ICARUS-VERILOG 2.5
$end
$timescale 1 ns
$end

The $timescale entry gives the unit of every time stamp in the file. With 1 ns, a time stamp #40 means 40 ns. It is usually the finest time precision used in the design, as described in Verilog Timescale.

Variable Definitions

The variable definitions are also part of the header. They list every recorded signal, grouped by the module scope it belongs to, and give each one a short identifier code. The value change section then uses these codes instead of the full names, which keeps the file much smaller.

KeywordDescription
$scopeDefines the scope of the variables being dumped
$varPrints the names and identifier codes of the variables being dumped
$upscopeIndicates a change of scope to the next higher level in the design hierarchy
$enddefinitionsMarks the end of the header information and definitions
$comment
List all signals to be monitored next
$end

$scope module logic $end
$var wire 1 a signal_a $end
$var wire 1 b signal_b $end
$var wire 1 c signal_c $end
$upscope $end
$enddefinitions $end

Each $var line has the same five fields:

$var   wire   1      a                 signal_a   $end
       type   size   identifier code   name
  • type: the kind of variable, such as wire, reg, integer or real
  • size: the number of bits
  • identifier code: a short code of printable characters, chosen by the simulator; real files usually use characters such as !, " and #
  • name: the signal name in the design, with a bit range such as data [7:0] for vectors

Nested modules appear as nested $scope and $upscope pairs, so a viewer can rebuild the design hierarchy. If the same net is visible in two scopes, for example a port and the wire it connects to, both $var lines can share one identifier code, and its changes are only written once.

Value Change Section

After $enddefinitions, the file lists value changes in time order. A line starting with # sets the current simulation time, and the lines that follow it give the new value of every signal that changed at that time. A signal that does not change is not written at all, which is what makes the format compact.

#0
0a
0b
0c

#10
1a

#20
1b

#30
1c

#40
0a

#50
0b

#60
0c

For a 1-bit signal, the value is written directly in front of the identifier code, with no space. At time 0, all three signals start at 0. Then signal_a (code a) rises at 10 ns, signal_b at 20 ns and signal_c at 30 ns, and they fall again in the same order at 40, 50 and 60 ns. In a waveform viewer, this appears as three staggered pulses, each 30 ns wide.

Vectors and real numbers use a prefix letter, followed by a space and the identifier code:

Value changeMeaning
1a1-bit signal a becomes 1 (also 0, x, z)
b1010 dVector d becomes binary 1010; leading zeros may be left out
bx0 dVector d with its upper bits at x and its lowest bit at 0
r3.14 eReal variable e becomes 3.14

The initial values at the start of the dump are often placed inside a $dumpvars ... $end block, right after the first time stamp, and a viewer treats them like any other value change.

Synthesis result: None. VCD files are produced only by simulation, and the system tasks that create them are ignored by synthesis tools.

Quick Check

In the value change section above, what are the values of signal_a, signal_b and signal_c at 35 ns?

Show Answer

All three are 1. The last change before 35 ns for each signal was 1a at 10, 1b at 20 and 1c at 30. A signal keeps its value until the file records a new one, so the viewer reads backwards to the most recent change.

A Complete Example

The testbench below drives the same three signals and creates a VCD file. The VCD tasks are covered in detail in Verilog Dump VCD.


`timescale 1ns/1ns

module tb;
  reg signal_a, signal_b, signal_c;

  initial begin
    $dumpfile ("dump.vcd");          // Name of the VCD file
    $dumpvars (0, tb);               // Record all variables in tb and below

    {signal_a, signal_b, signal_c} = 0;
    #10 signal_a = 1;
    #10 signal_b = 1;
    #10 signal_c = 1;
    #10 signal_a = 0;
    #10 signal_b = 0;
    #10 signal_c = 0;
    #10 $finish;
  end
endmodule

The resulting dump.vcd looks similar to this. The header lines and identifier codes differ slightly between simulators, but the structure is always the same:

$date ... $end
$version ... $end
$timescale 1ns $end
$scope module tb $end
$var reg 1 ! signal_a $end
$var reg 1 " signal_b $end
$var reg 1 # signal_c $end
$upscope $end
$enddefinitions $end
#0
$dumpvars
0!
0"
0#
$end
#10
1!
#20
1"
#30
1#
#40
0!
#50
0"
#60
0#
#70

The values at time 0 are 0, not x, because $dumpvars records the values at the end of the time step, after the assignment. Some simulators also write the final time, #70, when $finish ends the simulation.

Quick Check

A 4-bit reg [3:0] count with identifier code $ changes from 3 to 4 at 25 ns. Which lines does the VCD file contain for this change?

Show Answer

#25 followed by b100 $. A vector value uses the b prefix and a space before the identifier code, and the leading zero of 0100 may be left out. If other signals changed at 25 ns too, they are listed under the same #25.

Exchanging Waveforms Between Tools

Because VCD is a standard text format, it works as a common language between tools. A waveform captured with one simulator can be opened in a different viewer, sent to a colleague using other tools, or read by a script. Teams write small scripts that parse VCD files to measure things like the number of toggles on a bus or the latency between a request and its response.

Power Estimation

Dynamic power depends on how often signals toggle. Power analysis tools read the switching activity of a realistic workload from a simulation dump, such as a VCD file of the gate-level netlist, and combine it with the capacitance of each net to estimate how much power the chip consumes in that scenario.

Common Beginner Mistakes

Mistake #1: Dumping the whole design in a long simulation

Wrong: $dumpvars(0, tb); for a full chip simulation of millions of cycles
Right: Dump only the module under investigation, such as $dumpvars(0, tb.u_dut.u_fifo);, or only a time window

Why? VCD is plain text, and every change of every recorded signal adds a line. Large designs produce files of many gigabytes, and the dumping itself slows the simulation down considerably. Simulators also offer compressed binary formats for this reason.

Mistake #2: Forgetting $dumpvars

Wrong: Calling only $dumpfile("dump.vcd");
Right: Call $dumpvars after $dumpfile

Why? $dumpfile only names the file. Without $dumpvars, no variables are selected, and the file contains no signals.

Mistake #3: Expecting a VCD file to show glitches within a time step

Wrong: Looking in the VCD file for a value that changed and changed back within the same simulation time
Right: Use $display or $monitor at that time, or a viewer that can show delta cycles

Why? A four-state VCD file records at most one final value per signal per time stamp. A signal that goes from 0 to 1 and back to 0 in the same time step does not appear to change at all.

Mistake #4: Reading identifier codes as signal names

Wrong: Searching the value change section of a VCD file for signal_a
Right: Look up the identifier code of signal_a in its $var line first, then search for that code

Why? Names only appear in the header. The value changes use the short identifier codes, such as ! or a.

Practice Exercise

Challenge: Decode a VCD File

Read this VCD fragment and write down the values of clk, en and count at 12 ns and at 27 ns.

$timescale 1ns $end
$scope module tb $end
$var reg 1 ! clk $end
$var reg 1 " en $end
$var reg 4 # count [3:0] $end
$upscope $end
$enddefinitions $end
#0
0!
0"
b0 #
#5
1!
#10
0!
1"
#15
1!
b1 #
#20
0!
#25
1!
b10 #
#30
0!
Hint

For each signal, find the last change at or before the time you are interested in. Vector values are in binary.

Solution
Timeclkencount
12 ns0 (since 10)1 (since 10)0 (since 0)
27 ns1 (since 25)1 (since 10)2 (b10, since 25)

The clock has a period of 10 ns, and count increments on the rising edges at 15 and 25 ns, once en is 1.

Summary

In this tutorial, you learned:

  • A VCD file is a standard ASCII record of value changes, written by the simulator and read by waveform viewers
  • Four-state VCD records 0, 1, x and z; extended VCD also records strength and port direction
  • The header holds the date, version and timescale, and the variable definitions map each signal to a short identifier code
  • The value change section lists time stamps with #, each followed by the signals that changed at that time
  • 1-bit values are written as 1a, vectors as b1010 d and reals as r3.14 e
  • Dump only what you need, because VCD files of large designs grow very quickly
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5