Skip to content

AMBA APB · Module 5

PENABLE Behaviour Deep Dive

The exact PENABLE timing-legality rules and how they fall out of the transfer FSM — low in setup, high in access, exactly one cycle in a zero-wait transfer, held across waits, never high without PSEL — with the assertions that enforce them.

Module 3 told you what PENABLE means — it is the strobe that marks the access phase. This chapter answers the harder question that decides whether your manager is protocol-legal: what is the exact, cycle-by-cycle shape PENABLE is allowed to take, and how do you generate it so that shape is guaranteed rather than hoped for? The legal shape is tighter than "low then high": PENABLE is low in setup, high for exactly one cycle in a zero-wait access, held high across wait states without ever toggling, dropped at completion, and never high without PSEL. The single idea to carry: PENABLE is not a signal you control — it is a signal you derive, purely as state == ACCESS from the manager's transfer FSM, and that derivation is what makes every one of those legality rules structural instead of policed.

1. What problem is being solved?

The problem is emitting an access strobe whose every transition is provably legal, for a transfer of unknown length, without writing timing logic that can get it wrong.

A manager must drive PENABLE so that a subordinate can trust it: low for the decode cycle, high for the perform cycle(s), and stable in between. But the access length is not known when the manager starts — the subordinate may insert zero wait states or ten. If PENABLE were built from ad-hoc combinational logic (a counter, an edge detector, a "data valid" qualifier), each new corner — back-to-back transfers, a long wait, a single-cycle access — is a new chance to emit an illegal edge. APB removes that entire class of bug by making PENABLE a consequence of where the FSM already is:

  • The FSM already knows the phase. It is in SETUP for exactly one cycle, then ACCESS until PREADY completes it. That state register encodes everything PENABLE needs to say.
  • So PENABLE is a read-out, not a computation. assign penable = (state == ACCESS) — one driver, no decode beyond the state compare, no timing logic to get wrong.

The result is that the legal shape falls out for free: one cycle low (the FSM is in SETUP exactly once), held high through waits (the FSM stays in ACCESS), never high without PSEL (both SETUP and ACCESS assert PSEL). The problem being solved is making legality structural.

2. Why the previous model is not enough

Module 3 introduced PENABLE as the access-phase marker and gave you its role and its one-cycle-low contract. That chapter answers what PENABLE is. This one drills three things it deliberately left at the level of a rule:

  • The exact timing legality, not just the shape. Module 3 says PENABLE is "low then high, held through waits." This chapter makes that a closed set of legal transitions: PENABLE may go low→high only at the setup→access boundary; once high it may go high→low only on the completion edge; it may never go high while PSEL is low; and in a zero-wait access it is high for exactly one cycle — not zero, not two. These are the rules a protocol checker enforces, and each one names a real bug.
  • The generation, as a pure function of the FSM. Module 3 shows the one-line assignment; here that assignment is the whole argument. Because PENABLE is state == ACCESS, it is a single-driver, glitch-free decode of a registered state — which is why it cannot toggle mid-wait or rise in setup. We make the link from "pure state decode" to "every legality rule satisfied" explicit.
  • The verification that proves it. Module 3 lists the misconceptions; this chapter turns them into assertions — PENABLE implies PSEL, and PENABLE is high for exactly one cycle in a zero-wait transfer — so the legal shape is checked every cycle, not assumed.

So the model to add is the legality contract plus its generation and its checker: not "what PENABLE marks" but "what edges PENABLE is permitted, why the FSM derivation guarantees them, and how SVA fails the instant one is violated."

3. Mental model

The model: PENABLE is a shadow cast by the FSM state — it has no will of its own. Wherever the state register points, PENABLE follows on the same clock, one cycle behind nothing. You do not steer the shadow; you steer the FSM, and the shadow is correct by construction.

Think of a single-pole indicator light wired straight to one position of a rotary selector. The selector has three detents — IDLE, SETUP, ACCESS — and the lamp is hard-wired to the ACCESS detent only. You cannot make the lamp flicker while the selector rests on ACCESS (it is a clean contact, not a computed value); you cannot light it on SETUP (the wire is not there); and it stays lit for exactly as long as the selector sits on ACCESS — one click for a quick turn, several clicks if something jams the selector there (a wait state). The lamp's behaviour is entirely determined by the selector's position, which is exactly why it can never be illegal.

