Skip to content

AMBA AHB · Module 7

Debugging Bad Responses

A debugging methodology for unexpected AHB responses — identify the response from the waveform, confirm the two-cycle handshake, read HADDR, and check the address map to localize the root cause of an ERROR (or a stray RETRY/SPLIT).

This chapter closes Module 7 by turning the response knowledge into a debugging skill — the response-side counterpart to chapter 6.7's wait-state debugging. When a transfer returns an unexpected non-OKAY response, you need a method to go from symptom (a bad response on a waveform) to root cause (why it happened). The method is compact: identify which response it is, confirm the two-cycle handshake, read HADDR to find the target, and check the address map to localize the cause. The guiding insight: the response tells you what went wrong (failure), but HADDR plus the address map tell you where and why. Most unexpected ERRORs trace to an unmapped address, a permission violation, an unsupported access, or a slave-internal fault — and a stray RETRY/SPLIT in an AHB-Lite system is itself the bug.

1. What Is It?

Debugging bad responses is a methodology for diagnosing an unexpected non-OKAY response from a waveform. The steps:

  1. Identify the response — read HRESP and confirm which non-OKAY response (ERROR, or legacy RETRY/SPLIT) it is.
  2. Confirm the two-cycle handshake — a non-OKAY response must be the defined two-cycle sequence (warning then completion); a malformed one is itself a bug.
  3. Read HADDR — find the address phase of the failing transfer to identify the target.
  4. Check the address map — is HADDR mapped? to which subordinate? is the access permitted? This localizes the root cause.
A decision tree branching from a non-OKAY response into ERROR (check address map for unmapped/permission/fault) and RETRY/SPLIT (expected in full AHB, a bug in AHB-Lite).
Figure 1 — a decision tree for an unexpected response. Identify which response from the waveform. ERROR: read HADDR and check the map — unmapped means a bad pointer or wrong map; mapped-but-errored means a permission violation, an unsupported access, or a slave-internal fault. RETRY/SPLIT: expected in a full-AHB multi-master system (trace to the slow/busy slave), but in an AHB-Lite/AHB5 system, seeing them at all is the bug — a slave is driving an illegal response. Always confirm the two-cycle handshake.

The core principle is the division of information: the response value (ERROR/RETRY/SPLIT) tells you the category of what went wrong, but it doesn't tell you where or why — for that, you read HADDR (the target address) and check it against the address map. An ERROR alone says "this failed"; HADDR plus the map says "this access to address X, which is unmapped / which subordinate Y rejected for reason Z." So debugging responses is fundamentally about combining the response (what) with the address (where) and the map (why). That combination localizes the root cause.

2. Why Does It Exist? (Why a method is needed)

A debugging method exists because a bad response is a symptom with many possible causes, and without a systematic approach you can't efficiently go from "something returned ERROR" to "this specific thing is wrong."

A non-OKAY response is the end of a causal chain, not the cause itself. An ERROR could come from a wild pointer (unmapped address), a misconfigured address map (subordinate not where expected), a permission/security violation (HPROT/HNONSEC), an unsupported access (bad size/alignment), a genuine hardware fault (ECC), or even a protocol violation. So "I saw an ERROR" is the start of an investigation, not the answer. A method is needed to narrow the cause systematically — which is exactly what reading HADDR and checking the map does: it distinguishes "wrong address" (unmapped) from "right address, rejected" (permission/access/fault), cutting the possibilities in half immediately. The method exists to make this narrowing systematic rather than guesswork.

The two-cycle-handshake check exists because a malformed response is itself a class of bug worth ruling in or out early. A correct non-OKAY response is the defined two-cycle sequence (chapter 7.5/7.6); if a waveform shows a single-cycle non-OKAY, or a non-OKAY held during a simple wait, that is a protocol violation — the subordinate is misbehaving. So confirming the handshake distinguishes "a legitimate ERROR I need to trace" from "a subordinate driving an illegal response" (a different bug entirely). The method includes this check because the shape of the response can itself be the bug, and you want to know that before chasing the address.

