Main Content

Delay Balancing and Validation Model Workflow in HDL Coder

This example shows how HDL Coder™ can automatically balance delays within a model. HDL Coder may introduce additional delays in the HDL implementation for a given model. These delays may be introduced by either certain block implementations or by optimizations for the purpose of improving the efficiency of the hardware implementations. However, introducing delays on only certain paths can result functional behavior that is different from the original intent of the user model, thereby violating functional equivalence between the original user model and the HDL implementation.

Delay Balancing is a feature supported by HDL Coder for automatically balancing such newly introduced delays across all parallel paths, ensuring that functional integrity is preserved with reference to the original model. This equivalence relationship can be confirmed by invoking the validation model workflow that enables the user to visualize the HDL Code-generation model, the delays introduced by implementations and those introduced by delay balancing and verify the equivalence relationship with the original model.

Implementations and Optimizations introduce Latency

Some of the arithmetic blocks in Simulink® require complex hardware algorithms. Consider, for example, the reciprocal square root block. This block computes its answer in a single time step in Simulink. If the corresponding hardware implementation should stay cycle-accurate with Simulink, the hardware algorithm for this block must compute in a single clock cycle. However, this results in a long critical path that degrades the clock frequency and efficiency of hardware. Thus, HDL Coder implements this block with a 5-cycle latency, which means that every path containing this block will introduce a 5-cycle delay.

Certain optimizations supported by HDL Coder may also introduce additional delays. For example, specifying InputPipeline or OutputPipeline as an implementation parameter on a block introduces additional pipeline delays in the generated HDL. This is again unmatched across parallel paths and will result in functional differences with the original model.

Consider an example model that contains a square root block implementing the rSqrt function and the Gain3 block along the parallel path has the OutputPipeline HDL Block property set to 2.

load_system('hdl_delaybalancing');
open_system('hdl_delaybalancing/Subsystem');
set_param('hdl_delaybalancing', 'SimulationCommand', 'update');

Validation Model Generation

Due to changes in latency, the HDL Coder always generates a Code Generation model that captures the added delays during implementation. The RTL verification and automatic co-simulation model generation features validate that the RTL simulation of the generated HDL code is bit-accurate and cycle-accurate with the Simulink simulation of the Code-generation model. However, this does not say anything about the functional relationship with the original, user model.

The Validation model enables the user to verify that the functional equivalence of the original, user model with the Code-generation model. This feature is turned on by the model-level parameter, GenerateValidationModel. This parameter can be set by either the hdlset_param command or can be supplied as a makehdl argument. Then, during code generation, notice a message that says that validation model has been generated.

The Validation Model consists of two parts: the DUT from the original model (gm_hdl_delaybalancing_vnl/Subsystem_vnl) and the DUT from the Code-generation model (gm_hdl_delaybalancing_vnl/Subsystem).

hdlset_param('hdl_delaybalancing', 'GenerateValidationModel', 'on');
hdlset_param('hdl_delaybalancing', 'BalanceDelays', 'off');
makehdl('hdl_delaybalancing/Subsystem');
open_system('gm_hdl_delaybalancing_vnl');
set_param('gm_hdl_delaybalancing_vnl', 'SimulationCommand', 'update');
### Working on the model <a href="matlab:open_system('hdl_delaybalancing')">hdl_delaybalancing</a>
### Generating HDL for <a href="matlab:open_system('hdl_delaybalancing/Subsystem')">hdl_delaybalancing/Subsystem</a>
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdl_delaybalancing', { 'HDL Code Generation' } )">hdl_delaybalancing</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdl_delaybalancing'.
### Begin compilation of the model 'hdl_delaybalancing'...
### Working on the model 'hdl_delaybalancing'...
### Working on... <a href="matlab:configset.internal.open('hdl_delaybalancing', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdl_delaybalancing'...
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### Generated model saved at <a href="matlab:open_system('hdlsrc/hdl_delaybalancing/gm_hdl_delaybalancing.slx')">hdlsrc/hdl_delaybalancing/gm_hdl_delaybalancing.slx</a>
### Generating new validation model: '<a href="matlab:open_system('hdlsrc/hdl_delaybalancing/gm_hdl_delaybalancing_vnl')">gm_hdl_delaybalancing_vnl</a>'.
### Validation model generation complete.
### Begin VHDL Code Generation for 'hdl_delaybalancing'.
### MESSAGE: The design requires 3 times faster clock with respect to the base rate = 0.1.
### Begin VHDL Code Generation for 'Subsystem_tc'.
### Working on Subsystem_tc as hdlsrc/hdl_delaybalancing/Subsystem_tc.vhd.
### Code Generation for 'Subsystem_tc' completed.
### Working on hdl_delaybalancing/Subsystem/Sqrt/Sqrt_iv as hdlsrc/hdl_delaybalancing/Sqrt_iv.vhd.
### Working on hdl_delaybalancing/Subsystem/Sqrt/Sqrt_core as hdlsrc/hdl_delaybalancing/Sqrt_core.vhd.
### Working on hdl_delaybalancing/Subsystem/Sqrt as hdlsrc/hdl_delaybalancing/Sqrt.vhd.
### Working on hdl_delaybalancing/Subsystem as hdlsrc/hdl_delaybalancing/Subsystem.vhd.
### Generating package file hdlsrc/hdl_delaybalancing/Subsystem_pkg.vhd.
### Code Generation for 'hdl_delaybalancing' completed.
### Generating HTML files for code generation report at <a href="matlab:hdlcoder.report.openDdg('/tmp/Bdoc24a_2528353_2771371/tp0c35c709/hdlcoder-ex36242447/hdlsrc/hdl_delaybalancing/html/hdl_delaybalancing_codegen_rpt.html')">hdl_delaybalancing_codegen_rpt.html</a>
### Creating HDL Code Generation Check Report file:///tmp/Bdoc24a_2528353_2771371/tp0c35c709/hdlcoder-ex36242447/hdlsrc/hdl_delaybalancing/Subsystem_report.html
### HDL check for 'hdl_delaybalancing' complete with 0 errors, 0 warnings, and 5 messages.
### HDL code generation complete.

