Intended to be part of a tutorial for those new to FPGA design, this blog is specific to Xilinx's Synthesis tool "Vivado", and a refresher as someone returning to FPGA design having used different tools (Synplify Pro) over a decade ago. The principles are the same, but the method of application has changed for the better so that it is simpler to get right.
- Application of Constraints
- Out of Context Synthesis
- Specifying Asynchronous Registers
- Specifying Timing Path Exceptions
- Asynchronous Clocks
- False Paths Between Specific Clocks
- False Paths Between Registers
- Limiting Propagation Delay
- Verification of Application
- Report Exceptions
- Report Clock Domain Crossings
- Missing Asynchronous Registers
- Conclusions
- References
Application of Constraints
This section is in two parts:
- Apply boundary timing constraints for out of context synthesis
- Specify the path exceptions of "false paths" to be omitted from timing analysis
The logic circuit I'll use here is borrowed from the blog Specifying Boundary Timing Constraints in Vivado.

The source code for this logic can be found in Github, and is worth examining in order to understand the application of constraints in this blog.
Out of Context Synthesis
This parts sets up our small design correctly for timing analysis so that boundary I/O does not play a part in any timing violations by applying sensible input and output delays. This solution is directly cribbed from a previous blog Specifying Boundary Timing Constraints in Vivado, and applied to a randomly selected device part available in Vivado Webpack.
# Part: xc7k70tfbv676-1
# FDRE Setup Time (Setup_FDRE_C_D) is 0.058ns, set by Xilinx, see timing reports
set tsu 0.037
# FDRE Propagation Delay (Prop_FDRE_C_Q) is 0.049ns, set by Xilinx, see timing reports
set tpd 0.269
# FDRE Hold Time (Hold_FDRE_C_D) is 0.056 - 0.108ns, set by Xilinx, see timing reports
#set th 0.056
set th 0.218
# Default clock uncertainty 0.035ns, set by Xilinx, see timing reports
set tcu 0.035
# Choose these:
#
# Additional clock uncertainty desired for over constraining the design, set by designer choice
set tcu_add 0.000
# desired slack, set by designer choice
set ds 0.008
create_clock -period 5.000 -name clk_src1 [get_ports clk_src1]
create_clock -period 8.000 -name clk_src2 [get_ports clk_src2]
create_clock -period 4.000 -name clk_dest [get_ports clk_dest]
set input_ports_src1 [get_ports {flags_src1[*] reset_src1}]
set input_ports_src2 [get_ports {flags_src2[*] reset_src2}]
set input_ports_dest [get_ports {reset_dest}]
set output_ports [get_ports {flags_out[*]}]
# https://www.xilinx.com/publications/prod_mktg/club_vivado/presentation-2015/paris/Xilinx-TimingClosure.pdf
# Recommended technique for over-constraining a design:
set_clock_uncertainty $tcu_add [get_clocks]
# From: http://billauer.co.il/blog/2017/04/io-timing-constraints-meaning/, with amendments for additional clock uncertainty when applied to hold times.
#
# $tcu *should* not be required on hold timing analysis since the timing is relative to the same clock edge,
# not the next one. However, it is being included in the timing path analysis by Vivado here, and have yet
# to determine why.
#
# set_input_delay -clock ... -min ... : The minimal clock-to-output of the driving chip. If not given, choose zero (maybe a future revision of the driving chip will be manufactured with a really fast process)
# Actually needs to be > (clock uncertainty 0.035ns + Hold_FDRE_C_D)
# Hold (negative value)
set input_delay_min [expr $tcu + $tcu_add + $th + $ds]
#
# set_input_delay -clock ... -max ... : The maximal clock-to-output of the driving chip + board propagation delay
# Setup
set input_delay_max $tsu
#
# set_output_delay -clock ... -min ...: Minus the t_hold time of the receiving chip (e.g. set to -1 if the hold time is 1 ns).
# Hold (negative value)
#set output_delay_min -$th
# Set to be > -(clock uncertainty 0.035ns + Prop_FDRE_C_Q)
set output_delay_min [expr $tcu + $tcu_add - $tpd + $ds]
#
# set_output_delay -clock ... -max ... : The t_setup time of the receiving chip + board propagation delay
# Setup
set output_delay_max $tsu
set_input_delay -clock [get_clocks clk_src1] -min $input_delay_min $input_ports_src1
set_input_delay -clock [get_clocks clk_src1] -max $input_delay_max $input_ports_src1
set_input_delay -clock [get_clocks clk_src2] -min $input_delay_min $input_ports_src2
set_input_delay -clock [get_clocks clk_src2] -max $input_delay_max $input_ports_src2
set_input_delay -clock [get_clocks clk_dest] -min $input_delay_min $input_ports_dest
set_input_delay -clock [get_clocks clk_dest] -max $input_delay_max $input_ports_dest
set_output_delay -clock [get_clocks clk_dest] -min $output_delay_min $output_ports
set_output_delay -clock [get_clocks clk_dest] -max $output_delay_max $output_ports
Specifying Asynchronous Registers
ASYNC_REG is an attribute that affects many processes in the Vivado tools flow. ASYNC_REG specifies that:
- A register can receive asynchronous data on the D input pin relative to its source clock.
- A register is a synchronizing register within a synchronization chain.
Vivado synthesis treats the ASYNC_REG property like the DONT_TOUCH property, and pushes it forward in the synthesized netlist. This ensures that synthesis will not optimize registers or surrounding logic, and that downstream tools in the design flow receive the ASYNC_REG property for processing.
Specifying ASYNC_REG also affects optimization, placement, and routing to improve mean time between failure (MTBF) for registers that can go metastable. If ASYNC_REG is applied, the placer will ensure the flip-flops on a synchronization chain are placed closely together in order to maximize MTBF. Registers that have this property that are directly connected will be grouped and placed together into a single SLICE/CLB, assuming they have a compatible control set and the number of registers does not exceed the available resources of the SLICE/CLB.
In the example VHDL code used here, the ASYNC_REG constraints are applied at these lines. I note that Intel's Quartus Prime does not have the equivalent of this constraint or attribute, and manages to infer the retime registers automatically.
Specifying Timing Path Exceptions
Asynchronous Clock Domain Crossings
The Timing Constraints wizard analyzes the topology of clock domain crossing (CDC) paths between asynchronous clocks and recommends clock groups or false path constraints whenever it is safe to do so.
Asynchronous clocks are clocks with no known phase relationship, which typically happens when they do not share the same primary clock or do not have a common period. For this reason, slack computation on asynchronous CDC paths is not accurate and cannot be trusted. Due to potentially large skew between asynchronous clocks, the timing quality-of-result can be heavily impacted and prevent proper timing closure if any of the asynchronous CDC paths is timed. You are responsible for adding timing exceptions on these paths, such as set_clock_groups, set_false_path, or set_max_delay -datapath_only to either completely ignore timing analysis or just ignore the clock skew and uncertainty. Also, the design must implement proper CDC circuitry to prevent metastability.
The following video tutorial covers the above quite nicely, and suggests the use of the TCL report_exceptions command to verify the application of constraints. Hence I demonstrate their usage below.
I'm going to provide a worked example of the application of all three methods to the above example. It is possible to quickly verify the false paths have been correctly applied by visually inspecting the "Timing" tab created by the "Timing Report Summary" in Vivado.


