Skip to content

AMBA APB · Module 14

Why APB Is Not Pipelined

The architectural reason APB cannot overlap transfers — each transfer's SETUP and ACCESS belong to one transfer and the next cannot begin until the current completes. Pipelining would require the buffering and address/data decoupling that contradict APB's whole purpose as a dead-simple, low-power control bus.

You have used one fact in every cost argument of this module — APB transfers don't overlap, so each pays its full 2 + N with no burst bonus. Chapters 14.1 and 14.2 consumed that fact to derive latency and throughput. This chapter asks the deeper question: why? Why can a bus like AHB overlap one transfer's address phase with the previous transfer's data phase, while APB structurally cannot? The single idea to carry: APB is unpipelined by design, not by accident — overlapping transfers would require the buffering, address/data-phase decoupling, and per-slave handshake complexity that contradict APB's entire reason for existing (a dead-simple, low-power, low-gate control bus). The lack of a pipeline is a feature you bought in exchange for trivial slaves and tiny logic — accepted deliberately, not a flaw to be fixed.

1. Problem statement

The problem is explaining the architectural cause of APB's serial behaviour — not merely restating that transfers don't overlap, but showing why the protocol structurally forbids overlap, so an engineer can defend the design choice rather than treat it as a missing feature.

Performance chapters lean on "APB can't pipeline" as a given. But "can't" has a precise structural meaning that you must be able to articulate:

  • Each transfer owns the bus for both its phases. An APB transfer is two-phase: SETUP (PSEL high, PENABLE low) then ACCESS (PENABLE high until PREADY). The manager drives one address/control set, and the selected slave is committed for the whole two-phase transfer. There is no second address/control set in flight, so there is nothing for a "next" transfer's SETUP to occupy while the current ACCESS runs.
  • The next SETUP cannot begin until the current ACCESS completes. The manager's state machine moves IDLE → SETUP → ACCESS → (back to SETUP or IDLE). It only re-enters SETUP after ACCESS finishes. That serial state progression is the protocol — there is no path in which SETUP of transfer N+1 coexists with ACCESS of transfer N.
  • Pipelining would require machinery APB deliberately omits. Overlapping address and data phases (as AHB does) needs an address-to-data pipeline register, decoupled address/data handshakes, and a slave that can accept a new address while still returning old data. APB has none of these — and adding them would make it not-APB.

So the job is to explain why the structure serialises transfers, why that structure was chosen, and why "no pipeline" is the right answer for a control bus — the architectural reason behind the cost facts the rest of the module uses.

2. Why previous knowledge is insufficient

You already used the no-pipeline fact. In 14.1, latency anatomy you learned a transfer costs exactly 2 + N with "no overlap term"; in 14.2, throughput you learned back-to-back transfers don't amortise SETUP because APB can't pipeline. What you have not done is explain the cause:

  • You learned the consequence, not the mechanism. 14.1 stated "there is no overlap term" and 14.2 stated "no burst bonus" — both asserted the serialisation to do the math. This chapter supplies the why: the manager drives one address/control set at a time and the slave is held for the whole two-phase transfer, so there is structurally nothing to overlap. The cost facts become consequences of a design choice you can now justify.
  • You have seen a pipeline elsewhere but not contrasted it. AHB's pipelined operation overlaps phases by design; AHB's two-phase pipeline decouples address and data with a pipeline register. Knowing AHB does overlap is not the same as understanding why APB cannot — the contrast is the lesson, and it reveals exactly which machinery APB omits to stay simple.
  • You know APB exists to be simple, but not what simplicity costs structurally. Why APB exists and the APB2 baseline frame APB as the low-power, low-gate control bus. This chapter shows that the no-pipeline property is a direct, deliberate consequence of that goal: pipelining is precisely the complexity APB was built to avoid.

So the model to add is causal: serialisation is not a limitation bolted on after the fact — it falls directly out of the one-transfer-at-a-time structure APB chose so its slaves could be trivial.

3. Mental model

The model: an APB bus is a single-lane checkout with one cashier and one customer at a time. A customer (transfer) steps up (SETUP), is served (ACCESS), and only when they finish and leave does the next customer step up. There is no conveyor belt staging the next customer's items while the current one pays — one lane, one customer, start-to-finish. AHB, by contrast, is a checkout with a conveyor: the next customer's items are already being scanned (address phase) while the current customer pays (data phase). The conveyor is the pipeline register; APB simply doesn't have one.

