VHDL · Chapter 4.7 · Concurrent Statements
Port Maps — Named and Positional
Instantiation places a sub-block, and the port map wires it. A port map connects each of the instance's ports, called the formals, to a signal or port in the parent, called the actuals. There are two ways to write the connection. Named association states each link explicitly and does not depend on order, while positional association matches by declaration order alone. Named is the professional default because it is self-documenting and immune to reordering, whereas positional is terse but dangerously fragile. This lesson covers both styles, how to leave an unused output open, and why a positional mismatch with the right types but the wrong order is among the hardest structural bugs to spot, since everything compiles cleanly yet the wires go to the wrong places.
Foundation13 min readVHDLPort MapNamed AssociationPositionalStructuralConnectivity
1. Engineering intuition — soldering the pins
If instantiation is placing a chip, the port map is soldering its pins to the board's nets. Each
pin (port/formal) must reach the right net (signal/actual). You can solder by name — "connect pin
clk to net sys_clk" — or by position — "connect the pins in the order they are listed." Naming
each connection is slower to type but impossible to get subtly wrong; soldering by position is fast
but a single reordering silently miswires everything.
2. Formal explanation — named vs positional association
-- entity adder has ports, in this order: a, b, cin, sum, cout
-- NAMED association: 'formal => actual', any order, explicit:
u1 : entity work.adder
port map ( a => x, b => y, cin => '0', sum => s, cout => carry );
-- POSITIONAL association: actuals in the EXACT order of the entity's ports:
u2 : entity work.adder
port map ( x, y, '0', s, carry ); -- a<=x, b<=y, cin<='0', sum=>s, cout=>carryIn named association each formal port is paired with its actual explicitly (formal => actual),
so the order is irrelevant and the intent is on the page. In positional association the actuals
are matched to formals strictly by the entity's port declaration order — get the order wrong and the
tool happily connects the wrong nets if the types line up. In both cases each connection's
direction, type, and width must match the port.
3. Production-quality RTL — named maps and open
library ieee; use ieee.std_logic_1164.all;
-- Named association is self-documenting and reorder-proof:
u_fifo : entity work.fifo
port map ( clk => sys_clk,
rst => sys_rst,
wr_en => push,
din => wdata,
rd_en => pop,
dout => rdata,
full => fifo_full,
empty => open ); -- output we don't use → 'open'What hardware does this become? A FIFO instance with each pin wired to the named net; the unused
empty output is left unconnected (open). Naming every connection means this map is readable as a
wiring list and survives any future reordering of the entity's ports. Only outputs may be left
open; an input generally needs a driver (or a default), or it floats to 'U'.
4. Hardware interpretation — formals, actuals, and the binding
5. Structural interpretation — no new timing, just connectivity
A port map introduces no behaviour of its own; it is pure connectivity resolved at elaboration (lesson 4.6), when each formal is tied to its actual net. Because nothing here is about timing — the instance's behaviour over time is whatever the sub-block does — a structural binding diagram (above) is the right visualization, not a waveform. The only run-time consequence is that the instance now sees the parent's signals on its inputs and drives the parent's signals from its outputs.
6. Debugging example — the silent positional swap
Expected: a sub-block behaves correctly. Observed: it elaborates with no error, but its
function is wrong — outputs look like inputs were swapped. Root cause: a positional port map
listed two same-type actuals in the wrong order (e.g. b and a, or two control bits), so the tool
bound them silently because the types matched — no error, just miswired nets. Fix: switch the
instance to named association so every connection is explicit and a swap is impossible to miss.
Engineering takeaway: positional maps fail silently whenever same-type ports are reordered;
named association turns that whole class of bug into a visible, self-checking wiring list.
-- entity sub has ports in order: sel_a, sel_b (both std_logic)
-- WRONG: positional — actuals swapped, but types match, so NO error and wrong behaviour:
u : entity work.sub port map ( ctrl_b, ctrl_a ); -- sel_a<=ctrl_b, sel_b<=ctrl_a (swapped!)
-- RIGHT: named — the binding is explicit and the swap is impossible to make by accident:
u : entity work.sub port map ( sel_a => ctrl_a, sel_b => ctrl_b );7. Common mistakes & what to watch for
- Positional maps on real sub-blocks. A reorder silently miswires same-type ports. Use named association for anything beyond a trivial, stable interface.
- Leaving an input
open. Only outputs may beopen; an unconnected input floats to'U'. Drive every input (or give it a deliberate constant). - Direction/type/width mismatch. Each binding must match the port exactly; mismatches are elaboration errors (or, worse with positional, silent miswires when types happen to match).
- Connecting an
outport to read it internally. Read from the driving signal, not theoutport, unless usingbuffer/inoutdeliberately (lesson 1.6 on modes). - Mixing named and positional carelessly. It is allowed in a limited way but error-prone; pick named and stay consistent.
8. Engineering insight
The port map is where structural correctness is won or lost, and the choice of association style is a
real reliability decision. Named association costs a few extra characters and buys immunity to the
single most insidious structural bug — the silent same-type swap — while doubling as documentation:
the map reads as a labelled wiring list that survives port reordering and refactoring. Treat named
association as the default for every non-trivial instance, reserve open for outputs you genuinely
ignore, and let the direction/type/width checks catch the rest at elaboration. Reliable hierarchy is
built on explicit, checkable connections.
9. Summary
A port map binds an instance's formals (ports) to the parent's actuals (signals). Named association
(formal => actual) is explicit, order-independent, and self-documenting; positional association
matches by declaration order and fails silently on same-type reorders. Each binding's direction,
type, and width must match, only outputs may be left open, and named association is the
professional default.
10. Learning continuity
You can place a sub-block and wire it precisely. The last structural tool replicates them: the next
lesson, Generate Statements, uses for … generate and if … generate to instantiate arrays of
logic and conditionally include hardware — building regular structures like bit-sliced datapaths and
register files from a single parametric description, all still concurrent.