Community
cancel
Showing results for 
Search instead for 
Did you mean: 
MOliv45
Beginner
269 Views

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. 

0 Kudos
8 Replies
MEIYAN_L_Intel
Employee
100 Views

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
Beginner
100 Views

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)

Screenshot 2020-01-30 at 12.14.34.png

 

 

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
Beginner
100 Views

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
Employee
100 Views

Hi,

 

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

 

Thanks

MOliv45
Beginner
100 Views

Hi,

 

Yes, sure. Here it is :)

There is no testbench though.

MEIYAN_L_Intel
Employee
100 Views

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
Beginner
100 Views

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
Employee
100 Views

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.

Reply