Three refinements make it precise:

  • One address/control set, held for the whole transfer. The manager drives PADDR, PWRITE, PWDATA, PSEL for this transfer, and holds them stable through SETUP and ACCESS until PREADY. There is no second set of address/control wires staged behind it — so there is no "next transfer's address" that could be presented during the current ACCESS.
  • The slave is selected for the entire two-phase transfer. PSEL to the addressed slave stays high across SETUP and ACCESS. A pipeline would need the slave to accept a new address while still completing the old data — APB's single PSEL/single-address model gives it no way to be doing two things at once.
  • The state machine progresses serially, by definition. SETUP → ACCESS → (SETUP again only after ACCESS). There is no protocol state where SETUP(N+1) and ACCESS(N) coexist. The serialisation is the protocol, not a property layered on top — which is exactly why the cost is a clean 2 + N per transfer with nothing to amortise.
A side-by-side diagram: on top, AHB transfers overlap (transfer 2's address phase shares a cycle with transfer 1's data phase, highlighted as the pipeline overlap); on the bottom, APB transfers are strictly serial — transfer 2's SETUP only begins after transfer 1's ACCESS completes, with a red serial boundary and no overlap.
Figure 1 — pipelined (AHB) versus unpipelined (APB), side by side. Top (AHB, amber): the address phase of transfer 2 overlaps the data phase of transfer 1 — the two share a clock because a built-in pipeline register decouples address and data phases, which is the burst bonus. Bottom (APB, blue/green): transfer 1 runs its full SETUP then ACCESS, and only after ACCESS completes does transfer 2 begin its SETUP — a strict serial boundary, no overlap, because the manager drives one address/control set at a time and the slave is held for the whole two-phase transfer. The figure labels AHB's overlap region and APB's serial boundary to show the structural difference: APB omits the pipeline register, so transfers serialise by design.

4. Real SoC implementation

In real RTL, the serialisation is not enforced by extra logic — it falls out of the manager's two-phase state machine. The FSM simply has no transition that starts a new SETUP while an ACCESS is unfinished. The block below shows the structural cause, with comments contrasting what a pipeline would demand.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// APB manager FSM: structurally one transfer at a time.
// Note what is ABSENT — there is no address/data buffer and no path
// that starts SETUP(N+1) while ACCESS(N) is still in flight.
typedef enum logic [1:0] { IDLE, SETUP, ACCESS } apb_state_t;
apb_state_t state, next;
 
always_comb begin
  next = state;
  unique case (state)
    IDLE:   if (req)        next = SETUP;   // a new transfer may start
    SETUP:                  next = ACCESS;  // SETUP is always exactly one cycle
    ACCESS: if (pready) begin
              // completion. ONLY here can the next transfer begin its SETUP.
              next = req ? SETUP : IDLE;    // back-to-back => SETUP again, NOT overlap
            end
            // if !pready: stay in ACCESS (wait state). The next transfer
            // still cannot start — the bus is owned until PREADY.
  endcase
end
 
always_ff @(posedge pclk or negedge presetn) begin
  if (!presetn) state <= IDLE;
  else          state <= next;
end
 
// One address/control set, held stable for the WHOLE transfer:
assign psel    = (state == SETUP) || (state == ACCESS);
assign penable = (state == ACCESS);
// paddr/pwrite/pwdata are loaded at SETUP and held until PREADY — there is
// no second (staged) address register behind them.
 
// ---------------------------------------------------------------------------
// What PIPELINING would have required (and why it would no longer be APB):
//   - an address-to-data PIPELINE REGISTER, so the manager could present
//     transfer N+1's address while transfer N's data is still returning;
//   - DECOUPLED address-phase and data-phase handshakes (separate "address
//     accepted" vs "data ready"), instead of one PREADY for the whole transfer;
//   - a SLAVE able to latch a new address while still completing the old read,
//     i.e. per-slave buffering and outstanding-transfer tracking.
// All of that is exactly the gate count, power, and slave complexity APB
// was created to avoid. Omitting it IS the design — see /protocols/ahb/two-phase-pipeline.
// ---------------------------------------------------------------------------

Two facts make this the right way to see the cause. First, the serialisation is structural, not policed — there is no "wait for previous transfer" guard anywhere; the FSM simply re-enters SETUP only out of a completed ACCESS, so overlap is unrepresentable, not merely disallowed. Second, the absent machinery is the whole point: a pipeline would need the address/data register, decoupled handshakes, and a smarter slave listed in the comment — the very complexity that would inflate gate count and power and make slaves hard to write, which is precisely what APB exists to avoid (see why APB exists). The implementation doesn't prevent pipelining; it simply never built the mechanism that would enable it.

5. Engineering tradeoffs

Pipelining is a genuine trade, not a free win. AHB buys overlap-driven throughput by paying for buffering, decoupled handshakes, and slave complexity; APB declines the purchase to keep slaves trivial and logic tiny.

