Main Content

Generate Reusable Code for Subsystems

HDL Coder™ can detect atomic subsystems that are identical, or identical except for their mask parameter values, at any level of the model hierarchy, and generate a single reusable HDL module or entity. The reusable HDL code is generated as a single file and instantiated multiple times.

Requirements for Generating Reusable Code for Atomic Subsystems

  • The DefaultParameterBehavior Simulink® Configuration Parameter must be Inlined. You can set this parameter at the command line by using the set_param or hdlsetup function. To specify this setting in the Configuration Parameters dialog box, you must have Simulink Coder™.

    Note

    Using hdlsetup sets InlineParams property to on. Enabling this parameter is the same as setting DefaultParameterBehavior to Inlined. Setting InlineParams to off changes DefaultParameterBehavior value to Tunable.

  • Do not use functionality such as signal logging or using blocks like To Workspace or To File.

  • The atomic subsystems must be identical, or identical except for their mask parameter values.

    • MaskParameterAsGeneric must be on if the reusable subsystem has mask parameters with different values. This parameter has no effect on virtual subsystems. For more information, see Generate parameterized HDL code from masked subsystem.

    • Mask parameters must be tunable. The code generator does not share atomic subsystems with mask parameters that are nontunable.

    • Mask parameters must be scalar.

    • Mask parameter data types must be integer or fixed-point with a word length of less than or equal to 32.

    • The tunable parameter must be used in only Constant, Gain, or Compare To Constant blocks.

    • Port data types must match.

      If you change the value of the tunable mask parameter, the output port data type can change. If one of the atomic subsystems has a different port data type, the code generated for that subsystem also differs.

Requirements for Generating Reusable Code for Virtual Subsystems

  • The DefaultParameterBehavior Simulink Configuration Parameter must be Inlined. You can set this parameter at the command line by using the set_param or hdlsetup function. To specify this setting in the Configuration Parameters dialog box, you must have Simulink Coder.

    Note

    Using hdlsetup sets InlineParams property to on. Enabling this parameter is the same as setting DefaultParameterBehavior to Inlined. Setting InlineParams to off changes DefaultParameterBehavior value to Tunable.

  • Do not use logging functionality such as signal logging or blocks like To Workspace or To File.

  • The virtual subsystems must be identical.

    • SubsystemReuse must be set to 'Atomic and Virtual'.

      • Setting SubsystemReuse to 'Atomic and Virtual' reduces artificial algebraic errors and improves the recognition of identical subsystems, irrespective of their topology within the rest of the design. Identification of similar subsystems can help resource sharing.

      • To set these values to your required setting, in the MATLAB Command Window, enter:

        hdlset_param('myHDLModel', 'SubsystemReuse', 'Atomic and Virtual')
      • Alternatively, you can set this option from the top-level HDL Code Generation pane in the Configuration Parameters dialog box. Under Global Settings > Coding style, you can change the Code reuse setting to the required option.

      • The previous commands set the SubsystemReuse option for your project. To set this option for only the current code generation session, enter:

        makehdl(<DUT system>, 'SubsystemReuse', 'Atomic and Virtual')
    • The tunable parameter must be used in only Constant, Gain, or Compare To Constant blocks.

    • Port data types must match.

    • If the value of the tunable parameter changes during runtime, the code generator does not reuse the code.

Generate Reusable Code for Atomic Subsystems

This example shows HDL code generation of a model that has identical atomic subsystems. If your design contains identical atomic subsystems, the coder generates one HDL module or entity for the subsystem and instantiates it multiple times.

Open Model

Open the hdlcoder_reusable_code_identical_subsystem model to see an example of a DUT subsystem containing three identical atomic subsystems.

load_system('hdlcoder_reusable_code_identical_subsystem');
open_system('hdlcoder_reusable_code_identical_subsystem/DUT');

Generate HDL Code

You can generate the HDL code for the model by using makehdl function. To generate HDL code for DUT subsystem, run this command:

