AMBA AXI · Module 3
Backpressure & Stalls
How a destination de-asserting READY stalls an AXI channel, inserts bubbles, and propagates upstream through a pipeline — and how buffering absorbs it.
READY isn't just "I'm ready" — its absence is a control signal in its own right. When a destination drops READY, it is applying backpressure: telling the source "hold — I can't take a beat this cycle." This is the universal flow-control mechanism of AXI: every channel can be throttled the same way, and in a chain of stages a single slow consumer can ripple a stall all the way back to the producer. This chapter shows backpressure on a waveform, explains the bubbles it inserts, traces how it propagates upstream, and shows how buffering absorbs it. It builds directly on the handshake (3.1) and the transfer event (3.2); throughput math is the next chapter.
1. Backpressure Is READY Saying "Not Yet"
From the handshake contract, a beat transfers only when VALID && READY at a clock edge. The destination therefore has a lever: by holding READY low, it prevents the transfer even though the source is offering. That deliberate withholding is backpressure — the receiver throttling the sender.
The source's obligation during backpressure is exactly the stability rule (3.1): hold VALID high and keep the payload stable until READY finally rises and the beat transfers. So backpressure is a clean, lossless stall — nothing is dropped; the beat simply waits. Because every AXI channel uses the same handshake, every channel supports backpressure identically: a subordinate can backpressure write data (WREADY low), a manager can backpressure read data (RREADY low), and so on. One mechanism, everywhere.
READY backpressure — the destination stalls the source
8 cycles2. Bubbles — The Cost of a Stall
Every cycle the handshake doesn't complete is a bubble: the clock ticks, but no beat moves (no transfer event, from 3.2). Backpressure inserts bubbles deliberately — they're the price of matching a fast source to a slower destination. In Figure 1, cycles 2–4 are three bubbles: D1 sat waiting, moving no data, while the clock advanced.
Bubbles are not a bug — they're how flow control works — but they are exactly the lost throughput from Chapter 1.6: beats-per-cycle drops below one whenever a bubble appears. A channel running at full bandwidth has zero bubbles (a beat every edge); a backpressured channel trades bandwidth for the ability to not overrun a slow receiver. The whole point of buffering (below) and of throughput tuning (next chapter) is to minimize avoidable bubbles while keeping the lossless stall when a bubble is genuinely necessary.
3. Backpressure Propagates Upstream
Here's the behaviour that makes backpressure a system property, not a local one. Real datapaths are chains of stages, each connected to the next by a VALID/READY handshake. When the final consumer backpressures, the stall doesn't stay local — it ripples upstream:
- The consumer drops its
READY, so the last stage can't hand off its beat. - That stage, now holding a beat it can't drain, fills up — so it drops its input
READY. - The stage before it can't hand off either, fills, and drops its
READY— and so on, back toward the producer.
So a single slow consumer can, stage by stage, stall the entire pipeline back to the source. This is head-of-line blocking in its simplest form: the slowest point throttles everyone upstream of it.
4. Buffering Absorbs Transient Backpressure
If every consumer stall instantly froze the producer, throughput would be hostage to the slowest momentary hiccup. The fix is buffering: place a FIFO (or a skid buffer) between producer and consumer. The buffer absorbs transient backpressure — while the consumer is briefly not ready, beats pile into the buffer and the producer keeps running. Only if the buffer fills completely does backpressure finally reach the producer.
A pipeline stage's accept/offer logic captures the propagation precisely — it accepts input only when it can drain or has room, which is exactly how a stall ripples back:
// Conceptual — one buffered stage. Downstream backpressure (out_ready low)
// propagates to in_ready once the stage can't drain and has no room.
assign out_valid = occupied; // I offer a beat when I hold one
assign in_ready = !occupied || out_ready; // accept if empty, or I can drain now
// STALL case: occupied && !out_ready → in_ready = 0 → upstream is backpressuredBuffering doesn't make backpressure disappear — a sustained slow consumer will still eventually stall the producer once buffers fill. It hides transient stalls. (The skid buffer and FIFO designs that do this without losing throughput are Module 15.)
5. Reactive vs Speculative READY
A subtlety worth knowing: a destination can drive READY two ways. Reactive READY waits to see VALID before asserting — simple, but it costs a cycle of latency on each transfer because the destination only commits to accept after observing an offer. Speculative (or always-ready) READY is asserted ahead of VALID — the destination declares "I can take a beat whenever one arrives," so a transfer happens the instant VALID rises, with no acceptance latency.
Both are legal (recall 3.1: READY may depend on VALID, but need not). The trade-off is latency vs simplicity/area: always-ready gives the best latency and throughput but requires the destination to genuinely always have room (often backed by a buffer); reactive READY is simpler but inserts bubbles. This is a knob designers turn when tuning a path — and a thing to recognize on a waveform when reasoning about why a transfer took an extra cycle.
6. Common Misconceptions
7. Debugging Insight
8. Verification Insight
9. Interview Questions
10. Summary
Backpressure is a destination withholding READY to stall a source — AXI's universal, lossless flow control. The source obeys the stability rule (hold VALID and payload steady), so no beat is lost; the stall simply inserts bubbles (cycles with no transfer event), trading bandwidth for rate-matching. Crucially, backpressure is a system property: in a chain of VALID/READY stages it propagates upstream — a stalled consumer fills the last stage, which backpressures the previous one, rippling all the way to the producer (head-of-line blocking). Buffering (FIFOs, skid buffers) absorbs transient backpressure so the producer keeps running until a buffer fills — it hides hiccups, not a sustained rate mismatch. And a destination can drive READY reactively (simpler, +1 cycle latency) or speculatively/always-ready (lowest latency, needs guaranteed room).
For debugging, follow the backpressure downstream to its origin — the stalled producer is a symptom; the true bottleneck is the stage whose READY is low while its own downstream is ready. For verification, inject random per-channel backpressure and pair it with stability and liveness checks, since always-ready testing is a false pass. With the stall mechanism understood, the next chapter turns it into numbers: how back-to-back transfers and bubbles set sustained throughput.
11. What Comes Next
You understand the stall; now quantify it:
- 3.4 — Handshake Throughput (coming next) — connecting back-to-back transfer events and bubbles to sustained throughput.
- 3.5 — Handshake Dependency & Deadlock Rules (coming soon) — the cross-channel dependency graph that keeps decoupled, backpressured channels from deadlocking.
Previous: 3.2 — The Transfer Event. For the broader protocol catalog, see the AMBA family overview doc.