DimensionPipelined (AHB)Unpipelined (APB)
Address/data overlapYes — address phase of T(N+1) overlaps data phase of T(N)None — SETUP(N+1) only after ACCESS(N) completes
Buffering requiredAddress-to-data pipeline register; outstanding-transfer stateNone — one address/control set, held for the whole transfer
Slave complexityHigher — must accept a new address while completing old dataTrivial — select, respond, drive PREADY; one thing at a time
HandshakeDecoupled address-accept vs data-readySingle PREADY for the whole two-phase transfer
Gate cost / powerHigher — buffers, decode, control for overlapMinimal — the explicit goal of APB
ThroughputUp to ~1 transfer/cycle in a burst (overlap amortises)1 / (2 + N) per cycle, no burst bonus
Right forHigh-bandwidth memory/DMA trafficLow-bandwidth control/configuration registers

The throughline: pipelining and simplicity are the two ends of one trade. AHB spends gates, power, and slave complexity to win overlap; APB spends throughput to win a dead-simple slave and a tiny footprint. For a control bus — sparse register writes, not bandwidth-bound streaming — the APB end of the trade is the correct engineering choice. "No pipeline" is not a weakness here; it is the deliberately chosen side of a deliberate trade.

6. Common RTL mistakes

7. Debugging scenario

