The myth is that PENABLE may assert on the very first cycle of a transfer to save a clock — but the AMBA APB protocol mandates a SETUP cycle (PSEL high, PENABLE low) before the ACCESS cycle where PENABLE finally rises, so asserting PENABLE immediately deletes the decode window and violates the spec, not accelerates it. The belief is seductive: a transfer is two cycles, one feels wasteful, and if you could raise PENABLE the moment PSEL goes high you would have a one-cycle access. The reality is that the first-cycle-low PENABLE is not overhead — it is the protocol. APB is defined as a two-phase handshake precisely so a subordinate gets one clean, stable cycle to decode the address and direction before the transfer is allowed to commit. Assert PENABLE on cycle one and you have not built a faster APB; you have built a bus that no compliant slave decodes correctly and no protocol checker will pass.
1. Problem statement
The problem is that PENABLE low in the first cycle is a mandatory part of the transfer, not a spare cycle you may reclaim — and the belief that you can assert it immediately produces a bus that looks almost right and is actually illegal.
Every APB transfer has two phases. In the SETUP phase (the first cycle) the manager drives PSEL high with PENABLE low, and presents PADDR, PWRITE, and — for writes — PWDATA. In the ACCESS phase (the second cycle onward) the manager raises PENABLE, and the transfer is now permitted to complete when the subordinate returns PREADY. The one cycle where PSEL is high and PENABLE is low is the SETUP phase, and it is where a subordinate is expected to decode the access: look at PADDR to pick the target register, look at PWRITE to choose read versus write. PENABLE rising is the signal that says "the decode window is over; you may now act."
The myth compresses that to one cycle: assert PSEL and PENABLE together on the first cycle and complete in one clock. What breaks is not throughput — it is correctness. There is now no cycle in which the subordinate sees PSEL high and PENABLE low, so there is no defined moment to decode. Worse, on the single cycle you offer, PADDR and PWRITE may still be settling — the SETUP cycle exists partly to give those signals a full cycle to be stable before the access commits. A subordinate that follows the spec waits for PENABLE to rise before committing; if PENABLE is already high on cycle one it may commit against an address that is still changing. The engineering problem of this chapter is to show why the first-cycle-low PENABLE is load-bearing, what specific failures the "assert immediately" shortcut causes, and how to generate and check PENABLE so the shortcut is structurally impossible.
2. Why previous knowledge is insufficient
You already know what PENABLE is and how its legal shape is generated — but knowing the correct behaviour is not the same as being inoculated against the specific wrong mental model that produces this bug.
- The enable-strobe chapter taught that
PENABLEmarks the access phase and is low in setup, high in access. That is the rule. It does not confront the tempting misreading — "if the access phase is what matters, why not start there?" — nor does it show what silicon does when you skip SETUP. Knowing the rule and understanding why breaking it fails are different depths. - The behaviour deep-dive proved that
PENABLE = (state == ACCESS)makes the legal shape structural, and even listed "PENABLEhigh in the setup cycle is illegal" as a misconception. But it treated that as one line in a catalog of shape rules. This chapter takes that single misconception and makes it the whole subject: where the belief comes from, the exact decode and stability failures it causes, and the interview framing — because it is the single most common APB protocol violation a junior designer or a hand-written BFM commits. - Why APB has two phases argued the rationale for the two-cycle structure. This chapter is the inverse argument: it shows, concretely, what you lose the instant you collapse those two phases into one by asserting
PENABLEimmediately. The rationale tells you why the cycle exists; this tells you what its absence breaks on a real bus.
The gap is this: prior chapters taught the correct shape and its rationale in the abstract. None of them stood at the exact fork where a designer, wanting a one-cycle transfer, reaches for the "assert PENABLE on cycle one" shortcut — and showed that the fork leads to a protocol violation, an unstable decode, and a wall of monitor failures. Closing that specific misconception is this chapter; carrying the resulting discipline into the full transition rulebook is legal and illegal state transitions.
3. Mental model
The model: the SETUP cycle is a mandatory decode window, and PENABLE is the door that opens only after that window has passed — assert it immediately and the subordinate never gets to look before the door is open.
Picture a secure counter with a two-step protocol. Step one: you slide your form across (that is PSEL high, PADDR/PWRITE presented) and the clerk reads it — checks which account, whether it is a deposit or a withdrawal. During this step the shutter is down (PENABLE low); nothing has committed. Step two: the clerk raises the shutter (PENABLE high) and executes the transaction against the account they just decoded. The shutter-down cycle is not a delay the clerk imposes to be slow — it is the only cycle in which the form is read. Raise the shutter the instant the form arrives, and the clerk must both read and execute in the same motion, against a form whose ink may still be wet: they may act on the wrong account, or on a form that changed under their hand.
That maps exactly onto the bus:
- SETUP (
PSEL=1,PENABLE=0) is the read-the-form cycle. The subordinate decodesPADDRandPWRITE;PADDR/PWRITEare given a full cycle to be stable; nothing commits. This is the cycle the myth deletes. - ACCESS (
PENABLE=1) is the execute cycle.PENABLErising is the explicit "decode is done, act now" strobe. A spec-following subordinate commits here, not before — which is exactly why it needs a prior cycle wherePENABLEwas low. PENABLEimmediate = no read cycle at all. There is no cycle withPSELhigh andPENABLElow, so there is no defined decode window and no guaranteed-stable address at the commit point. The transfer is not faster; it is undefined.
Two refinements sharpen it. First, the SETUP cycle buys stability, not just decode time: the AMBA APB specification (IHI 0024C) §3.1 defines the access phase as entered by PENABLE on the cycle after PSEL asserts, and requires the address and control signals to remain stable through it — a guarantee you forfeit if PENABLE is high from cycle one. Second, the rule is structural in a correct manager: because PENABLE is state == ACCESS and ACCESS is only reachable through SETUP, a properly generated PENABLE cannot be high on the first cycle. The myth only appears when someone builds PENABLE from independent logic that bypasses the FSM.
4. Real SoC implementation
In real RTL the difference between the myth and the spec is a few lines in the manager's transfer FSM — and the myth is precisely what you get when someone tries to "optimise" PENABLE into its own combinational term instead of deriving it from the state. Here is the wrong-versus-right pair, with real APB signals.
// ============================================================
// WRONG — "assert PENABLE immediately" : one-cycle access, no SETUP
// ============================================================
// The designer wants a one-cycle transfer, so PENABLE is driven high
// on the SAME cycle PSEL asserts. There is now NO cycle with
// PSEL=1 && PENABLE=0 -> no SETUP phase -> no decode window, and
// PADDR/PWRITE are committed against on the cycle they first appear.
typedef enum logic { IDLE, ACTIVE } bad_state_t; // note: no SETUP state at all
bad_state_t bstate;
always_ff @(posedge pclk or negedge presetn) begin
if (!presetn) bstate <= IDLE;
else case (bstate)
IDLE: if (req) bstate <= ACTIVE;
ACTIVE: if (pready) bstate <= IDLE;
endcase
end
assign psel_bug = (bstate == ACTIVE);
assign penable_bug = (bstate == ACTIVE); // BUG: PENABLE == PSEL, high from cycle 1
assign paddr_bug = req_addr; // may still be settling when PENABLE=1
// ============================================================
// CORRECT — SETUP then ACCESS : PENABLE low in setup, high in access
// ============================================================
// A three-state FSM. SETUP is entered for exactly one cycle with
// PSEL=1 and PENABLE=0 (the mandatory decode window); ACCESS raises
// PENABLE only on the NEXT cycle and holds it until PREADY completes.
typedef enum logic [1:0] { IDLE, SETUP, ACCESS } apb_state_t;
apb_state_t state;
always_ff @(posedge pclk or negedge presetn) begin
if (!presetn) state <= IDLE;
else case (state)
IDLE: if (req) state <= SETUP; // request -> enter SETUP
SETUP: state <= ACCESS; // ALWAYS one setup cycle, then ACCESS
ACCESS: if (pready) state <= IDLE; // hold ACCESS until completion
endcase
end
// PSEL is high across BOTH phases; PENABLE is high ONLY in ACCESS.
assign psel = (state == SETUP) || (state == ACCESS);
assign penable = (state == ACCESS); // low in SETUP -> high in ACCESS
// PADDR/PWRITE are presented in SETUP and held stable through ACCESS,
// so they are guaranteed stable on the cycle PENABLE finally rises.Two facts drive the correct version. First, the SETUP state is not optional scaffolding — it is the decode window made structural. The bad FSM has no SETUP state at all, which is why PENABLE equals PSEL; the correct FSM spends exactly one cycle in SETUP (PSEL=1, PENABLE=0) before it can reach ACCESS, so a PENABLE-low decode cycle is guaranteed for every transfer. Second, PENABLE must be state == ACCESS, never an independent term. The moment PENABLE is computed from anything that can be true on the first cycle — psel, req, a decode of PADDR — you have reintroduced the immediate-assert bug. Deriving it from a state that is only reachable through SETUP makes "PENABLE low on cycle one" a property of the reachability graph, not a timing coincidence. The companion guarantee — that PADDR/PWRITE/PWDATA stay frozen from SETUP through ACCESS so the commit sees stable operands — is the subject of setup-phase mechanics and access-phase mechanics.
5. Engineering tradeoffs
The "assert PENABLE immediately" idea is really a claim that you can trade one cycle of latency for a protocol violation and come out ahead. The table shows why the trade never pays: every cell of the myth's supposed benefit is either false or fatal.
| Aspect | Myth: PENABLE high on cycle 1 | Reality: SETUP (PENABLE=0) then ACCESS (PENABLE=1) | Why the reality wins |
|---|---|---|---|
| Decode window | None — no cycle with PSEL=1, PENABLE=0 | One guaranteed cycle to decode PADDR/PWRITE | A compliant subordinate has no defined moment to decode; commits blindly |
| Address/control stability | PADDR/PWRITE may still be settling at commit | Held stable through SETUP into ACCESS | The access can commit against a changing address — wrong-register decode |
| Protocol legality (IHI 0024C §3.1) | Illegal — PENABLE must rise the cycle after PSEL | Legal — access phase entered on the next cycle | Every compliant checker/VIP flags PENABLE high in the first selected cycle |
| Latency "saved" | Appears to save one cycle | Two-cycle transfer as specified | The "saved" cycle is the decode window; deleting it saves nothing real |
| Interoperability | Fails against any spec-following slave/monitor | Works with every AMBA-compliant peripheral | A bus that only works with your own broken slave is not APB |
The throughline: there is no legitimate one-cycle APB transfer. The two-phase structure is the protocol's definition, not a performance knob — the SETUP cycle is the price of a decode window and stable operands, and it is a price the spec makes non-negotiable. If you genuinely need lower per-access latency, the answer is a different bus (AHB-Lite, AXI), not a mutilated APB. Trying to "speed up" APB by asserting PENABLE immediately does not produce a fast APB; it produces a non-APB that happens to share pin names.
6. Common RTL mistakes
7. Debugging scenario
Pick the classic form of this bug: a hand-written APB master model (a BFM in a testbench, or a junior's first RTL bridge) that "optimises" the transfer to a single cycle — and the wall of failures it produces the moment it meets a real slave.
- Observed symptom: a new APB master is integrated against an existing, previously-passing peripheral. Every access now either reads the wrong register or the peripheral's protocol monitor fires on the first cycle of every transfer with something like "PENABLE asserted in SETUP phase" or "PENABLE high without a preceding setup cycle." Reads come back with a neighbouring register's value; writes land in the wrong location or not at all.
- Waveform clue: in the capture (Figure 2), on the buggy master
PSELandPENABLErise on the same edge — there is no cycle wherePSELis high andPENABLEis low. On that same first cyclePADDRis still transitioning from its previous value toward the intended address. The slave's decode, which samples whenPENABLEis high, latches against the half-settledPADDR. Compare the correct master directly below:PSELrises,PENABLEstays low for one full cycle whilePADDRsettles, and only then doesPENABLErise into a stable address. - Root cause: the master was built without a SETUP state.
PENABLEwas wired equal toPSEL(or to areq/decode term true on cycle one) in the belief that a two-cycle transfer was wasteful. This deletes the SETUP phase, so there is no decode window and no stability guarantee — a direct violation of AMBA APB (IHI 0024C) §3.1, which requiresPENABLEto assert on the cycle afterPSEL. - Correct RTL: insert the SETUP state so
PENABLEis low for exactly one cycle afterPSELasserts, and derivePENABLEpurely from the state:Azvya Education Pvt. Ltd.VLSI MentorSnippetalways_ff @(posedge pclk or negedge presetn) if (!presetn) state <= IDLE; else case (state) IDLE: if (req) state <= SETUP; // decode window guaranteed SETUP: state <= ACCESS; // exactly one PENABLE-low cycle ACCESS: if (pready) state <= IDLE; endcase assign psel = (state == SETUP) || (state == ACCESS); assign penable = (state == ACCESS); // low in SETUP, high in ACCESS - Verification assertion: prove
PENABLEis low in the first selected cycle — it may not be high on the same edgePSELfirst rises:Azvya Education Pvt. Ltd.VLSI MentorSnippet// PENABLE must be low in the first cycle of selection (the SETUP phase) assert property (@(posedge pclk) disable iff (!presetn) (psel && !$past(psel)) |-> !penable ); - Debug habit: when a new master fails against a known-good slave with wrong-register or monitor-fires-immediately symptoms, do not chase the slave's decode logic — chase the master's
PENABLE. OverlayPSELandPENABLEand look for the one cycle wherePSELis high andPENABLEis low. If that cycle is missing, the master deleted the SETUP phase, and everything downstream is decoding against an unstable address.
8. Verification perspective
Because "assert PENABLE immediately" is a safety violation — it commits a transfer against an undefined decode — the verification is a small set of properties that fire the instant PENABLE is high when it should be in SETUP. These are exactly the checks a compliant APB monitor or VIP carries, which is why the myth fails against any real environment.
- First-selected-cycle must be SETUP. The core property: on the cycle
PSELfirst rises,PENABLEmust be low.assert property (@(posedge pclk) disable iff(!presetn) (psel && !$past(psel)) |-> !penable);— this fires immediately on any master that raisesPENABLEwithPSEL, catching the deleted-SETUP bug at its first transfer. It is the direct encoding of AMBA APB (IHI 0024C) §3.1: the access phase is entered on the cycle after selection. PENABLEimplies a prior setup cycle. Complementary framing: wheneverPENABLErises, the previous cycle must have been a setup cycle —PSELhigh,PENABLElow.assert property (@(posedge pclk) disable iff(!presetn) $rose(penable) |-> $past(psel && !penable));. This catches the same bug from thePENABLEside and also catches aPENABLEthat rises out of an idle cycle with no setup at all.- Address/control stability across the setup→access boundary. The reason the SETUP cycle exists is stability, so assert it:
PADDRandPWRITEmust not change on the edgePENABLErises —assert property (@(posedge pclk) disable iff(!presetn) $rose(penable) |-> $stable(paddr) && $stable(pwrite));. A master that skips SETUP will often also violate this, because it presents and commits the address in the same cycle. Pair these with a coverage bin that the SETUP phase was actually entered (psel && !penable) so a testbench that never exercises a clean setup cycle is visibly under-covered.
The point: a single property — PENABLE low in the first selected cycle — is sufficient to catch the entire "assert immediately" myth, and it is a safety check that fails on the offending edge rather than a subtle coverage gap. Carrying this alongside the full set of enable-shape properties (penable |-> psel, one-cycle-in-zero-wait, held-across-waits) is the job of PENABLE debug and error scenarios; the correct-versus-illegal transition set that these properties encode is enumerated in legal and illegal transitions.
9. Interview discussion
"Can PENABLE assert on the first cycle of a transfer?" is a fast, high-signal screening question, because the one-word answer ("no") is cheap but the reasoning separates someone who has memorised the waveform from someone who understands why the two-phase handshake exists.
Answer in three moves. First, the flat correction: no — PENABLE must be low in the first cycle, which is the SETUP phase (PSEL high, PENABLE low); it rises in the ACCESS phase on the next cycle, per AMBA APB (IHI 0024C) §3.1. Second, the why: that first low cycle is the subordinate's decode window and the guarantee that PADDR/PWRITE are stable before the access commits — assert PENABLE immediately and there is no cycle in which the slave is defined to decode, and the commit can race a still-settling address, so you get wrong-register decodes, not a faster bus. Third, the generation and check: the reason this is a structural guarantee in real RTL is that PENABLE is state == ACCESS and ACCESS is reachable only through SETUP, so a PENABLE-low first cycle is a property of the FSM, not a timing hope; and you prove it with psel && !$past(psel) |-> !penable. Land the depth point: the "saved" cycle is not overhead — it is the decode window — so there is no legal one-cycle APB transfer, and a master that produces one is not fast, it is broken. Closing with "and this is the single most common violation I see in hand-written masters and BFMs — PENABLE wired equal to PSEL" signals you have debugged real integrations, not just read the spec. For the adjacent traps interviewers pair with this one, see setup/access interview traps.
10. Practice
- Name the missing cycle. Given a waveform where
PSELandPENABLErise on the same edge, state which protocol phase is missing, what the subordinate loses, and which clause of AMBA APB (IHI 0024C) §3.1 is violated. - Fix the FSM. Given a two-state (
IDLE/ACTIVE) master wherePENABLE == PSEL, add the state and transition that guarantees exactly onePENABLE-low cycle afterPSELasserts, and write the correctedPENABLEassignment. - Write the assertion. From memory, write the SVA that proves
PENABLEis low in the first selected cycle, and explain whatpsel && !$past(psel)selects and why it is the right antecedent. - Reason about stability. Explain why asserting
PENABLEimmediately is not merely "one cycle early" but "commit before decode," and describe the wrong-register symptom it produces on a read. - Refute the optimisation. A colleague proposes a one-cycle APB transfer to cut latency. In three sentences, explain why no legal one-cycle APB transfer exists and what bus they should reach for instead if they truly need lower latency.
11. Q&A
12. Key takeaways
PENABLEcannot assert on the first cycle of a transfer. The first cycle is the SETUP phase (PSELhigh,PENABLElow);PENABLErises in the ACCESS phase on the next cycle, per AMBA APB (IHI 0024C) §3.1. There is no legal one-cycle APB transfer.- The SETUP cycle is a mandatory decode window, not overhead. It is the only cycle in which a subordinate is defined to decode
PADDR/PWRITE, and it guarantees those signals are stable before the access commits. Delete it and the slave commits blindly against a possibly-settling address. - "Assert immediately" is a stability bug, not a speed-up. It commits the transfer on the same cycle the address first appears, causing wrong-register decodes and wrong-direction latches — the symptom is bad data, not merely different timing.
- The guarantee is structural.
PENABLE = (state == ACCESS)withACCESSreachable only throughSETUPmakes "PENABLElow on cycle one" a property of the FSM. The bug reappears only whenPENABLEis built from an independent term that can be true on the first cycle. - One assertion catches the whole myth.
psel && !$past(psel) |-> !penablefires the instantPENABLEis high in the first selected cycle — the same check every compliant monitor carries, which is why the shortcut fails against any real slave. See PENABLE debug and error scenarios and the wider structure in the APB transfer overview and two-phase timing diagrams.