AMBA AHB · Module 16
HRESP Generation
Generating correct slave responses — HRESP OKAY (low) for normal transfers, ERROR (high) for accesses the slave cannot or should not perform (reserved addresses, illegal access types, protection violations, unsupported sizes). The ERROR response is a mandatory two-cycle sequence (HRESP=ERROR both cycles, HREADYOUT low then high) so the pipelined master can cancel the next address-phase transfer it had already issued; an errored access must not change slave state. AHB-Lite uses only OKAY and ERROR.
The slave's outputs so far: HREADYOUT (the pace — 16.4) and HRDATA (the read data — 16.5). This chapter builds the last one: HRESP, the slave's response — did the transfer succeed? For a normal transfer the slave responds OKAY (HRESP low), completing in one cycle. But for an access the slave cannot or should not perform — a reserved/unmapped address, an illegal access type (write to read-only), a protection violation, an unsupported size — the slave must signal ERROR (HRESP high). The catch: ERROR is a mandatory two-cycle sequence, not a single cycle. In the first error cycle the slave drives HRESP = ERROR with HREADYOUT low (not yet completing); in the second, it keeps HRESP = ERROR and drives HREADYOUT high (completing, error reported). Why two cycles? Because the master is pipelined — by the time the slave signals the error, the master has already issued the next transfer's address phase; the two-cycle sequence gives the master a cycle to see the error coming and cancel that already-issued transfer before it commits (the two-cycle ERROR response). (AHB-Lite uses only OKAY and ERROR — the RETRY/SPLIT of full AHB aren't used — chapter 7.) And critically, an errored access must not change the slave's state. This chapter builds HRESP generation, the two-cycle ERROR FSM, and the do-not-corrupt-state rule.
1. What Is It?
HRESP generation is the slave logic that drives the HRESP response — OKAY for normal transfers, the two-cycle ERROR for faulted ones. Its parts:
- OKAY (
HRESPlow) — the normal response: the transfer succeeded; complete in one cycle (HREADYOUThigh). - ERROR (
HRESPhigh) — for accesses the slave can't/shouldn't do (reserved address, illegal type, protection violation, unsupported size). - The two-cycle ERROR — cycle 1:
HRESP = ERROR,HREADYOUTlow; cycle 2:HRESP = ERROR,HREADYOUThigh (completes). - No state change on error — an errored write must not update state; an errored read returns no meaningful data. The slave stays clean.
So HRESP generation is the slave's status report on each transfer. Most transfers are fine — the slave responds OKAY (HRESP low) and completes normally. But some accesses are invalid — a read/write to an address with nothing there (reserved), a write to a read-only register, an access forbidden by protection/privilege, a size the slave can't handle. For these, the slave must not silently complete (which would hide the fault, or corrupt state) — it must signal ERROR (HRESP high). And the ERROR response is specifically a two-cycle handshake — HREADYOUT low then high, HRESP held ERROR throughout — mandated by the protocol so the pipelined master can react (cancel its already-issued next transfer). Plus the invariant: an errored access leaves the slave's state unchanged (no corruption). So HRESP generation is the slave's correct, two-cycle error reporting. So it's how a slave says "no".
2. Why Does It Exist?
HRESP exists because some bus accesses are invalid or impossible, and the slave must report that rather than silently failing — and the ERROR is two cycles because the pipelined bus requires the master a chance to unwind the transfer it has already started after the faulted one.
The errors must be reported is the root: not every access can succeed. The master might address a reserved location (nothing there), write a read-only register, attempt a forbidden (privilege/security) access, or request an unsupported size. If the slave silently completed such an access (responding OKAY), the fault would be hidden — the software would think a bad write succeeded, a read of nothing returned valid data, a forbidden access was allowed. That's dangerous — silent corruption, security holes, undetected bugs. So the slave must report the fault — HRESP = ERROR — so the master (and software) knows and can handle it (a bus-fault exception). So HRESP exists to surface invalid accesses rather than hiding them. So it's fault reporting. So errors must be visible.
The pipeline requires two cycles drives the ERROR timing: the bus is pipelined — the address phase of transfer N+1 overlaps the data phase of transfer N (chapter 3). So when the slave, in transfer N's data phase, detects an error, the master has already driven transfer N+1's address phase (it's committed to issuing N+1). If the error were a single cycle (complete immediately with ERROR), the master would have no clean way to cancel N+1 — it's already in flight. So the ERROR response takes two cycles: the first cycle (HREADYOUT low) signals the error while holding — giving the master a cycle to see HRESP = ERROR and decide to cancel N+1; the second cycle (HREADYOUT high) completes the errored transfer, and the master does not commit N+1 (it re-issues or abandons it). So the two cycles exist to let the pipelined master unwind the already-issued next transfer cleanly. So ERROR is two cycles because of pipelining. So the timing is structural.
The no-state-change invariant is why error handling is careful: an errored access must leave the slave's state unchanged — an errored write must not update the register/memory; an errored read must not trigger side effects (no FIFO pop, no clear). Because the access was invalid, performing it would corrupt state. So the slave must detect the error before committing the access and suppress the state change. So HRESP generation is coupled to suppressing the access. So HRESP exists because: invalid accesses must be reported, not hidden (the why — fault visibility, security, correctness); the pipelined bus needs two cycles so the master can cancel its already-issued next transfer (the timing — pipeline unwinding); and the errored access must not change slave state (the invariant — no corruption). So HRESP is the slave's correct failure mode — surfacing invalid accesses with a protocol-mandated two-cycle handshake that keeps the pipeline coherent, while leaving the slave uncorrupted. So this chapter builds the slave's "no" correctly. So errors are reported cleanly.
3. Mental Model
Model the two-cycle ERROR as a bank teller rejecting a transaction you handed over while you were already sliding the next form under the window. The teller can't just stamp "DENIED" and vanish — you've got another request in motion. So they first hold up a "PROBLEM — wait" card (cycle 1: error flagged, not done), giving you a beat to pull back the next form you'd already pushed; then they finalize the rejection and free the window (cycle 2: error completes), and you don't submit that next form. And crucially, a rejected transaction changes nothing in your account — no money moves.
A bank window where you and the teller work in a pipeline — while the teller processes your current request, you're already sliding the next form under the window (the next transfer's address phase, issued before the current one finishes). Now suppose your current request is invalid — you tried to withdraw from a closed account (a reserved address), or write to a statement-only record (a read-only register), or access an account you're not authorized for (a protection violation). The teller must reject it. But they can't just stamp "DENIED" and instantly slam the window — because you've already got the next form in motion, and slamming would leave that next request in a messy, half-submitted state. So the rejection takes two beats. Beat one: the teller holds up a "PROBLEM — please wait" card (HRESP = ERROR, HREADYOUT low) — flagging the error but not finalizing. This gives you a beat to notice the problem and pull back the next form you were sliding in (the master sees the error and prepares to cancel its already-issued next transfer). Beat two: the teller finalizes the rejection and frees the window (HRESP = ERROR held, HREADYOUT high — the errored transfer completes), and you don't submit that next form (the master doesn't commit N+1). And crucially: the rejected transaction changed nothing — no money moved, your balance is exactly as before (the errored access doesn't change the slave's state). If the teller had single-beat rejected, your half-slid next form would've jammed the window (the pipeline would be incoherent). The two beats exist precisely to let you cleanly pull back what you'd already started.
This captures the two-cycle ERROR: you sliding the next form while the current is processed = the pipelined master issuing N+1's address phase during N's data phase; the invalid request = a reserved/illegal/forbidden access; beat one, the "PROBLEM — wait" card = cycle 1 (HRESP = ERROR, HREADYOUT low — error flagged, not complete); you noticing and pulling back the next form = the master seeing the error and preparing to cancel N+1; beat two, finalizing and freeing the window = cycle 2 (HRESP = ERROR, HREADYOUT high — completes); you not submitting the next form = the master not committing N+1; no money moved = the errored access not changing slave state. Two beats so the pipeline unwinds cleanly, and the account stays untouched.
Watch the two-cycle ERROR and the master cancelling its next transfer:
The mandatory two-cycle ERROR response
4 cyclesThe model's lesson: two beats so the pipeline unwinds cleanly, and the account stays untouched. In the waveform, HRESP is ERROR for both error cycles, HREADYOUT goes low then high, the master cancels its already-issued next transfer, and the slave's state is unchanged.
4. Real Hardware Perspective
In hardware, HRESP is a single output driven OKAY by default and ERROR by a small FSM (the two-cycle sequence) when an error condition is detected; the error detection is combinational logic over the captured access; and the state-update logic is gated to suppress changes on error.
The error detection: the slave detects an error by combinational checks over the captured access context (addr_q, write_q, size, protection). The checks: is addr_q in a reserved/unmapped sub-region? Is this a write to a read-only register (write_q && is_RO(addr_q))? Does the protection/privilege fail (!allowed(HPROT_q, addr_q))? Is the size unsupported? Any true → an error condition for this access. So in hardware, error detection is combinational logic over the captured access. So it's a set of checks. So the slave knows when to error.
The two-cycle ERROR FSM: when an error is detected, a small FSM drives the two-cycle sequence. From the OKAY state, on an error condition the FSM goes to ERROR-1: HRESP = ERROR, HREADYOUT = 0 (signal, don't complete). Next cycle, ERROR-2: HRESP = ERROR (held), HREADYOUT = 1 (complete). Then back to OKAY. The FSM ensures HRESP is ERROR for both cycles and HREADYOUT is low then high — the exact protocol sequence. (Note: HRESP must be ERROR in both cycles — a common bug is asserting it only one cycle.) So in hardware, the two-cycle ERROR is a 2-state FSM sequence. So it's a small state machine. So that's the response timing.
The state-update suppression: critically, the state-update logic must be gated by the error condition — if (sel_q && write_q && !error_condition) regs[addr_q] <= HWDATA (and likewise suppress read side effects on error). So an errored write does not update state; an errored read does not pop a FIFO or clear a flag. The slave detects the error and suppresses the access atomically. So in hardware, the write-enable / side-effect logic is gated by !error — keeping state clean on errors. So in hardware, HRESP generation is: combinational error detection over the captured access, a 2-state FSM driving the two-cycle ERROR sequence (HRESP=ERROR both cycles, HREADYOUT low-then-high), and gated state-update logic suppressing changes on error. The FSM sequence and the state suppression are the two pieces to get right. So in hardware, detect, sequence, and suppress. So it's three coupled pieces.
5. System Architecture Perspective
At the system level, HRESP is the bus's error-signaling mechanism — how a hardware fault (bad address, illegal access) becomes a software-visible exception — and its two-cycle timing and state-protection are what make error handling coherent across the pipelined bus and safe for the system.
The hardware-to-software fault path: HRESP = ERROR is the start of a fault path that ends in software. The slave signals ERROR; the master (the CPU's bus interface) receives it and raises a bus-fault exception (a hardware trap); the software exception handler then responds (logs the fault, kills the offending process, recovers). So HRESP is the hardware origin of a bus fault — the mechanism by which a bad access becomes a handled exception. So at the system level, HRESP is the bus's fault-reporting channel into software. So it's the error path's source. So faults flow from HRESP.
The pipeline coherence: the two-cycle timing is what keeps the pipelined bus coherent on an error. Without it, an error on transfer N would leave the already-issued transfer N+1 in an ambiguous state (did it happen? was it cancelled?). The two cycles give the master a defined window to cancel N+1 cleanly — so the bus always has a coherent view of which transfers happened. So at the system level, the two-cycle ERROR is a pipeline-coherence mechanism — ensuring errors don't corrupt the transfer stream. So it's coherence under faults. So the pipeline stays consistent.
The system safety: the no-state-change invariant is a safety property — an invalid access must not corrupt the system. A forbidden write (security violation) must not alter protected state; a bad address must not trigger a side effect. So the slave's error-then-suppress behavior is a system-safety guarantee — invalid accesses are inert. This is especially critical for security (a denied access leaks/corrupts nothing) and robustness (a buggy access doesn't cascade). So at the system level, HRESP is the bus's error-signaling mechanism (the hardware origin of a software bus-fault exception — the fault path into software), its two-cycle timing maintains pipeline coherence under errors (a clean window to cancel the already-issued next transfer), and its no-state-change invariant is a system-safety guarantee (invalid accesses are inert — critical for security and robustness). So HRESP is where a hardware fault becomes a coherent, safe, software-visible event — making correct error generation essential to a trustworthy system. So report faults, keep the pipeline coherent, and never corrupt state.
6. Engineering Tradeoffs
HRESP generation embodies the report-not-hide, two-cycle, protect-state design.
- ERROR vs silent OKAY on a bad access. Signaling
ERRORsurfaces the fault (correct, safe, debuggable); silently respondingOKAYhides it (dangerous — corruption, security holes, undetected bugs). AlwaysERRORon an invalid access. - Two-cycle ERROR vs (illegal) one-cycle. The two-cycle sequence is mandatory (keeps the pipeline coherent — lets the master cancel N+1); a one-cycle "error" violates the protocol and leaves N+1 ambiguous. Always two cycles.
- Detect-and-suppress vs perform-then-undo. Detecting the error before committing and suppressing the access keeps state clean (correct); performing then trying to undo risks corruption/side effects. Detect and suppress atomically.
- Robust (full error checks) vs minimal (no checks). Full error checks (reserved, RO, protection, size) catch faults (robust, secure) at the cost of logic; minimal checks (assume valid) are smaller but unsafe. Implement the checks that matter for the slave's role.
The throughline: HRESP is the slave's response — OKAY (HRESP low) for a normal transfer, ERROR (HRESP high) for an access the slave cannot/should not perform (reserved address, illegal type, protection violation, unsupported size). The ERROR response is a mandatory two-cycle sequence: cycle 1 (HRESP=ERROR, HREADYOUT low — signal), cycle 2 (HRESP=ERROR held, HREADYOUT high — complete) — the two cycles let the pipelined master cancel its already-issued next transfer. An errored access must not change slave state (no corruption — a safety invariant). AHB-Lite uses only OKAY/ERROR. It's the bus's error-signaling mechanism — the hardware origin of a software bus-fault, keeping the pipeline coherent and the system safe.
7. Industry Example
Build the error responses for a peripheral with a reserved region and read-only registers.
A peripheral has registers (some read-only), a data region, and reserved address holes — and must error correctly on misuse.
- Reserved-address access → ERROR. A read or write to a reserved hole in the peripheral's region (no register there) triggers
ERROR. The slave's detection:addr_qdecodes to a reserved index → error condition. The two-cycle sequence runs; the master takes a bus fault. No state changes (there's nothing there anyway). - Write to a read-only register → ERROR. A write to the STATUS register (read-only) triggers
ERROR:write_q && is_RO(addr_q)→ error condition. Critically, the STATUS register is not written (state-update gated by!error). The two-cycle sequence runs; the master faults. (A read of STATUS is fine —OKAY.) - Protection violation → ERROR. If the peripheral is privileged-only and an unprivileged access arrives (
HPROT_qindicates user mode), the slave errors:!privileged(HPROT_q)→ error condition. The access is suppressed (no read/write performed) — a security guarantee. Two-cycle ERROR; master faults. - The two-cycle sequence. For each error, the slave drives
HRESP = ERRORwithHREADYOUTlow (cycle 1), thenHRESP = ERRORheld withHREADYOUThigh (cycle 2). The master, having issued the next transfer's address phase, sees the error and cancels that next transfer. - Normal accesses → OKAY. All valid accesses (read any register, write a RW/W1C register, read/write the data region) respond
OKAY(single cycle) — the common case. - The master's handling. On
ERROR, the master raises a bus-fault exception; software's handler logs the fault (which address, read/write) and recovers (chapter 7.7).
The example shows HRESP in action: OKAY for valid accesses (the common case), the two-cycle ERROR for reserved-address, read-only-write, and protection violations, with the errored access suppressed (no state change — especially the security-critical protection case), and the master faulting on the error. This is correct slave error reporting — surfacing faults safely and coherently. This is the slave's "no".
8. Common Mistakes
9. Interview Insight
HRESP generation is a classic RTL interview topic — the OKAY/ERROR meaning, the two-cycle ERROR sequence (and why), and the no-state-change invariant are the signals.
The answer that lands gives the response and the two-cycle reasoning: "HRESP is the slave's response output. For a normal transfer it drives OKAY, which is HRESP low, completing in one cycle. For an access it can't or shouldn't perform — a reserved or unmapped address, a write to a read-only register, a protection violation, an unsupported size — it drives ERROR, HRESP high. The key detail is that ERROR is a mandatory two-cycle response, not one cycle. In the first cycle the slave drives HRESP to ERROR with HREADYOUT low — signalling the error but not completing. In the second cycle it holds HRESP at ERROR and drives HREADYOUT high — completing the transfer. Two things must be right: HRESP is held ERROR for both cycles, because the master samples the response when HREADYOUT is high, which is the second cycle — if you dropped HRESP to OKAY in the second cycle, the master would miss the error. And HREADYOUT is low then high. The reason it's two cycles is pipelining: by the time the slave detects the error in the current transfer's data phase, the master has already issued the next transfer's address phase. The two cycles give the master a window to see the error coming and cancel that already-issued next transfer cleanly, keeping the pipeline coherent. The other critical thing is that an errored access must not change the slave's state — an errored write must not update the register, an errored read must not trigger a side effect like a FIFO pop. You gate the state update by the not-error condition, so an invalid access is inert. That's a safety property, especially for protection violations. And note AHB-Lite only has OKAY and ERROR — RETRY and SPLIT are full AHB; a busy slave just inserts wait states." The OKAY/ERROR meaning, the two-cycle sequence with the pipeline reasoning, the hold-HRESP-both-cycles detail, and the no-state-change invariant are the senior signals.
10. Practice Challenge
Build and reason from HRESP generation.
- OKAY and ERROR. State what
OKAYandERRORmean, and list the conditions under which a slave respondsERROR. - The two-cycle sequence. Describe the two-cycle
ERROR(HRESP and HREADYOUT in each cycle) and explain why it's two cycles. - Read the waveform. From Figure 2, explain the two error cycles, when the master cancels its next transfer, and that the slave's state is unchanged.
- Hold HRESP both cycles. Explain why
HRESPmust beERRORin both cycles and the bug if it's asserted only once. - Protect state. Explain why an errored access must not change state, and how the RTL enforces it (gating).
11. Key Takeaways
HRESPis the slave's response —OKAY(low) for a normal transfer,ERROR(high) for an access the slave can't/shouldn't perform (reserved address, illegal type, protection violation, unsupported size).- The
ERRORresponse is a mandatory two-cycle sequence — cycle 1:HRESP=ERROR,HREADYOUTlow; cycle 2:HRESP=ERROR(held),HREADYOUThigh (completes). - Two cycles exist for the pipeline — the master has already issued the next transfer's address phase; the two cycles let it cancel that transfer cleanly (pipeline coherence).
- Hold
HRESP=ERRORin both cycles — the master samples the response whenHREADYOUTis high (the second cycle); dropping it early makes the master miss the error. - An errored access must not change slave state — gate the write-enable/side-effects by
!errorso invalid accesses are inert (a safety/security guarantee). - AHB-Lite uses only
OKAY/ERROR—RETRY/SPLITare full-AHB; a busy slave inserts wait states, not aRETRY.HRESPis the hardware origin of a software bus-fault.
12. What Comes Next
You now can generate correct responses, including the two-cycle ERROR. The next chapters drill into the slave's capture and FSM internals:
- Address / Control Capture (next) — capture address-phase control for use in the data phase (the discipline underlying every slave output).
- Write FSM, Read FSM, and Bridge FSM (RTL) — the slave's sequential control.
To revisit the ERROR response from the protocol side, see The Two-Cycle ERROR Response and How the Master Reacts; for the pace signal the sequence uses, see HREADYOUT Generation.