Wishbone · Module 27
Missing ACK
A request is presented and nothing comes back. Ten mechanisms produce that symptom; a suppressed decode and a dropped return look identical at the master port and diverge at cycle 10 in different places.
A master is waiting. CYC_O and STB_O are asserted, the address has not moved, and no ACK_I, ERR_I or RTY_I has arrived. Everyone's first sentence is the same one, and it is almost always wrong:
"The slave forgot to acknowledge."
That sentence names a mechanism when the evidence supports only a symptom. This chapter is about the difference, and about the cheapest observation that settles it.
1. The Causality Chain
A completion is not one event. It is a chain, and a missing completion is a break in exactly one link of it:
Read the list of things that produce exactly the symptom above, and notice how few of them involve a slave forgetting anything:
- the master never presented a valid request at all;
- arbitration never granted the bus;
- decode selected no target;
- the request was selected but not forwarded;
- the slave is legitimately still working;
- the slave deadlocked;
- the slave terminated and the return route lost it;
ERR_IorRTY_Iarrived and the debug logic was watching onlyACK_I;- the response was qualified against the wrong condition;
- the testbench sampled the wrong boundary.
Ten mechanisms. One symptom. The only way through is to find the last boundary where the request was present and correct and the first boundary where it was not.
2. The System Under Debug
Every experiment in Module 27 runs on one fabric, instrumented at those five points. The endpoints are reused byte-for-byte: the register slave from Chapter 24.1 and the memory from Module 25, neither of which is edited. Defects live in the fabric, because in real work you almost never get to edit the IP.
// 0x0000 - 0x00FF S0 register slave (Module 24, byte-identical)
// 0x0100 - 0x01FF S1 memory (Module 25, byte-identical)
// everything else unmapped -> default responder answers ERR
//
// The two windows are ADJACENT on purpose. An off-by-one in a window
// boundary is invisible when the neighbours are far apart, and Chapter
// 27.2's boundary sweep needs a neighbour to fall into.The probes are not decoration. p2_decode_o reports what the decoder computed and p2_deliver_o reports what routing delivered, and keeping those two separate is what makes half of the next chapter possible:
// ── P2: what the selected target sees ──
output logic [1:0] p2_decode_o, // what DECODE computed
output logic [1:0] p2_deliver_o, // what ROUTING delivered
output logic p2_dflt_o, // default responder selected
output logic p2_none_o, // nothing selected at all3. The Known-Good Reference
Nothing about a failing run means anything without a baseline. SIM A runs eight operations across both targets, a read-only refusal and an unmapped address, on the correct system.
=== SIM A - CLEAN DEBUG BASELINE ===
TRANSACTION LOG
cycl op address sel data term target
3 WRITE 0x0000 sel=f data=0x0a5a5001 ACK target=S0 regs
9 READ 0x0000 sel=f data=0x0a5a5001 ACK target=S0 regs
15 WRITE 0x0104 sel=f data=0xdeadbee0 ACK target=S1 mem
21 READ 0x0104 sel=f data=0xdeadbee0 ACK target=S1 mem
27 READ 0x0006 sel=f data=0x00000000 ACK target=S0 regs
33 WRITE 0x0006 sel=f data=0x00000000 ERR target=S0 regs
39 READ 0x0300 sel=f data=0x00000000 ERR target=default
45 WRITE 0x0108 sel=f data=0x80000033 ACK target=S1 mem
BOUNDARY CENSUS
boundary opened presented terminated ack err open_at_end
P0 master 8 8 8 6 2 no
P2 S0 regs 4 4 4 3 1 no
P2 S1 mem 3 3 3 3 0 no
ops issued 8
ops retired 8
protocol violations P0 0 P2 0
monitor txn/ack/err 8 / 6 / 2 unknown 0
scoreboard compared 8 mismatches 0 orphan 0
SIM A errors 0Eight lines of transaction log and three lines of census. That is the whole evidence budget for a healthy system, and every number in it is a thing a later run can contradict: 4 + 3 + 1 phases distributed across register slave, memory and default responder, adding to the 8 the master saw.
4. The Experiment: Two Causes, One Symptom
Two defects, deliberately built to be indistinguishable where people look first.
SIM B suppresses the memory's decode result. Nothing downstream is selected — not the memory, not even the default responder — so the request is presented into empty space.
SIM C lets the memory answer perfectly and drops the acknowledgement on the way back.
Both run the same two-operation program: a register write that completes in every rig, then a memory read.
THE SYMPTOM, AS THE MASTER SEES IT
rig ops retired phases opened terminated still open clocks held
B 1 2 1 YES 391
C 1 2 1 YES 391
Identical. No observation at P0 separates them.Every number a master can see is the same. One operation completed, so the bus is alive and the master is not broken. One phase is open and has been for 391 clocks.
Now move one boundary in:
ONE BOUNDARY IN
rig S1 phases opened S1 terminated S1 ACK master ACKs
B 0 0 0 1
C 1 391 391 1
decode computed / delivered B: 2 / 0 C: 2 / 2
nothing selected at all B: 1 C: 0They are not similar any more.
In SIM B the memory was never addressed. Its strobe never rose. The decoder computed target 2 — it knew perfectly well where the request belonged — and routing delivered target 0. The divergence is between decode and deliver, two wires apart.
In SIM C the memory answered 391 times. Its request stayed presented because the master never saw a completion, and RULE 3.50 has the slave assert termination in response to STB_I — so it kept answering, clock after clock, into a return path that discarded every one.
5. First Divergence, As A Number
"Different boundary" is a qualitative claim. Make it quantitative:
FIRST DIVERGENCE, AS A CYCLE NUMBER
B decode says memory, memory strobe never rises
first cycle 10 occurrences 391
C memory terminates, master does not
first cycle 10 occurrences 391Both defects first bite on the same clock. That is the point. Timing is not what separates them and never was; location is. A debugger who sorts evidence by count instead of by boundary learns nothing here, because the counts are identical too.
SIM B and SIM C at the clock the request opens
6 cyclesEight signals. Not three hundred. Each one is there because it answers a question the hypotheses disagree about, and the chapter's whole conclusion is readable in the two rows labelled S1 STB.
6. Waiting Is Not A Protocol Violation
The most common bad sentence in a Wishbone bug report is "the slave violated the specification by not acknowledging within N cycles."
B3 bounds no latency. There is no timeout in the specification, no maximum wait-state count, and no rule a slow slave can break by being slow. Both defective rigs above report it:
WAITING IS NOT A PROTOCOL VIOLATION
B protocol violations P0 0 P2 0
C protocol violations P0 0 P2 0Zero, in a system that will never complete the transfer. If your system has a deadline, that deadline is local policy — it comes from a requirement document, not from B3 — and the honest statement a debugger may make is:
the phase has been open for 391 observed clocks
and never:
the slave violated the specification.
The distinction matters commercially as well as intellectually. The first sentence starts an investigation; the second starts an argument with a vendor you are about to lose.
7. The Fix That Is Not A Fix
A master-side timeout is the standard engineering response to a transfer that does not return, and Chapter 12.6 built one. Watch what a longer one buys on SIM C:
THE FIX THAT IS NOT A FIX
after 200 clocks phase open 191 clocks, terminations 1
after 400 clocks phase open 391 clocks, terminations 1
Doubling the patience doubles the wait and returns the
same number of completions. The memory answered every
one of those clocks (391 terminations at its own port).
A TIMEOUT IS A POLICY FOR SURVIVING A MISSING RESPONSE.
IT IS NOT A REPAIR FOR A RETURN PATH.The timeout is a good thing to have. It converts a hang into a reported error, and a reported error into a log line somebody can act on. What it cannot do is move a single bit across the boundary that dropped it. Treating the symptom is sometimes the right product decision and never the right diagnosis.
8. The Debug Record
Every major defect in this module is written up the same way, because the format is the habit:
| field | SIM B | SIM C |
|---|---|---|
| observed symptom | master waiting, one earlier op completed | identical |
| failing detector | none — no checker fires | none — no checker fires |
| reproduction | 2-op program, deterministic, no randomness | identical |
| first hypothesis | slave never acknowledged | slave never acknowledged |
| competing hypothesis | request never reached the slave | acknowledgement was lost returning |
| boundary observation | S1 phases opened = 0 | S1 phases opened = 1, ACKs = 391 |
| first causal divergence | cycle 10, decode-to-deliver | cycle 10, P3-to-P4 |
| root cause | target select suppressed | return path discards ACK |
| fix | forward the computed select | forward the termination |
| original test after fix | passes | passes |
| regression | clean | clean |
Two rows differ. They are the two that were measured rather than assumed.
9. What To Carry Forward
- A missing completion is a symptom with ten mechanisms. Naming one before observing anything is guessing with extra confidence.
- Find the last good boundary and the first bad one. Between them is the defect; outside them is noise.
- Sort evidence by location, not by count. SIM B and SIM C have identical counts and identical first-divergence cycles, and are nothing alike.
- Waiting is legal. A deadline is your system's, not Wishbone's, and the words you choose decide whether the next hour is an investigation or an argument.
- A timeout survives a missing response. It never repairs one.
Chapter 27.2 asks the harder version of the same question: the transfer completed, and it was acknowledged — but was it acknowledged by the right peripheral?
Continue learning
Related tutorials
- Related topic
Debug Checklist
A twelve-step procedure that ends in a proven mechanism, the evidence ladder that keeps you off the waveform, and three fixes that are not fixes.
- 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.
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.
