Skip to content

AMBA APB · Module 8

PREADY Timing

How a subordinate actually drives PREADY — combinational versus registered, the sample window the manager reads it in, and the glitch and setup hazards that make a logically-correct PREADY still wrong on silicon. The signal-integrity layer beneath the PREADY handshake.

You already know what PREADY means — high completes the transfer, low inserts a wait. This chapter is about something subtler and more dangerous: how a subordinate drives PREADY in time, and why a PREADY that is logically correct can still be electrically wrong. The manager samples PREADY on one clock edge per access cycle, so PREADY must be a clean, settled, glitch-free value at that edge. The single idea to carry: PREADY has two valid implementations — combinational (fast, zero added latency, glitch-prone) and registered (clean, glitch-free, one cycle slower) — and choosing wrong, or building the combinational form carelessly, is how a wait-state design that passes a quick simulation fails timing or glitches in silicon.

1. Problem statement

The problem is presenting a stable, correct PREADY to the manager at the exact instant it samples — the rising clock edge in the access phase — regardless of how the subordinate computes "am I ready?"

A wait-state handshake is only as good as the timing of the one bit that drives it. The manager's transfer FSM samples PREADY on each PCLK rising edge while in access (PENABLE high) and decides, on that edge, whether the access completes or holds. For that decision to be correct, PREADY must satisfy two electrical requirements that "it is logically 1 when ready" does not capture:

  • It must be stable in the sample window. PREADY has to be settled from setup-time before the rising edge through hold-time after it. A value that is still rippling as the edge arrives is a setup violation or a metastability risk.
  • It must be glitch-free into that edge. If PREADY is combinational off a decode that settles in stages, it can momentarily pulse the wrong way mid-cycle; if that transient lands in the sample window, the manager reads a lie.

So the job is not "compute readiness" — it is "deliver readiness as a clean value the manager can trust on its sampling edge," which is a timing and signal-integrity problem, not just a logic one.

2. Why previous knowledge is insufficient

Module 3 named PREADY as the completion-and-backpressure control, and Module 5 drilled the per-cycle sampling cadence — that the manager checks PREADY every access edge. Both treat PREADY as an idealized bit that is simply "1 or 0." Real RTL has to produce that bit, and that is where this chapter goes:

  • A logically-correct PREADY can be electrically wrong. "Drive PREADY high when the data is ready" is a logic statement. Whether that high arrives stable and glitch-free at the sampling edge depends on whether it is combinational or registered and on the depth of the cone behind it. The handshake view never asks how PREADY is built.
  • Combinational and registered PREADY are different transfers, not just styles. A combinational PREADY can complete a fast access in its first cycle; a registered PREADY cannot — its earliest high is one cycle later. So the choice changes the minimum latency of every transfer on the bus, which the idealized view hides.
  • The sample window is the whole game. The manager does not care what PREADY does mid-cycle; it cares what PREADY is at the rising edge. Understanding wait states at the RTL level means understanding that window and what can corrupt it — glitch, setup violation, or an X propagating from an undriven path.

So the model to add is the physical one: PREADY as a signal that must be clean in a specific window, built either combinationally (fast, risky) or registered (clean, slower).

3. Mental model

The model: PREADY is a ready light the manager glances at once per beat — and it must be steady at the glance, not flickering. What matters is the light's state at the instant of the glance (the rising edge), not what it did between glances.

A combinational PREADY is a light wired straight through a network of switches: flip the inputs and the light eventually shows the right state — but while the switches settle, it can flicker. If the manager glances during a flicker, it sees the wrong thing. A registered PREADY is a light driven by a latch that only updates on the clock: it is rock-steady between edges and never flickers — but it shows last cycle's decision, so it is always one beat behind. The engineering choice is "fast but must be kept flicker-free" versus "clean but one beat slower."