The RETRY/SPLIT-in-AHB-Lite check exists because version confusion is a real, distinctive bug. RETRY and SPLIT are full-AHB only (chapter 7.8); seeing them in a system that should be AHB-Lite/AHB5 means a subordinate is driving a response that shouldn't exist — an illegal response for that bus. So the method flags this immediately: a RETRY/SPLIT in AHB-Lite isn't a transfer to debug normally; it's a sign the subordinate is non-compliant with the bus's response set. The method exists partly to catch these version-mismatch bugs that a naive "just trace the response" approach would miss. So a systematic method is needed because bad responses have many causes, the response's shape can be the bug, and version mismatches are distinctive — all of which a structured approach handles efficiently.

3. Mental Model

Model debugging a bad response as a returned package with a "delivery failed" sticker — the sticker tells you it failed, but you read the address label and check it against the address book to learn whether the address was wrong, the recipient refused it, or the building doesn't accept that kind of package.

A package comes back with "delivery failed" (a non-OKAY response). The sticker (the response value) tells you that it failed and maybe a rough category, but not why. To diagnose, you read the address label on the package (HADDR — where it was going) and check it against your address book (the address map): Was the address even valid (mapped)? If not, you wrote the wrong address (bad pointer / wrong map). If the address was valid, why did it bounce — did the recipient refuse it (permission violation), was it the wrong kind of package for that address (unsupported access), or did something break on their end (slave fault)? You also check the sticker is a real failure notice, not a forged or malformed one (the two-cycle handshake — is this a legitimate response or a misbehaving slave?). The sticker says it failed; the address label and address book say where and why.

This captures the method: the "failed" sticker = the response value (what category); the address label = HADDR (where); the address book = the address map (why — mapped? permitted?); checking the sticker is legit = confirming the two-cycle handshake. You can't diagnose from the sticker alone — you need the address and the address book.

Read a bad response off a waveform:

Reading a bad response: HADDR plus the two-cycle ERROR

4 cycles
HADDR shows Abad in T0 (the failing transfer's address phase). HRESP is OKAY then ERROR for two cycles. HREADY is high, low, high. The ERROR's two-cycle handshake appears in the data phase one cycle after the Abad address phase; reading HADDR=Abad and checking the map localizes the cause.read HADDR=Abad — the target to check against the mapread HADDR=Abad — the …two-cycle ERROR completes — confirm the handshaketwo-cycle ERROR comple…HCLKHADDRAbadAbadAbadAbadHREADYHRESPOKAYERRORERROROKAYt0t1t2t3
Figure 2 — reading a bad response off a waveform. The failing transfer's address phase shows HADDR = a bad/unmapped address (Abad) in T0. One cycle later, its data phase shows the two-cycle ERROR (ERROR with HREADY low in T1, then ERROR with HREADY high in T2). To diagnose: read HADDR (Abad), check it against the address map (here, unmapped → the default subordinate returned ERROR → likely a bad pointer or wrong map). The address is the key to the root cause.

The model's lesson: read the address label (HADDR), not just the failure sticker (the response). In the waveform, the ERROR says "failed," but HADDR=Abad checked against the map says "unmapped — bad pointer." The address is what turns a symptom into a diagnosis.

4. Real Hardware Perspective

In hardware/simulation debugging, the practical workflow is to capture the waveform around the failing transfer, align the response to its address phase (accounting for the pipeline), read HADDR, and cross-reference the system's address map — with protocol assertions often flagging the issue first.

The pipeline alignment is a practical detail (chapters 5.2, 7.5): the response appears in the data phase, one cycle after the failing transfer's address phase. So when you see a bad HRESP, the relevant HADDR is the one from one cycle earlier (the address phase of the transfer now in its data phase). A common debugging mistake is reading the HADDR present at the same time as the ERROR — which is actually the next transfer's address (pipelined ahead). So you must align the response back to its own address phase. Getting this alignment right is essential to reading the correct target address. (This is the same pipeline-ownership care as chapter 6.4.)

Protocol assertions often catch the issue first (foreshadowing the verification modules). A testbench with AHB assertions will fire on an unexpected ERROR, a malformed (single-cycle) non-OKAY, a non-OKAY during a simple wait, or a RETRY/SPLIT on an AHB-Lite bus — pointing you straight to the failing transfer. So in a well-instrumented environment, the assertion tells you which transfer and what kind of violation, and your job is to trace the root cause (read HADDR, check the map). Assertions turn "something's wrong somewhere" into "this transfer violated this property," which is the starting point for the address-map cross-reference. So debugging responses in practice is often assertion-driven: the assertion localizes, you diagnose.

The address-map cross-reference is the diagnostic core in hardware. You take the HADDR from the failing transfer and look it up in the system's memory map (the decode configuration, chapters 3.9, 12.x): Is it in a defined region? Which subordinate owns it? What are its access rules? This lookup distinguishes the causes: not-in-any-region → unmapped (default subordinate's ERROR — bad pointer or wrong map); in-a-region-but-errored → that subordinate rejected it (check its permission rules, supported sizes, or fault status). So the address map is the reference that turns the target address into a root cause. In practice you keep the system's memory map handy when debugging responses — it's the key the whole method turns on.

