Skip to content
DenseChip
Learn
PracticeCode labInterview

DenseChip

Navigate

Menu

LearnPracticeCode labInterview

Tools

All toolsSV editorCode repoResume
DenseChip

Practice, courses, and chip-design tools in one focused workspace.

LearnPracticeCode labInterviewToolsLearning paths

© 2026 DenseChip

AboutContactPrivacyTerms
Skip to lesson

Course contents

  • How to Use This Course
  • Reading Paths
  • Quick Start: Your First Green Build
  • Part 1: How Chips Get Made6
  • Part 2: Your Workstation5
  • Part 3: Specify and Architect3
  • Part 4: The Design Loop6
    • Compile, Elaborate, Simulate, Synthesize, Lint
    • First Simulation
    • Waveforms with GTKWave
    • Lint with Verilator
    • First Synthesis Check
    • Simulation Code vs Synthesizable Code
  • Part 5: The Verification Ladder6
  • Part 6: Automation and Reproducibility5
  • Part 7: Hand-Off to the Back-End3
  • Part 8: When Things Go Wrong3
  • Part 9: Project and Next Steps3
  • Reference4
Loading lesson

‹Part 4: The Design Loop
  1. Topics
  2. Start Here: RTL and Verification
  3. Part 4: The Design Loop
  4. Waveforms with GTKWave

Part 4 · The Design Loop · Working (W)

Waveforms with GTKWave

A VCD file records every signal change and GTKWave draws it. Open a run, find the failing edge, and read the cycles around it.

