Skip to content

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. PSLVERR is only valid when PSEL && 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=1 does not cancel the access. The bus returns to IDLE/SETUP exactly as it would on success; on a read, PRDATA is 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. PSLVERR is the orthogonal axis: a transfer can complete-and-pass or complete-and-fail, and the manager needs both bits (PREADY for when, PSLVERR for whether).
  • PSLVERR inherits the sample-window discipline of PREADY — and adds a trap. Because it is only valid on the completion edge, an X or a stale value on PSLVERR outside that window is harmless if ignored but catastrophic if sampled. The wait-state chapters taught you to respect the sampling edge for PREADY; PSLVERR makes that discipline mandatory, because a slave is free to drive garbage on PSLVERR during waits.
  • There is no error recovery in the protocol to lean on. Earlier modules could assume a transfer either completes or stalls. PSLVERR introduces 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. PSLVERR must be sampled when PSEL && PENABLE && PREADY. The subordinate may drive it to anything before that (during setup or waits); only its value coincident with PREADY high is the verdict. A registered, clean PSLVERR aligned to that edge is the only safe implementation.
  • A stamped-FAIL package was still delivered. PSLVERR=1 does 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.
An APB timing diagram showing PSEL and PENABLE high across a wait and a completion cycle, PREADY low then high, and PSLVERR hatched as don't-care during setup and wait but sampled at the single completion edge where it is the pass/fail verdict, with the transfer completing identically whether PSLVERR is high or low.
Figure 1 — PSLVERR is a verdict sampled only on the completion edge. Across an access with one wait state, PSEL and PENABLE are high throughout; PREADY is low for the wait then high at completion. PSLVERR is don't-care (hatched) during setup and the wait — the subordinate may drive it to anything — and is only the error verdict at the single edge where PSEL, PENABLE, and PREADY are all high. The figure marks that one sampling instant in blue, stresses that PSLVERR low there means PASS and high means FAIL, and shows that the transfer completes and the bus returns to IDLE identically in both cases — PSLVERR colours the result, it does not abort the transfer.

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.

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

DecisionWhat it gives upWhat it buysWhen to choose it
Registered PSLVERROne cycle of decode slackGlitch-free, edge-aligned with PREADYAlmost always — the safe default
Combinational PSLVERRGlitch immunity; easy timingNo extra latencyOnly with a shallow, settled error term on a slow clock
Drive 0 when not completingNothing realA manager can never mis-sample a spurious errorAlways — defensive and free
Tie PSLVERR low (never error)All error reportingSimplicityOnly a slave that genuinely cannot fail (no map, no protection, no failable resource)
Consume into a bus-fault (CPU exception)Soft handlingImmediate, precise fault to softwareAccesses where silent failure is unacceptable
Consume into a sticky status bitPrecise per-access attributionCheap, pollable error captureLower-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, PSLVERR is 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 at PREADY high, sees 0 and reports success. On the spurious case, the slave drives PSLVERR high during a wait of a different completing path and a mis-built manager samples it off the wrong edge.
  • Root cause: PSLVERR was 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 at PREADY. The verdict and the completion are misaligned in time — the slave computed the right answer in the wrong cycle.
  • Correct RTL: produce PSLVERR on the same registered edge as PREADY, 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, and 0 otherwise.
  • Verification assertion: assert that PSLVERR is never high unless the access is completing — assert property (@(posedge pclk) disable iff(!presetn) pslverr |-> (psel && penable && pready)); — and that it is never X at 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 check PSLVERR only there. If PSLVERR pulses 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 with PREADY high.
Two stacked APB timing diagrams of the same faulting access: the top correct case has PSLVERR registered and high exactly at the completion edge in green; the bottom buggy case has PSLVERR pulsing high during the wait state and low at the completion edge in red, so the manager samples low and the error is lost.
Figure 2 — a misaligned PSLVERR versus a correct edge-aligned one, on the same faulting access. Top (correct, green): PSLVERR is registered alongside PREADY, so it is low through the wait and rises to high exactly at the completion edge where the manager samples it — the error is reported. Bottom (bug, red): PSLVERR is combinational off the error decode and pulses high during the wait cycle, then falls back low before the completion edge; the manager samples only at PREADY high, sees low, and reports success — the real error is silently lost. The figure shows that the slave computed the correct verdict but in the wrong cycle, and that the fix is to align PSLVERR to the completion edge, not to re-examine the error logic.

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 PSLVERR is high only on a completion edge (pslverr |-> psel && penable && pready), and that it is never X at 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 valuable PSLVERR assertion.
  • Check the consequence, not just the bit. A PSLVERR that is reported but not consumed is a silent hole. The verification plan must assert the downstream effect — that an injected PSLVERR sets 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_condition is 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

  1. Place the window. On an access with two wait states, mark the single edge PSLVERR is valid on, and state what PSLVERR is allowed to be during the two waits and why it doesn't matter.
  2. Pass vs fail sequencing. Draw the bus returning to IDLE after a PSLVERR=1 completion and after a PSLVERR=0 completion, and confirm they are identical — explain what that proves about "abort."
  3. Read vs write error. State what PSLVERR=1 means for PRDATA on a read, and for the register side effect on a write, and why the two consequences differ.
  4. Write the slave. From memory, write the registered PSLVERR/PREADY block that stamps the verdict on the completion edge and drives 0 otherwise; explain the else branch.
  5. Find the lost error. Given a waveform where PSLVERR pulses 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

  • PSLVERR is 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 defined 0 whenever 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 reading PSLVERR only at the completion edge.
  • A reported PSLVERR does nothing by itself. The manager/bridge must consume it into a bus-fault, interrupt, or status bit; on a read, treat PRDATA as 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: PSLVERR high only at completion, never X there, and an injected error actually produces the system effect — covered across read/write, wait-count, and error source.