Skip to content

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 PSLVERR for exactly one cycle, sampled together with PREADY at ACCESS completion. The upstream master never sees that signal — it only sees the bridge's AHB/AXI response. If the bridge does not capture PSLVERR at 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=ERROR response — a specific handshake the bridge must generate: HRESP=ERROR with HREADY low for one cycle, then HRESP=ERROR with HREADY high. AXI4-Lite reports it as a 2-bit response code (SLVERR = 0b10) on the B channel for a write or the R channel 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/R response. 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 PSLVERR is sampled with PREADY at 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 HRESP taught you the two-cycle ERROR response — 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 downstream PSLVERR it 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 BRESP and the read-response field taught you OKAY/SLVERR/DECERR as 2-bit codes returned on the B and R channels. 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=ERROR as 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 upstream DECERR, 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. PSLVERR is only valid the cycle PREADY is high. The bridge samples both together; if PSLVERR=1, that access's upstream response becomes an error. Because the bridge already holds HREADY low (or BVALID/RVALID not 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=ERROR with HREADY=0, cycle 2 HRESP=ERROR with HREADY=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 code SLVERR (0b10) on BRESP (write, on the B channel) or RRESP (read, on the R channel) — 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 a DECERR on AXI — distinct from the peripheral's SLVERR — and on AHB still the two-cycle HRESP=ERROR.
A timing diagram with three bands: an APB band showing PSEL, PENABLE, PREADY rising and PSLVERR high at the completion edge; an AHB band showing the two-cycle HRESP=ERROR response with HREADY low then high; and an AXI band showing BRESP=0b10 SLVERR on the B channel for a write and RRESP=0b10 SLVERR on the R channel for a read, all aligned to the same erroring transaction.
Figure 1 — the error translation, aligned to the erroring transaction. Top, the APB side: PSEL/PENABLE frame one two-phase transfer, and at the ACCESS completion edge PREADY rises while PSLVERR is also high — the peripheral's one-cycle error verdict. Middle, the AHB upstream translation: the bridge drives the two-cycle ERROR response — cycle 1 HRESP=ERROR with HREADY low, cycle 2 HRESP=ERROR with HREADY high — so the master samples the error and cancels the transfer. Bottom, the AXI4-Lite alternative: a single 2-bit response code SLVERR=0b10 returned on the B channel (BRESP, write) or the R channel (RRESP, read). The figure stresses the error is reported for the SAME transaction that erred — captured at the APB completion edge and re-emitted upstream in the native, correctly-sequenced form.

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.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ---------------------------------------------------------------
// 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/DECERR

Two 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 resultAHB upstream responseAXI4-Lite upstream responseSequencing / placement
PREADY=1, PSLVERR=0 (clean)HRESP=OKAY, HREADY=1BRESP/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 errorstwo-cycle HRESP=ERROR; HRDATA driven but untrustedRRESP=SLVERR; RDATA present but ignored by masterError on the R response of that read
Write that errorstwo-cycle HRESP=ERRORBRESP=SLVERRError on the B response of that write
Address not mapped by the bridge's decodetwo-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=OKAY always and never wire PSLVERR — 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.
  • SLVERR vs. DECERR granularity. On AXI you can collapse every error to SLVERR and skip DECERR. It is legal but lossy: software (and the bus monitor) can no longer distinguish "peripheral said no" from "this address is mapped to nothing." Emitting DECERR for 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=1 and PSLVERR=1 — the peripheral clearly reported an error. Upstream, on the AHB side, HRESP stays OKAY through the whole transfer and HREADY simply goes high once; the two-cycle ERROR response is nowhere. On an AXI bridge, BRESP/RRESP reads 0b00 OKAY despite the PSLVERR. The error verdict is visible on APB and absent upstream.
  • Root cause: the bridge wired PSLVERR only into its wait/data logic (it correctly used PREADY to release the master and return PRDATA) but never into the response path — HRESP was tied to OKAY, or the AXI resp_code ignored pslverr. 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 an ERR1/ERR2 two-cycle HRESP=ERROR on AHB, or resp_code = pslverr ? RESP_SLVERR : RESP_OKAY; on the B/R channel for AXI — emitted for that transaction.
  • Verification assertion: tie the downstream verdict to the upstream response so it cannot silently vanish:
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// 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 PSLVERR for 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.
Two stacked timing cases over one APB completion where PSLVERR is high. The bottom buggy case keeps HRESP at OKAY, returns garbage HRDATA, and the master continues with no fault, drawn red. The top correct case drives the two-cycle HRESP=ERROR response with HREADY low then high, and the master takes a bus fault that reaches software, drawn green.
Figure 2 — the lost-error bug, two cases. Bottom (bug, red): the bridge samples PREADY to release HREADY and return HRDATA but never wires PSLVERR into the response, so HRESP stays OKAY; the master sees a clean completion, accepts garbage read data, sets no fault, and software continues on corrupt data — the fault is lost. Top (correct, green): the bridge translates PSLVERR into the two-cycle HRESP=ERROR response (HREADY low then high, HRESP=ERROR), so the master cancels the transfer, takes a bus fault, sets a status bit, and an exception reaches software. The figure shows PSLVERR is single-cycle and must be captured into the upstream error response on the same transaction, or it vanishes between peripheral and CPU.

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. PSLVERR at APB completion must produce the upstream error (the two-cycle HRESP=ERROR on AHB, or SLVERR on BRESP/RRESP for 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=ERROR response is not a pulse — assert the exact handshake: HRESP=ERROR with HREADY=0 for one cycle, then HRESP=ERROR with HREADY=1. A bridge that asserts HRESP=ERROR for 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 R channel (RRESP) for a read, the B channel (BRESP) for a write on AXI; the same two-cycle HRESP on AHB but with read data still well-formed. Functional coverage must hit a PSLVERR on 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 asserting PSEL on APB; drive a mapped address whose peripheral faults and assert SLVERR. Coverage must include both the SLVERR and DECERR sources (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 responseHRESP=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

  1. 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 AXI SLVERR code and channel.
  2. Sequence the AHB error. For one APB transfer that completes with PSLVERR=1, draw HRESP and HREADY cycle-by-cycle from ACCESS completion through both error cycles.
  3. 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.
  4. Distinguish the sources. Give one scenario that produces SLVERR and one that produces DECERR, and explain why only one of them ever asserts PSEL.
  5. Spot the silent bug. Given a bridge that ties HRESP=OKAY and only wires PSLVERR into its HREADY/HRDATA logic, 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 PSLVERR into 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=ERROR with HREADY low, then HRESP=ERROR with HREADY high — 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) on BRESP (write, B channel) or RRESP (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 gives DECERR (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 PSLVERR for 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.