Skip to content

AMBA AHB · Module 16

Address / Control Capture

Capturing the address-phase control for use in the data phase — the single discipline underlying every slave output. Because AHB is pipelined, the address/control (HSEL+HTRANS, HWRITE, HADDR, HSIZE, HBURST, HPROT) is valid in the address phase, one cycle before the data phase where the slave acts, so the slave registers them (sel_q, write_q, addr_q, size_q, burst_q, prot_q) and acts on the copies one cycle later — with the capture enabled only when HREADY is high, so a wait state doesn't overwrite the in-progress transfer's context.

The last three chapters built the slave's outputs (HREADYOUT, HRDATA, HRESP); this chapter isolates the one discipline that makes all of them possible: capturing the address-phase control for use in the data phase. It's the move you've seen in every slave chapter since 16.1 — now examined on its own, because getting it right is the foundation of correct slave RTL. The reason it's needed is AHB's pipelining (pipelined operation): the address and control signals (HSEL+HTRANS, HWRITE, HADDR, HSIZE, HBURST, HPROT) are valid in the address phase — one cycle before the data phase in which the slave must act on them (write the data, mux the read, generate the response). The address/control signals won't still be there in the data phase (the master has moved on). So the slave must sample them into registers at the end of the address phase and use the registered copies (sel_q, write_q, addr_q, size_q, burst_q, prot_q) one cycle later. The critical detail is the enable: the capture must be gated by HREADY high — because a new address phase only commits when the current transfer completes; capturing unconditionally would let a wait state overwrite the in-progress transfer's context. This chapter builds the capture correctly — the bedrock under every slave output.

1. What Is It?

Address/control capture is the slave logic that registers the address-phase control signals so the data-phase logic can act on them one cycle later. Its parts:

  • Why register — AHB is pipelined: control is valid in the address phase, one cycle before the data phase where the slave acts; the signals are gone by then, so they must be captured.
  • What's captured — the qualified select (sel_q = HSEL && real HTRANS), write_q (HWRITE), addr_q (HADDR), and as needed size_q (HSIZE), burst_q (HBURST), prot_q (HPROT).
  • The HREADY-gated enable — the capture is enabled only when HREADY is high (a new address phase only commits when the current transfer completes).
  • Used everywhere — the captured copies feed every slave output (HREADYOUT, HRDATA, HRESP, write/read paths).
Address-phase control signals captured into registers (gated by HREADY) and used by the data-phase logic one cycle later.
Figure 1 — capturing address-phase control for the data phase. In the address phase (cycle N), the inputs HSEL+HTRANS→sel_q, HWRITE→write_q, HADDR→addr_q, HSIZE→size_q, HBURST→burst_q, HPROT→prot_q are valid. The slave samples them into capture registers (flops clocked by HCLK), enabled by HREADY high. In the data phase (cycle N+1), the data-phase logic uses the _q copies: a write stores HWDATA if sel_q && write_q; a read muxes source[addr_q] onto HRDATA; the response and wait logic use size_q, prot_q, etc. The address phase leads the data phase by one cycle, so the slave registers the control and acts on the copy one cycle later — and the capture is enabled only when HREADY is high, else a wait state overwrites the held context.

So address/control capture is the slave's bridge across the pipeline. AHB separates a transfer into an address phase (control valid) and a data phase (data moves), one cycle apart. The slave's work — writing the data, returning the read, generating the response — happens in the data phase, but the information about what to do (which address, read or write, what size) is on the bus in the address phase. So the slave must carry that information across the one-cycle gap — by registering it. The registered copies (_q signals) are then the slave's view of the current transfer throughout its data phase. And the enableHREADY high — ensures each committed transfer gets its own captured context, undisturbed by wait states. So address/control capture is the capture-then-act backbone made explicit — the discipline every slave output depends on. So it's the foundation of slave RTL.

2. Why Does It Exist?

Address/control capture exists because AHB's pipelining separates the control (address phase) from the action (data phase) by one cycle — so the slave must carry the control across that gap by registering it; and the enable is gated by HREADY because a transfer's context must survive its own wait states.

The pipelining separates control from action is the root: AHB pipelines transfers — the address phase (control valid) precedes the data phase (data moves) by one cycle, and consecutive transfers overlap (transfer N's data phase coincides with transfer N+1's address phase — chapter 2.5). So the control for a transfer is on the bus in one cycle (address phase), but the slave acts on it in the next (data phase). By the data phase, the bus's HADDR/HWRITE/etc. have moved on to the next transfer. So the slave cannot read the control in the data phase — it's gone. So it must have captured it earlier. So capture exists because the control and action are one cycle apart. So it's a pipeline-bridging necessity. So capture is forced by pipelining.

