Main Content

Use Multicycle Path Constraints to Meet Timing for Slow Paths

This example shows how to apply multicycle path constraints in your design to meet timing requirements. Using multicycle path constraints can save area and reduce synthesis run times. For more information, see Meet Timing Requirements Using Enable-Based Multicycle Path Constraints.

Algorithms modeled in Simulink® for HDL code generation can have multiple sample rates. These multiple rates can be part of the Simulink model or can be introduced with HDL Coder™ options, such as oversampling. When you enable oversampling, the generated HDL code can run on the FPGA at a faster clock rate. This faster rate allows additional optimizations to take effect. To learn more about specifying an oversampling value, see Specifying the Oversampling Value.

When HDL Coder is configured to use a single clock, it generates a timing controller to control clocked elements, such as delays, at different sample rates with clock enables. These clock enables are synchronous to the single clock and toggle at rates that are multiple times slower than the base clock. The data paths between slow-clocked element pairs are called multicycle paths because they allow data to take multiple clock cycles to travel. However, synthesis tools cannot infer this acceptable delay directly from the HDL code. The tools assume that data changes every cycle and must travel from one register to the next within one clock cycle. Synthesis tools have to take more effort to meet the excessive timing requirement and therefore can fail timing. By declaring a set of data paths as multicycle paths and providing the actual timing of these paths to the downstream synthesis tool, HDL Coder can simplify and accelerate the process of meeting the desired timing constraints for a design.

This example shows how to generate multicycle path constraints in HDL Coder so that you can specify timing requirements and enable efficient timing analysis in the synthesis tool.

Apply Multicycle Constraints Using HDL Coder

This example uses Xilinx® Vivado® 2020.2 post place and routing static timing analysis results for a Zynq® UltraScale+(TM) device (xazu11eg-ffvf1517-1-i) to show the impact of enabled multicycle path constraints. HDL Coder generates constraint files in XDC format for Xilinx Vivado, UCF format for Xilinx ISE, and SDC format for Altera Quartus II.

In this example, the hdlcoder_multi_cycle_path_constraints model contains a direct-form FIR filter with an adder chain in the critical path. The input data rate of this filter is 2MHz, but the goal of this design is to run as fast as possible so that it can be integrated with other IPs that require high frequency. First, set a 130MHz clock frequency without any timing optimization by setting the TargetFrequency to 130. Because you are modeling with actual hardware rates by setting the Sample Time of the Random Number block to .5e-6, or 2MHz, enable TreatRatesAsHardwareRates to allow HDL Coder to calculate an oversampling value needed to meet your target frequency.

load_system('hdlcoder_multi_cycle_path_constraints');
open_system('hdlcoder_multi_cycle_path_constraints/Subsystem/Dot Product');
hdlset_param('hdlcoder_multi_cycle_path_constraints','TargetFrequency',130);
hdlset_param('hdlcoder_multi_cycle_path_constraints','TreatRatesAsHardwareRates','on');
set_param('hdlcoder_multi_cycle_path_constraints','SimulationCommand','update');

Generate HDL code with these settings and inspect the generated model. The generated model is identical to the original model.

