Introduction to VHDL Design Units
VHDL (VHSIC Hardware Description Language) code is composed of design units, which are the fundamental building blocks of all source code, whether it’s behavioral, RTL (Register Transfer Level), or structural. A design unit may encompass an entire file or there may be multiple design units within a single file. All design units are ultimately compiled into a library for use in digital design projects.
The main VHDL design units are:
- Library
- Package
- Entity
- Architecture
- Configuration
1. Library
Libraries in VHDL are repositories for commonly used items and are comprised of one or more compiled packages. These libraries can be created by IEEE, vendors, or designers for code reuse and standardization.
- To use a library, declare it first with the keyword
library
- Specify which part or package of the library should be used
- Use the
.ALL
statement to include all packages from a library
Common VHDL libraries include:
- IEEE: Contains standard logic types and arithmetic functions
- STD: Provides basic VHDL types and functions
- WORK: Default library for the current project
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; library UNISIM; use UNISIM.VComponents.all;
2. Package
Packages in VHDL are used to encapsulate and store common declarations like types, subtypes, constants, procedures, and functions that can be shared across two or more design units. This promotes code reuse and modularity.
A package consists of two parts:
- Package Declaration (mandatory): Contains declarations of types, subtypes, constants, and function/procedure prototypes
- Package Body (optional): Describes the behavior of functions or procedures declared in the package declaration
-- Package Declaration package my_package is constant MAX_COUNT : integer := 255; type state_type is (IDLE, ACTIVE, DONE); function add_one(input : integer) return integer; end package my_package; -- Package Body package body my_package is function add_one(input : integer) return integer is begin return input + 1; end function add_one; end package body my_package;
3. Entity
An entity in VHDL describes the interface between the behavior of a module and the outside world or “calling” module. It defines the inputs and outputs of a design unit.
- The top of every design hierarchy must be an entity
- An entity is modeled using an entity declaration and one or more architectures
- The entity declaration specifies the name of the entity and lists the set of interface ports
The entity consists of two main parts:
- Generics: Provide a list of parameters used to control the width of ports or internal signals
- Ports: List the input, output, and bidirectional signals
There are four types of ports allowed in VHDL:
- in: Signals arriving into the module (can be read but not assigned)
- out: Signals produced by the module (can be assigned but not read within the module)
- inout: Bidirectional signals that can be used or modified
- buffer: Can be assigned and read internal to the module (less commonly used)
entity counter is generic ( WIDTH : integer := 8 ); port ( clk : in std_logic; reset : in std_logic; enable : in std_logic; count : out std_logic_vector(WIDTH-1 downto 0) ); end entity counter;
4. Architecture
The architecture in VHDL describes the behavior or structure of a module and contains the internal description of the entity used to implement a design. It defines how the outputs are generated based on the inputs and internal signals.
- VHDL allows multiple architectures for a single entity, as long as their names are unique in the target library
- Different architectures can represent different implementations or levels of abstraction (e.g., behavioral, RTL, structural)
- The architecture body consists of two main parts: the declarative part and the statement part
architecture RTL of counter is signal count_int : unsigned(WIDTH-1 downto 0); begin process(clk, reset) begin if reset = '1' then count_int <= (others => '0'); elsif rising_edge(clk) then if enable = '1' then count_int <= count_int + 1; end if; end if; end process; count <= std_logic_vector(count_int); end architecture RTL;
5. Configuration
A configuration in VHDL specifies the binding of one architecture body with an entity and the bindings of components used in the selected architecture body to other entities. It allows for flexible design management and the ability to select different implementations of components.
- Specifies which architecture to use for a given entity
- Can bind components to specific entity-architecture pairs
- Allows for easy swapping of different implementations without changing the main code
- An entity can have any number of different configurations
configuration counter_config of counter is for RTL -- Specify which architecture to use -- You can add component configurations here if needed end for; end configuration counter_config;
Typical VHDL "Module" Structure
A typical VHDL module consists of three basic design units: library declarations, entity, and architecture. Here are some key points about VHDL modules:
- They are members of a design hierarchy
- Each module typically performs a single idea or task
- A small top-level VHDL module is often made up of instantiated lower-level modules
- Modules should have a defined interface, behavior, and target performance
- The overall project should have defined performance goals and connections to the outside world
Here's an example of a typical VHDL module structure:
-- Library declarations library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; -- Entity declaration entity example_module is generic ( DATA_WIDTH : integer := 8 ); port ( clk : in std_logic; reset : in std_logic; input : in std_logic_vector(DATA_WIDTH-1 downto 0); output : out std_logic_vector(DATA_WIDTH-1 downto 0) ); end entity example_module; -- Architecture declaration architecture RTL of example_module is -- Internal signals, components, and type declarations signal internal_data : unsigned(DATA_WIDTH-1 downto 0); begin -- Behavioral description process(clk, reset) begin if reset = '1' then internal_data <= (others => '0'); elsif rising_edge(clk) then internal_data <= unsigned(input) + 1; end if; end process; output <= std_logic_vector(internal_data); end architecture RTL;
Understanding these VHDL design units and how they interact is crucial for effective digital design using VHDL. Each unit plays a specific role in describing the structure, behavior, and interfaces of digital systems, allowing for modular, reusable, and scalable designs.