Skip to content

PREADY is mandatory from APB3 onward — the manager samples it to complete every transfer, so tying it high is a design decision with a correctness obligation, never a licence to ignore the signal. The belief that PREADY is "optional in simple designs" is an APB2 memory that outlived the protocol it came from: APB2 genuinely had no PREADY and every access was a fixed two cycles, so a generation of engineers learned that the bus "just completes on schedule." APB3 added PREADY and made it part of the completion contract — the manager holds the ACCESS phase while PREADY is low and completes only when it samples PREADY high. The single idea to carry: a slave may legitimately drive assign pready = 1'b1; forever, but only because it is promising to be genuinely ready in one ACCESS cycle; and a manager may never assume that promise on the slave's behalf. Tie-high is an obligation; ignoring the sample is a bug.

1. Problem statement

The problem is that PREADY is treated as decoration you can drop for "simple" designs, when it is in fact the bit the manager uses to decide that any transfer has completed at all. Two mistakes hide under the same myth, and they fail in opposite directions.

  • The slave-side mistake: "my slave is simple, so I can tie PREADY high and forget it." Tying PREADY = 1 is perfectly legal — but only if the slave truly presents valid PRDATA (on a read) or accepts PWDATA (on a write) within the single ACCESS cycle. The moment that slave grows a clock-domain crossing, a multi-cycle memory, or an arbitrated resource, the tie-high is a lie: it claims readiness it does not have, and the transfer completes over invalid data.
  • The manager-side mistake: "I can ignore PREADY because my slaves are fast." A manager that hard-wires a fixed two-cycle completion — never sampling PREADY — will complete a transfer before a slow slave is ready. On a read it captures whatever stale value is still on PRDATA; on a write it launches PWDATA at a slave that never accepted it, and the write is silently dropped.

So the engineering problem is not "is PREADY needed?" — from APB3 it always is — but "what is the actual contract each side signs, and what breaks when either side treats PREADY as optional?" The AMBA APB specification (IHI 0024C) §2.1 lists PREADY as a slave output that the manager uses to extend the transfer; there is no conformant APB3+ manager that omits sampling it. The myth is real only as history — and this chapter's job is to separate the legal design decision (tie-high, honestly zero-wait) from the correctness violation (ignoring the sample) that the myth conflates.

2. Why previous knowledge is insufficient

You already know the mechanics of the handshake — this chapter is not re-teaching them, it is dismantling a belief that survives despite knowing them.

  • The ready handshake chapter taught how PREADY low holds the ACCESS phase and PREADY high releases it. That is the mechanism. It does not, by itself, tell you that a manager which never samples the signal is non-conformant, nor why "tie it high" is sometimes fine and sometimes catastrophic. The mechanism is necessary; the obligation attached to each side is the missing piece.
  • The PREADY introduction rationale explained why APB3 added flow control — latency-diverse peripherals were illegal without it. That reframes PREADY as making slow peripherals legal, which is exactly the counter to "it is optional": a signal that makes a whole class of designs legal is not optional. But that chapter argues the design-pressure case; this one argues the conformance and bug case at the level of the individual transfer.
  • The APB version evolution chapter and the APB3 introduction name the history — APB2 with no PREADY, APB3 = APB2 + PREADY + PSLVERR. That history is precisely where the myth is born: because APB2 really had no PREADY, "you can ignore it" was once true. The gap is that engineers carry the APB2 truth into an APB3+ world without noticing the version boundary that invalidated it.

The gap is therefore not mechanical knowledge — it is the failure to distinguish a legal simplification (a genuinely zero-wait slave tying PREADY high, and a manager that still samples it and finds it always high) from an illegal shortcut (a manager that stops sampling, or a slave that ties high while not truly ready). Building that distinction, and grounding it in the APB2-to-APB3 boundary where the myth originates, is this chapter. Where these mistakes turn into concrete shipped RTL bugs is the common design bugs catalog.

3. Mental model

The model: PREADY is a promise the slave makes and the manager must always read — tie-high is "I promise to be ready in one cycle," and ignoring the sample is "I refuse to listen to the promise." Both sides of the transfer sign a contract, and the myth is the fantasy that one side can quietly skip its signature.

