AMBA APB · Module 9
PSLVERR Behaviour
What PSLVERR actually means on APB — a status flag sampled only on the completion edge, not a transfer abort. The error contract: when it is valid, what the transfer still does, what the manager must and must not assume, and why a mis-timed or misread PSLVERR silently corrupts software's view of an error.
You already know a transfer completes on the single edge where PSEL, PENABLE, and PREADY are all high. This chapter adds the one bit that says whether that completed transfer succeeded: PSLVERR. The single idea to carry: PSLVERR is a status flag the manager samples on exactly the completion edge — it is not an abort, not a retry, and not valid at any other time. The transfer still finishes; PSLVERR only colours it pass or fail. Almost every APB error bug is a failure to respect where and how that one bit is valid.
1. Problem statement
The problem is reporting "this completed transfer failed" on a protocol that has no abort, no retry, and no transaction ID — using a single qualifier bit that is only meaningful for one cycle.
APB is deliberately minimal: there is no split transaction, no out-of-order completion, no error channel. So when a subordinate cannot honour an access — an unmapped address, a protection violation, a FIFO that overflowed, a hardware fault — it has exactly one mechanism to say so: drive PSLVERR high on the same edge it completes the transfer (PREADY high). That creates three obligations that "PSLVERR means error" does not capture:
- It is sampled, not held.
PSLVERRis only valid whenPSEL && PENABLE && PREADY— the completion edge. Its value during setup, during wait states, or after the transfer is meaningless and must be ignored. A manager that samples it anywhere else reads noise. - The transfer still completes.
PSLVERR=1does not cancel the access. The bus returns toIDLE/SETUPexactly as it would on success; on a read,PRDATAis present but must be treated as suspect; on a write, APB defines no rollback. "Error" here means "completed, but flag the result," not "didn't happen." - Recovery is the manager's job, above the bus. APB itself does nothing on an error — it does not retry, does not interrupt, does not unwind. Whatever happens next (a bus-fault exception, a status-register bit, a retry in software) is the integration layer's policy, not protocol behaviour.
So the job is not "detect an error" — it is "deliver a one-cycle pass/fail verdict on a completed transfer, sampled in exactly the right window, with the manager understanding that the transfer happened regardless."
2. Why previous knowledge is insufficient
Module 3 established the completion edge — PSEL && PENABLE && PREADY — and Module 8 drilled how PREADY itself must be a clean, sampled-at-the-edge value. Those chapters got you to "the transfer completes here." This chapter rides on that exact edge but asks a different question — did it succeed? — and that exposes gaps the handshake view never addressed:
- Completion and success are different facts. The handshake tells you when a transfer finishes; it says nothing about whether the subordinate could actually honour it.
PSLVERRis the orthogonal axis: a transfer can complete-and-pass or complete-and-fail, and the manager needs both bits (PREADYfor when,PSLVERRfor whether). PSLVERRinherits the sample-window discipline ofPREADY— and adds a trap. Because it is only valid on the completion edge, anXor a stale value onPSLVERRoutside that window is harmless if ignored but catastrophic if sampled. The wait-state chapters taught you to respect the sampling edge forPREADY;PSLVERRmakes that discipline mandatory, because a slave is free to drive garbage onPSLVERRduring waits.- There is no error recovery in the protocol to lean on. Earlier modules could assume a transfer either completes or stalls.
PSLVERRintroduces a third outcome — completed-but-failed — that the protocol does not act on at all. Understanding APB errors means understanding that the bus hands you a verdict and walks away; everything after is your design.
So the model to add is the verdict model: PSLVERR as a single-cycle pass/fail stamp on an already-completing transfer, valid only at the completion edge, with all consequences pushed above the bus.
3. Mental model
The model: PSLVERR is a receipt stamp, not a stop sign. The transfer is the package; it gets delivered either way. At the instant of delivery (the completion edge) the subordinate stamps the receipt PASS or FAIL. You read the stamp only at delivery — glancing at the stamp pad before the package arrives, or after it's gone, tells you nothing.
Three refinements make it precise:
- The stamp is only legible at the completion edge.
PSLVERRmust be sampled whenPSEL && PENABLE && PREADY. The subordinate may drive it to anything before that (during setup or waits); only its value coincident withPREADYhigh is the verdict. A registered, cleanPSLVERRaligned to that edge is the only safe implementation. - A stamped-FAIL package was still delivered.
PSLVERR=1does not undo the access. On a read, data still came back (treat it as invalid); on a write, the bus completed (APB guarantees no rollback, so a well-designed slave simply must not apply the side effect — covered in the write-error chapter). The bus sequencing is identical to success. - The stamp means nothing by itself — someone upstream must act. The manager/bridge decides the consequence: raise a bus-fault to the CPU, set a sticky error bit, log it, or retry at the software level. APB neither defines nor performs any of this. The bit is information; the policy is yours.
4. Real SoC implementation
In silicon, PSLVERR is a subordinate output that must be a clean value at the completion edge and don't-care elsewhere. The robust implementation registers it so it is glitch-free and aligned to PREADY, and — critically — drives it to a defined 0 whenever the slave is not completing, so an unselected or waiting slave never floats an error onto the bus.
// PSLVERR is the per-access verdict, valid only when the access completes.
// err_condition is the subordinate's own "I cannot honour this" signal:
// - address decoded to an unmapped/reserved region,
// - a PPROT permission mismatch,
// - an internal fault / overflow detected for THIS access.
// It must be evaluated for the access that is completing, not a stale one.
always_ff @(posedge pclk or negedge presetn) begin
if (!presetn) begin
pready <= 1'b0;
pslverr <= 1'b0;
end else if (sel && penable && access_done) begin
pready <= 1'b1; // complete the access THIS cycle...
pslverr <= err_condition; // ...and stamp the verdict on the SAME edge
end else begin
pready <= 1'b0;
pslverr <= 1'b0; // not completing -> drive a defined 0, never float/X
end
end
// Key contract: pslverr is only meaningful in the cycle pready is high.
// Driving it to 0 otherwise is defensive: it guarantees a mis-sampling manager
// (or a shared/muxed PSLVERR) can never see a spurious error.Two facts drive the real design. First, PSLVERR is sampled on the same edge as PREADY, so the two must be produced together — a common bug is to compute PSLVERR combinationally off a decode that has not settled while PREADY is registered, so the verdict and the completion disagree at the edge (error-response timing is the chapter on getting that alignment exact). Second, PSLVERR is optional in the protocol but mandatory in practice: a subordinate that never errors may tie it low, but any slave with an address map, protection, or a failable resource must drive it — and an integrator must wire the manager/bridge to consume it (into a bus-fault or status bit), because an unconsumed PSLVERR is an error that silently disappears.
5. Engineering tradeoffs
PSLVERR design is a set of small, consequential choices about when the bit is valid and what the system does with it.
| Decision | What it gives up | What it buys | When to choose it |
|---|---|---|---|
Registered PSLVERR | One cycle of decode slack | Glitch-free, edge-aligned with PREADY | Almost always — the safe default |
Combinational PSLVERR | Glitch immunity; easy timing | No extra latency | Only with a shallow, settled error term on a slow clock |
Drive 0 when not completing | Nothing real | A manager can never mis-sample a spurious error | Always — defensive and free |
Tie PSLVERR low (never error) | All error reporting | Simplicity | Only a slave that genuinely cannot fail (no map, no protection, no failable resource) |
| Consume into a bus-fault (CPU exception) | Soft handling | Immediate, precise fault to software | Accesses where silent failure is unacceptable |
| Consume into a sticky status bit | Precise per-access attribution | Cheap, pollable error capture | Lower-criticality peripherals; aggregated error logging |
The throughline: PSLVERR is cheap to drive and easy to get almost right, but its value is entirely about the window (the completion edge) and the consumer (whatever turns the bit into a consequence). A PSLVERR that is correct but unconsumed, or consumed but mis-sampled, is worse than none — it creates the illusion of error handling.
6. Common RTL mistakes
7. Debugging scenario
The signature PSLVERR bug is an error that exists on the bus but never reaches software — or a spurious error that fires on a perfectly good access — and both come down to where PSLVERR is sampled relative to the completion edge.
- Observed symptom: software reads a peripheral that is known to be faulting (e.g. an unmapped register), but the access returns clean — no bus fault, no error bit set — and software happily uses garbage data. Intermittently, the opposite also happens: an unrelated, valid access spuriously trips the error handler.
- Waveform clue: on the failing access,
PSLVERRis asserted by the slave — but one cycle early, during the wait state, and is back low by the completion edge; the manager, which (correctly) samples only atPREADYhigh, sees0and reports success. On the spurious case, the slave drivesPSLVERRhigh during a wait of a different completing path and a mis-built manager samples it off the wrong edge. - Root cause:
PSLVERRwas driven combinationally off the error-decode the moment the decode resolved, not registered and aligned to the completion edge. So its high pulse lands during the wait, not atPREADY. The verdict and the completion are misaligned in time — the slave computed the right answer in the wrong cycle. - Correct RTL: produce
PSLVERRon the same registered edge asPREADY, and only then:if (sel && penable && access_done) begin pready <= 1; pslverr <= err_condition; end else begin pready <= 0; pslverr <= 0; end. The verdict is now coincident with completion by construction, and0otherwise. - Verification assertion: assert that
PSLVERRis never high unless the access is completing —assert property (@(posedge pclk) disable iff(!presetn) pslverr |-> (psel && penable && pready));— and that it is neverXat the completion edge:assert property (@(posedge pclk) disable iff(!presetn) (psel && penable && pready) |-> !$isunknown(pslverr));. - Debug habit: when an APB error is "lost" or "spurious," do not start in the error handler — put a marker on the completion edge (
psel & penable & pready) and checkPSLVERRonly there. IfPSLVERRpulses anywhere other than that edge, it is a timing/alignment bug in the slave, not a handler bug. The verdict is only ever the value coincident withPREADYhigh.
8. Verification perspective
PSLVERR is a single-cycle, single-window signal, so verification has to pin both where it is valid and what it causes — and a functional test that never injects an error covers none of it.
- Assert the validity window. Bind a property that
PSLVERRis high only on a completion edge (pslverr |-> psel && penable && pready), and that it is neverXat that edge. Together these catch the two structural bugs: a verdict asserted in the wrong cycle, and an undriven error path. The window check is the single most valuablePSLVERRassertion. - Check the consequence, not just the bit. A
PSLVERRthat is reported but not consumed is a silent hole. The verification plan must assert the downstream effect — that an injectedPSLVERRsets the expected bus-fault / status bit / interrupt — and that a clean access never trips it. This is a scoreboard/checker responsibility, above the protocol monitor. - Cover the error matrix. Functional coverage should cross error-on-read vs error-on-write, error with zero waits vs error after N waits (the verdict must align to the actual completion edge in both), and each error source (unmapped address, protection, peripheral fault) so every path that can drive
err_conditionis exercised. An error suite that only ever errors on a zero-wait read leaves the wait-aligned and write-error corners — exactly where the timing bugs live — uncovered.
The point: PSLVERR correctness is a window property and a causality property. Verify that the bit is valid only at completion, that it is never X there, and that it actually produces the system consequence — and cover errors across read/write, wait-count, and source. (Tracing a reported PSLVERR back to its root cause is its own discipline.)
9. Interview discussion
"What does PSLVERR do to the transfer?" is a fast senior filter: the wrong answer is "it aborts it." A strong answer states the contract precisely and then shows you know where the bug lives.
Frame it as a verdict, not an abort: PSLVERR is a status bit the manager samples on exactly the completion edge (PSEL && PENABLE && PREADY); the transfer completes identically whether it is high or low, and APB defines no retry, no rollback, and no recovery — PSLVERR simply colours the completed access pass or fail. Then deliver the depth: it is only valid in that one window (its value during setup or waits is don't-care, so a slave must drive it cleanly — ideally registered — at the completion edge and 0 otherwise); the classic bug is a combinational PSLVERR that pulses during a wait and is gone by completion, so the error is silently lost, which is invisible unless you sample exactly at the edge; and a reported PSLVERR does nothing on its own — the integrator must consume it into a bus-fault, interrupt, or status bit, or the error disappears. Closing with "on a read, PSLVERR means treat PRDATA as suspect, not that no data came back; on a write, the bus doesn't roll back, so a correct slave must suppress the side effect itself" signals you have actually handled APB errors, not just read the table.
10. Practice
- Place the window. On an access with two wait states, mark the single edge
PSLVERRis valid on, and state whatPSLVERRis allowed to be during the two waits and why it doesn't matter. - Pass vs fail sequencing. Draw the bus returning to
IDLEafter aPSLVERR=1completion and after aPSLVERR=0completion, and confirm they are identical — explain what that proves about "abort." - Read vs write error. State what
PSLVERR=1means forPRDATAon a read, and for the register side effect on a write, and why the two consequences differ. - Write the slave. From memory, write the registered
PSLVERR/PREADYblock that stamps the verdict on the completion edge and drives0otherwise; explain theelsebranch. - Find the lost error. Given a waveform where
PSLVERRpulses high during a wait and is low at completion, explain why software never sees the error and what the one-line fix is.
11. Q&A
12. Key takeaways
PSLVERRis a verdict, not an abort. It stamps a completed transfer pass or fail; the bus sequences identically whether it is high or low. APB defines no retry, no rollback, no recovery.- It is valid only on the completion edge (
PSEL && PENABLE && PREADY). Its value during setup or wait states is don't-care and must be ignored; sampling it anywhere else reads noise. - Drive it cleanly and defensively: register it so it is glitch-free and aligned with
PREADY, and drive a defined0whenever not completing, so no spurious error can ever be sampled. - The classic bug is a misaligned
PSLVERR— combinational off a decode that pulses during a wait and is gone by completion — so the error is silently lost. Debug it by readingPSLVERRonly at the completion edge. - A reported
PSLVERRdoes nothing by itself. The manager/bridge must consume it into a bus-fault, interrupt, or status bit; on a read, treatPRDATAas suspect; on a write, a correct slave must suppress the side effect because the bus will not roll back. - Verify the window and the consequence:
PSLVERRhigh only at completion, neverXthere, and an injected error actually produces the system effect — covered across read/write, wait-count, and error source.