The the slave acts in the data phase is why the timing matters: the slave's actual work is data-phase work — a write moves HWDATA (which is itself a data-phase signal) into storage; a read drives HRDATA (data-phase); the response (HRESP) and pace (HREADYOUT) complete the data-phase transfer. All of this needs the control (which address? read or write? what size?) — but the control was address-phase. So the slave needs the address-phase control available in the data phase — which only the captured copies provide. So capture exists to supply the data-phase logic with the control it needs. So it's the data-phase logic's input. So the work needs the captured control.

The wait states demand the gated enable is why HREADY gates it: a transfer can take multiple cycles (wait states — chapter 6). During those waits, the transfer's context (its address, write flag) must persist — the slave is still working on it. But the master, during the wait, may already be driving the next transfer's address phase on the bus (the pipeline keeps moving). So if the slave recaptured every cycle, it would overwrite the in-progress transfer's context with the next one's — corrupting the access mid-flight. So the capture must be enabled only when the current transfer completes — i.e., when HREADY is high (the same condition that lets a new address phase commit). So the gated enable exists to protect each transfer's context through its waits. So HREADY gates the capture. So capture exists because: AHB's pipelining separates control (address phase) from action (data phase) by one cycle (the slave must register the control to bridge the gap — the why); the slave's work is data-phase (needing the address-phase control carried forward — the necessity); and wait states mean a transfer's context must survive (so the capture is gated by HREADY high — the enable). So address/control capture is the pipeline-bridging discipline that gives each transfer's data-phase logic the control it needs, protected through its wait states — the foundation every slave output is built on. So this chapter establishes the bedrock. So capture correctly, gated by HREADY.

3. Mental Model

Model address/control capture as a pharmacy counter where you hand over your prescription slip at the drop-off window (the address phase), and the pharmacist fills it at the pick-up window a step later (the data phase). The pharmacist can't fill from the slip if it's no longer in their hand — so they copy the details onto the bag the moment you drop it off, and work from the bag label, not the original slip (which you've taken back). And they only start a new bag when the previous order is actually handed over — they don't relabel a half-filled bag just because the next customer is already talking at the drop-off window.

A pharmacy with a drop-off window and a pick-up window, one step apart (the pipeline). You hand over your prescription slip at drop-off (the address phase — HADDR/HWRITE/etc. valid), then move to pick-up, where a step later the pharmacist hands you the filled order (the data phase — the slave acts). But here's the thing: by the time the pharmacist is filling your order at pick-up, the original slip is no longer in front of them — you've moved on, and the next customer is already at drop-off handing over their slip. So the pharmacist can't fill from the original slip in the data-phase moment — it's gone. The solution: the moment you drop off, the pharmacist copies the key details onto the bag's labelname, drug, dose, quantity (sel_q, write_q, addr_q, size_q…) — and then fills from the bag label, not the original slip. The bag label is their captured copy of your order, and it stays with the bag through the whole fill. Now suppose your order takes extra time (a wait state — they have to compound it). While they're still working on your bag, the next customer is already at drop-off describing their order. The pharmacist must not start relabeling your bag with the next customer's details — that would ruin your order. They only create and label a new bag when the previous order is actually handed over at pick-up (when HREADY goes high — the transfer completes). So each committed order gets its own bag with its own label, and that label survives however long the fill takes.

This captures address/control capture: the drop-off window = the address phase (control valid); the pick-up window one step later = the data phase (slave acts); the original slip being gone at fill time = the bus's HADDR/HWRITE moving on by the data phase; copying details onto the bag label = registering the control into _q flops; filling from the bag label not the slip = the data-phase logic using the _q copies; the bag label surviving a slow compound = the captured context persisting through wait states; not relabeling a half-filled bag when the next customer talks = gating the capture on HREADY (don't overwrite the in-progress transfer); labeling a new bag only on hand-over = capturing a new context only when HREADY is high (a transfer commits). Copy the details onto the bag, work from the copy, and only start a new bag when the last one is handed over.

Watch the capture survive a wait state — the context held while the master moves on:

HREADY-gated capture survives a wait state

