Main Content

Optimize Unconnected Ports in HDL Code for Simulink Models

HDL code generation improves code readability, reduces code size, and reduces area usage by removing unconnected ports from the generated code. This improvement includes removing unconnected vector and scalar ports, bus element ports, and bus ports. Unconnected port removal can help avoid synthesis failure caused by unused ports in the generated code.

Unused Port Removal

Unused port removal works in conjunction with removal of unused blocks in your design. See Remove Redundant Logic and Unused Blocks in Generated HDL Code.

You can see the effect of unused port removal in the generated HDL code. Ports are not removed from top-level DUT models or subsystems, implementation models, or validation models.

Open the model hdlcoder_RemoveUnconnectedPorts containing Bus Element ports and a port connected to an inactive output.

open_system('hdlcoder_RemoveUnconnectedPorts')
set_param('hdlcoder_RemoveUnconnectedPorts', 'SimulationCommand', 'update');

Open the dut Subsystem block, and then open the mid_Subsystem block. The mid_Subsystem contains the Bus Element ports. One of the output signals is connected to a Terminator block.

open_system('hdlcoder_RemoveUnconnectedPorts/dut/mid_Subsystem')

To generate HDL code for the design, at the MATLAB® command prompt, enter:

makehdl('hdlcoder_RemoveUnconnectedPorts/dut')

The generated code mid_Subsystem.vhd shows that unconnected ports are removed during HDL code generation. The input InBus_signal3 at the DUT input port is multiplied by a Gain block, and then connected to the output port OutBus_signal2, which is then passed to the DUT output port. Because the other input and output ports are unused at the DUT level, these ports are removed from the generated HDL code.

ARCHITECTURE rtl OF mid_Subsystem IS
-- Component Declarations
COMPONENT inner_Subsystem
  PORT( clk              :   IN    std_logic;
        reset            :   IN    std_logic;
        enb              :   IN    std_logic;
        InBus_signal3    :   IN    std_logic_vector(31 DOWNTO 0);  -- single
        OutBus_signal2   :   OUT   std_logic_vector(31 DOWNTO 0)  -- single
        );
END COMPONENT;
...
END rtl;

Disable Unused Port Deletion Optimization

By default, the optimization is enabled and unused ports are removed in the generated HDL code.

If you do not want unconnected ports to be removed from your design:

  1. In the Configuration Parameters dialog box, clear the Remove Unused Ports check box.

  2. When you run the HDL Workflow Advisor, in the Set Code Generation Options > Set Optimization Options task, clear the Remove Unused Ports check box.

  3. At the command line, set DeleteUnusedPorts to off with hdlset_param or makehdl. For example, to specify that you want to preserve the unused ports in the hdlcoder_RemoveUnconnectedPorts model, run this command:

makehdl('hdlcoder_RemoveUnconnectedPorts/dut', 'DeleteUnusedPorts', 'off')

The generated HDL code preserves the unused Bus Elements ports.

ARCHITECTURE rtl OF mid_Subsystem IS
-- Component Declarations
COMPONENT inner_Subsystem
  PORT( clk                :   IN    std_logic;
        reset              :   IN    std_logic;
        enb                :   IN    std_logic;
        InBus_signal1      :   IN    std_logic_vector(31 DOWNTO 0);  -- single
        InBus_signal2      :   IN    std_logic_vector(31 DOWNTO 0);  -- single
        InBus_signal3      :   IN    std_logic_vector(31 DOWNTO 0);  -- single
        InBus_signal4      :   IN    std_logic_vector(31 DOWNTO 0);  -- single
        OutBus_signal1     :   OUT   std_logic_vector(31 DOWNTO 0);  -- single
        OutBus_signal2     :   OUT   std_logic_vector(31 DOWNTO 0)  -- single
        );
END COMPONENT;
...
END rtl;

Unused Port Deletion for Subsystem Ports

This optimization can remove unused subsystem data ports. Control ports and ports of a referenced model are not removed.

