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:
| Type | Records | Created with |
|---|---|---|
| Four-state VCD | Changes between the four values 0, 1, x and z, without strength information | $dumpfile, $dumpvars and related tasks |
| Extended VCD | Changes 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:
- Header section: information about the file, such as the date and the timescale
- Variable definitions: the list of recorded signals, organized by hierarchy, each with a short identifier code
- 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.
| Keyword | Description |
|---|---|
| $comment | Inserts a comment in the VCD file |
| $date | Indicates the date on which the VCD file was generated |
| $enddefinitions | Marks the end of the file's header section |
| $timescale | Specifies what timescale was used for the simulation |
| $version | Indicates 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.
| Keyword | Description |
|---|---|
| $scope | Defines the scope of the variables being dumped |
| $var | Prints the names and identifier codes of the variables being dumped |
| $upscope | Indicates a change of scope to the next higher level in the design hierarchy |
| $enddefinitions | Marks 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,integerorreal - 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 change | Meaning |
|---|---|
1a | 1-bit signal a becomes 1 (also 0, x, z) |
b1010 d | Vector d becomes binary 1010; leading zeros may be left out |
bx0 d | Vector d with its upper bits at x and its lowest bit at 0 |
r3.14 e | Real 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
| Time | clk | en | count |
|---|---|---|---|
| 12 ns | 0 (since 10) | 1 (since 10) | 0 (since 0) |
| 27 ns | 1 (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 asb1010 dand reals asr3.14 e - Dump only what you need, because VCD files of large designs grow very quickly