%% Use Bus Signals to Improve Readability of Model and Generate HDL Code

% Copyright 2020 The MathWorks, Inc.

%%
% You can follow these guidelines to learn about bus signals, how to model
% your design by using these signals, and generate HDL code. 
% Each guideline has a severity level that indicates the level 
% of compliance requirements. To learn more, see 
% <docid:hdlcoder_ug#mw_582dd78b-4783-4c96-bea0-5a449ea85fb6>.
%
%% Guideline ID
% |1.3.3|

%% Severity
% _Informative_

%% Description
%
% *When to Use Buses?*
%
% If your DUT or other blocks in your model have many input or output signals, 
% you can create bus signals to improve the readability of your model. A bus 
% signal or bus is a composite signal that consists of other signals that are 
% called elements. The bus signal can have a structure of different data types 
% or a vector signal with the same data types. If all signals have the same data
% type, you generally use a <docid:simulink_ref#f7-891681> block. The constituent 
% signals or elements of a bus can be:
%
% * Mixed data type signals such as double, integer, and fixed-point
% * Mixed scalar and vector elements
% * Mixed real and complex signals
% * Other buses nested to any level
% * Multidimensional signals
%
%%
% *HDL Coder(TM) Support for Buses*
%
% You can generate HDL code for designs that have:
%
% * DUT subsystem ports connected to buses.
% * Simulink(R) and Stateflow(R) blocks supported for HDL code
% generation.
%
% HDL Coder supports code generation for bus-capable blocks in the *HDL Coder* 
% block library. Bus-capable blocks are blocks that can accept bus signals as input 
% and produce bus signals as outputs. For a list of bus-capable blocks that Simulink supports, 
% see <docid:simulink_ug#bq4jrcg-1>.
%
% See <docid:hdlcoder_ug#buaqcr_-2> for blocks that support HDL code generation 
% with buses.
%
%%
% *Create Bus Signals*
%
% You can create bus signals by using <docid:simulink_ref#f6-2920111> blocks.
% A Bus Creator block assigns a name to each signal that it creates.  You can 
% then refer to signals by name when you search for their sources. 
%
% For an example that illustrates how to model with buses, open
% |hdlcoder_bus_nested.slx|. Double-click the |HDL_DUT| Subsystem. 
open_system('hdlcoder_bus_nested')
set_param('hdlcoder_bus_nested','SimulationCommand','Update')
open_system('hdlcoder_bus_nested/HDL_DUT')
%%
% In this model, the Bus Creator blocks create two bus signals. One bus signal 
% contains |data1_En| and |CounterForParam| signals. The other bus signal contains 
% |Param| and |sin| signals. By default, each signal on the bus inherits the name 
% of the signal connected to the bus. This figure shows the *Signals in the bus* 
% block parameter for the Bus Creator block that takes inputs |data1_En| and 
% |CounterForParam|.
%
% <<../Bus_creator_signals_in_bus.png>>
%
%%
% *Nest Buses*
%
% You see another Bus Creator block that combines these two bus 
% signals. When one or more inputs to a Bus Creator block is a bus, the output
% is a nested bus. 
%
% The Bus Creator block generates names for bus signals whose corresponding
% inputs do not have names. The names are in the form |signaln|, where n is 
% the number of the port the input signal connects to. For example, if you 
% open the Block Parameters dialog box for the second Bus Creator block, you 
% see *Signals in the bus* as |signal1| and |Param_sin|.
%
%%
% *Assign Signal Values to Bus*
%
% To change bus element values, use a <docid:simulink_ref#f6-871776> block. 
% Use a Bus Assignment block to change bus element 
% values without adding Bus Selector and Bus Creator blocks that select 
% bus elements and reassemble them into a bus.
%
% For example, open the model |hdlcoder_bus_nested_assignment|.
open_system('hdlcoder_bus_nested_assignment')
set_param('hdlcoder_bus_nested_assignment','SimulationCommand','Update')
open_system('hdlcoder_bus_nested_assignment/HDL_DUT')
%%
% In the model, you see a Bus Assignment block that assigns the value |5| to the 
% |data1_En| signal in the bus.
%% 
% *Select Bus Outputs*
%
% To extract the signals from a bus that includes nested buses, use 
% <docid:simulink_ref#f6-1418226> blocks. By default, the block outputs the 
% specified bus elements as separate signals. You can also output the signals 
% as another bus. You can use the |OutputSignals| block property to see the 
% *Signals in the bus* that the block outputs. By using this property, you can 
% track which signals are entering a Bus Selector block deep within your model hierarchy.
get_param('hdlcoder_bus_nested/HDL_DUT/Bus Selector5', 'OutputSignals')
%% 
% *Generate HDL Code*
%
% To generate HDL code for this model, run this command:
%
%   makehdl('hdlcoder_bus_nested/HDL_DUT')
%
%%
% You see that the code generator expands the bus signals to scalar signals in
% the generated code. For example, if you open the generated Verilog file for 
% the |HDL_DUT| Subsystem, for the Delay block that takes the two nested bus signals 
% |signal1| and |Param_sin|, you see four always blocks created for each signal in the bus.
% For example, you see an always block for the |data1_En| signal that is
% part of |signal1|. This figure displays the scalar signals created for each
% bus signal in the module definition.
%
% <<../HDL_DUT_virtual.png>>
%%
% *Simplify Subsystem Bus Interfaces*
%
% You can simplify the Subsystem bus interfaces by using Bus Element
% blocks. The In Bus Element and Out Bus Element blocks provide a simplified 
% and flexible way to use bus signals as inputs and outputs to subsystems. The 
% In Bus Element block is equivalent to an Inport block combined with a Bus Selector 
% block. The Out Bus Element block is equivalent to an Outport block combined 
% with a Bus Creator block. To refactor an existing model that uses 
% Inport, Bus Selector, Bus Creator, and Outport blocks to use In Bus Element and 
% Out Bus Element blocks, you can use Simulink(R) Editor action bars. 
%
% For example, open the model |hdlcoder_bus_nested_simplified|. This model
% is functionally equivalent to the |hdlcoder_bus_nested| model but is a
% more simplified version. 
open_system('hdlcoder_bus_nested_simplified')
set_param('hdlcoder_bus_nested_simplified','SimulationCommand','Update')
open_system('hdlcoder_bus_nested_simplified/HDL_DUT')
%%
% The model has two Subsystems that perform bus creation and bus selection by using 
% Bus Element blocks. The |Bus_Creator_Subsystem| combines the Outport
% blocks with the Bus Creator blocks to create Out Bus Element blocks.
open_system('hdlcoder_bus_nested_simplified/HDL_DUT/Bus_Creator_Subsystem')
%%
% The |Bus_Selection_Subsystem| combines the Inport blocks with the Bus Selector 
% blocks to create In Bus Element blocks.
open_system('hdlcoder_bus_nested_simplified/HDL_DUT/Bus_Selection_Subsystem')
%% 
% To learn more, see <docid:simulink_ug#bvmdxg2>.
%
%% 
% *Virtual and Nonvirtual Buses*
%
% The bus signals in the model |hdlcoder_bus_nested| created earlier by using Bus Creator 
% and Bus Selector blocks are virtual buses. Each bus element signal is stored in
% memory, but the bus signal is not stored. The bus simplifies the graph but has no
% functional effect. In the generated HDL code, you see the constituent
% signals but not the bus signal.
%
% To more easily track the correspondence between a bus signal in the model and 
% the generated HDL code, use nonvirtual buses. Nonvirtual buses generate
% clean HDL code because it uses a structure to hold the bus signals. To
% convert a virtual bus to a nonvirtual bus, in the Block Parameters of the
% Bus Creator blocks, you specify the *Output data type* as |Bus: object_name| 
% by replacing |object_name| with the name of the bus
% object and then select *Output as nonvirtual bus*.
%
% See <docid:simulink_ref#mw_afb768f3-88ad-4724-a1da-a356c7501c8c>.
%% 
% *Array of Buses*
%
% An array of buses is an array whose elements are buses. Each element in 
% an array of buses must be nonvirtual and must have the same data type. 
%
% To learn more about modeling with array of buses, see 
% <docid:hdlcoder_ug#bvbzc80-1>.
