AMBA APB · Module 13
Error Propagation
Translating APB's single-cycle PSLVERR verdict into the upstream protocol's native error response — AHB's two-cycle HRESP=ERROR, or AXI4-Lite's BRESP/RRESP=SLVERR — correctly sequenced and aligned to the erroring transaction, so a peripheral fault becomes a CPU bus fault rather than being silently lost.
A peripheral that fails reports it as a single-cycle PSLVERR — but the CPU lives on AHB or AXI and has never heard of PSLVERR. The bridge's job on error is translation: turn APB's one-cycle error verdict into the upstream protocol's native error response — AHB's two-cycle HRESP=ERROR handshake, or AXI4-Lite's BRESP/RRESP=SLVERR response code — correctly sequenced and aligned to the exact transaction that erred. Get the sequencing or the alignment wrong and a real peripheral fault is silently swallowed between the slave and the software. This chapter is only the error path; its wait-state sibling, 13.4, owns PREADY.
1. Problem statement
The problem is carrying a peripheral's failure verdict across the protocol boundary: an APB slave signals an error with a single-cycle PSLVERR, but the master that issued the access speaks AHB or AXI, whose error mechanisms are completely different. The bridge must convert one into the other, for the right transaction, or the fault disappears.
Concretely, three things have to line up:
- The error verdict is single-cycle and downstream. APB asserts
PSLVERRfor exactly one cycle, sampled together withPREADYat ACCESS completion. The upstream master never sees that signal — it only sees the bridge's AHB/AXI response. If the bridge does not capturePSLVERRat that completion edge and turn it into an upstream error, the verdict is gone the very next cycle. - The upstream error mechanism is not the same shape. AHB reports an error as a two-cycle
HRESP=ERRORresponse — a specific handshake the bridge must generate:HRESP=ERRORwithHREADYlow for one cycle, thenHRESP=ERRORwithHREADYhigh. AXI4-Lite reports it as a 2-bit response code (SLVERR = 0b10) on theBchannel for a write or theRchannel for a read. The bridge must produce whichever is correct, in the correct shape. - The error must be aligned to the transaction that erred. With pipelining and (on AXI) independent channels, "an error happened" is not enough — it must be reported for the access that failed, on the right AHB transfer or the right
B/Rresponse. An error reported one transaction late, or on the wrong beat, corrupts a different access and the real one passes clean.
So the job is not "raise an error flag" — it is to translate a single-cycle downstream verdict into a correctly-shaped, correctly-aligned upstream error response, every time a peripheral says no.
2. Why previous knowledge is insufficient
You already know each piece in isolation; what you have not done is map one onto another across the bridge.
- You know the APB error semantics. Module 9 — PSLVERR behaviour taught you that
PSLVERRis sampled withPREADYat ACCESS, is only meaningful then, and means "this transfer failed." But Module 9 treated APB as the whole world — the error stopped at the APB manager. Here the APB manager is the bridge, and the error is only halfway home: it must keep travelling upstream. - You know the AHB error response. AHB
HRESPtaught you the two-cycleERRORresponse — that AHB errors are not a single pulse but a sequenced handshake the slave drives. But you saw it from the AHB master's seat, receiving it. Now the bridge must generate it, on demand, triggered by a downstreamPSLVERRit sampled a cycle earlier — and get the two-cycle sequencing exactly right, which an AHB-master-only view never required. - You know the AXI response codes. AXI
BRESPand the read-response field taught youOKAY/SLVERR/DECERRas 2-bit codes returned on theBandRchannels. But you have never had to decide which code a downstream APB result maps to, nor place it on the right channel for the right transaction. - The bridge fuses these into one obligation. The bridge itself, 13.1, established
PSLVERR → HRESP=ERRORas one of its two cross-boundary translations but only sketched it. The error translation has its own correctness rules — sequencing, alignment, decode-vs-slave error — that nothing prior covered. And the bridge's own address decode can manufacture an error too, which forward-links to 13.6 — bridge address mapping: an unmapped address inside the bridge becomes an upstreamDECERR, never reaching APB at all.
The model to add: the bridge as an error translator — sampling a single-cycle downstream verdict and re-emitting it in the upstream protocol's native, correctly-sequenced form.
3. Mental model
The model: the bridge is a courier carrying a sealed verdict from the peripheral to the CPU — and the verdict must arrive in the language and envelope the CPU expects, stamped with the right transaction's name. The peripheral hands over a one-cycle slip that says "this access failed." The courier cannot just shrug and lose it (the CPU would think all is well); it must re-write the verdict in AHB's two-cycle ERROR form or AXI's response-code form, and deliver it against the same transaction that failed — not the next one.
Three refinements make it precise:
- Sample the verdict at the completion edge, then re-emit it upstream.
PSLVERRis only valid the cyclePREADYis high. The bridge samples both together; ifPSLVERR=1, that access's upstream response becomes an error. Because the bridge already holdsHREADYlow (orBVALID/RVALIDnot yet asserted) until APB completes, the error and the completion arrive upstream together — naturally aligned to the transaction. - Emit the upstream protocol's native error shape. On AHB that is the two-cycle ERROR response: cycle 1
HRESP=ERRORwithHREADY=0, cycle 2HRESP=ERRORwithHREADY=1. The bridge must drive both cycles; a one-cycle pulse is not a legal AHB error and the master may mis-handle it. On AXI4-Lite it is the 2-bit codeSLVERR (0b10)onBRESP(write, on theBchannel) orRRESP(read, on theRchannel) — a single response beat, no extra sequencing. - Read data and write response on error are defined, not ignored. On an erroring read, the master should not trust the data — but the bridge still must complete the response (drive
HRDATA/RDATA, often whatever the peripheral returned, and flag the error). On an erroring write, there is no data to return, only the error response. And an error from the bridge's own decode (an address that matches no APB peripheral) is aDECERRon AXI — distinct from the peripheral'sSLVERR— and on AHB still the two-cycleHRESP=ERROR.
4. Real SoC implementation
In RTL the error path hangs off the same FSM that runs the APB transfer (13.1). At the APB completion edge the bridge samples PSLVERR; if set, it drives the upstream protocol's error response. The AHB version is the subtle one because the ERROR response is two cycles, so the bridge needs a small extra state.
// ---------------------------------------------------------------
// Bridge error translation: APB PSLVERR -> upstream error response.
// FSM extended with an ERR1/ERR2 pair so AHB gets the legal
// TWO-CYCLE HRESP=ERROR response (HREADY low, then high).
// ---------------------------------------------------------------
localparam HRESP_OKAY = 1'b0, HRESP_ERROR = 1'b1;
typedef enum logic [2:0] {IDLE, SETUP, ACCESS, ERR1, ERR2} state_t;
state_t state, nstate;
// APB transfer completes when PREADY is high in ACCESS; PSLVERR is
// only meaningful on that same edge (Module 9 semantics).
wire apb_done = (state == ACCESS) && pready;
wire apb_error = apb_done && pslverr; // capture the verdict here
always_comb begin
nstate = state;
unique case (state)
IDLE: if (ahb_accept) nstate = SETUP;
SETUP: nstate = ACCESS;
ACCESS: if (apb_error) nstate = ERR1; // -> two-cycle error
else if (pready) nstate = IDLE; // clean completion
ERR1: nstate = ERR2; // cycle 1 of ERROR
ERR2: nstate = IDLE; // cycle 2 of ERROR
endcase
end
always_ff @(posedge hclk or negedge hresetn)
if (!hresetn) state <= IDLE; else state <= nstate;
// --- AHB two-cycle ERROR response -------------------------------
// Cycle 1 (ERR1): HRESP=ERROR, HREADY=0 -> "error coming, not done"
// Cycle 2 (ERR2): HRESP=ERROR, HREADY=1 -> master samples ERROR, cancels
assign hresp =
((state == ERR1) || (state == ERR2)) ? HRESP_ERROR : HRESP_OKAY;
assign hready_out =
(state == IDLE) ? 1'b1 :
(state == ACCESS && pready && !pslverr) ? 1'b1 : // clean OKAY done
(state == ERR2) ? 1'b1 : // 2nd error cycle
1'b0; // stalling / ERR1
// read data still returned (master must not trust it on error, but
// the response is well-formed, not floating)
assign hrdata = prdata;
// ---------------------------------------------------------------
// AXI4-Lite variant: a single 2-bit response code, no sequencing.
// SLVERR for a peripheral fault, DECERR for an unmapped address
// caught by the bridge's own decode (see 13.6 address mapping).
// ---------------------------------------------------------------
localparam [1:0] RESP_OKAY = 2'b00, RESP_SLVERR = 2'b10, RESP_DECERR = 2'b11;
wire [1:0] resp_code = decode_miss ? RESP_DECERR : // bridge decode error
pslverr ? RESP_SLVERR : // peripheral error
RESP_OKAY;
// WRITE: returned on the B channel with BVALID.
assign bresp = resp_code; // sampled when BVALID && BREADY
// READ: returned on the R channel with RVALID, alongside RDATA.
assign rresp = resp_code; // sampled when RVALID && RREADY
assign rdata = prdata; // data present; master ignores it on SLVERR/DECERRTwo facts make this the canonical pattern. First, the AHB error is a two-cycle response, so the bridge needs explicit ERR1/ERR2 states — you cannot just OR HRESP=ERROR into a single ACCESS cycle and call it done; the protocol requires HREADY low then high while HRESP holds ERROR. Second, the AXI version is "just a code on the channel" (SLVERR/DECERR on B/R), but you must still pick the right code — a peripheral fault is SLVERR, while an address the bridge's own decode rejects is DECERR, which never reaches APB at all (13.6).
5. Engineering tradeoffs
The error path is small, but each choice decides whether a fault is faithfully reported or quietly mangled. The core mapping:
| APB result | AHB upstream response | AXI4-Lite upstream response | Sequencing / placement |
|---|---|---|---|
PREADY=1, PSLVERR=0 (clean) | HRESP=OKAY, HREADY=1 | BRESP/RRESP = OKAY (0b00) | Single cycle; normal completion |
PREADY=1, PSLVERR=1 (slave error) | HRESP=ERROR, two cycles (HREADY low → high) | BRESP=SLVERR (0b10) (write) / RRESP=SLVERR (0b10) (read) | AHB: 2-cycle handshake; AXI: one response beat on B/R |
| Read that errors | two-cycle HRESP=ERROR; HRDATA driven but untrusted | RRESP=SLVERR; RDATA present but ignored by master | Error on the R response of that read |
| Write that errors | two-cycle HRESP=ERROR | BRESP=SLVERR | Error on the B response of that write |
| Address not mapped by the bridge's decode | two-cycle HRESP=ERROR (never reaches APB) | BRESP/RRESP = DECERR (0b11) | Generated by the bridge itself; see 13.6 |
Beyond the mapping, the real tradeoffs:
- Faithful translation vs. "swallow and continue." A lazy bridge could tie
HRESP=OKAYalways and never wirePSLVERR— simpler, fewer states, and it "works" until a peripheral actually faults. The cost is a silent data-corruption bug that escapes to software. Always translate; the few extra states are non-negotiable. SLVERRvs.DECERRgranularity. On AXI you can collapse every error toSLVERRand skipDECERR. It is legal but lossy: software (and the bus monitor) can no longer distinguish "peripheral said no" from "this address is mapped to nothing." EmittingDECERRfor the bridge's own decode misses costs a comparator and earns precise diagnostics.- Read-data-on-error policy. Return the peripheral's
PRDATA(well-formed but to be ignored), or force a known pattern (e.g. all-zeros /0xDEAD...). Either is acceptable since the master must not trust it; forcing a poison pattern makes a missed error easier to catch in lab, at the cost of hiding what the peripheral actually drove.
6. Common RTL mistakes
7. Debugging scenario
The signature error-path bug is a peripheral fault that never reaches software — the bridge samples PSLVERR for waits/data but never wires it into the upstream error response, so the CPU reads garbage and marches on.
- Observed symptom: firmware reads a status register from a peripheral that is known to be powered-down / mis-clocked, and instead of taking a bus fault and entering its error handler, it gets a plausible-looking value and continues. No exception fires; a later, unrelated assertion or hang is the first visible failure — far from the real cause.
- Waveform clue: at the APB completion edge,
PREADY=1andPSLVERR=1— the peripheral clearly reported an error. Upstream, on the AHB side,HRESPstaysOKAYthrough the whole transfer andHREADYsimply goes high once; the two-cycleERRORresponse is nowhere. On an AXI bridge,BRESP/RRESPreads0b00 OKAYdespite thePSLVERR. The error verdict is visible on APB and absent upstream. - Root cause: the bridge wired
PSLVERRonly into its wait/data logic (it correctly usedPREADYto release the master and returnPRDATA) but never into the response path —HRESPwas tied toOKAY, or the AXIresp_codeignoredpslverr. The single-cycle verdict was sampled and then thrown away. - Correct RTL: sample the verdict at completion and route it to the response:
wire apb_error = (state==ACCESS) && pready && pslverr;driving anERR1/ERR2two-cycleHRESP=ERRORon AHB, orresp_code = pslverr ? RESP_SLVERR : RESP_OKAY;on theB/Rchannel for AXI — emitted for that transaction. - Verification assertion: tie the downstream verdict to the upstream response so it cannot silently vanish:
// AHB: a PSLVERR at APB completion must produce a 2-cycle HRESP=ERROR
// for this transaction (ERROR held while HREADY goes low then high).
property pslverr_maps_to_ahb_error;
@(posedge hclk) disable iff (!hresetn)
(state == ACCESS && pready && pslverr) |=>
(hresp == HRESP_ERROR && !hready_out) // cycle 1: ERROR, HREADY low
##1 (hresp == HRESP_ERROR && hready_out); // cycle 2: ERROR, HREADY high
endproperty
assert property (pslverr_maps_to_ahb_error);
// AXI: a PSLVERR must surface as SLVERR on the response channel.
assert property (@(posedge aclk) disable iff (!aresetn)
(apb_done && pslverr && bvalid) |-> (bresp == 2'b10));- Debug habit: when an error "disappears," trace it as a chain — peripheral asserted it → did the bridge sample it → did the bridge re-emit it upstream → did the master act on it. The break is almost always at "re-emit upstream": the bridge used
PSLVERRfor flow/data but forgot the response path. Always check that the single-cycle downstream verdict has a registered home in the upstream response, on the same transaction.
8. Verification perspective
The error path is small in RTL and enormous in escape risk — a missed mapping is a silent data-corruption bug. Verify it as an explicit set of mapping, sequencing, and alignment checks, not as a by-product of the happy path.
- Assert the core mapping in both directions.
PSLVERRat APB completion must produce the upstream error (the two-cycleHRESP=ERRORon AHB, orSLVERRonBRESP/RRESPfor AXI), and a clean APB completion (PSLVERR=0) must never produce an upstream error. Both directions matter: a bridge that errors spuriously is as broken as one that swallows errors. - Check the AHB two-cycle sequencing precisely. The
HRESP=ERRORresponse is not a pulse — assert the exact handshake:HRESP=ERRORwithHREADY=0for one cycle, thenHRESP=ERRORwithHREADY=1. A bridge that assertsHRESP=ERRORfor a single cycle, or holds it for three, is illegal even though it "raised an error." - Cover error-on-read versus error-on-write separately. They take different upstream paths — the
Rchannel (RRESP) for a read, theBchannel (BRESP) for a write on AXI; the same two-cycleHRESPon AHB but with read data still well-formed. Functional coverage must hit aPSLVERRon a read and on a write; a suite that only errors writes leaves the read-data-on-error path untested. - Distinguish decode-error from slave-error. Drive an address the bridge's own decode rejects and assert it produces
DECERR(AXI) without ever assertingPSELon APB; drive a mapped address whose peripheral faults and assertSLVERR. Coverage must include both theSLVERRandDECERRsources (13.6). - Prove alignment to the erroring transaction. With back-to-back and (on AXI) outstanding transactions, scoreboard that the error response carries the id/order of the transaction that actually erred — not the one before or after. An off-by-one in alignment passes every per-transaction check yet corrupts the wrong access; only a transaction-tracking scoreboard catches it.
The point: the error path needs its own dedicated mapping, sequencing, alignment, and read-vs-write coverage — the happy-path monitors will pass a bridge that silently drops every fault.
9. Interview discussion
"How does a peripheral error get from APB up to the CPU?" is a high-signal bridge question, and the strong answer leads with translation of a single-cycle verdict into the upstream protocol's native error shape, aligned to the transaction.
Frame it as: APB reports failure with a one-cycle PSLVERR sampled at ACCESS completion; the master speaks AHB or AXI and never sees PSLVERR, so the bridge must capture it at that edge and re-emit it upstream. Then deliver the depth that separates senior answers. On AHB, name the two-cycle HRESP=ERROR response — HRESP=ERROR with HREADY low, then HRESP=ERROR with HREADY high — and that the bridge must generate this exact handshake, not a one-cycle pulse. On AXI4-Lite, name the 2-bit response code SLVERR (0b10) returned on the B channel for a write or the R channel for a read — simpler, no extra sequencing. Add the distinction that earns the most points: a peripheral fault is SLVERR, but an address the bridge's own decode rejects is DECERR — it never reaches APB. Close with the failure mode — "if the bridge uses PSLVERR only for flow control and forgets the response path, the fault is silently lost and software runs on garbage" — and the alignment point, that the error must land on the same transaction that erred. That arc — verdict → native upstream shape → correct sequencing → right transaction → the cost of getting it wrong — is exactly the reasoning an interviewer is probing for.
10. Practice
- State the two upstream shapes. Write the AHB error response and the AXI4-Lite error response for a single APB
PSLVERR, including the exact AHB two-cycle sequencing and the AXISLVERRcode and channel. - Sequence the AHB error. For one APB transfer that completes with
PSLVERR=1, drawHRESPandHREADYcycle-by-cycle from ACCESS completion through both error cycles. - Map read vs write. State which AXI channel carries the error for an erroring read and for an erroring write, and the response code on each.
- Distinguish the sources. Give one scenario that produces
SLVERRand one that producesDECERR, and explain why only one of them ever assertsPSEL. - Spot the silent bug. Given a bridge that ties
HRESP=OKAYand only wiresPSLVERRinto itsHREADY/HRDATAlogic, describe exactly what software observes when a peripheral faults, and the one-line fix.
11. Q&A
12. Key takeaways
- The bridge translates a single-cycle
PSLVERRinto the upstream protocol's native error response — it captures the verdict at the APB completion edge and re-emits it for the same transaction, or the fault is silently lost. - AHB's error is a two-cycle response:
HRESP=ERRORwithHREADYlow, thenHRESP=ERRORwithHREADYhigh — the bridge must generate this exact handshake, not a one-cycle pulse. - AXI4-Lite's error is a 2-bit code on the channel:
SLVERR (0b10)onBRESP(write, B channel) orRRESP(read, R channel) — a single response beat, no sequencing. - Decode-error ≠ slave-error: a faulting peripheral gives
SLVERR; an address the bridge's own decode rejects givesDECERR(AXI), never reaching APB — collapsing them loses diagnostic information (13.6). - Read data on error is defined, not floating — the bridge drives a well-formed bus that the master ignores; the error response flags it invalid.
- The signature bug is a swallowed error — the bridge uses
PSLVERRfor flow/data but forgets the response path, so the CPU runs on garbage; verify the mapping, the two-cycle sequencing, read-vs-write, decode-vs-slave, and alignment explicitly.