4 cycles
Cycle 0: capture addr_q=A (HREADY high). Cycle 1: A's data phase with a wait (HREADY low); master drives HADDR=B, but capture is disabled so addr_q stays A. Cycle 2: A completes (HREADY high), capture enabled, addr_q becomes B. The capture enable follows HREADY; addr_q only updates when HREADY is high, so the in-progress transfer keeps its context through the wait.HREADY high → capture addr_q = AHREADY high → capture …Wait (HREADY low) → capture disabled, addr_q stays A (master moved to B)Wait (HREADY low) → ca…A completes (HREADY high) → capture B; addr_q = BA completes (HREADY hi…HCLKHADDR (bus)ABBCHREADYcapture enableaddr_q (held)AAABt0t1t2t3
Figure 2 — the captured context survives a wait state; the capture is enabled only when HREADY is high. Cycle 0: address phase for transfer to address A — the slave captures addr_q=A, write_q (HREADY was high, so capture enabled). Cycle 1: data phase of A, but the slave inserts a wait (HREADY low); meanwhile the master has moved HADDR to B (the next transfer's address phase). Because HREADY is low, the capture is NOT enabled — addr_q stays A (the in-progress transfer keeps its context). Cycle 2: A completes (HREADY high) — now the capture is enabled, sampling B; addr_q becomes B. The 'capture enable' row tracks HREADY; addr_q only updates when it's high. The in-progress transfer A keeps addr_q=A through its wait.

The model's lesson: copy the details onto the bag, work from the copy, and only start a new bag when the last one is handed over. In the waveform, addr_q holds A through A's wait state (capture disabled while HREADY low), even though the master has already driven B on the bus — and only updates to B when A completes.

4. Real Hardware Perspective

In hardware, address/control capture is a bank of flops (one per captured signal) with a common enable tied to HREADY, clocked by HCLK; the data-phase logic is purely combinational on the _q outputs; and the qualified select is formed before capture.

The capture flops with HREADY enable: each captured signal is a flop with an enable: if (HREADY) addr_q <= HADDR; (and likewise write_q <= HWRITE, size_q <= HSIZE, etc.), all clocked by HCLK. The common enable is HREADY — when high, the flops sample the address phase; when low (a wait), they hold. So in hardware, the capture is an enabled register bank. So it's flops with one enable. So that's the structure.

Comparison of unconditional capture (corrupts the in-progress transfer during a wait) versus HREADY-gated capture (keeps each committed transfer's context).
Figure 3 — why the capture must be gated by HREADY. Left (wrong): capturing every cycle unconditionally. During a wait state, the master may already be driving the next transfer's address phase, so an unconditional capture overwrites the in-progress transfer's held context with the next transfer's — corrupting the access (wrong address/data). Right (correct): capturing only when HREADY is high. The address phase only commits when the current transfer completes (HREADY high), so the capture updates only then, and the in-progress transfer keeps its own context through its wait states. This is the same rule the master uses to advance: a new address phase commits only on HREADY high.

The qualified select formed before capture: the select captured is the qualified select — sel_q = HSEL && (HTRANS == NONSEQ || HTRANS == SEQ) (chapter 16.1) — so a real transfer is captured, not an IDLE/BUSY with HSEL high. The qualification (combinational, on the address-phase HSEL/HTRANS) is done before (or at) the capture, so sel_q records "a real transfer was selected". So in hardware, the select is qualified at capture time. So sel_q means a real, selected transfer. So the qualification is built in.

The combinational data-phase logic on the _q copies: with the control captured, the data-phase logic is combinational on the _q outputs (plus the data-phase HWDATA/storage). The write: if (sel_q && write_q && !error) regs[addr_q] <= HWDATA;. The read: HRDATA = source[addr_q];. The response/pace: functions of sel_q, size_q, prot_q, the memory-ready condition. So in hardware, the data-phase logic reads the captured copies — it never touches the (now-stale) bus control. So the _q signals are the single source of the transfer's control in the data phase. So in hardware, address/control capture is an enabled register bank (enable = HREADY, clock = HCLK), capturing the qualified select and the needed control, feeding combinational data-phase logic. The enable and the qualified select are the two pieces that distinguish a correct capture from a buggy one. So in hardware, gate on HREADY and qualify the select. So those are the crux.

5. System Architecture Perspective

At the system level, address/control capture is the universal slave-side manifestation of AHB's pipeline — every slave does it, identically — and it's the single point where a slave's understanding of the pipeline is encoded; getting it right is what makes a slave pipeline-correct.

The universal slave pattern: every AHB slave — simple, register bank, memory, bridge — must capture the address-phase control to act in the data phase. It's not optional or slave-specific; it's the universal slave-side response to the pipelined protocol. So at the system level, address/control capture is the common pattern all slaves share — the slave-side of the pipeline contract. So it's universal. So every slave does it.

The pipeline understanding encoded: the capture is where a slave's handling of the pipeline is concentrated. The two subtle points — capture in the address phase, act in the data phase (the one-cycle offset) and gate on HREADY (survive wait states) — are exactly the points where a slave designer must understand the pipeline. A slave that gets these right is pipeline-correct; one that doesn't has subtle, traffic-dependent bugs. So at the system level, the capture is the locus of pipeline-correctness — the place where "does this slave understand AHB's timing?" is answered. So it's the pipeline test. So correctness lives here.

The foundation for reuse: because the capture pattern is universal and subtle, it's an ideal candidate for a reusable template (chapter 16.11) — a correct capture block (enabled register bank, qualified select, HREADY gate) that every slave instantiates, rather than re-deriving (and re-bugging) each time. So at the system level, the capture is a reuse anchor — encapsulating the pipeline-handling once, correctly. So at the system level, address/control capture is the universal slave-side manifestation of AHB's pipeline (every slave does it identically — the slave-side of the pipeline contract), the locus of pipeline-correctness (where the one-cycle offset and the HREADY-gating — the subtle points — are encoded, determining whether a slave is pipeline-correct), and a natural reuse anchor (a correct capture block every slave instantiates — chapter 16.11). So address/control capture is the foundational discipline of slave RTL — small in code, but the crux of correct, pipeline-aware slave design. So encode the pipeline correctly here, once, and reuse it.

6. Engineering Tradeoffs

Address/control capture embodies the register-the-control, gate-on-HREADY, act-on-copies design.

  • Capture (register) vs use bus control directly. Capturing is necessary (the bus control is gone by the data phase) — using the bus control directly in the data phase reads the next transfer's values (wrong). Always capture.
  • HREADY-gated enable vs unconditional capture. The gated enable protects the in-progress transfer's context through waits (correct); unconditional capture overwrites it during a wait (corrupts the access). Always gate on HREADY.
  • Capture only what's needed vs capture everything. Capturing only the signals the slave uses (e.g. a simple slave may not need burst_q) saves flops; capturing everything is uniform but larger. Capture what the slave's logic consumes.
  • Per-slave capture vs reusable capture block. A reusable capture block (chapter 16.11) encodes the pipeline-handling once, correctly (less bug surface); per-slave hand-coding risks re-introducing the subtle bugs. Prefer a reusable, verified capture.

The throughline: address/control capture is the slave's bridge across AHB's pipeline — because the control (HSEL+HTRANS, HWRITE, HADDR, HSIZE, HBURST, HPROT) is valid in the address phase, one cycle before the data phase where the slave acts, the slave registers it (sel_q, write_q, addr_q, size_q, burst_q, prot_q) and acts on the copies one cycle later. The capture is enabled only when HREADY is high — so a wait state can't overwrite the in-progress transfer's context (the same condition that lets a new address phase commit). The captured qualified select (sel_q = HSEL && real HTRANS) ensures a real transfer. This one discipline — capture-then-act, gated by HREADY — is universal across slaves and the locus of pipeline-correctness, underlying every slave output (HREADYOUT, HRDATA, HRESP, write/read paths).

7. Industry Example

Trace the capture through a write to a memory slave that inserts a wait state — the case that exposes the gating.

The master writes data D to address A in a memory slave that needs one wait state.

  • Cycle 0 — A's address phase. The master drives HADDR = A, HWRITE = write, HSEL high with a real HTRANS. HREADY is high (the previous transfer completed), so the slave's capture is enabled: it samples addr_q = A, write_q = 1, sel_q = 1.
  • Cycle 1 — A's data phase (with a wait). The master drives HWDATA = D (the write data, a data-phase signal). The slave begins the write but needs a wait (the memory isn't ready), so it drives HREADYOUT low. Meanwhile, the pipelined master has already moved HADDR to the next transfer's address (say B). Because HREADY is low (A's wait), the slave's capture is disabledaddr_q holds A. So the slave's write-in-progress still targets A — correct.
  • Cycle 2 — A completes. The memory is ready; the slave drives HREADYOUT high, completing A's write: regs[addr_q] <= HWDATA with addr_q = A (held correctly) and HWDATA = DD is written to A, the right location. Now HREADY is high, so the capture is enabled, sampling B (addr_q = B) for the next transfer.
  • The bug avoided. Had the capture been free-running, cycle 1 would have sampled addr_q = B (the master's next address), and cycle 2's write would have gone to regs[B] <= Dthe wrong location. The HREADY gate prevents this.
  • The qualified select. sel_q was captured as a qualified select (real HTRANS), so an IDLE with HSEL high wouldn't have triggered a spurious write.

The example shows the capture's gating doing its job: across A's wait state, addr_q holds A (because HREADY is low, capture disabled), so the write lands at the correct address — even though the master had already moved the bus to B. The HREADY-gated enable is what makes the waited write correct. This is address/control capture under realistic (waited, pipelined) traffic. This is the foundation working.

8. Common Mistakes

9. Interview Insight

Address/control capture is a foundational RTL interview topic — the why (pipelining), the what (the captured signals), and especially the HREADY-gated enable are the signals.

A summary card on address/control capture: pipelining rationale, the captured signals, the HREADY-gated enable, and its universality.
Figure 4 — a strong answer in one card: AHB is pipelined, so control is valid in the address phase one cycle before the data phase; register sel_q, write_q, addr_q, size_q, burst_q, prot_q and act on the copies one cycle later; enable the capture only when HREADY is high (else a wait state clobbers the in-progress transfer's context); this one discipline underlies every slave output. The senior point: register the address-phase control, enable on HREADY high, act on the copies one cycle later.

The answer that lands gives the why and the gating: "AHB is pipelined — the address and control signals are valid in the address phase, which is one cycle before the data phase where the slave actually acts. By the data phase, the bus has moved on to the next transfer's address, so the original control is gone. So the slave must register the address-phase control — the qualified select, the write flag, the address, and as needed the size, burst, and protection — and use those registered copies in the data phase: a write stores HWDATA at the captured address, a read muxes the captured address onto HRDATA, the response uses the captured control. The critical detail is the capture enable. You must gate it on HREADY being high, not capture every cycle. Here's why: if the slave inserts a wait state, its transfer's data phase spans multiple cycles, but the pipelined master has already moved the address bus to the next transfer during the wait. If the capture were free-running, it would sample that next address into the registers during the wait, overwriting the in-progress transfer's context — so when the waited transfer completes, it acts on the wrong address. By gating the capture on HREADY high — the same condition the master uses to commit a new address phase — the capture only updates when the current transfer completes, so each transfer keeps its own context through its wait states. The bug is sneaky because it only shows up on transfers with wait states; zero-wait transfers happen to sample the right value, so it passes naive tests. This capture-then-act discipline, gated by HREADY, is the foundation under every slave output." The pipelining rationale, the captured signals, and the HREADY-gated enable with the wait-state reasoning are the senior signals.

10. Practice Challenge

Build and reason from address/control capture.

  1. Why capture. Explain why the slave must register the address-phase control instead of using the bus signals in the data phase (the pipelining reason).
  2. What's captured. List the captured signals (sel_q, write_q, addr_q, size_q, burst_q, prot_q) and what each is for; define the qualified select.
  3. Read the waveform. From Figure 2, explain how addr_q holds A through A's wait state and only updates to B when A completes.
  4. The HREADY gate. Explain why the capture must be gated by HREADY, the free-running-capture bug, and why it hides in zero-wait tests.
  5. Foundation. Explain how the captured copies feed every slave output (HREADYOUT, HRDATA, HRESP, write path).

11. Key Takeaways

  • AHB is pipelined, so the address/control is valid in the address phase, one cycle before the data phase where the slave acts — so the slave must register it and use the copies one cycle later.
  • Captured signals: the qualified select (sel_q = HSEL && real HTRANS), write_q, addr_q, and as needed size_q, burst_q, prot_q. HWDATA is not captured (it's a data-phase signal).
  • The capture enable is HREADY highnot free-running. A free-running capture overwrites the in-progress transfer's context during a wait state (the master is already driving the next address), corrupting the waited access.
  • The bug hides in zero-wait tests — it only manifests on transfers with wait states; the HREADY gate must mirror the master's advance condition.
  • The captured copies feed every slave outputHREADYOUT, HRDATA, HRESP, and the write/read paths all read the _q signals. Capture is the foundation.
  • It's universal and subtle — the same pattern in every slave, the locus of pipeline-correctness, and an ideal reusable block (chapter 16.11).

12. What Comes Next

You now have the capture discipline that underlies every slave output. The next chapters build the slave's sequential control — the FSMs:

  • Write FSM (next) — design the slave write-side FSM.
  • Read FSM and Bridge FSM (RTL) — the slave's read-side and bridge control.

To revisit the pipeline this bridges, see Pipelined Operation and The Address / Control Phase; to see the capture in a full slave, see A Simple AHB-Lite Slave.