Code Generation DUT: Output Pipeline Insertion

The top subsystem (gm_hdl_delaybalancing_vnl/Subsystem) in the Validation model is the DUT as implemented for HDL code generation and this is reference DUT when performing RTL testbench verification and Cosimulation block based verification. Notice that OutputPipeline parameter on the Gain3 block is implemented by an integer delay of length 2.

open_system('gm_hdl_delaybalancing_vnl/Subsystem');

Code Generation DUT: Sqrt Block Implementation

Implementing the square root function in on clock cycle is not efficient for hardware. The coder implements a pipelined architecture and this is reflected in the Code-Generation DUT model (under the square root subsystem) by the five additional delays.

open_system('gm_hdl_delaybalancing_vnl/Subsystem/Sqrt');

Equivalence Checking with the Validation Model

Validation model performs equivalence checking by routing the same inputs to both (the original and code-generation) DUTs using From and Goto blocks. This is encapsulated in the ToCoverifySrc and FromCoverifySrc subsystems. Both DUTs now respond to the same stimuli in each time step. The outputs from both DUTs are then sampled in each time step and their equivalence is checked. This is done by comparing the outputs from each output port, computing their difference, which should always be zero for functional equivalence.

In the current example, however, notice that functional equivalence is violated. The difference between the two outputs is non-zero in several time steps. This results in mismatch assertions and is also reflected in the last panel of the comparison scope.

open_system('gm_hdl_delaybalancing_vnl/Compare/Assert_Out1');
sim('gm_hdl_delaybalancing_vnl');
open_system('gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/compare: Out1')
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 0 
Warning: Division by zero occurred. Quotient was saturated. This originated
from 'gm_hdl_delaybalancing_vnl/Subsystem/Sqrt/Sqrt'
Suggested Actions:
    •  - Suppress
 
Warning: Saturate on overflow detected. This originated from
'gm_hdl_delaybalancing_vnl/Subsystem/Sqrt/Sqrt'
Suggested Actions:
    •  - Suppress
 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 0.4 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 0.8 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 1.2 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 1.6 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 2 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 2.4 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 2.8 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 3.2 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 3.6 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 4 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 4.4 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 5.2 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 5.6 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 6 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 6.4 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 6.8 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 7.2 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 7.6 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 8 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 8.4 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 8.8 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 9.2 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 9.6 
Warning: Assertion detected in
'gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/AssertEq' at time 10 

Automatic Delay Balancing

To solve the functional equivalence problem, you can turn on the delay balancing feature by setting the model-level BalanceDelays option to on. This can be done through either the hdlset_param command or as a makehdl argument.

With BalanceDelays turned on, HDL Coder automatically identifies the locations where matching delays need to be added to guarantee functional equivalence. After taking into account all of the delays introduced from implementation and optimizations, BalanceDelays adds delays that cover regular cut-sets, multi-rate boundaries, and subsystem boundaries.

Now when we observe the Code-generation DUT from the validation model notice that several additional delays have been added for matching delays introduced by the Sqrt block and OutputPipeline option. The names of these delays are typically prefixed with delayMatch. Notice that the coder also automatically computes the appropriate delays needed when crossing rate boundaries.

