Forum Discussion

MOliv45's avatar
MOliv45
Icon for New Contributor rankNew Contributor
6 years ago

DRC check CDC-50001 does not work if the given bit is part of a vector?

Summary:

If the bit that is missing a synchronizer is part of a vector, the DRC check CDC-50001 FAILS.

VHDL code:

library IEEE;

use IEEE.STD_LOGIC_1164.all;

entity cdc is

port (

clk1 : in std_logic;

clk2 : in std_logic;

Input : in std_logic;

Output_A : out std_logic;

Output_B : out std_logic

);

end entity;

architecture rtl of cdc is

signal datai : std_logic;

signal datao : std_logic_vector(0 to 1);

begin

process (clk1) is

begin

if rising_edge(clk1) then

datai <= Input;

end if;

end process;

process (clk2) is

begin

if rising_edge(clk2) then

datao <= datai & '1';

Output_A <= datao(0);

Output_B <= datai;

end if;

end process;

end architecture;

SDC constraints:

#**************************************************************

# Create Clock

#**************************************************************

create_clock -name {clk2} -period 10.000 -waveform { 0.000 5.000 } [get_ports {clk2}]

create_clock -name {clk1} -period 10.000 -waveform { 0.000 5.000 } [get_ports {clk1}]

#**************************************************************

# Set Clock Groups

#**************************************************************

set_clock_groups -asynchronous \

-group [get_clocks {clk1}] \

-group [get_clocks {clk2}]

Problem observed:

A 1-bit synchronizer is needed in each of the paths driving outputs A and B. However, only the missing 1-bit synchronizer in output B is detected.

