Main Content

Use Delay Absorption While Modeling with Latency

Learn how to model your design with latency to apply the delay absorption optimization that runs when you generate HDL code with delay balancing.

Delay absorption is part of the delay balancing optimization. Delay absorption uses design delays in place of pipeline delays introduced from optimizations to prevent unused latency from being added to your design. You can use delay absorption by modeling with latency, which means that you add design delays to your model to take the place of introduced latency from optimizations. By modeling your design with latency, HDL Coder™ can use delay absorption to absorb the design delays and not introduce extra pipeline delays that add latency to your model, which prevents timing differences between the original model and generated model and allows HDL Coder to generate a functionally equivalent model to the generated HDL code.

Delays in your design can either be design delays or pipeline delays. Design delays are delays that you manually insert in your design by using Delay blocks, or other blocks that have state, including Queue, HDL FIFO, or Buffer blocks. Pipeline delays are delays that are generated by optimization settings, such as input or output pipelining options or block implementation settings, such as the ShiftAdd implementation for a Divide block and the CORDIC approximation for a Trigonometric Function block.

Certain block implementations, floating-point operations, and optimization settings, such as input pipelining or resource sharing, introduce latency to the generated HDL code and generated model. The additional latency results in a timing difference between the original model and the generated model. To avoid this timing difference, such as when you are using a control system with a feedback loop, you can add design delays to your model. For delay absorption to absorb the design delays:

  • Place a Delay block after the block that is introducing latency. You can place the Delay block anywhere downstream on the data path from the block that introduces latency.

  • Set the Delay block Delay length parameter to a value equal to the block latency.

By adding Delay blocks to your original model, you can simulate your original model with latency.

These blocks can introduce latency:

  • Divide, Sqrt, and Reciprocal blocks that have custom latency value greater than zero

  • Trigonometric Function blocks that have Function set to sin, cos, sincos, cos+jsin, or atan2 and Approximation method set to CORDIC

  • Native floating-point operators that have the HDL block property LatencyStrategy set to Max, Min, or a custom value greater than zero

To learn about blocks that have custom latency with fixed-point types, open the HDLMathLib library. The library contains fixed-point blocks that have control signals.

open_system('HDLMathLib')

Model with Latency When Blocks Introduce Latency

To learn how HDL Coder absorbs delays, open the model hdlcoder_absorb_delay_timing.

open_system('hdlcoder_absorb_delays')
set_param('hdlcoder_absorb_delays', 'SimulationCommand', 'Update')

Inside the HDL_DUT subsystem, you see a Delay block that has Delay length equal to 12 beside the Divide block. This Delay length corresponds to the latency of the division operation for fixed-point data types. In this case, the required Delay length is the sum of the bitwidth, 8, and 4, which is equal to 12.

load_system('hdlcoder_absorb_delays')
open_system('hdlcoder_absorb_delays/HDL_DUT')

To generate HDL code for the DUT subsystem, use the makehdl function.

makehdl('hdlcoder_absorb_delays/HDL_DUT')
### Generating HDL for 'hdlcoder_absorb_delays/HDL_DUT'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoder_absorb_delays', { 'HDL Code Generation' } )">hdlcoder_absorb_delays</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdlcoder_absorb_delays'.
### Begin compilation of the model 'hdlcoder_absorb_delays'...
### Begin compilation of the model 'hdlcoder_absorb_delays'...
### Working on the model 'hdlcoder_absorb_delays'...
### Working on... <a href="matlab:configset.internal.open('hdlcoder_absorb_delays', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdlcoder_absorb_delays' ....
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### Begin VHDL Code Generation for 'hdlcoder_absorb_delays'.
### Working on hdlcoder_absorb_delays/HDL_DUT/Divide as hdlsrc/hdlcoder_absorb_delays/Divide.vhd.
### Working on hdlcoder_absorb_delays/HDL_DUT as hdlsrc/hdlcoder_absorb_delays/HDL_DUT.vhd.
### Code Generation for 'hdlcoder_absorb_delays' completed.
### Creating HDL Code Generation Check Report file:///tmp/Bdoc23b_2361005_1048037/tp07bba342/hdlcoder-ex00529152/hdlsrc/hdlcoder_absorb_delays/HDL_DUT_report.html
### HDL check for 'hdlcoder_absorb_delays' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

