APB Series — APB-08: Operating States — VLSI Trainers
APB Series · APB-08

Operating States

The three-state APB FSM — IDLE, SETUP, and ACCESS — the exact conditions for every transition, what signals must hold in each state, back-to-back transfers without returning to IDLE, and a complete annotated state diagram from the spec.

📋 The Three States

The APB interface operates as a simple three-state finite state machine. The state machine runs entirely in the Requester (APB bridge) — the Completer (peripheral) does not have a state machine; it only responds to the signals driven by the Requester.

IDLE
PSELx = 0
PENABLE = 0
Default state
No transfer active
SETUP
PSELx = 1
PENABLE = 0
Always 1 cycle
Address & data presented
ACCESS
PSELx = 1
PENABLE = 1
1+ cycles
Completes on PREADY=1

The state machine starts in IDLE after reset. It enters SETUP when the bridge needs to start a transfer, spends exactly one clock cycle there, then moves unconditionally to ACCESS. It remains in ACCESS until the Completer asserts PREADY, at which point it either returns to IDLE (no further transfers) or jumps directly to SETUP (back-to-back transfer to the same or a different peripheral).

📋 State Diagram

APB State Diagram — From ARM IHI 0024E IDLE PSELx = 0 SETUP PSELx = 1 PENABLE = 0 ACCESS PSELx = 1 PENABLE = 1 Transfer required Always (next clock) PREADY=1 & no transfer PREADY=1 & transfer PREADY=0 No transfer Transition legend IDLE→SETUP or ACCESS→SETUP SETUP→ACCESS (always) ACCESS→IDLE Wait state (stay in ACCESS)
Figure 1 — APB state diagram as defined in ARM IHI 0024E Chapter 4. SETUP always lasts exactly one clock cycle — there is no condition on the SETUP→ACCESS transition. The ACCESS state loops on itself when PREADY=0 (wait states). On PREADY=1, it exits to either IDLE or directly to SETUP for the next transfer.

📋 IDLE State

IDLE is the default state of the APB interface. The system enters IDLE after reset and returns to IDLE between transfers (unless back-to-back transfers occur — see ACCESS). In IDLE:

The Requester exits IDLE when it has a transfer to perform. It asserts PSELx for the target Completer and presents PADDR, PWRITE, PWDATA (if write) and control signals. On the next rising clock edge the system is in SETUP.

Idle cycles are free — no handshake required. The APB interface can stay in IDLE indefinitely between transfers. There is no timeout, no keep-alive, no “bus idle” signal. The bridge simply keeps PSELx deasserted until it has work to do.

📋 SETUP State

The SETUP state is entered when the bridge asserts PSELx to start a transfer. In SETUP:

SETUP always lasts exactly one clock cycle — no exceptions. There is no condition that can keep the interface in SETUP. The spec is unambiguous: “The interface only remains in the SETUP state for one clock cycle and always moves to the ACCESS state on the next rising edge of the clock.” This is one of the most important rules in the entire APB specification. A bridge that holds PENABLE deasserted for more than one cycle after asserting PSELx is non-compliant.

The Completer uses the SETUP cycle to decode the address and prepare for the transfer. It should use this cycle to determine which register is being accessed and whether the access is permitted. By the time ACCESS begins (PENABLE asserted), the Completer should be ready to complete the transfer — if it is not, it deasserts PREADY to add wait states.

📋 ACCESS State

The ACCESS state is entered unconditionally from SETUP on the clock cycle after PSELx was asserted. In ACCESS:

The Completer controls exit from ACCESS via PREADY:

On exit from ACCESS (PREADY=1), the bridge chooses one of two paths:

The ACCESS→SETUP path eliminates one idle cycle between back-to-back transfers. This is significant for performance when writing a sequence of registers to the same peripheral (e.g. initialising a DMA controller or programming a crypto engine). Without it, every transfer pair would have an idle cycle overhead.

📋 All Transitions Explained

FromToConditionWhat happens
IDLESETUP Transfer required Bridge asserts PSELx for target Completer. Presents PADDR, PWRITE, PWDATA, PPROT, PSTRB. PENABLE stays LOW.
IDLEIDLE No transfer pending Interface stays idle. PSELx and PENABLE remain deasserted. No signal changes required.
SETUPACCESS Always — next rising edge Bridge asserts PENABLE. All other signals hold their values from SETUP. The Completer may now assert PREADY to complete in this cycle, or deassert PREADY to insert wait states.
ACCESSACCESS PREADY = 0 Wait state. All bus signals (PADDR, PWRITE, PWDATA, PSELx, PENABLE, PPROT, PSTRB, PAUSER, PWUSER) must remain completely unchanged.
ACCESSIDLE PREADY = 1 AND no transfer pending Transfer completes. Bridge deasserts PSELx and PENABLE. Interface returns to default idle state.
ACCESSSETUP PREADY = 1 AND next transfer pending Transfer completes AND next transfer begins simultaneously. Bridge deasserts PENABLE, updates address/control signals for next transfer, keeps or switches PSELx. No idle cycle between the two transfers.

Full Timing — All Paths

This timing diagram shows all three state paths in one waveform: a write with wait state → completion → back-to-back read → idle.