makehdl('hdlcoder_multi_cycle_path_constraints/Subsystem');
load_system('gm_hdlcoder_multi_cycle_path_constraints');
set_param('gm_hdlcoder_multi_cycle_path_constraints','SimulationCommand','update');
open_system('gm_hdlcoder_multi_cycle_path_constraints/Subsystem/Dot Product');
### Generating HDL for 'hdlcoder_multi_cycle_path_constraints/Subsystem'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoder_multi_cycle_path_constraints', { 'HDL Code Generation' } )">hdlcoder_multi_cycle_path_constraints</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdlcoder_multi_cycle_path_constraints'.
### Begin compilation of the model 'hdlcoder_multi_cycle_path_constraints'...
### Working on the model 'hdlcoder_multi_cycle_path_constraints'...
### <a href="matlab:configset.internal.open('hdlcoder_multi_cycle_path_constraints','AdaptivePipelining')">'AdaptivePipelining'</a> is set to 'Off' for the model. 'AdaptivePipelining' can improve the achievable clock frequency and reduce the area usage on FPGA boards. To enable adaptive pipelining, please set the option to 'On'. When adaptive pipelining is enabled, it inserts pipeline registers to create patterns that efficiently map blocks to DSP units on the target FPGA device.
### <a href="matlab:configset.internal.open('hdlcoder_multi_cycle_path_constraints','LUTMapToRAM')">'LUTMapToRAM'</a> is set to 'On' for the model. This option is used to map lookup tables to a block RAM in hardware.  To disable pipeline insertion for mapping lookup tables to RAM, please set the option to 'Off'.
### Working on... <a href="matlab:configset.internal.open('hdlcoder_multi_cycle_path_constraints', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdlcoder_multi_cycle_path_constraints' ....
### Copying DUT to the generated model....
### Model generation complete.
### Begin VHDL Code Generation for 'hdlcoder_multi_cycle_path_constraints'.
### MESSAGE: The design requires 65 times faster clock with respect to the base rate = 5e-07.
### Begin VHDL Code Generation for 'Subsystem_tc'.
### Working on Subsystem_tc as hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_tc.vhd.
### Code Generation for 'Subsystem_tc' completed.
### Working on hdlcoder_multi_cycle_path_constraints/Subsystem/Dot Product as hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Dot_Product.vhd.
### Working on hdlcoder_multi_cycle_path_constraints/Subsystem as hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem.vhd.
### Generating package file hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_pkg.vhd.
### Code Generation for 'hdlcoder_multi_cycle_path_constraints' completed.
### Writing Vivado multicycle constraints XDC file <a href="matlab:edit('hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_constraints.xdc')">hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_constraints.xdc</a>
### Creating HDL Code Generation Check Report file:///tmp/Bdoc23b_2361005_1074364/tp5b2d2056/hdlcoder-ex62646573/hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_report.html
### HDL check for 'hdlcoder_multi_cycle_path_constraints' complete with 0 errors, 0 warnings, and 4 messages.
### HDL code generation complete.

The generated HDL code fails to meet the 130MHz timing requirement for the clock. The timing requirement is 7.692 ns, or 1/130MHz, and a negative slack indicates a timing violation of this requirement.

To meet timing requirements, use multicycle path constraints. Check the original model.

open_system('hdlcoder_multi_cycle_path_constraints/Subsystem');

The Dot Product subsystem is surrounded by delays that run at the desired 2MHz data rate. The design can tolerate multiple clock cycles for the data to propagate through it because of the oversampling value set by enabling TreatRatesAsHardwareRates. HDL Coder requires multicycle regions to be surrounded by slow-clocked elements, such as these delays, so that the constraints can define the paths among them as multicycle paths. Enable MulticyclePathConstraints and HDL Coder generates an additional file during HDL code generation.

hdlset_param('hdlcoder_multi_cycle_path_constraints', 'MulticyclePathConstraints', 'on');

Increase the target frequency to 300MHz to increase the clock rate.

hdlset_param('hdlcoder_multi_cycle_path_constraints', 'TargetFrequency', 300);

Generate HDL code and the multicycle path constraints.

makehdl('hdlcoder_multi_cycle_path_constraints/Subsystem');
### Generating HDL for 'hdlcoder_multi_cycle_path_constraints/Subsystem'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoder_multi_cycle_path_constraints', { 'HDL Code Generation' } )">hdlcoder_multi_cycle_path_constraints</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdlcoder_multi_cycle_path_constraints'.
### Begin compilation of the model 'hdlcoder_multi_cycle_path_constraints'...
### Working on the model 'hdlcoder_multi_cycle_path_constraints'...
### <a href="matlab:configset.internal.open('hdlcoder_multi_cycle_path_constraints','AdaptivePipelining')">'AdaptivePipelining'</a> is set to 'Off' for the model. 'AdaptivePipelining' can improve the achievable clock frequency and reduce the area usage on FPGA boards. To enable adaptive pipelining, please set the option to 'On'. When adaptive pipelining is enabled, it inserts pipeline registers to create patterns that efficiently map blocks to DSP units on the target FPGA device.
### <a href="matlab:configset.internal.open('hdlcoder_multi_cycle_path_constraints','LUTMapToRAM')">'LUTMapToRAM'</a> is set to 'On' for the model. This option is used to map lookup tables to a block RAM in hardware.  To disable pipeline insertion for mapping lookup tables to RAM, please set the option to 'Off'.
### Working on... <a href="matlab:configset.internal.open('hdlcoder_multi_cycle_path_constraints', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdlcoder_multi_cycle_path_constraints' ....
### Copying DUT to the generated model....
### Model generation complete.
### Begin VHDL Code Generation for 'hdlcoder_multi_cycle_path_constraints'.
### MESSAGE: The design requires 150 times faster clock with respect to the base rate = 5e-07.
### Begin VHDL Code Generation for 'Subsystem_tc'.
### Working on Subsystem_tc as hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_tc.vhd.
### Code Generation for 'Subsystem_tc' completed.
### Working on hdlcoder_multi_cycle_path_constraints/Subsystem/Dot Product as hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Dot_Product.vhd.
### Working on hdlcoder_multi_cycle_path_constraints/Subsystem as hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem.vhd.
### Generating package file hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_pkg.vhd.
### Code Generation for 'hdlcoder_multi_cycle_path_constraints' completed.
### Writing Vivado multicycle constraints XDC file <a href="matlab:edit('hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_constraints.xdc')">hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_constraints.xdc</a>
### Creating HDL Code Generation Check Report file:///tmp/Bdoc23b_2361005_1074364/tp5b2d2056/hdlcoder-ex62646573/hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_report.html
### HDL check for 'hdlcoder_multi_cycle_path_constraints' complete with 0 errors, 0 warnings, and 4 messages.
### HDL code generation complete.