In the generated model, the delays beside the Divide block are absorbed into the block latency. When you double-click this Divide block, you see the original Divide block and the Delay block with Delay length of 12.

For an example that shows delay absorption for floating-point operations, see Latency Considerations with Native Floating Point.

Model with Latency When Optimizations Introduce Latency

Optimizations such as streaming can introduce latency. For example, open the model hdlcoder_absorb_delay_streaming. The DUT contains a Delay block to model the original design with latency and a subsystem that contains a Product block. The inputs are vectors of size 10.

load_system('hdlcoder_absorb_delay_streaming');
open_system('hdlcoder_absorb_delay_streaming/DUT');
set_param('hdlcoder_absorb_delay_streaming','SimulationCommand','Update');

To stream the vector computations, set the HDL block property StreamingFactor to 10 on the lower-level subsystem. To model with latency, allow delay absorption to absorb Delay blocks in your model by using the model property AllowDelayDistribution, which is enabled by default. Then, generate HDL code for the DUT subsystem using the makehdl function.

hdlset_param('hdlcoder_absorb_delay_streaming/DUT/Subsystem', 'StreamingFactor', 10);
hdlget_param('hdlcoder_absorb_delay_streaming', 'AllowDelayDistribution');
makehdl('hdlcoder_absorb_delay_streaming/DUT');
### Generating HDL for 'hdlcoder_absorb_delay_streaming/DUT'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoder_absorb_delay_streaming', { 'HDL Code Generation' } )">hdlcoder_absorb_delay_streaming</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdlcoder_absorb_delay_streaming'.
### Begin compilation of the model 'hdlcoder_absorb_delay_streaming'...
### Working on the model 'hdlcoder_absorb_delay_streaming'...
### Working on... <a href="matlab:configset.internal.open('hdlcoder_absorb_delay_streaming', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdlcoder_absorb_delay_streaming' ....
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### Generating new validation model: <a href="matlab:open_system('hdlsrc/hdlcoder_absorb_delay_streaming/gm_hdlcoder_absorb_delay_streaming_vnl')">gm_hdlcoder_absorb_delay_streaming_vnl</a>.
### Validation model generation complete.
### Begin VHDL Code Generation for 'hdlcoder_absorb_delay_streaming'.
### MESSAGE: The design requires 10 times faster clock with respect to the base rate = 0.1.
### Begin VHDL Code Generation for 'DUT_tc'.
### Working on DUT_tc as hdlsrc/hdlcoder_absorb_delay_streaming/DUT_tc.vhd.
### Code Generation for 'DUT_tc' completed.
### Working on hdlcoder_absorb_delay_streaming/DUT/Subsystem as hdlsrc/hdlcoder_absorb_delay_streaming/Subsystem.vhd.
### Working on hdlcoder_absorb_delay_streaming/DUT as hdlsrc/hdlcoder_absorb_delay_streaming/DUT.vhd.
### Generating package file hdlsrc/hdlcoder_absorb_delay_streaming/DUT_pkg.vhd.
### Code Generation for 'hdlcoder_absorb_delay_streaming' completed.
### Creating HDL Code Generation Check Report file:///tmp/Bdoc23b_2361005_1048037/tp07bba342/hdlcoder-ex00529152/hdlsrc/hdlcoder_absorb_delay_streaming/DUT_report.html
### HDL check for 'hdlcoder_absorb_delay_streaming' complete with 0 errors, 0 warnings, and 1 messages.
### HDL code generation complete.

When streaming is enabled, a Deserializer block that has 1 cycle of delay is inserted in the generated design. If the original model did not include a Delay block, the generated design would have 1 cycle of extra latency compared to the original design. The delay absorption optimization uses the Delay block in the original model to offset the delay introduced by streaming so that the generated design does not have any added latency. Open the generated model to see the original delay block absorbed after code generation.

open_system('gm_hdlcoder_absorb_delay_streaming/DUT');
set_param('gm_hdlcoder_absorb_delay_streaming','SimulationCommand','Update');

To disable delay absorption from using Delay blocks in the original model, set the model property AllowDelayDistribution to off. Notice that because the delay absorption is disabled, there is now 1 cycle of extra latency in the generated model.

