Part 3 answers: Where and when did it first go wrong?
The fastest debuggers do not read more; they cut the search space in half, again and again. This part bisects in time, in the design hierarchy, in the stimulus, across configurations and across version history, then traces the cone of logic behind the first wrong signal.
Walk back from a scoreboard error to the first wrong cycle.
Find the commit that introduced a bug with git bisect in a handful of steps.
Trace the fan-in cone of a wrong signal to a short list of suspects.
10 lessons, about 112 min
The part on one page, taken from each lesson's Remember box.
The First Wrong Cycle
Each hop asks one thing: given its inputs at that cycle, is this value right? If an input is wrong, it becomes the next symptom.
Stop where every input is right and the output is wrong. That cycle and that line are the place to hypothesise about.
A value can be wrong because something never happened. Then the next hop is the event that should have written it.
Rule of thumb: judge every hop against what the design was meant to do, never against what its code happens to do.
Bisection in Time
The question must flip once: clean before some cycle, bad after it. Check both ends first; reset and later overwrites can break that.
Each look must leave the run unchanged up to its cycle. Read state from the side, never through the bus the design uses.
Bisection finds the first cycle your question can see. A sharper question sees earlier; then walk back the last hops.
Rule of thumb: if you can check every cycle cheaply, do that in one run; bisect in time when each look is costly.
Bisection in Space
A monitor checks its interface's own rules (known controls, known data when valid, order), so it needs no model of the whole design.
Compare first-breach times, not yes or no. A wrong value can echo backwards through feedback, like FIFO pointers, and breach upstream later.
The block to open is the one whose inputs were clean at the moment its outputs first went wrong. Then halve inside it the same way.
Rule of thumb: blame the side that drives the breaching signal at the earliest breach, never simply the upstream side.
Bisection in Stimulus
Split by kind, not by position: source (CPU, DMA), operation type, mode, length. The answer names a feature of the design, not a line of one test.
Removing a class must not quietly change the classes you keep. Dropping traffic also drops time; make the replay wait instead of skip.
Run the split on every failing seed. Seeds that need the same class are probably one bug; classes that share an attribute point at the shared logic.
Rule of thumb: a class is needed only if removing it makes the same failure go away, with everything else replayed exactly as before.
Bisection in History
Bisection needs a known good version, a known bad version and a test that tells them apart on its own. Check both ends before you start.
Each test halves the suspects: 11 commits take 4 runs, 1,000 take 10. The script's exit code is the answer: 0 good, 1 bad, 125 skip.
Bisect answers "when did this test start failing", which is not always "when did this bug arrive". Test for the bug's own signature.
Rule of thumb: never trust a bisect whose test can fail for more than one reason.
Bisection Across Configurations and Seeds
Ordered dimensions (commits, numeric parameters, tool versions) can be bisected to a boundary. Unordered ones (simulators, option sets, seeds) are compared in a matrix.
Read the pattern: failing everywhere means logic; only with X or random start values, uninitialised state; a failure that moves with a parameter, a path.
A pass means "not seen with this configuration and this stimulus". Check the test still tests the feature, and push the stimulus past the new limit.
Rule of thumb: change one dimension at a time from a failing configuration, and never read a pass as a fix until the stimulus reaches the new boundary.
Cone-of-Influence Tracing
Take the cone one stage at a time. The whole transitive cone of an output is usually most of the design; one stage is a handful of registers.
Clear a suspect only with a value from the failing run at the right cycle. A cleared register removes its whole cone from the search.
If every register behind a wrong value was right, the cause is the logic between them, or an input the logic should have and does not.
Rule of thumb: never read the RTL behind a wrong signal before you have its stage-one suspect list and a value for each suspect.
Differential Debugging
A reference is only as useful as the list of ways it is allowed to differ. Write that list first; everything else in the diff is evidence.
Compare on every beat if you can. An end-of-test compare can pass a design that was wrong for most of the run.
Which references disagree is itself a clue: tool-independent bugs agree everywhere; X and initial-state bugs split the simulators.
Rule of thumb: never diff two runs until you can say, in one sentence, every way they are supposed to differ.
When the Bug Is in the Test
A FAIL is a disagreement. The spec, not the design and not the bench, decides which side is wrong.
Ask where the expected value came from. A checker that records its own reasoning answers that in one line.
After fixing a checker, prove it still fails on a design with a real bug. A checker that passes everything is the worst bench bug of all.
Rule of thumb: never change an expected value until you can quote the line of the spec that says the old one was wrong.
The Localisation Checklist
Localise is finished when you can name one signal, one cycle and one module where the values first go wrong, and the checker is cleared.
Cheap references first: the commit before, the other simulator, the other configuration. Each takes a minute and can cut the search to one change or one class of bug.
Walk the cone from the first wrong value, pruned by values, and check the checker before you blame the design.
Rule of thumb: do not start Hypothesise until you can write the first wrong signal, cycle and module in one sentence.
Practice question: Counter with wrap and saturate modes
Practice question: Design a simple DMA controller
Code lab: DMA control FSM
Practice question: Inline RTL checkers: X/Z detection, liveness and bindable monitors
Code lab: Isolation cell model
Interview: run a mock interview on this topic