APB Operating States

The APB protocol follows a strict, simple state machine consisting of three states: IDLE, SETUP, and ACCESS.

State Diagram

The state machine controls the PSEL and PENABLE signals.

State      | PSEL | PENABLE
-----------------------------IDLE       |  0   |   0     // No transfer
SETUP      |  1   |   0     // First Cycle (Address Phase)
ACCESS     |  1   |   1     // Second Cycle (Data Phase)
Transitions:
1. IDLE   -> SETUP  : When transfer Required.
2. SETUP  -> ACCESS : Always happens on next clock edge.
3. ACCESS -> ACCESS : If PREADY == 0 (Wait State).
4. ACCESS -> IDLE   : If PREADY == 1 and No More Transfers.
5. ACCESS -> SETUP  : If PREADY == 1 and Next Transfer Pending.

Detailed Description

1. IDLE

The default state. No transfer is occurring. PSEL and PENABLE are both LOW.

2. SETUP

The Master drives the Address (PADDR) and Data (PWDATA, if write) onto the bus. It asserts PSEL but keeps PENABLE LOW. This phase lasts for exactly ONE clock cycle.

3. ACCESS

The Master asserts PENABLE. PSEL remains HIGH. The signals must remain stable. The Slave must respond by driving PREADY.
- If PREADY=0, the master stays in ACCESS.
- If PREADY=1, the transfer completes at the end of this cycle.

APB Master FSM in SystemVerilog

module apb_master_fsm (
    input logic pclk, presetn,
    input logic transfer_req,
    input logic pready,
    output logic psel, penable,
    output logic [1:0] state_out
);
    typedef enum logic [1:0] {
        IDLE   = 2'b00,
        SETUP  = 2'b01,
        ACCESS = 2'b10
    } state_t;
    state_t state, next_state;
    // Sequential Logic
    always_ff @(posedge pclk or negedge presetn) begin
        if (!presetn) state <= IDLE;
        else          state <= next_state;
    end
    // Combinational Next State Logic
    always_comb begin
        next_state = state;
        case (state)
            IDLE: begin
                if (transfer_req) next_state = SETUP;
            end
            SETUP: begin
                // Unconditionally go to ACCESS
                next_state = ACCESS;
            end
            ACCESS: begin
                if (pready) begin
                    if (transfer_req) next_state = SETUP;  // Back-to-back
                    else              next_state = IDLE;
                end
                // Else stay in ACCESS (Wait State)
            end
        endcase
    end
    // Output Logic
    assign psel    = (state == SETUP) || (state == ACCESS);
    assign penable = (state == ACCESS);
    assign state_out = state;
endmodule

Common Interview Questions

Q: Why do we need the SETUP state? Why not go IDLE->ACCESS?
The SETUP state ensures glitch-free operation and allows combinational decoding of the address to select the slave (generating PSEL) before the Enable signal asserts. This relaxes timing constraints for the Slave's address decoding logic.
Q: Can signals change during the ACCESS state?
No! Once in the ACCESS state, PADDR, PWRITE, PWDATA (for writes), and PSEL must remain stable until the transfer completes (PREADY=1). Changing them violates the protocol.