A four-step workflow for reading a bad response from a waveform: find the address phase, read the data-phase response, check the address map, and verify the master's reaction.
Figure 3 — reading a bad response off a waveform, step by step. (1) Find the failing transfer's address phase and note HADDR (the target) — the response belongs to the transfer addressed one cycle earlier. (2) Look one cycle later at the data phase, read HRESP, and confirm the two-cycle handshake. (3) Check HADDR against the address map to localize the cause. (4) Confirm the master reacted correctly (cancelled the next transfer, faulted) — if not, the bug is master-side.

A hardware note on distinguishing master-side vs slave-side bugs: after identifying the response and its cause, check that the master handled it correctly (chapter 7.7) — did it cancel the next transfer (HTRANS→IDLE in the warning cycle) and fault appropriately? If the slave's ERROR was legitimate but the master mishandled it (e.g., consumed the invalid data, or failed to cancel the next transfer), the bug is master-side, not slave-side. So the method also checks the master's reaction, because a "bad response" symptom can actually be a master mis-handling a correct response. Localizing the bug to the right component (slave generating, or master handling) is part of the diagnosis.

5. System Architecture Perspective

At the system level, response debugging is where bus-level symptoms connect to system-level faults — an ERROR on a waveform usually corresponds to a software bug (bad pointer), a configuration error (wrong address map), a security event (denied access), or a hardware fault, and the method bridges from the bus trace to the system-level cause.

The software-bug connection is the most common: an unexpected ERROR frequently traces to a software bug — a wild or uninitialized pointer dereferencing unmapped or wrong memory. So when debugging an ERROR, the bus trace (HADDR=unmapped) often points back to faulty software that generated the bad address. The bus is doing its job (catching the bad access via ERROR); the root cause is in the software that issued it. So response debugging frequently bridges from a bus waveform to a software defect — the ERROR is the bus catching what the software did wrong. This is why bus faults are a key debugging tool for software: they pinpoint bad accesses.

The configuration-error connection is the next most common: an ERROR (or a transfer hitting the wrong subordinate) can mean the address map is misconfigured — a subordinate placed at the wrong base address, an overlapping region, or a gap. So response debugging also surfaces system integration errors: the components are fine, but the address map wiring them together is wrong. Here the fix is in the decode/interconnect configuration, not the master or subordinate. So the method distinguishes a software bug (bad address from correct map) from a configuration bug (correct address, wrong map) — both surface as ERROR, but the fix is in different places, and the address-map cross-reference is what tells them apart.