Hold three refinements:

  • Tie-high is a decision with an obligation, not the absence of a decision. assign pready = 1'b1; is a real, legal, common design choice — for a register file that answers combinationally, it is exactly right. But it asserts that the slave is zero-wait: valid data on every read edge, accepted write on every write edge, no exceptions. If the RTL ever cannot honour that, the tie-high has become a false promise, and the fix is not "remove PREADY" — it is "drive PREADY from the real data-valid term."
  • The manager must sample PREADY even when it is always high. A conformant APB3 manager completes a transfer on the edge where psel && penable && pready all hold. If every slave happens to be zero-wait, the manager samples PREADY and finds it 1 every time — and the code path that checks it must still exist. The bug is not "the slave is fast"; the bug is a manager whose completion logic has no PREADY term at all, so it would complete a slow slave early the moment one appears on the bus.
  • "Simple" is a property of the slave, not a licence for the manager. A simple, zero-wait slave lets the slave tie PREADY high. It never lets the manager stop sampling. The manager is shared across every slave; the day a CDC or flash peripheral is added, a manager that ignored PREADY corrupts it — while a manager that always sampled it just naturally waits.

The discipline this buys you: separate the two signatures. When you see PREADY = 1, ask "is this slave genuinely zero-wait?" — a slave question. When you see a completion that does not include a PREADY term, ask "does this manager sample PREADY at all?" — a manager question. The myth collapses the moment you stop treating "optional" as a single claim and see it as two distinct, both-wrong shortcuts.

A two-column myth-versus-reality map. The left red column states the PREADY-is-optional myth and its APB2 origin and lists stale-read and dropped-write consequences. The right green column states that PREADY is mandatory from APB3, that tie-high is a zero-wait obligation not an act of ignoring the signal, and that the manager must always sample it. A bottom band shows APB2 had no PREADY while APB3 and APB4 require it.
Figure 1 — the myth versus the reality of PREADY being optional. The left (red) column states the myth — PREADY is optional and can be ignored in simple designs — and traces it to its true root: APB2 had no PREADY, so a fixed two-cycle transfer was the whole story and 'the bus completes on schedule' was a safe habit. It then shows what ignoring PREADY actually does on APB3: the manager completes before a slow slave is ready and captures stale PRDATA on a read, or drops the write. The right (green) column states the reality: from APB3 the manager samples PREADY every ACCESS cycle to complete every transfer, so tying PREADY high always is a legitimate decision only when the slave is genuinely zero-wait, and it carries the obligation to actually present valid data in the one ACCESS cycle — a promise, not an act of ignoring the signal. The bottom band tracks the version history that the myth forgets: APB2 had none, APB3 and APB4 require it.

4. Real SoC implementation

Here are the two sides of the contract in real APB signals: a legitimate always-ready slave that ties PREADY high (and the obligation that makes it correct), contrasted with a wrong manager that ignores PREADY and completes on a fixed two-cycle assumption — the exact code that captures stale reads and drops writes.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ============================================================
// LEGITIMATE — an always-ready (zero-wait) register slave.
// Tying PREADY high is a DESIGN DECISION, and it is correct here
// ONLY because this slave genuinely answers in the single ACCESS
// cycle: the read mux is combinational and the write commits in
// one PCLK edge. The tie-high is a PROMISE the RTL keeps.
// ============================================================
module apb_reg_slave (
  input              pclk, presetn,
  input              psel, penable, pwrite,
  input      [11:0]  paddr,
  input      [31:0]  pwdata,
  output reg [31:0]  prdata,
  output             pready              // tied high — see the obligation below
);
  reg [31:0] ctrl_q, status_q;
 
  // OBLIGATION #1 (read): valid PRDATA in the SAME ACCESS cycle,
  // combinationally, so 'ready now' is true.
  always_comb begin
    prdata = 32'h0;
    case (paddr[3:2])
      2'd0: prdata = ctrl_q;
      2'd1: prdata = status_q;
      default: prdata = 32'h0;
    endcase
  end
 
  // OBLIGATION #2 (write): accept PWDATA on the ACCESS edge, one cycle.
  always_ff @(posedge pclk or negedge presetn) begin
    if (!presetn)                       ctrl_q <= 32'h0;
    else if (psel && penable && pwrite) ctrl_q <= pwdata;   // committed in one cycle
  end
 
  // The tie-high is legal because BOTH obligations hold every access.
  // If this slave later gained a CDC/flash path, this line would become
  // a FALSE promise and must be replaced by a real data-valid term.
  assign pready = 1'b1;                  // genuinely zero-wait: honest, not "ignoring PREADY"
endmodule
 
