Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
All support for Intel NUC 7 - 13 systems has transitioned to ASUS. Read latest update.
16477 Discussions

Crossing Clock Domain Problems | Timing Analyser ignores set_max_skew assignment


Hello everyone,

I have a problem with quartus 20.1 while trying to cross a clock domain. I have followed the Intel video regarding the crossing and the Intel Help .

I also have attached the code for the synchroniser at the bottom. However Timing Analyser always reports that it ignores the set_max_skew assignments with the following message:



No path is found satisfying assignment "set_max_skew -from [get_registers {neuralNetwork|InputSync|clk1_Buffer[*][*]}] -to [get_registers {neuralNetwork|InputSync|clk2_Buffer[0][*][*]}] 2.693 ". This assignment will be ignored.



It does not matter if i use from_clock or from with the registers. I get the same error.

However I do not get any warning during analysis as I would if I would have a wrong path in there (had  typos in there and got the warning).

The problem is that I can not use the max_skew report and thus see if the timings are actually held. Does anyone have any idea?

Best regards

Edit: I have just checked in the TA. I can find the registers when setting up new assignments. I also tried setting just the individual register connections, which I can definitively find the Technology Map Viewer. It also gets ignored.


Edit 2: I have now looked through the output for the timing analyser during compilation. There it says it detects all of the synchronizer chains, calculates a MTBF, settling time, etc.
Afterwards I went ahead and tested the design on the FPGA and all output look good. I really do not understand why TA is not able to create the report. Any ideas?

SDC constrains:



# Create Clock
create_clock -name {input_clk} -period 13.468 -waveform { 0.000 6.734 } [get_ports {clk}]

# Create Generated Clock

create_generated_clock -name output_clk -source [get_ports {clk}] -master_clock input_clk -add [get_ports {clk_o}]
create_generated_clock -name {pllBaseClock} -source [get_pins {neuralNetwork|PLL|nnfpga_pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|refclkin}] -duty_cycle 50/1 -multiply_by 16 -divide_by 2 -master_clock {input_clk} [get_pins {neuralNetwork|PLL|nnfpga_pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|vcoph[0]}] 
create_generated_clock -name {neuralNetworkClock} -source [get_pins {neuralNetwork|PLL|nnfpga_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|vco0ph[0]}] -duty_cycle 50/1 -multiply_by 1 -divide_by 2 -master_clock {pllBaseClock} [get_pins {neuralNetwork|PLL|nnfpga_pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}]  

# Set Clock Groups

set_clock_groups -asynchronous -group [get_clocks {neuralNetworkClock}] -group [get_clocks {input_clk}] 

# Set Net Delay

set_net_delay -max 2.693 -from [get_pins {neuralNetwork|InputSync|clk1_Buffer[*][*]|q}]
set_net_delay -max 2.693 -from [get_pins {neuralNetwork|OutputSync|clk1_Buffer[*][*]|q}]

# Set Max Skew

set_max_skew -from [get_registers {neuralNetwork|InputSync|clk1_Buffer[*][*]}] -to [get_registers {neuralNetwork|InputSync|clk2_Buffer[0][*][*]}] 2.693
set_max_skew -from [get_registers {neuralNetwork|OutputSync|clk1_Buffer[*][*]}] -to [get_registers {neuralNetwork|OutputSync|clk2_Buffer[0][*][*]}] 2.693







-- Synchorniser for array of std_logic_vector of variable size
-- Requires VHDL 2008 support! 
-- (c) Christian Woznik

library IEEE;
use ieee.std_logic_1164.all;

USE ieee.math_real.log2;
USE ieee.math_real.ceil;

library work;
use work.types.all;

entity synchroniserArrayStdLogicVector is
	generic (arraySize 		: integer;
				stages			: integer;
				inputdataWidth : integer);
	port (clk1        : in 	std_logic;
			clk2 			: in 	std_logic; 			
			dataIn		: in variableSizeLogicVectorArray (0 to (arraySize) -1)(inputdataWidth-1 downto 0);
			dataOut 		: out variableSizeLogicVectorArray (0 to (arraySize) -1)(inputdataWidth-1 downto 0));
end synchroniserArrayStdLogicVector ;

architecture behave of synchroniserArrayStdLogicVector is	
	signal clk1_Buffer : variableSizeLogicVectorArray (0 to (arraySize) -1)(inputdataWidth-1 downto 0);
	type t_BufferArray is array (0 to stages-1) of variableSizeLogicVectorArray(0 to (arraySize) -1)(inputdataWidth-1 downto 0);
	signal clk2_Buffer : t_BufferArray;
		if rising_edge(clk1) then
			clk1_Buffer <= dataIn;
		end if;
	end process;
		variable i : integer;
		if rising_edge(clk2) then
			clk2_Buffer(0) <= clk1_Buffer;
			for i in 0 to stages-2 loop
				clk2_Buffer(i+1) <= clk2_Buffer(i);
			end loop;
		end if;
	end process;
	dataOut <= clk2_Buffer(stages-1);
end behave;



0 Kudos
3 Replies


What version of Quartus are you using? If you are using Pro, there is feature like DA DRC for CDC and CDC Viewer report in Timing Analyzer which will tell you there is CDC still occur in your design easily.

Since you mentioned during compilation the PnR works and the output is correct, no meta. furthermore no hardware failure during testing and error during compilation, this could be a bug as well for TA. Is it possible to attach you qar here to reproduce the issue. 

0 Kudos


May I know if there is any update?

0 Kudos

The answer is easy: Quartus has a bug since at least Quartus 16.1, which means you cannot use "set_max_skew" to constrain "Clock Domain Crossing" paths (CDCs); which is unfortunate, because this is the correct constraint for these kind of paths.

Note that even if you would be able to use "set_max_skew" it wouldn't help, because the fitter ignores these constraints.

Additionally you can only use "set_net_delay" for CDC paths, which do not contain ANY combinational logic in between; so you can only use "set_net_delay" for pure register to register paths.


The only way to get reliable CDC logic is to put it into an own entity and then use "logic lock" regions to make sure the fitter puts all the registers as close together as possible.


To get some notion about timings for CDC logic, you then need an extra "SDC" file, where you remove all "set_false_path" and "set_clock_group" constraints, because then the timing analyzer will be at least able to give you numbers for the "set_max_skew" constraints.


Welcome to the world of unreliable tools and "community" support, which does not even understand what you are talking about.

0 Kudos