Quartus® Prime Pro Edition User Guide: Timing Analyzer

ID 683243
Date 11/26/2024
Public
Document Table of Contents

3.1.3.3. Identifying Synchronizer CDC Issues

The use of synchronizers is common in digital design to enable reliable communication and data integrity across different clock domains.

However, improper synchronizer implementation is a common cause of CDC issues. For correct synchronizer implementation, you must ensure the following:

  • The destination of an asynchronous transfer forms a chain of two or more registers, with each register in the same clock domain as the destination of the transfer.
  • No combinational logic is present between any of the registers in the chain.
  • No combinational logic is present on the path to the first register in the chain.
Figure 198. Synchronizer Example


The following Verilog HDL and VHDL examples show how to define a three-stage synchronizer. These synchronizers take an asynchronous input signal from one clock domain, and then produce a synchronized output signal for use in another clock domain.

Both examples implement the synchronizer as a chain of three flipflops (sync_ff). The asynchronous input signal ( async_in) is captured by the first flipflop on the rising edge of the clock signal (clk) of the destination domain. The signal then propagates through the second and third flipflops, with each stage providing additional time for the signal to stabilize. The output of the third flipflop (sync_out) is then used within the destination clock domain, significantly reducing the risk of metastability.

Three-Stage Synchronizer Example (Verilog HDL)

module three_stage_synchronizer (
    input wire clk,          // Clock signal of the destination domain
    input wire async_in,     // Asynchronous input signal from the source domain
    output reg sync_out      // Synchronized output signal for the destination domain
);

reg [2:0] sync_ff; // 3 flip-flops for the synchronizer chain

always @(posedge clk) begin
    sync_ff[0] <= async_in;       // First stage captures the asynchronous input
    sync_ff[1] <= sync_ff[0];     // Second stage
    sync_ff[2] <= sync_ff[1];     // Third stage
end
assign sync_out = sync_ff[2];       // Output from the third stage

endmodule

Three-Stage Synchronizer Example (VHDL)

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity three_stage_synchronizer is
    Port (
        clk : in STD_LOGIC;           -- Clock signal of the destination domain
        async_in : in STD_LOGIC;      -- Asynchronous input signal from the source domain
        sync_out : out STD_LOGIC      -- Synchronized output signal for the destination domain
    );
end three_stage_synchronizer;
architecture Behavioral of three_stage_synchronizer is
    signal sync_ff : STD_LOGIC_VECTOR(2 downto 0); -- 3 flip-flops for the synchronizer chain
begin

    process(clk)
    begin
        if rising_edge(clk) then
            sync_ff(0) <= async_in;       -- First stage captures the asynchronous input
            sync_ff(1) <= sync_ff(0);     -- Second stage
            sync_ff(2) <= sync_ff(1);     -- Third stage
        end if;
    end process;

    sync_out <= sync_ff(2);       -- Output from the third stage

end Behavioral;

The following topics describe how to identify and constrain CDCs in synchronizers.