AMBA AHB · Module 16
HREADYOUT Generation
Implementing correct per-slave HREADYOUT timing — the slave output saying 'I can complete the current transfer this cycle' (high) or 'insert a wait state' (low). A zero-wait slave ties it high; a wait slave drives it from a counter/FSM modeling the access latency. Crucially, HREADYOUT (the slave's output) is not HREADY (the shared input — the selected slave's HREADYOUT routed back to all); gate the address-phase capture on HREADY, not your own HREADYOUT, and never drive HREADYOUT high before genuinely ready.
The last three chapters built whole slaves; this chapter zooms in on the single most timing-critical output a slave drives: HREADYOUT. Every AHB slave drives a HREADYOUT that answers one question each cycle — "can I complete the current transfer this cycle?" High means yes, finish now; low means no, insert a wait state (hold the master — chapter 6.2). A zero-wait slave (the simple slave, the register bank) ties HREADYOUT high — it's always ready. A wait-inserting slave (the memory slave, a slow peripheral) drives HREADYOUT from a small counter or FSM that models the access latency — low while the access is in progress, high in the cycle it can genuinely finish. The chapter's other half is a crucial distinction most beginners get wrong: HREADYOUT (the slave's output) is not HREADY (the slave's input). HREADY is the shared bus-ready signal — the interconnect selects the addressed slave's HREADYOUT and routes it back to every slave (and the master), so all slaves know when the current bus transfer actually completes (HREADY vs HREADYOUT). This chapter implements correct HREADYOUT generation — the timing contract at the heart of every slave.
1. What Is It?
HREADYOUT generation is the slave logic that drives the HREADYOUT output — the slave's per-cycle statement of whether it can complete the current transfer. Its parts:
- The meaning —
HREADYOUThigh = "I can complete the current transfer this cycle"; low = "not ready — insert a wait state" (hold the master). - Zero-wait — a slave that always responds in one cycle ties
HREADYOUThigh (no logic needed). - Wait-inserting — a slave with latency drives
HREADYOUTfrom a counter/FSM modeling the access: low while not ready, high when ready. - HREADYOUT ≠ HREADY —
HREADYOUTis the slave's output;HREADYis the shared input (the selected slave'sHREADYOUTrouted back to all slaves and the master).
So HREADYOUT generation is the slave's timing contract: it tells the bus, every cycle, whether the slave is done (high) or needs more time (low). For a zero-wait slave, this is trivial — tie it high (the slave is always ready, so it never stalls the bus). For a wait-inserting slave, it's the core timing logic — a counter or FSM that models how many cycles the access needs and drives HREADYOUT low for the wait cycles, high in the cycle the access completes. The discipline is twofold: (1) drive HREADYOUT high only in the cycle the slave can genuinely finish (too early → the master samples garbage; chapter 16.3), and (2) don't confuse HREADYOUT (output) with HREADY (input). So HREADYOUT generation is the timing heart of a slave — the signal that paces every transfer. So it's the most timing-critical slave output.
2. Why Does It Exist?
HREADYOUT exists because the bus protocol is fixed-rhythm (one transfer advances per cycle when ready), but slaves have varying speeds — so each slave needs a per-cycle signal to say "ready" or "not ready", and the bus needs to combine these into a single shared pace.
The per-slave ready signal is the root: the bus advances a transfer when the addressed slave is ready. But slaves differ — a fast SRAM is ready immediately, a slow flash needs cycles, a busy peripheral may stall. So each slave needs a way to say, each cycle, whether it's ready — and that's HREADYOUT. So HREADYOUT exists as the slave's per-cycle ready statement. So the bus can know when this slave is done. So it's the slave's pace signal.
The shared bus pace drives the HREADY distinction: the bus has one master pacing one transfer at a time, but many slaves. Only the addressed slave's readiness matters for the current transfer — yet every slave (and the master) needs to know when the current transfer completes (to advance their own pipelines correctly). So the interconnect selects the addressed slave's HREADYOUT and broadcasts it as the shared HREADY — the one signal that paces the whole bus. So HREADYOUT (per-slave) and HREADY (shared) exist as two signals: each slave drives its HREADYOUT, the interconnect combines them (by selection) into the shared HREADY, and everyone receives HREADY. So the two-signal structure exists to turn many per-slave readinesses into one shared bus pace. So it's per-slave out, shared in. So the distinction is structural.
The correct timing requirement is why generation is delicate: because HREADYOUT paces the transfer, getting its timing right is critical. Drive it high too early (before the data is ready) and the master samples garbage (corruption). Drive it low forever (stuck) and the bus hangs (chapter 18.1). Drive it low on an idle cycle (unqualified) and you stall the bus needlessly. So HREADYOUT generation must be precisely timed — high exactly when ready, low only for genuine waits on real transfers. So the logic (tie-high for zero-wait, counter/FSM for waits) exists to get this timing right. So HREADYOUT exists because: the bus advances on slave readiness (the per-slave ready signal — the why); the bus needs one shared pace from many slaves (the interconnect selects and broadcasts the addressed slave's HREADYOUT as the shared HREADY — the two-signal structure); and the timing must be precise (high exactly when ready, low only for real waits — driving the careful generation logic). So HREADYOUT is the slave's contribution to the bus's pace — the per-cycle "ready/not-ready" that, selected and broadcast as HREADY, paces every transfer on the bus. So generating it correctly is foundational to a working slave. So this chapter gets the pace signal right.
3. Mental Model
Model HREADYOUT as each chef in a kitchen raising or lowering a "dish ready" paddle — paddle up means "this dish is plated, send it out now", paddle down means "still cooking, the waiter must wait". The head waiter (the interconnect) watches only the chef cooking the current order (the addressed slave) and rings a single shared bell (HREADY) when that chef's paddle is up — and everyone in the kitchen hears the bell, so they all know the current order just went out.
A kitchen of chefs (the slaves), each cooking to order. Each chef has a "dish ready" paddle (HREADYOUT). When a chef's dish is plated and ready, they raise the paddle (HREADYOUT high) — "send it out now". When the dish is still cooking, the paddle stays down (HREADYOUT low) — "the waiter must wait". A fast chef (a zero-wait slave) always has the paddle up — their dishes are instant (the paddle is nailed up). A slow chef (a wait-inserting slave) keeps the paddle down while cooking and raises it the moment the dish is done — and they know how long each dish takes (a counter/FSM modeling the latency). Now, the head waiter (the interconnect) is handling one order at a time, and watches only the chef cooking that order (the addressed slave). When that chef's paddle goes up, the head waiter rings a single shared bell (HREADY) — "the current order is ready, it's going out". Crucially, everyone in the kitchen hears the bell — all the chefs, and the expediter (the master). They need to hear it: the bell tells them the current order just completed, so they can advance — start prepping the next order, clear the pass, etc. So the paddle is each chef's own signal (raise it when your dish is ready), but the bell is the shared signal (rung from the current chef's paddle, heard by all). A chef must not raise the paddle before the dish is actually ready — sending out a half-cooked dish (the master sampling garbage). And a chef shouldn't keep the paddle down when there's no order for them (stalling the pass needlessly — an unqualified wait on an idle cycle).
This captures HREADYOUT: each chef's paddle = each slave's HREADYOUT output; paddle up = HREADYOUT high (ready, complete now); paddle down = HREADYOUT low (wait state); the always-up paddle = a zero-wait slave (tie high); the slow chef raising it when done, knowing the cook time = a wait slave's counter/FSM; the head waiter watching only the current chef = the interconnect selecting the addressed slave's HREADYOUT; the single shared bell heard by all = the shared HREADY broadcast to every slave and the master; not raising the paddle on a half-cooked dish = not driving HREADYOUT high before ready (no garbage); not holding the paddle down with no order = qualifying waits to a real selected transfer. Each chef's own paddle, one shared bell rung from the current chef's.
Watch a zero-wait slave and a wait-inserting slave drive HREADYOUT, and the shared HREADY follow the selected one:
Per-slave HREADYOUT and the shared HREADY
5 cyclesThe model's lesson: each slave drives its own HREADYOUT paddle; the shared HREADY is rung from the currently-addressed slave's paddle and heard by all. In the waveform, the shared HREADY follows whichever slave is addressed — high for zero-wait A, then low-then-high for wait-inserting B.
4. Real Hardware Perspective
In hardware, HREADYOUT is a single output wire driven either by a constant (zero-wait) or by a small counter/FSM (wait-inserting); the interconnect builds the shared HREADY by muxing the addressed slave's HREADYOUT; and the slave consumes HREADY to pace its own pipeline.
The zero-wait tie-high: for a slave that always completes in one cycle (the simple slave 16.1, the register bank 16.2 — combinational read, single-cycle write), HREADYOUT is tied high (assign HREADYOUT = 1'b1;). No logic, no flop — the slave is always ready. So in hardware, a zero-wait slave's HREADYOUT is a constant. So it costs nothing. So zero-wait is the cheap case.
The wait-inserting counter/FSM: for a slave with latency (the memory slave 16.3, a slow peripheral), HREADYOUT is driven by a small counter or FSM. When a real access starts (sel_q and a transfer in the data phase), the slave drives HREADYOUT low and counts the access latency; while counting, HREADYOUT stays low (wait states); when the count expires (the access can complete), HREADYOUT goes high for one cycle (completing the transfer), then the slave is ready for the next. The FSM ensures HREADYOUT is low exactly for the wait cycles and high exactly when ready. So in hardware, a wait slave's HREADYOUT is sequential logic modeling the latency. So it's a counter/FSM. So waits cost a little logic.
The interconnect mux and the HREADY input: the interconnect forms the shared HREADY by selecting the addressed slave's HREADYOUT — HREADY = HREADYOUT[selected_slave] (a mux driven by the address decode — chapter 13.7, HREADY aggregation). This HREADY is broadcast to all slaves and the master. Each slave consumes HREADY as an input — it tells the slave when the current bus transfer completes, which the slave needs to advance its own address-phase capture correctly (recall 16.1: the slave captures the address-phase context gated on HREADY high — because the address phase is only valid to capture when the previous transfer is completing). So in hardware, HREADY is a separate input the slave uses to pace its capture — distinct from the HREADYOUT it drives. So in hardware, HREADYOUT generation is a constant (zero-wait) or a counter/FSM (wait), the interconnect muxes the addressed HREADYOUT into the shared HREADY, and the slave consumes HREADY to pace its capture. The two signals — HREADYOUT out, HREADY in — are physically distinct wires with distinct roles. So in hardware, keep them separate. So the wiring distinguishes them.
5. System Architecture Perspective
At the system level, HREADYOUT/HREADY is the bus's flow-control mechanism — the way the single shared bus paces itself to the speed of whichever slave is currently addressed — and its correctness is foundational: a single mistimed or stuck HREADYOUT can corrupt data or hang the entire bus.
The bus flow control: HREADYOUT/HREADY is the flow-control signal of AHB — it's how the bus adapts its pace to the current slave. When a fast slave is addressed, HREADY is high and transfers fly by (one per cycle); when a slow slave is addressed, HREADY drops (wait states) and the bus slows to match. So at the system level, HREADYOUT/HREADY is the throttle — the mechanism that paces the bus to the addressed slave. So it's how the bus handles heterogeneous slave speeds. So it's the flow-control backbone.
The single-point criticality: because HREADY is shared and paces the whole bus, a single slave's HREADYOUT bug has system-wide consequences. If one slave drives HREADYOUT high too early, the master samples garbage on that slave's transfers (data corruption). If one slave gets stuck with HREADYOUT low (a hung FSM, a missed completion), the shared HREADY (when that slave is addressed) is stuck low — and the entire bus hangs (the master waits forever — chapter 18.1, stuck HREADY). So at the system level, every slave's HREADYOUT must be correct — a single faulty slave can break the whole bus. So HREADYOUT correctness is a system property, not a local one. So it's a single point of failure. So get every slave's HREADYOUT right.
The timeout protection: because a stuck HREADYOUT hangs the bus, systems often add a timeout/watchdog — if HREADY stays low too long (a slave that never completes), a bus watchdog triggers an error/recovery (rather than hanging forever). So at the system level, the risk of a stuck HREADYOUT is mitigated by timeout logic. So robust systems guard against the single-point failure. So at the system level, HREADYOUT/HREADY is the bus's flow-control mechanism (the throttle pacing the bus to the addressed slave — adapting to heterogeneous speeds), its correctness is a system property (a single mistimed HREADYOUT corrupts data; a single stuck one hangs the whole bus — chapter 18.1), and robust systems add timeout/watchdog protection against stuck-ready hangs. So HREADYOUT is where a local slave decision becomes a global bus behavior — making its correct generation one of the most consequential pieces of slave RTL. So pace correctly, never stick, and guard with timeouts.
6. Engineering Tradeoffs
HREADYOUT generation embodies the ready/not-ready, per-slave-vs-shared, precisely-timed design.
- Tie-high (zero-wait) vs counter/FSM (wait). Tie-high is free and fast (no logic) but requires the slave to truly be single-cycle; a counter/FSM handles latency at the cost of sequential logic. Tie high only if genuinely zero-wait.
- Combinational vs registered HREADYOUT. A combinational
HREADYOUT(derived from current state) can respond fast but may create long paths / timing pressure; a registeredHREADYOUTeases timing but must be planned a cycle ahead. Choose by timing closure. - Drive high exactly when ready vs conservatively late. Driving
HREADYOUThigh exactly when ready maximizes performance but demands precise latency modeling; an extra wait (conservative) is safe but slower. Be precise, but never early. - Per-slave correctness vs system robustness. Relying on every slave's
HREADYOUTbeing correct is the ideal but fragile (one bug hangs the bus); adding a bus timeout/watchdog costs logic but contains the failure. Add a timeout in robust systems.
The throughline: HREADYOUT is the slave's per-cycle output stating whether it can complete the current transfer — high to finish now, low to insert a wait state (hold the master — chapter 6.2). A zero-wait slave ties it high; a wait-inserting slave drives it from a counter/FSM modeling the access latency (low while not ready, high when ready). It must be driven high only when the slave can genuinely finish (too early → garbage; chapter 16.3) and never stick low (hangs the bus; chapter 18.1). Critically, HREADYOUT (the slave's output) is not HREADY (the shared input — the interconnect selects the addressed slave's HREADYOUT and broadcasts it to all slaves and the master). Qualify wait insertion to a real selected transfer. It's the bus's flow-control signal — local correctness with system-wide consequence.
7. Industry Example
Trace HREADYOUT across a fast SRAM, a slow flash, and the interconnect that combines them.
A system has a zero-wait SRAM (Slave A) and a 4-cycle flash (Slave B) on the bus.
- SRAM (Slave A) — tie-high. The SRAM is single-cycle, so
HREADYOUT_A = 1always (tied high). When the master addresses A, the interconnect selectsHREADYOUT_Aas the sharedHREADY— which is high — so A's transfers complete one per cycle. No wait logic. - Flash (Slave B) — counter FSM. The flash needs 4 cycles. When the master addresses B with a real read (
sel_qand a transfer), B's FSM drivesHREADYOUT_Blow and loads a 3-count; for 3 cyclesHREADYOUT_Bstays low (3 wait states); on the 4th cycle (data ready),HREADYOUT_Bgoes high, completing the read. The FSM models the flash's latency exactly. - The interconnect — select and broadcast. The interconnect forms the shared
HREADYby selecting the addressed slave'sHREADYOUT: when A is addressed,HREADY = HREADYOUT_A; when B is addressed,HREADY = HREADYOUT_B. The sharedHREADYis broadcast to A, B, and the master. SoHREADYis high during A's transfers and low-for-3-then-high during B's. - The slaves consume HREADY. Both A and B use the shared
HREADY(not their ownHREADYOUT) to gate their address-phase capture — they sample the next address phase only whenHREADYis high (the current transfer completing). So even Slave A, while B is mid-wait and B is addressed, paces its pipeline by the sharedHREADY. - A stuck-ready guard. A bus watchdog watches
HREADY: if it stays low for, say, 256 cycles (a slave that never completes — a flash fault), the watchdog triggers an error, preventing a permanent hang.
The example shows HREADYOUT across the speed spectrum and the per-slave/shared distinction: the SRAM ties it high (zero-wait), the flash drives it from a counter FSM (4-cycle latency), the interconnect selects and broadcasts the addressed slave's HREADYOUT as the shared HREADY, the slaves consume HREADY (not HREADYOUT) to pace their capture, and a watchdog guards against a stuck-ready hang. This is HREADYOUT generation in a real multi-slave system. This is the bus's flow control.
8. Common Mistakes
9. Interview Insight
HREADYOUT generation is a sharp RTL interview topic — the high/low meaning, the zero-wait-vs-counter distinction, and especially the HREADYOUT-vs-HREADY separation are the signals.
The answer that lands gives the meaning and the distinction: "HREADYOUT is the slave's output that says, each cycle, whether it can complete the current transfer — high means I can finish this cycle, low means insert a wait state and hold the master. A zero-wait slave, like a simple register slave, just ties HREADYOUT high — it's always ready. A slave with latency, like a memory slave on a slow flash, drives HREADYOUT from a small counter or FSM that models the access latency: low while the access is in progress, high in the cycle it can genuinely complete. Two things are critical. First, you drive HREADYOUT high only when you're truly ready — if you drive it high before the data is ready, the master samples garbage, a data-corruption bug. And you must never get stuck low, because that hangs the whole bus. Second — and this is the one people get wrong — HREADYOUT is not HREADY. HREADYOUT is this slave's output, its own readiness. HREADY is the shared bus-ready input: the interconnect selects the currently-addressed slave's HREADYOUT and routes it back to every slave and the master. A slave drives HREADYOUT to control its own transfers, but consumes HREADY to know when the current bus transfer completes — and it gates its address-phase capture on HREADY, the bus's pace, not on its own HREADYOUT. If you mix them up and gate on HREADYOUT, you mis-time the slave's pipeline — a subtle bug that hides in a single-slave testbench and surfaces in a real multi-slave system. So: output your readiness as HREADYOUT, input the bus pace as HREADY." The high/low meaning, the zero-wait-vs-FSM, and the HREADYOUT/HREADY separation are the senior signals.
10. Practice Challenge
Build and reason from HREADYOUT generation.
- The meaning. State what
HREADYOUThigh and low mean, and how a zero-wait slave vs a wait-inserting slave drives it. - HREADYOUT vs HREADY. Explain the difference (output vs input), how the interconnect forms
HREADY, and who receives it. - Read the waveform. From Figure 2, explain how the shared
HREADYfollows the addressed slave (zero-wait A, then wait-inserting B). - Gate on HREADY. Explain why a slave gates its address-phase capture on
HREADY, not its ownHREADYOUT, and the bug otherwise. - Timing failures. Explain the consequences of driving
HREADYOUThigh too early, stuck low, and too late.
11. Key Takeaways
HREADYOUTis the slave's per-cycle output stating whether it can complete the current transfer — high = finish now; low = insert a wait state (hold the master — chapter 6.2).- Zero-wait slaves tie
HREADYOUThigh; wait-inserting slaves drive it from a counter/FSM modeling the access latency (low while not ready, high when ready). HREADYOUT(output) ≠HREADY(input) —HREADYOUTis this slave's own readiness;HREADYis the shared signal (the interconnect selects the addressed slave'sHREADYOUTand broadcasts it to all slaves and the master).- Gate address-phase capture on
HREADY, notHREADYOUT— the slave's pipeline must advance with the bus's pace; usingHREADYOUTmis-times capture (a subtle multi-slave bug). - Drive
HREADYOUThigh only when genuinely ready (too early → garbage — chapter 16.3) and never stick low (hangs the bus — chapter 18.1); qualify waits to a real selected transfer. - It's the bus's flow-control signal — a local slave decision with system-wide consequence; robust systems add a timeout/watchdog against stuck-ready hangs.
12. What Comes Next
You now can generate HREADYOUT correctly. The next chapters complete the slave's output paths:
- HRDATA Muxing (next) — build the read-data return path and the slave read mux.
- HRESP Generation, Address / Control Capture, and the FSMs — the rest of the slave RTL.
To revisit the wait-state mechanism HREADYOUT implements, see Slave-Inserted Wait States and HREADY vs HREADYOUT; for the slave this paces, see A Simple AHB-Lite Slave.