On this page

    Note

    Level: Working (W) · Answers: The test failed at edge 4. How do you see why?

    Before this: First Simulation

    The test failed at edge 4. How do you see why?

    The run ends with an error naming edge 4. The transcript gives you one line: the expected count, the count you got, and nothing about the cycles that led there. The bug hides in the edges around the failure, and you need a way to see them.

    A VCD file records every change

    A value change dump (VCD) is a file of signal changes: every time a recorded signal changes value, the simulator appends the new value with its simulation time. The testbench chooses the file with a dump call that names it, and chooses the signals with a second call that names the scope. This course records everything under the testbench, so no signal you need is missing.

    GTKWave is a program that draws VCD files as waveforms. It is a viewer, not a simulator: it cannot change what the run computed, it only shows it. The steps below follow the GTKWave documentation; menu names differ between versions, so treat the words as landmarks rather than exact labels. GTKWave is also optional: every lesson in this course shows the same runs as simulated waveforms on the page, so you can learn the whole loop without installing it.

    Below is the real viewer, GTKWave 3.3.116 on Ubuntu 24.04, with a failing run loaded. The run uses the lesson testbench against a design with one planted bug: it checks the event input before the clear input, so counting beats clearing. The simulator printed ERROR edge 4: expected count=0 got 4, and then three more errors on edges 5, 6 and 7. Find the three panes: the signal tree on the left, the list of selected signals in the middle, and the waveforms on the right.

    A screenshot of GTKWave 3.3.116 (Ubuntu 24.04, run in a container) showing the failing run. The clear input is high from 40 to 50 ns, but the count keeps climbing from 3 to 4 to 5 instead of dropping to 0. That is the failure the testbench reported at edge 4.

    The count row is the evidence. Clear is high from 40 to 50 ns, yet the count goes 3, 4, 5 instead of dropping to 0. For comparison, here is the same testbench and the same inputs against the correct design: the count drops to 0 while clear is high, and the later hold edges stay at 1.

    The same view for the correct design: the count reads x, 0, 1, 2, 3, 0, 1. When clear is high, the count returns to 0.

    The count row starts as x because nothing has reset the register yet: simulation begins with unknown values, and the first rising edge with reset low sets it to 0. When you first open a file, the waveform pane is empty and zoomed far in; the next picture shows exactly that state, before any signals are added.

    GTKWave right after opening wave.vcd, before choosing any signals. Expand tb in the signal tree, select signals, and append them; then use the zoom-fit button to fit the whole run.

    Run it: open the failing run and read edge 4

    Open the VCD file from a run of the eight-edge testbench from the previous lesson, and walk it to the failing edge:

    1. Open wave.vcd in GTKWave.

    2. Expand the testbench hierarchy in the signal tree until you see the design signals.

    3. Select the clock, the control inputs, and the count, and append them to the display.

    4. Zoom to fit so all eight edges fill the window.

    5. Place the cursor on a rising clock edge and read each value at the cursor.

    The figure below is the correct design’s run, drawn by the course pages from the same kind of VCD data, with the edges numbered. Edge numbers count rising edges from zero, matching the testbench checks. Look at edge 4, where clear beats a simultaneous event, and at edges 6 and 7, where the count holds:

    • Edge 4: clear wins. The event and clear inputs are both high at the rising edge, and the count row falls from 3 to 0. The priority list decides: clear sits above counting, so the simultaneous event is ignored.

    • Edges 6 and 7: the count holds. The event input is low on both edges, so the count row stays at 1. No event means no change: the hold branch keeps the register steady, which is exactly what an idle counter must do.

    Which edge exposes a broken clear?

    Predict first Imagine the clear branch is broken so clear never takes effect. Edges 4, 6, and 7 all show the count doing something other than rising. Before reading on: which edge exposes the clear bug, and why do the other two stay quiet?

    Only edge 4. It is the one edge where clear is high together with an event, so only it exercises the clear branch. Edges 6 and 7 never assert clear; a broken clear changes nothing there, and the hold checks pass on the broken design too. An edge proves only the branches it drives.

    Break it on purpose: simulate without recording

    Now remove the recording and watch what disappears. This run compiled a copy of the lesson testbench with its two dump calls deleted, then simulated and listed the build folder:

    Diagram
    # captured terminal output
    $ mkdir -p build && iverilog -g2012 -s tb_mini_controller -o build/s.vvp rtl/mini_controller.sv tb/tb_mini_controller.sv && sed -i.bak '/dumpfile/d;/dumpvars/d' tb/tb_mini_controller.sv && iverilog -g2012 -s tb_mini_controller -o build/s2.vvp rtl/mini_controller.sv tb/tb_mini_controller.sv && (cd build && vvp s2.vvp | tail -n 2; ls *.vcd 2>&1 | head -n 1)
    PASS: mini_controller
    tb/tb_mini_controller.sv:67: $finish called at 2396000 (1ps)
    ls: *.vcd: No such file or directory

    This output came from Icarus Verilog 13.0 on macOS. The simulation passes and the finish line stamps the time, but the listing finds no VCD file: the checks ran and the recording never started, because nothing asked the simulator to write one. The fix is to keep both dump calls in every testbench you write, so every run leaves a file the viewer can open.

    Two mistakes every beginner makes

    • Reading the waveform as real timing. The viewer draws simulated behavior: ideal clocks, settled values, no silicon delays. It proves the logic answers its inputs correctly, never that the hardware meets timing.

    • Committing VCD files. A VCD records every change of every recorded signal, so it grows fast and regenerates on every run. The example project never commits them: its ignore file excludes *.vcd along with the build folder, compiled outputs, and logs, so record freely and let version control ignore the recordings.

    Rule: when a check fails, read the cycles around it, not only the line.

    Check yourself Find the clear-priority edge in the waveform above. What is the count after that edge, and what would it be if clear did not win?

    Edge 4: the event and clear inputs are both high, and the count goes from 3 to 0. If clear lost, the event would count and the count would go from 3 to 4, which is exactly the signature the previous lesson reads in its count-by-two run.

    Check yourself GTKWave opens your VCD but the waveform pane stays empty. What do you check first?

    Whether the run that wrote the file contained its dump calls with the right scope. An empty pane usually means the VCD holds no signals, as in the deleted-dump run above. Restore the dump calls, rerun, and reopen before suspecting the viewer.

    Check yourself Edges 6 and 7 hold at 1 but you expected the count to keep rising. Where do you look first?

    The event input on those edges: it is low, so the hold branch is doing its job and the design obeyed its inputs. Check the stimulus or your expectation, not the counter.

    Interview

    Asked: "What is a VCD file?"

    Weak answer: It is the waveform picture from the simulation.

    Strong answer: A value change dump: a text file the simulator writes listing every change of every recorded signal with its simulation time. The testbench selects the file with one dump call and the signals with another; a viewer like GTKWave draws the time histories from it, and the course pages render the same data as simulated figures.

    Follow-ups: (1) Which two calls must a testbench contain to produce one? (2) Why is a VCD from a passing run still useful?

    Key takeaways

    • A VCD records every recorded signal change with its time; a viewer draws it.

    • Read the cycles around a failing edge: the inputs at the edge explain the output after it.

    • Waveforms show simulated behavior, never real timing, and VCD files stay out of version control.

    Keep going

    Next: Lesson 4.4, Lint with Verilator. You can read what the design did. The next lesson finds bugs without running it at all.

    Related topics

    • Hardware Debug: Reading a Waveform with a Question

    • Design Loop: First Simulation

    Previous

    20 / 47

    Next: Lint with Verilator

    Up next

    Up nextLint with Verilator

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Compile, Elaborate, Simulate, Synthesize, Lint
    • First Synthesis Check
    • Simulation Code vs Synthesizable Code
    clkrst_nevent_validclear_countcount012301
    Eight rising edges of the counter run. Look at edge 4, where clear beats a simultaneous event and the count returns to 0, and at edges 6 and 7, where the event input is low and the count holds at 1.