VHDL Quick Reference

Synthesizable VHDL-2008 patterns without the boilerplate archaeology.

Entity + architecture skeleton

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;            -- the only arithmetic package you need

entity my_block is
    generic (WIDTH : integer := 8);
    port (
        clk       : in  std_logic;
        rst       : in  std_logic;
        din       : in  std_logic_vector(WIDTH-1 downto 0);
        din_valid : in  std_logic;
        dout      : out std_logic_vector(WIDTH-1 downto 0)
    );
end entity;

architecture rtl of my_block is
    signal count : unsigned(WIDTH-1 downto 0);
begin
    -- ...
end architecture;

The two processes that matter

-- 1. Sequential (registered) logic
process (clk) begin
    if rising_edge(clk) then
        if rst = '1' then
            q <= (others => '0');
        else
            q <= d;
        end if;
    end if;
end process;

-- 2. Combinational: VHDL-2008 'all' kills sensitivity-list bugs
process (all) begin
    y <= a and b;
    if sel = '1' then y <= c; end if;   -- assign every path or infer a latch
end process;

Types and conversions (the eternal table)

From → To Expression
std_logic_vectorunsigned unsigned(slv)
unsignedstd_logic_vector std_logic_vector(u)
unsignedinteger to_integer(u)
integerunsigned to_unsigned(i, width)
integersigned to_signed(i, width)
std_logic_vectorinteger to_integer(unsigned(slv))

Never use std_logic_arith / std_logic_unsigned — they're non-standard; numeric_std does everything.

Common inferences

-- Counter
count <= (others => '0') when rst = '1' else count + 1 when rising_edge(clk);

-- Block RAM (registered read)
type ram_t is array (0 to DEPTH-1) of std_logic_vector(7 downto 0);
signal ram : ram_t;
process (clk) begin
    if rising_edge(clk) then
        if we = '1' then ram(to_integer(unsigned(waddr))) <= wdata; end if;
        rdata <= ram(to_integer(unsigned(raddr)));
    end if;
end process;

-- FSM with enumerated type (tools re-encode automatically)
type state_t is (IDLE, RUN, DONE);
signal state : state_t;
process (clk) begin
    if rising_edge(clk) then
        if rst = '1' then state <= IDLE;
        else
            case state is
                when IDLE => if start = '1' then state <= RUN;  end if;
                when RUN  => if last  = '1' then state <= DONE; end if;
                when DONE => state <= IDLE;
            end case;
        end if;
    end if;
end process;

VHDL-2008 conveniences worth enabling

Gotchas