FPGA learning notes -- single bit signal synchronization in cross clock domain (CDC) design

FPGA learning notes - cross clock domain (CDC) design

   Clock Domain Crossing (CDC) refers to that there are two or more asynchronous clock domains in the design. At present, the problem of cross clock domain design is often faced by logic designers. The method to solve this kind of problem is called CDC technology, that is, cross clock domain technology.
   when transmitting signals across clock domain boundaries, there may be two situations. Determining which situation is very important for design:
  (1). Allow data loss when passing between clock domains.
  (2). Each signal transmitted between clock domains must be sampled.
   the first case: sometimes it is not necessary to sample each value, but the sampling value must be accurate. An example is the gray code counter set used in standard asynchronous FIFO design. In a properly designed asynchronous FIFO model, the synchronous gray code counter does not need to capture each legal value from the opposite clock domain, but it is essential that the sampling value must be accurate to identify when full and empty conditions occur.
   the second case: before allowing the change of CDC signal, the CDC signal must be correctly identified or identified and confirmed.
   in both cases, the CDC signal will need some form of synchronization to enter the receiving clock domain.
   cross clock domain synchronization of asynchronous signals. It is generally divided into single bit control signal synchronization and multi bit data signal synchronization. Multi bit signal synchronization will be completed by holding register, handshake or asynchronous FIFO, and single bit signal synchronization is the design basis of clock seamless switching circuit and asynchronous FIFO circuit. Here we first introduce single bit signal synchronization processing.

Single bit signal synchronization

1, Level synchronizer

   the most common synchronizer is to use two-level registers, that is, to synchronize by using two beats of registers, that is, the so-called level synchronizer. As shown in the figure below

   in the level synchronizer, the signal across the clock domain shall maintain the high level or low level for more than two clock cycles in the receiving domain. The signal after synchronization is in the form of level, and the number of clock cycles maintained by this level is the number of times it is detected by the rising edge during the cross clock domain. After each synchronization, the input signal shall be restored to the invalid state. Therefore, if it is from fast to slow, the signal is likely to be filtered out. It is applicable to the slow clock domain to the fast clock domain.

   principle that two-stage trigger can prevent metastable propagation: assuming that the input of the first stage trigger does not meet its establishment and holding time, and its output data is metastable after the arrival of the first pulse edge, then before the arrival of the next pulse edge, its output metastable data must be stable after a recovery time, and the stable data must meet the establishment time of the second stage trigger. If they are met, When the next pulse arrives, the second stage flip-flop will not appear metastable because the data at its input meets its establishment and holding time.
   more specifically, the input pulse width must be greater than the sum of the synchronization clock cycle and the holding time required by the first stage trigger. The safest pulse width is twice the synchronous clock cycle. Therefore, such a synchronous circuit is more effective for asynchronous signals from a slower clock domain to enter a faster clock domain, but has no effect on entering a slower clock domain.
   of course, it is still possible that the output of the cascaded second register will also show an unstable state, but this dual register synchronizer can solve most of these metastable problems. Generally speaking, the first-order probability is great, and the third-order improvement is not great. If the third level register is added, because the second level register has played a great role in improving the processing of metastable state, the third level register can be said to be only the delay of the second level register to a great extent, so it is of little significance.
The following principles should be followed when designing this synchronizer:
1. The cascaded registers must use the same sampling clock.
2. There shall be no other combinational logic between the transmitter clock domain register output and the receiver asynchronous clock domain cascade register input.
3. Except for the last register, all registers in the synchronizer can only have one fan out, that is, it can only drive the input of the next level register.

Level synchronizer code

module    Level_Sync(Clk_fast, Clk_slow,Rst_n, Data_in,Data_out);

    /********************Parameter definition********************/

    /*********************IO Explain********************/

	input    wire        Clk_slow  ;//Send domain clock
	input    wire        Clk_fast  ;//Receive domain clock
	input    wire        Rst_n ;    //Asynchronous reset
	input    wire        Data_in;   //Send domain data input
	output   reg         Data_out;  //Receive domain data output
	/********************** Internal signal declaration**********************/   
    reg   Data_in_Q;
	reg   Data_out_Q;

	/*************************Function definition*************************/

	always@(posedge Clk_slow or negedge Rst_n)
	begin
	    if(!Rst_n)
		    Data_in_Q <= 1'b0;
      	else 
		    Data_in_Q <= Data_in;
	end

	always@(posedge Clk_fast or negedge Rst_n) 
    begin
        if(!Rst_n)
		begin
		    Data_out_Q <= 1'b0;
			Data_out <= 1'b0;
		end
		else
		begin
		    Data_out_Q <= Data_in_Q;
			Data_out <= Data_out_Q;
		end
    end	
endmodule

2, Edge synchronizer

   the edge detection synchronizer adds a trigger and logic gate at the output of the level synchronizer, as shown in the figure below.

   the output of the new trigger is inverted and operated with the output of the level synchronizer. This circuit will detect the rising edge of the synchronizer input and generate a high-level effective pulse with the same width as the clock cycle. If the two inputs of the gate are exchanged, a synchronizer for detecting the falling edge of the input signal can be formed. Changing and gate to NAND gate can build a circuit to generate low-level effective pulse.
   the edge synchronizer is similar to the level synchronizer, that is, the width of the input pulse must be greater than the sum of the synchronization clock cycle and the holding time required for the first synchronization trigger. The safest pulse width is twice the clock cycle of the synchronizer. If the input is a single clock width pulse entering a slower clock domain, the synchronizer has no effect. In this case, the pulse synchronizer should be used.

