Components & Instantiation

Designing structural architectures in VHDL: component declarations, port map, generic map, and direct instantiation.

Structural Design

In VHDL there are two main ways to describe a circuit:

StyleDescription
Behavioral (RTL)Describes what the circuit does (process, assignments)
StructuralAssembles existing components like a schematic

The structural style is essential for organizing large designs into hierarchical blocks. A top-level connects components (UART, ALU, FIFO…) through internal signals.


Component Declaration (component)

Before instantiating a component, its interface must be declared in the architecture declarative region:

architecture rtl of top_level is
 
  -- Component declaration (copy of the entity)
  component adder is
    generic (
      g_WIDTH : integer := 8
    );
    port (
      i_a    : in  std_logic_vector(g_WIDTH-1 downto 0);
      i_b    : in  std_logic_vector(g_WIDTH-1 downto 0);
      o_sum  : out std_logic_vector(g_WIDTH-1 downto 0);
      o_cout : out std_logic
    );
  end component adder;
 
  -- Interconnect signals
  signal w_result : std_logic_vector(7 downto 0);
  signal w_carry  : std_logic;
 
begin
  -- Instantiation
  U_ADD : adder
    generic map (g_WIDTH => 8)
    port map (
      i_a    => i_operand_a,
      i_b    => i_operand_b,
      o_sum  => w_result,
      o_cout => w_carry
    );
 
end architecture rtl;

Convention: instances are prefixed U_ (Unit) or numbered U1, U2.


Direct Instantiation (VHDL-93)

The modern approach without component — instantiating directly from the entity:

architecture rtl of top_level is
  signal w_sum   : std_logic_vector(7 downto 0);
  signal w_carry : std_logic;
begin
 
  U_ADD : entity work.adder
    generic map (g_WIDTH => 8)
    port map (
      i_a    => i_op_a,
      i_b    => i_op_b,
      o_sum  => w_sum,
      o_cout => w_carry
    );
 
end architecture rtl;

work refers to the current working library — the one containing your project's files.


Named vs Positional Association

-- Named association (recommended — explicit and safe)
port map (
  i_clk   => i_clk,
  i_rst   => i_reset,
  o_data  => w_data_out
);
 
-- Positional association (discouraged — fragile)
port map (i_clk, i_reset, w_data_out);

Always use named association. Positional association breaks if the port order changes in the entity.


The open Port — Unconnected Output

If a component output is not used, explicitly leave it open:

U_CNT : entity work.counter
  port map (
    i_clk    => i_clk,
    i_rst    => i_rst,
    o_count  => w_count,
    o_tc     => open     -- Terminal Count not used
  );

open is forbidden on inputs — an input must always be connected to a signal or a value ('0', '1', etc.).


Complete Example: Structural Top-Level

A top-level connecting a BCD counter to a 7-segment decoder:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity top_display is
  port (
    i_clk   : in  std_logic;
    i_rst   : in  std_logic;
    o_seg   : out std_logic_vector(6 downto 0)
  );
end entity top_display;
 
architecture structural of top_display is
 
  signal w_bcd : std_logic_vector(3 downto 0);
 
begin
 
  -- BCD counter: counts from 0 to 9
  U_CNT : entity work.bcd_counter
    port map (
      i_clk   => i_clk,
      i_rst   => i_rst,
      i_en    => '1',
      o_count => w_bcd,
      o_tc    => open
    );
 
  -- 7-segment decoder: BCD → display
  U_DEC : entity work.decoder_7seg
    port map (
      i_bcd => w_bcd,
      o_seg => o_seg
    );
 
end architecture structural;

The BCD value flows through the internal signal w_bcdcomponents never connect directly to each other, they always go through signals.


Multiple Instances of the Same Component

A component can be instantiated multiple times. Example: 4 D flip-flops forming a shift register:

architecture structural of shift_reg_4 is
  signal w_chain : std_logic_vector(4 downto 0);
begin
 
  w_chain(0) <= i_data;
 
  GEN_FF : for i in 0 to 3 generate
    U_FF : entity work.dff
      port map (
        i_clk => i_clk,
        i_rst => i_rst,
        i_d   => w_chain(i),
        o_q   => w_chain(i+1)
      );
  end generate GEN_FF;
 
  o_data <= w_chain(4);
 
end architecture structural;

The generate statement creates N instances automatically — essential for regular structures (register arrays, matrices).


Mixed: Structural + Behavioral

Both styles can coexist in the same architecture:

architecture rtl of mixed_example is
  signal w_count : unsigned(7 downto 0);
  signal w_done  : std_logic;
begin
 
  -- Behavioral block (process)
  p_ctrl : process(i_clk)
  begin
    if rising_edge(i_clk) then
      if w_done = '1' then
        o_led <= '1';
      end if;
    end if;
  end process p_ctrl;
 
  -- Structural block (instantiation)
  U_CNT : entity work.counter_8bit
    port map (
      i_clk   => i_clk,
      i_rst   => i_rst,
      o_count => w_count,
      o_tc    => w_done
    );
 
end architecture rtl;

Summary

ConceptSyntax
Direct instantiationU_X : entity work.name
With genericgeneric map (g_PARAM => value)
Port connectionport map (port => signal)
Unused outputo_port => open
Multiple instancesgenerate loop

Golden rule: the top-level contains only instantiations and interconnect signals — all business logic lives inside the sub-components.