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_vector → unsigned |
unsigned(slv) |
unsigned → std_logic_vector |
std_logic_vector(u) |
unsigned → integer |
to_integer(u) |
integer → unsigned |
to_unsigned(i, width) |
integer → signed |
to_signed(i, width) |
std_logic_vector → integer |
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
process (all)— automatic sensitivity list- Conditional/selected signal assignment inside processes
if rising_edge(clk) and en = '1' then— boolean mixing- Reading
outports (no more dummy internal signals) slv sll 3, unaryand/or/xorreduction:and v,xor v
Gotchas
'1'vs"1"vs1: character, vector, integer — the compiler will punish confusion with pages of overload errors.- Integer types are 32-bit signed unless range-constrained; constrain
(
integer range 0 to 255) so synthesis knows the width. - Variables (
:=) update immediately inside a process; signals (<=) update at the end of the delta — mixing them carelessly reorders logic. - Default port values are ignored by synthesis when the port is unconnected in some tools; connect everything explicitly.