A subsystem data port is considered to be active when it contributes to a DUT output port downstream or is connected to an active black box subsystem, or a component that is preserved during HDL code generation.

Open the model hdlcoder_subsys_ports_unused.

open_system('hdlcoder_subsys_ports_unused')
sim('hdlcoder_subsys_ports_unused');

The model contains a normal_subsys_dead_out subsystem that contains an output port out3 that is terminated and does not contribute to the DUT output.

open_system('hdlcoder_subsys_ports_unused/DUT')

To generate HDL code for the DUT subsystem, run this command:

makehdl('hdlcoder_subsys_ports_unused/DUT')

By default, when DeleteUnusedPorts is on, the Add block calculation and output port Out3 are removed in the generated HDL code.

ENTITY normal_subsys_dead_out IS
 PORT( In1       :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1      :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2      :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END normal_subsys_dead_out;
ARCHITECTURE rtl OF normal_subsys_dead_out IS
...
  Out1 <= std_logic_vector(Gain_out1);
...
  Out2 <= std_logic_vector(Gain1_out1);
END rtl;

To disable DeleteUnusedPorts optimization, run this command:

makehdl('hdlcoder_subsys_ports_unused/DUT', 'DeleteUnusedPorts', 'off')

When you set DeleteUnusedPorts to off, this port and the Add block calculation are preserved in the generated HDL code.

ENTITY normal_subsys_dead_out IS
 PORT( In1     :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1    :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2    :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out3    :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END normal_subsys_dead_out;
ARCHITECTURE rtl OF normal_subsys_dead_out IS
...
  Out1 <= std_logic_vector(Gain_out1);
...
  Out2 <= std_logic_vector(Gain1_out1
  Add_out1 <= to_signed(16#0000#, 16);
  Out3 <= std_logic_vector(Add_out1);
END rtl;

Unused Port Deletion for Atomic Subsystems

For unused ports outside atomic subsystems, atomic subsystem instances are removed from the generated HDL code.

Open the model hdlcoder_atomic_subsys3_redundant

open_system('hdlcoder_atomic_subsys3_redundant')
sim('hdlcoder_atomic_subsys3_redundant');

The DUT subsystem contains three atomic subsystem instances. The outputs of two of the atomic subsystem instances are connected to Terminator blocks.

open_system('hdlcoder_atomic_subsys3_redundant/DUT')

To generate HDL code for the DUT subsystem, run this command:

makehdl('hdlcoder_atomic_subsys3_redundant/DUT')
ENTITY DUT IS
 PORT( In1      :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1     :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2     :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END DUT;
ARCHITECTURE rtl OF DUT IS
-- Component Declarations
COMPONENT atomic_subsys_dead_out_instance_1
  PORT( In1    :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
        Out1   :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
        Out2   :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
        );
END COMPONENT;
...
END rtl;

To set DeleteUnusedPorts to off, run this command:

makehdl('hdlcoder_atomic_subsys3_redundant/DUT', 'DeleteUnusedPorts', 'off')

If you set DeleteUnusedPorta to off, the input port In2 is preserved in the generated HDL code but it is feeding into an input port that is driving an unused component.

ENTITY DUT IS
 PORT( In1        :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1       :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2       :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END DUT;
ARCHITECTURE rtl OF DUT IS
-- Component Declarations
COMPONENT atomic_subsys_dead_out_instance_1
  PORT( In1      :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
        In2      :   IN    std_logic_vector(7 DOWNTO 0);  -- int8
        Out1     :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
        Out2     :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
        );
END COMPONENT;
...
END rtl;

Unused Port Deletion for Output Ports of Atomic Subsystems

When you have multiple active atomic subsystem instances, the redundant logic across the boundary including any ports is preserved in the HDL code independent of the DeleteUnusedPorts setting. When you have only one Atomic Subsystem instance, by default, when DeleteUnusedPorts is on, any redundant logic and ports across the subsystem boundary are removed. If you set DeleteUnusedPorts to off, any unused port is preserved though the logic is redundant.

Open the model hdlcoder_atomic_subsys2_ports_redundant.

open_system('hdlcoder_atomic_subsys2_ports_redundant')
sim('hdlcoder_atomic_subsys2_ports_redundant');

The DUT subsystem contains an Atomic Subsystem block that contains an Add block connected to an output port terminated outside the subsystem.

open_system('hdlcoder_atomic_subsys2_ports_redundant/DUT')

To generate HDL code for the DUT subsystem, run this command:

makehdl('hdlcoder_atomic_subsys2_ports_redundant/DUT')

In the generated HDL code, the Add block and corresponding output port Out3 is removed because it does not contribute to an active output.

ENTITY DUT IS
 PORT( In1    :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1   :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2   :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END DUT;
ARCHITECTURE rtl OF DUT IS
-- Component Declarations
COMPONENT single_instance_atomic_subsys_dead_out
  PORT( In1    :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
        Out1   :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
        Out2   :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
        );
END COMPONENT;
...
END rtl;

To set DeleteUnusedPorts to off, run this command:

makehdl('hdlcoder_atomic_subsys2_ports_redundant/DUT', 'DeleteUnusedPorts', 'off')

If you set DeleteUnusedPorts to off, the output port Out3 is preserved in the generated HDL code.

ENTITY DUT IS
 PORT( In1    :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1   :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2   :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END DUT;
ARCHITECTURE rtl OF DUT IS
-- Component Declarations
COMPONENT single_instance_atomic_subsys_dead_out
  PORT( In1    :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
        Out1   :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
        Out2   :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
        Out3   :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
        );
END COMPONENT;
...
END rtl;
ENTITY single_instance_atomic_subsys_dead_out IS
 PORT( In1      :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1     :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2     :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out3     :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END single_instance_atomic_subsys_dead_out;
ARCHITECTURE rtl OF single_instance_atomic_subsys_dead_out IS
...
Add_out1 <= to_signed(16#0000#, 16);
Out3 <= std_logic_vector(Add_out1);
END rtl;

If there are multiple atomic subsystem instances that are not active, the unused port and logic are removed or preserved depending on the DeleteUnusedPorts setting.

Open the model hdlcoder_atomic_subsys3_ports_redundant.

open_system('hdlcoder_atomic_subsys3_ports_redundant')
sim('hdlcoder_atomic_subsys3_ports_redundant');

The DUT subsystem contains an Atomic Subsystem block that contains an Add block connected to an output port terminated outside the subsystem.

open_system('hdlcoder_atomic_subsys3_ports_redundant/DUT')

The two atomic subsystem instances that have the output ports terminated are removed in the generated HDL code. In the other Atomic Subsystem block, the Add block calculation and its output is removed.

ENTITY DUT IS
 PORT( In1          :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1         :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2         :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END DUT;
ARCHITECTURE rtl OF DUT IS
-- Component Declarations
COMPONENT atomic_subsys_instance_1
  PORT( In1        :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
        Out1       :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
        Out2       :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
        );
END COMPONENT;
...
-- Removed
--
-- Removed
u_atomic_subsys_instance_1 : atomic_subsys_instance_1
  PORT MAP( In1 => In1,  -- int16
            Out1 => atomic_subsys_instance_1_out1,  -- int16
            Out2 => atomic_subsys_instance_1_out2  -- int16
            );
Out1 <= atomic_subsys_instance_1_out1;
Out2 <= atomic_subsys_instance_1_out2;
END rtl;

To set DeleteUnusedPorts to off, run this command:

makehdl('hdlcoder_atomic_subsys3_ports_redundant/DUT', 'DeleteUnusedPorts', 'off')

If you set DeleteUnusedPorts to off, the output port Out3 is preserved in the generated HDL code.

ENTITY DUT IS
 PORT( In1         :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1        :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2        :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END DUT;
ARCHITECTURE rtl OF DUT IS
-- Component Declarations
COMPONENT atomic_subsys_instance_1
  PORT( In1        :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
        Out1       :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
        Out2       :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
        Out3       :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
        );
END COMPONENT;

If you see the generated HDL code for the Atomic Subsystem instance, it shows that the Add block computation and Out3 is preserved in the generated HDL code.

ENTITY atomic_subsys_instance_1 IS
 PORT( In1          :   IN    std_logic_vector(15 DOWNTO 0);  -- int16
       Out1         :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out2         :   OUT   std_logic_vector(15 DOWNTO 0);  -- int16
       Out3         :   OUT   std_logic_vector(15 DOWNTO 0)  -- int16
       );
END atomic_subsys_instance_1;
ARCHITECTURE rtl OF atomic_subsys_instance_1 IS
...
Add_out1 <= In1_signed + In1_signed;
Out3 <= std_logic_vector(Add_out1);
END rtl;

Upstream Logic Preservation of Unused Port

You can preserve logic upstream from a Terminator block, its unused logic, while still removing other unconnected ports and unused logic. You can choose specific unused logic that you want to preserve for generated HDL code while still optimizing the rest of your model. Enable the HDL block property PreserveUpstreamLogic for the Terminator block for which you want to preserve the logic upstream. See PreserveUpstreamLogic.

Open the model hdlcoder_subsys_port_preserve.

open_system('hdlcoder_subsys_ports_preserved')
sim('hdlcoder_subsys_ports_preserved');

The model contains a DUT subsystem that has two Terminator blocks as output ports for the subsystem. The Terminator block TermPres has the HDL block property PreserveUpstreamLogic set to on. The Terminator block TermRem does not (the default setting). The model property DeleteUnusedPorts is enabled by default.

open_system('hdlcoder_subsys_ports_preserved/DUT')
hdlget_param('hdlcoder_subsys_ports_preserved/DUT/TermPres', 'PreserveUpstreamLogic')
ans =

    'on'

When you generate HDL code, the logic connected upstream from the TermPres block is preserved in the HDL code, including the outport Out2 from the normal_subsys_dead_out subsystem. Enabling PreserveUpstreamLogic for a Terminator block takes priority over the enabled DeleteUnusedPorts option. The logic connected upstream from the TermRem block is not preserved, including not preserving the outport from the normal_subsys_dead_out subsystem.

To generate HDL code for the DUT subsystem, run this command:

makehdl('hdlcoder_subsys_ports_preserved/DUT')

In the code traceability report, click the G1 gain connected to TermPres. The corresponding HDL code shows that the logic connected upstream from TermPres, such as G1, is preserved. No corresponding HDL code exists for the logic upstream from TermRem.

You can highlight the removed logic blocks upstream from TermRem by clicking the script highlightRemovedDeadBlocks.m in the output of the makehdl command. The removed blocks appear in red in the model. To clear the highlighting, click the script clearHighlightingRemovedDeadBlocks.m.

You can also view all eliminated and virtual blocks in the code generation report. Click Traceability Report, then view the Eliminated / Virtual Blocks section.

You can preserve the output port from the normal_subsys_dead_out subsystem connected to TermRem but still remove any upstream logic by disabling DeleteUnusedPorts for the model.

hdlset_param('hdlcoder_subsys_ports_preserved', 'DeleteUnusedPorts', 'off')

Generate HDL code for the DUT subsystem:

makehdl('hdlcoder_subsys_ports_preserved/DUT');

The traceability report now highlights the difference between the last HDL code generated and this HDL code. The logic upstream from TermRem, such as the gain block G2, is still removed because PreserveUpstreamLogic is off. The outport Out3 is now in the generated HDL code because DeleteUnusedPorts is set to off for the model.

Limitations

If your model contains multiple instances of atomic subsystems, model references, or Foreach Subsystem blocks, and these blocks are active during HDL code generation, then ports are preserved in the generated code. Components connected upstream to these ports are also considered active. The ports are preserved independently of whether you enable or disable the DeleteUnusedPorts setting.

This limitation also applies to bus signals. In this case, the entire bus is preserved in the generated HDL code. For an example, see Remove Redundant Logic and Unused Blocks in Generated HDL Code.

Related Topics