Wishbone · Module 5
Handshake Rules
The handshake obligations gathered by engineering responsibility, with every specification requirement separated from the design decisions that merely look like one, plus a full debug checklist.
Seven chapters have introduced rules where they were needed. This one gathers them, organised by who is responsible rather than by rule number, and draws the line that matters most in practice.
Which handshake obligations are Wishbone rules, which are good local policy, and how do you tell them apart?
1. Master Initiation
| # | Obligation | Status |
|---|---|---|
| M1 | CYC_O asserted no later than the edge qualifying STB_O | RULE 3.25 |
| M2 | ADR_O, DAT_O, SEL_O, WE_O, tags qualified by STB_O | RULE 3.60 |
| M3 | STB_O and CYC_O may share one signal if no wait states | PERMISSION 3.40 |
| M4 | CYC_O may be asserted before a transfer is presented | RULE 3.25 ("no later than") |
| M5 | Request metadata latched at acceptance | local policy |
| M6 | One outstanding transaction; no accept while busy | local policy |
| M7 | Acceptance exposed as an explicit signal | local policy |
M2 is the one that bites. Qualified by means meaningful for as long as the strobe is asserted, which across a multi-cycle presentation means held still. Chapter 5.5 measured a master violating it for 3 of 4 cycles while reporting success.
M5 exists to make M2 achievable. The specification does not mention latching — it constrains the bus signals and leaves the mechanism alone. Latching is simply the only practical way to satisfy M2 against a client that may change its mind.
Assertion: stb_o |-> cyc_o (M1, spec) · (cyc_o && stb_o && !terminated) |=> $stable({adr_o, we_o, dat_o, sel_o}) (M2, spec) · acc_o |-> !busy_o (M6, policy).
2. Master Holding
| # | Obligation | Status |
|---|---|---|
| H1 | CYC_O asserted for the whole cycle | RULE 3.25 |
| H2 | A master with no wait states does not negate STB_O mid-cycle | OBSERVATION 3.55 |
| H3 | CYC_O may be asserted indefinitely | PERMISSION 3.05 |
| H4 | Holding CYC_O may cause arbitration problems | RECOMMENDATION 3.05 |
| H5 | No protocol-level way to abandon an outstanding transfer | engineering consequence |
H3 and H4 together are the specification's clearest example of "legal but inadvisable". Holding CYC_O breaks no rule and starves a shared bus, and because Wishbone deliberately leaves arbitration policy to the integrator, a recommendation is the strongest instrument available.
H5 is a consequence, not a rule. Nothing forbids negating CYC_O early — but Chapter 5.2 showed what happens: RULE 3.30 stops the slave responding, no termination ever arrives, and if the slave had begun a side effect nobody learns whether it completed.
Assertion: (cyc_o && stb_o && !terminated) |=> cyc_o (H1, spec).
3. Slave Response
| # | Obligation | Status |
|---|---|---|
| S1 | May not respond to slave signals while CYC_I is negated | RULE 3.30 |
| S2 | Terminations generated from the AND of CYC_I and STB_I | RULE 3.35 |
| S3 | STB_I is only valid when CYC_I is valid | OBSERVATION 3.25 |
| S4 | ACK_O may be tied to STB_I & CYC_I — if it keeps pace and no ERR/RTY | PERMISSION 3.10 |
| S5 | Other signals may participate in generating terminations | PERMISSION 3.15 |
| S6 | Termination assertion may be combinational from STB_I | PERMISSION 3.30 |
| S7 | A slave may hold ACK_O asserted | PERMISSION 3.35 |
| S8 | Side effects occur once per accepted transfer, not per presented cycle | design obligation |
| S9 | Every qualified transfer receives a termination | engineering consequence of DESC STB_O |
S4's two preconditions are routinely misquoted. The slave must keep pace and not use ERR_O/RTY_O. A slave with an error output is covered by S5, not S4.
S8 is the trap of this module. Chapter 5.3 measured a conformant bus — one transfer, one termination, zero trace differences — with four register updates instead of one. No specification rule was broken, because Wishbone does not know what side effects a slave has.
S9 comes from the STB_O signal description — "The SLAVE asserts either the [ACK_I], [ERR_I] or [RTY_I] signals in response to every assertion of the [STB_O] signal" — rather than from a numbered rule. It is why silence is never an acceptable answer.
Assertion: ack_o |-> (cyc_i && stb_i) (S2, spec) · $changed(state) |-> $past(ack_o && we_i) (S8, design obligation, needs white-box access).
4. Termination
| # | Obligation | Status |
|---|---|---|
| T1 | At most one of ACK_O/ERR_O/RTY_O at a time | RULE 3.45 |
| T2 | Terminations asserted and negated in response to STB_I | RULE 3.50 |
| T3 | Slaves automatically negate terminations when STB_I negates | OBSERVATION 3.10 |
| T4 | A master must operate normally when a slave holds ACK_I asserted | RULE 3.55 |
| T5 | A slave qualifies its DAT_O with its termination | RULE 3.65 |
| T6 | A master captures read data at the termination edge | design obligation from T5 |
| T7 | No capture on ERR_I or RTY_I | design obligation |
| T8 | One bus termination produces one local completion | local policy |
T4 is the rule most masters are written without reading, and it is unusual: it constrains a master's design rather than any wire. Chapter 5.4 measured an edge-detecting master counting 1 transfer where a level-sampling one counted 3, from a single rising edge.
T5 is specification; T6 is not. The rule constrains the slave. What the master does with that window is the master's design — which is why Chapter 5.6 labels its capture property a design obligation despite resting on a real rule number.
Assertion: $onehot0({ack_o, err_o, rty_o}) (T1, spec) · !stb_i |-> !ack_o (T2, spec) · (cyc_i && stb_i && ack_o) |-> m_progress (T4, spec, needs white-box access) · $changed(rdat_q) |-> $past(cyc_o && stb_o && ack_i && !we_o) (T6, design obligation).
5. Reset
| # | Obligation | Status |
|---|---|---|
| R1 | Initialise at the rising edge following RST_I assertion | RULE 3.00 |
| R2 | RST_I asserted at least one full clock cycle | RULE 3.05 |
| R3 | STB_O and CYC_O negated at that edge and held negated | RULE 3.20 |
| R4 | Interfaces must react to RST_I at any time | RULE 3.10 |
| R5 | STB_O/CYC_O may assert from the edge following RST_I negation | OBSERVATION 3.05 |
| R6 | Slaves must always respond to SYSCON signals | RULE 3.30 |
| R7 | Asynchronous reset is a non-Wishbone signal | SUGGESTION 3.00 |
R3 is why every master in Modules 4 and 5 clears its state flag on reset rather than assigning the outputs directly — the flag drives both qualifiers, so clearing it satisfies R3 through the encoding. A reviewer checking R3 must trace that, which is worth a comment.
R6 is the one exception to slave gating. RST_I is not qualified by anything: Chapter 4.2's slave has its reset outside every qualification term.
6. Data Validity
| # | Obligation | Status |
|---|---|---|
| D1 | Master DAT_O qualified by STB_O — not by WE_O | RULE 3.60 |
| D2 | Slave DAT_O qualified by its termination | RULE 3.65 |
| D3 | SEL_O names where valid data is expected/placed | DESC SEL_O() |
| D4 | Data organisation follows the specification's tables | RULES 3.90, 3.100 |
| D5 | Unselected byte lanes untouched on a write | design obligation from D3 |
| D6 | A slave drives '0 when not producing read data | local policy |
D1's omission is deliberate and consequential. Because DAT_O is qualified by the strobe alone, a master may legally leave stale write data on the bus during a read — and Chapter 4.6 showed the slave bug that follows: a write path missing WE_I writes a register on every read, with the previous write's value.
D6 is policy, not a rule. D2 requires a slave to qualify its read data; driving zero otherwise is a convention that keeps a merged return path clean, and Chapter 4.7 noted a slave returning the full word is equally conformant.
7. Cycle and Transfer
| # | Obligation | Status |
|---|---|---|
| C1 | CYC_O spans SINGLE, BLOCK and RMW cycles | RULE 3.25 |
| C2 | CYC_O asserted first transfer through last | DESC CYC_O |
| C3 | CYC_O requests the bus from an arbiter | DESC CYC_O |
| C4 | Cycle and transfer coincide only for a single transfer | engineering consequence |
| C5 | Atomicity needs a held CYC_O, a compliant arbiter, and no back door | engineering consequence |
C5 is worth restating because it is a three-part claim and the specification supplies one part. Chapter 4.9 showed a read-modify-write losing an update with CYC_O held perfectly — because the slave had a second port.
8. The Handshake Invariants
Seven statements. If all hold, the handshake is legal.
I1. STB_O never asserted without CYC_O. (RULE 3.25)
I2. Everything STB_O qualifies is stable from presentation to termination. (RULE 3.60)
I3. A slave acts only on CYC_I & STB_I. (RULES 3.30, 3.35)
I4. At most one termination at a time. (RULE 3.45)
I5. Terminations negate when STB_I negates. (RULE 3.50)
I6. Read data is meaningful only in the termination cycle. (RULE 3.65)
I7. Every qualified transfer eventually receives a termination. (STB_O description)
All seven are checkable from the bus alone. A passive monitor implementing them catches every conformance failure in this module.
And it catches none of these, each measured in an earlier chapter:
| Failure | Bus status | Measured in |
|---|---|---|
| Side effect four times per transfer | fully legal | 5.3 |
Master stalls on a held ACK | fully legal | 5.4 |
| Lost read-modify-write update | fully legal | 4.9 |
| Retry livelock | fully legal | 4.12 |
That table is the most important thing in this chapter. Conformance is necessary, finite, and reusable. It is not sufficient, and the gap is not an oversight — it is the boundary of what a protocol specification can say.
9. Local Policies Worth Having
None of these is a Wishbone rule. All are worth adopting, and RULE 2.15 requires the ones affecting the interface to be documented.
One outstanding transaction, unless the architecture genuinely needs more.
Explicit acceptance signalling. Chapter 5.5 §9 argued that an inferred boundary is maintained in two places.
Side effects gated on the termination, always — even when it is redundant. Chapter 5.7 §11 showed why: registering an acknowledge for timing reasons turns the redundant term into the only defence, and nobody re-reviews the slave for a timing change.
Distinct ERR and RTY handling. Merging them discards the one bit of information the third wire exists to carry.
Deterministic inactive outputs. Driving '0 when not responding keeps a merged return path clean.
Bounded completion, as a system policy — and the specification says where to put it:
RECOMMENDATION 3.10 — "Design INTERCON modules to prevent deadlock conditions. One solution to this problem is to include a watchdog timer function that monitors the MASTER's [STB_O] signal."
Note where it goes: the interconnect, not the master. A master cannot legally abandon a transfer — that is H5 — so a watchdog in the master would have nothing legal to do. A watchdog in the interconnect can terminate the transfer, turning a silent hang into a reported error with an address attached.
Registered outputs on the qualifiers, per RECOMMENDATION 3.15: no intermediate logic between a flop and STB_O/CYC_O.
10. Debug Checklist
Ordered so each step eliminates the largest number of candidates.
Symptom: master hangs, no termination.
CYC_Oat the master. Negated whileSTB_Ois asserted? → RULE 3.25 duration violation. Check this first — the slave is innocent and its waveform looks identical to three other causes.CYC_I/STB_Iat the intended slave. Absent? → decode or forward routing.ACK_Oat that slave. Absent? → the slave has an unterminated path, usually an unhandleddefault.ACK_Iat the master. Present at the slave, absent here? → return path, or the master does not implement the termination the slave produced. OBSERVATION 3.35 names that case.- Is
ACK_Ihigh while the master sits still? → not a hang. RULE 3.55 violation; the master is edge-detecting.
Symptom: wrong read data.
- Slave's
DAT_Oin the acknowledged cycle correct? No → RULE 3.65 violation in the slave. - Correct there, wrong at the master? → capture edge. Every read returning the previous value is diagnostic.
- All reads return zero, address-independent? → capture one cycle late in a quiet system (5.6 measured exactly this).
- Data register changed on an errored read? → capture gated on
terminatedrather thanack_i.
Symptom: side effect happens too many times.
- Count side effects against wait length, not transfer count. Equal to the presented duration → gated on presented, not accepted.
- Did someone recently register the acknowledge for timing? → that change made a redundant term load-bearing.
- Idempotent state only? → look at counters and FIFOs; the bug hides in registers.
Symptom: works alone, fails under arbitration.
cyc_iat the slave when it misbehaves. Low whilestb_ihigh → RULE 3.30 violation in the slave.- Competing access visible on the bus? Yes → arbiter granted during an open cycle. No → back-door port.
Symptom: closes function, fails timing.
- Read the critical path, not the slack. Master flop → decode → slave → merge → master flop is the OBSERVATION 3.50 loopback.
- Register the termination, or cut the loop once with a hierarchical bridge. Do not register every slave reflexively.
11. Interview Reasoning
Find the sentence it comes from, and check which side of the interface that sentence constrains.
If it is a numbered RULE constraining the thing you are checking, it is conformance. ack_o |-> (cyc_i && stb_i) is RULE 3.35 restated, applies to every Wishbone slave ever built, and a failure means non-conformant.
If it is an inference from a rule about the other side, it is a design obligation. RULE 3.65 says a slave qualifies its DAT_O with its termination. That the master must capture there follows soundly — but the specification never says it, because what a master does with a valid-data window is the master's design.
If there is no sentence at all, it is local policy. "One outstanding transaction", "report completion once", "abandon a block on error" — real obligations, none of them Wishbone's.
Three reasons I would not treat this as pedantry.
It decides what a failure means. Conformance failure: the interface cannot ship and will break against some partner. Policy failure: this design disagrees with its own datasheet — or the datasheet changed and the property is stale and should be deleted.
It decides what you may demand of someone else's IP. You can reject a slave that drives read data outside its termination; that violates RULE 3.65 and corrupts a merged return path. You cannot reject a master for capturing differently, as long as it works.
It stops you inventing rules. Writing "RULE 3.65 requires the master to capture at the termination edge" would be a normative claim the specification does not make. That exact failure — a plausible rule number attached to a statement it does not support — is the one that survives review, because a citation looks like evidence.
The check I actually run. Before writing a property, name the rule and quote it. If quoting it does not produce the property, it is an inference or a policy, and it gets labelled as such in the comment. That labelling is what tells the next engineer whether a failing assertion means "fix the design" or "update the property".
12. Understanding Check
13. What's Next
Module 5 is complete. The handshake is no longer three signal definitions but a timed contract: a cycle that frames, a strobe that presents and persists, a termination that answers once and is sampled as a level — with a clear line between what Wishbone requires and what a design decides.
| Chapter | Owns |
|---|---|
| 5.1 | the whole conversation, and the four-probe debug path |
| 5.2 | cycle framing; the early-drop failure |
| 5.3 | presented vs accepted; the repeated side effect |
| 5.4 | level vs edge; RULE 3.55 |
| 5.5 | the acceptance boundary and metadata capture |
| 5.6 | the termination edge's four obligations |
| 5.7 | intervals, the loopback, correctness vs closure |
| 5.8 | the rules, sorted by responsibility (this chapter) |
Every transfer so far has been a vehicle for the handshake. The next module stops using reads as examples and makes one its subject — the address phase, how a slave produces returned data, when it generates its acknowledge, and how wait states appear in a real read waveform.
What happens, end to end, in a single Wishbone read cycle?
Module 6 — Read Transactions answers it, beginning with Read Cycle Flow. The full path is on the Wishbone curriculum index.
Continue learning
Related tutorials
- 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.
- 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
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.
- Related topic
Transaction Extension
Stretching a transfer from one clock to six changes its duration and nothing else. A measured matrix: same transfers, same terminations, same value, same single side effect.
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.
