Skip to content

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:

reg_en.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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-bit d) and one 4-bit output q. That is the entire contract; anything using this block sees only these five ports.
  • The implementation (architecture). One clocked process. The sensitivity list is just (clk), and rising_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, q is 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.

Enable register: select logic feeding a 4-bit flip-flop bankd[3:0]data inrst / encontrolnext-value selectrst→0 · en→d · else hold4 × D flip-flopclocked by clkq[3:0]registered out12
The design synthesizes to four D flip-flops (the 4-bit register q) clocked by clk. In front of each flip-flop, selection logic chooses the next value: reset forces 0, else enable selects d, else the flip-flop's own current value (hold). rst, en, and clk are control inputs into that logic; d is the data path; q is the registered output. This is the canonical enabled-register structure.

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 cycles
reg_en — reset clears, enable loads d, low enable holdsrst=1 → q stays 0000rst=1 → q stays 0000en=1 → q loads d (=5)en=1 → q loads d (=5)en=0 → q holds 5 though d=9en=0 → q holds 5 thoug…en=1 → q loads new d (=3)en=1 → q loads new d (…clkrstend555599993333qt0t1t2t3t4t5t6t7t8t9t10t11
q only changes at a rising edge, and only when reset or enable says so. While en=0, q holds 5 even as d moves to 9 — the register is ignoring its input, exactly as the 'else: hold' branch describes.

6. 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:

tb_reg_en.vhd — stimulus sketch (testbench-only)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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 drive q unconditionally, destroying the enable behaviour. "Do nothing on this edge" is the hold — leave q unassigned.
  • Reading q inside the process. q is an out port; 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 in reg_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.