%% Delay Balancing and Validation Model Workflow In HDL Coder(TM)
% 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 cut-sets,
% 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.

% Copyright 2006-2013 The MathWorks, Inc.


%% 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 cut-sets 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' implementation parameter set to 2.

bdclose all;
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 (called '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');


%% 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 5 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')

%% Automatic Delay Balancing
% To solve the functional equivalence problem, the user 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 this option turned on, HDL Coder will automatically
% identify the locations where matching delays need to be
% added to guarantee functional equivalence. This will cover regular
% cut-sets, multi-rate boundaries and subsystem boundaries, after taking 
% in to account, all the implementation- and optimization-induced delays.
%
% 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');

%% 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 the 
% user's responsibility to 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 the user's responsibility to 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')

%% 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
% <docid:hdlcoder_ug#example-hdlcoder_local_delay_balancing> show how this
% option can be applied locally to individual subsystems instead of the 
% entire DuT.

displayEndOfDemoMessage(mfilename)