// ============================================================
// WRONG — a manager that IGNORES PREADY and completes on a fixed
// two-cycle assumption (the APB2 habit surviving into APB3).
// It never samples pready, so a slow slave is completed EARLY:
// reads capture stale PRDATA, writes are dropped.
// ============================================================
module apb_mgr_ignores_pready (
  input             pclk, presetn,
  output reg        psel, penable,
  input             pready,             // <-- present on the port, NEVER sampled
  input     [31:0]  prdata,
  output reg [31:0] capture_q
);
  typedef enum logic [1:0] {IDLE, SETUP, ACCESS} state_e;
  state_e state;
 
  always_ff @(posedge pclk or negedge presetn) begin
    if (!presetn) begin
      state <= IDLE; psel <= 1'b0; penable <= 1'b0; capture_q <= 32'h0;
    end else case (state)
      IDLE:   begin psel <= 1'b1; penable <= 1'b0; state <= SETUP;  end
      SETUP:  begin              penable <= 1'b1; state <= ACCESS; end
      ACCESS: begin
        // BUG: completes here unconditionally, WITHOUT checking pready.
        // A slow slave still has pready == 0 and stale prdata right now.
        capture_q <= prdata;         // captures STALE data if slave not ready
        psel <= 1'b0; penable <= 1'b0; state <= IDLE;   // drops a write the same way
      end
    endcase
  end
endmodule
 
// CORRECT completion term (what the ACCESS state MUST use):
//   if (penable && pready) begin capture_q <= prdata; state <= IDLE; end
//   else                   state <= ACCESS;   // hold the phase — sample PREADY again
// i.e. complete only on:  psel && penable && pready.

Two facts make this contrast the whole lesson. First, the tie-high slave is not "ignoring PREADY" — it is answering it. It drives PREADY = 1 because it has genuinely done the work in one cycle; the always_comb read and the one-edge write commit are the evidence behind the promise. Remove that evidence (add a CDC path) and the same assign pready = 1'b1; becomes a bug — the tie-high was correct only as long as the obligation held. Second, the wrong manager's flaw is structural, not a fast/slow accident. Its ACCESS state completes with no pready term at all, so it is correct by luck on zero-wait slaves and broken by design the instant a slow slave shares the bus. The fix is not more speed — it is adding the one term the myth told it to omit: complete only when psel && penable && pready.

5. Engineering tradeoffs

The real decision is not "use PREADY or not" — from APB3 you always must — it is which slaves may legitimately tie it high, and how a manager must be written so no slave can be completed early. This table sorts the four positions the myth blurs together.

PositionLegal on APB3+?What it actually requiresWhat breaks if the requirement fails
Slave ties PREADY = 1, genuinely zero-waitYes — a real design decisionValid PRDATA every read edge; write committed in one ACCESS cycleNothing — this is the correct always-ready pattern
Slave ties PREADY = 1, but not truly readyNo — a false promise(it cannot meet the requirement)Reads complete over unsettled/stale data; writes race the commit
Manager samples PREADY, slaves happen to be fastYes — conformantA completion term of psel && penable && preadyNothing — and it stays correct when a slow slave is added
Manager ignores PREADY (fixed 2-cycle)No — non-conformant(it omits the mandatory sample)Slow slave completed early: stale reads, dropped writes

The throughline: only two of the four are legal, and both keep PREADY in the contract. The legal tie-high keeps it as a slave promise the RTL honours; the legal manager keeps it as a sample it always performs. The two illegal positions are the myth's two faces — a slave that promises readiness it lacks, and a manager that refuses to read the promise at all. Note the asymmetry that makes the manager mistake more dangerous: a false-promise slave breaks only its own transfers, but a PREADY-ignoring manager breaks every slow slave that ever shares its bus — it is a latent, bus-wide bug that hides until the first non-zero-wait peripheral is integrated, which is often long after the manager was "verified." That is why "we can ignore PREADY, our slaves are fast" is the costlier half of the myth: it fails on a design the manager's author never saw. Keeping every slave to the always-ready obligation or driving PREADY from a real data-valid term is covered in the slave RTL templates; driving PREADY correctly in either case is PREADY generation.

6. Common RTL mistakes

7. Debugging scenario

