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

To generate reusable HDL 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.

  • Logging functionality must not be used, such as signal logging or using blocks such as To Workspace or To File.

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

    • MaskParameterAsGeneric must be on. For more information, see Generate parameterized HDL code from masked subsystem.

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

    • Mask parameter data types cannot be double or single.

    • The tunable parameter must be used in only Constant or Gain 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

To generate reusable HDL 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.

  • Logging functionality must not be used, such as signal logging or using blocks such as To Workspace or To File.

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

    • 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')
    • MaskParameterAsGeneric must be on. For more information, see Generate parameterized HDL code from masked subsystem.

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

    • Mask parameter data types cannot be double or single.

    • The tunable parameter must be used in only Constant or Gain 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.

Generate Reusable Code for 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.

Example

The hdlcoder_reusable_code_identical_subsystem model shows an example of a DUT subsystem containing three identical atomic subsystems.

HDL Coder generates a single VHDL® file, vsum.vhd, for the three subsystems.

makehdl('hdlcoder_reusable_code_identical_subsystem/DUT')
### Generating HDL for 'hdlcoder_reusable_code_identical_subsystem/DUT'.
### Starting HDL check.
### Generating new validation model: gm_hdlcoder_reusable_code_identical_subsystem_vnl.
### Validation model generation complete.
### Begin VHDL Code Generation for 'hdlcoder_reusable_code_identical_subsystem'.
### Working on hdlcoder_reusable_code_identical_subsystem/DUT/vsum/Sum of Elements as 
    hdl_prj\hdlsrc\hdlcoder_reusable_code_identical_subsystem\Sum_of_Elements.vhd.
### 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.
### Creating HDL Code Generation Check Report DUT_report.html
### HDL check for 'hdlcoder_reusable_code_identical_subsystem' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

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

If your design contains 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.

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

For example, to enable the generation of reusable code for the atomic subsystems with tunable parameters in the hdlcoder_reusable_code_parameterized_subsystem model, enter:

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.

Example

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.

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.

With MaskParameterAsGeneric enabled, HDL Coder generates a single source file, gain_module.v, for the three gain module subsystems.

makehdl('hdlcoder_reusable_code_parameterized_subsystem/DUT','MaskParameterAsGeneric','on',...
        'TargetLanguage','Verilog')
### Generating HDL for 'hdlcoder_reusable_code_parameterized_subsystem/DUT'.
### Starting HDL check.
### 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.
### Creating HDL Code Generation Check Report DUT_report.html
### HDL check for 'hdlcoder_reusable_code_parameterized_subsystem' complete with 0 errors, 0 warnings, and 0 messages.
### HDL code generation complete.

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

Related Topics