Modern digital systems commonly use multiple clock domains with different frequencies and phase relationships. This allows for interfacing with different functional blocks running at different speeds (e.g., CPU vs. peripherals), etxernal interfaces needing specific clocks (e.g., HDMI, Ethernet, DDR), aynschronous inputs from buttons or sensors, and IP blocks that operate using their own independent clocks. Whenever signals or data are transferred between clock domains that are not guaranteed to be synchronized, a Clock Domain Crossing (CDC) occurs. CDC introduces several important design challenges, including metastability, data loss, data corruption, and timing uncertainty. These issues must be carefully addressed to ensure reliable operation across the entire system.
Metastability occurs when a flip-flop's setup or hold-time requirements are violated, typically when an asynchronous signal changes close to the active edge of the receiving clock. In this situation, the flip-flop may temporarily enter a metastable state in which its output does not resolve immediately to a valid logic 0 or 1. Although a metastable output will eventually resolve to a stable logic level, the resolution time is unpredictable. If the signal is used directly by downstream logic, metastability can propagate and potentially cause incorrect behavior. CDC synchronization techniques reduce the probability of metastability propagating into the receiving clock domain by providing additional time for the signal to resolve.
Data can be lost or corrupted when signals are transferred between asynchronous clock domains without an appropriate synchronization mechanism. The behavior depends on the type of signal and the relative clock frequencies. For example, a pulse generated in a fast clock domain may be too short for a slower clock domain to observe, resulting in a missed event. Conversely, transferring multi-bit data without ensuring that all bits are captured consistently can cause the receiving domain to observe a mixture of old and new values. Different CDC structures are therefore required depending on whether the design is transferring a single-bit level, a pulse/event, multi-bit data, or a continuous stream of data.
Proper CDC design is essential for building reliable and robust digital systems. The appropriate synchronization technique depends on the type of signal being transferred, the relationship between the clock domains, the required throughput, and the acceptable latency This repository provides implementations and examples of several commonly used CDC techniques, including:
Toggle Synchronizer — used to reliably transfer events or pulses between asynchronous clock domains. Multi-Bit Synchronizer — used to transfer multi-bit data while maintaining data consistency across clock domains. Asynchronous FIFO — used to safely transfer streams of data between independent clock domains while providing buffering and independent read/write control.
Each CDC implementation includes its own documentation, RTL design, testbench, and script to run simulation and generate waveforms. Refer to the individual component's README for details on its architecture, operation, limitations, and verification methodology.