T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 IDLE SETUP 1 ACCESS 1 (wait) ACCESS 1 done IDLE SETUP 2 ACCESS 2 done IDLE PCLK PADDR PWRITE PSELx PENABLE PWDATA PREADY Addr 1 (write) Addr 2 (read) HIGH=Write LOW=Read Data 1 PREADY=0 wait
Figure 2 — Complete APB timing showing IDLE→SETUP 1→ACCESS 1 (with wait state)→IDLE→SETUP 2→ACCESS 2→IDLE. Two separate transfers with an idle cycle between them. Note PENABLE deasserts to zero between the two transfers (back at IDLE, then new SETUP), and the wait state cycle at T3 where PREADY=0 keeps the interface in ACCESS.

Back-to-back (ACCESS→SETUP direct)

T0 T1 T2 T3 T4 T5 IDLE SETUP 1 ACCESS 1 SETUP 2 ACCESS 2 IDLE PCLK PADDR PSELx PENABLE PREADY State → Addr 1 Addr 2 IDLE SETUP ACCESS SETUP ACCESS IDLE ↑ PENABLE=0 new Setup
Figure 3 — Back-to-back transfers (ACCESS→SETUP direct path). At T2, PREADY=1 completes transfer 1 AND T3 is already the SETUP phase of transfer 2. PSELx stays HIGH throughout. PENABLE deasserts for exactly one cycle (T3) then reasserts for ACCESS 2. PADDR changes at T3 to the new address. No IDLE cycle between the two transfers.

📋 Signals Per State

SignalIDLESETUPACCESS (wait)ACCESS (complete)
PSELx0111 (then 0)
PENABLE0011 (then 0)
PADDRDon’t careValid & stableMust not changeStable (then can change)
PWRITEDon’t careValid & stableMust not changeStable (then can change)
PWDATADon’t careValid (write only)Must not changeStable (then can change)
PPROTDon’t careValid & stableMust not changeStable (then can change)
PSTRBDon’t careValid & stableMust not changeStable (then can change)
PREADYDon’t careDon’t care0 (Completer not ready)1 (Completer ready)
PRDATADon’t careDon’t careUndefined (Completer preparing)Valid (Completer drives)
PSLVERRRec: 0Rec: 0Rec: 0Valid (error indicator)

📋 RTL Implementation

The APB state machine in a bridge is straightforward. Here is a synthesisable SystemVerilog implementation:

typedef enum logic [1:0] {IDLE=2'b00, SETUP=2'b01, ACCESS=2'b10} apb_state_t;
apb_state_t state;

always_ff @(posedge PCLK or negedge PRESETn) begin
  if (!PRESETn) begin
    state <= IDLE;
    PSELx <= 1'b0;
    PENABLE <= 1'b0;
  end else begin
    case (state)
      IDLE: begin
        if (transfer_req) begin
          state <= SETUP;
          PSELx <= 1'b1;
          PENABLE <= 1'b0;
          PADDR <= req_addr;
          PWRITE <= req_write;
          PWDATA <= req_wdata;
        end
      end
      SETUP: begin
        state <= ACCESS; // always
        PENABLE <= 1'b1;
      end
      ACCESS: begin
        if (PREADY) begin
          PENABLE <= 1'b0;
          if (transfer_req) begin
            state <= SETUP; // back-to-back
            PADDR <= req_addr;
            PWRITE <= req_write;
            PWDATA <= req_wdata;
          end else begin
            state <= IDLE;
            PSELx <= 1'b0;
          end
        end // else stay in ACCESS (wait state)
      end
    endcase
  end
end

The SETUP→ACCESS transition has no condition — state <= ACCESS is unconditional in the SETUP case. This directly encodes the spec rule that SETUP always lasts exactly one cycle.

📋 Quick Reference

ItemRule
Number of states3 — IDLE, SETUP, ACCESS
State machine ownerRequester (APB bridge) — the Completer has no state machine
IDLE: PSELx0 — no Completer selected
IDLE: PENABLE0
SETUP: PSELx1
SETUP: PENABLE0 — distinguishes Setup from Access
SETUP durationAlways exactly 1 clock cycle — no exceptions, no conditions
SETUP→ACCESSUnconditional — always on the next rising clock edge after SETUP
ACCESS: PSELx1
ACCESS: PENABLE1
ACCESS wait state conditionPREADY=0 → stay in ACCESS, all bus signals must hold
ACCESS completion conditionPREADY=1 → transfer completes on this rising edge
ACCESS→IDLE conditionPREADY=1 AND no next transfer pending
ACCESS→SETUP conditionPREADY=1 AND next transfer pending (back-to-back)
Back-to-back benefitEliminates one idle cycle between transfers to the same or different peripheral
PREADY in SETUPDon’t care — Completer may drive anything, Requester ignores it
Signals stable during waitPADDR, PWRITE, PWDATA, PSELx, PENABLE, PPROT, PSTRB, PAUSER, PWUSER
PRDATA valid whenOnly at ACCESS completion (PSEL+PENABLE+PREADY=1, PWRITE=0)
PSLVERR valid whenOnly at ACCESS completion (PSEL+PENABLE+PREADY=1)
Scroll to Top