Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

Do I need synchronizer block for this

i am feeding reset, aclk and siga to the fpga as input. aclk is running very fast may be 350mhz. siga is one aclk period wide and derived from synchronizer block and then anded to gather before going into fpga. something like this in verilog testbench

//generate stimulus

initial begin

siga1 = 1'b0;

siga2 = 1'b0;

reset = 1'b1;# 520 //keep reset asserted for a while

reset = 1'b0;# 1000; //give some time before generating siga

@(posedge aclk);

siga1 = 1'b1;

@(posedge aclk);

siga2 = 1'b1;# 5000;

siga1 = 1'b0;

siga2 = 1'b0;# 3000;

$finish;

end

assign# 1 siga = (siga1 & ~siga2); //mimic external and gate that ultimately generates one aclk wide pulse

in this case i do not know the board trace length mis-match between aclk and siga. if so, do i need to synchronize siga signal inside the fpga?

also how to pass the siga signal to different or slower clock domain?

6 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You will need to register your input to ensure your design does not have issues. If your design permits, I recommend registering all inbound signals before using them in your logic.

    To pass the clock-wide pulse to a slower domain is not horrible, it just takes some logic to work. I am not great at verilog, so I'm posting a VHDL clock sync design. It isn't the greatest, but you should be able to get an idea on how it can work. It has restrictions on maximum pulse rate on fast clock domain vs fast/slow clock speed ratio. *Disclaimer: I did not try to compile this so errors may exist.

    PROCESS(FAST_CLK,RESET)
    BEGIN
      IF(RESET = '1') THEN
        input_register_s <= '0';
        feedback_register_s <= '0';
      ELSIF (rising_edge(FAST_CLK)) THEN
        input_register_s <= SigA;  //register the input
        feedback_register_s <= slow_domain_status_register_s;  //register the feedback from slow domain
        IF (input_register_s = '1') THEN //if pulse detected, set feedforward
          feedforward_register_s <= '1';
        ELSIF (feedback_register_s = '1') THEN  //if feedback indicates pulse seen at slow domain clear feedforward
          feedforward_register_s <= '0';
        END IF;
      END IF;
    END PROCESS;
    PROCESS(SLOW_CLK, RESET)
    BEGIN
      IF (RESET = '1') THEN
        slow_domain_status_register_s <= '0';
        slow_domain_status_register1_s <= '0';
        slow_domain_SigA <= '0';
      ELSIF (rising_edge(SLOW_CLK)) THEN
        slow_domain_status_register_s <= input_register_s;  //register on new clock domain
        slow_domain_status_register1_s <= slow_domain_status_register_s;  //remember what last value was
        IF ((slow_domain_status_register1_s = '0') AND (slow_domain_status_register_s = '1')) THEN  //rising edge detect
          slow_domain_SigA <= '1';  //send pulse in slow domain
        ELSE
          slow_domain_SigA <= '0';
        END IF;
      END IF;
    END PROCESS;
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    You will need to register your input to ensure your design does not have issues. If your design permits, I recommend registering all inbound signals before using them in your logic.

    To pass the clock-wide pulse to a slower domain is not horrible, it just takes some logic to work. I am not great at verilog, so I'm posting a VHDL clock sync design. It isn't the greatest, but you should be able to get an idea on how it can work. It has restrictions on maximum pulse rate on fast clock domain vs fast/slow clock speed ratio. *Disclaimer: I did not try to compile this so errors may exist.

    PROCESS(FAST_CLK,RESET)
    BEGIN
      IF(RESET = '1') THEN
        input_register_s <= '0';
        feedback_register_s <= '0';
      ELSIF (rising_edge(FAST_CLK)) THEN
        input_register_s <= SigA;  //register the input
        feedback_register_s <= slow_domain_status_register_s;  //register the feedback from slow domain
        IF (input_register_s = '1') THEN //if pulse detected, set feedforward
          feedforward_register_s <= '1';
        ELSIF (feedback_register_s = '1') THEN  //if feedback indicates pulse seen at slow domain clear feedforward
          feedforward_register_s <= '0';
        END IF;
      END IF;
    END PROCESS;
    PROCESS(SLOW_CLK, RESET)
    BEGIN
      IF (RESET = '1') THEN
        slow_domain_status_register_s <= '0';
        slow_domain_status_register1_s <= '0';
        slow_domain_SigA <= '0';
      ELSIF (rising_edge(SLOW_CLK)) THEN
        slow_domain_status_register_s <= input_register_s;  //register on new clock domain
        slow_domain_status_register1_s <= slow_domain_status_register_s;  //remember what last value was
        IF ((slow_domain_status_register1_s = '0') AND (slow_domain_status_register_s = '1')) THEN  //rising edge detect
          slow_domain_SigA <= '1';  //send pulse in slow domain
        ELSE
          slow_domain_SigA <= '0';
        END IF;
      END IF;
    END PROCESS;
    

    --- Quote End ---

    Thanks for getting back to me. Can we not just set input_register_s to 1 upon SigA assertion? Then pass the Input_register_s to slow clock domain - synchronize it and generate single pulse using AND gate. Doing so will ensure that it works in any clock domain fast to slow or slow to fast. This method does not require feedback as there is only one SigA pulse. Also as per my understanding, it takes two flipflop to synchronize the asynchronous signal. Just curious. Sorry here is what I was thinking in verilog.

    //Synchronize the input signal as it is going through AND gate

    //Also not clear on the external trace length mis-match

    //between AClk and SigA

    always @(posedge AClk or posedge Reset) begin

    if (Reset) begin

    SigAQ0 <= 1'b0;

    SigAQ1 <= 1'b0;

    end

    else begin

    SigAQ0 <= SigA;

    SigAQ1 <= SigAQ0;

    end

    end

    //Generate SigAFlag based on SigAQ1 pulse

    //SigAFlag asserts upon SigA assertion

    always @(posedge AClk or posedge Reset) begin

    if (Reset) begin

    SigAFlag <= 1'b0;

    end

    else begin

    if (SigAQ1) begin

    SigAFlag <= 1'b1;

    end

    else begin

    SigAFlag <= SigAFlag;

    end

    end

    end

    //Synchronize the SigAFlag to BClk domain and generate SigB

    always @(posedge BClk or posedge Reset) begin

    if (Reset) begin

    SigBQ0 <= 1'b0;

    SigBQ1 <= 1'b0;

    SigBQ2 <= 1'b0;

    SigB <= 1'b0;

    end

    else begin

    SigBQ0 <= SigAFlag;

    SigBQ1 <= SigBQ0;

    SigBQ2 <= SigBQ1;

    SigB <= SigBQ1 & ~SigBQ2;

    end

    end

    It will be great if you can provide feedback.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The reason for the feedback is to clear the flag in the fast clock domain to look for more pulses. If you will only have one ever between resets, your code should work fine. If you have multiple pulses, you need a way to clear SigAFlag in your fast domain.

    I have seen recommendations to use two registers to cross clock domains. Although it may be bad practice, I have always used one and had no real issues with it. Using two shouldn't be a problem, it will just take a little more time and a few more resources. Good luck with your design!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks for response. I am bit concerned about the way I have used the AND gate to derive single pulse as in following statement

    SigB <= SigBQ1 & ~SigBQ2;

    Normally I see people using XOR gate. I do not know why to use XOR instead of AND.

    I see the following paper from Cadence suggesting some issue with AND gate but they did not provide a solution. In the figure CLKA and CLKB to be same clock frequency.

    http://w2.cadence.com/whitepapers/cdc_wp.pdf Section 3.3 figure 6.

    --- Quote Start ---

    The reason for the feedback is to clear the flag in the fast clock domain to look for more pulses. If you will only have one ever between resets, your code should work fine. If you have multiple pulses, you need a way to clear SigAFlag in your fast domain.

    I have seen recommendations to use two registers to cross clock domains. Although it may be bad practice, I have always used one and had no real issues with it. Using two shouldn't be a problem, it will just take a little more time and a few more resources. Good luck with your design!

    --- Quote End ---

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    If a straight XOR is used, you will get two pulses, one for the rising edge, and one for the falling edge. Your use of the & operator should not be a problem. Both SigBQ1 and SigBQ2 are not crossing domains as shown in your document's figure 6.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    SigBQ1 is going high and staying high and then one clock later SigBQ2 is doing the same thing. so AND or XOR gate should generate the same result of one BClk wide pulse.