Structs

  • A BitSynchronizer is used to move signals that are asynchronous to a clock into that clock domain using a pair of back-to-back flip-flops. While the first flip flop may become metastable, the second one is likely to be stable.
  • A SyncReceiver works together with a SyncSender to transmit data from one clock domain to another (in one direction). To use a SyncReceiver wire up the [sig_cross], [flag_in] and [ack_out] signals between the two.
  • When you need to send many bits between two clock domains, it is risky to use a vector of BitSynchronizer structs. That is because, you cannot guarantee at any given moment that all of the bits of your multi-bit signal will cross into the new clock domain at once. So to synchronize a multi-bit signal, use a SyncSender and SyncReceiver pair. These widgets will use a set of handshake signals to move a value from one clock domain to another safely. Note that while the state machine is executing, the synchronizer will indicate it is busy. Crossing clock domains with greater ease is best done with an [AsynchronousFIFO].
  • A VectorSynchronizer uses a SyncSender and SyncReceiver in a matched pair to transmit a vector of bits (or any Synth type from one clock domain to a second clock domain without metastability or data corruption. You can think of a VectorSynchronizer as a single-element asynchronous FIFO, and indeed [AsynchronousFIFO] uses the VectorSynchronizer internally.