Inspect the generated constraint XDC file.

dbtype('hdl_prj/hdlsrc/hdlcoder_multi_cycle_path_constraints/Subsystem_constraints.xdc');
1     # Multicycle constraints for clock enable: Subsystem_tc.u1_d150_o0
2     set enbregcell [get_cells -hier -filter {mcp_info=="Subsystem_tc.u1_d150_o0"}]
3     set enbregnet [get_nets -of_objects [get_pins -of_objects $enbregcell -filter {DIRECTION == OUT}]]
4     set reglist1 [get_cells -of [filter [all_fanout -flat -endpoints_only $enbregnet] IS_ENABLE]]
5     set_multicycle_path 150 -setup -from $reglist1 -to $reglist1 -quiet
6     set_multicycle_path 149 -hold -from $reglist1 -to $reglist1 -quiet
7     
8     # Multicycle constraints for clock enable: Subsystem_tc.u1_d150_o1
9     set enbregcell [get_cells -hier -filter {mcp_info=="Subsystem_tc.u1_d150_o1"}]
10    set enbregnet [get_nets -of_objects [get_pins -of_objects $enbregcell -filter {DIRECTION == OUT}]]
11    set reglist2 [get_cells -of [filter [all_fanout -flat -endpoints_only $enbregnet] IS_ENABLE]]
12    set_multicycle_path 150 -setup -from $reglist2 -to $reglist2 -quiet
13    set_multicycle_path 149 -hold -from $reglist2 -to $reglist2 -quiet
14    
15    # Multicycle constraints from clock enable: Subsystem_tc.u1_d150_o1 to clock enable: Subsystem_tc.u1_d150_o0
16    set_multicycle_path 149 -setup -from $reglist2 -to $reglist1 -quiet
17    set_multicycle_path 149 -hold -from $reglist2 -to $reglist1 -quiet
18    
19    # Multicycle constraints from clock enable: Subsystem_tc.u1_d150_o0 to clock enable: Subsystem_tc.u1_d150_o1
20    set_multicycle_path 151 -setup -from $reglist1 -to $reglist2 -quiet
21    set_multicycle_path 149 -hold -from $reglist1 -to $reglist2 -quiet
22    

These constraints first find flip flops driven by the 2MHz clock enable signal. Then, they define the paths among these flip flops to allow up to 150 cycles for data to propagate.

Inspect the generated model.

open_system('gm_hdlcoder_multi_cycle_path_constraints/Subsystem/Dot Product');
set_param('gm_hdlcoder_multi_cycle_path_constraints', 'SimulationCommand', 'update');

The generated model and HDL code are identical to the previous results because generating enabled based multicycle path constraints does not alter the HDL architecture. However, the multicycle path constraints enable the design to run at 300MHz on the FPGA.

Additional Information About Multicycle Path Constraints

Multicycle path constraints are required for synthesis tools to understand timing requirements. This information is extracted from the Simulink model since it cannot be inferred from the generated HDL code. Multicycle path constraints identify paths between clocked elements driven by the same clock enable. It can fail to meet timing requirements in certain cases. For example, a data path is not recognized as a multicycle path, if it is not gated with both input and output delays or is between two delays of different rates. Therefore, if you want to use multicycle path constraints for certain parts in your design, it is important to retain the multicycle paths in that region from being altered by optimizations introducing pipelines, such as input and output pipelining, clock rate pipelining, adaptive pipelining resource sharing, streaming, pipelined math operations, e.g. Newton-Raphson method for sqrt or recip, Cordic algorithm for trigonometric functions, and floating-point IP mapping.