hdlset_param('hdlcoder_absorb_delay_streaming', 'AllowDelayDistribution', 'off');
makehdl('hdlcoder_absorb_delay_streaming/DUT');
open_system('gm_hdlcoder_absorb_delay_streaming/DUT');
### Generating HDL for 'hdlcoder_absorb_delay_streaming/DUT'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoder_absorb_delay_streaming', { 'HDL Code Generation' } )">hdlcoder_absorb_delay_streaming</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdlcoder_absorb_delay_streaming'.
### Begin compilation of the model 'hdlcoder_absorb_delay_streaming'...
### Working on the model 'hdlcoder_absorb_delay_streaming'...
### The DUT requires an initial pipeline setup latency. Each output port experiences these additional delays.
### Output port 1: 1 cycles.
### Working on... <a href="matlab:configset.internal.open('hdlcoder_absorb_delay_streaming', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdlcoder_absorb_delay_streaming' ....
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### Generating new validation model: <a href="matlab:open_system('hdlsrc/hdlcoder_absorb_delay_streaming/gm_hdlcoder_absorb_delay_streaming_vnl')">gm_hdlcoder_absorb_delay_streaming_vnl</a>.
### Validation model generation complete.
### Begin VHDL Code Generation for 'hdlcoder_absorb_delay_streaming'.
### MESSAGE: The design requires 10 times faster clock with respect to the base rate = 0.1.
### Begin VHDL Code Generation for 'DUT_tc'.
### Working on DUT_tc as hdlsrc/hdlcoder_absorb_delay_streaming/DUT_tc.vhd.
### Code Generation for 'DUT_tc' completed.
### Working on hdlcoder_absorb_delay_streaming/DUT/Subsystem as hdlsrc/hdlcoder_absorb_delay_streaming/Subsystem.vhd.
### Working on hdlcoder_absorb_delay_streaming/DUT as hdlsrc/hdlcoder_absorb_delay_streaming/DUT.vhd.
### Generating package file hdlsrc/hdlcoder_absorb_delay_streaming/DUT_pkg.vhd.
### Code Generation for 'hdlcoder_absorb_delay_streaming' completed.
### Creating HDL Code Generation Check Report file:///tmp/Bdoc23b_2361005_1048037/tp07bba342/hdlcoder-ex00529152/hdlsrc/hdlcoder_absorb_delay_streaming/DUT_report.html
### HDL check for 'hdlcoder_absorb_delay_streaming' complete with 0 errors, 0 warnings, and 1 messages.
### HDL code generation complete.

You can also disable delay absorption for a specific Delay block by disabling the HDL block property AllowDelayDistribution for the block. For more information, see AllowDelayDistribution.

Model with Latency in a Feedback Loop

When you model with latency in a feedback loop, you can either:

  • Use clock-rate pipelining. For more information see Clock-Rate Pipelining.

  • Use delay absorption. For example, you can model a feedback loop at the clock rate with some of amount of latency expressed as design delays to absorb the latency introduced from native floating-point operators or pipeline optimizations.

In this example, use delay absorption to model with latency in a feedback loop.

This example contains output pipelines to help optimize the speed of the design, but at the cost of introducing an extra cycle of latency for each pipeline. This additional latency is balanced during delay balancing so that the numerics and functionality of the algorithm are preserved. However, in a feedback loop, delay balancing requires you to model with latency in order to absorb the design delays to prevent a timing mismatch as a result of the pipeline optimizations.

For example, if you generate code with output pipelines added in a feedback loop without modeling with latency, HDL Coder generates a delay balancing error. You can observe this in the delay_absorption_feedback_loop model, where the subsystem delay_absorption_feedback_loop/DUT/Subsystem is in a feedback loop and the delay_absorption_feedback_loop/DUT/Feed_Forward/Sum block has the HDL block property OutputPipeline set to 2.

Load and open the model to its DUT subsystem.

load_system('delay_absorption_feedback_loop');
open_system('delay_absorption_feedback_loop/DUT');

View the non-default parameters by using hdlsaveparams to see the OutputPipeline setting for the Sum block.

hdlsaveparams('delay_absorption_feedback_loop');
%% Set Model 'delay_absorption_feedback_loop' HDL parameters
hdlset_param('delay_absorption_feedback_loop', 'GenerateValidationModel', 'on');
hdlset_param('delay_absorption_feedback_loop', 'HDLSubsystem', 'delay_absorption_feedback_loop/DUT');
hdlset_param('delay_absorption_feedback_loop', 'OptimizationReport', 'on');

