As you build your constraints into your design, there are a few best practices that can be used to ensure the constraints are properly and efficiently designed for your application.
The organization of your constraints within the .xdc file helps the compiler correctly analyze the constraints in the design. The compiler will interpret constraints in a sequential manner, from top to bottom, until all constraints have been analyzed. The recommended constraint organization structure from Xilinx UG903 Using Constraints Guide is the following:
## Timing Assertions Section
# Primary clocks
# Virtual clocks
# Generated clocks
# Clock Groups
# Input and output delay constraints
## Timing Exceptions Section
# False Paths
# Max Delay / Min Delay
# Multicycle Paths
# Case Analysis
# Disable Timing
Be sure to include comments in your constraints file that clearly indicates the intent of the constraint, and the signal that is being acted upon. Clearly labeling this information, along with any decisions that went into including the constraint, will help any reader of the .xdc file to quickly identify the reason behind the constraint and its location in the design.
# User Clock Constraint: the value is selected based on the line rate of the module
create_clock -name TS_port0_user_clk_i -period 6.206 [get_pins %ClipInstancePath%/AuroraBlock.Port0_clock_module_i/user_clk_net_i/O]
Be sure to create all clocks in your design, using create_clock, that are generated within the CLIP. An example of such clocks are TXOUTCLK and RXOUTCLK, which are generated by the GTXE2_CHANNEL primitive that resides in the CLIP of every MGT design. Any missing clock in your design could lead to issues where your compilation may pass timing, but fail to work consistently during functional testing.
If the clock is generated in the LV FPGA design, such as a base clock source from the LV FPGA project, you do not need to create constraints for these clocks. These constraints are automatically generated by your LV FPGA project.
Asynchronous resets which originate inside your CLIP should also be added to your constraints file in order to remove false timing violations that may occur. Identify all reset signals in your CLIP design and be sure to include constraints as required.
Info: If you choose to assign a top level reset signal in LV FPGA’s CLIP Wizard, you should not create a constraint for this signal in the .xdc file.
False Path and Max Delay
Some typical constraints that are used in your .xdc file are set_false_path and set_max_delay. Whether timing is evaluated on an asynchronous signal or a clock domain crossing, not including constraints for these paths will result in the tools incorrectly analyzing the timing for these paths, which could possibly result in timing failures. It is important to understand the implications and the correct application of set_false_path in order to successfully compile your design while not mistakenly ignoring time-critical paths in your design that need analysis.
Anytime set_false_path is used, care must be taken to understand where the constraint begins and where it ends. Using both –to and –from creates the most control over the path of interest to be ignored. Be careful using just one or the other, as connected paths other than the one you intend to constrain in the design may be ignored that are timing critical.
NI recommends only using set_max_delay constraints in place of set_false_path constraints. While both commands could be utilized to create a successfully constrained project, set_max_delay provides more timing control over path delay than set_false_path.
For instance, a path delay of 20 ns would not be reported to the designer if a set_false_path command was used, yet the compiler could choose to route your signal with any delay it needed based on the constraint. On the other hand, using set_max_delay at 10 ns would safely constrain the maximum path delay in the fabric to 10ns. Experiment with relaxing the maximum delay path value to find the optimal value for your particular design.
When setting two clock domains asynchronous of each other in your constraints file, it is common to use the set_clock_groups Tcl command. This command will ignore any timing analysis between two clock domains. A scenario where using this command is acceptable is when you have a clock domain crossing between two clocks that exist entirely within the CLIP and are not related to one another.
With the High Speed Serial Instruments, there are multiple LV FPGA base clocks that are created and constrained for you in the design. Therefore, if any LV FPGA base clocks in the design need to be set asynchronous from a clock created in your CLIP, it is unsafe to use the set_clock_groups command. This is due to other parts of the design outside of the CLIP that may be affected by the clocking relationship. For instance, bringing a clock created in the CLIP into LV FPGA and setting it asynchronous of a base clock can create unsafe conditions where timing may need to be analyzed on the diagram and in the “black box” fixed logic of the LV FPGA design.
The best practice for constraining a properly implemented clock domain crossing is to clearly mark any clock domain crossings (CDCs) and their related D flop in the design, and use the set_max_delay or set_false_path command for all registers or FIFOs crossing into a new clock domain. Some example constraints that performs this function are below:
set_false_path -to [get_pins -hier *aurora_64b66b_cdc_to*/D] (all D inputs of cdc synchronization registers are ignored)
set_max_delay 10 -to [get_pins -hier *aurora_64b66b_cdc_to*/D] (all D inputs of cdc synchronization registers have maximum delay of 10 ns)
Creating .xdc Constraints
When you are creating a path to the pin or cell that you are trying to constrain, there are several different methods available to create the constraint path using Vivado constraint syntax. Here are some tips to consider while building the path to your pin, port, or cell in your design. A majority of this section is adopted from Xilinx UG903 Using Constraints Guide chapter 2, Creating Synthesis Constraints:
- When you first are creating your .xdc constraints, you may use the Tcl Console to validate the syntax of the .xdc commands before saving them in the .xdc files. This can be performed by creating a project in Vivado and opening the elaborated or synthesized design, which will then allow you to copy/paste constraints in the Tcl Console. Refer to the Xilinx UG903 guide for more information.
- It is recommended to avoid using -hierarchical in your constraints and explicitly use the / character at all levels of hierarchy to avoid potential problems with finding the path in memory. The reason is that Vivado synthesis can sometimes flatten hierarchy levels, which then removes some of the hierarchy path from memory. Creating a constraint that uses the -hierarchical option with partial paths, such as using wildcards across multiple levels of hierarchy, may return a warning that the object was not found. This example is adapted from the Xilinx UG903 guide:
RTL Design Example: register in overall design
If the hierarchy is flattened, the following constraints will be found in the resulting flattened design. However, if the hierarchy is not flattened, they will not be found. Note that a wildcard is used to traverse multiple levels in both instances. Because a wildcard is used to represent multiple levels of hierarchy with the hierarchical command, Vivado cannot find the path in the design.
% get_cells –hierarchical *inst_B/control_reg (path not found/constraint not applied in design, missing inst_A level)
% get_cells inst_A*control_reg (path not found/constraint not applied in design, missing inst_b level)
Explicitly writing all or some part of every level in the hierarchy ensures that constraints are properly found in both flattened and unflattened hierarchies, leading up to the object you wish to constraint. The following is a correction to the above constraints to be found in any synthesis/implementation of control_reg. Wildcards are still used within a level of hierarchy, but do not traverse any hierarchy level:
% get_cells inst_A/inst_B/*_reg (successfully finds all pins/cells with *_reg at the control_reg level)
% get_cells inst_*/inst_B/control_reg (successfully finds all pins/cells with inst_* at the top inst_A level)
Please look at the following Xilinx Answer Record for more information: AR# 62136 Vivado Constraints - Understanding how hierarchy separator "/" works with wildcard * in XDC and UCF
- When working with NI Devices, we provide a %ClipInstancePath% token that appends the overall VHDL hierarchy used by the LV FPGA compiler to your existing top level VHDL path. For instance, if you have a constraint for your CLIP that works in Vivado, when you bring that constraint into LV FPGA, you may append the token to the beginning of the object path so that the compiler can still find it in memory:
% get_cells inst_A/inst_B/control_reg(Vivado constraint)
% get_cells %ClipInstancePath%/inst_A/inst_B/control_reg(LV FPGA constraint that adds additional hierarchy levels)
You may reference the Constraints and Hierarchy section of the NI High-Speed Serial Instruments User Manual for more information.
Design Analysis and Closure Techniques
When working with a VHDL design in Vivado, it is common to run into timing violations or design issues. Vivado has provided many tools for analysis and debug of a design as it relates to logic or constraints. One powerful tool that will help identify the need for timing constraints is the Report Timing Summary tool. You can use this tool once you have synthesized your design in Vivado. The report shows endpoints which are missing create_clock constraints (no_clock) or violate setup and hold timing (potential max_delay candidate). For more information on using various Vivado tools for analysis and timing closure, refer to the following link: Vivado Design Suite User Guide - Design Analysis and Closure Techniques