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 Foundations57
    • 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
      • Reference Model Plus Checks
      • Useful Runtime Instrumentation
      • Verification Quality Gates
      • First Project: a 4-bit ALU
      • Interview-Ready Simulation Patterns
      • Simulation TB Summary
      • Worked Examples and Waveforms
  • Combinational Design58
  • Sequential Design61
  • FSM & Control66
  • Timing & Clocking64
  • Reset & CDC58
  • Memory & Buses94
  • Advanced RTL60
  • Senior & Interview175
  • Glossary and Notation
Loading lesson

‹Simulation and Testbenches
  1. Topics
  2. RTL Design
  3. RTL Foundations
  4. Simulation and Testbenches
  5. Minimal but Robust Testbench Structure

Part 1 · Foundations · Beginner

Minimal but Robust Testbench Structure

Six parts of a small testbench: clock, reset, stimulus, checks, watchdog and verdict.

On this page

    Why this matters

    A testbench with no watchdog runs forever when the DUT never produces the event it waits for. A run that stops at the first error hides the other failures.

    After this lesson you can: build a testbench with a clock, reset, DUT, stimulus, a checking task, a watchdog and one greppable verdict.

    The skeleton

    Every testbench needs the same six parts. The testbench below shows them working together.

    1. Clock generator, defined once.

    2. Reset sequence with a clear assert and release.

    3. DUT instance, connected by name.

    4. Stimulus, driven at well-defined times relative to the clock.

    5. Checks that compare against expected values and count errors.

    6. Watchdog that ends the simulation if the test hangs, and a final verdict.

    Clock generator, reset sequence and stimulus all feed the DUT. The DUT outputs go to checks that count errors, which lead to the final verdict. A watchdog timer leads to the verdict through a timeout path.
    The six parts of tb_counter: clock, reset and stimulus feed the DUT, checks count errors, and either the verdict or the watchdog ends the run

    Read the chart top to bottom; the numbers match the list above and the numbered comments in the testbench below.

    • Three inputs, one DUT: the clock, the reset sequence and the stimulus are the only things that drive it.

    • Two ways out: the normal path goes through the checks to a PASS or FAIL verdict; the watchdog is the second exit, for a test that hangs.

    The testbench has no ports. It is the top of the simulation, generating the clock and observing the DUT.

    Use detailed ERROR diagnostics, then one final greppable PASS: or FAIL: verdict. Normal completion calls $finish; unexpected failure calls $fatal(1, ...) so standalone automation also gets a failing status. A watchdog is an alternative failure exit, not another success verdict.

    Habits that keep tests honest

    • Declare timeunit 1ns; timeprecision 1ps; in the testbench. For this 10 ns clock, #1 samples 1 ns after an edge and before the next edge; it is a teaching observation delay, not a physical gate delay.

    • Put checks in a task so every failure prints the same useful message (what, when, got, expected).

    • A testbench without a watchdog can run forever when the DUT never produces the event you wait for. Always add one.

    • Count errors instead of stopping at the first. A run that shows all failures is easier to debug.

    Check yourself Why does this testbench wait #1 after @(posedge clk) before calling check?

    Its clocked assignments update in the NBA region of the edge's timestamp. Sampling 1 ns later observes the settled outputs in this zero-delay RTL example. The delay must remain shorter than the next relevant edge; it is not a universal race fix or a timing guarantee. Larger environments use explicit clocking/sampling contracts.

    Testbench

    A counter testbench exercising reset, counting and hold.

    counter.sv
    1
    2
    3
    4
    5
    6
    7
    8
    module counter (
      input  logic       clk, rst_n, en,
      output logic [3:0] count
    );
      always_ff @(posedge clk or negedge rst_n)
        if (!rst_n)  count <= '0;
        else if (en) count <= count + 1'b1;
    endmodule
    

    Remember

    • Six parts: clock, reset, DUT by name, stimulus, checks that count errors, and a watchdog.

    • Put checks in a task so every failure prints what, when, got and expected.

    • End with one PASS: or FAIL: line. Use $fatal(1, ...) on unexpected failure so automation sees a failing status.

    Rule of thumb: a test that cannot fail, or cannot finish, is not a test.

    Keep going

    • Interview: run a mock interview on this topic

    Related topics

    • Clock and reset best practices

    Previous

    48 / 694

    Next: Clock and Reset Best Practices

    Up next

    Up nextClock and Reset Best Practices

    Sign in to save progress

    Practice this lessonReport an error

    See also

    • Self-Checking and Observability
    • Reference Model Plus Checks
    • Useful Runtime Instrumentation