← Back to the series

Verification, From First Principles — Part 3 of 10

Approaches to Verification

Once you know verification is a loop of "drive, predict, compare" — the next question is: who decides what gets driven? That decision has a name, and a few standard answers.

Directed testing

A directed test is exactly what it sounds like: you, the verification engineer, decide the exact sequence of inputs ahead of time. "Write 0xFF to address 4, then read address 4, check it returns 0xFF." It's predictable, easy to debug when it fails (you know exactly what you asked for), and it's how most people write their very first testbench.

Its weakness is exactly its strength: it only tests what you thought to write. If you didn't think of a particular combination of back-to-back reads and writes, a directed test will never generate it — and neither will the bug it might have caught.

Constrained-random testing

Instead of hand-writing every input, you describe the legal range of inputs — "address is between 0 and 255," "data is any 32-bit value," "back-to-back reads can happen, but not more than 4 in a row" — as constraints, and let a randomizer generate thousands of legal-but-unpredictable stimulus combinations for you. This is the dominant approach in UVM-based verification, because it finds the bugs you didn't think to look for, precisely by not being limited to your imagination.

It trades some of directed testing's predictability for reach: when a randomized test fails, you first have to reconstruct exactly what sequence triggered it, which is why UVM environments log detailed transaction and seed information — so a failure can be reproduced deterministically later.

Black-box vs. white-box

This is a separate axis from directed-vs-random, about how much internal visibility your testbench assumes:

  • Black-box: the testbench only drives the design's external interface and checks its external outputs — exactly like the design will actually be used once it's integrated into a bigger chip. Most UVM environments are built this way.
  • White-box: the testbench (or a checker) can also look at internal signals — an internal FIFO's pointer, an internal state machine's current state — to check things that aren't directly observable from the interface. Useful for hard-to-reach internal corner cases, but it couples your testbench to internal implementation details that might change.

Top-down vs. bottom-up

This is about where you verify, not how: bottom-up means verifying small blocks (a FIFO, an arbiter) in isolation first, where bugs are cheap and fast to root-cause; top-down means verifying at the full-chip or subsystem level, where you catch integration bugs that only show up when blocks interact — but where a failure can take much longer to trace back to its actual source. Real projects do both: block-level (often called IP-level) verification first, then integration-level verification once the blocks are individually trusted.

Takeaway

Directed vs. constrained-random is about who picks the stimulus. Black-box vs. white-box is about how much internal visibility the checker has. Bottom-up vs. top-down is about which level of the design you're targeting. A real verification plan makes a deliberate choice on all three axes — it's rarely just one style throughout.

Next: these approaches don't run themselves — they need a language. Part 4 traces how Verilog, SystemVerilog, and UVM each earned their place in a modern testbench.