A minimal TB has four jobs: clock, reset, stimulus, check (plus optional waves).
Skeleton
module tb;
logic clk, rst_n;
// DUT ports …
dut u_dut (.*);
// clock
initial clk = 0;
always #5 clk = ~clk; // TB-only delay
// reset + stimulus
initial begin
rst_n = 0;
// drive inputs idle
repeat (4) @(posedge clk);
rst_n = 1;
// … directed tests …
#100 $finish;
end
// waves (RTL Studio / Verilator friendly)
initial begin
$dumpfile("sim/dump.vcd");
$dumpvars(0, tb);
end
endmodule
Separation of concerns
| Piece | Lives in |
|---|---|
| Synthesizable design | rtl/ |
| Clock/reset/stimulus/checks | tb/ |
| Wave dump | TB initial |
Never leave #delay or $dumpvars inside production DUT modules.
Checking styles
- Scoreboard light: expected vs actual on a handshake
- Timeouts:
repeat (N) @(posedge clk); assert(done) $error/$fatal: fail the run clearly
@(posedge clk);
if (data !== 8'hA5) $error("bad data %h", data);
Tips for RtlStudio
- Keep
$dumpfilepath under the workspace (e.g.sim/dump.vcd). - Prefer small directed tests that finish quickly in-browser.
- Reset thoroughly before the first check — X’s are easy to misread as failures.