Three refinements make it precise:

  • The glance is the rising edge in access. The manager samples PREADY on each PCLK rising edge while PENABLE is high. Only that instant matters; PREADY must meet setup and hold around it.
  • Combinational PREADY trades latency for cleanliness. It can complete a ready access in the first access cycle (zero wait states), but the cone that computes it must settle inside the cycle and not glitch into the sample window. The faster the bus clock, the harder that is.
  • Registered PREADY trades a cycle for safety. A flop guarantees a glitch-free, setup-friendly value, at the cost of one extra cycle of minimum latency. On a slow control bus, that cycle is usually free — which is why registered PREADY is the safe default.
A structural diagram with two paths to PREADY: the top combinational path runs ready logic straight into PREADY with a glitch-and-setup warning and zero added latency; the bottom registered path runs the ready logic through a flip-flop into PREADY, glitch-free but one cycle later, with the manager's sampling rising edge marked.
Figure 1 — the two ways to drive PREADY. Top, combinational: the ready logic (address decode plus a data-ready term) feeds PREADY directly through combinational gates, so PREADY can be high in the first access cycle (zero added latency) — but the cone must settle within the cycle and must not glitch into the manager's sample window, and on a fast clock it can violate setup. Bottom, registered: a flip-flop drives PREADY, so it is glitch-free and easy to time, but its earliest high is one cycle later, adding a cycle of minimum latency to every transfer. The figure frames the choice as fast-but-must-stay-clean versus clean-but-one-beat-slower, and marks the manager's sampling edge as the only instant that matters.

4. Real SoC implementation

In silicon, PREADY is the subordinate's output, and the two implementations are a few lines apart but worlds apart in behaviour. The combinational form drives readiness directly; the registered form clocks it.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// --- Combinational PREADY: fast (zero added latency) but must be glitch-free ---
// data_ready is a combinational term: is the addressed source available NOW?
// A fast subordinate that is always ready ties this high.
assign pready_comb = sel ? data_ready : 1'b1;   // unselected -> 1 (do not hold the bus)
// HAZARD: data_ready often depends on the PADDR decode; if that decode ripples,
// pready_comb can glitch. It must settle and be stable in the manager's sample
// window (setup before the PCLK rising edge through hold after it).
 
// --- Registered PREADY: glitch-free and timing-friendly, +1 cycle latency ---
// pready is now a clean flop output; its earliest high is one cycle after select.
always_ff @(posedge pclk or negedge presetn) begin
  if (!presetn)            pready_reg <= 1'b0;
  else if (sel && penable) pready_reg <= data_ready;  // sampled, then presented clean
  else                     pready_reg <= 1'b0;
end
// Trade-off in one line: pready_comb can complete in the first access cycle;
// pready_reg cannot — but pready_reg is rock-steady at the sampling edge.

Two facts drive the real decision. First, the sample window is the only timing constraint that matters: whichever form you pick, PREADY must be stable across the PCLK rising edge the manager samples on — a static-timing tool checks this as a normal setup/hold path, and a combinational PREADY with a deep decode cone is exactly where that path fails on a fast clock. Second, the default-ready rule: an unselected subordinate must drive PREADY high (or, more precisely, must not pull the shared/muxed PREADY low), so that the bus does not hang — which is why the combinational form returns 1'b1 when !sel. (How PREADY=0 then extends the access cycle by cycle is the transfer-extension mechanics; this chapter is about getting the PREADY value clean at the edge.)

An APB timing diagram showing PENABLE high across two access cycles, PCLK with dashed sample lines on its rising edges, and PREADY low-and-stable on the first sampled edge (hold) then high-and-stable on the second (complete), with the setup-and-hold sample window highlighted around each rising edge.
Figure 2 — the PREADY sample window across an access with one wait state, against PCLK. PENABLE is high throughout the access. The manager samples PREADY on each PCLK rising edge (the dashed sample lines). On the first access cycle PREADY is low and stable through the sample window — the access holds (a wait). On the second, PREADY is high and stable through the sample window — the access completes. The figure highlights the sample window around each rising edge (a setup region before and a hold region after) and stresses that PREADY must be settled and glitch-free across that window: what PREADY does between edges is irrelevant, but a transient inside the window is sampled as a real value.

5. Engineering tradeoffs