8 Replies

  • MEIYAN_L_Intel's avatar
    MEIYAN_L_Intel
    Icon for Frequent Contributor rankFrequent Contributor

    Hi,

    May I know the Quartus version and edition you are using?

    I would like to test it on my side.

    By reviewing you code "signal datao : std_logic_vector(0 to 1)", this is declaring the vector signal hold two bit while in your code "datao <= datai & '1'" and "Output_A <= datao(0)" show is only hold one bit.

    Thanks

    • MOliv45's avatar
      MOliv45
      Icon for New Contributor rankNew Contributor

      Hi Mylee,

      Yes, sure. I am using Quartus Prime Pro 19.3 Linux :)

      In fact, in the previous code, you are right, the CDC was not detected because it had already two registers.

      The reason I created this post was to reproduce the effect I see in a larger project, which would be difficult to share here.

      I believe I have now managed to isolate the issue better. It seems that CDC-50001 DOES not work if the clock domain crossing is starting from an IP component pin. (nothing related to the vector, sorry)

      For instance, the crossing from the IP pin "locked" to "Output_A" is not detected in the CDC-50001 DRC check, while the crossing from "locked_reg" to "Output_B" is.

      Note that "clk1" and "outclk_0" belong to the same group, which is unrelated to clk2.

      Therefore, the crossing from "locked" to "Output_A" should have been detected with the missing 1-bit synchronizer flag (DRC check CDC-50001)

      This post is part of a larger effort in view of detecting mis-implemented clock domain crossings in larger projects we have here at CERN.

      We like very much the Intel DRC check report, but we have leaned thorugh the experience in one of our projects that CDC-50001 does not work in this case, i.e. when the clock domain crossing involves an IP-component pin.

      Can you help us out solving this issue?

      Best Regards.

      Marcos

  • MOliv45's avatar
    MOliv45
    Icon for New Contributor rankNew Contributor

    For your reference:

    VHDL file:

    library IEEE;
    use IEEE.STD_LOGIC_1164.all;
     
    entity cdc is
        port (
            clk1     : in  std_logic;
            clk2     : in  std_logic;
            rst      : in  std_logic;
            Output_A : out std_logic;
            Output_B : out std_logic
        );
    end entity;
     
    architecture rtl of cdc is
     
        signal locked     : std_logic;
        signal locked_reg : std_logic;
        signal clk1_pll   : std_logic;
     
        component pll is
            port (
                rst      : in  std_logic := 'X';  -- reset
                refclk   : in  std_logic := 'X';  -- clk
                locked   : out std_logic;         -- export
                outclk_0 : out std_logic          -- clk
            );
        end component pll;
     
    begin
     
        u0 : component pll
            port map (
                rst      => rst,            --   reset.reset
                refclk   => clk1,           --  refclk.clk
                locked   => locked,         --  locked.export
                outclk_0 => clk1_pll        -- outclk0.clk
            );
     
        process (clk1_pll) is
        begin
            if rising_edge(clk1_pll) then
                locked_reg <= locked;
            end if;
        end process;
     
     
        process (clk2) is
        begin
            if rising_edge(clk2) then
                Output_A <= locked;
                Output_B <= locked_reg;
     
     
            end if;
        end process;
     
     
     
    end architecture;

    SDC file:

    #**************************************************************
    # Create Clock
    #**************************************************************
     
    create_clock -name {clk2} -period 10.000 -waveform { 0.000 5.000 } [get_ports {clk2}]
    create_clock -name {clk1} -period 10.000 -waveform { 0.000 5.000 } [get_ports {clk1}]
     
     
    #**************************************************************
    # Create Generated Clock
    #**************************************************************
     
    create_generated_clock -name {u0|iopll_0|outclk0} -source [get_pins {u0|iopll_0|altera_iopll_i|twentynm_pll|iopll_inst|refclk[0]}] -duty_cycle 50/1 -multiply_by 6 -divide_by 6 -master_clock {clk1} [get_pins {u0|iopll_0|altera_iopll_i|twentynm_pll|iopll_inst|outclk[0]}] 
     
     
    #**************************************************************
    # Set Clock Latency
    #**************************************************************
     
     
     
    #**************************************************************
    # Set Clock Uncertainty
    #**************************************************************
     
    set_clock_uncertainty -rise_from [get_clocks {clk1}] -rise_to [get_clocks {clk1}]  0.030  
    set_clock_uncertainty -rise_from [get_clocks {clk1}] -fall_to [get_clocks {clk1}]  0.030  
    set_clock_uncertainty -fall_from [get_clocks {clk1}] -rise_to [get_clocks {clk1}]  0.030  
    set_clock_uncertainty -fall_from [get_clocks {clk1}] -fall_to [get_clocks {clk1}]  0.030  
    set_clock_uncertainty -rise_from [get_clocks {clk2}] -rise_to [get_clocks {clk2}]  0.030  
    set_clock_uncertainty -rise_from [get_clocks {clk2}] -fall_to [get_clocks {clk2}]  0.030  
    set_clock_uncertainty -fall_from [get_clocks {clk2}] -rise_to [get_clocks {clk2}]  0.030  
    set_clock_uncertainty -fall_from [get_clocks {clk2}] -fall_to [get_clocks {clk2}]  0.030  
     
     
    #**************************************************************
    # Set Input Delay
    #**************************************************************
     
     
     
    #**************************************************************
    # Set Output Delay
    #**************************************************************
     
     
     
    #**************************************************************
    # Set Clock Groups
    #**************************************************************
     
    set_clock_groups -asynchronous -group [get_clocks {clk1 u0|iopll_0|outclk0}] -group [get_clocks {clk2}] 
     
     

  • MEIYAN_L_Intel's avatar
    MEIYAN_L_Intel
    Icon for Frequent Contributor rankFrequent Contributor

    Hi,

    May I have the .qar design file (include the test bench file) for further investigate?

    Thanks

  • MEIYAN_L_Intel's avatar
    MEIYAN_L_Intel
    Icon for Frequent Contributor rankFrequent Contributor

    Hi,

    It seems like the output for pll_locked to output_a is not a timing path.

    CDC rules only show violation for timing paths.

    Thanks

    • MOliv45's avatar
      MOliv45
      Icon for New Contributor rankNew Contributor

      Hi,

      Indeed. There is an internal request at intel to discuss if this port should be timed or not.

      I believe it should. In one way or the other the DRC check has to be able to detect a missing synchronizer from an IP port, right?

      Cheers.

  • MEIYAN_L_Intel's avatar
    MEIYAN_L_Intel
    Icon for Frequent Contributor rankFrequent Contributor

    It depends on whether we have the DRC check rule that was able to do it. My suggestion is in your internal request, if this feature does not exist, request them to have a enhancement on it.