Wishbone · Module 27
Wrong Address Decode
Every transfer acknowledged, zero protocol violations, and the register bank never strobed once. Plus two broken decoders that agree on the failing address and are separated by one other.
Chapter 27.1 dealt with transfers that never came back. This chapter deals with the ones that did — on time, cleanly, with a perfect handshake — and went to the wrong place.
ACK_Iis a statement about the handshake. It says nothing whatever about the destination.
1. What Decoding Actually Decides
Module 12 established the structure and this chapter assumes it:
global address -> ownership decision -> target selection -> local addressFour steps, four independent ways to be wrong, and B3 puts all four in the same place without describing any of them:
"each SLAVE decodes only the range of addresses that it requires... The remaining address bits are decoded by the interconnection system."
The map, first-match-wins, and what happens to an unmapped address are local policy. That is not a caveat — it is the reason a decode bug cannot be caught by a protocol checker. There is no rule to break.
2. The Decode Trace
The transaction log in Chapter 27.1 recorded what happened. It cannot express this chapter's failure, because a log line reading ACK at 0x0000 is identical whether the register bank or the memory answered.
So the trace records two things a log conflates: what the master asked for and who received it.
T``_rad[T``_rn] <= T``_p0adr; \
T``_rtg[T``_rn] <= T``_dflt ? 2'd0 : T``_del; \
T``_rtm[T``_rn] <= T``_p0a ? 2'd0 : (T``_p0e ? 2'd1 : 2'd2); \
T``_rmu[T``_rn] <= T``_multi; \
T``_rof[T``_rn] <= (T``_p2adr == T``_p0adr); \The fields are, in order: the address the master asked for; the target the request was delivered to; the termination class; whether more than one region claimed the address; and whether the address survived the trip downstream. The trailing backslashes are real — this is the body of a macro, so that every rig in every testbench is built from the same text.
Five fields. Four of them are invisible in any log that records only the interface.
3. SIM D — Wrong Target, Perfect Protocol
The decode is correct and the routing is not: every register access is delivered to the memory instead. The same four operations run on a control rig and on the defective one.
=== SIM D - WRONG TARGET, PERFECT PROTOCOL ===
op address control target SIM D target control term SIM D term
0 0x0000 S0 regs S1 mem ACK ACK
1 0x0000 S0 regs S1 mem ACK ACK
2 0x0006 S0 regs S1 mem ERR ACK
3 0x0004 S0 regs S1 mem ACK ACK
register slave phases presented control 4 SIM D 0
memory phases presented control 0 SIM D 4
register slave writes committed control 1 SIM D 0
protocol violations control P0 0 P2 0 SIM D P0 0 P2 0
monitor transactions control 4 SIM D 4
scoreboard mismatch control 0 SIM D 1
of which data control 0 SIM D 0
of which term control 0 SIM D 1Read the numbers in the order a debugger would meet them.
Protocol violations: zero. Both checkers, at both boundaries, on both rigs. Nothing illegal happened, because delivering a request to the wrong slave is not illegal — it is merely wrong.
Monitor transactions: four in each. The observer reconstructed four transfers in both rigs, with the same addresses and the same directions. The monitor is working perfectly and has nothing useful to say.
Register slave phases presented: zero. This is the line that breaks the case open. Four register operations were acknowledged and the register bank was never strobed once.
Scoreboard mismatches: one. Out of four. The single failing transfer is op 2, a write to the read-only register at offset 6: the correct system refuses it with ERR, and the memory — which has no concept of a read-only location — cheerfully acknowledges. Three of the four wrong transfers produced no mismatch at all, because writing and reading the same wrong location is self-consistent. A scoreboard that compares reads against writes cannot see a systematic redirection.
4. The Address Ownership Audit
A decode bug is found by sweeping, not by staring. For the correct system, compare expected target against delivered target across an address set chosen to hit edges:
=== ADDRESS OWNERSHIP CONSISTENCY AUDIT - CORRECT SYSTEM ===
address expected delivered offset kept multi term
0x0100 S1 mem S1 mem yes no ACK
0x01ff S1 mem S1 mem yes no ACK
0x0000 S0 regs S0 regs yes no ACK
0x00ff S0 regs S0 regs yes no ERR
0x0100 S1 mem S1 mem yes no ACK
0x01ff S1 mem S1 mem yes no ACK
0x0200 unmapped unmapped yes no ERR
0x0300 unmapped unmapped yes no ERR
0x1000 unmapped unmapped yes no ERR
addresses checked 9
target mismatches 0
local-offset mismatches 0
multi-select events 0
no-select where selection expected 0
AUDIT errors 0The expected column is computed from the map, written as ranges, and deliberately not from the fabric's mask arithmetic:
// ── the expected decode, written from the MAP and not from the
// fabric's arithmetic. Ranges, not masks: a bug in the fabric's
// mask handling must not be able to hide inside the checker that is
// supposed to catch it.
function [1:0] expect_tgt(input [15:0] a);
begin
if (a <= 16'h00FF) expect_tgt = 2'd1;
else if (a >= 16'h0100 && a <= 16'h01FF) expect_tgt = 2'd2;
else expect_tgt = 2'd0;
end
endfunctionNote 0x00FF terminates with ERR and still counts as a correct decode. Termination class and target ownership are different questions, and the audit asks only one of them. The register slave refuses offset 0xF because it is reserved — that is a correct refusal by the correct peripheral.
5. The Audit's Own First Bug
The first version of this sweep read memory words nobody had ever written, and reported two mismatches on a system with no defect armed:
THE AUDIT'S OWN FIRST BUG
scoreboard mismatches 2
of which data 2
monitor unknown fields 2
target mismatches 0The discriminator is in the third line. The reference model predicts zero for an unwritten word; the memory returns X; and an X cannot be a wrong value the design computed, because the design never computed anything. Target mismatches are zero — the decode was never implicated.
This is the same class of error Chapter 26.4 paid for with a reference model that guessed an address map. Here the guess is about state rather than structure, and the fix is the same shape: define what you are about to read.
6. SIM E — Two Broken Decoders That Agree
Now the interesting case. Two different decode defects:
- WINDOW_WIDE — the register window's mask is one bit short, so S0 claims
0x0000–0x01FFand swallows its neighbour. - ADDR_TRUNCATE — the region compare uses
ADR[7:0]only.
=== SIM E - TWO DECODES, ONE SYMPTOM ===
address expected E1 WINDOW_WIDE E2 ADDR_TRUNCATE E1 multi
0x0000 S0 regs S0 regs S0 regs no
0x00ff S0 regs S0 regs S0 regs no
0x0100 S1 mem S0 regs S0 regs YES
0x01ff S1 mem S0 regs S0 regs YES
0x0200 unmapped unmapped S0 regs no
0x0300 unmapped unmapped S0 regs no
0x1000 unmapped unmapped S0 regs no
E1 target mismatches 2
E2 target mismatches 5
E1 multi-select events 2 E2 multi-select events 0
protocol violations E1 P0 0 P2 0 E2 P0 0 P2 0On the failing address they are identical. 0x0100 — the first word of the memory, the address a real bug report would arrive quoting — goes to the register bank in both. A debugger handed only that address has two live hypotheses and no way to choose.
The sweep chooses for them.
THE DISCRIMINATING ADDRESS IS 0x0200.
0x0200 -> E1 unmapped (ERR ) E2 S0 regs (ACK )0x0200 lies outside both windows. Widening S0 by one mask bit extends it to 0x01FF and stops — so a widened window still answers ERR there. A truncated compare discards the high byte, 0x0200 becomes 0x0000, and S0 claims it.
One address. One observation. One hypothesis eliminated. The discriminating experiment is not the one that reproduces the bug; it is the one whose two possible outcomes belong to different explanations.
| WINDOW_WIDE | ADDR_TRUNCATE | |
|---|---|---|
0x0100 | S0 regs | S0 regs |
0x0200 | unmapped, ERR | S0 regs, ACK |
| targets wrong, of 7 | 2 | 5 |
| multi-select events | 2 | 0 |
| protocol violations | 0 | 0 |
7. The Overlap That Says Nothing
The multi column is the second discriminator, and it is worth its own wire.
A widened S0 does not collide with the memory in any way the system announces. First-match-wins resolves the overlap deterministically and silently, and the memory simply never receives anything again. The fabric reports it only because it was built to:
// An overlap that first-match-wins makes SILENT. A widened window
// does not announce itself as a collision; it simply shadows its
// neighbour, and this is the only wire that says so.
assign p2_multi_o = present && hit0 && hit1;Two multi-select events on E1; zero on E2. A truncated compare produces no overlap at all — the truncated address matches exactly one region — which is why the two defects produce different shapes of wrongness despite agreeing on the address everyone would report.
8. The Debug Record
| field | SIM D | SIM E1 | SIM E2 |
|---|---|---|---|
| observed symptom | one write refused that should have succeeded | memory reads return register data | identical |
| failing detector | scoreboard, termination class | scoreboard, data | scoreboard, data |
| first hypothesis | the register bank is broken | the memory is broken | the memory is broken |
| competing hypothesis | the request went elsewhere | the decode is wrong | the decode is wrong |
| discriminating observation | register slave phases = 0 | sweep address 0x0200 | sweep address 0x0200 |
| first causal divergence | decode S0, delivered S1 | overlap at 0x0100 | 0x0200 claimed by S0 |
| first bad boundary | routing, after decode | decode mask | decode compare width |
| root cause | routing ignores the computed select | mask one bit short | compare on ADR[7:0] |
| protocol violations | 0 | 0 | 0 |
The last row is the one to remember. Three decode defects, zero protocol violations, and a monitor that reconstructed every transaction correctly. Chapter 26.1 put it as a slogan; here it is a measurement.
9. What To Carry Forward
ACKproves a handshake completed. It proves nothing about which peripheral completed it.- Separate what decode computed from what routing delivered. SIM D is invisible unless those are different wires.
- Sweep boundaries, not typical addresses. First and last of each window, one above and below, a hole, and an alias candidate.
- Look for the address that distinguishes hypotheses, not the one that reproduces the bug.
0x0100reproduces;0x0200decides. - A silent overlap is worse than a collision. If your decoder cannot report multi-select, a shadowed peripheral disappears without a word.
- Define the state you are about to read. An X in a mismatch is a stimulus bug wearing a design bug's clothes.
Chapter 27.3 takes the defects that do not exist at all until the transfer is slow enough to have an inside.
Continue learning
Related tutorials
- Related topic
FPGA Design Challenges
Six peripherals and two masters on one FPGA is where on-chip integration stops being theory. The decode that must be exhaustive and one-hot, the read multiplexer that grows with every target and carries the critical path, the latency and reset conventions that refuse to agree, and the point at which the fabric rather than the peripherals starts failing timing.
- Related topic
Address Space
An address is a number until a decoder turns it into a target selection and a local offset. Range comparison and mask comparison are different engineering choices with different costs; exhaustive, mutually exclusive decode is a property to be proved rather than assumed; and a flat decoder's critical path is what eventually forces a hierarchy.
- Related topic
The Interconnect
Two conforming Wishbone interfaces still cannot talk without something between them. The INTERCON holds the address map, distributes exactly one strobe, merges read data and terminations, and answers for addresses nobody owns — and the specification defines it by its job rather than by a signal set.
- Related topic
Data Flow
One Wishbone access, followed through every block in both directions: what the master drives, where the address changes form, which signals are broadcast and which are decoded, and how read data and termination find their way back to exactly one requester.
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.