The combinational-versus-registered choice is the core PREADY design decision. Each row is a real consequence.

PREADY implementationWhat it gives upWhat it buysWhen to choose it
CombinationalGlitch immunity; easy timingZero added latency — completes in the first access cycleSlow clock, shallow ready cone, latency matters
RegisteredOne cycle of minimum latencyGlitch-free, setup-friendly, trivially timedFast clock, deep decode, or when robustness matters most
Always-ready (tie high)Any backpressureThe simplest, fastest pathA register that genuinely answers every cycle
!sel → 1 defaultA subordinate-side "busy when idle"A bus that never hangs on an unselected slaveAlways — an unselected slave must not pull PREADY low
Deep combinational coneTiming closure on a fast clock(nothing — this is the trap)Never on a fast bus; register it instead

The throughline: PREADY is the one bit whose timing — not just logic — decides whether a wait-state design works. On a slow control bus the combinational form is fine and saves a cycle; as the clock rises or the decode deepens, register it. When unsure, register it: a cycle of latency on sparse control traffic is cheap, a metastable manager is not.

6. Common RTL mistakes

7. Debugging scenario

A wait-state design that "works in a quick sim" but misbehaves on a faster clock or in gate-level is almost always a PREADY timing bug, not a logic bug — and it is invisible in a zero-delay RTL run.

  • Observed symptom: an access intermittently completes a cycle early (capturing garbage) or the design fails timing closure on the real clock, even though the RTL PREADY logic "looks right" and passes a fast zero-delay simulation. It gets worse as the clock frequency rises.
  • Waveform clue: in a gate-level or annotated-delay waveform (Figure 3), PREADY is combinational and glitches during the access cycle — it pulses high briefly as the PADDR decode settles, before the data is actually ready, and that transient lands inside the manager's sample window, so the manager samples a premature 1 and completes early.
  • Root cause: PREADY was driven combinationally off a multi-level cone that includes the PADDR decode; as the address bits settle at different times, the decode (and thus PREADY) ripples through intermediate states, one of which is a spurious high that coincides with the sampling edge.
  • Correct RTL: either register PREADY so it is a clean flop output — always_ff: if (sel && penable) pready <= data_ready; — or, if the combinational form is required, drive it from a settled, registered data_ready term and a registered select so the cone has no rippling decode in it: assign pready = sel_q ? data_ready_q : 1'b1;.
  • Verification assertion: assert PREADY is stable across the sampling edge and clean — e.g. assert property (@(posedge pclk) disable iff(!presetn) (psel && penable) |-> !$isunknown(pready)); plus a glitch check in gate-level sim that PREADY does not change within a guard window before the clock edge; and a property that the access does not complete before data_ready is genuinely asserted.
  • Debug habit: when a wait-state design works in RTL sim but fails on the real clock or in gate-level, do not re-read the PREADY logic — look at the PREADY timing: is it combinational off a decode? Run a delay-annotated or gate-level sim and watch PREADY across the sample window for a glitch. The fix is almost always to register PREADY or its inputs.
Two stacked APB timing diagrams of the same access: the top correct case has a registered PREADY that is clean and stable across both sampling edges; the bottom buggy case has a combinational PREADY that glitches high mid-cycle inside the first sample window, drawn in red, causing the manager to complete the access early.
Figure 3 — a combinational PREADY glitch versus a clean registered PREADY, on the same access. Top (correct, green): a registered PREADY is a clean flop output — low through the wait, high at completion, rock-steady across both sample windows, so the manager samples exactly the intended values. Bottom (bug, red): a combinational PREADY driven off a rippling PADDR decode pulses high briefly mid-cycle, before the data is ready, and that glitch lands inside the manager's sample window at the first access edge; the manager samples a premature high and completes the access a cycle early, capturing garbage. The figure shows that the bug is invisible in a zero-delay RTL run and only appears with real or annotated delays, which is why PREADY timing is debugged in gate-level, not RTL.

8. Verification perspective

