%% Control the Scope of Delay Balancing
% This example shows how to balance delays in specific parts of a design,
% without balancing delays on the entire design.

% Copyright 2013 The MathWorks, Inc.

%% Introduction
% You can use the 'BalanceDelays' option to
% balance the additional delays introduced by HDL Coder(TM) for certain block
% implementations and optimizations.  This model-level option
% controls delay balancing for the entire model.  However, for certain
% designs, you may want to balance delays in only some parts of the design.
% For example, in a design containing a data path and a control path, delay
% balancing should be applied only on the data path of the  design, i.e.,
% the paths requiring data synchronization. This example shows how to
% use a subsystem-level 'BalanceDelays' option provides fine-grained
% control on how HDL Coder balances delays in individual subsystems.

%%
% We use two examples to demonstrate the use of this subsystem-level
% feature:
%
% # hdlcoder_localdelaybalancing.slx shows how to disable delay balancing on user-defined control paths.
% # hdlcoder_localdelaybalancing_sharing.slx shows how the user can apply HDL optimizations like resource sharing in the presence of complicated control paths that require carefully constrained delay balancing.

%% Example 1: Constraining Delay Balancing to the data path
% The example model, "hdlcoder_localdelaybalancing.slx", has two
% subsystems under hdlcoder_localdelaybalancing/Subsystem: param_control
% and symmetric_fir, containing the control logic and the data path,
% respectively.
bdclose('all');
open_system('hdlcoder_localdelaybalancing');
open_system('hdlcoder_localdelaybalancing/Subsystem');

%%
% Each subsystem has one block that has one output pipeline register to
% achieve good timing results.
hdldispblkparams('hdlcoder_localdelaybalancing/Subsystem/param_control/And');
hdldispblkparams('hdlcoder_localdelaybalancing/Subsystem/symmetric_fir/Add');

%%
% When the global, model-level 'BalanceDelays' option is set to 'on', then
% delay balancing inserts matching delays on both the control path as well
% as the data path, as shown in the validation model.

hdlset_param('hdlcoder_localdelaybalancing', 'BalanceDelays', 'on');
hdlset_param('hdlcoder_localdelaybalancing', 'GenerateValidationModel', 'on');
makehdl('hdlcoder_localdelaybalancing/Subsystem');
load_system('gm_hdlcoder_localdelaybalancing_vnl');
set_param('gm_hdlcoder_localdelaybalancing_vnl', 'SimulationCommand', 'update');
open_system('gm_hdlcoder_localdelaybalancing_vnl/Subsystem/param_control');

%%
% In this example design, only the data path, symmetric_fir, requires
% data synchronization.  The outputs from param_control are coefficients to
% the FIR filter and do not have to synchronize with each other or
% with the processed data.  Turning off delay balancing on the control
% logic therefore saves resources. In order to achieve this, the
% model-level 'BalanceDelays' option must be 'off', and the subsystem-level 
% 'BalanceDelays' options must be set appropriately on the data path and
% control path.
hdlset_param('hdlcoder_localdelaybalancing', 'BalanceDelays', 'off');
hdlset_param('hdlcoder_localdelaybalancing/Subsystem/param_control', 'BalanceDelays', 'off');
hdlset_param('hdlcoder_localdelaybalancing/Subsystem/symmetric_fir', 'BalanceDelays', 'on');

%%
% Now when HDL code is generated, delay balancing is only active in the
% data path subsystem and does not insert any delays in the control path
% subsystem.
bdclose('gm_hdlcoder_localdelaybalancing_vnl');
makehdl('hdlcoder_localdelaybalancing/Subsystem');
load_system('gm_hdlcoder_localdelaybalancing_vnl');
set_param('gm_hdlcoder_localdelaybalancing_vnl', 'SimulationCommand', 'update');
open_system('gm_hdlcoder_localdelaybalancing_vnl/Subsystem/param_control');

%%
% Notice that simulating the validation model now
% shows mismatches, because the validation model does not compensate for 
% latency inserted by optimizations or block implementations.


%% Example 2: Localized Delay Balancing and Resource Sharing
% The resource sharing optimization saves area usage in the final HDL
% implementation, at the cost of introducing a cycle of latency for each
% sharing group. This additional latency is usually balanced during delay
% balancing so that the numerics and functionality of the algorithm
% are preserved. One of the restrictions of resource sharing is that it
% cannot be applied on a subsystem within a feedback loop. Thus, if
% resource sharing is specified for a subsystem  
% within a loop, then the optimization will fail. You can observe this in 
% hdlcoder_localdelaybalancing_sharing.slx, where
% hdlcoder_localdelaybalancing_sharing/Subsystem/Subsystem is
% within a feedback loop. 
bdclose('all');
load_system('hdlcoder_localdelaybalancing_sharing');
open_system('hdlcoder_localdelaybalancing_sharing/Subsystem');

%%
% However, in this design, you may know that the feedback loop is rarely
% used since the control signal causes the switch block,
% 'hdlcoder_localdelaybalancing_sharing/Subsystem/Subsystem/Switch', to
% choose the top input, the feed-forward path, most of the time. This
% user insight implies that it is fine to go ahead with resource
% sharing in this subsystem and disregard the feedback loop in the parent subsystem.
% In such cases, if you wish to ignore feedback loops during delay
% balancing, you must turn off delay balancing in the subsystem
% containing the feedback loop. This enables HDL Coder (TM) to ignore the
% feedback loop and proceed with resource sharing.

hdlset_param('hdlcoder_localdelaybalancing_sharing', 'BalanceDelays', 'off');
hdlset_param('hdlcoder_localdelaybalancing_sharing/Subsystem', 'BalanceDelays', 'off');
hdlset_param('hdlcoder_localdelaybalancing_sharing/Subsystem/Subsystem', 'BalanceDelays', 'on');
makehdl('hdlcoder_localdelaybalancing_sharing/Subsystem');
load_system('gm_hdlcoder_localdelaybalancing_sharing');
set_param('gm_hdlcoder_localdelaybalancing_sharing_vnl', 'SimulationCommand', 'update');

%%
% Notice that not only does sharing succeed in the inner subsystem, but local
% delay balancing also succeeds within this subsystem by inserting matching
% delays on the inputs to the adder.
open_system('gm_hdlcoder_localdelaybalancing_sharing_vnl/Subsystem/Subsystem');

displayEndOfDemoMessage(mfilename)
