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

  • RTL Foundations36
    • Digital Logic for RTL Engineers
    • Number Systems for RTL Engineers
    • Verilog Fundamentals
    • Verilog Operators and Types
    • SystemVerilog for RTL
    • Simulation and Testbenches
      • Minimal but Robust Testbench Structure
      • Clock and Reset Best Practices
      • Self-Checking and Observability
      • Useful Runtime Instrumentation
      • Verification Quality Gates
      • First Project: a 4-bit ALU
  • Combinational Design25
  • Sequential Design27
  • FSM & Control27
  • Timing & Clocking39
  • Reset & CDC34
  • Memory & Buses57
  • Advanced RTL28
  • Senior & Interview76
  • Glossary and Notation
Loading lesson

‹Simulation and Testbenches
  1. Topics
  2. RTL Design
  3. RTL Foundations
  4. Simulation and Testbenches
  5. Useful Runtime Instrumentation

Part 1 · Foundations · Beginner

Useful Runtime Instrumentation

Seeds, verbosity and waveform switches controlled from the command line for replayable runs.

On this page

    Why this matters

    A nightly regression runs thousands of tests, and a failure is only useful if you can replay it exactly. That needs the seed in the log and switches such as +VERBOSE, with no source edits.

    After this lesson you can: reproduce a failing run from its seed, control logging and waveform dumping with plusargs, and name the checks a regression needs.

    Reproducible runs

    A regression runs thousands of tests. Debugging one means replaying it exactly with extra visibility and no source edits.

    Plusargs (+NAME=value on the simulator command line) provide that control.

    Tasks worth knowing

    Task

    Use

    $value$plusargs("X=%d", v)

    Read a number from the command line; returns 0 if absent, so provide a default.

    $test$plusargs("VERBOSE")

    True if the flag is present.

    $display / $write

    Print with or without a newline.

    $time / $realtime

    Current simulation time.

    $monitor

    Print automatically whenever a listed signal changes; handy for a quick look.

    $dumpfile / $dumpvars

    Write a VCD waveform file.

    $urandom / $urandom_range

    Reproducible random numbers when seeded.

    $error / $fatal

    Report a failure with severity; $fatal also ends the simulation.

    Warning

    Waveform dumping slows a simulation and creates huge files. Enable it only for the test you are debugging, as the +VERBOSE switch in the testbench below does.

    Tip

    Print the seed at the start of every run. A failing nightly regression is only useful if you can read the seed from its log and replay it.

    Interview-ready patterns

    • Directed tests for the corner cases you know (reset, full, empty, back-to-back), then constrained-random for the ones you do not.

    • A scoreboard (queue) for in-order data, an associative array when order may differ.

    • A watchdog timer and a final PASS/FAIL line so regressions can be scripted.

    • Assertions for protocol rules that must hold every cycle, plus coverage to show that the interesting cases actually occurred.

    Check yourself A nightly random test failed. What do you need from its log to reproduce it, and how do you get more visibility?

    The random seed and the command line. Rerun with the same seed to reproduce the failure, then add +VERBOSE (or turn on waveform dumping) to see detail without changing the code.

    Testbench

    This standalone listing uses the same two-stage pipeline as the preceding lesson. Each seeded byte is driven on a falling edge, checked after a rising edge, and logged when verbose. The final byte is drained before the verdict, so the seed, mismatch log and VCD describe one timed experiment. The reference stores the previous input rather than copying the pipeline implementation.

    instrumented_pipe.sv
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    module instrumented_pipe (
      input logic clk, rst_n,
      input logic [7:0] d,
      output logic [7:0] y
    );
      logic [7:0] s1;
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n) begin s1 <= '0; y <= '0; end
        else begin s1 <= d; y <= s1; end
    endmodule
    
    Diagram
    # run with defaults
    vvp sim.out
    # replay a failure and get detailed output and waveforms
    vvp sim.out +SEED=4711 +N=200 +VERBOSE

    The language defines the $urandom seed argument as input-only. Some Icarus versions overwrite it as a historical deviation. Seed from a copy as a compatibility precaution so the original value stays in the log for replay.

    The loop assigns d inside its body on every iteration. A declaration such as logic [7:0] x = $urandom; inside a static initial block would not work: an initialiser on a static variable runs only once, so every iteration would reuse the same value.

    Remember

    • Print the seed at the start of every run so any failure can be replayed.

    • Plusargs turn on verbose logging and dumping without editing the source.

    • Dump waveforms only for the test being debugged; they slow the run and the files are huge.

    Rule of thumb: log the seed first.

    Keep going

    • Interview: run a mock interview on this topic

    Related topics

    • Verification quality gates

    Previous

    34 / 350

    Next: Verification Quality Gates

    Up next

    Up nextVerification Quality Gates

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Minimal but Robust Testbench Structure
    • Clock and Reset Best Practices
    • First Project: a 4-bit ALU