Ultimate VHDL Cheat Companion: Templates, Idioms, and Best Practices

VHDL Cheat Guide for Beginners: Essential Tips and Examples

What VHDL is — quickly

VHDL (VHSIC Hardware Description Language) models digital hardware at multiple abstraction levels. It describes structure and behavior so synthesis tools can map designs to FPGAs/ASICs. Think of it as code that defines circuits rather than sequential programs.

File and basic structure

  • Entity: External interface (ports).
  • Architecture: Internal implementation (behavior/structure).
  • Library/use: Include standard packages (e.g., IEEE). Minimal template:

vhdl

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity my_module is port ( clk : in std_logic; rst_n : in std_logic; a : in std_logic_vector(7 downto 0); y : out std_logic_vector(7 downto 0) ); end my_module; architecture rtl of my_module is begin – implementation end rtl;

Common types

  • std_logic — single-valued digital signal (0,1,Z,X,…).
  • std_logic_vector(N downto 0) — bus of bits.
  • signed / unsigned — arithmetic vectors (from IEEE.NUMERIC_STD).
  • integer, boolean — for simulation and synthesis-limited uses.

Always prefer IEEE.NUMERICSTD for arithmetic:

vhdl

use IEEE.NUMERIC_STD.ALL; signal asigned : signed(7 downto 0);

Combinational vs. sequential coding

  • Combinational: outputs update whenever inputs change. Use concurrent assignment or combinational process with all signals in sensitivity list.

vhdl

– concurrent y <= a and b; – combinational process process(a, b) begin if a = ‘1’ then y <= b; else y <= ‘0’; end if; end process;
  • Sequential (clocked): state changes on clock edge. Use risingedge(clk) or clk’event and clk = ‘1’.

vhdl

process(clk, rst_n) begin if rst_n = ‘0’ then q <= (others => ‘0’); elsif rising_edge(clk) then q <= d; end if; end process;

Reset styles

  • Synchronous reset: checked inside clock edge.
  • Asynchronous reset: checked before edge in process sensitivity. Prefer one style consistently per design and follow target FPGA vendor recommendations.

Vectors and slicing

  • Concatenate: x <= a & b;
  • Slice: part <= vec(7 downto 4);
  • Resize/convert with numericstd:

vhdl

c <= std_logic_vector(resize(a_signed, 16));

Arithmetic tips

  • Convert std_logicvector ↔ signed/unsigned for math:

vhdl

signal a, b : std_logic_vector(7 downto 0); signal sum : std_logic_vector(8 downto 0); sum <= std_logic_vector(unsigned(a) + unsigned(b));
  • Avoid arithmetic on std_logicvector directly.

State machines

  • Use enumerated types for states.
  • Two-process FSM (one for state register, one for next-state/outputs) is clear and synthesis-friendly. Example:

vhdl

type state_t is (IDLE, LOAD, RUN); signal state, next_state : state_t; – state register process(clk, rst_n) begin if rst_n = ‘0’ then state <= IDLE; elsif rising_edge(clk) then state <= next_state; end if; end process; – next-state logic process(state, start) begin case state is when IDLE => if start = ‘1’ then next_state <= LOAD; else next_state <= IDLE; end if; when others => next_state <= IDLE; end case; end process;

Clock domain crossing (CDC) basics

  • Avoid direct transfers between different clock domains.
  • Use synchronizer flip-flops for single-bit signals.
  • Use FIFOs for multibit data crossing domains.

Testbenches and simulation

  • Testbench has no ports; instantiate DUT and drive stimuli.
  • Use assert statements for checks; use wait for and process timing. Simple testbench skeleton: “`vhdl entity tb_my_module is end tb_my_module;

architecture sim of tb_my_module is signal clk : std_logic := ‘0’; begin clk_gen: process begin