Recent from talks
Nothing was collected or created yet.
This article has multiple issues. Please help improve it or discuss these issues on the talk page. (Learn how and when to remove these messages)
|
| VHDL | |
|---|---|
| Paradigm | concurrent, reactive, dataflow |
| First appeared | 1980s |
| Stable release | IEEE 1076-2019
/ 23 December 2019 |
| Typing discipline | strong |
| Filename extensions | .vhd |
| Website | IEEE VASG |
| Dialects | |
| VHDL-AMS | |
| Influenced by | |
| Ada,[1] Pascal | |
| |

VHDL (VHSIC Hardware Description Language) is a hardware description language that can model the behavior and structure of digital systems at multiple levels of abstraction, ranging from the system level down to that of logic gates, for design entry, documentation, and verification purposes. The language was developed for the US military VHSIC program in the 1980s, and has been standardized by the Institute of Electrical and Electronics Engineers (IEEE) as IEEE Std 1076; the latest version of which is IEEE Std 1076-2019. To model analog and mixed-signal systems, an IEEE-standardized HDL based on VHDL called VHDL-AMS (officially IEEE 1076.1) has been developed.
History
[edit]In 1983, VHDL was originally developed at the behest of the U.S. Department of Defense in order to document the behavior of the ASIC that supplier companies were including in equipment. The standard MIL-STD-454N[2] in Requirement 64 in section 4.5.1 "ASIC documentation in VHDL" explicitly requires documentation of "Microelectronic Devices" in VHDL.
The idea of being able to simulate the ASICs from the information in this documentation was so obviously attractive that logic simulators were developed that could read the VHDL files. The next step was the development of logic synthesis tools that read the VHDL and output a definition of the physical implementation of the circuit.
Due to the Department of Defense requiring as much of the syntax as possible to be based on Ada, in order to avoid re-inventing concepts that had already been thoroughly tested in the development of Ada,[citation needed] VHDL borrows heavily from the Ada programming language in both concept and syntax.
The initial version of VHDL, designed to IEEE standard IEEE 1076–1987,[3] included a wide range of data types, including numerical (integer and real), logical (bit and Boolean), character and time, plus arrays of bit called bit_vector and of character called string.
A problem not solved by this edition, however, was "multi-valued logic", where a signal's drive strength (none, weak or strong) and unknown values are also considered. This required IEEE standard 1164, which defined the 9-value logic types: scalar std_logic and its vector version std_logic_vector. Being a resolved subtype of its std_Ulogic parent type, std_logic-typed signals allow multiple driving for modeling bus structures, whereby the connected resolution function handles conflicting assignments adequately.
The updated IEEE 1076, in 1993, made the syntax more consistent, allowed more flexibility in naming, extended the character type to allow ISO-8859-1 printable characters, added the xnor operator, etc.[specify]
Minor changes in the standard (2000 and 2002) added the idea of protected types (similar to the concept of class in C++) and removed some restrictions from port mapping rules.
In addition to IEEE standard 1164, several child standards were introduced to extend functionality of the language. IEEE standard 1076.2 added better handling of real and complex data types. IEEE standard 1076.3 introduced signed and unsigned types to facilitate arithmetical operations on vectors. IEEE standard 1076.1 (known as VHDL-AMS) provided analog and mixed-signal circuit design extensions.
Some other standards support wider use of VHDL, notably VITAL (VHDL Initiative Towards ASIC Libraries)[4] and microwave circuit design extensions.
In June 2006, the VHDL Technical Committee of Accellera (delegated by IEEE to work on the next update of the standard) approved so-called Draft 3.0 of VHDL-2006. While maintaining full compatibility with older versions, this proposed standard provides numerous extensions that make writing and managing VHDL code easier. Key changes include incorporation of child standards (1164, 1076.2, 1076.3) into the main 1076 standard, an extended set of operators, more flexible syntax of case and generate statements, incorporation of VHPI (VHDL Procedural Interface) (interface to C/C++ languages) and a subset of PSL (Property Specification Language). These changes should improve quality of synthesizable VHDL code, make testbenches more flexible, and allow wider use of VHDL for system-level descriptions.
In February 2008, Accellera approved VHDL 4.0, also informally known as VHDL 2008, which addressed more than 90 issues discovered during the trial period for version 3.0 and includes enhanced generic types. In 2008, Accellera released VHDL 4.0 to the IEEE for balloting for inclusion in IEEE 1076–2008. The VHDL standard IEEE 1076-2008[5] was published in January 2009.
Standardization
[edit]The IEEE Standard 1076 defines the VHSIC Hardware Description Language, or VHDL. It was originally developed under contract F33615-83-C-1003 from the United States Air Force awarded in 1983 to a team of Intermetrics, Inc. as language experts and prime contractor, Texas Instruments as chip design experts and IBM as computer-system design experts. The language has undergone numerous revisions and has a variety of sub-standards associated with it that augment or extend it in important ways.
IEEE Standard 1076 was and continues to be a milestone in the design of electronic systems.[6]
Revisions
[edit]- IEEE 1076–1987[3] First standardized revision of ver 7.2 of the language from the United States Air Force.
- IEEE 1076–1993[7] (also published with ISBN 1-55937-376-8). Significant improvements resulting from several years of feedback. Probably the most widely used version with the greatest vendor tool support.
- IEEE 1076–2000.[8] Minor revision. Introduces the use of protected types.
- IEEE 1076–2002.[9] Minor revision of 1076–2000. Rules with regard to buffer ports are relaxed.
- IEC 61691-1-1:2004.[10] IEC adoption of IEEE 1076–2002.
- IEEE 1076c–2007.[11] Introduced VHPI, the VHDL procedural interface, which provides software with the means to access the VHDL model. The VHDL language required minor modifications to accommodate the VHPI.
- IEEE 1076–2008 (previously referred to as 1076–200x). Major revision released on 2009-01-26. Among other changes, this standard incorporates a basic subset of PSL, allows for generics on packages and subprograms and introduces the use of external names.
- IEC 61691-1-1:2011.[12] IEC adoption of IEEE 1076–2008.
- IEEE 1076–2019. Major revision.
Related standards
[edit]- IEEE 1076.1 VHDL Analog and Mixed-Signal (VHDL-AMS)
- IEEE 1076.1.1 VHDL-AMS Standard Packages (stdpkgs)
- IEEE 1076.2 VHDL Math Package
- IEEE 1076.3 VHDL Synthesis Package (vhdlsynth) (numeric std)
- IEEE 1076.3 VHDL Synthesis Package – Floating Point (fphdl)
- IEEE 1076.4 Timing (VHDL Initiative Towards ASIC Libraries: VITAL)
- IEEE 1076.6 VHDL Synthesis Interoperability (withdrawn in 2010)[13]
- IEEE 1164 VHDL Multivalue Logic (std_logic_1164) Packages
Design
[edit]VHDL is generally used to write text models that describe a logic circuit. Such a model is processed by a synthesis program, only if it is part of the logic design. A simulation program is used to test the logic design using simulation models to represent the logic circuits that interface to the design. This collection of simulation models is commonly called a testbench.
A VHDL simulator is typically an event-driven simulator.[14] This means that each transaction is added to an event queue for a specific scheduled time. For example, if a signal assignment should occur after 1 nanosecond, the event is added to the queue for time +1ns. Zero delay is also allowed, but still needs to be scheduled: for these cases delta delay is used, which represent an infinitely small time step. The simulation alters between two modes: statement execution, where triggered statements are evaluated, and event processing, where events in the queue are processed.
VHDL has constructs to handle the parallelism inherent in hardware designs, but these constructs (processes) differ in syntax from the parallel constructs in Ada (tasks). Like Ada, VHDL is strongly typed and is not case sensitive. In order to directly represent operations which are common in hardware, there are many features of VHDL which are not found in Ada, such as an extended set of Boolean operators including nand and nor.
VHDL has file input and output capabilities, and can be used as a general-purpose language for text processing, but files are more commonly used by a simulation testbench for stimulus or verification data. There are some VHDL compilers which build executable binaries. In this case, it might be possible to use VHDL to write a testbench to verify the functionality of the design using files on the host computer to define stimuli, to interact with the user, and to compare results with those expected. However, most designers leave this job to the simulator.
It is relatively easy for an inexperienced developer to produce code that simulates successfully but that cannot be synthesized into a real device, or is too large to be practical. One particular pitfall is the accidental production of transparent latches rather than D-type flip-flops as storage elements.[15]
One can design hardware in a VHDL IDE (for FPGA implementation such as Xilinx ISE, Altera Quartus, Synopsys Synplify, or Mentor Graphics HDL Designer) to produce the RTL schematic of the desired circuit. After that, the generated schematic can be verified using simulation software which shows the waveforms of inputs and outputs of the circuit after generating the appropriate testbench. To generate an appropriate testbench for a particular circuit or VHDL code, the inputs have to be defined correctly. For example, for clock input, a loop process or an iterative statement is required.[16]
It is important to note that when a VHDL model is translated into the "gates and wires" that are mapped onto a programmable logic device such as a CPLD or FPGA, then it is the actual hardware being configured, rather than the VHDL code being "executed" as if on some form of a processor chip.
Advantages
[edit]The key advantage of VHDL, when used for systems design, is that it allows the behavior of the required system to be described (modeled) and verified (simulated) before synthesis tools translate the design into real hardware (gates and wires).
Another benefit is that VHDL allows the description of a concurrent system. VHDL is a dataflow language in which every statement is considered for execution simultaneously, unlike procedural computing languages such as BASIC, C, and assembly language, where a sequence of statements is run sequentially one instruction at a time.
A VHDL project is multipurpose. Being created once, a calculation block can be used in many other projects. However, many formational and functional block parameters can be tuned (capacity parameters, memory size, element base, block composition and interconnection structure).
A VHDL project is portable. Being created for one element base, a computing device project can be ported on another element base; for example, VLSI with various technologies.
A big advantage of VHDL compared to original Verilog is that VHDL has a full type system. Designers can use the type system to write much more structured code (especially by declaring record types).[17]
Design examples
[edit]This section contains instructions or advice. (January 2013) |
In VHDL, a design consists at a minimum of an entity which describes the interface and an architecture which contains the actual implementation. In addition, most designs import library modules. Some designs also contain multiple architectures and configurations.
A simple AND gate in VHDL would look something like:
-- (this is a VHDL comment)
/*
this is a block comment (VHDL-2008)
*/
-- import std_logic from the IEEE library
library IEEE;
use IEEE.std_logic_1164.all;
-- this is the entity
entity ANDGATE is
port (
I1 : in std_logic;
I2 : in std_logic;
O : out std_logic);
end entity ANDGATE;
-- this is the architecture
architecture RTL of ANDGATE is
begin
O <= I1 and I2;
end architecture RTL;
(Notice that RTL stands for Register transfer level design.) While the example above may seem verbose to HDL beginners, many parts are either optional or need to be written only once. Generally, simple functions like this are part of a larger behavioral module, instead of having a separate module for something so simple. In addition, use of elements such as the std_logic type might at first seem to be an overkill. One could easily use the built-in bit type and avoid the library import in the beginning. However, using a form of many-valued logic, specifically 9-valued logic (U,X,0,1,Z,W,H,L,-), instead of simple bits (0,1) offers a very powerful simulation and debugging tool to the designer which currently does not exist in any other HDL.
In the examples that follow, one will see that VHDL code can be written in a very compact form. However, more experienced designers usually avoid these compact forms and use a more verbose coding style for the sake of readability and maintainability.
Synthesizable constructs and VHDL templates
[edit]VHDL is frequently used for two different goals: simulation of electronic designs and synthesis of such designs. Synthesis is a process where a VHDL is compiled and mapped into an implementation technology such as an FPGA or an ASIC.
Not all constructs in VHDL are suitable for synthesis. For example, most constructs that explicitly deal with timing such as wait for 10 ns; are not synthesizable despite being valid for simulation. While different synthesis tools have different capabilities, there exists a common synthesizable subset of VHDL that defines what language constructs and idioms map into common hardware for many synthesis tools. IEEE 1076.6 defines a subset of the language that is considered the official synthesis subset. It is generally considered a "best practice" to write very idiomatic code for synthesis as results can be incorrect or suboptimal for non-standard constructs.
MUX template
[edit]The multiplexer, or 'MUX' as it is usually called, is a simple construct very common in hardware design. The example below demonstrates a simple two to one MUX, with inputs A and B, selector S and output X. Note that there are many other ways to express the same MUX in VHDL.[18]
X <= A when S = '1' else B;
A more complex example of a MUX with 4×3 inputs and a 2-bit selector:
library IEEE;
use IEEE.std_logic_1164.all;
entity mux4 is
port(
a1 : in std_logic_vector(2 downto 0);
a2 : in std_logic_vector(2 downto 0);
a3 : in std_logic_vector(2 downto 0);
a4 : in std_logic_vector(2 downto 0);
sel : in std_logic_vector(1 downto 0);
b : out std_logic_vector(2 downto 0)
);
end mux4;
architecture rtl of mux4 is
-- declarative part: empty
begin
p_mux : process(a1,a2,a3,a4,sel)
begin
case sel is
when "00" => b <= a1 ;
when "01" => b <= a2 ;
when "10" => b <= a3 ;
when others => b <= a4 ;
end case;
end process p_mux;
end rtl;
Latch template
[edit]A transparent latch is basically one bit of memory which is updated when an enable signal is raised. Again, there are many other ways this can be expressed in VHDL.
-- latch template 1:
Q <= D when Enable = '1' else Q;
-- latch template 2:
process(all)
begin
Q <= D when(Enable);
end process;
D-type flip-flops
[edit]The D-type flip-flop samples an incoming signal at the rising (or falling) edge of a clock. This example has an asynchronous, active-high reset, and samples at the rising clock edge.
DFF : process(all) is
begin
if RST then
Q <= '0';
elsif rising_edge(CLK) then
Q <= D;
end if;
end process DFF;
Another common way to write edge-triggered behavior in VHDL is with the 'event' signal attribute. A single apostrophe has to be written between the signal name and the name of the attribute.
DFF : process(RST, CLK) is
begin
if RST then
Q <= '0';
elsif CLK'event and CLK = '1' then
Q <= D;
end if;
end process DFF;
VHDL also lends itself to "one-liners" such as:
DFF : Q <= '0' when RST = '1' else D when rising_edge(clk);
or:
DFF : process(all) is
begin
if rising_edge(CLK) then
Q <= D;
end if;
if RST then
Q <= '0';
end if;
end process DFF;
or:
Library IEEE;
USE IEEE.Std_logic_1164.all;
entity RisingEdge_DFlipFlop_SyncReset is
port(
Q : out std_logic;
Clk : in std_logic;
sync_reset : in std_logic;
D : in std_logic
);
end RisingEdge_DFlipFlop_SyncReset;
architecture Behavioral of RisingEdge_DFlipFlop_SyncReset is
begin
process(Clk)
begin
if (rising_edge(Clk)) then
if (sync_reset='1') then
Q <= '0';
else
Q <= D;
end if;
end if;
end process;
end Behavioral;
Which can be useful if not all signals (registers) driven by this process should be reset.
Example: a counter
[edit]The following example is an up-counter with asynchronous reset, parallel load and configurable width. It demonstrates the use of the 'unsigned' type, type conversions between 'unsigned' and 'std_logic_vector' and VHDL generics. The generics are very close to arguments or templates in other traditional programming languages like C++. The example is in VHDL 2008 language.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all; -- for the unsigned type
entity COUNTER is
generic (
WIDTH : in natural := 32);
port (
RST : in std_logic;
CLK : in std_logic;
LOAD : in std_logic;
DATA : in std_logic_vector(WIDTH-1 downto 0);
Q : out std_logic_vector(WIDTH-1 downto 0));
end entity COUNTER;
architecture RTL of COUNTER is
begin
process(all) is
begin
if RST then
Q <= (others => '0');
elsif rising_edge(CLK) then
if LOAD='1' then
Q <= DATA;
else
Q <= std_logic_vector(unsigned(Q) + 1);
end if;
end if;
end process;
end architecture RTL;
More complex counters may add if/then/else statements within the rising_edge(CLK) elsif to add other functions, such as count enables, stopping or rolling over at some count value, and generating output signals like terminal count signals. Care must be taken with the ordering and nesting of such controls if used together, in order to produce the desired priorities and minimize the number of logic levels needed.
Simulation-only constructs
[edit]A large subset of VHDL cannot be translated into hardware. This subset is known as the non-synthesizable or the simulation-only subset of VHDL and can only be used for prototyping, simulation and debugging. For example, the following code will generate a clock with a frequency of 50 MHz. It can, for example, be used to drive a clock input in a design during simulation. It is, however, a simulation-only construct and cannot be implemented in hardware. In actual hardware, the clock is generated externally; it can be scaled down internally by user logic or dedicated hardware.
process
begin
CLK <= '1'; wait for 10 NS;
CLK <= '0'; wait for 10 NS;
end process;
The simulation-only constructs can be used to build complex waveforms in a very short time. Such waveforms can be used, for example, as test vectors for a complex design or as a prototype of some synthesizer logic that will be implemented in the future.
process
begin
wait until START = '1'; -- wait until START is high
for i in 1 to 10 loop -- then wait for a few clock periods...
wait until rising_edge(CLK);
end loop;
for i in 1 to 10 loop -- write numbers 1 to 10 to DATA, 1 every cycle
DATA <= to_unsigned(i, 8);
wait until rising_edge(CLK);
end loop;
-- wait until the output changes
wait on RESULT;
-- now raise ACK for clock period
ACK <= '1';
wait until rising_edge(CLK);
ACK <= '0';
-- and so on...
end process;
VHDL-2008 Features
[edit]Hierarchical Aliases
[edit]library ieee;
use ieee.std_logic_1164.all;
entity bfm is end entity;
architecture beh of bfm is
signal en :std_logic;
begin
-- insert implementation here
end architecture;
//------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity test1 is end entity;
architecture beh of test1 is
begin
ibfm: entity work.bfm;
-- The testbench process
process
alias probe_en is <<signal .test1.ibfm.en :std_logic>>;
begin
probe_en <= '1';
wait for 100 ns;
probe_en <= '0';
wait for 100 ns;
probe_en <= '1';
wait for 100 ns;
std.env.stop(0);
end process;
end architecture;
Standard libraries
[edit]Also referred as standard packages.
IEEE Standard Package
[edit]The IEEE Standard Package includes the following:[19]
- numeric_std
- std_logic_1164
- std_logic_arith
- std_logic_unsigned
- std_logic_signed
- std_logic_misc
VHDL simulators
[edit]Commercial:
- Aldec Active-HDL
- Cadence Incisive
- Mentor Graphics ModelSim
- Mentor Graphics Questa Advanced Simulator
- Synopsys VCS-MX[20]
- Xilinx Vivado Design Suite (features the Vivado Simulator)
Other:
- EDA Playground is a free web-based VHDL IDE (uses Synopsys VCS, Cadence Incisive, Aldec Riviera-PRO and GHDL for VHDL simulation)
- GHDL is an open source[21] VHDL compiler that can execute VHDL programs. (GHDL on GitHub)
- boot by freerangefactory.org is a VHDL compiler and simulator based on GHDL and GTKWave.
- Simili by Symphony EDA is a free commercial VHDL simulator at the Wayback Machine (archived 2007-10-02)
- nvc by Nick Gasson is an open source VHDL compiler and simulator.[22][23]
- freehdl by Edwin Naroska was an open source VHDL simulator, abandoned since 2001.[24]
See also
[edit]- Altera Hardware Description Language (AHDL)
- Chisel
- Gezel
- numeric std, a standard package which provides arithmetic functions for vectors
- SystemC
- SystemVerilog
- Verilog
- List of HDL simulators
References
[edit]- ^ David R. Coelho (30 June 1989). The VHDL Handbook. Springer Science & Business Media. ISBN 978-0-7923-9031-2.
- ^ Department of Defense (1992). Military Standard, Standard general requirements for electronic equipment. Retrieved November 15, 2017.
- ^ a b 1076-1987 – IEEE Standard VHDL Language Reference Manual. 1988. doi:10.1109/IEEESTD.1988.122645. ISBN 0-7381-4324-3.
- ^ "VHDL - VITAL". www.vhdl.renerta.com. Archived from the original on 2011-10-22.
- ^ 1076-2008 – IEEE Standard VHDL Language Reference Manual. 2009. doi:10.1109/IEEESTD.2009.4772740. ISBN 978-0-7381-6854-8.
- ^ IEEE P1076 Working Group VHDL Analysis and Standardization Group (VASG)
- ^ 1076-1993 – IEEE Standard VHDL Language Reference Manual. 1994. doi:10.1109/IEEESTD.1994.121433. ISBN 0-7381-0986-X.
- ^ 1076-2000 – IEEE Standard VHDL Language Reference Manual. 2000. doi:10.1109/IEEESTD.2000.92297. ISBN 0-7381-1948-2.
- ^ 1076-2002 – IEEE Standard VHDL Language Reference Manual. 2002. doi:10.1109/IEEESTD.2002.93614. ISBN 0-7381-3247-0.
- ^ IEC 61691-1-1 First edition 2004-10; IEEE 1076 — IEC/IEEE Behavioural Languages – Part 1-1: VHDL Language Reference Manual (Adoption of IEEE Std 1076-2002). 2004. doi:10.1109/IEEESTD.2004.95752. ISBN 2-8318-7691-5.
- ^ 1076c-2007 – IEEE Standard VHDL Language Reference Manual Amendment 1: Procedural Language Application Interface. 2007. doi:10.1109/IEEESTD.2007.4299594. ISBN 978-0-7381-5523-4.
- ^ 61691-1-1-2011 — Behavioural languages – Part 1-1: VHDL Language Reference Manual. 2011. doi:10.1109/IEEESTD.2011.5967868. ISBN 978-0-7381-6605-6.
- ^ "IEEE 1076.6-2004 - IEEE Standard for VHDL Register Transfer Level (RTL) Synthesis".
- ^ "ELEC3017 - Simulation" (PDF). University of Southampton. Archived (PDF) from the original on 2017-02-23. Retrieved 23 February 2017.
- ^ "Why should I care about Transparent Latches?". Doulos. Archived from the original on 20 January 2013. Retrieved 22 December 2012.
- ^ "Clock Generation - VHDL Designers Guide". Doulos. Archived from the original on 20 January 2013. Retrieved 22 December 2012.
- ^ Jiri Gaisler. "A structured VHDL Design Method" (PDF). Archived (PDF) from the original on 2022-10-10. Retrieved 15 November 2017.
- ^ "VHDL Logical Operators and Signal Assignments for Combinatorial Logic". FPGAtutorial. 16 May 2020. Retrieved 2020-08-23.
- ^ Chiusano, Silvia (April 5, 2011). "VHDL Data types and Operators available in the IEEE Standard Packages" (PDF). Polytechnic University of Turin. Archived (PDF) from the original on 2022-10-10.
- ^ "VCS: Industry's Highest Performance Simulation Solution". synopsis.com.
- ^ "Copyrights | Licenses". GHDL Documentation -- GHDL 0.36-dev documentation. readthedocs.io.[dead link]
- ^ Gasson, Nick (November 5, 2011). "Writing a VHDL compiler".
- ^ Gasson, Nick (July 22, 2023). "NVC - VHDL Compiler and Simulator". Retrieved July 23, 2023.
- ^ "freehdl: By Thread". Archived from the original on February 10, 2002.
- Notes
- 1076/INT-1991 – IEEE Standards Interpretations: IEEE Std 1076-1987, IEEE Standard VHDL Language Reference Manual. 1992. doi:10.1109/IEEESTD.1992.101084. ISBN 0-7381-0987-8.
Further reading
[edit]- Ashenden, Peter J. (2008). The Designer's Guide to VHDL, Third Edition (Systems on Silicon). ISBN 978-0-1208-8785-9. (The VHDL reference book written by one of the lead developers of the language)
- Bryan Mealy, Fabrizio Tappero (February 2012). [1]. The no-frills guide to writing powerful VHDL code for your digital implementations. Archived from the original Free Range VHDL on 2015-02-13.
- Johan Sandstrom (October 1995). "Comparing Verilog to VHDL Syntactically and Semantically". Integrated System Design. EE Times. — Sandstrom presents a table relating VHDL constructs to Verilog constructs.
- Qualis Design Corporation (2000-07-20). "VHDL quick reference card" (PDF). 1.1. Qualis Design Corporation. Archived from the original (PDF) on 2003-12-10.
- Qualis Design Corporation (2000-07-20). "1164 packages quick reference card" (PDF). 1.0. Qualis Design Corporation. Archived from the original (PDF) on 2016-03-14.
- Janick Bergeron, "Writing Testbenches: Functional Verification of HDL Models", 2000, ISBN 0-7923-7766-4. (The HDL Testbench Bible)
- Krolikoski, S.J. (May 1995). "Standardizing ASIC libraries in VHDL using VITAL: A tutorial". Proceedings of the IEEE 1995 Custom Integrated Circuits Conference. pp. 603–610. doi:10.1109/CICC.1995.518256. ISBN 0-7803-2584-2.
- Vreeland, Russell E. "Connecting the System to the Chip: Using VHDL/VITAL for Board-level Simulation" (PDF). Retrieved 12 May 2025.
- Rushton, Andrew (2011). VHDL for logic synthesis (3rd ed.). Chichester, West Sussex, U.K: Wiley. p. 4. ISBN 9780470977972.
- Vreeland, Russell E. "Board-level component modeling using VITAL". Retrieved 12 May 2025.
- Tuzov, Ilya; Ruiz, Juan-Carlos; de Andrés, David (September 2017). "Accurately Simulating the Effects of Faults in VHDL Models Described at the Implementation-Level". 2017 13th European Dependable Computing Conference (EDCC). Institute of Electrical and Electronics Engineers. pp. 10–17. doi:10.1109/EDCC.2017.26. ISBN 978-1-5386-0602-5.
External links
[edit]Overview
Definition and Purpose
VHDL, an acronym for VHSIC Hardware Description Language where VHSIC stands for Very High Speed Integrated Circuit, is a standardized hardware description language designed for modeling and simulating the behavior and structure of digital hardware systems.[6][7] Originating from the U.S. Department of Defense's Very High Speed Integrated Circuit (VHSIC) program initiated in March 1980, VHDL was created to meet the need for a reliable, standardized method to document and design complex high-speed digital circuits, particularly for military applications.[8][7] The primary purpose of VHDL is to enable the description of electronic systems at multiple levels of abstraction, ranging from gate-level implementations to high-level behavioral models and system-level architectures, facilitating both simulation for verification and synthesis for implementation on field-programmable gate arrays (FPGAs) or application-specific integrated circuits (ASICs).[9][10] Among these abstraction levels, behavioral modeling describes functionality without hardware details, structural modeling interconnects components, and register-transfer level (RTL) modeling—emphasized for synthesis—specifies data flow between registers and operations, bridging simulation and hardware realization.[9] VHDL serves as one of the two dominant hardware description languages, alongside Verilog, for digital system design and verification.[11]Key Concepts
VHDL is fundamentally a hardware description language that emphasizes concurrency to model the parallel nature of digital hardware. Unlike sequential programming languages, which execute instructions one at a time, VHDL employs concurrent statements that execute simultaneously, reflecting the inherent parallelism in hardware circuits where multiple operations occur independently.[12] This approach allows designers to describe complex systems where signals propagate and logic gates operate in parallel without predefined execution order.[13] Time modeling in VHDL provides explicit control over simulation timing, essential for representing real-world hardware behaviors such as propagation delays and clock cycles. Through mechanisms like delay specifications and wait statements, VHDL simulates the passage of time in an event-driven manner, enabling accurate verification of timing-dependent designs.[12] Delays can be inertial or transport-based to mimic signal settling times, while wait statements suspend process execution until specific conditions or durations are met, distinguishing VHDL's temporal modeling from the instantaneous execution typical in software.[13] The language supports hierarchical design through entities and architectures, promoting modularity and reusability in large-scale systems. An entity defines the external interface of a component, while one or more architectures describe its internal behavior or structure, allowing designs to be composed from interconnected subcomponents at various abstraction levels.[12] This hierarchical structure facilitates top-down or bottom-up design methodologies, encapsulating complexity and enabling efficient management of digital systems.[13] As a strongly typed language, VHDL requires all signals, variables, and constants to be explicitly declared with precise types, preventing type mismatches and enhancing design reliability. This strict typing system, including built-in and user-defined types, ensures that operations are only performed on compatible data, catching errors early during compilation rather than at runtime.[13] In contrast to software languages that focus on algorithmic flow, VHDL describes hardware behavior—what occurs simultaneously across components—prioritizing structural and temporal aspects over sequential control.[12]History
Origins and Development
VHDL, or VHSIC Hardware Description Language, emerged from the U.S. Department of Defense's (DoD) Very High Speed Integrated Circuit (VHSIC) program, initiated in 1980 to tackle escalating challenges in hardware design amid the rise of very large-scale integration (VLSI) technologies. The program's primary motivations were to shorten design cycles for complex digital systems, foster interoperability among diverse hardware design and simulation tools from multiple vendors, and supplant fragmented, proprietary methods like schematic capture and custom simulators that hindered efficient collaboration and reuse in military applications. By standardizing a single, non-proprietary language, the DoD aimed to streamline documentation, simulation, and synthesis processes, ultimately reducing costs and accelerating the integration of advanced circuits into defense systems.[14][15] Development of VHDL began in earnest in 1983, when the DoD awarded a contract to a consortium comprising Intermetrics, Inc., IBM, and Texas Instruments to create the baseline language specification. Intermetrics led the effort, drawing syntactic inspiration from the Ada programming language to ensure readability and robustness suitable for safety-critical hardware descriptions. Over the next two years, the team iterated through multiple drafts, incorporating feedback from VHSIC phase contractors to balance expressiveness for behavioral modeling with support for structural and register-transfer level designs. This collaborative approach addressed the growing complexity of VLSI, where traditional tools struggled with portability and verification across heterogeneous environments.[15][16][17] The first complete draft, version 7.2, was released in August 1985 for public review, marking a pivotal milestone that invited broader input to refine the language before standardization. In 1986, the DoD placed VHDL into the public domain to encourage widespread adoption beyond military confines, eliminating proprietary barriers and promoting tool development by commercial vendors. Early adoption faced hurdles due to the scarcity of mature simulators and synthesizers, as the ecosystem of supporting software was nascent and required significant investment in validation and training. Nonetheless, VHDL quickly gained footing in military and aerospace sectors, where its rigor aligned with stringent reliability needs, enabling reusable design libraries and improved system-level verification in projects like avionics and radar systems.[15][18][19]Standardization Process
The standardization of VHDL was managed by the IEEE Computer Society's Design Automation Standards Committee (DASC), which established the VHDL Analysis and Standardization Group (VASG) as the primary working group responsible for refining and formalizing the language.[20] This effort built upon the initial language developed under the U.S. Department of Defense's Very High Speed Integrated Circuit (VHSIC) program, transitioning it from a proprietary tool to an open industry standard.[21] The standardization process followed IEEE's consensus-based procedures, including iterative development by the VASG, public review periods for soliciting feedback from industry and academia, and formal balloting among qualified IEEE members to resolve issues and achieve approval.[22] Key objectives included aligning the language with DoD requirements for hardware description, emphasizing portability to enable designs to be simulated and implemented across diverse electronic design automation (EDA) tools without vendor-specific dependencies.[23] The process culminated in the ratification of IEEE Std 1076-1987 by the IEEE Standards Board in December 1987, which defined the core syntax, semantics, and constructs of VHDL primarily for modeling and simulating digital logic systems. The initial scope of IEEE Std 1076-1987 focused on behavioral and structural description for simulation purposes, laying the foundation for later extensions that supported synthesis and higher-level modeling.[24] By establishing a vendor-neutral specification, the standard facilitated the proliferation of compatible VHDL tools and libraries, driving industry-wide adoption and innovation in EDA software during the 1990s.[25]Language Fundamentals
Syntax and Structure
VHDL code is organized into a hierarchical structure of design units, primarily libraries, packages, entities, and architectures, which collectively form the foundation for describing hardware systems. Libraries serve as repositories for compiled design units, enabling reuse across projects, while packages encapsulate declarations such as types, subtypes, constants, and subprograms that can be shared among multiple design units. Entities define the interface of a hardware component through ports and generics, and architectures provide the internal description of the entity's behavior or structure.[26] The language employs a set of reserved keywords, including 'entity', 'architecture', and 'process', to denote specific constructs, and uses delimiters such as semicolons to terminate statements, colons for labels and type indications, and parentheses for grouping. These elements ensure precise parsing and unambiguous interpretation of the code during compilation and simulation. VHDL supports single-line comments initiated by two adjacent hyphens (--), which extend to the end of the line and may include any printable characters except certain format effectors like line feeds; multi-line comments are not defined in the language.[20][27] Processes, which model concurrent behavior, include sensitivity lists that enumerate signals whose events—such as value changes—trigger the process's sequential execution. This mechanism supports the inherent concurrency of hardware by suspending the process until relevant signal events occur. Configurations provide a means to select specific architectures for entities in a design hierarchy, allowing flexible instantiation without altering the source code.[26][27] Generics, declared in the entity interface via a generic clause, enable parameterization of designs by allowing constant values—such as bit widths or delay parameters—to be specified at instantiation time, promoting reusability and customization. VHDL is case insensitive with respect to identifiers and keywords, treating uppercase and lowercase variants as equivalent, though established conventions recommend lowercase for keywords and uppercase for user-defined identifiers to enhance readability.[26][27]Data Types and Objects
VHDL employs a strongly typed system, where every constant, signal, variable, and other object must be declared with an explicit type, ensuring type safety and facilitating simulation and synthesis. The language defines scalar types for single values, composite types for structured data, and various object classes to hold values of these types. Access types and file types provide additional capabilities for dynamic allocation and input/output operations, respectively, though they are infrequently used in synthesizable hardware descriptions. Subtypes allow for constrained views of base types, promoting reusability and error prevention. Scalar types in VHDL represent individual values and form the foundation for more complex structures. The standard package (IEEE Std 1076) predefines several scalar types, including bit, an enumerated type with literals '0' and '1' suitable for simple binary modeling.[28] The boolean type supports logical values false and true, often used in conditional statements. Integer is a signed integer type with an implementation-defined range that must include at least -263 to 263-1 in VHDL-2019, ideal for counters and indices.[26] Real provides floating-point representation for non-integer arithmetic, though its use is limited in digital hardware due to synthesis challenges. For multi-value logic essential in digital design, the IEEE Std 1164 package introduces std_logic, an enumerated type with nine values: 'U' (uninitialized), 'X' (unknown), '0', '1', 'Z' (high impedance), 'W' (weak unknown), 'L' (weak low), 'H' (weak high), and '-' (don't care); this type models realistic signal behaviors like contention and tri-state logic.[29] Unlike the two-valued bit, std_logic is a resolved type, meaning multiple drivers on a signal are reconciled via a resolution function.[29] Composite types aggregate multiple elements into a single value, enabling representation of buses, memories, and structured data. Arrays are collections of elements of the same type, declared as either unconstrained (no fixed bounds, e.g.,type bit_array is array (natural range <>) of bit;) or constrained (specific bounds, e.g., subtype word is bit_vector(31 downto 0);).[20] The std_logic_vector, defined in IEEE Std 1164 as array (natural range <>) of std_logic, is widely used for modeling multi-bit signals like data buses.[29] Records, in contrast, group elements of potentially different types into a named structure, similar to C structs; for example:
type bus_record is
record
address : std_logic_vector(7 downto 0);
data : std_logic_vector(15 downto 0);
valid : boolean;
end record;
type bus_record is
record
address : std_logic_vector(7 downto 0);
data : std_logic_vector(15 downto 0);
valid : boolean;
end record;
signal_bus.address).[20] Both array and record types support multidimensional arrays and nested composites for complex hierarchies.
Objects in VHDL are named entities that store values of declared types and belong to one of four classes: constants (immutable after initialization), signals (for inter-component communication), variables (for local storage), or files (for I/O). Signals model wires or nets in hardware, supporting concurrent assignments across design units; updates to signals occur after a simulation delta cycle, introducing implicit delays that prevent race conditions in concurrent execution.[20] For example, signal clk : std_logic; declares a clock signal. Variables, declared within processes or subprograms, update immediately upon assignment and are used for sequential algorithm modeling, akin to software variables.[20] Access types enable pointer-like indirection to dynamically allocated objects, declared as type ptr is access some_type;, supporting linked lists or trees but rarely synthesized due to hardware mapping difficulties.[26] File types, via the TEXTIO package, handle reading/writing to external files during simulation, e.g., file output_file : text;, though they are non-synthesizable.
Type resolution addresses scenarios with multiple drivers, such as resolved signals like std_logic; the resolution function, predefined in IEEE Std 1164, uses a truth table to compute the effective value (e.g., conflicting '0' and '1' resolve to 'X').[29] Unresolved types like std_ulogic require explicit handling to avoid errors. Subtypes impose constraints on base types for validation, such as subtype natural is [integer](/page/Integer) range 0 to integer'high;, which restricts values to non-negative integers and inherits the base type's operations.[30] This mechanism enhances design clarity without altering the underlying type semantics.
Modeling and Design
Entities and Architectures
In VHDL, the fundamental unit of design is the entity, which serves as the external interface specification for a hardware module. An entity declaration defines the name of the design unit and its ports, which represent the input, output, and bidirectional connections to the external environment. Ports are declared with modes such asin for inputs, out for outputs, and inout for bidirectional signals, and they can utilize various data types like std_logic or std_logic_vector to model electrical characteristics more accurately than binary types.[31][32] Additionally, entities may include generics, which are constant parameters that enable parameterization without altering the core structure, such as specifying vector widths or delays; generics are declared before ports and can have default values that are overridden during instantiation.[33][2]
The architecture body provides the internal description of the entity's behavior or structure, associated with a specific entity via its name. It consists of two main parts: the declarative part, where internal signals, constants, components, and subprograms are defined, and the statement part, which contains the concurrent or sequential statements implementing the design logic. This separation allows for clear organization, with the declarative part preceding the begin keyword and the statement part following until end architecture. Architectures support hierarchical designs by permitting component instantiations within them.[31][2][32]
Port mapping is essential for instantiating components within an architecture, connecting the entity's internal signals or other components to the ports of the instantiated unit. This is achieved through the port map clause in a component instantiation statement, which supports both positional and named associations to explicitly link actual signals to formal ports, ensuring correct interfacing in hierarchical designs. For generics, a corresponding generic map clause allows passing specific values to the component's parameters during instantiation.[31][33][2]
VHDL facilitates structural modeling in architectures by interconnecting multiple entity-architecture pairs, akin to schematic capture, where components are declared and instantiated to form larger systems. This approach promotes modularity and reuse, as predefined or user-defined entities can be composed like building blocks, with signals routing data between them. In contrast, behavioral modeling abstracts the internals using high-level concurrent statements or processes to describe functionality without specifying exact hardware implementation, focusing on algorithmic intent such as conditional logic or arithmetic operations. These modeling styles can be mixed within a single architecture for flexibility.[31][32][2]
A key feature of VHDL is the ability to define multiple architectures for the same entity, allowing different implementations—such as one for simulation with detailed timing and another for synthesis targeting specific hardware—while sharing the same interface. Selection among these architectures occurs via configuration declarations, enabling context-specific views without redesign. This supports design exploration and verification across phases.[31][2]
Processes and Concurrency
In VHDL, processes serve as the primary mechanism for describing sequential behavior within an architecture, consisting of a block of sequential statements that execute in order but operate concurrently with other processes and statements in the design.[4] A process is declared using theprocess keyword, optionally followed by a sensitivity list of signals that trigger its execution, and it ends with end [process](/page/Process).[4] For example, a simple process might be structured as process (clk, reset) begin if reset = '1' then ... end if; end [process](/page/Process);, where changes to clk or reset resume the process from its beginning.[34]
Concurrent statements, in contrast, execute simultaneously outside of processes and remain active throughout the simulation, modeling the inherent parallelism of hardware.[4] These include signal assignment statements, such as out_signal <= in1 and in2;, which continuously evaluate and update the target signal whenever inputs change, without needing explicit triggering.[4] Unlike processes, concurrent statements do not contain sequential control flow and are used to describe combinational logic or interconnections directly in the architecture body.[34]
Timing control within processes is achieved through wait statements, which suspend execution until a specified condition or duration is met, enabling modeling of clocked or timed behaviors.[4] The forms include wait on signal_list; to pause until events on listed signals, wait until boolean_expression; to wait for a condition like a clock edge (e.g., wait until clk = '1';), and wait for time_expression; for a fixed delay such as a timeout.[4] Processes using wait statements cannot have a sensitivity list, as the waits provide the triggering mechanism.[4]
VHDL distinguishes sequential execution within processes from overall concurrency by the update semantics of variables and signals: variables, declared locally in processes, update immediately upon assignment using the := operator, providing blocking behavior similar to software variables, while signals schedule updates using the <= operator, resulting in non-blocking behavior where the new value takes effect only after the process suspends or at the end of the simulation cycle.[4] This difference ensures that signal assignments propagate events to other concurrent elements without immediate feedback loops within the same process.[34] VHDL lacks explicit blocking or non-blocking keywords, unlike Verilog, relying instead on the inherent nature of variable and signal assignments.[4]
The VHDL simulation model resolves concurrent events through delta cycles, an infinitesimal time unit that advances without progressing the overall simulation time, allowing ordered evaluation of signal updates and process activations within the same timestamp.[35] During each delta cycle, the simulator updates projected signal values from assignments, propagates events to sensitive processes, and re-executes until no further changes occur, preventing races in concurrent descriptions like feedback loops.[35] For instance, in a design with mutual signal dependencies, multiple delta cycles may iterate at time t=0 to stabilize values before time advances.[34] This event-driven cycle repeats indefinitely, modeling hardware concurrency faithfully during simulation.[35]
Synthesis and Simulation
Synthesizable Elements
In VHDL, synthesizable elements refer to the subset of language constructs that can be directly translated into hardware structures such as gates, flip-flops, and multiplexers during the synthesis process, as defined in standards like IEEE 1076.6 for register-transfer level (RTL) synthesis. These elements enable the description of digital circuits at the behavioral and structural levels while ensuring predictable mapping to physical hardware by logic synthesis tools. Concurrent signal assignments outside of processes typically infer combinational logic, such as logic gates or arithmetic units, based on the operators and expressions used.[36] Supported operators in synthesizable VHDL include logical operators (and, or, nand, nor, xor, xnor, not), relational operators (=, /=, <, <=, >, >=), and arithmetic operators (+, -, *, /, abs, rem, mod), with restrictions on division, remainder, and modulus to cases where the right operand is a constant power of 2 to ensure efficient hardware implementation. Shift operators (sll, srl, sla, sra, rol, ror) are also supported for bit manipulation. VHDL-2008 extensions add matching relational operators (?=, ?/=, ?<, ?<=, ?>, ?>=) and functions like maximum and minimum, which are synthesizable when applied to appropriate types like std_logic_vector. These operators form the basis for inferring hardware components, such as adders from '+' or multiplexers from conditional expressions.[36] Conditional statements like if-then-else and case are key for synthesizing selection logic, such as multiplexers and decoders. An if-then-else statement infers a multiplexer when used in concurrent assignments or processes, provided all branches assign values to the target signal to avoid unintended latch inference; an else clause or complete condition coverage is required for full synthesizability. Similarly, case statements synthesize priority encoders or decoders but demand exhaustive coverage, including a "when others =>" clause, to ensure no undefined paths that could lead to latches instead of combinational logic. These constructs must be used within the static bounds of the language to guarantee hardware equivalence across tools.[36][37] Loops in synthesizable VHDL are limited to generate statements for hardware replication, such as creating bit-wide arrays of identical components like registers or adders. A for-generate statement with constant bounds unrolls into multiple instances of the enclosed architecture, inferring parallel hardware without runtime iteration; if-generate statements are supported only with static (compile-time constant) conditions. Unbounded or runtime-determined loops, such as while loops without fixed iterations, are not synthesizable as they cannot map to finite hardware.[36] Sequential logic is inferred from clocked processes, where the sensitivity list includes a clock signal and optionally resets. The rising_edge(clk) or falling_edge(clk) function within an if statement detects clock edges to trigger flip-flop inference for registered outputs; asynchronous resets are modeled outside the clock condition, while synchronous resets or enables are placed inside. Processes referenced from the concurrency model thus enable the creation of state elements like D flip-flops when assignments depend on clock events.[37][36] Synthesizable VHDL excludes certain features to maintain hardware fidelity, such as real (floating-point) types, which are permitted only in functions for constant computations but not for signals or variables in RTL code. Time types are similarly restricted, and constructs like wait statements with time expressions or after clauses are unsupported, as they imply simulation timing rather than structural hardware.[36]Simulation Constructs
VHDL provides several constructs dedicated to simulation and verification, enabling precise modeling of timing, event-driven behavior, and error checking without implications for hardware synthesis. These features support the creation of testbenches and detailed behavioral simulations, allowing designers to verify system functionality under various conditions. Unlike synthesizable code, these elements focus on temporal aspects and diagnostic capabilities inherent to the simulation kernel defined in IEEE Std 1076.[26] The after clause specifies explicit delays in signal assignments, crucial for timing simulations to model propagation and inertial delays. In a waveform element of a signal assignment statement, such assignal <= value after 5 ns;, the after clause schedules the value change at the specified time relative to the current simulation time. If omitted, an implicit after 0 ns is assumed, resulting in immediate scheduling. This mechanism relies on the simulator's time advancement and event scheduling, ensuring accurate representation of asynchronous behaviors during verification.[26][20]
Wait statements facilitate event-driven simulation by suspending process execution until specific conditions or events occur. The wait on variant suspends until an event on listed signals, such as wait on clk;, triggering resumption on any change to those signals. Wait until pauses until a boolean condition becomes true, often used for edge detection like wait until rising_edge(clk);. The wait for form suspends for a fixed time duration, e.g., wait for 10 ns;, modeling timeouts or delays in test scenarios. These statements, when combined in a process without a sensitivity list, enable flexible control flow in testbenches, aligning with VHDL's discrete event simulation model.[26][20]
Assertions offer a mechanism for runtime verification by checking conditions and reporting failures during simulation. The syntax is assert condition [report "message"] [severity level];, where the condition is a boolean expression evaluated at each assertion point. If false, the optional report string is output, and the severity (note, warning, error, or failure) determines simulator response, such as halting execution for severity failure. Concurrent and sequential forms exist, supporting both structural and behavioral checks in testbenches to detect protocol violations or logical errors early.[26][38]
Text I/O capabilities, provided by the TEXTIO package in the STD library, enable reading from and writing to files or the console for logging simulation results and stimulus generation. Procedures like write(file, value); output data in ASCII format, while read(file, value); parses input lines into variables, supporting types such as integers and bits. For example:
use std.textio.all;
...
write(output, "Time: " & time'image(now));
use std.textio.all;
...
write(output, "Time: " & time'image(now));
std_logic, the predefined function returns 'X' (unknown) for conflicting drives like '0' and '1', or prioritizes stronger values over weaker ones (e.g., '1' over 'Z'). These functions are invoked automatically each simulation cycle for active resolved signals, preventing undefined behavior in multi-driver scenarios and aiding fault simulation. Custom resolution functions can be defined for user types to simulate specific contention resolutions.[26][20]
Non-determinism in VHDL simulation arises primarily from initial values and potential race conditions, which must be managed to ensure reproducible verification. Signals initialize to the leftmost array value of their type, often 'U' (uninitialized) for std_logic, leading to indeterminate propagation if not explicitly driven. Race conditions occur in delta time cycles when multiple processes update signals in unspecified order, potentially causing order-dependent results; designers avoid them by using guarded assignments or single-driver signals. Shared variables, introduced in VHDL-1993, can introduce true non-determinism if accessed concurrently without synchronization, though they are rarely used in simulation due to this risk.[26][40]
Practical Examples
Combinational Logic Templates
Combinational logic templates in VHDL provide reusable patterns for designing stateless circuits that produce outputs based solely on current inputs, without memory elements. These templates leverage concurrent signal assignments or processes to model basic building blocks like gates, multiplexers, and arithmetic units, ensuring synthesizable descriptions that map directly to hardware logic. By using standard operators defined in IEEE Std 1076, developers can express functionality concisely while adhering to the language's semantics for combinational behavior.[27] Basic logic gates are implemented using concurrent assignments with predefined logical operators such asand, or, and not, which operate on std_logic types from the IEEE Std_Logic_1164 package. For instance, a two-input AND gate assigns the output as the logical AND of its inputs: out1 <= in1 and in2;. Similarly, OR and NOT gates use or and not operators in concurrent statements outside any process, directly inferring gate-level hardware during synthesis. These operators follow the resolution functions of std_logic to handle multi-driver scenarios, ensuring robust combinational logic.[27][41]
Multiplexers (MUXes) select one input from multiple sources based on a select signal, commonly modeled in an entity with inputs, a select port, and an output. In the architecture, behavioral styles use conditional statements within a process for selection logic. For a 2:1 MUX, an if-else structure or case statement routes either input to the output based on the select bit, as shown in the following behavioral example:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mux_2to1 is
port (
a, b : in STD_LOGIC;
sel : in STD_LOGIC;
y : out STD_LOGIC
);
end mux_2to1;
architecture Behavioral of mux_2to1 is
begin
process(a, b, sel)
begin
if sel = '1' then
y <= b;
else
y <= a;
end if;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity mux_2to1 is
port (
a, b : in STD_LOGIC;
sel : in STD_LOGIC;
y : out STD_LOGIC
);
end mux_2to1;
architecture Behavioral of mux_2to1 is
begin
process(a, b, sel)
begin
if sel = '1' then
y <= b;
else
y <= a;
end if;
end process;
end Behavioral;
std_logic_vector for multi-bit inputs and select lines, with case statements handling multiple selections.[42][43]
Arithmetic units like adders utilize the overloaded + operator provided by the IEEE.numeric_std package on types such as unsigned or signed (which are compatible with std_logic_vector), performing bit-wise addition with implicit carry propagation in a ripple-carry fashion (or optimized by the synthesizer). A simple n-bit adder requires importing library ieee; use ieee.numeric_std.all;, declares two input vectors as unsigned, and a sum output of the same width, with the architecture assigning sum <= input1 + input2;. For a full adder handling carry-in in an n-bit context, the entity includes n-bit vector inputs, a 1-bit carry-in port (cin : in std_logic), and an (n+1)-bit result output. The assignment involves resizing for compatibility, such as result <= resize(unsigned(input1), n+1) + resize(unsigned(input2), n+1) + to_unsigned(cin, n+1);, where the lower n bits of result form the n-bit sum and the most significant bit is the carry-out. This approach synthesizes to efficient adder hardware without explicit gate-level descriptions.[27][44]
Encoders and decoders manipulate bit patterns for address or priority encoding, often using loops or case statements for scalability. A priority encoder, such as a 4-to-2 version, converts active input bits to a binary code prioritizing the highest active input via nested if-else in a process: the output code reflects the position of the highest '1' input, with an additional valid output signaling activity. Conversely, a 2-to-4 decoder generates one-hot outputs from a binary input using a case statement to activate the corresponding line. These structures employ std_logic_vector for input and output ports to handle multi-bit operations efficiently.[45][46]
To ensure purely combinational synthesis without unintended latches, all possible input conditions must be covered in conditional statements like if-else or case, assigning values to every output signal in every execution path. Omitting an else clause or when others in a case can infer a latch to hold the previous output value, leading to timing issues and non-combinational behavior. Default assignments before conditionals or exhaustive branches prevent this, maintaining the stateless nature of the design.[47][48]
Sequential Logic Components
Sequential logic components in VHDL model state-holding elements that capture and retain data based on clock signals, enabling the design of circuits with memory such as flip-flops and registers. These constructs are typically implemented using processes sensitive to the clock and optional reset signals, ensuring synthesizable hardware descriptions that map to FPGA or ASIC primitives. The use of therising_edge function within a process defines clocked behavior, where data updates occur only on the positive clock transition, promoting predictable timing and avoiding race conditions.[49]
A D-type flip-flop (DFF) serves as the fundamental building block for sequential logic, storing a single bit of data until the next clock edge. In VHDL, it is described using a concurrent process sensitive to the clock and asynchronous reset signals. For asynchronous reset handling, the reset condition is checked outside the clock edge, allowing immediate state clearing independent of the clock. Synchronous reset, conversely, occurs within the clocked branch, tying the reset to the clock cycle. A basic synthesizable template for a DFF with asynchronous active-high reset is shown below:
process (clk, rst)
begin
if rst = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
process (clk, rst)
begin
if rst = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
process (clk, clr, pre)
begin
if clr = '1' then
q <= '0';
elsif pre = '1' then
q <= '1';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
process (clk, clr, pre)
begin
if clr = '1' then
q <= '0';
elsif pre = '1' then
q <= '1';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
q holds the input d value across clock cycles unless reset intervenes.
A register extends the DFF concept to multi-bit data storage, typically as an array of DFFs with an enable signal to control loading. The enable acts as a clock gate in the synchronous path, updating the register only when asserted, which optimizes power in hardware implementations. A standard 8-bit register with synchronous enable and reset uses a vector signal:
process (clk)
begin
if rising_edge(clk) then
if rst = '1' then
reg <= (others => '0');
elsif en = '1' then
reg <= din;
end if;
end if;
end process;
process (clk)
begin
if rising_edge(clk) then
if rst = '1' then
reg <= (others => '0');
elsif en = '1' then
reg <= din;
end if;
end if;
end process;
reg and din are declared as std_logic_vector(7 downto 0), and the process is sensitive only to clk for fully synchronous behavior. This template infers parallel DFFs during synthesis, preserving data when en is low.
Shift registers facilitate serial-to-parallel data conversion, commonly used in communication interfaces. A serial-in, parallel-out (SIPO) shift register loads bits sequentially on each clock edge, shifting existing data right or left. Implemented with a loop in the process for bit manipulation, an 8-bit left-shifting SIPO example is:
process (clk)
begin
if rising_edge(clk) then
for i in 7 downto 1 loop
sreg(i) <= sreg(i-1);
end loop;
sreg(0) <= serial_in;
end if;
end process;
parallel_out <= sreg;
process (clk)
begin
if rising_edge(clk) then
for i in 7 downto 1 loop
sreg(i) <= sreg(i-1);
end loop;
sreg(0) <= serial_in;
end if;
end process;
parallel_out <= sreg;
sreg as std_logic_vector(7 downto 0), this loads the serial input at the least significant bit, shifting toward the most significant bit over eight cycles to fill the parallel output. An alternative uses concatenation for conciseness: sreg <= sreg(6 downto 0) & serial_in;. Both approaches synthesize to a chain of DFFs, with the loop version aiding readability for wider registers.[50]
Latches, unlike flip-flops, are level-sensitive and transparent when enabled, but their inference in VHDL is often unintended and should be avoided in clocked designs due to timing unpredictability and poor synthesis support in FPGAs. Incomplete conditional statements in combinational processes, such as an if without an else branch, cause synthesis tools to infer a latch to hold the last value. To prevent this, assign default values to all outputs before conditionals and ensure full case coverage. A deliberate transparent latch template, for edge cases like low-power retention, is:
process (en, d)
begin
if en = '1' then
q <= d;
end if;
end process;
process (en, d)
begin
if en = '1' then
q <= d;
end if;
end process;
d to q while en is high, but latches are generally discouraged in favor of clocked elements for synchronous designs.[47]
Timing considerations in VHDL sequential components, such as setup and hold times, are implicitly modeled in simulation through signal stability requirements around clock edges. Setup time mandates data stability before the clock edge, while hold time requires it after, preventing metastability; violations in simulation manifest as undefined or metastable states in tools like ModelSim. These parameters are verified post-synthesis using static timing analysis, where VHDL descriptions guide constraint files to enforce margins, ensuring reliable clocked behavior without explicit code for internal paths.[51]
Full Circuit Example
A full circuit example in VHDL is a 4-bit up-counter, which demonstrates the integration of entity declaration, architectural process for sequential behavior, concurrent signal assignments for combinational logic, and overall synthesizable structure. This design includes inputs for clock (clk), synchronous reset (reset), and enable (enable), with outputs for the 4-bit count (q) and a combinational overflow flag (overflow) that asserts when the count reaches its maximum value. The counter increments the count on each rising clock edge if enable is active and reset is inactive, wrapping around after overflow, while the overflow signal provides immediate detection without affecting the sequential state.[52] The following code snippet presents the complete entity-architecture pair using the IEEE standard libraries for type definitions and arithmetic operations:library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity up_counter is
port (
clk : in std_logic;
reset : in std_logic;
enable : in std_logic;
q : out unsigned(3 downto 0);
overflow : out std_logic
);
end entity up_counter;
architecture behavioral of up_counter is
signal count : unsigned(3 downto 0);
begin
process (clk)
begin
if rising_edge(clk) then
if reset = '1' then
count <= (others => '0');
elsif enable = '1' then
count <= count + 1;
end if;
end if;
end process;
q <= count;
overflow <= '1' when count = "1111" else '0';
end architecture behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity up_counter is
port (
clk : in std_logic;
reset : in std_logic;
enable : in std_logic;
q : out unsigned(3 downto 0);
overflow : out std_logic
);
end entity up_counter;
architecture behavioral of up_counter is
signal count : unsigned(3 downto 0);
begin
process (clk)
begin
if rising_edge(clk) then
if reset = '1' then
count <= (others => '0');
elsif enable = '1' then
count <= count + 1;
end if;
end if;
end process;
q <= count;
overflow <= '1' when count = "1111" else '0';
end architecture behavioral;
Standards and Evolutions
Core Revisions
The VHDL standard originated with IEEE 1076-1987, establishing the foundational syntax and semantics for hardware description. Subsequent revisions have iteratively enhanced the language to address evolving needs in digital system design and verification. The IEEE 1076-1993 revision introduced shared variables to support concurrent access across multiple processes and improvements to synthesis support, including better handling of guarded signals and attribute usage to enable more reliable translation to hardware implementations.[53][54][15] The IEEE 1076-2000 revision introduced protected types for encapsulating data with associated methods to manage shared state safely.[55] The IEEE 1076-2002 revision was minor, primarily relaxing rules on buffer ports to improve usability in designs and fully integrating protected types.[56][57] The IEEE 1076-2008 revision expanded expressiveness with dynamic types enabling runtime allocation via access types in more contexts, sequential elaboration for deterministic ordering in complex hierarchies during simulation, and enhancements to text I/O procedures for improved string manipulation and file operations in testbenches.[58][59] IEEE 1076-2019 introduced interfaces for bundling ports to streamline testbench connections, conditional analysis directives for configuration-dependent code, enhancements to file I/O including directory operations and environment variable reading, generics on protected types and subprograms, and shared variables on entities to support advanced verification.[2][60] These core revisions were primarily driven by industry feedback, including demands from FPGA and ASIC designers for streamlined design flows, enhanced verification productivity, and better integration with emerging tools.[15] Each revision supersedes its predecessor while preserving backward compatibility, ensuring that code compliant with earlier versions remains valid unless explicitly deprecated for safety or clarity reasons.[61]Advanced Features in Later Versions
VHDL-2008 introduced external names, enabling the creation of aliases to reference signals and objects across the design hierarchy without specifying full paths, which simplifies verification tasks such as error injection and signal forcing from testbenches.[62] This feature uses syntax likealias my_alias is << /top.uut.signal_name >>; to access nested elements, overcoming scoping limitations in prior versions and supporting hierarchical access during simulation.[63] External names must reference elaborated objects, and their use is primarily for verification rather than synthesis.[27]
The same revision enhanced array aggregates by permitting slices and nested aggregates, providing a unified and simplified syntax for initializing and assigning multi-dimensional arrays. Prior to VHDL-2008, aggregates required positional or named associations without slices, but the update allows expressions like (others => (1 to 4 => '0')) for a two-dimensional array, reducing verbosity and improving readability for complex data structures.[62] This applies to both synthesizable and simulatable code, with support for unconstrained array dimensions in aggregates.[64]
Generics saw significant expansions starting in VHDL-2002 and maturing in VHDL-2008, allowing packages, subprograms, and types as generic parameters to promote IP reuse and parameterization. For instance, an entity can declare a generic type data_type and a generic function, enabling flexible binding such as generic (type data_type; function increment(data_type) return data_type);, which facilitates reusable arithmetic units.[65] VHDL-2019 further refined these by permitting generics on protected types and subprograms with ordered parameter lists, enhancing modularity for verification components.[66]
VHDL-2019 advanced verification through protected type enhancements, including generics and improved access methods, which enable more robust modeling of non-deterministic behaviors in testbenches via libraries like OSVVM. These updates support shared variables on entities and conditional analysis directives for configuration-dependent code, aiding probabilistic-like simulations in complex systems.[67] Interfaces, declared using records and mode views, bundle ports for streamlined testbench connections, reducing boilerplate in verification environments.[60]
For mixed-signal applications, the VHDL-AMS standard (IEEE 1076.1-2017) extends core VHDL with analog and continuous-time modeling capabilities, supporting simultaneous simulation of digital and analog domains through simultaneous statements and quantity declarations. It introduces real and electrical types for behavioral descriptions of circuits like amplifiers, enabling co-simulation of event-driven digital logic with solved differential equations for analog components.[68] This superset maintains VHDL compatibility while adding domains like thermal and mechanical for multi-physics modeling.[69]
The IEEE P1076 working group is developing the VHDL-202X revision, with the project authorized in 2021 and completion projected for December 2025, focusing on user-submitted enhancements to address modern design needs.[70][71]
Libraries and Packages
Built-in Packages
VHDL includes several built-in packages that provide essential functionality independent of optional extensions, ensuring core language operations are available by default. The STANDARD package is the foundational predefined package, which declares the basic scalar and composite types required for describing hardware behavior and performing fundamental computations. It defines types such as bit (a two-valued logic type with values '0' and '1'), boolean (with values false and true), integer (a signed whole number ranging typically from -2^31 to 2^31-1, though implementation-dependent), real (a floating-point number), time (for delay specifications), severity_level (for assertions), and string (an array of characters), along with corresponding array types like bit_vector.[72][73][74] In addition to types, the STANDARD package overloads operators for these types, enabling arithmetic operations (addition, subtraction, multiplication, division), logical operations (AND, OR, NOT, XOR), relational comparisons (equality, inequality, greater than, less than), and shifting functions (sll, srl, sla, sra, rol, ror) directly on compatible operands without explicit declarations. This package is automatically visible in all design units, requiring no library clause or use clause, which allows immediate access to these elements for signal declarations, constant assignments, and expression evaluations in entities and architectures.[72][73][20] The WORK library functions as the default repository for compilation units in VHDL, automatically placing analyzed primary and secondary design units (such as entities, architectures, and packages) into this logical library unless otherwise specified. It acts as a placeholder for the current compilation environment, facilitating modular design by grouping related units without needing explicit library mappings during initial development. In practice, when compiling VHDL source files, tools map the WORK library to a physical directory, enabling seamless referencing of units within the same project scope.[75][76][77] For simulation support, the TEXTIO package offers basic formatted input/output operations using ASCII text files, primarily to generate readable output or load stimulus data during testbench execution. It declares the file type text (representing lines of characters), the access type line (pointers to strings for manipulation), and procedures such as readline (to read a line from a file into a line object), writeline (to write a line object to a file), read (to parse values like integers or bits from a line), and write (to format and append values to a line), along with file opening and closing functions. TEXTIO is part of the STD library and must be explicitly referenced via a use clause (e.g., use std.textio.all;) to enable file handling in processes, though it is limited to simulation environments and does not synthesize to hardware.[20][78][79] These built-in packages collectively cover essential arithmetic, logical, and simulation I/O needs but have inherent limitations: the STANDARD package supports only two-valued logic via bit and lacks multi-value resolution for modeling real-world signal behaviors, such as unknown states (e.g., 'U' or 'Z'), necessitating reliance on IEEE-defined packages like std_logic_1164 for advanced digital design applications.[72][80]IEEE Standard Libraries
The IEEE standard libraries in VHDL, defined under IEEE Std 1076, provide essential packages that extend the language's capabilities for modeling digital logic, arithmetic operations, and mathematical computations in hardware descriptions. These libraries are crucial for ensuring interoperability and portability across tools, with key packages focusing on multi-value logic types, numeric arithmetic, utility functions, and advanced math support for simulation environments.[56] The std_logic_1164 package, standardized in IEEE Std 1164-1993 and integrated into subsequent VHDL revisions, introduces the std_logic type as a resolved multi-value logic system to model signals more accurately than the basic bit type. This type supports nine possible values: 'U' (uninitialized), 'X' (unknown or conflicting), '0' (logic low), '1' (logic high), 'Z' (high impedance), 'W' (weak unknown), 'L' (weak low), 'H' (weak high), and '-' (don't care). The package also includes a resolution function that handles concurrent signal assignments by prioritizing values in cases of multiple drivers, such as resolving 'Z' with '0' to '0'. This enables realistic simulation of tri-state logic and bus contention scenarios in digital designs. To support file I/O with std_logic types, the std_logic_textio package extends the functionality of TEXTIO by providing procedures like hread, hwrite, bwrite, and owrite for reading and writing std_logic and std_logic_vector in hexadecimal, binary, and octal formats. This package, part of IEEE Std 1164, is essential for testbenches involving multi-value logic and must be explicitly used (e.g., use ieee.std_logic_textio.all;). Like TEXTIO, it is simulation-only and non-synthesizable.[29] For arithmetic operations on logic vectors, the numeric_std package offers a standardized approach using signed and unsigned types derived from std_logic_vector, promoting portable and synthesizable code. It defines overloaded operators for addition, subtraction, multiplication, division, and comparisons on these types, treating signed as two's complement representation and unsigned as natural binary. This package is recommended over the deprecated non-standard std_logic_arith and std_logic_unsigned, as it ensures consistent behavior across vendors and avoids ambiguity in overflow handling. For instance, adding two unsigned vectors results in truncation if the length exceeds the operand size, while signed operations preserve sign extension where applicable. Mathematical extensions are provided by the math_real and math_complex packages, outlined in IEEE Std 1076.2-1996, for simulation-based computations involving real numbers and complex quantities. The math_real package supports floating-point operations on the predefined real type, including transcendental functions like SIN, COS, EXP, LOG, and SQRT, with arguments and results adhering to IEEE 754 precision guidelines where feasible. Meanwhile, math_complex defines a complex type as a record of two reals (real and imaginary parts) and overloads operators for addition, subtraction, multiplication, division, and polar conversions, along with functions like ARG (argument) and COMPLEX (constructor). These are primarily for testbench modeling and algorithmic verification, not synthesis, as they operate on unbounded real arithmetic unsuitable for hardware mapping. To incorporate these packages in a VHDL design, declarations such aslibrary ieee; use ieee.std_logic_1164.all; are placed before the entity or architecture, making the types and functions visible within the scope. Selective imports like use ieee.[numeric_std](/page/Numeric_std).all; can limit namespace pollution, and multiple packages are often combined for comprehensive designs, e.g., pairing std_logic_1164 with numeric_std for arithmetic circuits.[81]
The evolution of these libraries saw significant updates in IEEE Std 1076-2008, which improved consistency by refining numeric_std to better align with synthesis requirements, deprecating conflicting vendor extensions, and enhancing mathematical package generics for fixed- and floating-point support in later revisions. These changes promoted standardization, reducing portability issues in multi-tool flows.