The security-event connection ties response debugging to the system's protection architecture: a permission/security ERROR (HPROT/HNONSEC violation) may be a legitimate security denial (the system correctly blocking an unauthorized access) rather than a bug — so part of debugging is determining whether an ERROR is a fault to fix or a security policy working as intended. A non-secure access to a secure region should ERROR; that's not a bug, it's the protection enforcing itself (chapter 7.2). So response debugging includes recognizing when an ERROR is correct behavior (security working) versus a defect. This requires understanding the system's protection policy, connecting bus debugging to the security architecture. So at the system level, response debugging bridges the bus trace to software bugs, configuration errors, security events, and hardware faults — making it a key skill for system bring-up and integration, where these issues surface as bad responses on the bus.

6. Engineering Tradeoffs

Response debugging reflects the symptom-to-cause, assertion-assisted approach.

  • Systematic method vs ad-hoc guessing. A structured method (identify → confirm handshake → read HADDR → check map) localizes the cause efficiently; ad-hoc guessing wastes time. The method's small overhead (a few systematic steps) pays off in fast, reliable diagnosis — worth it for a symptom with many causes.
  • Assertion-driven vs manual waveform hunting. Protocol assertions catch and localize violations automatically (fast, reliable) at the cost of writing/maintaining them. Manual waveform inspection needs no setup but is slow and error-prone at scale. Well-instrumented environments invest in assertions; the method uses them as the starting point when available.
  • Address-map-centric vs response-centric diagnosis. Centering the diagnosis on HADDR + the address map (rather than the response value alone) localizes the cause; the response value alone only gives the category. The map cross-reference is the higher-value step — it's where the root cause is found.
  • Distinguishing slave-generate vs master-handle bugs. Checking both the slave's response and the master's reaction catches master-side bugs that masquerade as bad responses, at the cost of an extra check. Worth it — a mishandled correct response is a real and easily-misattributed bug.

The throughline: response debugging is a systematic symptom-to-cause method — identify the response, confirm its shape, read HADDR, check the address map — that bridges a bus-level bad response to its system-level root cause (software bug, config error, security event, or hardware fault). The approach is assertion-assisted where possible and address-map-centric always. Its small structured overhead buys efficient, reliable diagnosis of a symptom that otherwise has confusingly many possible causes.

7. Industry Example

Trace several response-debugging sessions during system bring-up.