Asynchronous Clocks
This is the most automatic and pain free way to specify false paths. All the paths between the declared asynchronous clocks are automatically found. This options has the highest precedence, i.e. over those that follow below. And this can be unhelpful, since any specific paths that have been carefully constrained, e.g. with set_max_delay, will then be overridden.
set_clock_groups \
-asynchronous \
-group [get_clocks {clk_src1}] \
-group [get_clocks {clk_src2}] \
-group [get_clocks {clk_dest}]
Advice on the Xilinx support forums suggests use of this construct should be avoided:
So, you have hit on the main problem with using set_clock_groups; it is the highest priority exception and hence takes precedence over everything else. This is the main reason that I highly discourage its use.
The only function of the set_clock_groups is to disable timing checks on paths that go between the clock groups. This is equivalent to set_false_path constraints between each pair of clocks in the clock groups. This is specifically telling the tool "I don't care about the timing on these paths at all" and there is nothing that can be done to override them.
I prefer a much more cautious approach to CDC constraints. Only apply exceptions to the clock crossing paths themselves (not the clocks) and make sure the exception is appropriate. <SNIP>
Doing this CDC path by CDC path, you apply only the constraints you need - presumably only placing exceptions on paths that have valid CDC circuits on them, and each exception is correct for the CDC circuit (since not all CDC circuits need the same exceptions). You can use the report_clock_interaction report (and report_cdc in later versions of Vivado) to ensure that you have placed exceptions on all CDC paths.
False Paths Between Specific Clocks
As clock crossing is directional, this method requires forward and, if necessary, reverse direction crossings to be specified. This method allows false paths to be specified between any registers in the source clock domain to any registers in the destination clock domain.
set_false_path -from [get_clocks clk_src1] -to [get_clocks clk_dest]
set_false_path -from [get_clocks clk_dest] -to [get_clocks clk_src1]
set_false_path -from [get_clocks clk_src2] -to [get_clocks clk_dest]
set_false_path -from [get_clocks clk_dest] -to [get_clocks clk_src2]
False Paths Between Registers
This is the method I had used until recently since the (sensible) ability to specify asynchronous clocks appeared during my absence from FPGA design. It allows the false path to be specified between specific named registers. In a large design this could be many registers, unmanageable and fragile to changes.
set_false_path -from [get_cells {flags_out_reg[*]}] -to [get_cells {conf_src1_r1_reg[*]}]
set_false_path -from [get_cells {flags_out_reg[*]}] -to [get_cells {conf_src2_r1_reg[*]}]
set_false_path -from [get_cells {reg_catch1_reg[*]}] -to [get_cells {reg_dest_r_reg[*]}]
set_false_path -from [get_cells {reg_catch2_reg[*]}] -to [get_cells {reg_dest_r_reg[*]}]
IMPORTANT: Although the previous two set_false_path examples perform what is intended, when two or more clock domains are asynchronous and the paths between those clock domains should be disabled in either direction, Xilinx recommends using the set_clock_groups command instead.
Limiting Propagation Delay
This is perhaps the most reliable way to ensure the timing between the final register in one clock domain and the first in a new clock domain. What we're seeking to avoid is a net that has a pathologically bad propagation delay when left unconstrained by a false path constraint. This might not happen often in practice, but you just don't know when it might have happened, and could easily be the case in a congested design. If the CDC follows a pattern where data bus is accompanied by a 'data valid' signal to qualify the data, then typically one only needs to double retime the data valid signal and then resample the data bus in the new clock domain. The data will have had two destination clock cycles to settle before the resampling. However, it is essential to ensure that one gets those two clock cycles, and that the propagation delay from the old clock domain to the new is not unconstrained such that the net delays exceed those two clock cycles. Here set_max_delay -datapath_only is preferable to set_false_path. Just make sure the constraint is not clobbered by a false path or asynchronous clock group.
Aside: For this reason I wonder if Xilinx have made a mistake with the precedence order? set_clock_groups -asynchronous should have the least precedence, and set_max_delay the highest. It should be possible to tighten the timing for more specific paths rather than loosen it globally so easily. Multiple carefully constructed specific constraints can be wiped out with a single constraint. Would that mean including a set_true_path TCL command to counter a more global default? Or perhaps just increasing the precedence of set_max_delay over set_false_path et al.
Verification of Application
This sections is in two parts:
- Report Exceptions - The paths that are omitted or ignored from timing analysis.
- Report Clock Domain Crossings - The paths that cross clock domains and an indication of how safe they are.
Report Exceptions
The basic TCL commands to use are given below.
# Report timing exceptions
report_exceptions
# List number of constraints by type, e.g. asynchronous clocks, false paths etc
report_exceptions -summary
# List stated false paths
report_exceptions -coverage
# Objects that should not have been specified due to lack of path
report_exceptions -ignored_objects
# Constraints that duplicate
report_exceptions -ignored
To illustrate the usage of the report_exceptions commands, I'll over specify the false paths between clk_src1 and clk_dest using both set_clock_groups and set_false_path commands as shown below.
set_clock_groups \
-asynchronous \
-group [get_clocks {clk_src1}] \
-group [get_clocks {clk_src2}] \
-group [get_clocks {clk_dest}]
set_false_path -from [get_clocks clk_src1] -to [get_clocks clk_dest]
set_false_path -from [get_clocks clk_dest] -to [get_clocks clk_src1]
We can now interrogate our design to identify paths that have been specified as exceptions more than once, and refine the constraints.
report_exceptions -ignored INFO: [Timing 38-91] UpdateTimingParams: Speed grade: -1, Delay Type: min_max. INFO: [Timing 38-191] Multithreading enabled for timing update using a maximum of 6 CPUs Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. -------------------------------------------------------------------------------------- | Tool Version : Vivado v.2019.1.1 (win64) Build 2580384 Sat Jun 29 08:12:21 MDT 2019 | Date : Sun Dec 5 16:18:31 2021 | Host : Rievaulx running 64-bit major release (build 9200) | Command : report_exceptions -ignored | Design : transfer | Device : 7k70t-fbv676 | Speed File : -1 PRODUCTION 1.12 2017-02-17 -------------------------------------------------------------------------------------- Exceptions Report Position From Through To Setup Hold Status -------- --------------------- -------------- --------------------- -------------- -------------- -------------------------------- 14 [get_clocks clk_src1] * [get_clocks clk_dest] false false Totally overridden path by CG 13 15 [get_clocks clk_dest] * [get_clocks clk_src1] false false Totally overridden path by CG 13
Two constraints are reported as having been "totally overridden". The question then is, what is CG 13? To find that, run report_exceptions with no parameters.
report_exceptions INFO: [Timing 38-91] UpdateTimingParams: Speed grade: -1, Delay Type: min_max. INFO: [Timing 38-191] Multithreading enabled for timing update using a maximum of 6 CPUs INFO: [Timing 38-35] Done setting XDC timing constraints. Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. -------------------------------------------------------------------------------------- | Tool Version : Vivado v.2019.1.1 (win64) Build 2580384 Sat Jun 29 08:12:21 MDT 2019 | Date : Sun Dec 5 16:17:38 2021 | Host : Rievaulx running 64-bit major release (build 9200) | Command : report_exceptions | Design : transfer | Device : 7k70t-fbv676 | Speed File : -1 PRODUCTION 1.12 2017-02-17 -------------------------------------------------------------------------------------- Exceptions Report Position From Through To Setup Hold Status -------- ------------------------- -------------- ------------------------- -------------- -------------- ----------------- 13 [get_clocks { clk_src1 }] [get_clocks { clk_dest }] clock_group clock_group 13 [get_clocks { clk_src2 }] [get_clocks { clk_dest }] clock_group clock_group 13 [get_clocks { clk_dest }] [get_clocks { clk_src1 }] clock_group clock_group 13 [get_clocks { clk_src2 }] [get_clocks { clk_src1 }] clock_group clock_group Non-existent path 13 [get_clocks { clk_src1 }] [get_clocks { clk_src2 }] clock_group clock_group Non-existent path 13 [get_clocks { clk_dest }] [get_clocks { clk_src2 }] clock_group clock_group
CG 13 refers to the "Clock Group" in position 13. The positions here (13, 14 & 15) refer to the order of specification of constraints in the XDC file. Here, my out of context synthesis XDC file has been augmented with the three additional TCL commands: set_clock_groups and two set_false_path. These form the over specification we are examining here. The numbers are not line numbers in the file. If you open the XDC with "Edit Timing Constraints" in the Vivado GUI, the position numbers are provided. You can also open the exception report in the GUI using "Reports -> Timing -> Report Exceptions..." The "Non-existent path" lists two paths between clk_src1 and clk_src2 in each direction where there are no path crossings. This is caused by including all three clocks in the same set_clock_groups -asynchronous command. This can be avoided by separating this command into two as shown below.
set_clock_groups \
-asynchronous \
-group [get_clocks {clk_src2}] \
-group [get_clocks {clk_dest}]
set_clock_groups \
-asynchronous \
-group [get_clocks {clk_src1}] \
-group [get_clocks {clk_dest}]
The main additional command not illustrated above is report_exceptions -ignored_objects which will find any specified paths that do not actually exist so they can be removed or most likely the paths to the registers corrected after design changes.
Report Clock Domain Crossings
Finally it is possible to list all clock domain crossings and verify that they are "safe" according to Vivado.
report_cdc INFO: [Timing 38-91] UpdateTimingParams: No interconnect No Cell Dly, Speed grade: -1, Delay Type: min_max. INFO: [Timing 38-191] Multithreading enabled for timing update using a maximum of 6 CPUs INFO: [Timing 38-314] The report_cdc command only analyzes and reports clock domain crossing paths where clocks have been defined on both source and destination sides. Ports with no input delay constraint are skipped. Please run check_timing to verify there are no missing clock definitions in your design, nor any unconstrained input port. Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. -------------------------------------------------------------------------------------- | Tool Version : Vivado v.2019.1.1 (win64) Build 2580384 Sat Jun 29 08:12:21 MDT 2019 | Date : Sun Dec 5 16:47:11 2021 | Host : Rievaulx running 64-bit major release (build 9200) | Command : report_cdc | Design : transfer | Device : 7k70t-fbv676 | Speed File : -1 PRODUCTION 1.12 2017-02-17 -------------------------------------------------------------------------------------- CDC Report Severity Source Clock Destination Clock CDC Type Exceptions Endpoints Safe Unsafe Unknown No ASYNC_REG -------- ------------ ----------------- ----------------------- ------------------- --------- ---- ------ ------- ------------ Warning clk_src2 clk_dest No Common Primary Clock Asynch Clock Groups 4 4 0 0 0 Warning clk_dest clk_src2 No Common Primary Clock Asynch Clock Groups 4 4 0 0 0 Info clk_src1 clk_dest No Common Primary Clock Asynch Clock Groups 2 2 0 0 0 Info clk_dest clk_src1 No Common Primary Clock Asynch Clock Groups 2 2 0 0 0
I find it slightly alarming that two of the lines here are listed with a "warning" just because they relate to multiple bits whilst lines referring to single bits are just for "info". It is then possible to get each "CDC violation" as follows:
get_cdc_violations CDC-3#1 CDC-3#2 CDC-6#1 CDC-3#3 CDC-3#4 CDC-6#2
Which is quite unhelpful, so the following TCL procedure will list the CDC violations in a more friendly format.
proc pretty_print_cdc {} {
report_cdc -quiet
set ret [get_cdc_violations]
foreach cdc $ret {
puts [format "%s#%d: " [get_property CHECK $cdc] [get_property ID $cdc]]
puts " Description: [get_property DESCRIPTION $cdc]"
puts " Severity: [get_property SEVERITY $cdc]"
puts " Clock Crossing: [get_property STARTPOINT_CLOCK $cdc] -> [get_property ENDPOINT_CLOCK $cdc]"
puts " Start Pins: [get_property STARTPOINT_PIN $cdc]"
puts " End Pins: [get_property ENDPOINT_PIN $cdc]"
puts " Exception: [get_property EXCEPTION $cdc]"
}
return $ret
}
Adapted from some code originally proposed in a previous blog Automating Code Review Design Checks in Vivado. This procedure now provides some insight into the sources and destinations of each path, as well as the constraint source.
pretty_print_cdc CDC-3#1: Description: 1-bit synchronized with ASYNC_REG property Severity: Info Clock Crossing: clk_src1 -> clk_dest Start Pins: reg_catch1_reg[0]/C End Pins: reg_dest_r_reg[4]/D Exception: Asynch Clock Groups CDC-3#2: Description: 1-bit synchronized with ASYNC_REG property Severity: Info Clock Crossing: clk_src1 -> clk_dest Start Pins: reg_catch1_reg[1]/C End Pins: reg_dest_r_reg[5]/D Exception: Asynch Clock Groups CDC-6#1: Description: Multi-bit synchronized with ASYNC_REG property Severity: Warning Clock Crossing: clk_src2 -> clk_dest Start Pins: reg_catch2_reg[0]/C reg_catch2_reg[1]/C reg_catch2_reg[2]/C reg_catch2_reg[3]/C End Pins: reg_dest_r_reg[0]/D reg_dest_r_reg[1]/D reg_dest_r_reg[2]/D reg_dest_r_reg[3]/D Exception: Asynch Clock Groups CDC-3#3: Description: 1-bit synchronized with ASYNC_REG property Severity: Info Clock Crossing: clk_dest -> clk_src1 Start Pins: flags_out_reg[4]/C End Pins: conf_src1_r1_reg[0]/D Exception: Asynch Clock Groups CDC-3#4: Description: 1-bit synchronized with ASYNC_REG property Severity: Info Clock Crossing: clk_dest -> clk_src1 Start Pins: flags_out_reg[5]/C End Pins: conf_src1_r1_reg[1]/D Exception: Asynch Clock Groups CDC-6#2: Description: Multi-bit synchronized with ASYNC_REG property Severity: Warning Clock Crossing: clk_dest -> clk_src2 Start Pins: flags_out_reg[0]/C flags_out_reg[1]/C flags_out_reg[2]/C flags_out_reg[3]/C End Pins: conf_src2_r1_reg[0]/D conf_src2_r1_reg[1]/D conf_src2_r1_reg[2]/D conf_src2_r1_reg[3]/D Exception: Asynch Clock Groups CDC-3#1 CDC-3#2 CDC-6#1 CDC-3#3 CDC-3#4 CDC-6#2
To list the dangerous clock domains, borrow the filter conditions from the TCL procedure at Critical Clock Domain Crossing Issues.
Missing Asynchronous Registers
For this example I commented out two of the lines of VHDL attributes in the example VHDL code.
report_cdc INFO: [Timing 38-91] UpdateTimingParams: No interconnect No Cell Dly, Speed grade: -1, Delay Type: min_max. INFO: [Timing 38-191] Multithreading enabled for timing update using a maximum of 6 CPUs INFO: [Timing 38-314] The report_cdc command only analyzes and reports clock domain crossing paths where clocks have been defined on both source and destination sides. Ports with no input delay constraint are skipped. Please run check_timing to verify there are no missing clock definitions in your design, nor any unconstrained input port. Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. -------------------------------------------------------------------------------------- | Tool Version : Vivado v.2019.1.1 (win64) Build 2580384 Sat Jun 29 08:12:21 MDT 2019 | Date : Mon Dec 6 08:31:17 2021 | Host : Rievaulx running 64-bit major release (build 9200) | Command : report_cdc | Design : transfer | Device : 7k70t-fbv676 | Speed File : -1 PRODUCTION 1.12 2017-02-17 -------------------------------------------------------------------------------------- CDC Report Severity Source Clock Destination Clock CDC Type Exceptions Endpoints Safe Unsafe Unknown No ASYNC_REG -------- ------------ ----------------- ----------------------- ------------------- --------- ---- ------ ------- ------------ Warning clk_src2 clk_dest No Common Primary Clock Asynch Clock Groups 4 4 0 0 0 Warning clk_dest clk_src2 No Common Primary Clock Asynch Clock Groups 4 4 0 0 4 Info clk_src1 clk_dest No Common Primary Clock Asynch Clock Groups 2 2 0 0 0 Info clk_dest clk_src1 No Common Primary Clock Asynch Clock Groups 2 2 0 0 0
Using 'pretty_print_cdc' the 4 "no ASYNCH_REG" warnings can be traced back to CDC-5#1 and hence the start and end pins of the path so that the missing constraints or attributes can be applied.
Conclusions
I've always viewed the issue of paths correctly crossing a clock domain to be one where "education" is better than "automation" so that understanding is maintained. By "automation" I mean providing a self-contained solution that can be brought out and applied mindlessly, i.e. without thought. Metastability issues are significant in that they are often where simulation deviates from reality. Automation gives reassurances that the correct solutions have been implemented, but the danger is the designer overlooks their presence and forgets how to perform the important task reliably. For as long as false path constraints had to be specified from source register to the first double retime register, a self-contained solution was only ever a partial solution. This adds the risk that the designer might omit the false path constraint from the constraints file and not be aware of which part of the solution had been solved, and more importantly which part was left to them to complete.
A separate (personal) goal of mine is to retain the re-usability of component code by avoiding inflicting constraints on another instantiation by hard coding them into VHDL attributes. So my attitude is to always put constraints in a constraints file (XDC) specific to a design (full image, or SCOPED_TO_REF to an entity) in preference to VHDL attributes. This maximises the reusability of the VHDL code for including as library components in multiple designs.
I find my initial instincts compromised on two accounts:
- The specification of asynchronous clock groups globally (once) instead of multiple individual false paths reduces the risks of forgetting to set up the timing exceptions.
- The sole purpose of the double retime registers is one that always requires the ASYNC_REG constraint to be specified, no matter where it is instantiated. The competing risk is that the ASYNC_REG constraint will be omitted from an accompanying constraints file, or the constraints file does exist with the correct constraints and is nevertheless omitted from the FPGA build.
Finally, it feels there are some design checks that need to be implemented post synthesis as a matter of course. The two highlighted here are:
- Critical CDC issues
- Over specified false path constraints that point to a risk, that being a drop in clarity of thought or understanding of the design.
References
- Github Source Code
- Xilinx Vivado QuickTake: Advanced Timing Exceptions - False Path, Min-Max Delay and Set Case Analysis
- Vivado Design Suite User Guide, Using Constraints, UG903
- Vivado Design Suite Properties Reference Guide, UG912
- Specifying Boundary Timing Constraints in Vivado
- Automating Code Review Design Checks in Vivado
- Visualising Clock Domain Crossings in Vivado