VHDL · Chapter 1.5 · Foundation
Entities and Architectures
Every VHDL block is built from two halves that the language deliberately keeps apart. The entity is its external interface, a contract of ports and their directions, and the architecture is the implementation hidden behind that contract. This is the most-used pattern in the language, and separating the interface from the implementation is what lets one design plug into another. This lesson teaches you to read and write a minimal entity and architecture pair, to understand port modes and how internal signals differ from ports, and to see exactly why the separation matters by giving one entity two different architectures that behave the same to the outside world.
Foundation15 min readVHDLEntityArchitecturePortsInterfaceRTL Design
1. Intuition — the chip's pinout and what's inside it
Picture a single chip in a package. From the outside you can only see its pins — which are inputs, which are outputs, how wide each bus is. You cannot see the logic inside the plastic. That outside view is the entity: it is the contract the block makes with the rest of the world.
The logic sealed inside the package — the gates and flip-flops that make the pins behave — is the architecture. Two chips can have the same pinout but completely different internals, and any board that uses them cannot tell the difference. VHDL builds this exact separation into the language.
2. The entity — an interface of ports
An entity declares the block's name and its ports — the named wires on its boundary. Every port has a mode (its direction) and a type:
library ieee;
use ieee.std_logic_1164.all;
entity mux2 is
port (
a : in std_logic; -- data input 0
b : in std_logic; -- data input 1
sel : in std_logic; -- select line
y : out std_logic -- selected output
);
end entity mux2;The mode is the direction of data flow at the boundary:
| Mode | Meaning | Typical use |
|---|---|---|
in | value flows into the block; read-only inside | inputs, clocks, resets |
out | value flows out of the block; driven inside | outputs |
inout | bidirectional | tri-state buses, pads |
buffer | an output the block also reads back | rare; usually avoidable |
For everyday RTL you live in in and out. The entity says nothing about how y
is produced — only that y exists, is an output, and is a std_logic.
3. The architecture — the implementation
The architecture is bound to an entity (architecture <name> of mux2 is) and
describes how the outputs are produced from the inputs. Here is a 2:1 multiplexer in
a single concurrent assignment:
architecture dataflow of mux2 is
begin
y <= a when sel = '0' else b; -- sel picks a (0) or b (1)
end architecture dataflow;Read y <= a when sel = '0' else b; as hardware, not as an if: it describes a
multiplexer whose output y is permanently wired to a or b depending on sel.
Ports vs internal signals
Ports cross the boundary; internal signals stay inside. You declare internal
signals in the architecture's declarative part (before begin) and use them to wire
sub-results together. They are invisible from outside the entity:
architecture rtl of mux2 is
signal nsel : std_logic; -- internal: not part of the interface
begin
nsel <= not sel; -- a helper wire inside the block
y <= (a and nsel) or (b and sel);
end architecture rtl;nsel is a real internal wire, but it is not a port — nothing outside mux2 can
see or connect to it. A frequent beginner mistake is trying to read an out port or
expose an internal signal; ports are the only contract, internal signals are private.
4. One entity, two architectures — why separation pays off
Because the interface and implementation are separate units, the same mux2
entity can have several architectures. We already wrote a dataflow one; here
is a behavioural one using a process — same pins, different style:
architecture behavioural of mux2 is
begin
process (a, b, sel)
begin
if sel = '0' then
y <= a;
else
y <= b;
end if;
end process;
end architecture behavioural;Both architectures implement the identical entity and produce the identical
hardware — a 2:1 mux. Anything that instantiates mux2 is unaffected by which one
you pick, because it only depends on the entity. That is the payoff of separating
interface from implementation: implementations are swappable, contracts are stable.
5. Black-box view — reading the pair as hardware
Putting it together: the entity is the boundary with ports on it; the architecture is the logic drawn inside that boundary.
6. Behaviour over time — the mux in a waveform
The mux is combinational: y follows whichever input sel currently selects, with
no clock involved. Watch sel steer the output between a and b:
mux2 — y = a when sel = '0', else b
6 cycles7. Common mistakes & what to watch for
- Putting logic in the entity. The entity is a contract — ports and generics only. All behaviour belongs in the architecture.
- Reading an
outport. A plainoutport is write-only inside the block. If you need the value internally, drive an internal signal and assign the port from it (or use a later-lesson construct), rather than reading the port back. - Confusing internal signals with ports. Internal signals (declared before
begin) are private wires; only ports appear on the boundary and connect outward. - Mismatched names or modes. The architecture must use the exact port names from its entity, with directions that match how they are driven; a mode mismatch is a compile error, not a warning.
8. Summary & next step
The entity/architecture pair is the heart of VHDL. The entity is the external interface — a contract of named ports, each with a mode and a type. The architecture is the implementation behind that contract, where internal signals and logic live, hidden from the outside. Keeping them separate is what lets one entity carry several interchangeable architectures and what makes VHDL designs composable.
From here the foundations continue into the details this pair depends on — ports and
their modes in depth, the strong type system behind std_logic, and the
signal model that governs how assignments like y <= a actually behave over time.