PREADY timing bugs are the canonical "passes RTL, fails silicon" class, so verification has to attack them at the right level and with the right checks — a zero-delay RTL run will never catch a glitch.

  • Assert the sample-window contract. Bind properties that PREADY is never X while PSEL && PENABLE (catches undriven paths), and — in gate-level or delay-annotated simulation — that PREADY does not transition within a setup guard-band before each PCLK rising edge (catches glitches landing in the window). The X-check runs in RTL; the glitch check needs delays.
  • Check readiness causality, not just value. Beyond "is PREADY clean," assert that the access does not complete before the data is genuinely available: (complete) |-> (data_was_ready). This catches the asserted-too-early bug, which is a different failure from a glitch and which a stability check alone will miss.
  • Cover both implementations and the corners. Functional coverage should distinguish a combinational-ready completion (complete in the first access cycle) from a registered-ready completion (complete one cycle later), and hit: zero-wait, one-wait, multi-wait, an unselected slave during another's access (default-ready), and back-to-back transfers. A wait-state suite that never exercises the first-cycle completion path has a hole exactly where the combinational glitch lives. (Wait-state coverage is a chapter of its own.)

The point: PREADY correctness is a timing property, so the verification plan must specify the level (gate-level for glitches) and the causality (ready-before-complete), not just sample the value in RTL.

9. Interview discussion

"Combinational or registered PREADY — which, and why?" is a sharp senior question because it separates people who know the handshake from people who have closed timing on one. A weak answer picks one; a strong answer states the trade and the hazard.

Frame it as latency versus integrity: combinational PREADY adds zero latency and can complete an access in its first cycle, but its cone must settle within the cycle and stay glitch-free across the manager's sample window — risky on a fast clock or a deep PADDR decode. Registered PREADY is glitch-free and trivially timed but adds one cycle of minimum latency to every transfer. Then deliver the depth points: the only instant that matters is the manager's sampling edge (a transient outside the window is harmless; one inside it is sampled as real), and the classic bug — a combinational PREADY glitching off a rippling decode — is invisible in zero-delay RTL and only shows up in gate-level, which is why you either register PREADY or drive it from registered inputs, and verify it with a glitch check plus a ready-before-complete property. Closing with "on a slow control bus I register it by default — a cycle is cheap, a metastable manager is not" signals real silicon experience.

10. Practice

  1. Place the window. On an access with one wait state, mark each PCLK edge the manager samples PREADY and the setup/hold window around it; state what PREADY between edges is allowed to do.
  2. Compare latency. For the same always-ready subordinate, state the earliest completion cycle with a combinational PREADY versus a registered PREADY, and why they differ by one.
  3. Spot the glitch. Given a combinational PREADY = decode(paddr) & data_ready, explain how a rippling PADDR can glitch PREADY and what must be true for that glitch to corrupt a transfer.
  4. Write both forms. From memory, write the combinational and the registered PREADY, and the !sel → 1 default, and explain the latency and integrity trade between them.
  5. Pick the level. State which PREADY bug a zero-delay RTL simulation can catch and which requires gate-level or delay-annotated simulation, and the assertion for each.

11. Q&A

12. Key takeaways

  • PREADY correctness is a timing property, not just a logic one. It must be stable and glitch-free in the manager's sample window — the PCLK rising edge in the access phase — or a logically-right PREADY is sampled wrong.
  • Combinational PREADY is fast but risky: zero added latency (can complete in the first access cycle), but its cone must settle within the cycle and not glitch into the sample window.
  • Registered PREADY is clean but a beat slower: glitch-free and trivially timed, at the cost of one cycle of minimum latency on every transfer. It is the safe default on a slow control bus.
  • An unselected subordinate must drive PREADY high (the !sel → 1 default), or it stalls another slave's access or hangs the bus on an unmapped address.
  • The classic bug — a combinational PREADY glitch off a rippling decode — is invisible in zero-delay RTL and only appears in gate-level or delay-annotated simulation; the fix is to register PREADY or its inputs.
  • Verify PREADY at the right level: X-checks and ready-before-complete causality in RTL, and a glitch guard-band check in gate-level — and cover both the first-cycle (combinational) and one-later (registered) completion paths.