Wishbone · Module 6
Data Return
Read data travels from a register through a slave multiplexer, a shared return path and into a capture register. It is electrically present far more often than it is architecturally valid.
Chapter 6.2 delivered the question to the right register. This chapter is the answer's journey back, which is a harder problem than the outward trip.
How does read data travel from peripheral state back to the requester, and when is that data trustworthy?
1. The Return Path, Stage by Stage
| Stage | Owns it | Characteristic failure | Evidence |
|---|---|---|---|
| Registers | slave | state itself is wrong | value wrong everywhere, including at the mux |
| Read mux | slave | wrong case arm, or a latch | one offset wrong, others right |
DAT_O gating | slave | drives outside its termination | corrupts other slaves' reads |
| Merge | interconnect | wrong source, or two sources OR-ed | wrong slave's value, or a bitwise blend |
| Capture | master | wrong edge | every read off by one, address-independent |
The fourth row is the one that catches people out. A slave driving read data when it has not terminated is not merely untidy — in a merged return path it corrupts transfers belonging to other slaves, so the symptom appears at a peripheral that is entirely innocent.
2. Why Non-Selected Slaves Drive Zero
Chapter 3.5 showed read data from several slaves merged onto one return path. The usual implementation is a bitwise OR, and it works only under one condition: every slave that is not answering contributes zero.
RULE 3.65 is what makes that achievable. A slave qualifies its DAT_O with its own termination; it is not terminating, so it drives nothing meaningful. Driving '0 specifically is an implementation policy, not a rule — the specification says the output must be qualified, not that it must be zero.
Two legal policies, with different consequences.
Drive '0 when not terminating. An OR-merge works. This is what every slave in Modules 4, 5 and 6 does.
Drive the register value continuously. Also conformant — the master is told by RULE 3.65 when to believe it. But an OR-merge now blends every slave's output together, so the interconnect must use a multiplexer driven by the select vector instead.
The two are not interchangeable, and mixing them is a real integration failure: a slave written for a mux-based fabric, dropped into an OR-based one, corrupts every read in the system. This is exactly the kind of thing RULE 2.15's datasheet exists to record.
3. RTL — The Read Multiplexer and the Merge
// ─────────────────────────────────────────────────────────────────────────
// wb_read_mux — the slave-side read multiplexer, isolated.
//
// PURPOSE. Turn a local word offset into one register value. This is
// stage 2 of Figure 1, pulled out of Chapter 6.1's wb_read_regs so the
// multiplexer's own hazards are visible without the surrounding slave.
//
// NOT A STANDALONE WISHBONE SLAVE — it has no qualifiers and terminates
// nothing. It is a combinational function, instantiated by a slave.
//
// THE LATCH HAZARD, which is the reason this block is worth isolating:
// an always_comb whose output is not assigned on every path infers a
// latch. Here `value_o` is assigned unconditionally first, so every path
// through the case — including `default` — leaves it defined.
// ─────────────────────────────────────────────────────────────────────────
module wb_read_mux #(
parameter int unsigned OFF_AW = 3,
parameter int unsigned DW = 32
) (
input logic [OFF_AW-1:0] off_i,
input logic [DW-1:0] status_i,
input logic [DW-1:0] count_i,
input logic [DW-1:0] ctrl_i,
input logic [DW-1:0] input_data_i,
output logic [DW-1:0] value_o,
output logic known_o // offset is implemented
);
localparam logic [OFF_AW-1:0] O_STATUS = 3'd0;
localparam logic [OFF_AW-1:0] O_COUNT = 3'd1;
localparam logic [OFF_AW-1:0] O_CTRL = 3'd2;
localparam logic [OFF_AW-1:0] O_INPUT = 3'd3;
localparam logic [OFF_AW-1:0] O_ID = 3'd4;
localparam logic [DW-1:0] ID_VALUE = 32'h5742_0601;
always_comb begin
// Unconditional defaults FIRST. Every later assignment overrides them,
// and no path can leave either output unassigned.
value_o = '0;
known_o = 1'b1;
unique case (off_i)
O_STATUS: value_o = status_i;
O_COUNT: value_o = count_i;
O_CTRL: value_o = ctrl_i;
O_INPUT: value_o = input_data_i;
O_ID: value_o = ID_VALUE;
default: begin
// An unimplemented offset. Reporting it separately lets the
// enclosing slave choose ERR_O rather than silently returning a
// value — Chapter 4.11's argument that silence and zero are both
// worse than an explicit refusal.
value_o = '0;
known_o = 1'b0;
end
endcase
end
endmodule// ─────────────────────────────────────────────────────────────────────────
// wb_read_merge — the interconnect's response merge, OR-based.
//
// PURPOSE. Combine every slave's read data and termination onto the single
// return path the master sees. Stage 4 of Figure 1.
//
// WHY OR WORKS. It depends entirely on non-selected slaves contributing
// zero, which RULE 3.65 makes achievable and which is this system's stated
// slave policy (Section 2). A slave that drives its register value
// continuously would corrupt every read here — that incompatibility is an
// INTEGRATION contract, not a Wishbone rule.
//
// Reset: none required — purely combinational.
// ─────────────────────────────────────────────────────────────────────────
module wb_read_merge #(
parameter int unsigned DW = 32,
parameter int unsigned NSLV = 2
) (
input logic [NSLV-1:0] ack_i, // per-slave terminations
input logic [NSLV-1:0] err_i,
input logic [NSLV*DW-1:0] dat_i, // per-slave read data, packed
output logic ack_o, // to the master
output logic err_o,
output logic [DW-1:0] dat_o
);
// Packed rather than an unpacked array port: Chapter 2.2 recorded that
// Icarus rejects array parameters and unpacked array ports, so the whole
// course uses flat vectors with part-selects for portability.
always_comb begin
dat_o = '0;
for (int unsigned i = 0; i < NSLV; i++) begin
dat_o = dat_o | dat_i[i*DW +: DW];
end
end
// Terminations merge the same way. RULE 3.45 keeps ACK/ERR/RTY mutually
// exclusive AT EACH SLAVE; the interconnect's job is to ensure only one
// slave is ever strobed, which Chapter 6.2's one-hot decode does.
assign ack_o = |ack_i;
assign err_o = |err_i;
endmodule// ─────────────────────────────────────────────────────────────────────────
// wb_read_slave — the running peripheral rebuilt from the pieces above.
//
// PURPOSE. Show the composition explicitly: a read multiplexer, a
// termination decision, and the RULE 3.65 gate between them.
//
// Functionally identical to Chapter 6.1's wb_read_regs; the difference is
// that the multiplexer is now a separate reviewable block and the gating
// is a single visible line.
//
// Reset: SYNCHRONOUS, ACTIVE HIGH (RULES 2.30, 3.00).
// ─────────────────────────────────────────────────────────────────────────
module wb_read_slave #(
parameter int unsigned OFF_AW = 3,
parameter int unsigned DW = 32
) (
input logic clk_i,
input logic rst_i,
input logic cyc_i,
input logic stb_i,
input logic we_i,
input logic [OFF_AW-1:0] adr_i,
input logic [DW-1:0] dat_i,
input logic [DW/8-1:0] sel_i,
output logic [DW-1:0] dat_o,
output logic ack_o,
output logic err_o,
input logic [DW-1:0] input_data_i,
input logic [7:0] flags_i
);
localparam logic [OFF_AW-1:0] O_CTRL = 3'd2;
logic [DW-1:0] ctrl_q, count_q;
logic xfer;
assign xfer = cyc_i & stb_i; // RULES 3.30 & 3.35
// ── THE MULTIPLEXER ───────────────────────────────────────────────────
// Runs continuously, on every cycle, regardless of whether a transfer
// exists. That is fine and costs nothing: it is combinational logic
// whose output is gated below. Gating the MUX itself instead of its
// output would add logic and change nothing.
logic [DW-1:0] mux_value;
logic known_off;
wb_read_mux #(.OFF_AW(OFF_AW), .DW(DW)) u_mux (
.off_i(adr_i),
.status_i({24'd0, flags_i}),
.count_i(count_q),
.ctrl_i(ctrl_q),
.input_data_i(input_data_i),
.value_o(mux_value),
.known_o(known_off)
);
logic illegal;
assign illegal = ~known_off | (we_i & (adr_i != O_CTRL));
assign err_o = xfer & illegal;
assign ack_o = xfer & ~illegal;
// ── THE RULE 3.65 GATE ────────────────────────────────────────────────
// One line, and it is the whole validity contract. dat_o carries the
// multiplexer's value ONLY while this slave is terminating a read;
// otherwise it is zero, which is what lets wb_read_merge use an OR.
//
// Removing `ack_o` here would leave the slave driving its register value
// continuously — still conformant under RULE 3.65's letter if the
// interconnect used a mux, and fatal to an OR-merge (Section 2).
assign dat_o = (xfer && !we_i && ack_o) ? mux_value : '0;
always_ff @(posedge clk_i) begin
if (rst_i) begin
ctrl_q <= '0;
count_q <= '0;
end else begin
count_q <= count_q + 32'd1;
if (xfer && we_i && ack_o && (adr_i == O_CTRL)) begin
for (int unsigned n = 0; n < DW/8; n++) begin
if (sel_i[n]) ctrl_q[n*8 +: 8] <= dat_i[n*8 +: 8];
end
end
end
end
endmoduleReading the group
Purpose. The multiplexer maps an offset to a value; the merge combines slaves onto one path; the slave composes them with the RULE 3.65 gate.
Interface. The multiplexer is a pure function — no clock, no qualifiers, no termination. The merge is likewise combinational. Only the slave has a Wishbone interface.
State. Multiplexer and merge: none, so neither needs a reset and neither has one. A reviewer checking RULE 3.20 should confirm a block is stateless rather than look for a missing reset. The slave holds CONTROL and the free-running counter.
Combinational logic. The multiplexer's case; the merge's OR reduction; the slave's xfer, legality, two exclusive terminations and the gate.
Sequential logic. Only the slave's counter and single write path.
Read start. The slave has no start event — only the first cycle in which xfer is true. Chapter 5.3 made that point generally; the multiplexer running continuously is the concrete form of it.
Address. adr_i is the local offset produced by Chapter 6.2's decode, consumed directly by the multiplexer.
Data return. mux_value continuously; dat_o only while terminating a read.
ACK. Combinational from the qualified transfer and legality, per PERMISSION 3.30.
Capture. Not here — that is the master's, at the termination edge.
Waiting. This slave never waits. Chapter 6.5 adds latency and shows what the multiplexer must then do.
Reset. Synchronous, active high, per RULES 2.30 and 3.00.
Failure modes. Section 7.
Simplifications. ID is a constant inside the multiplexer rather than a parameter. The merge assumes one-hot selection upstream — it does not verify it, which is Chapter 6.2's property P2's job.
4. Combinational or Registered Read Data
The multiplexer above is combinational, and Chapter 6.1's slave answers in the cycle it is asked. That is one legal choice of two.
Combinational read data — the value flows from register through mux to DAT_O within the cycle.
OBSERVATION 3.40 — "The asynchronous assertion of [ACK_O], [ERR_O], and [RTY_O] assures that the interface can accomplish one data transfer per clock cycle."
Registered read data — the slave captures the request, produces the value on a later cycle.
OBSERVATION 3.45 — "The asynchronous assertion ... could proof impossible to implement. For example slave wait states are easiest implemented using a registered [ACK_O] signal."
The cost of the combinational form is a path the specification names:
OBSERVATION 3.50 — "In large high speed designs the asynchronous assertion of [ACK_O], [ERR_O], and [RTY_O] could lead to unacceptable delay times, caused by the loopback delay from the MASTER to the SLAVE and back to the MASTER."
For a read that loop is at its longest, because the return path carries data as well as a termination:
master flop → decode → slave read mux → DAT_O gate → merge → master flopEvery stage of Figure 1 is inside one clock period. Chapter 5.7 §3 traced the same loop for the handshake; a read adds the multiplexer and a full data-width merge to it.
Neither form is universally right, and Chapter 6.4 builds both and weighs them against a synthesis report rather than a preference. What matters here is that the choice is a timing decision, not a correctness one — a master cannot tell which kind of slave it is talking to, and RULE 3.55 requires it to work with either.
5. Where Stale Data Comes From
"Stale data" is three different bugs with three different cures. Separating them is the point of this section.
Stale because the master captured too late. The master sampled DAT_I in the cycle after the termination. By then the strobe has dropped and the slave has reverted per RULE 3.50. Chapter 5.6 measured this returning zero on every read.
Stale because the master captured too early. The master sampled while the read was still outstanding and no termination had arrived. It gets whatever the return path held — zero in a quiet system, another transfer's data in a busy one.
Stale because a slave drives outside its termination. The value is not stale at the master at all; a non-selected slave is contributing to the OR-merge, so the master receives a blend. The symptom appears at whichever peripheral was legitimately being read, which is why this one is so hard to attribute.
| Cause | Address-dependent? | Fixes |
|---|---|---|
| Captured late | no — every read wrong | move the capture into the termination cycle |
| Captured early | no — every read wrong | same |
| Slave drives ungated | yes — only when that slave is powered/active | add the RULE 3.65 gate to the offending slave |
The address-dependence column is the discriminator. A capture-edge bug is uniform across every read in the system; a rogue slave corrupts some reads and not others.
6. Waveform — Early, Correct and Late
The one-cycle validity window
7 cyclesCycles 2 and 3 carry zero because no termination is asserted. A slave obeying RULE 3.65 has nothing to drive yet, and this system's slave policy is to drive '0.
Cycle 4 is one cycle wide and is the entire window.
Both broken masters return zero here, which makes them indistinguishable in this trace — and that is worth noticing. To tell early from late you need the capture strobe itself, not just the result. Chapter 6.6 makes probing the capture edge an explicit step for this reason.
7. Failure Modes and Discriminating Evidence
Symptom: every read returns zero, regardless of address.
Candidate causes. The master captures outside the termination cycle — either early or late.
Discriminating evidence. Address-independence is the first clue: a slave or decode fault varies with address, a capture fault does not. Then probe the master's capture strobe against ACK_I. Before the acknowledge edge means early; after means late.
Likely RTL location. The capture condition. if (ack_i) placed outside the outstanding-transfer state runs a cycle late; a capture gated on stb_o alone runs early.
Property. P1 in Section 9.
Symptom: every read returns the previous read's value.
Candidate causes. A late capture in a system where the return path holds a previous value rather than reverting to zero.
Discriminating evidence. The perfect, address-independent off-by-one. Chapter 5.6 measured the zero-returning variant; this is the same bug in a busier fabric, and it is more dangerous because the values look plausible.
Symptom: one register reads wrong; the others are fine.
Candidate causes. A wrong or missing case arm in the read multiplexer.
Discriminating evidence. Address-dependence localises it to the slave immediately. Probe the multiplexer's output directly against the register it should have selected. If the mux is wrong, the fault is one arm; if the mux is right and DAT_O is wrong, the fault is the gate.
Likely RTL location. The case in wb_read_mux.
Symptom: reads from a correct peripheral are corrupted, and the corruption correlates with activity elsewhere.
Candidate causes. A different slave is driving its DAT_O outside its own termination, contributing to the OR-merge.
Discriminating evidence. Probe every slave's DAT_O during the affected read. Any non-zero output from a slave that is not terminating is conclusive — and it is a RULE 3.65 violation in that slave, not in the one being read.
Likely RTL location. The offending slave's dat_o assignment, missing its termination gate.
Property. P2.
Symptom: read values are a bitwise blend of two registers.
Candidate causes. Two slaves selected at once, both terminating, both driving — an OR of two valid responses.
Discriminating evidence. The blend itself is diagnostic: a value that is neither register but has bits from both cannot arise from a multiplexer. Then probe the select vector; two asserted confirms a decode fault (Chapter 6.2).
Symptom: a read multiplexer synthesises with a latch warning.
Candidate causes. An always_comb path that leaves the output unassigned — usually a case with no default and no unconditional default assignment.
Discriminating evidence. The synthesis report names the inferred latch and the signal. In simulation it may behave correctly, because the last assigned value persists, which is why this often escapes to synthesis.
Likely RTL location. The multiplexer. wb_read_mux assigns both outputs unconditionally before the case for exactly this reason.
8. Simulation — Read Multiplexer and the Stale-Data Trap
Simulation D — every offset through the composed slave.
=== SIMULATION D - read-data mux ===
off register expected via wb_read_slave status
0 STATUS 0x000000a5 0x000000a5 OK
1 COUNT (moving) 0x00000006 OK
2 CONTROL 0x00000000 0x00000000 OK
3 INPUT_DATA 0xcafebabe 0xcafebabe OK
4 ID 0x57420601 0x57420601 OK
5 (unmapped) - 0x00000000 ERR
slave DAT_O non-zero while NOT terminating: 0 cyclesThe last line is the RULE 3.65 check, and it matters more than the value rows. The slave's DAT_O was zero on every cycle it was not terminating, which is what makes the OR-merge sound.
Simulation E — the stale-data trap.
A deliberately broken master captures DAT_I whenever its transfer is presented, rather than at the termination, against a slave with two wait states.
=== SIMULATION E - early capture ===
read of ID (word 4), WAITS=2
cycles presented 3
DAT_I during cycles 1..2 0x00000000 (no termination yet)
DAT_I at the termination cycle 0x57420601
correct master captured 0x57420601
early master captured 0x00000000
early master's status OKThe early master reported OK — a successful read, with zero as the value. Nothing in its own view indicates a problem: the transfer completed, the termination was ACK, the status is success.
And the bus was fully conformant throughout. One presented transfer, one termination, stable qualified signals, read data correctly gated. A protocol checker attached to this bus passes. The failure is entirely inside the master's capture condition, and only a property with white-box access to the capture register finds it — which is P1.
9. Verification
// ─────────────────────────────────────────────────────────────────────────
// wb_data_return_checker — return-path properties.
//
// P1 is a DESIGN OBLIGATION derived from RULE 3.65: the rule constrains the
// SLAVE's DAT_O, and what a master does with that window is the master's
// design. P2 IS specification — it checks the slave side of the same rule.
// P3 is LOCAL POLICY about this system's OR-merge.
// ─────────────────────────────────────────────────────────────────────────
module wb_data_return_checker #(
parameter int unsigned DW = 32
) (
input logic clk_i,
input logic rst_i,
// master side
input logic cyc_o,
input logic stb_o,
input logic we_o,
input logic ack_i,
input logic [DW-1:0] rdat_q, // white-box: capture register
// slave side
input logic s_cyc,
input logic s_stb,
input logic s_ack,
input logic s_err,
input logic [DW-1:0] s_dat_o
);
default disable iff (rst_i);
// P1 — DESIGN OBLIGATION (from RULE 3.65). The capture register changes
// only at the edge of a successful read termination. Catches the
// early capture, the late capture and an unconditional one, and it
// is the ONLY check that finds them — the bus stays conformant
// during all three.
//
// $past is required: rdat_q changes AT the edge while the
// authorising conditions were true BEFORE it.
property p_capture_in_the_window;
@(posedge clk_i) $changed(rdat_q) |-> $past(cyc_o && stb_o && ack_i && !we_o);
endproperty
a_capture_in_the_window : assert property (p_capture_in_the_window)
else $error("read data captured outside the RULE 3.65 window");
// P2 — SPECIFICATION (RULE 3.65), slave side, stated in the
// contrapositive: no termination, no read data. This is the
// property that protects OTHER slaves' reads, because a violation
// corrupts the shared return path rather than this slave's own
// transfers.
property p_slave_data_qualified;
@(posedge clk_i) (!s_ack && !s_err) |-> (s_dat_o == '0);
endproperty
a_slave_data_qualified : assert property (p_slave_data_qualified)
else $error("RULE 3.65: slave drove read data without a termination");
// P3 — LOCAL POLICY. This system's slaves drive '0 when not terminating
// so the interconnect can OR-merge. A mux-based fabric would not
// need this, and a slave written for one does not drop into the
// other — an INTEGRATION contract (Section 2), not a Wishbone rule.
property p_no_data_outside_transfer;
@(posedge clk_i) !(s_cyc && s_stb) |-> (s_dat_o == '0);
endproperty
a_no_data_outside_transfer : assert property (p_no_data_outside_transfer)
else $error("LOCAL: slave drove data outside a qualified transfer");
endmoduleP2 deserves emphasis because of who it protects. A slave violating it does not break its own reads — it breaks other slaves', by polluting the merge. The symptom surfaces at an innocent peripheral, so the assertion has to live on every slave rather than on the one that appears faulty.
P1 needs white-box access and is the only way to catch capture-edge bugs, since the bus is legal throughout. That is the fourth time this course has reached that boundary — after lost atomicity (4.9), repeated side effects (5.3) and the RULE 3.55 stall (5.4) — and Chapter 5.8 §8 collected the pattern.
Tooling limitation. Icarus Verilog has no SVA support and cannot execute any of these. They are reviewed by inspection; the synthesizable RTL is elaborated and both simulations above were run.
10. Common Mistakes
"DAT_I is valid whenever the slave drives it."
Wrong mental model: the presence of a value implies permission to use it.
Concrete bug: a master registering DAT_I every cycle, or one gated on STB_O alone.
Observable evidence: every read returning zero or a previous value, uniformly across all addresses.
Correct model: RULE 3.65 qualifies the slave's DAT_O with its termination. Present and valid are different states, and three cycles out of four carry a value nobody may believe.
"A slave can just drive its register value continuously — the master knows when to look."
Wrong mental model: RULE 3.65 is only about the master's discipline.
Concrete bug: an ungated dat_o in a system whose interconnect OR-merges. Every read in the system is corrupted by every other slave.
Observable evidence: reads from a correct peripheral returning blended values, correlated with unrelated activity.
Correct model: the gate protects the shared return path. It is legal to drive continuously only if the fabric muxes — and that compatibility belongs in the datasheet, per RULE 2.15.
"Registered read data is safer."
Wrong mental model: flops fix things.
Concrete bug: none directly — but registering reflexively adds a cycle to every read in the system, and a registered response must also preserve the request context it is answering, which is new state and a new way to be wrong (Chapter 6.4).
Observable evidence: uniformly increased read latency with no timing justification.
Correct model: combinational and registered are a documented trade-off in OBSERVATIONS 3.40–3.50. Decide it against a synthesis report.
11. Interview Reasoning
One question first, because it splits the five candidates in half: is the fault address-dependent?
If every read is wrong regardless of address, the fault is at the master's capture or at the merge — stages that see all reads. If only some offsets are wrong, it is the register, the multiplexer, or a per-slave gate.
For the address-independent case, probe the master's capture strobe against ACK_I. Capturing before the acknowledge edge is early; after it is late. Both typically return zero in a quiet system, which is why the result does not distinguish them and the strobe does. If the capture edge is correct, look at the merge — is it selecting the right source, and is exactly one slave contributing?
For the address-dependent case, probe inward. Compare the register's own value against the multiplexer's output, then the multiplexer's output against DAT_O. The first mismatch names the stage: registers wrong means the state is wrong, mux wrong means a case arm, DAT_O wrong with a correct mux means the RULE 3.65 gate.
The fifth failure mode is the one this ordering is designed to catch — a different slave driving its DAT_O without terminating, polluting the OR-merge. It presents as address-dependent corruption of a peripheral that is entirely correct. The probe is every slave's DAT_O during the affected read, and any non-zero output from a non-terminating slave is conclusive.
Why I would not start by reading the slave's RTL. Two of the five stages are outside the slave, one is in a different slave, and the returned value alone distinguishes none of them. Each probe above is a single signal and eliminates a stage definitively.
The assertion that makes most of this unnecessary. P2 — no termination, no read data — bound on every slave. It fires at the moment a slave pollutes the path, naming the guilty slave rather than the victim.
12. Understanding Check
13. What's Next
The return path is now understood end to end: a multiplexer, a gate, a merge and a capture, with validity owned by one rule and a single-cycle window.
That window is defined by the termination — and the termination has been treated as something the slave simply produces. For a read it is not that simple: the acknowledge must not arrive before the data is ready, and the slave must not acknowledge a transfer that was never addressed to it.
When should a read slave acknowledge, and what must be true when it does?
Chapter 6.4 — ACK Generation answers it. The full path is on the Wishbone curriculum index.
Continue learning
Related tutorials
- 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.
- Related topic
SoC Communication
Six chapters built the pieces; this one assembles them into a working fabric and traces three real accesses through it. The result works, and reading the nine unwritten rules a third party would need is what makes the case for a published protocol concrete rather than theoretical.
- Related topic
DAT_I
A master's DAT_I is returned read data; a slave's is incoming write data. Neither may be believed without the condition that qualifies it — and sampling one cycle late returns the previous transaction's value.
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.