Three refinements make the model precise:

  • One driver, one source of truth. PENABLE is state == ACCESS and nothing else. There is no second branch, no qualifier, no override. That single source is why it is glitch-free: it is a decode of a registered value, settling once per clock.
  • The legal edges are the FSM's edges. PENABLE rises only when the FSM moves SETUP → ACCESS, and falls only when the FSM leaves ACCESS on completion. Because the FSM cannot enter ACCESS from anywhere but SETUP, and SETUP always asserts PSEL, PENABLE can never be high without PSEL.
  • Length is the FSM's, not PENABLE's. A zero-wait access spends one cycle in ACCESS, so PENABLE is high one cycle. A waited access stays in ACCESS, so PENABLE holds high — unchanged — until completion. PENABLE never measures the wait; it just reflects the state.
A three-state APB FSM — IDLE, SETUP, ACCESS — with PENABLE annotated 0, 0, and 1 per state, transitions for transfer-requested, always-next-cycle, the PREADY=0 wait self-loop, and the two completion exits, plus a boxed equation PENABLE = (state == ACCESS).
Figure 1 — PENABLE generated as a pure function of the manager's transfer FSM. PENABLE is 0 in IDLE and SETUP and 1 in ACCESS, derived as the single assignment PENABLE = (state == ACCESS). Because the FSM enters ACCESS only from SETUP (which always asserts PSEL and lasts exactly one cycle) and stays in ACCESS while PREADY is low, every PENABLE legality rule is structural: it is high in exactly one state, low for exactly one setup cycle, held high across waits, and never high without PSEL. The figure stresses that PENABLE is a glitch-free decode of a registered state with one driver — a shadow of the FSM, not independent logic.

4. Real SoC / hardware context

In a real SoC the manager is the bridge from the system interconnect (AHB or AXI) down to the APB subordinates, and its transfer FSM is the small machine that paces each peripheral access. PENABLE is the cleanest output that FSM produces: a one-state decode with no companion logic. Here is the generation, plus the two assertions that hold its legality:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// PENABLE generation + legality assertions in the APB manager (teaching sketch).
typedef enum logic [1:0] { IDLE, SETUP, ACCESS } apb_state_t;
apb_state_t state;
 
// The entire PENABLE contract in one driver: high in ACCESS, low everywhere else.
assign penable = (state == ACCESS);
assign psel    = (state == SETUP) || (state == ACCESS);
 
// Legality 1: PENABLE is never high without PSEL — the access strobe may not
// fire on a peripheral that is not selected. Fails the instant a manager
// asserts PENABLE in an unselected/idle cycle.
property p_penable_implies_psel;
  @(posedge pclk) disable iff (!presetn) penable |-> psel;
endproperty
assert property (p_penable_implies_psel);
 
// Legality 2: in a ZERO-WAIT access (PREADY high in the first access cycle),
// PENABLE is high for EXACTLY one cycle — it must drop the next cycle, never
// linger into a second access cycle.
property p_penable_one_cycle_zero_wait;
  @(posedge pclk) disable iff (!presetn)
    ($rose(penable) && pready) |=> !penable;
endproperty
assert property (p_penable_one_cycle_zero_wait);

Two legality rules fall straight out of the generation. Because the FSM passes through SETUP (where PSEL is high, PENABLE low) before reaching ACCESS, PENABLE cannot rise without PSEL already being high — the first property can only fail if someone bypasses the FSM. And because ACCESS is entered for one cycle in a zero-wait transfer, PENABLE drops the next cycle automatically — the second property catches the bug where custom logic holds it high for a phantom second cycle. The held-high-across-waits behaviour needs no extra logic at all: the FSM stays in ACCESS while PREADY is low, so PENABLE holds high, unchanged, for the whole wait. The deeper companion contract — that the access-defining signals stay frozen while PENABLE is held — is covered in signal-stability requirements.

Two stacked APB timing diagrams. Top: a zero-wait transfer where PENABLE is low in setup and high for exactly one access cycle. Bottom: a two-wait-state transfer where PENABLE rises once at setup-to-access and stays high across both waits and completion without toggling, with annotations for 0-in-setup, rises-at-boundary, held-high-across-waits, and never-high-without-PSEL.
Figure 2 — PENABLE's legal shape across two cases against PCLK. Case A (zero-wait): PENABLE is 0 in SETUP, rises at the setup-to-access boundary, and is high for exactly one cycle before dropping at completion (PREADY high). Case B (two wait states): PENABLE is 0 in SETUP, rises once at the setup-to-access boundary, then stays continuously high across both wait cycles (PREADY low) and the completion cycle — it is held high across the waits and never toggles. Both cases are annotated that PENABLE is 0 in setup, rises at setup-to-access, and is never high without PSEL. The figure makes the legality concrete: exactly one high cycle with no waits, one continuous high pulse with waits, and zero illegal mid-wait edges.