hdlset_param('hdl_delaybalancing', 'BalanceDelays', 'on');
makehdl('hdl_delaybalancing/Subsystem');
open_system('gm_hdl_delaybalancing_vnl/Subsystem')
set_param('gm_hdl_delaybalancing_vnl', 'SimulationCommand', 'update');
### Working on the model <a href="matlab:open_system('hdl_delaybalancing')">hdl_delaybalancing</a>
### Generating HDL for <a href="matlab:open_system('hdl_delaybalancing/Subsystem')">hdl_delaybalancing/Subsystem</a>
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdl_delaybalancing', { 'HDL Code Generation' } )">hdl_delaybalancing</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdl_delaybalancing'.
### Begin compilation of the model 'hdl_delaybalancing'...
### Working on the model 'hdl_delaybalancing'...
### 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('hdl_delaybalancing', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdl_delaybalancing'...
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### Generated model saved at <a href="matlab:open_system('hdlsrc/hdl_delaybalancing/gm_hdl_delaybalancing.slx')">hdlsrc/hdl_delaybalancing/gm_hdl_delaybalancing.slx</a>
### Generating new validation model: '<a href="matlab:open_system('hdlsrc/hdl_delaybalancing/gm_hdl_delaybalancing_vnl')">gm_hdl_delaybalancing_vnl</a>'.
### Validation model generation complete.
### Begin VHDL Code Generation for 'hdl_delaybalancing'.
### MESSAGE: The design requires 3 times faster clock with respect to the base rate = 0.1.
### Begin VHDL Code Generation for 'Subsystem_tc'.
### Working on Subsystem_tc as hdlsrc/hdl_delaybalancing/Subsystem_tc.vhd.
### Code Generation for 'Subsystem_tc' completed.
### Working on hdl_delaybalancing/Subsystem/Sqrt/Sqrt_iv as hdlsrc/hdl_delaybalancing/Sqrt_iv.vhd.
### Working on hdl_delaybalancing/Subsystem/Sqrt/Sqrt_core as hdlsrc/hdl_delaybalancing/Sqrt_core.vhd.
### Working on hdl_delaybalancing/Subsystem/Sqrt as hdlsrc/hdl_delaybalancing/Sqrt.vhd.
### Working on hdl_delaybalancing/Subsystem as hdlsrc/hdl_delaybalancing/Subsystem.vhd.
### Generating package file hdlsrc/hdl_delaybalancing/Subsystem_pkg.vhd.
### Code Generation for 'hdl_delaybalancing' completed.
### Generating HTML files for code generation report at <a href="matlab:hdlcoder.report.openDdg('/tmp/Bdoc24a_2528353_2771371/tp0c35c709/hdlcoder-ex36242447/hdlsrc/hdl_delaybalancing/html/hdl_delaybalancing_codegen_rpt.html')">hdl_delaybalancing_codegen_rpt.html</a>
### Creating HDL Code Generation Check Report file:///tmp/Bdoc24a_2528353_2771371/tp0c35c709/hdlcoder-ex36242447/hdlsrc/hdl_delaybalancing/Subsystem_report.html
### HDL check for 'hdl_delaybalancing' complete with 0 errors, 0 warnings, and 4 messages.
### HDL code generation complete.

Initial Latency and Functional Validation

The delays introduced by implementations essentially construct a pipelined hardware architecture to improve clock frequency and hardware efficiency. The pipeline however introduces an initial latency and the first output sample is generated after this initial latency. While these pipeline delays are automatically balanced inside the DUT, it is important to manually balance delays outside the DUT in the rest of the model. The amount of delay (or initial latency) is communicated to the user during code generation as follows:

  ### Some latency changes occurred in the DUT. Each output port experiences these additional delays
  ### Output port 0: 2 cycles

The equivalence checking in the Validation model uses this initial latency information for delaying the output from the original DUT. This is an example of balancing the delay outside DUT, since the balancing occurs at the inputs of the equivalence checking subsystem. Now, when we simulate the Validation model, note that there are no assertions and thus functional equivalence is preserved. While the pipeline delays are automatically balanced inside the DUT, it is important to manually balance delays outside the DUT in the rest of the model.

close_system('gm_hdl_delaybalancing_vnl/Subsystem')
sim('gm_hdl_delaybalancing_vnl');
open_system('gm_hdl_delaybalancing_vnl/Compare/Assert_Out1/compare: Out1')
Warning: Division by zero occurred. Quotient was saturated. This originated
from 'gm_hdl_delaybalancing_vnl/Subsystem/Sqrt/Sqrt'
Suggested Actions:
    •  - Suppress
 
Warning: Saturate on overflow detected. This originated from
'gm_hdl_delaybalancing_vnl/Subsystem/Sqrt/Sqrt'
Suggested Actions:
    •  - Suppress
 

Control the scope of delay balancing

The examples above describe the delay balancing feature as applied to the whole DUT. Sometimes, the design may explicitly model control and data paths, and you may not want to insert matching delays on the control path during delay balancing. The examples in Control the Scope of Delay Balancing show how this option can be applied locally to individual subsystems instead of the entire DUT.