trsim Waveforms
The Tuwa RTL Simulator, version 1.0
How to get a waveform out of a run, and how to look at it.
Getting a VCD
There are two ways, and the first is usually better because it keeps the decision with the design.
From the testbench
initial begin
$dumpfile("counter.vcd");
$dumpvars(0, counter_tb);
...
end
$dumpfile names the output. $dumpvars(0, top) dumps everything under top — the 0 means "no depth limit". The file is written as the simulation runs, so it is there even if the run is interrupted.
From the command line
trsim -top my_tb -time 100000 -vcd out.vcd rtl\*.v tb\my_tb.v
Use this when the testbench does not call $dumpfile and you do not want to edit it.
Controlling the dump
| Task | Effect |
|---|---|
$dumpoff | stop recording changes |
$dumpon | start again |
$dumpall | write the current value of everything, whether it changed or not |
$dumpflush | flush what has been written so far to disk |
$dumplimit(n) | stop once the file reaches n bytes |
$dumplimit is worth knowing on a long run: a VCD of a busy design grows quickly, and a capped file is better than a full disk.
What the file contains
The output is plain IEEE 1364 Annex A VCD: a header describing the design's scopes and signals, then a stream of timestamped value changes.
$date Thu Aug 20 00:21:42 2026 $end
$version TuwaRTLSIM 1.0 $end
$timescale 1ns $end
$scope module seq_detect_tb $end
$var reg 1 ! clk $end
$var reg 1 " rst_n $end
$var reg 16 ( pattern $end
$scope module dut $end
$var reg 3 - state $end
$var reg 3 . next $end
$upscope $end
$upscope $end
$enddefinitions $end
Scopes follow the instance hierarchy, so dut appears nested inside the testbench and two instances of the same module are told apart by their instance names.
What is not recorded
Array elements inside an instantiated module. A memory declared inside a submodule appears in the header and shows its contents at time 0, then a flat line. Scalars and vectors inside a module are recorded correctly. If you need to watch a memory location, assign it to a scalar in the testbench and watch that:
wire [7:0] watch_entry3 = dut.mem[3];
Viewing the waveform
In another tool
The file is standard, so:
gtkwave counter.vcd
ModelSim reads it directly, or converts it: vcd2wlf counter.vcd counter.wlf. Verdi reads VCD as well.
In trsim's viewer
Start trsimgui.exe and open the .vcd. The viewer is built for the job rather than being a general chart:
Choosing what to see. A real design declares more signals than fit on a screen. The filter box above the signal list narrows the list as you type; * matches any run of characters and ? any single one, and a pattern with no wildcard matches as a substring. The right-click menu has a Scope submenu listing every scope in the dump, so you can go straight to one block.
Radix. Right-click a signal for hexadecimal, binary, decimal, octal or ASCII. Double-clicking a signal name cycles through them.
Cursors. Click to place the primary cursor; Ctrl-click for the second. The time between them is shown, which is the quickest way to measure a pulse or a latency. Hold Alt while clicking to place a cursor exactly where you clicked instead of snapping to the nearest edge.
Stepping along a signal. Select a signal and press N or P to move the cursor to the next or previous change. Shift+N/Shift+P step only rising edges and Ctrl+N/Ctrl+P only falling ones. On a bus, plain N and P are what you want: they step to the next change of any kind.
Zooming. The mouse wheel scrolls; Ctrl+wheel zooms about the pointer, so whatever is under the cursor stays there. Shift+wheel and the arrow keys pan. Shift-drag rubber-bands a region to zoom into it. F fits the whole run to the window.
Sessions. Which signals you chose, their order, their radix and colour, and the zoom and cursors can be saved beside the dump and reloaded, so reopening a design does not mean setting it up again.
Reading x and z
Unknown and high-impedance values are drawn distinctly rather than as 0: a scalar sits at mid level, and a bus is drawn with a dashed outline. A partly unknown vector prints x only in the digits that are actually unknown, so 8'b1010_xxxx reads as ax rather than collapsing to xx.
This matters more than it sounds. The commonest real bug a waveform shows is a value that is x when you expected a number, and the quickest way to find its cause is to step back to where the x first appears.
A worked look
Run the state-machine example and open its dump:
cd examples\04_fsm
trsim -top seq_detect_tb -time 5000 seq_detect.v
gtkwave seq_detect.vcd
Put clk, din, dut.state and found on screen in that order. You will see state climb 0-1-2-3-4 as the bits 1, 0, 1, 1 arrive, and found go high for one cycle while the machine sits in state 4. Because the output is a function of the state alone, found appears one cycle after the last bit — which is what makes it a Moore machine, and is exactly the kind of thing a waveform makes obvious and a print statement does not.