5. Engineering tradeoff table

Generating PENABLE as a pure FSM decode is a deliberate choice that trades flexibility for guaranteed legality. Each row is a rule and the bargain it strikes.

Generation / legality ruleWhat it gives upWhat it buysWhy it is correct for APB
PENABLE = state == ACCESS (one driver)Custom enable shapingGlitch-free, single-source strobeA registered-state decode cannot race or contend
High in exactly one stateA multi-cycle "active" windowThe one-cycle-low decode window is structuralThe FSM is in SETUP exactly once per transfer
Held high across waits (no toggle)A per-cycle "still busy" pulseBackpressure owned by PREADY aloneThe access is held, not restarted; the marker must not blink
Dropped only on completion or next setupA free trailing high cycleBack-to-back ACCESS → SETUP with no idle gapAdjacency without overlap keeps throughput up
Never high without PSELAn "enable" usable outside a selectA strobe that can only target a selected peripheralAn unselected peripheral must never see an access fire

The throughline: every legality rule is bought by not building independent PENABLE logic. The moment a designer adds a qualifier or a counter to "improve" PENABLE, they reintroduce exactly the illegal edges the FSM decode rules out.

6. Common RTL / waveform mistakes

7. Interview framing

This is a senior-level discriminator because the precise answer proves you think about PENABLE as generated and verified, not just defined. The weak answer recites "low in setup, high in access." The strong answer states the legality rules and where they come from.

Say it in three moves. First, the legal shape: PENABLE is low in setup, rises only at the setup→access boundary, is high for exactly one cycle in a zero-wait access, is held high — never toggled — across wait states, drops on completion or rolls straight into the next setup, and is never high without PSEL. Second, the generation: it is not controlled, it is derived — assign penable = (state == ACCESS), a single-driver, glitch-free decode of the manager's FSM, which is why every one of those rules is structural rather than policed. Third, the verification: bind penable |-> psel and a "high for exactly one cycle in a zero-wait access" property, and the canonical bugs — PENABLE high in setup, a multi-cycle zero-wait PENABLE, a PENABLE that toggles mid-wait — fail at the offending cycle. An interviewer who hears "derived from the FSM, so legality is structural" knows you have built a real bridge, not just read the spec.

8. Q&A

9. Practice

  1. Map rules to states. For each PENABLE legality rule (low in setup, one cycle in zero-wait, held across waits, never high without PSEL), name the FSM property that guarantees it.
  2. Draw both cases. Draw PSEL, PENABLE, and PREADY for a zero-wait transfer and a two-wait-state transfer; mark the single legal rising edge and the single legal falling edge in each.
  3. Spot the illegal edge. Given a waveform where PENABLE is high in the first cycle a transfer appears, state which legality rule is broken and what the subordinate loses.
  4. Write the assertions. From memory, write penable |-> psel and the "exactly one high cycle in a zero-wait access" property, and explain what each antecedent selects.
  5. Diagnose the toggle. A PENABLE that drops mid-wait passes in zero-wait sims but fails on a slow subordinate. Explain why generating PENABLE from a counter instead of state == ACCESS produces exactly this, and the one-line fix.

10. Key takeaways

  • PENABLE's legal shape is tight: low in setup, high for exactly one cycle in a zero-wait access, held high across wait states without toggling, dropped on completion or rolled into the next setup, and never high without PSEL.
  • It is derived, not controlled. assign penable = (state == ACCESS) — a single-driver, glitch-free decode of the manager's transfer FSM, with no companion logic.
  • The FSM makes every legality rule structural. One SETUP cycle, the PREADY = 0 wait self-loop, and ACCESS reachable only from SETUP give you the one-cycle-low, held-high, and never-without-PSEL rules for free.
  • The canonical bugs come from building independent PENABLE logic: high in setup, a multi-cycle zero-wait pulse, or a toggle mid-wait — each one a counter or qualifier reintroducing an illegal edge.
  • Assert it. penable |-> psel and a "high for exactly one cycle in a zero-wait access" property catch the canonical bugs at the offending cycle; the assertions prove no one bypassed the FSM.
  • The throughline: legality is bought by not shaping PENABLE yourself — steer the FSM, and the strobe is correct by construction. See why APB has two phases for the reason that one held-low cycle exists at all.