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:
| Style | Description |
|---|---|
| Behavioral (RTL) | Describes what the circuit does (process, assignments) |
| Structural | Assembles 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 numberedU1,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
);
openis 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_bcd — components 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
| Concept | Syntax |
|---|---|
| Direct instantiation | U_X : entity work.name |
| With generic | generic map (g_PARAM => value) |
| Port connection | port map (port => signal) |
| Unused output | o_port => open |
| Multiple instances | generate loop |
Golden rule: the top-level contains only instantiations and interconnect signals — all business logic lives inside the sub-components.