A team brings up a new SoC and hits various bad responses on the AHB.

  • Unexpected ERROR → software bad pointer. A test fails with an ERROR. The team captures the waveform, aligns the response to its address phase, reads HADDR — an address in unmapped space. The default subordinate returned ERROR. Root cause: a software bug — an uninitialized pointer dereferenced unmapped memory. Fix: the software. The bus correctly caught the bad access.
  • Unexpected ERROR → wrong address map. Another test errors on an access that should hit a peripheral. HADDR looks correct, but checking the map reveals the peripheral was configured at the wrong base address in the decoder — so the address decoded to unmapped space. Root cause: a configuration error in the interconnect's address map. Fix: correct the decode configuration. The components were fine; the map was wrong.
  • Permission ERROR → security working as intended. A non-secure test accesses a secure region and gets ERROR. Investigation shows this is correct — the security policy (HNONSEC) properly denied the unauthorized access. Not a bug; the protection is working. The "fix" is to recognize the test was doing something it shouldn't, or that the denial is expected.
  • Malformed response → non-compliant slave. A custom subordinate drives a single-cycle ERROR (no warning cycle). A protocol assertion fires on the malformed handshake. Root cause: the subordinate's response logic is non-compliant (it skips the mandatory two-cycle sequence, chapter 7.6). Fix: the subordinate's RTL. The shape of the response was the bug.
  • RETRY in AHB-Lite → illegal response. A subordinate in the AHB-Lite system drives a RETRY response. Since AHB-Lite has no RETRY (chapter 7.8), this is immediately flagged as illegal — the subordinate is non-compliant with the bus's response set. Fix: the subordinate (it should use wait states or ERROR). Seeing RETRY at all was the bug.
  • "Bad response" that's actually master-side. A transfer's ERROR is legitimate (unmapped test address), but the system crashes oddly afterward. Checking the master reveals it consumed the read data despite the ERROR (chapter 7.7) — using garbage. Root cause: a master-side handling bug (it didn't gate consumption on OKAY). Fix: the master. The slave's response was correct; the master mishandled it.

The example shows the method localizing diverse root causes: a software bad pointer, a configuration error, a correct security denial, a non-compliant slave (malformed and illegal responses), and a master-side handling bug. In each, the response was the symptom; reading HADDR, checking the map, confirming the handshake, and verifying the master's reaction localized the actual cause — across software, configuration, security, slave RTL, and master RTL. This breadth is why a systematic method matters during bring-up.

8. Common Mistakes

9. Interview Insight

Response debugging is a practical interview topic — it tests whether you can reason systematically from a waveform symptom to a root cause.

A summary card describing the response-debugging method: identify, confirm handshake, read HADDR, check the address map, with the what-vs-where-and-why division.
Figure 4 — a strong answer in one card: to debug a bad response, identify it and confirm the two-cycle handshake, then read HADDR and check it against the address map — unmapped means a bad pointer or wrong map; mapped-but-errored means permission, bad access, or fault; RETRY/SPLIT in an AHB-Lite system is itself the bug. The senior point: the response says what failed, but HADDR plus the address map say where and why.

The answer that lands gives a systematic method: "I'd identify the response and confirm it's a proper two-cycle handshake — a malformed single-cycle non-OKAY is itself a bug. Then the key step: align the response back to its own address phase (it's in the data phase, one cycle after) and read HADDR to find the target. Then check HADDR against the address map. If it's unmapped, the default subordinate returned ERROR — likely a bad pointer or a misconfigured map. If it's mapped but errored, that subordinate rejected it — check permissions (HPROT/HNONSEC), supported access sizes, or a fault. The principle is that the response tells me what category of failure, but HADDR plus the map tell me where and why. I'd also check the master handled it correctly — a master consuming data on an ERROR is a master-side bug. And if I saw RETRY or SPLIT on an AHB-Lite bus, that's immediately the bug — they're full-AHB only." The systematic method, the what-vs-where-and-why division, and the master-side check are the senior signals.

10. Practice Challenge

Reason from the debugging method.

  1. State the method. Give the four steps for diagnosing an unexpected response.
  2. Read the waveform. From Figure 2, explain how to find the failing transfer's target address and why alignment matters.
  3. Classify an ERROR. Given an ERROR at an unmapped HADDR vs a mapped HADDR, give the likely cause for each.
  4. Legitimate vs defect. Give an example where an ERROR is correct behavior, not a bug.
  5. Localize the component. Explain how to tell a slave-generation bug from a master-handling bug.

11. Key Takeaways

  • Method: identify the response, confirm the two-cycle handshake, read HADDR (aligned to its address phase), and check the address map.
  • The response says what failed (category); HADDR + the address map say where and why — always cross-reference the address.
  • Unmapped HADDR → bad pointer or wrong map; mapped-but-errored → permission/security, unsupported access, or slave fault.
  • An ERROR is often the bus working correctly — catching a software bad pointer or enforcing security. Ask whether the access should have succeeded before assuming a defect.
  • A malformed response (single-cycle non-OKAY) or RETRY/SPLIT on an AHB-Lite bus is itself the bug — a non-compliant subordinate.
  • Check the master's reaction too — a master mishandling a correct response (e.g., consuming data on ERROR) is a master-side bug masquerading as a bad response.

12. What Comes Next

This completes Module 7 — Responses. You now understand OKAY, ERROR, the legacy RETRY/SPLIT, response timing, the two-cycle ERROR handshake, how the master reacts, the AHB-Lite simplification, and how to debug bad responses. The next module turns to the efficiency mechanism that defines AHB's data movement:

  • Module 8 — Burst Transfers (coming next) — bursts, the HBURST encodings, INCR/WRAP types, beat sequencing, and how bursts amortize the address phase for efficient data movement.

To revisit the responses, see OKAY Response, ERROR Response, The Two-Cycle ERROR Response, and How the Master Reacts. For the address decode this method cross-references, see HSEL and Master, Slave, Decoder & Arbiter. For the broader protocol map, see the AMBA family overview.