Wishbone · Module 23
Slave Design
A master may be slow; a slave must assert AND negate its termination in response to STB_I. Two broken slaves were built, and both came back clean until the testbench was allowed to break RULE 3.25 itself.
Chapter 23.1 built the master and found that B3 constrains it loosely: a master may take as long as it likes to issue, and the specification never says how fast it must be.
The slave has no such latitude. Read its rules together and a pattern appears that the master's do not have — the slave is told what it must do and, just as firmly, what it must stop doing.
RULE 3.50: SLAVE interfaces MUST be designed so that the
[ACK_O],[ERR_O], and[RTY_O]signals are asserted and negated in response to the assertion and negation of[STB_I].
Four words do the work there: and negated. A slave that raises [ACK_O] correctly and then forgets to lower it has broken the specification just as surely as one that never raises it, and the failure is far harder to see.
1. The Slave's Minimum Port List
RULE 3.40 again, the other half:
"...As a minimum, the SLAVE interface MUST include the following signals:
[ACK_O],[CLK_I],[CYC_I],[STB_I], and[RST_I]. All other signals are optional."
"All other signals are optional" is not padding. It means [ERR_O] and [RTY_O] are optional, [DAT_O()] is optional, and [ADR_I] is optional — a single-register peripheral that is selected by the interconnect and has exactly one thing to say needs no address input at all. Chapter 23.5 is where those unused address bits get decoded on the slave's behalf, and B3 says so directly in its Partial Address Decoding section:
"each SLAVE decodes only the range of addresses that it requires... The remaining address bits are decoded by the interconnection system."
2. The Gate, And The Version Everybody Writes First
Here is the first mistake, and it is so natural that it survives review:
// ─── DO NOT SHIP THIS ───────────────────────────────────────────────
// "STB_I means the master wants me. Respond to it."
assign ack_o = stb_i; // <-- RULE 3.30 VIOLATIONIt reads correctly. [STB_I] is the strobe; responding to the strobe is the job. And it is wrong, because RULE 3.30 says:
"SLAVE interfaces MAY NOT respond to any SLAVE signals when
[CYC_I]is negated."
OBSERVATION 3.25 then explains why the two are one mechanism rather than two:
"SLAVE interfaces assert a cycle termination signal in response to
[STB_I]. However,[STB_I]is only valid when[CYC_I]is valid."
So the correct gate is the AND, applied once, with everything downstream forbidden to look at anything else:
// RULE 3.30 gate. selected is the ONLY thing downstream may look at.
// NO_CYC_GATE removes cyc_i and is a violation, not a design option.
logic selected;
assign selected = NO_CYC_GATE ? stb_i : (cyc_i && stb_i);Why does the broken version survive review? Because in a single-master system with a conformant master it never misbehaves. A conformant master raises [CYC_O] no later than [STB_O] — RULE 3.25 — so [STB_I] without [CYC_I] simply never occurs on the wire. The bug is real, latent, and invisible until an interconnect, a second master, or a partially-decoded address puts a stray strobe in front of it. Section 7 shows exactly how much work it took to make it visible at all.
3. One-Hot Terminations, And A Priority That Is Yours
RULE 3.45 — "the SLAVE MUST NOT assert more than one of the following signals at any time: [ACK_O], [ERR_O] or [RTY_O]."
One-hot, always. So the slave must choose, and B3 does not tell you how:
// ── the one-hot termination choice, RULE 3.45 ──
// Priority is explicit and is a LOCAL POLICY: retry outranks error
// outranks acknowledge, because a busy slave has not yet decided
// whether the access would have failed.
logic want_rty, want_err, want_ack;
assign want_rty = selected && waited && force_rty_i;
assign want_err = selected && waited && !force_rty_i && force_err_i;
assign want_ack = selected && waited && !force_rty_i && !force_err_i;RTY over ERR is a local policy and the comment says so. The reasoning is defensible — a slave that is too busy to look has not yet determined whether the access would have failed — but a design that reports the error first is equally conformant. RULE 2.00's datasheet is where you tell an integrator which one you built.
The slave's own readiness is allowed to participate, and PERMISSION 3.15 is the licence:
// the slave's own readiness. PERMISSION 3.15 explicitly allows internal
// state to participate: "Other signals, besides [CYC_I] and [STB_I],
// MAY be included in the generation of the cycle termination signals."
logic waited;
assign waited = held_q >= WAITS[7:0];4. The Combinational Answer, Stated With Both Halves
A slave may answer on the same clock it is asked. PERMISSION 3.10 allows the simplest possible form:
"If the SLAVE guarantees it can keep pace with all MASTER interfaces and if the
[ERR_I]and[RTY_I]signals are not used, then the SLAVE's[ACK_O]signal MAY be tied to the logical AND of the SLAVE's[STB_I]and[CYC_I]inputs."
PERMISSION 3.30 names the path this creates, in the specification's own words:
"The assertion of
[ACK_O],[ERR_O], and[RTY_O]MAY be asynchronous to the[CLK_I]signal (i.e. there is a combinatorial logic path between[STB_I]and[ACK_O])."
OBSERVATION 3.40 states the benefit:
"The asynchronous assertion of
[ACK_O],[ERR_O], and[RTY_O]assures that the interface can accomplish one data transfer per clock cycle. Furthermore, it simplifies the design of arbiters..."
And B3 §4.1 states the cost of the same path, four paragraphs later in the same document:
"...this results in an asynchronous loop from the MASTER, through the INTERCONN to the SLAVE, and then from the SLAVE through the INTERCONN back to the MASTER... In large System-on-Chip devices this routing delay between MASTER and SLAVE is the dominant timing factor."
These are not competing opinions. They are one path described twice — once as a feature, once as a hazard — and any chapter that publishes a one-clock result while quoting only the first half is selling you something.
The slave therefore offers both, as a parameter, with the trade written into the comment:
// REG_ACK = 0 : combinational, one-clock transfer (PERMISSION 3.30)
// REG_ACK = 1 : registered, the loop is cut, one wait state appears
//
// RULE 3.50 requires the termination to be negated in response to
// [STB_I] falling. The `selected &&` on the registered path is that
// obligation; HOLD_ACK removes it.
assign ack_o = REG_ACK ? (HOLD_ACK ? ack_q : (ack_q && selected))
: want_ack;REG_ACK = 0 | REG_ACK = 1 | |
|---|---|---|
| clocks per transfer | 1 | 2 |
[STB_I] → [ACK_O] path | combinational, crosses the interconnect twice | cut at a flop |
| authority for it | PERMISSION 3.10, 3.30; OBSERVATION 3.40 | — (always legal) |
| the hazard | B3 §4.1, "dominant timing factor" | none |
| where it breaks | a large SoC at high frequency | a latency-sensitive core |
Neither column is the right answer. The measurement that decides between them is synthesis, and this chapter cannot run it.
5. The Negation Obligation, Which Is Where Slaves Actually Break
On the registered path, look closely at what selected && is doing:
assign ack_o = REG_ACK ? (HOLD_ACK ? ack_q : (ack_q && selected))ack_q is the slave's decision, made one clock ahead. selected is RULE 3.50 enforced in a single term. The instant [STB_I] falls, selected falls, and [ACK_O] falls with it — in response to the negation of [STB_I], exactly as the rule words it.
HOLD_ACK deletes that term. The slave then keeps [ACK_O] asserted into the next clock on its own schedule.
This is not a hypothetical defect. It is the bug Chapter 22.5 found in a published block-transfer timing scheme, where a slave held [ACK_O] across beats and the measured cost came out at N+1 clocks where B3's own Table 4-1 predicts 2N. The same defect, reproduced here as a parameter so it can be pointed at.
6. PERMISSION 4.15 Contradicts RULE 3.50 — Until You Read The Scope
Chapter 4 of B3 says something that looks like a flat contradiction:
PERMISSION 4.15: "In addition to the WISHBONE Classic rules for generating cycle termination signals
[ACK_O],[RTY_O], and[ERR_O], a SLAVE MAY assert a termination cycle without checking the[STB_I]signal."
RULE 3.50 says the termination answers [STB_I]. PERMISSION 4.15 says a slave need not check [STB_I]. Both are in the same document.
The resolution is scope: RULE 3.50 governs Classic cycles; PERMISSION 4.15 governs registered-feedback cycles, and RULE 4.15 supplies the bound that makes the relaxation safe:
"A cycle terminates when both the cycle termination signal and
[STB_I],[STB_O]is asserted. Even if[ACK_O],[ACK_I]is asserted, the other signals are only valid when[STB_O],[STB_I]is also asserted."
OBSERVATION 4.00 says why the relaxation is needed at all: to remove the inherent wait state, the slave must answer before it can know the strobe is still there.
A slave written to one scope and deployed under the other is a genuine defect, and nothing on the wire announces it. The conformance monitor in this module is a Classic monitor and says so in its header, because pointing it at a CTI-capable slave would report violations that are not violations.
7. Breaking It On Purpose — And Failing To
Here is the part that matters more than the RTL.
Two broken slaves were built: NO_CYC_GATE (responds to [STB_I] alone) and HOLD_ACK (never negates). The conformance monitor was attached. A correct master drove all three rigs with an identical workload.
Every rig came back clean. Zero violations, on the broken ones as well as the correct one.
The checker was not broken. The stimulus could not pose the question. A conformant master never asserts [STB_O] without [CYC_O] — RULE 3.25 forbids it — so NO_CYC_GATE was never offered a strobe outside a cycle and behaved identically to a correct slave. The defect was real, present, and unobservable.
The fix was to stop using a master. The testbench drives the wires directly and breaks RULE 3.25 itself, deliberately:
rig STBnoCYC TERMnoREQ MULTI CTXmoved TERMheld
correct 3 0 0 0 0
NO_CYC_GATE 3 3 0 0 0
HOLD_ACK 3 1 0 0 1Read column 1 first, because it looks like a failure and is not. STBnoCYC is 3 on every rig, the correct one included. RULE 3.25 constrains [CYC_O] and [STB_O] — signals a slave never drives. That column is reporting on the stimulus, identically for all three rigs, and it has to be non-zero or the other columns would all be zero too.
The columns that separate the rigs are TERMnoREQ and TERMheld:
NO_CYC_GATEanswered 3 strobes that had no cycle open. That is RULE 3.30 violated three times.HOLD_ACKheld its termination past the strobe once. That is RULE 3.50.- The correct slave scored zero on both.
A checker firing is not always a bug in the DUT, and a checker staying silent is not always a clean DUT. Both of those sentences cost this module a testbench rewrite to learn.
8. Where This Slave Stops
This is a skeleton, and the boundary is deliberate. Module 24 is five chapters on slave design; this chapter would be stealing from it if it went further.
| 23.2 builds | Module 24 builds |
|---|---|
| the port list, from RULE 3.40 | the register map |
the [CYC_I]/[STB_I] gate, from RULE 3.30 | the read datapath |
| the one-hot termination choice, from RULE 3.45 | the write datapath |
| wait-state generation, under PERMISSION 3.15 | [ACK_O] timing in depth |
| the negate obligation, from RULE 3.50 | [ERR_O] / [RTY_O] policy in depth |
The datapath here is one scratch register with byte lanes — enough to prove the handshake moves data and no more:
// the datapath: one scratch register, per byte lane. Module 24
// replaces this with a real map.What this slave does not do, stated plainly: no burst or [CTI_I()] support; no address decoding (Chapter 23.5 owns it); no timeout (B3 has none); no register map (Module 24 owns it).
Next: Chapter 23.3 — Register Bank Design takes the skeleton and makes it a generator: four access policies expressed as a table parameter, so that adding a register is adding a row rather than editing three case statements.
Continue learning
Related tutorials
- Related topic
Wishbone Architecture Overview
Wishbone names four architectural roles and defines only two of them as interfaces. A MASTER generates bus cycles, a SLAVE receives them, an INTERCON connects them and a SYSCON drives clock and reset — and the specification deliberately standardises the endpoint interfaces while leaving the fabric between them to the integrator.
- Related topic
The Slave Interface
A Wishbone slave never initiates. It observes a qualified request, interprets a local offset, and ends the transfer with exactly one of three terminations. Everything that makes it reusable comes from what it refuses to know: its own base address, the topology, and which master is asking.
- Related topic
CPU to Peripheral Communication
A CPU reaches hardware outside itself by reading and writing addressed locations, and a peripheral is hardware it cannot execute. Everything a driver does has to be expressed as a read or a write of a location the peripheral answers for — and once more than a couple of peripherals exist, wiring each one to the core separately stops scaling. That is the problem an on-chip bus is the answer to.
- Related topic
Need for Standardized Interconnects
An address map answers where a register lives. It says nothing about which wires carry the request, when they are valid, how the target reports completion, or what happens on an error. Three peripherals with three private interfaces produce three adapters, three verification efforts and three ways to be wrong — which is the argument for standardising the interface rather than the map.
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.