makehdl('hdlcoder_reusable_code_identical_subsystem/DUT')
### Working on the model <a href="matlab:open_system('hdlcoder_reusable_code_identical_subsystem')">hdlcoder_reusable_code_identical_subsystem</a>
### Generating HDL for <a href="matlab:open_system('hdlcoder_reusable_code_identical_subsystem/DUT')">hdlcoder_reusable_code_identical_subsystem/DUT</a>
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoder_reusable_code_identical_subsystem', { 'HDL Code Generation' } )">hdlcoder_reusable_code_identical_subsystem</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdlcoder_reusable_code_identical_subsystem'.
### Begin compilation of the model 'hdlcoder_reusable_code_identical_subsystem'...
### Working on the model 'hdlcoder_reusable_code_identical_subsystem'...
### Working on... <a href="matlab:configset.internal.open('hdlcoder_reusable_code_identical_subsystem', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdlcoder_reusable_code_identical_subsystem'...
### Rendering DUT with optimization related changes (IO, Area, Pipelining)...
### Model generation complete.
### Generated model saved at <a href="matlab:open_system('hdl_prj/hdlsrc/hdlcoder_reusable_code_identical_subsystem/gm_hdlcoder_reusable_code_identical_subsystem.slx')">hdl_prj/hdlsrc/hdlcoder_reusable_code_identical_subsystem/gm_hdlcoder_reusable_code_identical_subsystem.slx</a>
### Generating new validation model: '<a href="matlab:open_system('hdl_prj/hdlsrc/hdlcoder_reusable_code_identical_subsystem/gm_hdlcoder_reusable_code_identical_subsystem_vnl')">gm_hdlcoder_reusable_code_identical_subsystem_vnl</a>'.
### Validation model generation complete.
### Begin VHDL Code Generation for 'hdlcoder_reusable_code_identical_subsystem'.
### Working on hdlcoder_reusable_code_identical_subsystem/DUT/vsum as hdl_prj/hdlsrc/hdlcoder_reusable_code_identical_subsystem/vsum.vhd.
### Working on hdlcoder_reusable_code_identical_subsystem/DUT as hdl_prj/hdlsrc/hdlcoder_reusable_code_identical_subsystem/DUT.vhd.
### Generating package file hdl_prj/hdlsrc/hdlcoder_reusable_code_identical_subsystem/DUT_pkg.vhd.
### Code Generation for 'hdlcoder_reusable_code_identical_subsystem' completed.
### Generating HTML files for code generation report at <a href="matlab:hdlcoder.report.openDdg('/tmp/Bdoc24a_2528353_2773140/tp23306d3d/hdlcoder-ex21822210/hdl_prj/hdlsrc/hdlcoder_reusable_code_identical_subsystem/html/hdlcoder_reusable_code_identical_subsystem_codegen_rpt.html')">hdlcoder_reusable_code_identical_subsystem_codegen_rpt.html</a>
### Creating HDL Code Generation Check Report file:///tmp/Bdoc24a_2528353_2773140/tp23306d3d/hdlcoder-ex21822210/hdl_prj/hdlsrc/hdlcoder_reusable_code_identical_subsystem/DUT_report.html
### HDL check for 'hdlcoder_reusable_code_identical_subsystem' complete with 0 errors, 0 warnings, and 2 messages.
### HDL code generation complete.

HDL Coder generates a single VHDL® file, vsum.vhd, for the three subsystems. The generated code for the DUT subsystem, DUT.vhd, contains three instantiations of the vsum component.

ARCHITECTURE rtl OF DUT IS
-- Component Declarations
COMPONENT vsum
  PORT( In1                             :   IN    vector_of_std_logic_vector16(0 TO 9);  -- int16 [10]
        Out1                            :   OUT   std_logic_vector(19 DOWNTO 0)  -- sfix20
        );
END COMPONENT;
-- Component Configuration Statements
FOR ALL : vsum
  USE ENTITY work.vsum(rtl);
