VHDL · Chapter 1.11 · Foundation
Your First VHDL Design
Everything in this chapter so far has been a single piece: entities, ports, the signal model, and libraries. This lesson assembles them into one complete, working design, a small register with an enable, which is the kind of block that appears in every real RTL project. You will read it from the outside in, starting with the interface and then the implementation, see exactly what hardware it becomes, watch its behaviour in a waveform, and see how a testbench would exercise it. It is deliberately simple, because the goal here is a design you fully understand from top to bottom before moving on to larger and more elaborate blocks.
Foundation15 min readVHDLFirst DesignRegisterEnableTestbenchRTL Design
1. Intuition — a register you can switch on and off
The block we will build is a register with an enable: on each clock edge, if enable is high, it captures the input; otherwise it holds what it already has. A reset clears it to zero. That is it — and it is genuinely useful: enable-registers are how designs hold a value steady until they are ready to update it (a captured sample, a configuration word, a pipeline stage that can stall).
It is the simplest design that is still real: it has state, a clock, a control input, and a reset — the four ingredients of almost all sequential hardware.
2. The complete design
Here is the whole thing — library/use, entity, and architecture in one file:
library ieee;
use ieee.std_logic_1164.all;
entity reg_en is
port (
clk : in std_logic; -- clock
rst : in std_logic; -- synchronous reset, active high
en : in std_logic; -- load enable
d : in std_logic_vector(3 downto 0); -- data in
q : out std_logic_vector(3 downto 0) -- registered data out
);
end entity reg_en;
architecture rtl of reg_en is
begin
process (clk)
begin
if rising_edge(clk) then -- everything happens on the rising edge
if rst = '1' then
q <= (others => '0'); -- reset wins: clear to 0000
elsif en = '1' then
q <= d; -- enabled: capture d
end if; -- else: hold (q keeps its value)
end if;
end process;
end architecture rtl;3. Reading it from interface to implementation
Read any VHDL design the way the tools do — outside first, then inside.
- The interface (
entity). Four inputs (clk,rst,en, a 4-bitd) and one 4-bit outputq. That is the entire contract; anything using this block sees only these five ports. - The implementation (
architecture). One clockedprocess. The sensitivity list is just(clk), andrising_edge(clk)means the body acts only at the rising edge — so this is sequential logic. The priority is explicit: reset first, then enable, and if neither applies,qis simply not assigned — which in a clocked process means it holds its value (the register remembers).
That "else: hold" is the key idea. Not assigning q on some edge does not create a latch
here (we are already inside an edge-triggered process) — it is exactly how you describe a
flip-flop that keeps its value when not loaded.
4. The hardware it becomes
This description is not abstract — it maps to a specific, predictable circuit: a 4-bit bank of flip-flops, with a small amount of logic in front of them choosing what to load.
The edge from the flip-flops back into the select logic is the hold path — when
en = '0', the register feeds its own value back in, which is what "keep the value" means
in gates.
5. Watching it run
A waveform makes the behaviour concrete. Reset clears q; an enabled edge loads d; with
enable low, q holds across edges even as d changes:
reg_en — reset clears, enable loads d, low enable holds
12 cycles6. How a testbench would drive it
You verify a design by wrapping it in a testbench that generates a clock, applies
stimulus, and lets you observe q. At a high level it does three things — make a clock,
sequence the controls, and run:
clk <= not clk after 5 ns; -- free-running clock (simulation only)
stim : process
begin
rst <= '1'; en <= '0'; wait for 12 ns; -- hold in reset
rst <= '0'; d <= "0101"; en <= '1'; -- load 5
wait for 10 ns;
en <= '0'; d <= "1001"; -- en low: q must hold (d ignored)
wait for 20 ns;
d <= "0011"; en <= '1'; -- load 3
wait for 10 ns;
wait; -- stop stimulus
end process;Note the after and wait for: this is testbench-only code (see the previous lesson)
— it drives the simulation but is never synthesized. The reg_en design itself contains
none of it.
7. Common mistakes & what to watch for
- Forgetting the hold case. New designers often add an
else q <= d;or drivequnconditionally, destroying the enable behaviour. "Do nothing on this edge" is the hold — leavequnassigned. - Reading
qinside the process.qis anoutport; if you needed its value internally you would use an internal signal (covered in ports and modes). Here you do not. - Putting clock generation in the design. The
after-based clock belongs in the testbench, never inreg_en. - Async vs sync reset confusion. This reset is synchronous (checked inside
rising_edge). An asynchronous reset is written differently — a deliberate choice covered later.
8. Summary & next step
You built a complete, real design: a 4-bit register with enable and synchronous reset. Read interface-first, it is five ports; read implementation-first, it is one clocked process with a clear reset → enable → hold priority. It synthesizes to four flip-flops with selection logic, behaves exactly as its waveform shows, and is exercised by a small testbench whose timing constructs stay out of the design. That is the shape of essentially all sequential RTL.
One thing stood between writing this file and seeing that waveform: a toolchain. The final foundations lesson covers what a VHDL toolchain does — analyse, elaborate, simulate, and optionally synthesize — and how to organise a beginner project so the flow is smooth.