A failure that cannot be reproduced cannot be narrowed. The seed, the plusargs, and the first failing transaction are logged before any wave is opened.
A rerun with the same seed must fail at the same cycle. That stability is what makes the search possible.
Each level answers one question. The search drops a level only when the level above has named a suspect.
Level | Question | Example |
|---|---|---|
L1: top-level symptom | What looks wrong from outside? | Timeouts, stale data, wrong ordering |
L2: block contract | Which interface rule broke? | Valid/ready mismatch, bad state transition |
L3: local root cause | Which assignment caused it? | Missing default, race, width mismatch, reset issue |
Read the funnel from the top. Each band is narrower because it covers less of the design.
L1 is what the test saw: one wrong output word.
L2 names the rule that broke, here the decode of one address.
L3 is one line of RTL, and only now is the code opened.
A 2-bit decoder returns 1000 for address 2 instead of 0100. The sweep below checks four addresses against a one-hot reference.
The first mismatch lands on address 2, the third check of the sweep. L1 (wrong one-hot word) becomes L2 (the decode contract for address 2) becomes L3 (the case entry for 2'd2).
It narrows the search and avoids following only downstream symptoms, but it need not be the original corruption. Trace the affected transaction and state history backward; the root cause may predate every currently monitored boundary.
The decode contract for address 2. The upper levels are settled, so the search drops to the case entry for that address.
The decoder with one wrong entry plus the sweep that pinpoints it.
`timescale 1ns/1ps
module dec24_bug (
input logic [1:0] addr,
output logic [3:0] line
);
always_comb begin
line = 4'b0000;
case (addr)
2'd0: line = 4'b0001;
2'd1: line = 4'b0010;
2'd2: line = 4'b1000; // BUG: should be 0100
2'd3: line = 4'b1000;
endcase
end
endmodule
module tb_dec24_triage;
initial begin
#100000;
$fatal(1, "FAIL: bounded bench watchdog expired");
end
logic [1:0] addr;
logic [3:0] line, exp_line;
dec24_bug dut (.*);
int errors = 0, first_bad = -1;
initial begin
for (int s = 0; s < 4; s++) begin
addr = s[1:0]; #1;
exp_line = (4'b0001 << s);
if (line !== exp_line) begin
errors++;
if (first_bad == -1) first_bad = s;
end
end
if (errors == 1 && first_bad == 2) $display("PASS: the 4-address sweep isolates the faulty decoder output at address 2");
else $fatal(1, "FAIL: errors=%0d first_bad=%0d", errors, first_bad);
$finish;
end
endmodule