Wishbone · Module 3
The Wishbone Mental Model
Wishbone is two levels, not one: a master opens a bus cycle and presents transfers inside it, and an addressed slave terminates each transfer with exactly one of three signals. That two-level structure is why describing Wishbone as valid/ready with renamed signals is wrong rather than merely imprecise.
Chapter 3.1 made the architecture drawable: two specified interfaces, two modules defined by their jobs, four named topologies. What it did not give is a way to reason about a transfer without consulting a signal table.
This chapter builds that model. It is short on signals and long on structure, because the structure is what makes the signals read as obvious when Module 4 arrives.
What compact mental model lets an engineer reason about a Wishbone transfer?
1. The Model, Stated Once
Four sentences, each of which maps to something the specification fixes.
One — a master opens a cycle. CYC_O asserted means a valid bus cycle is in progress, and RULE 3.25 requires the master to assert it for the duration of single, block and read-modify-write cycles: no later than the rising edge that qualifies STB_O, and negated no earlier than the edge that qualifies STB_O's negation.
Two — inside the cycle, the master presents transfers. STB_O indicates a valid data transfer and qualifies the other request signals. RULE 3.60 requires the master to qualify ADR_O, DAT_O, SEL_O, WE_O and the tag outputs with STB_O — meaning those signals are meaningful only while the strobe is asserted.
Three — exactly one addressed slave owns the response. Selection is the INTERCON's job, per Chapter 3.1. The selected slave is the only one that may terminate.
Four — the slave ends each transfer with exactly one of three signals. RULE 3.35 requires termination to be generated in response to the logical AND of CYC_I and STB_I. RULE 3.45 requires that a slave supporting ERR_O or RTY_O must never assert more than one of ACK_O, ERR_O or RTY_O at a time.
That is the model. Everything in Modules 4 through 7 is detail hung on those four sentences.
2. Mapping Module 2 Onto Wishbone
Module 2's teaching interface was built generically on purpose. Here is what maps cleanly and what does not.
| Module 2 generic | Wishbone Classic | Clean mapping? |
|---|---|---|
addr | ADR_O / ADR_I | Yes |
wdata | master DAT_O → slave DAT_I | Yes |
rdata | slave DAT_O → master DAT_I | Yes |
write | WE_O / WE_I | Yes |
byte_en | SEL_O / SEL_I | Yes, at this level |
valid | STB_O and CYC_O | No — one becomes two |
ready | ACK_O | No — one becomes three |
error | ERR_O | folded into termination |
| — | RTY_O | no Module 2 equivalent at all |
rst_n, async, active low | RST_I, synchronous, active high | No — opposite on both counts |
Five of the ten rows map cleanly and five do not, and the five that do not are where a reader coming from Module 2 will make mistakes. The address, the two data paths, the direction and the byte lanes are genuinely the same ideas with different names. The qualifiers, the termination and the reset are not.
RTY_O deserves a sentence because it has no generic counterpart. It is a termination meaning not now, ask again — distinct from success and from failure. Module 2's interface could not express it, and a design that treats it as an error or as a success is wrong in opposite directions. Module 11 owns retry; what matters here is that termination is a three-way choice.
3. Why This Is Not valid/ready With Renamed Signals
This is the misconception the chapter exists to kill, and it deserves a real argument rather than an assertion.
Difference 1 — there are two master-side qualifiers, and they are not redundant.
In a valid/ready interface, valid is one statement: I have a transfer for you now. Wishbone splits that into two signals that mean different things. CYC_O says I hold this interconnection. STB_O says I am presenting a transfer this cycle.
The combination CYC_O asserted with STB_O negated is legal and meaningful, and it has no valid/ready equivalent. It says: the master still owns the bus, and is not presenting a transfer right now. During a block cycle a master may insert such cycles between transfers without giving up its tenure.
Difference 2 — the cycle is the arbitration unit, and valid/ready has no arbitration unit.
An arbiter in a multi-master Wishbone system watches CYC_O, not STB_O. The cycle is precisely the interval during which ownership must not move — Chapter 2.6's grant-stability rule, now carried by a dedicated signal that the protocol defines. A valid/ready interface carries no such signal, so a system built on it must invent one, which is exactly the kind of unwritten rule Chapter 2.7 ended on.
Difference 3 — termination is a three-way choice, not a boolean.
ready is one bit meaning accepted. Wishbone's slave chooses among ACK_O, ERR_O and RTY_O, and RULE 3.45 makes them mutually exclusive. Success, failure and try again later are three architecturally distinct endings, and collapsing them loses information the master needs to act differently on each.
Difference 4 — and this is the sharpest one — Wishbone Classic has no independent readiness signal.
In valid/ready, ready is a capability statement. A target may assert ready while no valid is present, meaning I could take a transfer if you had one. The two signals are independent and the transfer happens where they coincide.
Wishbone Classic has nothing equivalent. RULE 3.35 requires termination to be generated in response to CYC_I and STB_I — a slave does not advertise readiness, it answers a qualified request. And in Classic there is no stall signal: the absence of a termination is how a slave makes the master wait.
4. RTL — The Smallest Complete Interaction
A master that performs one transfer, and a slave that answers it. This is the minimum RTL that exhibits the model in Section 1.
// ─────────────────────────────────────────────────────────────────────────
// wb_min_slave — the smallest conforming Wishbone Classic SLAVE.
//
// PURPOSE. Show the three architectural obligations of a slave in isolation:
// terminate only in response to a qualified request, drive read data, and
// own nothing else.
//
// Reset is SYNCHRONOUS, ACTIVE HIGH — RULE 2.30 (active-high logic) and
// RULE 3.00 (initialise at the rising CLK_I edge FOLLOWING assertion of
// RST_I). This is the opposite of Module 2's convention on both counts.
//
// SCOPE. This is architecture orientation. The full semantics of each
// signal are Module 4's, and the handshake's timing rules are Module 5's.
// ─────────────────────────────────────────────────────────────────────────
module wb_min_slave #(
parameter int unsigned AW = 8,
parameter int unsigned DW = 32
) (
input logic clk_i,
input logic rst_i, // synchronous, active high
input logic cyc_i, // master holds the interconnection
input logic stb_i, // this cycle carries a transfer
input logic we_i,
input logic [AW-1:0] adr_i, // LOCAL offset — not a system address
input logic [DW-1:0] dat_i, // write data, master → slave
output logic [DW-1:0] dat_o, // read data, slave → master
output logic ack_o
);
// ── The qualified-request term. RULE 3.35: termination signals must be
// generated in response to the logical AND of CYC_I and STB_I.
// Terminating on stb_i alone is the single most common conformance
// error in a hand-written slave, and it works in point-to-point.
logic xfer;
assign xfer = cyc_i & stb_i;
logic [DW-1:0] scratch_q;
// ── Sequential. Synchronous reset: the reset branch is INSIDE the
// clocked block with no reset in the sensitivity list.
always_ff @(posedge clk_i) begin
if (rst_i) begin
scratch_q <= '0;
end else if (xfer && we_i) begin
scratch_q <= dat_i;
end
end
// ── Combinational read path. Zero-extended, assigned on every path.
always_comb begin
dat_o = '0;
if (xfer && !we_i) dat_o = scratch_q;
end
// ── Termination. This slave is never busy, so it acknowledges in the
// cycle it is asked. A slave that needed longer would hold ACK_O low
// — in Classic there is no separate stall signal, so the ABSENCE of
// a termination is how a slave makes a master wait.
assign ack_o = xfer;
endmodule// ─────────────────────────────────────────────────────────────────────────
// wb_min_master — a MASTER that performs exactly one transfer on request.
//
// PURPOSE. Show the two-level model from the master's side: open a cycle,
// present a transfer inside it, hold both until a termination arrives,
// then close.
//
// SCOPE. Deliberately minimal — one transfer per cycle, no block cycles,
// no ERR/RTY handling. Chapter 3.3 builds a master that is useful; this one
// exists to make the model concrete in as few lines as possible.
// ─────────────────────────────────────────────────────────────────────────
module wb_min_master #(
parameter int unsigned AW = 8,
parameter int unsigned DW = 32
) (
input logic clk_i,
input logic rst_i, // synchronous, active high
// Local client side
input logic go_i, // start one transfer
input logic we_i,
input logic [AW-1:0] adr_i,
input logic [DW-1:0] wdat_i,
output logic [DW-1:0] rdat_o,
output logic done_o, // one-cycle pulse
// Wishbone MASTER interface
output logic cyc_o,
output logic stb_o,
output logic we_o,
output logic [AW-1:0] adr_o,
output logic [DW-1:0] dat_o,
input logic [DW-1:0] dat_i,
input logic ack_i
);
logic active_q;
logic we_q;
logic [AW-1:0] adr_q;
logic [DW-1:0] dat_q;
// ── Both qualifiers come from the same state bit here, because this
// master presents exactly one transfer per cycle. RULE 3.25 is
// satisfied trivially: CYC_O is asserted no later than the edge that
// qualifies STB_O, and negated no earlier.
//
// A master performing a BLOCK cycle would drive them separately —
// holding CYC_O across several transfers — which is the case that
// makes them visibly distinct signals. Module 8 owns block cycles.
assign cyc_o = active_q;
assign stb_o = active_q;
assign we_o = we_q;
assign adr_o = adr_q;
assign dat_o = dat_q;
always_ff @(posedge clk_i) begin
if (rst_i) begin
// RULE 3.20: STB_O and CYC_O must be negated at the rising CLK_I edge
// following assertion of RST_I. Clearing active_q does both.
active_q <= 1'b0;
we_q <= 1'b0;
adr_q <= '0;
dat_q <= '0;
rdat_o <= '0;
done_o <= 1'b0;
end else begin
done_o <= 1'b0;
if (!active_q) begin
if (go_i) begin
// Latch the whole request once, so the Wishbone outputs are
// driven from stable state rather than from the client's live
// signals — the structural-stability argument of Chapter 2.5.
active_q <= 1'b1;
we_q <= we_i;
adr_q <= adr_i;
dat_q <= wdat_i;
end
end else if (ack_i) begin
// Termination observed: capture read data in the SAME cycle the
// termination is asserted, then close the cycle.
active_q <= 1'b0;
rdat_o <= dat_i;
done_o <= 1'b1;
end
end
end
endmoduleReading the pair
Purpose. Between them these two modules exhibit every sentence of Section 1's model in about sixty lines of behaviour.
Ownership. The master drives cyc_o, stb_o, we_o, adr_o, dat_o. The slave drives dat_o and ack_o. No signal is driven from both ends, and the port directions enforce it.
Combinational behaviour. In the slave: one AND to form the qualified-request term, a read multiplexer, and the termination. In the master: five output assignments from registered state. Nothing else is decided in-cycle.
Sequential behaviour. The slave holds one register. The master holds the request and a single active_q bit that is the cycle.
Timing, for a read that the slave answers immediately:
| Cycle | active_q | cyc_o/stb_o | ack_i | What happens |
|---|---|---|---|---|
| 0 | 0 | 0 | – | go_i high; request latched at the edge |
| 1 | 1 | 1 | 1 | Slave sees cyc_i & stb_i, drives dat_o and ack_o |
| 2 | 0 | 0 | – | Master captured dat_i, done_o pulses |
Assumptions and simplifications. One transfer per cycle, so cyc_o and stb_o are driven from the same bit; no ERR_I or RTY_I handling; no SEL_O; the slave is never busy. Each of those is removed in a later chapter or module.
How it could fail.
- Slave terminates on
stb_ialone. Works point-to-point, violates RULE 3.35, and in a shared system terminates transfers aimed at other slaves. - Master drives Wishbone outputs from
adr_irather thanadr_q. Works against a never-busy slave and breaks the first time one waits — the stability failure from Chapter 2.5. - Master captures
dat_ia cycle afterack_i. Reads return the following transfer's data. - Asynchronous or active-low reset. The interface is then non-conforming in a way that shows up only after a warm restart.
What to verify. Section 5.
5. Verification — Architectural Invariants
// ─────────────────────────────────────────────────────────────────────────
// wb_model_checker — architectural invariants of the Chapter 3.2 model.
//
// These check the FOUR SENTENCES of Section 1 against a slave interface.
// They are not a complete Wishbone conformance suite — Module 26 owns that
// — and they deliberately avoid timing rules that Module 5 has not yet
// introduced.
// ─────────────────────────────────────────────────────────────────────────
module wb_model_checker #(
parameter int unsigned DW = 32
) (
input logic clk_i,
input logic rst_i,
input logic cyc_i,
input logic stb_i,
input logic ack_o,
input logic err_o,
input logic rty_o,
input logic [DW-1:0] dat_o
);
// Wishbone RST_I is active HIGH, so the disable condition is rst_i itself.
default disable iff (rst_i);
// P1 — RULE 3.35. Termination is generated in response to the logical AND
// of CYC_I and STB_I. A slave that terminates on STB_I alone passes
// point-to-point and fails in any shared interconnection.
property p_term_requires_qualified;
@(posedge clk_i) (ack_o || err_o || rty_o) |-> (cyc_i && stb_i);
endproperty
a_term_requires_qualified : assert property (p_term_requires_qualified)
else $error("termination asserted without CYC_I && STB_I");
// P2 — RULE 3.45. A slave supporting ERR_O or RTY_O must never assert
// more than one of the three terminations at a time.
property p_term_exclusive;
@(posedge clk_i) $onehot0({ack_o, err_o, rty_o});
endproperty
a_term_exclusive : assert property (p_term_exclusive)
else $error("more than one termination asserted: ack=%b err=%b rty=%b",
ack_o, err_o, rty_o);
// P3 — architectural, not a numbered rule: an unselected slave must not
// drive read data, or a shared return path merges two slaves' values
// into a number belonging to neither. Chapter 3.5 builds that path.
property p_quiet_when_unqualified;
@(posedge clk_i) (!(cyc_i && stb_i)) |-> (dat_o == '0);
endproperty
a_quiet_when_unqualified : assert property (p_quiet_when_unqualified)
else $error("slave drove dat_o = %h outside a qualified transfer", dat_o);
endmoduleWhy these three. P1 and P2 are the two numbered rules from Section 1 that a slave can violate on its own, in one cycle, without any timing context. P3 is an architectural requirement rather than a specification rule — the specification does not dictate how an INTERCON merges read data, so this property belongs to the system's chosen return path, and it is stated as interpretation rather than as a citation.
What is deliberately absent. Nothing about how long a slave may take, nothing about CYC_O versus STB_O timing beyond the qualified-request term, and nothing about what a master must do on ERR_I or RTY_I. Those need Module 5's handshake and Modules 10 and 11's termination semantics.
Tooling note, stated honestly: the synthesisable modules in this chapter are elaborated with Icarus Verilog. Icarus has no SystemVerilog Assertion support, so this checker was reviewed by inspection only — no tool available here has executed it.
6. Failure Modes and Discriminating Evidence
Symptom: a slave works point-to-point and corrupts other slaves' transfers once an INTERCON is added.
Candidate causes. The slave terminates on stb_i alone, ignoring cyc_i. Or the INTERCON broadcasts an undecoded strobe.
Discriminating evidence. Probe cyc_i, stb_i and ack_o at the suspect slave during an access aimed elsewhere. If stb_i is asserted at a slave that should not be selected, the fault is the INTERCON's distribution. If stb_i is correctly low but ack_o still asserts, the slave is terminating on something else entirely.
Property that catches it. P1.
Symptom: the master observes a termination and the data is wrong.
Candidate causes. Two slaves drove read data into an OR-based return path. Or the master captured dat_i outside the termination cycle.
Discriminating evidence. Compare the value the master captured against each slave's dat_o in the termination cycle. A bitwise OR of two of them is conclusive. If only one slave drove and the value still differs, the capture is at the wrong edge.
Property that catches it. P3 at the slave; the capture timing is a master-side review.
Symptom: a transfer never terminates and the master hangs.
Candidate causes. No slave selected — an unmapped address with no default. The selected slave requires a condition that never occurs. Or the slave asserted a termination and the return path did not carry it.
Discriminating evidence. Probe the slave's ack_o and the master's ack_i in the same cycle. Asserted locally but not at the master localises the fault to the INTERCON's return path rather than to the slave's register logic. Neither asserted, with stb_i high at the slave, means the slave is genuinely not answering. stb_i low everywhere means nothing was selected.
Likely RTL location. In order of likelihood: the decode, the return multiplexer, then the slave.
Symptom: the first transfer after a warm reset behaves differently from every later one.
Candidate causes. A reset convention mismatch — a block written against Module 2's asynchronous active-low reset.
Discriminating evidence. Capture rst_i and one internal register at assertion. Non-zero state while rst_i is high means the block was never reset. RULE 3.20 additionally requires STB_O and CYC_O to be negated at the rising edge following assertion of RST_I; a master still driving either during reset is non-conforming.
7. Common Mistakes
"Wishbone is valid/ready with different names."
Wrong mental model: the two protocols are structurally identical and differ only in naming.
Concrete bug: a bridge written as a renaming, which then cannot decide what to do with RTY_I, synthesises CYC_O from valid so a block cycle is impossible, and cannot honour the valid/ready side's independent ready at all.
Observable evidence: a bridge that works for single transfers and fails on anything else, with no obvious defect in either endpoint.
Correct model: four structural differences, each with consequences — two qualifiers instead of one, the cycle as an arbitration unit, three mutually exclusive terminations instead of one boolean, and no independent readiness statement in Classic. Section 3 is the argument.
"CYC_O and STB_O are redundant."
Wrong mental model: both mean "a transfer is happening", so one is decoration.
Concrete bug: a master that drives them from a single bit and therefore cannot hold the bus across a block cycle; or an arbiter that watches STB_O and releases ownership between transfers inside one cycle.
Observable evidence: in a multi-master system, another master winning the bus in the middle of a block transfer.
Correct model: CYC_O is tenure, STB_O is a transfer. CYC_O asserted with STB_O negated is legal and meaningful. The minimal master in Section 4 drives them from one bit only because it performs exactly one transfer per cycle, and it says so.
"A slave can just tie its acknowledge high."
Wrong mental model: an always-free slave has nothing to wait for, so it can advertise permanent readiness.
Concrete bug: the slave terminates every transfer in the system, including ones aimed elsewhere, and the master sees terminations for transfers it never issued.
Observable evidence: transfers completing immediately and returning data from the wrong peripheral.
Correct model: RULE 3.35 requires termination to be generated in response to CYC_I and STB_I. A never-busy slave asserts its acknowledge as a function of the qualified request — which is what assign ack_o = xfer; does — not as a constant.
"The slave decides whether the transfer is for it."
Wrong mental model: every slave compares the address and recognises its own.
Concrete bug: a slave containing its own base address, which cannot then be instantiated twice or relocated.
Observable evidence: adding a second instance requires editing the peripheral.
Correct model: the INTERCON selects, by giving exactly one slave a qualified strobe. The slave interprets a local offset. Chapter 3.5 builds the selecting side.
8. Interview Reasoning
Four structural differences, each with a consequence rather than a naming difference.
Two master-side qualifiers instead of one. CYC_O says the master holds the interconnection; STB_O says it is presenting a transfer this cycle. The combination cycle asserted, strobe negated is legal and meaningful, and valid/ready cannot express it.
The cycle is the arbitration unit. An arbiter watches CYC_O, because that is the interval during which ownership must not move. A valid/ready interface carries no equivalent signal, so any system built on it must invent one — an unwritten rule of exactly the kind Chapter 2.7 ended on.
Three mutually exclusive terminations instead of one boolean. Success, failure and try again later are architecturally distinct endings, and RULE 3.45 forbids asserting more than one. RTY_O in particular has no valid/ready counterpart, and treating it as either success or failure is wrong in opposite directions.
No independent readiness statement in Classic. In valid/ready, ready is a capability that may be asserted with no valid present. RULE 3.35 requires Wishbone termination to be generated in response to CYC_I and STB_I — a slave answers a qualified request rather than advertising availability, and in Classic the absence of a termination is how it makes the master wait.
Why it matters practically: a bridge between the two is real logic with real decisions, and the renaming description hides every one of them. The qualification a careful answer adds: B4's optional pipelined mode introduces a stall signal and changes the fourth point substantially.
9. Understanding Check
10. What's Next
The model is now four sentences: a master opens a cycle, presents transfers inside it, exactly one addressed slave owns the response, and each transfer ends in exactly one of three terminations. Section 3 established why that structure is not a renaming of anything.
The model says what happens. It does not say who is responsible for making it happen.
What must a Wishbone master actually know, decide, and hold responsibility for — and what is it deliberately not allowed to know?
Chapter 3.3 — The Master Interface answers that with a master that does real work rather than one transfer. The full path is on the Wishbone curriculum index.
Continue learning
Related tutorials
- Related topic
The Wishbone Handshake
The smallest correct conversation between a Wishbone master and slave: a master presents a transfer and holds it, a slave terminates it, and the transaction exists across an interval rather than at an instant.
- 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
ACK_I
The only mandatory termination. What a slave promises by asserting it, how wait states work without a wait signal, and why RULE 3.55 requires a master to keep working when a slave holds it asserted.
- Related topic
ERR_I
An abnormal termination whose meaning the specification deliberately delegates to the IP core supplier — which makes RULE 2.15's datasheet normative, and an undocumented ERR_O a real integration hazard.
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.