% Set Sum HDL parameters
hdlset_param('delay_absorption_feedback_loop/DUT/Feed_Forward/Sum', 'OutputPipeline', 2);

If you generate code by using the makehdl function, there is a delay balancing error in the HDL Code Generation Report. To fix this error, you need to add enough latency in your design to match the amount of latency added from the output pipelining optimization.

In this example, you need two unit delays total, or a single design delay with a Delay Length of two. The error mentions only one extra cycle of latency because the current Delay block in the feedback path is absorbed to handle one of the two extra cycles of latency. Increase the feedback delay block from a Delay Length of one to a Delay Length of two. You can do this by setting the parameter in the Delay block or by using this command:

set_param('delay_absorption_feedback_loop/DUT/Delay', 'DelayLength', '2');

Generate HDL code by using the makehdl function.

makehdl('delay_absorption_feedback_loop/DUT');
### Generating HDL for 'delay_absorption_feedback_loop/DUT'.
### Using the config set for model <a href="matlab:configset.showParameterGroup('delay_absorption_feedback_loop', { 'HDL Code Generation' } )">delay_absorption_feedback_loop</a> for HDL code generation parameters.
### Running HDL checks on the model 'delay_absorption_feedback_loop'.
### Begin compilation of the model 'delay_absorption_feedback_loop'...
### Working on the model 'delay_absorption_feedback_loop'...
### The code generation and optimization options you have chosen have introduced additional pipeline delays.
### The delay balancing feature has automatically inserted matching delays for compensation.
### The DUT requires an initial pipeline setup latency. Each output port experiences these additional delays.
### Output port 1: 2 cycles.
### Working on... <a href="matlab:configset.internal.open('delay_absorption_feedback_loop', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_delay_absorption_feedback_loop' ....
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### Generating new validation model: <a href="matlab:open_system('hdlsrc/delay_absorption_feedback_loop/gm_delay_absorption_feedback_loop_vnl')">gm_delay_absorption_feedback_loop_vnl</a>.
### Validation model generation complete.
### Begin VHDL Code Generation for 'delay_absorption_feedback_loop'.
### Working on delay_absorption_feedback_loop/DUT/Feed_Forward as hdlsrc/delay_absorption_feedback_loop/Feed_Forward.vhd.
### Working on delay_absorption_feedback_loop/DUT as hdlsrc/delay_absorption_feedback_loop/DUT.vhd.
### Generating package file hdlsrc/delay_absorption_feedback_loop/DUT_pkg.vhd.
### Code Generation for 'delay_absorption_feedback_loop' completed.
### Generating HTML files for code generation report at <a href="matlab:web('/tmp/Bdoc23b_2361005_1048037/tp07bba342/hdlcoder-ex00529152/hdlsrc/delay_absorption_feedback_loop/html/delay_absorption_feedback_loop_codegen_rpt.html')">delay_absorption_feedback_loop_codegen_rpt.html</a>
### Creating HDL Code Generation Check Report file:///tmp/Bdoc23b_2361005_1048037/tp07bba342/hdlcoder-ex00529152/hdlsrc/delay_absorption_feedback_loop/DUT_report.html
### HDL check for 'delay_absorption_feedback_loop' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

Open the generated model to view the absorbed design delays. The feedback delays were absorbed and moved into the Feed_Forward subsystem to handle the latency added from output pipelining. No extra latency is introduced as a result of delay absorption.

open_system('gm_delay_absorption_feedback_loop/DUT');
set_param('gm_delay_absorption_feedback_loop', 'SimulationCommand', 'update');

When applying delay absorption in a feedback loop, follow these guidelines:

  • Add the design delays to be absorbed at the same subsystem level as the feedback loop.

  • Delay absorption cannot absorb upstream latency from a feedback loop, which means that if there are design delays placed before a feedback loop in your model, delay absorption does not absorb those upstream design delays. If you do have upstream latency that is not absorbed, HDL code generation produces a delay balancing error message in the HDL code generation report. Use clock-rate pipelining to model with latency when there is upstream latency in your design.

  • Delay absorption cannot absorb design delays separated from the block that introduces latency by a component that takes in a zero-input value and outputs a non-zero value, such as a NOT Logical Operator block.

Related Topics