When to use it
Any time a 1-bit level crosses from another clock domain (or an external pin like a button) into yours, sample it through two flip-flops before any logic looks at it. Feed a raw asynchronous signal straight into your design and it will eventually change too close to a clock edge, violating setup/hold, and the capturing flop goes metastable, hovering between 0 and 1.
How it works
The first flop may go metastable, but it is given a full clock cycle to settle
before the second flop samples it. By the time sync_out feeds your logic, the odds
of it still being undecided are astronomically small.
Gotchas
- This is for level signals. To cross a pulse or a multi-bit bus you need a toggle synchronizer or a gray-coded handshake, not this.
- Never fan the raw async signal out to more than one synchronizer, each destination might resolve differently. Synchronize once, then distribute.