-- Signals
SIGNAL vsum_out1                        : std_logic_vector(19 DOWNTO 0);  -- ufix20
SIGNAL vsum1_out1                       : std_logic_vector(19 DOWNTO 0);  -- ufix20
SIGNAL vsum2_out1                       : std_logic_vector(19 DOWNTO 0);  -- ufix20
BEGIN
u_vsum : vsum
  PORT MAP( In1 => In1,  -- int16 [10]
            Out1 => vsum_out1  -- sfix20
            );
u_vsum1 : vsum
  PORT MAP( In1 => In2,  -- int16 [10]
            Out1 => vsum1_out1  -- sfix20
            );
u_vsum2 : vsum
  PORT MAP( In1 => In3,  -- int16 [10]
            Out1 => vsum2_out1  -- sfix20
            );
Out1 <= vsum_out1;
Out2 <= vsum1_out1;
Out3 <= vsum2_out1;
END rtl;

Generate Reusable Code for Atomic Subsystems with Tunable Mask Parameters

Using this example, you can generate HDL code for your design containing atomic subsystems that are identical except for their tunable mask parameter values. You can generate one HDL module or entity for the subsystem. In the generated code, the module or entity is instantiated multiple times.

Open Model

The hdlcoder_reusable_code_parameterized_subsystem model shows an example of a DUT subsystem containing atomic subsystems that are identical except for their tunable mask parameter values.

load_system('hdlcoder_reusable_code_parameterized_subsystem');
open_system('hdlcoder_reusable_code_parameterized_subsystem/DUT');

In hdlcoder_reusable_code_parameterized_subsystem/DUT, the gain modules are subsystems with gain values represented by tunable mask parameters. Gain values are: 4 for gain_module, 5 for gain_module1, and 7 for gain_module2.

Generate HDL Code

To generate reusable code for identical atomic subsystems, enable MaskParameterAsGeneric for the model. By default, MaskParameterAsGeneric is disabled.

To enable the generation of reusable code for the atomic subsystems with tunable parameters, set MaskParameterAsGeneric option to "on" for a model by using hdlset_param function.

hdlset_param('hdlcoder_reusable_code_parameterized_subsystem','MaskParameterAsGeneric','on');

Alternatively, in the Configuration Parameters dialog box, in the HDL Code Generation > Global Settings > Coding Style tab, enable the Generate parameterized HDL code from masked subsystem option.

You can also enable MaskParameterAsGeneric option by using makehdl function and generate HDL code for a DUT subsystem.

makehdl('hdlcoder_reusable_code_parameterized_subsystem/DUT','MaskParameterAsGeneric','on',...
        'TargetLanguage','Verilog')
