A register block on a configuration bus answers most reads in one cycle. One of its registers, a counter in another clock domain, needs four cycles to read safely. The bus has to let that register take longer without slowing every other access, and without the processor reading a half-updated value.
How can a target slow down one transfer without adding a whole new handshake?
One obvious answer is a fixed latency long enough for the slowest register: every read takes four cycles. Every fast register now pays for the slow one. The opposite answer is valid-only (lesson 3.1): the target must answer in one cycle, which the slow register cannot do. What is wanted sits in between: one cycle when possible, more only when needed, decided by the target, transfer by transfer.
In a wait state scheme, the initiator starts a transfer and keeps every signal steady; the target signals "done" when it is ready. Each cycle the target is not done is a wait state, and the transfer simply lasts longer. Only one transfer is in flight, so there is nothing to buffer and nothing to reorder: the initiator just waits.
A clock-stretching scheme does the same on a bus where the initiator drives the clock: the target holds the clock line in its waiting state, and the initiator cannot advance to the next bit until the target lets go.
Both are back-pressure, like valid/ready, but simpler: back-pressure on the current transfer only, because the protocol allows no more than one at a time.
This is the APB write and read from lesson 0.4, simulated. The write takes one wait state; the read takes none.
Slot 2: the write is in its access phase but pready is low: a wait state. Address and data must stay exactly as they are.
Slot 3: pready is high, so the write completes at the edge that ends slot 3, one cycle later than it could have.
Slots 4 and 5: the read's completer is ready immediately, so the read takes only the two mandatory cycles.
The slow counter register from the opening would hold PREADY low for three cycles; every other register keeps answering in the minimum time.
I2C's wires are open-drain: any device can pull a line low, and the line is high only when nobody pulls it. That wired-AND behaviour is what makes stretching free: the master releases SCL to let it go high, notices it is still low, and waits. No extra signal is needed.
Scheme | What it costs | When it wins |
|---|---|---|
Fixed latency | Every transfer pays the slowest target's time | All targets equally fast |
Wait states (target signals done) | One extra signal; the initiator is blocked while it waits; one transfer at a time | Register buses: simple targets, low traffic |
Clock stretching | Nothing extra on open-drain buses; the whole bus waits | Slow multi-drop buses where the initiator drives the clock |
valid/ready handshakes (lesson 3.3) | A handshake per channel | Streams and buses that keep several transfers moving |
The limitation of wait states is the same one that makes them simple: while the target waits, everything waits. The initiator cannot start the next transfer, even to a different, fast target. Buses that need more throughput separate the request from the response (lesson 5.5) so other transfers can proceed.
Protocol | Its push-back mechanism |
|---|---|
APB | Wait states: the access phase lasts until the completer drives PREADY high; address, control and write data stay constant meanwhile. PREADY arrived in APB3; earlier APB had no wait states. |
I2C | Clock stretching: a slave may hold SCL low, and the open-drain wiring makes the master wait. |
A completer drives PREADY low forever after a bug in its state machine (illustrative). Because APB allows any number of wait states, the processor's access never completes, the processor stalls, and the whole system hangs with no error. Wait-state protocols need a timeout somewhere: a bus monitor that ends a transfer after a maximum number of wait states and reports an error (Part 9). The scheme's simplicity, "just wait until done", is also its risk: nothing in the protocol limits how long "until" is.
The completer may capture them on the edge that finally completes the transfer, which it chooses. The requester does not know which edge that will be, so it must hold them until completion.
Only one transfer is in flight. While one slow target holds the transfer open, the initiator cannot start anything else, even to fast targets.
Open-drain (wired-AND) lines: any device pulling SCL low keeps it low, so the slave can hold it low against the master.
Wait states let the target hold the current transfer open until it is ready; clock stretching does the same when the initiator drives the clock.
They are back-pressure on one transfer at a time: simple, but the initiator is blocked while it waits.
Unbounded waiting needs a timeout somewhere, or one stuck target hangs the system.