The signature "bug" here is not a logic error — it is an architectural costing mistake: an engineer who assumed APB would pipeline like AHB, budgeted a peripheral region for pipelined throughput, and then found real traffic running at half the assumed rate because APB serialises.

  • Observed symptom: a peripheral-configuration region was budgeted at ~5 cycles for a burst of four back-to-back register writes (assuming ~1 transfer/cycle), but the subsystem measures ~8 cycles for the same burst — roughly double — and a boot-time configuration sequence misses its timing budget. Every transfer is functionally correct; the aggregate rate is wrong.
  • Waveform clue: decomposing the trace shows no overlap between consecutive transfers — each transfer shows a full SETUP cycle (PSEL high, PENABLE low) followed by an ACCESS cycle (PENABLE high, PREADY high), and the next transfer's SETUP begins only on the cycle after the previous PREADY. There is never a cycle where one transfer's PENABLE-high ACCESS coincides with another transfer's PENABLE-low SETUP. The expected pipelined overlap simply isn't there.
  • Root cause: the architect's throughput model assumed an AHB-style pipeline (address of T(N+1) overlapping data of T(N)). APB has no such pipeline — the manager drives one address/control set at a time and the slave is held for the whole two-phase transfer, so each transfer costs its full 2 + N and the burst rate is 1 / (2 + N) with no overlap. The budget used the wrong structural model, not the wrong RTL.
  • Correct RTL: there is nothing to fix in the RTL — the serial behaviour is correct APB. The fix is in the model and the placement: re-cost the region with the serial 2 + N-per-transfer math (the burst is 4 × 2 = 8 cycles for zero-wait, not 5), and if the region genuinely needs higher throughput, relocate the bursty traffic onto a pipelined bus (AHB/AXI) rather than expecting APB to overlap. Where it stays on APB, accept the serial rate as the design point.
  • Verification assertion: assert that no overlap is even possible — the next SETUP never asserts while the previous ACCESS is incomplete: assert property (@(posedge pclk) disable iff(!presetn) (psel && penable && !pready) |-> ##1 (penable || !psel)); — i.e. while in an unfinished ACCESS (PENABLE high, PREADY low), the very next cycle is still that same ACCESS (still PENABLE high) or the transfer ends (PSEL deasserted), never a fresh PSEL-high/PENABLE-low SETUP of a new transfer overlapping it. Pair it with a performance coverpoint that the back-to-back burst rate matches 1 / (2 + N).
  • Debug habit: when an APB region "runs slower than budgeted" with every transfer correct, don't hunt for a logic bug — check the throughput model. APB never pipelines, so any budget that assumed overlap is wrong by construction. Confirm the absence of overlap on the waveform, re-cost with serial 2 + N, and decide between accepting the serial rate or moving the traffic to a pipelined bus.
A two-case timeline: the top red case shows four APB transfers wrongly assumed to overlap into about five cycles; the bottom case shows the real serial APB — four transfers, each a SETUP plus ACCESS, taking eight cycles with red serial boundaries and no overlap, double the assumed time.
Figure 2 — assumed pipelined throughput versus actual serial APB, for four back-to-back transfers. Top (assumed, red): the architect modelled APB as overlapping each transfer's address with the previous transfer's data, fitting four transfers into roughly five cycles at about one transfer per cycle — an overlap that never happens on APB. Bottom (actual, blue/green): APB serialises, so each transfer pays its full SETUP + ACCESS (two cycles for zero-wait), and four transfers take eight cycles — exactly double the assumed five, about half the assumed throughput. The figure marks the assumed-overlap regions that don't occur and the real serial boundaries between transfers, showing the region was budgeted for twice its real rate. The fix is to re-cost with the serial 2 + N model or move bursty traffic to a pipelined bus.

8. Verification perspective

Because the no-pipeline property is structural, verification's job is to prove the serialisation holds — that no two transfers ever overlap, that each SETUP follows the previous transfer's completion, and that the serial rate is what the system budgeted against.

  • Assert no transfer overlap, ever. The core property is that a new transfer's SETUP (PSEL high, PENABLE low for a fresh address) never coexists with another transfer's in-flight ACCESS. Equivalently, while PENABLE is high and PREADY low (unfinished ACCESS), the next cycle is still that ACCESS or the transfer ends — never a new transfer's first cycle. This proves the bus carries exactly one transfer at a time, which is the whole no-pipeline claim.
  • Assert SETUP follows the previous completion. Check that every entry into SETUP for a back-to-back transfer is preceded by a completed ACCESS (PENABLE && PREADY) of the prior transfer — i.e. the FSM only re-enters SETUP out of completion. This catches any (illegal) attempt to start a transfer early and confirms the serial state progression directly.
  • Cover that serialisation holds under back-to-back traffic. Functional coverage must include a stream of back-to-back transfers (with and without wait states) and confirm the measured burst rate equals 1 / (2 + N) — no cycle is ever saved by overlap. A suite that only exercises isolated transfers proves nothing about serialisation; the burst case is where a mistaken pipeline assumption would show up, so it must be covered explicitly.

The point: verify that APB carries one transfer at a time (no overlap), that SETUP only follows the prior completion, and that back-to-back streams run at the serial 1 / (2 + N) rate — so the no-pipeline guarantee the whole performance model depends on is proven, not assumed.

9. Interview discussion

"Why isn't APB pipelined?" is a favourite because the weak answer is a tautology — "because it doesn't overlap transfers" — and the strong answer explains the structural cause and the design intent behind it.

State the cause first: APB drives one address/control set at a time and selects the slave for the whole two-phase transfer, so the manager's state machine can only re-enter SETUP after the current ACCESS completes — there is structurally no second transfer in flight to overlap. Then deliver the intent: pipelining (as in AHB) requires an address-to-data pipeline register, decoupled address/data handshakes, and a slave that can accept a new address while completing the old one — exactly the buffering, decoupling, and per-slave complexity APB was built to avoid. So APB is unpipelined by design: it trades overlap for a trivial slave, tiny gate count, and low power, which is the right trade for a control bus that handles sparse register accesses, not bandwidth-bound streaming. The senior flourish ties it to cost: "because there's no overlap, each transfer is a clean 2 + N and the back-to-back rate is just its reciprocal with no burst bonus — so if a region needs real throughput you put it on AHB or AXI, not APB." Framing it as a deliberate, defensible trade — not a limitation — is what signals you understand why the bus exists, not just what it does.

10. Practice

  1. Explain the cause. In two or three sentences, state the structural reason APB cannot overlap transfers — without using the word "pipeline" as the explanation itself.
  2. Name the missing machinery. List the three things a bus needs to pipeline transfers that APB deliberately omits, and say what each would cost.
  3. Contrast with AHB. Describe exactly what AHB overlaps that APB does not, and which AHB structure (named in prose) makes that overlap possible.
  4. Cost a burst. For four back-to-back zero-wait transfers, give the APB cycle count and the (wrongly) assumed pipelined count, and state the ratio.
  5. Write the assertion. From memory, sketch the SystemVerilog assertion that proves no new transfer's SETUP ever overlaps an in-flight ACCESS.

11. Q&A

12. Key takeaways

  • APB transfers serialise by structure: the manager drives one address/control set at a time and holds the slave for the whole two-phase transfer, so the next SETUP can only begin after the current ACCESS completes. There is structurally nothing to overlap.
  • The serialisation is unrepresentable, not policed. The manager's FSM re-enters SETUP only out of a completed ACCESS — there is no state where SETUP(N+1) and ACCESS(N) coexist, so the cost is a clean 2 + N per transfer with no overlap term.
  • Pipelining would require machinery APB deliberately omits: an address-to-data pipeline register, decoupled address/data handshakes, and a slave that latches a new address while completing the old one — exactly the buffering, decoupling, and complexity APB exists to avoid.
  • No pipeline is a feature, not a flaw. APB trades overlap-driven throughput for a trivial slave, minimal gates, and low power — the correct trade for a control bus, and the deliberate other end of the same trade AHB makes for bandwidth.
  • The contrast is AHB: AHB's two-phase pipeline decouples address and data so the next transfer's address overlaps the current data; APB has no such register, so it can't — and "add a pipeline to APB" just means "use AHB."
  • Verify the serialisation holds: assert no transfer ever overlaps an in-flight ACCESS, that SETUP only follows the prior completion, and cover that back-to-back streams run at the serial 1 / (2 + N) rate the whole performance model assumes.