Take the classic form of this bug: an APB2-era manager reused on an APB3 subsystem, where the myth "PREADY was optional, our old manager is fine" is baked straight into silicon.

  • Observed symptom: a subsystem integrates a new flash-backed configuration peripheral alongside the existing GPIO and timer blocks. The GPIO and timer read and write flawlessly, but the flash peripheral reads back the wrong value on the first access after any address change, and some configuration writes never take effect — the register reads back its reset value. No bus error, no hang, no protocol assertion fires on the fast peripherals.
  • Waveform clue: on the flash access (Figure 2), the slave holds PREADY low for one ACCESS cycle because its data is not valid yet — but the manager asserts PSEL/PENABLE for exactly two cycles and completes regardless, sampling PRDATA while it still holds the previous read's value and PREADY is still 0. On a write, PSEL/PENABLE drop before the slave ever sampled PWDATA with PREADY high. The fast peripherals happen to have PREADY high in that same window, so they look correct — masking the bug.
  • Root cause: the manager was ported from an APB2 design and its ACCESS state completes on a fixed two-cycle count with no PREADY term. On APB2 that was legal — there was no PREADY. On APB3 it is a conformance violation: the manager never samples PREADY, so any slave that inserts even one wait state is completed early. The tie-high fast slaves hid it; the honestly-slow flash slave exposed it. The myth "PREADY is optional in simple designs" was encoded as a two-cycle assumption that the flash peripheral violated.
  • Correct RTL: make completion depend on the sampled PREADY, holding the ACCESS phase while it is low:
    Azvya Education Pvt. Ltd.VLSI Mentor
    Snippet
    // ACCESS state: complete ONLY when the slave is ready; otherwise hold and re-sample.
    ACCESS: if (penable && pready) begin
              capture_q <= prdata;                 // read data now guaranteed valid
              psel <= 1'b0; penable <= 1'b0; state <= IDLE;   // write also accepted here
            end else begin
              state <= ACCESS;                     // PREADY low -> extend, sample again
            end
  • Verification assertion: prove the manager never completes a transfer while the slave is not ready — the exact thing the myth lets slip:
    Azvya Education Pvt. Ltd.VLSI Mentor
    Snippet
    // A transfer may complete only on psel && penable && pready.
    // If the manager ever tears down the access while pready is low, this fires.
    assert property (@(posedge pclk) disable iff (!presetn)
      (psel && penable && $fell(penable)) |-> $past(pready)
    );
  • Debug habit: when a newly integrated peripheral reads stale or drops writes while the existing peripherals are fine, do not suspect the new slave first — suspect the manager's completion term. Ask immediately: does the manager sample PREADY, or does it complete on a fixed cycle count? A fault that appears only on the first slow slave added to an otherwise-working bus is the fingerprint of a manager that inherited the "PREADY is optional" assumption from an APB2 lineage. The related failure where a slave leaves PREADY low forever is PREADY stuck low; the full completion rules are transfer completion rules.
Two stacked APB read timing diagrams of the same slow slave that needs one wait state. The top red case shows a manager ignoring PREADY and completing early at the first ACCESS edge while PREADY is low and PRDATA is stale, capturing the wrong value. The bottom green case shows a manager holding the ACCESS phase while PREADY is low and completing on the edge PREADY rises with valid PRDATA, capturing correct data. Both completing edges are marked.
Figure 2 — a slow slave that needs one wait state, read two ways. The slave holds PREADY low for the first ACCESS cycle because its data is not valid yet, then drives PREADY high the cycle the data becomes valid. Top (bug, red): the manager ignores PREADY and completes on a fixed two-cycle assumption, tearing down the access at the first ACCESS edge while PREADY is still low and PRDATA still holds the previous read's value — so it captures stale data (and a write here would be dropped, since the slave never accepted it). Bottom (correct, green): the manager samples PREADY every ACCESS cycle, sees it low and holds the phase, then completes on the edge where PREADY is high and PRDATA is valid, capturing correct data. Both completing edges are marked, showing that from APB3 the manager completes only when psel and penable and pready all hold.

8. Verification perspective

Because the myth is really two shortcuts — a slave tie-high that may be a false promise, and a manager that may not sample at all — the verification job is to prove both signatures are present: the slave is honestly ready whenever it claims to be, and the manager completes only on a sampled PREADY. Neither is caught by a testbench that only ever drives zero-wait slaves.

  • Manager side — completion must include the PREADY sample. The core property is that a transfer completes only when the slave is ready. Assert that the access is never torn down while PREADY is low, and equivalently that the completing edge coincides with PREADY high:
    Azvya Education Pvt. Ltd.VLSI Mentor
    Snippet
    // Manager completes a transfer ONLY on psel && penable && pready.
    // Any completion with PREADY low is the "ignored PREADY" bug.
    property complete_only_when_ready;
      @(posedge pclk) disable iff (!presetn)
        (psel && penable && pready) or          // legal completion window, or
        (psel && penable && !pready) |=> psel;  // if not ready, must still be selected (held)
    endproperty
    assert property (complete_only_when_ready);
  • Slave side — a tied-high PREADY must be backed by valid data in the ACCESS cycle. A slave that drives PREADY high is promising readiness; assert that whenever it does, its data-valid term genuinely holds — so a false tie-high fires rather than passing silently:
    Azvya Education Pvt. Ltd.VLSI Mentor
    Snippet
    // A tie-high (or any high) PREADY must present valid data in the SAME ACCESS cycle.
    // If the slave claims ready without valid data, this catches the false promise.
    assert property (@(posedge pclk) disable iff (!presetn)
      (psel && penable && pready && !pwrite) |-> !$isunknown(prdata) && data_valid
    );
  • Sweep zero-wait and wait-inserting slaves against the same manager. The manager mistake is invisible if every slave is zero-wait — the fixed two-cycle completion happens to land on PREADY high. So the verification plan must drive the manager against a slave that inserts one, then several, wait states, and confirm it holds the phase and completes correctly in each case. Reuse the wait-state randomization from multiple wait cycles, and cover the zero-wait, single-wait, and multi-wait bins explicitly — the zero-wait bin is where a broken manager passes, so a plan that stops there certifies the bug.

