The myth is that an APB transfer always completes in one clock cycle. The correction is that APB is defined as a two-phase transfer — a SETUP cycle followed by an ACCESS cycle — so the minimum is two cycles, and because PREADY can hold the ACCESS phase, a transfer extends to any number of cycles. APB is genuinely simple and unpipelined, and that simplicity is exactly what gets mis-remembered as "single-cycle." This chapter takes the belief apart: it states the myth precisely, shows the multi-cycle counterexample the myth cannot survive, traces where the belief comes from, catalogues the real bugs it ships, and hands you the crisp two-sentence argument that settles it in a review or an interview.
1. Problem statement
The problem is that a large number of otherwise-competent engineers carry the belief that "an APB transfer is one clock cycle," and that belief is false in a way that quietly ships real bugs. Stated precisely, the myth is: an APB access asserts its control and data and completes on a single PCLK edge, so a manager can drive one beat per cycle and a subordinate can be modelled as a fixed one-cycle latch. Every clause of that sentence is wrong.
Where does the belief come from? Three roots, and they are worth naming because each points at a different mind that holds it:
- Confusing "simple / unpipelined" with "single-cycle." APB is the simplest AMBA bus — no pipelining, no bursts, one transfer at a time. The mind hears "simple, one transfer at a time" and compresses it to "one cycle per transfer." But "unpipelined" means transfers do not overlap; it says nothing about how many cycles one transfer takes. The two ideas got fused, and the fused version is the myth.
- Only ever having seen a zero-wait slave. In a first testbench the subordinate is usually a register file that is always ready —
PREADYis tied high — so every transfer happens to take the same small number of cycles and the engineer never watches a wait state form. From that sample of one, "it always takes the same short time" hardens into "it takes one cycle." - Collapsing the two phases into one mental cell. SETUP and ACCESS are two distinct cycles with different control-signal values, but on a lazy reading of a waveform — where
PSELis high across both — they blur into a single "the transfer" box. Once the two phases are one box in your head, "the transfer is one cycle" follows naturally.
The engineering stakes are concrete. A manager built on the myth never samples PREADY — it assumes completion after a fixed count — so the first time it meets a real slave that inserts a wait state, it reads before the data is valid or drives the next beat on top of an unfinished one. A subordinate model built on the myth is a fixed one-cycle latch that no real slow peripheral matches, so integration breaks the moment a flash controller, a re-timed CDC bridge, or a clock-divided peripheral needs even one wait cycle. The myth is not a harmless simplification; it is a specification error waiting for a slow peripheral.
2. Why previous knowledge is insufficient
If you have read the earlier chapters of this track, you already know the correct mechanics — but knowing the mechanics is not the same as being inoculated against the myth, because the myth is a framing error, not a mechanics gap.
- The transfer overview and single-cycle transfer chapters taught the SETUP and ACCESS phases and the zero-wait case. But the very existence of a "single-cycle transfer" chapter is where the myth hides: "single-cycle transfer" is loose shorthand for "single-wait-state-free transfer," which is still two clock cycles (SETUP + ACCESS). Read the phrase without care and it feeds the myth instead of refuting it. This chapter exists to nail down that "no wait states" is not "one cycle."
- The multi-cycle transfer and multiple wait cycles chapters taught that
PREADYextends ACCESS. You can know that mechanism cold and still mentally default to "usually it's one cycle though," because the wait-state case was filed as an exception rather than as proof that the transfer length is variable by design. - Why wait states exist and slow-peripheral behaviour explained why a slave stalls. That is the motivation; it does not by itself dislodge the false default count in an engineer's head.
The gap this chapter closes is not a missing fact. It is a mis-set default: the earlier chapters give you the true model as one option among several, and the myth is the habit of treating "one cycle" as the baseline and everything else as a special case. The fix is to invert the default — the baseline is "at least two cycles, extensible" — and to be able to argue it from the spec on demand. That inversion, and the argument, is the content here.
3. Mental model
The model to install, replacing "one cycle," has two moving parts and one hard floor:
- Part one — the mandatory two phases. Per AMBA APB (IHI 0024C) §3.1, every transfer is a SETUP cycle followed by an ACCESS cycle. In SETUP the manager asserts
PSELand drivesPADDR,PWRITE, and (for a write)PWDATA, withPENABLElow. On the next edge it enters ACCESS by raisingPENABLE. These are two distinct clock cycles with different control values — they cannot be collapsed. This alone makes the hard floor two cycles: there is no legal way to complete a transfer in onePCLKcycle, ever. - Part two — the extensible ACCESS phase. The ACCESS phase is not one cycle wide by definition; it is held for as long as the subordinate keeps
PREADYlow. Each cycle the manager sits in ACCESS withPREADYsampled low is one wait state. When the subordinate finally drivesPREADYhigh, that cycle is the completing cycle — the manager samplesPRDATA(on a read) and the transfer ends. So the ACCESS phase is one-or-more cycles.
Put the two parts together and the transfer length is:
length = 1 (SETUP) + 1 (first ACCESS) + N (wait states) = 2 + N cycles, N ≥ 0.
The floor is 2 (a zero-wait slave), and there is no ceiling in the protocol — the count is set by the subordinate, not fixed by the bus. Three refinements sharpen the model:
- "Simple" governs concurrency, not duration. APB's simplicity is that it is unpipelined — only one transfer is ever in flight. That says the next transfer waits for this one; it says nothing about how many cycles this one takes. Duration is a
PREADYquestion, entirely separate from the pipelining question. - The manager's obligation is a sample, not a count. A correct manager does not "wait a fixed number of cycles"; it samples
PREADYat every ACCESS edge and only completes when it reads high. The moment you model completion as a count you have re-introduced the myth. - Zero-wait is a slave choice, not a protocol guarantee. A slave may tie
PREADYhigh and give you the 2-cycle minimum on every access — but nothing in the protocol promises the slave you actually integrate against will do so. Designing for the minimum is designing for a slave you might not get.
4. Real SoC implementation
The fastest way to kill the myth is a counterexample it cannot survive: one real read that is unambiguously more than one cycle. Take a subordinate that needs time to fetch — a flash-shadow register, a clock-divided peripheral, a CDC bridge — and inserts two wait states. The read is then SETUP + ACCESS + 2 waits = 4 cycles.
Here is a compact subordinate that produces exactly that, using the real APB signals, followed by the cycle-by-cycle numbers.
// A subordinate that needs two wait states before its read data is valid.
// One read through this block is SETUP + ACCESS + 2 waits = 4 PCLK cycles.
module apb_slow_read_slave #(parameter int WAITS = 2) (
input logic pclk,
input logic presetn,
input logic psel,
input logic penable,
input logic pwrite,
input logic [11:0] paddr,
input logic [31:0] pwdata,
output logic [31:0] prdata,
output logic pready,
output logic pslverr
);
logic [3:0] cnt; // counts wait cycles inside the ACCESS phase
logic [31:0] mem [0:1023];
// ACCESS phase = psel && penable. Hold PREADY low for WAITS cycles, then complete.
always_ff @(posedge pclk or negedge presetn) begin
if (!presetn) begin
cnt <= '0;
pready <= 1'b0;
prdata <= '0;
end else if (psel && penable) begin // we are in the ACCESS phase
if (cnt == WAITS) begin
pready <= 1'b1; // completing cycle: data is now valid
prdata <= mem[paddr[11:2]]; // present read data on the SAME edge PREADY rises
end else begin
cnt <= cnt + 1'b1; // still fetching: insert one more wait state
pready <= 1'b0; // PREADY low => ACCESS is held one more cycle
end
end else begin // SETUP or idle: not in ACCESS, not ready
cnt <= '0;
pready <= 1'b0;
end
end
assign pslverr = 1'b0; // no error path in this minimal example
endmoduleNow the numbers for one read, the counterexample in full. PADDR is stable across all four cycles; PSEL is high throughout.
| Cycle | Phase | PSEL | PENABLE | PREADY | PRDATA | What happens |
| --- | --- | --- | --- | --- | --- |
| C1 | SETUP | 1 | 0 | 0 | — | Manager drives PADDR/PWRITE; PENABLE still low. |
| C2 | ACCESS (wait 1) | 1 | 1 | 0 | invalid | Manager raises PENABLE, samples PREADY — low, so it stays in ACCESS. |
| C3 | ACCESS (wait 2) | 1 | 1 | 0 | invalid | Second wait state; PREADY still low, ACCESS held again. |
| C4 | ACCESS (complete) | 1 | 1 | 1 | valid | Slave drives valid PRDATA and raises PREADY; manager samples the data and completes. |
That read is four cycles. Set WAITS = 0 and the same module gives you a two-cycle read (SETUP + a single ACCESS that is immediately ready) — still not one cycle. There is no parameter value, no address, no configuration of this legal subordinate that produces a one-cycle transfer, because the SETUP phase is unconditional. The myth predicts one cycle; the spec-compliant hardware produces two-or-more. The counterexample stands, and one counterexample is all it takes to falsify a universal claim.
5. Engineering tradeoffs
If the transfer is never one cycle, the real design question is how many cycles, and that is a genuine tradeoff surface — the myth's damage is that it hides this surface entirely.
- Minimum-latency (zero-wait) slaves vs. area/timing. A subordinate can tie
PREADYhigh and answer in the 2-cycle minimum, but only if its read-data path closes timing combinationally within one ACCESS cycle. A large register file, a memory macro, or anything behind a CDC boundary usually cannot, so it chooses wait states to buy setup time. The tradeoff is latency (more wait states) versus timing closure and area (a faster, wider, more pipelined data path). The myth erases this choice by pretending latency is fixed at one. - Fixed-count managers vs.
PREADY-sampling managers. A manager that assumes a fixed cycle count is smaller and simpler — noPREADYinput to route or sample. But it is only correct against the exact slave it was tuned to, and it breaks silently against any other. APREADY-sampling manager costs one extra sampled input and a tiny bit of FSM logic and is correct against every legal slave. The correct trade is always to sample; the "saving" from not sampling is a latent integration bug, not a real saving. - Modelling a slave as a one-cycle latch vs. a wait-capable model. In early architecture models it is tempting to stub every peripheral as a one-cycle latch for speed. That is fine as an abstraction only if the surrounding manager still samples a (constant-high) ready; the moment the stub's fixed latency leaks into the manager's assumptions, you have baked the myth into the model and it will diverge from silicon.
The throughline: APB gives you a latency dial (wait states), not a latency constant. Every real design sits somewhere on that dial for good timing/area reasons, and every correct manager must tolerate the whole dial. The myth's cost is that it convinces you the dial does not exist.
6. Common RTL mistakes
7. Debugging scenario
The myth ships a specific, recognisable field bug. Here is the canonical one.
- Observed symptom: a driver that has worked for months against an on-chip register block starts reading garbage — and occasionally hanging — the moment it is pointed at a newly added peripheral (say, a flash-configuration block or a sensor bridge behind a clock divider). Reads from the old block are still fine. The bus shows no protocol error flagged.
- Waveform clue: on the new peripheral's transfers,
PRDATAis being sampled whilePREADYis still low. The manager raisesPENABLE, and one cycle later — without checkingPREADY— it latchesPRDATAand moves on. The new slave, however, holdsPREADYlow for one or two cycles because its data path is slower, so at the manager's sampling edgePRDATAis not yet valid. The old register block tiedPREADYhigh, so the manager's premature sample happened to always land on valid data and the bug stayed invisible for months. - Root cause: the manager was written on the myth. Its FSM treats ACCESS as exactly one cycle —
SETUP -> ACCESS -> DONE, unconditional — and it never samplesPREADY. Against a zero-wait slave that fixed timing is accidentally correct; against a wait-inserting slave it completes early, reads the pre-fetch value, and (if the manager also asserts the next SETUP on top of the still-active ACCESS) can wedge the bus. - Correct RTL: make ACCESS conditional on
PREADY— hold until it is sampled high, then complete.Azvya Education Pvt. Ltd.VLSI MentorSnippet// Manager FSM: ACCESS is HELD until PREADY is sampled high. No fixed count. always_ff @(posedge pclk or negedge presetn) begin if (!presetn) state <= IDLE; else case (state) IDLE: if (start) state <= SETUP; SETUP: state <= ACCESS; // one SETUP cycle, always ACCESS: if (pready) state <= DONE; // complete only when READY high // else: stay in ACCESS -> this IS the wait state DONE: state <= IDLE; endcase end // Sample read data on the completing edge only: assign capture_rdata = (state == ACCESS) && pready && !pwrite; - Debug habit: when a driver works on one peripheral and fails on a newly integrated one, do not start in the data path — check whether the manager is sampling
PREADYat all. OverlayPENABLE,PREADY, and the manager's data-capture strobe on one capture. If the capture strobe fires on a cycle wherePREADYis low, you have found a myth-based manager, and the fix is to gate completion (and the read-data sample) onPREADY, not on a fixed cycle count.
8. Verification perspective
Verifying against the myth means proving two things: that the DUT never assumes a one-cycle transfer, and that it tolerates the full range of legal transfer lengths. That is an assertion job plus a coverage job.
- The core safety property: never complete or sample without
PREADY. A manager must not treat a transfer as done — and must not latch read data — on a cycle wherePREADYis low. Write it as aPREADY-gated completion assertion:Azvya Education Pvt. Ltd.VLSI MentorSnippet// A manager must not complete an access until PREADY is sampled high. // If we are in ACCESS (psel && penable) and PREADY is low, we must remain in ACCESS. property p_no_complete_without_pready; @(posedge pclk) disable iff (!presetn) (psel && penable && !pready) |=> (psel && penable); endproperty a_no_complete_without_pready: assert property (p_no_complete_without_pready); // And read data must only be captured on the completing (PREADY-high) ACCESS edge. a_rdata_sampled_ready: assert property ( @(posedge pclk) disable iff (!presetn) (capture_rdata && !pwrite) |-> (psel && penable && pready) ); - The floor property: no transfer is ever one cycle. Assert that
PENABLEis always preceded by a SETUP cycle — i.e. the ACCESS phase can never be entered in the same cycle a freshPSELrises — which is the structural guarantee that the minimum is two cycles:(!psel ##1 psel) |-> !penableon the newly-selected cycle. - The coverage side: hit the whole latency dial. A
PREADY-gated assertion proves correctness under waits, but you only trust it if the stimulus actually produces waits. Cover0,1,2, and a "many" bucket of wait states per transfer, and cover back-to-back transfers of different latencies (a zero-wait access abutting a multi-wait one) — the mixed-latency case is where a myth-based manager that "usually works" finally exposes itself. A responder VIP that randomisesPREADYdelay is the standard way to sweep the dial; a responder that only ever tiesPREADYhigh will hide every myth bug, exactly as the buggy silicon did.
The point: one PREADY-gated completion assertion catches the entire class of myth bugs, but it is only as good as stimulus that inserts real, varied wait states — so the verification plan is "gate completion on PREADY, then randomise the wait count so the gate actually gets tested."
9. Interview discussion
"Is an APB transfer single-cycle?" is a deceptively good screening question, because the confident-but-wrong "yes, APB is single-cycle, it's the simple one" answer instantly separates spec-readers from people who have watched real APB waveforms.
The strong answer is two sentences and a counterexample. First, state the correction from the spec: APB (IHI 0024C §3.1) defines every transfer as a two-phase SETUP-then-ACCESS sequence, so the minimum is two clock cycles, and there is no legal one-cycle transfer because the SETUP phase is unconditional. Second, give the extension: the ACCESS phase is held while PREADY is low, so a transfer is 2 + N cycles for N wait states, bounded only by the subordinate — a slow peripheral behind a clock divider or a CDC bridge routinely inserts waits. Then land the counterexample: "a read from a two-wait-state slave is four cycles — SETUP, ACCESS, wait, complete — and the same read is two cycles against a zero-wait slave, so the length is a slave choice, not a fixed constant." If asked where the myth comes from, name the confusion: "unpipelined" governs concurrency, not duration — people hear "simple, one transfer at a time" and wrongly compress it to "one cycle per transfer." Closing with "so a correct manager samples PREADY at every ACCESS edge rather than counting cycles, and that's the bug I look for first when a driver works on one peripheral and fails on a new one" signals you have debugged this in silicon, not just read the diagram.
10. Practice
- Falsify the claim. In two sentences, refute "an APB transfer is one cycle" using the spec's two-phase definition, and state the exact minimum cycle count with a one-line justification.
- Count the cycles. A subordinate inserts three wait states on a read. Write the transfer length as a formula in terms of the wait count
N, evaluate it for this case, and label each cycle by phase (SETUP / ACCESS / wait / complete). - Trace the myth to a bug. A manager FSM is
SETUP -> ACCESS -> DONEwith an unconditionalACCESS -> DONEedge. Explain precisely what goes wrong when this manager talks to a two-wait-state slave, and name which cycle the read data is (wrongly) sampled. - Fix the manager. Rewrite the FSM edge from practice 3 so ACCESS is held until
PREADYis sampled high, and write the one condition under which read data may be captured. - Explain the propagation. Explain why the phrase "single-cycle transfer" is a cause of the myth even though the transfer it names is actually two cycles, and state the wait-state count that phrase really refers to.
11. Q&A
12. Key takeaways
- An APB transfer is never one clock cycle. It is a mandatory two-phase sequence — SETUP then ACCESS (IHI 0024C §3.1) — so the minimum is two cycles, and the SETUP phase is unconditional, meaning no legal transfer completes in one cycle.
- Transfer length is
2 + N, bounded only by the slave. The ACCESS phase is held whilePREADYis low; each held cycle is one wait state. A zero-wait slave gives the two-cycle floor; a slow peripheral gives2 + N. The count is a slave choice, not a protocol constant. - The myth comes from three confusions: treating "simple / unpipelined" as "single-cycle" (unpipelined governs concurrency, not duration), only ever seeing zero-wait slaves, and collapsing the two phases into one mental cell. The loose phrase "single-cycle transfer" (which really means zero wait states) propagates it.
- The myth ships real bugs: a manager that never samples
PREADYand completes on a fixed count, and a fixed one-cycle slave model that breaks against any real slow peripheral (flash, CDC bridge, clock-divided block). The correct manager samplesPREADYat every ACCESS edge and captures read data only on the completing edge. - Verify it with one
PREADY-gated completion assertion plus wait-state coverage. Prove the manager cannot complete or sample read data whilePREADYis low, then randomise the wait count (0, 1, 2, many, and mixed-latency back-to-back) so the gate is actually exercised — a responder that only tiesPREADYhigh hides every myth bug.