VCD is the Verilog Value Change Dump file format. It's often used in EDA tools to trace values over time and can be displayed with tools like GTKWave.
The following package can be used to generate VCD files:
package require TclOO package provide vcd oo::class create VCD { constructor {fnm} { variable f variable c0 32 variable c1 32 variable c2 32 variable c3 32 set f [open $fnm w] } destructor { variable f close $f } method get_id {} { variable c0 variable c1 variable c2 variable c3 incr c0 if {$c0 >= 127} { incr c1 set n0 33 } if {$c1 >= 127} { incr c2 set n1 33 } if {$c2 >= 127} { incr c3 set n2 33 } if {$c3 >= 127} { error "Out of id's" } set id "" if {$c3 > 32} { append id [format %c $c3] } if {$c2 > 32} { append id [format %c $c2] } if {$c1 > 32} { append id [format %c $c1] } if {$c0 > 32} { append id [format %c $c0] } return $id } method comment {txt} { variable f puts $f "\$comment\n$txt\n\$end" } method date {} { variable f puts $f "\$date [clock format [clock seconds]] \$end" } method timescale {number scale} { variable f puts $f "\$timescale $number $scale \$end" } method define_variable {type width reference} { variable ids variable typ variable wid variable f set ids($reference) [my get_id] set typ($reference) $type set wid($reference) $width puts $f "\$var $type $width $ids($reference) $reference \$end" } method enddefinitions {} { variable f puts $f "\$enddefinitions \$end" } method scope {type identifier} { variable f puts $f "\$scope $type $identifier \$end" } method upscope { } { variable f puts $f "\$upscope \$end" } method version {txt} { variable f puts $f "\$version\n$txt\n\$end" } method simulation_time {time} { variable f puts $f "\#$time" } method value {reference value} { variable ids variable typ variable wid variable f switch -exact -- $typ($reference) { "integer" { if {![string is integer -strict $value]} { error "Value '$value' for reference '$reference' is not an integer" } puts $f "b[string trimleft [format %b $value] 0] $ids($reference)" } "real" { error "Unsupported type '$typ($reference)' for reference '$reference'" } default { if {$value ni {0 1 x z}} { error "Value '$value' for reference '$reference' must be 0, 1, x or z" } puts $f "$value$ids($reference)" } } } }
Example usage:
VCD create log test.vcd log comment "Some comments from the user" log date log define_variable integer 32 var1 log define_variable integer 32 var2 log define_variable integer 32 var3 log define_variable integer 32 var4 log define_variable integer 32 var5 log define_variable integer 32 var6 log define_variable integer 32 var7 log define_variable integer 32 var8 log define_variable wire 1 wire1 log define_variable wire 1 wire2 log define_variable wire 1 wire3 log define_variable wire 1 wire4 log define_variable wire 1 wire5 log define_variable wire 1 wire6 log define_variable wire 1 wire7 log define_variable wire 1 wire8 log timescale 10 ns log enddefinitions log simulation_time 10 log value var1 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log simulation_time 20 log value var2 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log simulation_time 30 log value var3 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log simulation_time 40 log value var4 [expr {entier(rand()*0xffffffff)}] log value var5 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log simulation_time 50 log value var6 [expr {entier(rand()*0xffffffff)}] log value var7 [expr {entier(rand()*0xffffffff)}] log value var8 [expr {entier(rand()*0xffffffff)}] log value var1 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log value wire6 [lindex {0 1 x z} [expr {round(rand()*3)}]] log simulation_time 60 log value var2 [expr {entier(rand()*0xffffffff)}] log value var3 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log value wire5 [lindex {0 1 x z} [expr {round(rand()*3)}]] log simulation_time 70 log value var4 [expr {entier(rand()*0xffffffff)}] log value var5 [expr {entier(rand()*0xffffffff)}] log value var6 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log value wire4 [lindex {0 1 x z} [expr {round(rand()*3)}]] log simulation_time 80 log value var7 [expr {entier(rand()*0xffffffff)}] log value var8 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log value wire2 [lindex {0 1 x z} [expr {round(rand()*3)}]] log simulation_time 90 log value var1 [expr {entier(rand()*0xffffffff)}] log value var3 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log value wire2 [lindex {0 1 x z} [expr {round(rand()*3)}]] log simulation_time 100 log value var5 [expr {entier(rand()*0xffffffff)}] log value var7 [expr {entier(rand()*0xffffffff)}] log value var2 [expr {entier(rand()*0xffffffff)}] log value var4 [expr {entier(rand()*0xffffffff)}] log value var6 [expr {entier(rand()*0xffffffff)}] log value var8 [expr {entier(rand()*0xffffffff)}] log value var1 [expr {entier(rand()*0xffffffff)}] log value var3 [expr {entier(rand()*0xffffffff)}] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log value wire1 [lindex {0 1 x z} [expr {round(rand()*3)}]] log destroy
The resulting output file looks like this:
$comment Some comments from the user $end $date Thu Oct 28 17:24:16 CEST 2010 $end $var integer 32 ! var1 $end $var integer 32 " var2 $end $var integer 32 # var3 $end $var integer 32 $ var4 $end $var integer 32 % var5 $end $var integer 32 & var6 $end $var integer 32 ' var7 $end $var integer 32 ( var8 $end $var wire 1 ) wire1 $end $var wire 1 * wire2 $end $var wire 1 + wire3 $end $var wire 1 , wire4 $end $var wire 1 - wire5 $end $var wire 1 . wire6 $end $var wire 1 / wire7 $end $var wire 1 0 wire8 $end $timescale 10 ns $end $enddefinitions $end #10 b1001010000001011110011111110 ! 1) #20 b111110010011110000101100111100 " x) #30 b10111101010011110101010110111010 # x) #40 b10010011011111101001101010100000 $ b1011100110110011100101000000110 % z) #50 b1110000001110010101111000110 & b11111000110010101101101101011010 ' b11001110000001110111000101010000 ( b1001010101000001010010011011100 ! 1) 1. #60 b11000010100101110010000010010010 " b1001111110110111011010100001100 # z) 0- #70 b1110110110010111110011011101000 $ b1000100101001001100011001000110 % b10011101110101010100000011011110 & 0) 0, #80 b100111010011011001000011011010 ' b1010101011000001110110001011110 ( 1) z* #90 b11110101101011001011100011010000 ! b11110100110011101110110110010 # 0) 0* #100 b10100010101111011101001101110100 % b1011100100001011011100000100100 ' b1001110111111000111001011110000 " b10011111110111100001001100010010 $ b10101100101101100101010010111100 & b11110110011101010101101100111000 ( b10010010101110000011011111110000 ! b1111100011000001011100011010000 # x) x)