Day 62: HDLBits daily: “Circuits” (part 2) + self-checking testbenches
HDLBits Circuits part 2 + self-checking testbenches
Finish the HDLBits Circuits section (sequential and FSM problems), then level up your own verification: a self-checking testbench drives stimulus, computes the *expected* result independently, compares against the DUT, and prints PASS/FAIL — no human eyeballing waveforms. This is enforced from now on: 'looks right in GTKWave' is not sign-off (failure mode #2).
module tb;
reg [7:0] a, b;
wire [8:0] sum;
integer errors = 0;
adder8 dut (.a(a), .b(b), .sum(sum));
task check(input [7:0] ta, tb_);
begin
a = ta; b = tb_; #1;
if (sum !== (ta + tb_)) begin
$display("FAIL: %0d + %0d = %0d (exp %0d)", ta, tb_, sum, ta+tb_);
errors = errors + 1;
end
end
endtask
initial begin
check(0,0); check(255,1); check(100,55);
// ... directed + a loop of random cases ...
if (errors == 0) $display("ALL PASS");
else $display("%0d FAILURES", errors);
$finish;
end
endmoduleWaveform-staring is not verification
Waveforms are for *debugging a known failure*, not for *deciding* whether a module is correct. A self-checking testbench encodes the correct answer once and checks it automatically, every run — which scales to regressions (Stage 3) and catches regressions you'd never spot by eye. Build this habit now on tiny modules.
Key terms
- Testbench
- Non-synthesizable code that instantiates a DUT, drives stimulus, and checks results.
- Self-checking
- A testbench that computes expected results and compares automatically, reporting PASS/FAIL.
- DUT
- Design under test — the module the testbench exercises.
- Directed vs random stimulus
- Hand-picked corner cases vs randomized inputs; good testbenches use both.
Ship for Day 62
What makes a testbench "self-checking"?