### Working on the model <a href="matlab:open_system('hdlcoder_reusable_code_parameterized_subsystem')">hdlcoder_reusable_code_parameterized_subsystem</a>
### Generating HDL for <a href="matlab:open_system('hdlcoder_reusable_code_parameterized_subsystem/DUT')">hdlcoder_reusable_code_parameterized_subsystem/DUT</a>
### Using the config set for model <a href="matlab:configset.showParameterGroup('hdlcoder_reusable_code_parameterized_subsystem', { 'HDL Code Generation' } )">hdlcoder_reusable_code_parameterized_subsystem</a> for HDL code generation parameters.
### Running HDL checks on the model 'hdlcoder_reusable_code_parameterized_subsystem'.
### Begin compilation of the model 'hdlcoder_reusable_code_parameterized_subsystem'...
### Working on the model 'hdlcoder_reusable_code_parameterized_subsystem'...
### Working on... <a href="matlab:configset.internal.open('hdlcoder_reusable_code_parameterized_subsystem', 'GenerateModel')">GenerateModel</a>
### Begin model generation 'gm_hdlcoder_reusable_code_parameterized_subsystem'...
### Copying DUT to the generated model....
### Model generation complete.
### Generated model saved at <a href="matlab:open_system('hdlsrc/hdlcoder_reusable_code_parameterized_subsystem/gm_hdlcoder_reusable_code_parameterized_subsystem.slx')">hdlsrc/hdlcoder_reusable_code_parameterized_subsystem/gm_hdlcoder_reusable_code_parameterized_subsystem.slx</a>
### Begin Verilog Code Generation for 'hdlcoder_reusable_code_parameterized_subsystem'.
### Working on hdlcoder_reusable_code_parameterized_subsystem/DUT/gain_module as hdlsrc/hdlcoder_reusable_code_parameterized_subsystem/gain_module.v.
### Working on hdlcoder_reusable_code_parameterized_subsystem/DUT as hdlsrc/hdlcoder_reusable_code_parameterized_subsystem/DUT.v.
### Code Generation for 'hdlcoder_reusable_code_parameterized_subsystem' completed.
### Generating HTML files for code generation report at <a href="matlab:hdlcoder.report.openDdg('/tmp/Bdoc24a_2528353_2772716/tp17c37791/hdlcoder-ex53380017/hdlsrc/hdlcoder_reusable_code_parameterized_subsystem/html/hdlcoder_reusable_code_parameterized_subsystem_codegen_rpt.html')">hdlcoder_reusable_code_parameterized_subsystem_codegen_rpt.html</a>
### Creating HDL Code Generation Check Report file:///tmp/Bdoc24a_2528353_2772716/tp17c37791/hdlcoder-ex53380017/hdlsrc/hdlcoder_reusable_code_parameterized_subsystem/DUT_report.html
### HDL check for 'hdlcoder_reusable_code_parameterized_subsystem' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

With MaskParameterAsGeneric enabled, HDL Coder generates a single source file, gain_module.v, for the three gain module subsystems. The generated code for the DUT subsystem, DUT.v, contains three instantiations of the gain_module component.

module DUT
        (
         In1,
         In2,
         In3,
         Out1,
         Out2,
         Out3
        );
input   [7:0] In1;  // uint8
input   [7:0] In2;  // uint8
input   [7:0] In3;  // uint8
output  [31:0] Out1;  // uint32
output  [31:0] Out2;  // uint32
output  [31:0] Out3;  // uint32
wire [31:0] gain_module_out1;  // uint32
wire [31:0] gain_module1_out1;  // uint32
wire [31:0] gain_module2_out1;  // uint32
gain_module   #  (.myGain(4)
                  )
              u_gain_module   (.In1(In1),  // uint8
                               .Out1(gain_module_out1)  // uint32
                               );
assign Out1 = gain_module_out1;
gain_module   #  (.myGain(5)
                  )
              u_gain_module1   (.In1(In2),  // uint8
                                .Out1(gain_module1_out1)  // uint32
                                );
assign Out2 = gain_module1_out1;
gain_module   #  (.myGain(7)
                  )
              u_gain_module2   (.In1(In3),  // uint8
                                .Out1(gain_module2_out1)  // uint32
                                );
assign Out3 = gain_module2_out1;
endmodule  // DUT

In gain_module.v, the myGain Verilog® parameter is generated for the tunable mask parameter.

module gain_module
        (
         In1,
         Out1
        );
input   [7:0] In1;  // uint8
output  [31:0] Out1;  // uint32
parameter [31:0] myGain = 4;  // ufix32
wire [31:0] kconst;  // ufix32
wire [39:0] Gain_mul_temp;  // ufix40
wire [31:0] Gain_out1;  // uint32
assign kconst = myGain;
assign Gain_mul_temp = kconst * In1;
assign Gain_out1 = Gain_mul_temp[31:0];
assign Out1 = Gain_out1;
endmodule  // gain_module

If the input model has subsystems that contains mask information such as mask variables and mask initialization code, the mask information of those subsystems is preserved in the generated model. If you do not need this information, you can remove it.

Related Topics