Ten related signals crossing as ten synchronisers are ten chances to mix old and new values, ten constraint entries, and ten rows to keep correct. The same ten signals crossing as one handshake with a data bus are one protocol with one proof. Fewer crossings are not just tidier; each removed crossing removes a whole failure mode.
Instead of... | Cross... |
|---|---|
Several event pulses in the same direction | One toggle or handshake carrying an event code; the destination decodes it. |
Data plus a separate valid pulse | One handshake where the data is held stable and the request is the valid. |
A counter mirrored across the boundary | Gray code for a monotonically stepping pointer, or a handshake for a value that can jump (see do not synchronise buses bit by bit). |
Scattered status flags from one block | One status word captured with a single load pulse. |
A continuous wide stream | One asynchronous FIFO (see async FIFO). |
A DMA engine needs to tell the control domain that a transfer finished, which descriptor completed, and whether an error occurred. Three pulses (done, descriptor index changed, error flag) can arrive skewed. One handshake returning a completion word with the descriptor number and an error bit cannot skew: the word is captured whole when the request arrives.
A sensor block streams 16-bit samples with a data-ready strobe into a slower domain. A per-sample pulse plus a synchronised bus tears under skew. One small asynchronous FIFO takes the stream; the ready strobe disappears entirely because FIFO-not-empty is the ready signal.
The reviewer groups the inventory by source-destination pair and asks of each group: could these cross as one protocol? Every surviving singleton needs a reason, such as genuinely independent single-bit flags with no timing relationship.
The three signals have independent synchroniser delays, so the destination can pair a new request with the old address. The address must be held stable and captured by the handshake, not synchronised on its own.