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/Bdoc24b_2725827_3885934/tp61e4414f/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/Bdoc24b_2725827_3885934/tp61e4414f/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/Bdoc24b_2725827_3885934/tp61e4414f/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/Bdoc24b_2725827_3885934/tp61e4414f/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.