Part 6 · Testbench Architecture · Intermediate

Testbench Architecture in SystemVerilog

Hand-built class-based testbenches: layered architecture, generators, drivers, monitors, scoreboards, synchronization, self-checking regression, and the bridge to UVM.

What this section covers

Before UVM, verification teams built layered class-based testbenches by hand — and every concept UVM later standardized (agents, sequences, factories, phases) was first a plain SystemVerilog class wired together with mailboxes and virtual interfaces. This section teaches you to build that testbench yourself: not for nostalgia, but because interviewers probe it constantly, and because you cannot debug a UVM environment you could not have built from scratch.

Flat procedural testbenches — one giant initial block driving pins and eyeballing waveforms — collapse past a few hundred lines. Stimulus, driving, checking, and test intent are tangled together, so changing one breaks all. Layering separates these concerns into classes connected by mailbox channels, so each piece can be written, reused, and swapped independently.

Full layered architecture

diagram
LAYERED CLASS-BASED TESTBENCH (pre-UVM, plain SystemVerilog)

  ┌──────────────────────────────────────────────────────────────────┐
  │  TEST (class)         picks config, knobs, constraint overrides   │
  └────────────────────────────────┬─────────────────────────────────┘
                                   │ builds & runs
  ┌────────────────────────────────▼─────────────────────────────────┐
  │  ENVIRONMENT (class)  constructs everything, wires mailboxes      │
  │                                                                    │
  │   ┌────────────┐   mailbox    ┌──────────┐        ┌────────────┐ │
  │   │ GENERATOR  │─────────────►│  DRIVER  │        │ REFERENCE  │ │
  │   │ randomize  │  #(txn)      │ pin      │        │ MODEL      │ │
  │   │ txns       │              │ wiggling │        │ (predict)  │ │
  │   └────────────┘              └────┬─────┘        └─────┬──────┘ │
  │                                    │ vif                │ exp    │
  │                                    ▼                    ▼        │
  │   ┌────────────┐   mailbox    ┌──────────┐        ┌────────────┐ │
  │   │  MONITOR   │─────────────►│SCOREBOARD│◄───────│ exp queue  │ │
  │   │ sample vif │  #(txn)      │ exp==act?│        └────────────┘ │
  │   └─────┬──────┘              └──────────┘                       │
  └─────────┼─────────────────────────┬─────────────────────────────┘
            │ vif (observe)           │ vif (drive)
  ┌─────────▼─────────────────────────▼─────────────────────────────┐
  │  tb_top (module)   clock gen │ reset gen │ interface │ DUT       │
  │                          ┌─────────┐                             │
  │                          │   DUT   │                             │
  │                          └─────────┘                             │
  └──────────────────────────────────────────────────────────────────┘

  Class world talks to the module world ONLY through virtual interfaces.

Topic map

diagram
TESTBENCH SECTION — topic map

┌───────────────────────────────────────────────────────────────────┐
│  1. TESTBENCH ANATOMY                                              │
│     layers │ tb_top harness │ env class │ tests │ program │ mini TB│
│                                                                    │
│  2. STIMULUS GENERATION                                            │
│     txn design │ generators │ drivers │ pipelining │ directed+rand │
│                                                                    │
│  3. MONITORS & SCOREBOARDS                                         │
│     passive sampling │ exp vs act │ reference models │ ordering    │
│                                                                    │
│  4. SYNCHRONIZATION                                                │
│     mailboxes │ events │ semaphores │ end-of-test │ reset handling │
│                                                                    │
│  5. SELF-CHECKING REGRESSION                                       │
│     pass/fail criteria │ seeds │ plusargs │ logs │ regression flow │
│                                                                    │
│  6. BRIDGE TO UVM                                                  │
│     what UVM standardizes │ class  UVM component map │ migration  │
└───────────────────────────────────────────────────────────────────┘

Topics in this section

  1. Testbench Anatomy & Layering — the layer stack, tb_top harness, environment class, test classes, the program-block debate, and a complete annotated mini testbench.

  2. Stimulus Generation — transaction design, generator patterns, driver design, pipelined/backpressured driving, and mixing directed with random stimulus.

  3. Monitors & Scoreboards — passive bus sampling, expected-vs-actual checking, reference models, and out-of-order matching.

  4. Synchronization — mailboxes, events, semaphores, end-of-test detection, and reset-aware components.

  5. Self-Checking Regression — pass/fail automation, seed management, plusarg control, and regression scripting.

  6. Bridge to UVM — mapping every hand-built class to its UVM counterpart so the methodology feels earned, not memorized.


Why this matters for interviews

A staple senior-DV interview question is: “Build me a testbench for this FIFO without UVM.” It tests whether you understand the architecture or merely the macros. Candidates who can sketch the generator → mailbox → driver → DUT → monitor → scoreboard pipeline, explain why each boundary exists, and write the mailbox plumbing from memory stand apart immediately.

Key takeaways

  • Layered class-based TBs separate stimulus, driving, observing, and checking so each is independently reusable.

  • The class world reaches pins only through virtual interfaces; tb_top owns all static structure.

  • Mailboxes are the standard inter-component channel — generator-to-driver and monitor-to-scoreboard.

  • Everything UVM provides existed first as hand-built classes; learn this layer and UVM becomes obvious.

Common pitfalls

  • Writing stimulus, driving, and checking in one initial block — unmaintainable past toy examples.

  • Letting classes touch DUT pins directly instead of via virtual interfaces — kills reuse across instances.

  • Skipping the scoreboard and eyeballing waveforms — does not scale to regression and random stimulus.

  • Jumping straight to UVM macros without this foundation — you cannot debug what you cannot build.