Wishbone · Module 7
Waveform Analysis
A ten-step method for reading an unfamiliar Wishbone write off a waveform, applied to five traces — and the one question a bus trace can never answer about a write.
Chapter 6.6 built a nine-step method for reading a Wishbone read off a trace. A write needs one more step, and it is the one the bus cannot help with.
How do you read an arbitrary Wishbone write off a waveform, and localise a failure from evidence alone?
1. The Ten-Step Method
| # | Question | Look at | What a wrong answer means |
|---|---|---|---|
| 1 | Is there a bus cycle? | CYC_O | no cycle → master state machine |
| 2 | Is a transfer presented? | STB_O within CYC_O | strobe outside a cycle → RULE 3.25 violation |
| 3 | Is it a write? | WE_O asserted | negated → this is a read; wrong chapter |
| 4 | Which register? | ADR_O only while qualified | 4× expected → byte/word confusion |
| 5 | What value? | DAT_O only while qualified | differs from the request → master capture |
| 6 | Which byte lanes? | SEL_O | all-zero → legal, commits nothing |
| 7 | Which target? | slave select / per-slave STB_I | none → unmapped; two → decode fault |
| 8 | When should it commit? | the slave's declared policy | not on the bus — read the datasheet |
| 9 | How did it end? | ACK_I / ERR_I / RTY_I | none → hang; ERR → legally refused |
| 10 | Did it release? | CYC_O/STB_O negate; one done | no release → master completion logic |
Steps 4, 5 and 6 are the write triple — Chapter 7.2 §1 showed each produces a distinguishable symptom, so checking them in order separates three faults that all present as "the register is wrong".
Step 9 comes late deliberately. On a read the termination gates the data, so it had to come before inspecting DAT_I. On a write the payload is the master's and is valid from the first cycle, so the termination only tells you when it ended — and checking it early tempts you to stop at "it acknowledged, so it worked".
2. Trace A — A Correct Write
Trace A: a correct delayed write
8 cyclesWalking the method:
1–3. CYC_O asserted cycles 2–4; STB_O across the same interval; WE_O asserted throughout and never changing. A write, and it stayed a write.
4–6. ADR_O reads 0x2 in all three qualified cycles, DAT_O reads 0x0000000F, SEL_O reads 1111. One value each, no drift — RULE 3.60 and §3.2.2 satisfied.
7. One target selected for exactly the presented interval.
8. The slave's declared policy — commit on the edge it returns ACK_O — puts the commit at the edge ending cycle 4.
9. ACK_I in cycle 4 only. Cycles 2 and 3 are wait states.
10. Both qualifiers negate in cycle 5, one done pulse, CONTROL reads 0x0000000F.
Every step consistent. Note that CONTROL changes after edge 4 — the flop loaded at that edge, so the new value is visible from cycle 5. Reading it as "CONTROL changed in cycle 5" is the before/at/after confusion this course has been careful about: it changed at edge 4 and is observable in cycle 5.
3. Trace B — The Payload Drifted
Trace B: payload instability
7 cyclesSteps 1–3 pass. Steps 7 through 10 also pass — one clean termination, one commit, a proper release.
Steps 4 and 5 fail together, and that pairing is itself information: an address that drifts alone is one bug, an address and data drifting together is a master that lost its whole payload copy.
CONTROL was never written; OUTPUT_DATA holds a value nobody requested. The master reported success.
Two master faults produce this, and the trace alone does not separate them — Chapter 7.3 §5 showed the discriminator is the slave's remembered offset, not anything on the bus:
| Remembered | Committed | Fault |
|---|---|---|
| wrong | same as remembered | the master never latched |
| right | different | the slave committed from the bus |
And a third possibility the trace does distinguish: if ADR_O tracks the client's current request input, the master is unlatched; if it diverges from both the client and the original request, the master latched and then rewrote.
4. Trace C — The Mask Was Ignored
Trace C: SEL ignored
6 cyclesAll ten steps pass. The payload is stable, SEL_O is driven and meaningful, the termination is single and clean, the release is proper.
And three bytes that the transfer never named are gone. 0x11, 0x22 and 0x44 were valid state; only lane 1 was selected.
The tell is in the committed value itself. CONTROL became exactly DAT_O. A correct masked write can never produce that unless SEL_O was 1111 — so SEL_O = 0010 with CONTROL == DAT_O is conclusive without any internal probe.
That is unusual and worth noticing, because it is one of the few write faults the bus trace does settle. Chapter 7.2 §6 measured zero trace differences between this slave and a correct one — but that was comparing two traces; here the single trace plus the committed value is enough.
5. Trace D — The Command Fired Four Times
Trace D: repeated side effect
9 cyclesSteps 1–7 pass and steps 9–10 pass. One transfer, one termination, a stable payload, a clean release.
Step 8 is the failure, and it is visible here only because cmd_pulse and launches are in the trace. Neither is a Wishbone signal.
Remove those two rows and this trace is indistinguishable from Trace A with a different address. That is the point: Chapter 7.4 §5 measured byte-identical bus traces between a correct slave and this one.
The two evidence patterns to recognise:
The launch count tracks the wait length, not the number of writes. Four launches for a three-wait write; two for a one-wait write. Correlation with latency rather than traffic is unique to this bug.
The pulse is four cycles wide instead of one. A downstream block that edge-detects sees one launch and masks the bug entirely; a level-sensitive one sees a long assertion. That divergence between consumers is itself diagnostic, and it explains why the same RTL can appear fine in one integration and fail in another.
6. Trace E — Refused, Not Failed
Trace E: a legal refusal
6 cyclesStep 9 is where this trace differs from every other, and reading it as a failure is the mistake.
STATUS is read-only. The slave refused the write with ERR_O and committed nothing — and the same term that produced the refusal also blocked the commit, so they cannot disagree.
This is the trace that catches a client bug, not a hardware one. A client that ignores its status output sees a completed transfer and a register that did not change — indistinguishable, from the client's side, from Trace C or D.
RULE 3.45 keeps ACK_O and ERR_O mutually exclusive, so the evidence is unambiguous once you look. Step 9 says check which one, not whether either arrived.
7. The Decision Tree
The rightmost branch is where a write differs most from a read. On a read, "all steps pass and the value is wrong" left four candidates (Chapter 6.6 §5). On a write it leaves two — the byte mask or the register decode — because Trace C showed the mask fault is often settled by the committed value alone.
What to add to the trace when the bus view is exhausted, in order of usefulness: the slave's commit term, its local offset, the per-slave select vector, any side-effect counter, and — for a registered slave — its remembered payload. Those five resolve every failure in Module 7.
8. Failure Modes and Discriminating Evidence
Symptom: the write completes and the register did not change.
Candidate causes. A legal refusal; an all-zero SEL_O; a commit that never fired; a write to the wrong register that changed a different one.
Discriminating evidence. Check ERR_I first — it is one signal and it eliminates the commonest non-bug. Then SEL_O. Then whether any register changed at all; if one did, this is a wrong-address fault wearing a different symptom.
Symptom: a register the software never addressed changed.
Candidate causes. A drifting payload, or a decode fault.
Discriminating evidence. ADR_O across the whole strobe assertion. Stable and wrong means decode; changing means the payload drifted, and then Chapter 7.3's remembered-offset comparison separates master from slave.
Symptom: bytes the write never named changed.
Candidate causes. The commit ignores SEL_I.
Discriminating evidence. CONTROL == DAT_O with SEL_O != 1111 is conclusive from the bus trace alone, which is unusual for a write fault.
Symptom: an operation starts more times than software asked.
Candidate causes. The commit is gated on presentation.
Discriminating evidence. Count side effects against the wait length. Correlation with latency rather than traffic is unique to this bug, and the pulse width is a second, independent tell.
Symptom: the write hangs.
Candidate causes. Decode selected nobody; the slave has an unterminated path; the return path drops it; the master lacks the termination input the slave produced.
Discriminating evidence. Chapter 6.1 §6's probe order applies unchanged — the forward and return paths are the same for both directions. OBSERVATION 3.35 names the last case.
Symptom: works at zero wait states, breaks with latency.
Candidate causes. Either master bug from Trace B, or the commit gating from Trace D. All three are structurally invisible at zero latency.
Discriminating evidence. Re-run with LAT > 0. If the fault only appears then, it is one of those three — and whether the payload drifted separates the master bugs from the slave one.
9. What a Write Waveform Cannot Tell You
Worth stating plainly, because the method's value depends on knowing its edge.
A bus trace can establish: that the protocol was obeyed; which register was addressed; what value and which lanes were presented; whether the payload held still; how the transfer ended.
A bus trace cannot establish: when the slave actually committed; how many times it committed; whether a side effect fired once; whether the bytes that changed are the bytes that should have.
Traces C and D are the two halves. C is fully conformant and destroyed neighbouring state — though its committed value happens to betray it. D is fully conformant and shows nothing at all without two non-bus signals.
This is the same boundary the whole course has been mapping — Chapter 5.8 §8 collected it, and Modules 6 and 7 added four more instances. Conformance is necessary, finite, and not sufficient.
And on a write the consequence is worse. A read fault returns a wrong answer that a re-read corrects. A write fault has already replaced state that no longer exists anywhere.
10. Common Mistakes
"ACK arrived, so the write worked."
Wrong mental model: protocol completion equals architectural success.
Concrete bug: Traces B, C and D all acknowledge normally.
Observable evidence: a clean trace and a device in the wrong state.
Correct model: ACK_O proves the transfer ended. Step 9 is the ninth step for a reason — it says when, not whether it worked.
"The register did not change, so the write failed."
Wrong mental model: an unchanged register means a fault.
Concrete bug: Trace E — a correct refusal of a read-only register, or a legal all-zero SEL_O.
Observable evidence: ERR_I asserted, which a client ignoring its status never sees.
Correct model: check which termination arrived before concluding anything.
"Read DAT_O to see what was written."
Wrong mental model: the data bus always says the data.
Concrete bug: reading DAT_O from an unqualified cycle and diagnosing the wrong value.
Observable evidence: a value that matches neither the request nor the committed state — because it is residue.
Correct model: RULE 3.60 makes DAT_O meaningful only under STB_O. Steps 4, 5 and 6 all say while qualified for this reason.
11. Interview Reasoning
Ten questions in a fixed order, and I stop at the first one whose answer does not make sense.
Is there a cycle, is a transfer presented inside it, and is it a write? CYC_O, STB_O within it, then WE_O asserted — and asserted for the whole presented interval, because a direction that flips mid-transfer means RULE 3.60's stability was broken.
What is the triple — address, data, byte lanes — and did any of it move? All three read only in qualified cycles; outside them they are residue. An address four times too large is a byte/word confusion. And I check all three even if only one looks wrong, because which ones drifted together tells me whether the master lost one register or its whole payload copy.
Which target? Per-slave STB_I or the select vector. None means unmapped; two means a decode fault.
When should this slave have committed? This is the step with no read equivalent, and the answer is not on the bus — it comes from the slave's declared policy. A slave that commits on the edge it acknowledges and one that commits a cycle earlier are both legal, and "the register changed at the wrong time" is unanswerable without knowing which.
How did it end? One of ACK_I, ERR_I, RTY_I. ERR is not a failure to diagnose — it may be a correct refusal of a read-only register, and a client that ignores status cannot tell that from a silent fault.
Did it release cleanly, with one completion?
What I am driving at is not "I recognise this bug" but "the method stopped at step N, so open that stage". And if all ten pass and the state is still wrong, that is itself the finding — the bus has told me everything it can, and the rest is the byte mask or the register decode inside the slave.
The one shortcut worth knowing. If the committed value equals DAT_O exactly while SEL_O was not all-ones, the slave ignored the mask. That is the rare write fault the bus trace settles on its own.
12. Understanding Check
13. Module 7 Complete
A Wishbone write is now fully traced, implemented, verified and diagnosable.
| Chapter | Owns |
|---|---|
| 7.1 | the nine-stage path; the ownership reversal; the declared commit policy |
| 7.2 | the payload path; the byte-lane mask; what a narrow write must not destroy |
| 7.3 | termination versus commit; registered responses and lost context |
| 7.4 | payload coherence while waiting; one commit, however long it takes |
| 7.5 | the ten-step method; five traces; what a write trace cannot answer (this chapter) |
What Module 7 deliberately did not do. It used one basic write throughout and left the wider subjects alone: Module 8 owns the cycle taxonomy — including its own treatment of the single write cycle alongside block and read-modify-write — Module 9 wait-state generation and performance, Module 10 errors, Module 11 retry, Module 12 address decoding, Module 13 byte selects.
Modules 6 and 7 now hold the two primitives. A read asks and receives; a write carries and commits. Everything Wishbone does beyond this point is built from those two — held together under one CYC_O, repeated back to back, or combined into an indivisible pair.
How do the single read and the single write compose into Wishbone's full set of bus cycles?
Module 8 — Bus Cycles answers it. It has not shipped yet, which is why it appears in bold rather than as a link. The full path is on the Wishbone curriculum index.
Continue learning
Related tutorials
- Related topic
Waveform Analysis
A nine-step method for reading an unfamiliar Wishbone read off a waveform, applied to five traces where each failure is localised from evidence rather than recognised from memory.
- Related topic
Common Bugs
Seven measured wait-state failures and the observation that identifies each — including an off-by-one that is one clock wrong at three wait states and a permanent hang at zero.
- Related topic
Transaction Lifecycle
One Wishbone transaction from a master's decision to act through the slave's termination and back to the caller: what is fixed by the protocol, what every implementation may vary, and what a real simulation of the assembled system shows at each step.
- Related topic
Transaction Initiation
The boundary where a local client's request becomes a bus transaction, and why a master that does not latch its metadata produces transfers whose address changes mid-flight.
Standards & specifications
- Governing standard
- Wishbone SoC Interconnection Architecture (OpenCores)(opens OpenCores in a new tab)
Defines the Wishbone signal set, the bus cycles built from it and the interface rules a portable IP core must follow. It deliberately leaves interconnect topology, address map and arbitration policy to the integrator, so those are system decisions rather than requirements of the specification.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the Wishbone curriculum.