The point: proving PREADY is honoured is not one check but two — a safety property that the manager never completes early, and a promise property that a tie-high slave is genuinely ready — exercised across a latency sweep that the myth would let you skip. Why the wait states exist in the first place is why wait states exist.

9. Interview discussion

"Is PREADY optional — can a simple slave just ignore it?" is a deliberately baited question. The weak answer takes the bait ("yes, if it is fast you can tie it high and ignore it"); the strong answer separates the legal decision from the myth.

Lead with the version boundary: PREADY was genuinely absent in APB2 — every transfer was a fixed two cycles — so "you can ignore it" was once true, and that is exactly where the myth is born (cite the APB2-to-APB3 evolution and IHI 0024C §2.1). From APB3 the manager samples PREADY to complete every transfer, so it is mandatory. Then draw the two-signature distinction that shows real understanding: tying PREADY = 1 is a legitimate slave decision, but it carries an obligation — the slave must genuinely present valid data (or accept the write) in the one ACCESS cycle; it is a promise, not an act of ignoring the signal. Separately, a manager may never stop sampling PREADY, because it is shared across every slave and will corrupt the first slow one it meets. Land the silicon depth point: the costlier half of the myth is the manager side — a manager ported from an APB2 design that completes on a fixed two-cycle count reads stale data and drops writes the instant a CDC or flash peripheral shares its bus, a latent bug that passes on every fast slave and surfaces only at integration. Close with the crisp line: PREADY is mandatory from APB3; tie-high is a zero-wait promise the slave must keep, and the manager must always sample it — "optional" is an APB2 habit, not an APB3 truth. That answer signals you reason about conformance, obligations, and integration risk, not just handshakes.

10. Practice

  1. Split the myth. State the two distinct shortcuts the phrase "PREADY is optional" hides — one on the slave, one on the manager — and say which one is a legal decision and which is always a bug.
  2. Justify a tie-high. For a combinational register file, write the two obligations that make assign pready = 1'b1; correct, and describe the one change to that slave that would turn the same line into a false promise.
  3. Find the missing term. Given a manager whose ACCESS state completes on a fixed two-cycle count, write the corrected completion condition and explain why it stays correct when a slow slave is later added to the bus.
  4. Trace the failure. For a read and for a write to a slow slave, describe exactly what a PREADY-ignoring manager captures or drops, and why the fast peripherals on the same bus hide it.
  5. Write both checks. Sketch the SVA that proves a manager completes only on psel && penable && pready, and the SVA that proves a tied-high slave actually presents valid data in the ACCESS cycle — and say which half of the myth each one catches.

11. Q&A

12. Key takeaways

  • PREADY is mandatory from APB3 onward. The manager samples it to complete every transfer (AMBA APB IHI 0024C §2.1). The "optional in simple designs" belief is an APB2 memory — APB2 really had no PREADY — carried across the version boundary that invalidated it.
  • Tie-high is a decision with an obligation, not an act of ignoring the signal. assign pready = 1'b1; is legal only when the slave is genuinely zero-wait: valid PRDATA every read edge, write committed in one ACCESS cycle. It is a promise the RTL must keep, and it becomes a bug the moment the slave grows a multi-cycle path.
  • The manager must always sample PREADY, even when slaves are fast. A completion term without a PREADY bit is correct only by luck on zero-wait slaves and corrupts the first slow slave that shares the bus. Complete only on psel && penable && pready.
  • The manager mistake is the costlier half of the myth. A false-promise slave breaks only its own transfers; a PREADY-ignoring manager breaks every slow slave that ever shares its bus — a latent, bus-wide bug that passes on fast slaves and surfaces at integration, often on a peripheral its author never saw.
  • Verify both signatures. A safety property that the manager never completes while PREADY is low, and a promise property that a tied-high slave genuinely presents valid data in the ACCESS cycle — exercised across a zero-wait-through-multi-wait latency sweep, because the zero-wait-only test is where a broken manager passes.