Sometimes you can define a timing constraint between two clock domains that share a period but include a phase shift. In these cases, understand the default setup and hold relationships the timing engine uses. If you do not adjust them carefully, the phase shift can over-constrain logic between the two domains.
For example, assume the following:
- The two clocks,
CLK1andCLK2, share the same waveform. -
CLK2shifts by +0.3 ns.
The timing engine evaluates all edges on both waveforms. It selects launch and capture edges that produce the stricter setup constraint. Because of the phase shift, the engine’s chosen setup and hold edges can differ from your intent.
In this example, the phase shift creates a 0.3 ns setup requirement. Achieving timing closure becomes nearly impossible. The hold check is −3.7 ns, which is too lenient.
The setup and hold edges must be adjusted to match your intent. This is done by adding a multicycle constraint with a setup multiplier of two:
set_multicycle_path 2 -setup -from [get_clocks CLK1] -to [get_clocks CLK2]
This moves the setup capture edge forward by one cycle. The hold edge derives from the setup change. You do not need to specify it.
-end), Hold Moved Accordingly
With a negative phase shift, launch and capture edges for setup and hold resemble the single-domain case.
For a negative phase shift, you typically do not need a multicycle constraint. Use one only if the shift is large and edges require adjustment to keep realistic requirements.