VHDL Reference
Free reference guide: VHDL Reference
About VHDL Reference
The VHDL Reference is a comprehensive, searchable cheat sheet covering the VHSIC Hardware Description Language used for FPGA and ASIC design. It documents entity declarations with port modes (in, out, inout, buffer), generic parameters for configurable constants, component declaration and instantiation with port maps/generic maps, and VHDL-93 direct entity instantiation without component declarations. Architecture definitions are covered including signal declarations (internal wires), variable usage within processes (immediate assignment vs signal end-of-process update), and concurrent signal assignment with conditional (when/else) and selected (with/select) forms.
The type system section covers IEEE STD_LOGIC_1164 nine-value logic (0, 1, Z, X, U, W, L, H, -), IEEE NUMERIC_STD unsigned/signed arithmetic types with complete type conversion examples (std_logic_vector to unsigned to integer and back), user-defined enumeration types for FSM states, record types for bus interfaces (like AXI Stream), array types for memory/ROM/RAM declaration, and constant declarations. The process and control section details synchronous processes for flip-flop inference (with synchronous and asynchronous reset patterns), combinational processes with sensitivity list requirements (and VHDL-2008 process(all)), FSM state machine design patterns with case statements, and generate statements for repetitive (for generate) and conditional (if generate) hardware instantiation.
Operator and function coverage includes logical operators (and, or, xor, nand, nor, xnor, not, sll, srl, rol), numeric_std arithmetic (addition with carry, multiplication, signed/unsigned comparison), user-defined synthesizable functions (like log2ceil for bit-width calculation), and aggregate notation with others keyword and concatenation. The testbench section provides templates for clock generation, DUT instantiation, stimulus processes, assert/report statements with severity levels, wait statements (time, condition, clock cycles), and file I/O using std.textio for reading test vectors. Package and library sections cover package declaration/body, library/use imports (IEEE vs non-standard), and vendor-specific synthesis attributes (fsm_encoding, dont_touch, IOB). VHDL syntax is highlighted throughout. All content runs entirely in your browser.
Key Features
- Entity/port declarations with all port modes (in, out, inout, buffer), generics, and component instantiation
- Architecture patterns: signal vs variable, concurrent assignment (when/else, with/select), and direct instantiation
- Complete type system: std_logic (9-value), unsigned/signed with type conversions, enumerations, records, and arrays
- Synchronous and combinational process patterns with reset styles and VHDL-2008 process(all)
- FSM state machine design template with case statements and proper reset handling
- Operator reference: logical, arithmetic, shift, comparison, and aggregate notation with examples
- Testbench templates: clock generation, assert/report, wait statements, and file I/O for test vectors
- Package/library usage: IEEE standard imports, user packages, and vendor-specific synthesis attributes
Frequently Asked Questions
What is the difference between a signal and a variable in VHDL?
Signals represent physical wires and are updated at the end of the current process execution (delta cycle). Variables exist only inside processes and are updated immediately when assigned. This means if you assign a signal multiple times in a process, only the last assignment takes effect. Variables reflect each assignment instantly, making them useful for intermediate calculations. Signals use <= for assignment, variables use :=. In synthesizable RTL, signals infer registers or wires depending on context, while variables typically create combinational logic.
How do I avoid unintended latches in combinational processes?
Unintended latches are inferred when a signal is not assigned in all possible branches of a combinational process. To prevent this: (1) always include all read signals in the sensitivity list (or use process(all) in VHDL-2008), (2) assign default values to all outputs at the top of the process before any if/case statements, (3) always include an "others" clause in case statements, and (4) ensure every signal is assigned in every possible execution path. If a signal is conditionally assigned without a default, the synthesizer infers a latch to hold the previous value.
Should I use synchronous or asynchronous reset?
Synchronous reset (checked inside rising_edge(clk)) is generally preferred for FPGA designs because it uses the flip-flop's synchronous reset input, results in cleaner timing, and avoids potential metastability issues. Asynchronous reset (in the sensitivity list, checked before rising_edge) is required when the clock might not be running during reset, such as in power-on sequences. Xilinx recommends synchronous reset for most FPGA designs. The key pattern: synchronous has "if rising_edge(clk) then if rst..." while asynchronous has "if rst... elsif rising_edge(clk)".
Why should I use numeric_std instead of std_logic_arith?
IEEE NUMERIC_STD is the official IEEE standard (1076.3) for arithmetic operations on std_logic_vector-based types. std_logic_arith and std_logic_unsigned are Synopsys proprietary packages that are NOT part of the IEEE standard, though they were historically included in many tools. Using numeric_std avoids ambiguity (it explicitly separates unsigned and signed types), is portable across all tools, and is the universally recommended practice. Never mix numeric_std with std_logic_arith in the same file.
How do I convert between std_logic_vector, unsigned, integer, and signed?
Use these conversion functions from IEEE.NUMERIC_STD: std_logic_vector to unsigned: unsigned(slv). Unsigned to std_logic_vector: std_logic_vector(u). Unsigned to integer: to_integer(u). Integer to unsigned: to_unsigned(int_val, width). For signed: signed(slv), std_logic_vector(s), to_integer(s), to_signed(int_val, width). Direct conversion between std_logic_vector and integer requires going through unsigned or signed as an intermediate step.
What is a generate statement and when should I use it?
Generate statements create repetitive or conditional hardware structures at elaboration time (before synthesis). "for generate" creates multiple instances of the same component — for example, instantiating N register cells in a shift register. "if generate" conditionally includes hardware based on a generic or constant — for example, including a parity generator only when USE_PARITY is true. Generate statements replace manual copy-paste of repeated structures, making designs parameterizable and maintainable. They execute at compile time, not runtime.
How do I write a proper VHDL testbench?
A testbench entity has no ports (entity tb_name is end entity). In the architecture: (1) declare signals matching the DUT ports, (2) generate a clock with "clk <= not clk after CLK_PERIOD/2", (3) instantiate the DUT with port map, (4) create a stimulus process using wait statements to apply inputs and wait for results. Use assert statements to verify outputs: "assert actual = expected report error_message severity error". End the stimulus process with "wait;" to stop simulation. Use file I/O (std.textio) to read test vectors from external files for thorough testing.
What are vendor-specific synthesis attributes in VHDL?
Synthesis attributes are directives to the synthesis tool that control how VHDL code is implemented in hardware. Common examples: fsm_encoding controls state machine encoding (one_hot, sequential, gray); dont_touch prevents the optimizer from removing or modifying a signal/component; IOB forces a register into an I/O block for better timing. These are declared with "attribute attr_name : string" and applied with "attribute attr_name of signal_name : signal is value". Attributes vary by vendor (Xilinx, Intel/Altera, Lattice) — check your tool documentation for supported attributes.