Edge synchronizer code

/* ======================== *\
*    Filename     : Edge_Sync.v
*    Author       : You and I met at the top of the mountain
*    Description  : Edge synchronizer
*    Called by    :
*    Target Device:	EP4CE10F17C8
*    Tool versions:	Quartus Prime 19.1
*    Create Date  : 2022/5/3
*    Revision     : 1.0 
*    Email        : 
*    Company      : 
*    Copyright(c) 2022,
\* ========================= */

module    Edge_Sync(Clk_fast, Clk_slow,Rst_n, Data_in,Data_out);

    /********************Parameter definition********************/

    /*********************IO Explain********************/

	input    wire        Clk_slow  ;//Send domain clock
	input    wire        Clk_fast  ;//Receive domain clock
	input    wire        Rst_n ;    //Asynchronous reset
	input    wire        Data_in;   //Send domain data input
	output   wire        Data_out;  //Edge output
	/********************** Internal signal declaration**********************/   
    reg   Data_in_Q;
	reg   Data_out_Q1;
    reg   Data_out_Q2;
	reg   Data_out_Q3;
	/*************************Define function*************************/
    
	always@(posedge Clk_slow or negedge Rst_n)
	begin
	    if(!Rst_n)
		    Data_in_Q <= 1'b0;
      	else 
		    Data_in_Q <= Data_in;
	end

	always@(posedge Clk_fast or negedge Rst_n) 
    begin
        if(!Rst_n)
		begin
		    Data_out_Q1 <= 1'b0;
			Data_out_Q2 <= 1'b0;
			Data_out_Q3 <= 1'b0;
			
		end
		else
		begin
		    Data_out_Q1 <= Data_in_Q;
			Data_out_Q2 <= Data_out_Q1;
			Data_out_Q3 <= Data_out_Q2;
		end
    end	
	
	assign    Data_out = ~Data_out_Q3 & Data_out_Q2;    //Detect rising edge
//	assign    Data_ out = Data_ out_ Q3 & ~Data_ out_ Q2;    // Detect the lower rising edge
//	assign    Data_out = Data_out_Q3 ^  Data_out_Q2;    // Detect the lower rising edge and falling edge
endmodule

3, Pulse synchronizer

   the basic function of pulse synchronizer is to take out a single clock width pulse from a certain clock domain, and then establish another single clock width pulse in the new clock domain. As shown in the figure below:


   the pulse synchronizer also has a limitation that the minimum interval between input pulses must be equal to two synchronizer clock cycles. If the input pulses are too close to each other, the output pulses in the new clock domain are also closely adjacent. As a result, the output pulse width is wider than one clock cycle.
   this problem is more serious when the input pulse clock cycle is greater than two synchronizer clock cycles. In this case, if the input pulses are too close together, the synchronizer cannot detect each pulse.

Take the Niuke network problem as an example: extract A single clock cycle width pulse from the clock domain A, and then establish another single clock width pulse in the new clock domain B. The frequency of clock domain A is 10 times that of clock domain B; The interval between pulses in A clock domain is very large, so there is no need to consider the problem of too small pulse interval. The interface of the circuit is shown in the figure below. data_in is the pulse input signal, data_out is A new pulse signal; clk_fast is the clock signal of A clock domain, clk_slow is the clock signal of B clock domain; rst_n is asynchronous reset signal.

code:

module    Pulse_Sync(Clk_fast, Clk_slow,Rst_n, Data_in,Data_out);

    /********************Parameter definition********************/

    /*********************IO Explain********************/

	input    wire        Clk_slow  ;//Receive domain clock
	input    wire        Clk_fast  ;//Send domain clock
	input    wire        Rst_n ;    //Asynchronous reset
	input    wire        Data_in;   //Send domain data input
	output   wire        Data_out;  //Edge output
	/********************** Internal signal declaration**********************/   
    reg   Data_in_Q;
	reg   Data_out_Q1;
    reg   Data_out_Q2;
	reg   Data_out_Q3;
	/*************************Function definition*************************/
    /*Pulse signal to level signal*/
	always@(posedge Clk_fast or negedge Rst_n)
	begin
	    if(!Rst_n)
		    Data_in_Q <= 1'b0;
      	else 
		    Data_in_Q <= Data_in? ~Data_in_Q:Data_in_Q;
	end
    
	/*The level signal takes two beats and then turns into a pulse signal*/
	always@(posedge Clk_slow or negedge Rst_n) 
    begin
        if(!Rst_n)
		begin
		    Data_out_Q1 <= 1'b0;
			Data_out_Q2 <= 1'b0;
			Data_out_Q3 <= 1'b0;
			
		end
		else
		begin
		    Data_out_Q1 <= Data_in_Q;
			Data_out_Q2 <= Data_out_Q1;
			Data_out_Q3 <= Data_out_Q2;
		end
    end	
	
	assign    Data_out = Data_out_Q3 ^ Data_out_Q2;    
endmodule

4, Summary


Recommended practices for Synchronizer Design:
The synchronizer is divided into separate modules and two independent clocks are introduced
Other modules are designed as single clock module and fully synchronous module
The clock domain is used as the prefix of the signal name
During static timing analysis, set false path for asynchronous input signal of synchronizer module:
Use wildcards (. * wildcards, which automatically match the same name, belonging to systemverilog syntax)

Posted by stomlin on Wed, 04 May 2022 06:26:31 +0300