I based an FPGA design on Lattice reference code that, in the timing constraints .lpf
file, specifies:
BLOCK INTERCLOCKDOMAIN PATHS
The design two main clock domains are 100Mhz and 125Mhz so I expect them to drift through phase relationships that violate cross-domain setup and hold times periodically. Each clock domain has appropriately constrained frequencies and the transfer of data between domains looks sound.
Lattice themselves post advice that seems to discourage the use of BLOCK INTERCLOCKDOMAIN PATHS
in their FAQ:
Question How can I block clock domain transfers where I have synchronizer circuits?
Answer ...
trace
analyzes all clock domain transfers in which it can relate the source and destination clock domains. This may not always be desired. You may utilize your own synchronizer to handle the transfer between the clock domains. In this casetrace
should not analyze the clock domain transfer. This can be done in three ways:
BLOCK INTERCLOCKDOMAIN PATHS
This preference will block all clock domain transfers in the design. If all of the clock domain transfers in the design are handled by the logic within the design then this can be used. Be careful with this preference since it will stoptrace
from analyzing all clock domain transfers.
BLOCK PATH FROM CLKNET "src_clk" TO CLKNET "dst_clk"
This preference will block all clock domain transfers from src_clk to dst_clk. This covers all of the transfers between these two domains. All other clock domain transfers will be reported and timed bytrace
.
BLOCK FROM CELL "myff1*" TO CELL "myff2*"
This preference will block the clock domain transfer from myff1* to myff2*. This is a very specific path and is useful if you have several different types of clock domain transfers between two domains. For example, a design may contain an asynchronous FIFO and a FF-to-FF domain transfer between the same domains. The asynchronous FIFO transfer can be safely blocked, but the FF-to-FF transfer needs to be timed.
And:
Question What is the "BLOCK INTERCLOCKDOMAIN PATH" preference used for?
Answer This constraint is used to block paths that involve data transfer between registers that are clocked by different clock nets. If used without understanding, it will block all clocks domains from each other, even if they are supposed to be related. This can cause your tools to not calculate the necessary routing delay between related clock and data paths and can lead to intermittent setup and hold errors in your design.
It's best to use a
BLOCK CLKNET
for each path that is unrelated in case you have related clocks.
I feel obliged to remove the catch-all constraint given this advice and explicitly determine the relevant cells in my synchroniser (and their path in the hierarchy) that cross the domains, then block analysis of each known crossing explicitly at the cell level. I know where these should be after all - I designed them in, but the exact hierarchy names will take a while to find from the timing report violations I expect when remove this constraint. This will probably take a day and a few P&R cycles to get them all.
The net effect will probably end up being the exact same design I have at the moment, with a longer constraint file and the same near-critical paths.
So - would you bit the bullet and take out the catch-all BLOCK INTERCLOCKDOMAIN PATHS
, and sub in BLOCK .. CELL
constraints for every crossing? Or is it not worth the effort and keep the catch-all?