Wishbone · Module 27
Data Corruption
Five rigs, one program, one line of output each: the scoreboard reports a data mismatch. Two of the five contain no design defect at all, and the data lineage separates them at five different edges.
The bus completed normally. The handshake was correct, the target was correct, the termination was ACK, and the value is wrong.
Where was the first wrong value created?
Not which module is guilty — that is the question people reach for and it has no evidence behind it yet. The answerable question is about an edge: the payload passed through a chain of hands, and one of them changed it.
1. Transport Correctness Is Not Payload Correctness
Everything in Chapters 27.1 through 27.4 was about transport: did it arrive, where did it go, when, and whose was it. This chapter assumes all of that is right.
The write lineage:
Ten edges. The last two are not in the design at all. A monitor that samples early and a reference model with the wrong semantics both land on the same final line, and there is nothing in that line to say so.
2. Five Rigs, One Program
One five-operation program — seed two memory words to 0xFFFFFFFF, perform a single-lane write of 0x0000AA00 to the first, read both back — run on six rigs.
=== SIM I / SIM J / SIM K - FIVE CAUSES, ONE SYMPTOM ===
rig defect scoreboard data term protocol P0 protocol P2
C0 none 0 0 0 0 0
I1 WRONG_BYTE_MASK 1 1 0 0 0
I2 WRONG_STORE_IDX 2 2 0 0 0
J WRONG_RETURN_MUX 2 2 0 0 0
K1 EARLY_READ_SAMPLE 2 2 0 0 0
K2 REF_IGNORES_SEL 1 1 0 0 0
Every rig is protocol-clean. Four of the five report the
same mismatch count. TWO OF THEM CONTAIN NO DESIGN DEFECT
AT ALL.Five defects. Zero protocol violations anywhere. The mismatch counts — 1, 2, 2, 2, 1 — carry no information about cause; I1 and K2 both report exactly one data mismatch, and one of them is a bug in the design while the other is a bug in the testbench.
The seed is not a nicety
// ── THE SEED MATTERS ────────────────────────────────────────────────────
// The partial write is performed over a word seeded with 0xFFFFFFFF.
// Chapter 26.5 measured a coverage model that hit the partial-write bin
// while the stimulus remained INSENSITIVE to lane defects, because
// zero-filled data written into a zero register is indistinguishable
// from a masked write that did nothing. A non-zero background is not a
// nicety here; without it SIM I detects nothing.Writing zeros into a zero location through the wrong mask produces the correct answer by accident. Chapter 26.5 measured detection moving from 6 of 8 to 8 of 8 with the coverage number unchanged. The bin was always hit; the stimulus was never sensitive.
3. The Lineage
The correct result of W 0x0110 sel=2 data=0x0000AA00 over 0xFFFFFFFF is 0xFFFFAAFF. Here is every edge, for every rig.
C0 master mask 2 delivered mask 2
master addr 0x0110 delivered addr 0x0110
committed storage 0xffffaaff
slave DAT_O 0xffffaaff
returned on bus 0xffffaaff
monitor recorded 0xffffaaff
model expected 0xffffaaff
I1 master mask 2 delivered mask f
master addr 0x0110 delivered addr 0x0110
committed storage 0x0000aa00
slave DAT_O 0x0000aa00
returned on bus 0x0000aa00
monitor recorded 0x0000aa00
model expected 0xffffaaff
I2 master mask 2 delivered mask 2
master addr 0x0110 delivered addr 0x0114
committed storage 0xffffffff
slave DAT_O 0xffffffff
returned on bus 0xffffffff
monitor recorded 0xffffffff
model expected 0xffffaaff
J master mask 2 delivered mask 2
master addr 0x0110 delivered addr 0x0110
committed storage 0xffffaaff
slave DAT_O 0xffffaaff
returned on bus 0x00000000
monitor recorded 0x00000000
model expected 0xffffaaff
K1 master mask 2 delivered mask 2
master addr 0x0110 delivered addr 0x0110
committed storage 0xffffaaff
slave DAT_O 0xffffaaff
returned on bus 0xffffaaff
monitor recorded 0x00000000
model expected 0xffffaaff
K2 master mask 2 delivered mask 2
master addr 0x0110 delivered addr 0x0110
committed storage 0xffffaaff
slave DAT_O 0xffffaaff
returned on bus 0xffffaaff
monitor recorded 0xffffaaff
model expected 0x0000aa00Read each block downwards and stop at the first line that differs from C0. That line is the answer.
=== THE FIRST DISAGREEING EDGE ===
rig first edge that disagrees with the correct rig
I1 delivered write mask f vs 2 -> write path
I2 delivered write address 0x0114 vs 0x0110 -> write path
J returned bus data 0x00000000 vs 0xffffaaff -> return path
K1 monitor record 0x00000000 vs 0xffffaaff -> OBSERVER
K2 model expectation 0x0000aa00 vs 0xffffaaff -> PREDICTORFive rigs, five different edges, and none of them is the edge the scoreboard reported.
4. Exonerating The Memory
Two of these cases look exactly like "the memory stored the wrong value" and neither is.
J's storage read back 0xffffaaff through the back door and
its slave drove 0xffffaaff onto its own DAT_O. THE MEMORY IS
INNOCENT; only the mux between it and the master is not.J's storage is correct. Its slave drove the correct value onto its own DAT_O. Something between that pin and the master's DAT_I substituted a different value entirely. Opening the memory model to debug this would have consumed an afternoon and found nothing.
I2's storage at 0x0110 reads 0xffffffff through the back
door, and the value it was given is not lost - it is at
0x0114, which reads 0xffffaaff. NOTHING WAS CORRUPTED.
Something was filed in the wrong drawer, and the read
that went looking for it addressed the right one.I2 is more interesting still. No value was corrupted anywhere. The merge was correct, the lanes were correct, the data was correct. It was committed to the neighbouring word, and the readback — which addressed the right word — found the seed still sitting there. Both the write and the read did precisely what they were told; only one of them was told the truth.
// WRONG_STORE_IDX corrupts the address of WRITES only. Reads go where
// they were asked to go, which is what makes the symptom so misleading:
// the value comes back wrong from a location the read addressed
// correctly, and the memory holding it is innocent.5. When The Verification Environment Is The Defect
K1 and K2 both indict a design that did exactly what it
was asked. K1's bus carried 0xffffaaff and its monitor wrote
down 0x00000000. K2's bus carried 0xffffaaff and its model
predicted 0x0000aa00. Neither number came from the DUT.K1 is the monitor of Chapter 26.3, sampling read data one clock early. RULE 3.65 qualifies DAT_O() with the termination, so a monitor that latches the previous clock records whatever was on the bus before the slave drove it — here, zero.
K2 is the reference model of Chapter 26.4, applying a partial write as if it were a full one. Its prediction is 0x0000AA00; the design's answer is 0xFFFFAAFF; and the design is right.
In both, the bus carried the correct value. Every design signal in the lineage is correct. The divergence is at edge nine or edge ten — inside the thing doing the checking.
6. The Symptom Collision
THE SYMPTOM COLLISION
I1 is a defect in the design. K2 is a defect in the
verification environment. Both report 1 data mismatch,
and their reports are indistinguishable. The lineage
separates them in one line: I1's DELIVERED MASK is wrong
(f, asked for 2) and K2's is right (2).This is the pair worth memorising, because the two are semantically identical: both amount to "SEL was ignored on a partial write". One ignores it in the fabric, one ignores it in the model. They produce the same count, the same failing transfer, the same expected value and the same observed value — with the roles of expected and observed swapped, which no report prints.
One line of lineage tells them apart: what mask did the slave actually receive? f when 2 was asked for is a design defect. 2 when 2 was asked for is not.
The instinct to distrust the design first is a bias, and it is expensive. A scoreboard mismatch is a statement that two things disagree. It contains no information about which of them is wrong, and on this evidence two of five are not the design at all.
7. The Debug Record
| field | I1 | I2 | J | K1 | K2 |
|---|---|---|---|---|---|
| symptom | readback mismatch | readback mismatch | readback mismatch | readback mismatch | readback mismatch |
| protocol violations | 0 | 0 | 0 | 0 | 0 |
| storage correct? | no | yes, wrong word | yes | yes | yes |
slave DAT_O correct? | no | no | yes | yes | yes |
| bus data correct? | no | no | no | yes | yes |
| monitor correct? | n/a | n/a | n/a | no | yes |
| model correct? | yes | yes | yes | yes | no |
| first bad edge | delivered mask | delivered address | return mux | observer | predictor |
| guilty party | design | design | design | testbench | testbench |
Every column ends at the same scoreboard line. The row where each first says no is the finding.
8. What To Carry Forward
- A scoreboard mismatch is a symptom. It says two things disagree, never which one is wrong.
- Record the value at every edge, not just at the ends. The middle is where the answer lives, and the ends are where the report is generated.
- Walk the lineage downwards and stop at the first disagreement. Everything below it is a consequence.
- Exonerate before you accuse. A back-door read and the slave's own
DAT_Ocleared the memory in two of five cases. - Wrong data is not always corrupted data. I2 lost nothing; it filed correctly computed data in the wrong place.
- Seed with non-zero values. A masked write over zeros into zeros is correct by accident and proves nothing.
- Two of five defects were in the verification environment. If that ratio surprises you, it is because scoreboard reports never mention the possibility.
Chapter 27.6 closes the module with the evidence everybody reaches for first and should reach for last.
Continue learning
Related tutorials
- 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.
- Related topic
DAT_O
Both masters and slaves have a DAT_O, and they mean opposite things. What each must drive, when it must be valid, and why a master may legally leave stale write data on the bus during a read.
- 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.
- Related topic
WE_O
One bit decides which data path carries the meaningful value. It is a direction selector and never a write trigger, and a slave that ignores it writes a register on every read with the previous write's data.
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.
