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.

Introduction

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. With oversampling specified, the generated HDL code will run on the FPGA at a faster clock rate. This faster rate allows additional optimizations to take effect.

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 demonstrates how to generate multicycle path constraints in HDL Coder so that timing requirements may be specified, allowing efficient timing analysis in the synthesis tool.

Applying multicycle constraints using HDL Coder

In this example, we use 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 based multicycle path constraints. Other synthesis tools and devices have similar behavior. HDL Coder generates constraint files of XDC format for Xilinx Vivado, UCF format for Xilinx ISE, and SDC format for Altera Quartus II.

Consider the example, hdlcoder_multi_cycle_path_constraints.slx. The model contains a direct form FIR filter with an adder chain in the critical path. While the input data rate of this filter is specified to be 2MHz, we want this design to run as fast as possible so that it can be integrated with other IPs requiring high frequency. We start by choosing a 130MHz clock frequency without any timing optimization by setting the Oversampling factor to 65 and the Target Frequency to 130.

bdclose('all');
load_system('hdlcoder_multi_cycle_path_constraints');
open_system('hdlcoder_multi_cycle_path_constraints/Subsystem/Dot Product');
hdlset_param('hdlcoder_multi_cycle_path_constraints', 'Oversampling', 65);
hdlset_param('hdlcoder_multi_cycle_path_constraints', 'TargetFrequency', 130);
set_param('hdlcoder_multi_cycle_path_constraints', 'SimulationCommand', 'update');

Generate HDL with these settings and inspect the generated model. Notice that the generated model is actually 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 = 2.
### 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/Bdoc23a_2213998_3307074/tp49a7f6b9/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 3 messages.
### HDL code generation complete.

The generated HDL fails to meet the timing requirement for the clock at 130MHz. As shown in the timing report snippet below, the timing requirement is 7.692 ns (1/130MHz) and a negative slack indicates a timing violation of this requirement. Other synthesis tools' timing reports may look different, although the critical path from this example design will remain the same.

We are going to use multicycle path constraints to meet timing requirements. Check the original model.

open_system('hdlcoder_multi_cycle_path_constraints/Subsystem');

Notice that the Dot Product subsystem is surrounded by delays running at the desired 2MHz data rate. Due to the specified 65x oversampling, the design can tolerate multiple clock cycles for the data to propagate through it. 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. Turn MulticyclePathConstraints on and HDL Coder will generate an additional file.

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

We can even increase the target frequency to 300MHz.

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

Generate HDL and 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 = 2.
### 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/Bdoc23a_2213998_3307074/tp49a7f6b9/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 3 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 that are driven by the 2MHz clock enable signal. Then, they define the paths among these flip flops multicycle paths 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. The design was previously unable to meet the desired timing at 130MHz. However, when you specify multicycle path constraints, this design can 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.