WHAT IS VHDL??
The VHSIC Hardware Description Language is an industry standard language used to describe hardware from the abstract to the concrete level. VHDL resulted from work done in the ’70s and early ’80s by the U.S. Department of Defense. Its roots are in the ADA language, as will be seen by the overall structure of VHDL as well as other VHDL statements.
VHDL usage has risen rapidly since its inception and is used by literally tens of thousands of engineers around the globe to create sophisticated electronic products. This chapter will start the process of easing the reader into the complexities of VHDL.VHDL is a powerful language with numerous language constructs that are capable of describing very complex behavior. Learning all the features of VHDL is not a simple task. Complex features will be introduced in a simple form and then more complex usage will be described.
In 1986, VHDL was proposed as an IEEE standard. It went through a number of revisions and changes until it was adopted as the IEEE 1076 standard in December 1987. The IEEE 1076-1987 standard VHDL is the VHDL used in this book. (Appendix D contains a brief description of VHDL 1076-1993.) All the examples have been described in IEEE 1076 VHDL, and compiled and simulated with the VHDL simulation environment from Model Technology Inc. The synthesis examples were synthesized with the Exemplar Logic Inc. synthesis tools.
VHDL describes the behavior and structure of digital systems. The acronym VHDL
stands for VHSIC Hardware Descriptive Language and VHSIC in turn stands for
Very High Speed Integrated Circuit. VHDL can describe a digital system at different
levels of abstraction:
• Data flow
For instance, consider the case of a binary adder. The binary adder could be described at behavioral in terms of its actual function of adding two numbers without any additional implementation details. The same could be described at the data flow by giving logical equations for the adder (sum & carry). Finally, the adder could be described at the structural level by specifying the basic modules that are used to build the adder and also by specifying the interconnections between the same. The different levels will be dealt in detail with examples in later section. VHDL adopts a top-down design methodology, in which a system is first specified at a high level and tested. Once debugged, the design can gradually be refined, eventually leading to a structural description closely related to the actual hardware implementation. VHDL is designed to be technology independent.
A Brief History of VHDL
The development of VHDL was initiated in 1981 by the United States Department of Defence to address the hardware life cycle crisis. The cost of reprocuring electronic hardware as technologies became obsolete was reaching crisis point, because the function of the parts was not adequately documented, and the various components making up a system were individually verified using a wide range of different and incompatible simulation languages and tools. The requirement was for a language with a wide range of descriptive capability that would work the same on any simulator and was independent of technology or design methodology.
The standardization process for VHDL was unique in that the participation and feedback from industry was sought at an early stage. A baseline language (version 7.2) was published 2 years before the standard so that tool development could begin in earnest in advance of the standard. All rights to the language definition were given away by the DoD to the IEEE in order to encourage industry acceptance and investment.
DoD Mil Std 454 mandates the supply of a comprehensive VHDL description with every ASIC delivered to the DoD. The best way to provide the required level of description is to use VHDL throughout the design process.
As an IEEE standard, VHDL must undergo a review process every 5 years (or sooner) to ensure its ongoing relevance to the industry. The first such revision was completed in September 1993, and this is still the most widely supported version of VHDL.
VHDL 2000 and VHDL 2002
One of the features that was introduced in VHDL-1993 was shared variables. Unfortunately, it wasn't possible to use these in any meaningful way. A working group eventually resolved this by proposing the addition of protected types to VHDL. VHDL 2000 Edition is simply VHDL-1993 with protected types.
VHDL-2002 is a minor revision of VHDL 2000 Edition. There is one significant change, though: the rules on using buffer ports are relaxed, which makes these much more useful than hitherto.
In 2007, an amendment to VHDL 2002 was created. This introduces the VHDL Procedural Interface (VHPI) and also makes a few minor changes to the text of VHDL 2002. Apart from the VHPI itself, no new features were added to VHDL.
The VHPI allows tools programmable access to a VHDL model before and during simulation. In other words, you can write programs in a language such as C that interact eith a VHDL simulator.
The next revision of VHDL was released in January 2009, and is currently referred to as "VHDL-2008". Further details can be found here
Summary: History of VHDL
1981 Initiated by US DoD to address hardware life-cycle crisis
1983-85 Development of baseline language by Intermetrics, IBM and TI
1986 All rights transferred to IEEE
1987 Publication of IEEE Standard
1987 Mil Std 454 requires comprehensive VHDL descriptions to be delivered with ASICs
1994 Revised standard (named VHDL 1076-1993)
2000 Revised standard (named VHDL 1076 2000, Edition)
2002 Revised standard (named VHDL 1076-2002)
2007 VHDL Procedural Language Application Interface standard (VHDL 1076c-2007)
2009 Revised Standard (named VHDL 1076-2008)
Benefits of VHDL
VHDL is defined by IEEE. This standard is known by all the VHDL tool developers. So
there is only one language to learn. This language is used by all the circuit designers around the world. The life time for this language is assured, since it is an IEEE standards. Any investment or learning is assured for lifetime. Abundance of models available from different sources can be used with ease. Some tools might support Foreign Language Interface, by which you can add your model in C language to the VHDL code. It is a modern language, powerful and general. Other advantages include readability of the code and portability. The code developed is portable to any technology at any time. Time to market is short (leads to leadership in the market). Any error found during the simulation phase is less expensive than by discovering the errors after making the circuit board (Investment is saved). The great advantage is that the Project Managers can modify the specification without leading to disaster (only the necessary portion of the code need to be changed). It can deliver designs 100% error free at short duration. New Concepts in
hardware design (for example, in image processing, DSP, etc.,) can be modeled in VHDL and its efficiency or viability can be proven without doing the hardware. A large number of ASICs fail to work when plugged into a system even if they meet their specifications first time. VHDL addresses this issue in two ways: A VHDL specification can be executed in order to achieve a high level of confidence in its correctness before commencing design, and may simulate one to two orders of magnitude faster than a gate level description. A VHDL specification for a part can form the basis for a simulation model to verify the operation of the part in the wider system context (e.g. printed circuit board simulation). This depends on how accurately the specification handles aspects such as timing and initialization.
Entity – Architecture
A VHDL program consists of an entity declaration and an architectural declaration. All the input, output signals, type of each signal are mentioned in the entity whereas the behavior of the digital systems is described in the architecture in terms of logical equations or by mentioning the functional implementation or by any other means. Consider the example of a 1 bit full adder:
entity FullAdder is --declaration of entity
port (a, b, cin : in bit; --Inputs sum, cout : out bit); --Outputs
end FullAdder; --End of entity
• entity, port, is, end : key words
• in, out : modes
• FullAdder : identifier
• Bit : data type
The words entity, is, port, in, out, and, end are reserved words (keywords). They all have a special meaning to the VHDL compiler. Anything that follows “--“ is a VHDL comment. These will be not be considered during the compilation. The port declaration specifies that a, b, cin are input signals of type (data type) bit and sum, cout are output signals of type bit. The operation of the full adder is specified by an architectural declaration:
architecture dataflow of FullAdder is
sum <= a xor b xor cin;
cout <= (a and b) or (b and cin) or (cin or a);
Once again, the words in bold indicate the reserved words (key words). It should be noted that each statement in VHDL must end with a semicolon.In this example, the architecture name (dataflow) is arbitrary, but the entity name (FullAdder) must match the name used in the associated entity declaration. Signal names and other VHDL identifiers may contain letters, numbers, and the underscore character.An identifier must start with a letter, and it cannot end with an underscore.
Data Types in VHDL
Like a high-level software programming language, VHDL allows data to be represented
in terms of high-level data types. A data type is an abstract representation of stored data,
such as you might encounter in software languages. These data types might represent
individual wires in a circuit, or they might represent collections of wires.
For instance, the bit data type has only two possible values: ‘1’ or ‘0’. A bit_vector is
simply an array of bits. Every data type in VHDL has a defined set of values, and a
defined set of valid operations. Type checking is strict, so it is not possible, for example,
to directly assign the value of an integer data type to a bit_vector data type. But, there
are ways to get around this restriction, using what are called type conversion functions
which are beyond the scope of the material.
The Table below summarizes the fundamental data types available in VHDL.
Data Type Values Example
Bit ‘1’, ‘0’ Q <= ‘1’;
bit_ vector (array of bits) DataOut <= "00010101";
Boolean True, False EQ <= True;
Integer -2, -1, 0, 1, 2, 3, 4 . . . Count <= Count + 2;
Real 1.0, -1.0E5 V1 = V2 / 5.3
Time 1 us, 7 ns, 100 ps Q <= ‘1’ after 6 ns;
Character ‘a’, ‘b’, ‘2, ‘$’, etc. CharData <= ‘X’;
String (Array of characters) Msg <= "MEM: " & Addr
An absolute value operator can be applied to any numeric type in an expression.
Example: Delta <= abs(A-B)
The logical "both or neither" (equality) operator can be used in an expression. The
expression "A xnor B" returns True only when
• A is true and B is true
• A is false and B is false
The logical "and" operator can be used in an expression. The expression "A and B"
returns true only if both A and B are true.
The modulus operator can be applied to integer types. The result of the expression "A
mod B" is an integer type and is defined to be the value such that:
• the sign of (A mod B) is the same as the sign of B, and
• abs (A mod B) < abs (B), and
• (A mod B) = (A * (B - N)) for some integer N.
The logical "not and" operator can be used in an expression. It produces the opposite of
the logical "and" operator. The expression "A nand B" returns True only when
• A is false
• B is false
• Both A and B are false
The logical "not or" operator can be used in an expression. It produces the opposite of
the logical "or" operator. The expression "A nor B" returns True only when both A and
B are false.
The logical "not" operator can be used in an expression. The expression "not A" returns
True if A is false and returns False if A is true.
The logical "or" operator can be used in an expression. The expression "A or B" returns
• A is true
• B is true
Both A and B are true
The remainder operator can be applied to integer types. The result of the expression "A
rem B" is an integer type and is defined to be the value such that:
• The sign of (A rem B) is the same as the sign of A, and
• abs (A rem B) < abs (B), and
• (A rem B) = (A - (A / B) * B).
Rotate left operator.
Example: Sreg <= Sreg rol 2;
Rotate right operator.
Example: Sreg <= Sreg ror 2;
Shift left arithmetic operator
Example: Addr <= Addr sla 8;
Shift left logical operator.
Example: Addr <= Addr sll 8;
Shift right arithmetic operator.
Example: Addr <= Addr sra 8;
Shift right logical operator.
Example: Addr <= Addr srl 8;
The logical "one or the other but not both" (inequality) operator can be used in an
expression. The expression "A xor B" returns True only when
• A is true and B is false
• A is false and B is true
The equality operator can be used in an expression on any type except file types. The
resulting type of an expression using this operator is Boolean (that is, True or
False). The expression "A = B" returns True only if A and B are equal.
The inequality operator can be used in an expression on any type except file types. The
resulting type of an expression using this operator is Boolean (that is, True or
False). The expression "A /= B" returns True only if A and B are not equal.
This is the assignment operator for a variable. The expression "TEST_VAR := 1"
means that the variable TEST_VAR is assigned the value 1.
The "less than" operator can be used in an expression on scalar types and discrete array
types. The resulting type of an expression using this operator is Boolean (that is, True
or False). The expression "A < B" returns True only if A is less than B.
This symbol has two purposes. When used in an expression on scalar types and discrete
array types, it is the "less than or equal to" operator. The resulting type of an expression
using this operator in this context is Boolean (that is, True or False). In this context, the
expression "A <= B" returns True only if A is less than or equal to B.
Example: LE := ‘1’ when A <= B else ‘0’;
In a signal assignment statement, the symbol "<=" is the assignment operator. Thus, the
expression "TEST_SIGNAL <= 5" means that the signal TEST_SIGNAL is assigned
the value 5.
Example: DataBUS <= 0x"E800";
The "greater than" operator can be used in an expression on scalar types and discrete
array types. The resulting type of an expression using this operator is Boolean (that is,
True or False). The expression "A > B" returns True only if A is greater than B.
The "greater than or equal to" operator can be used in an expression on scalar types and
discrete array types. The resulting type of an expression using this operator is Boolean
(that is, True or False). The expression "A >= B" returns True only if A is greater than
or equal to B.
This is the addition operator. Both operands must be numeric and of the same
type. The result is also of the same numeric type. Thus, if A = 2 and B = 3, the result
of the expression "A + B" is 5.
This operator may also be used as a unary operator representing the identity
function. Thus, the expression "+A" would be equal to A.
This is the subtraction operator. Both operands must be numeric and of the same
type. The result is also of the same numeric type. Thus, if A = 5 and B = 3, the result
of the expression "A - B" is 2.
This operator may also be used as a unary operator representing the negative
function. Thus, the expression "-A" would be equal to the negative of A.
This is the concatenation operator. Each operand must be either an element type or a 1-
dimensional array type. The result is a 1-dimensional array type.
This is the multiplication operator. Both operands must be of the same integer or
floating point type.
The multiplication operator can also be used where one operand is of a physical type
and the other is of an integer or real type. In these cases, the result is of a physical type.
This is the division operator. Both operands must be of the same integer or floating
The division operator can also be used where a physical type is being divided by either
an integer type or a real type. In these cases, the result is of a physical type. Also, a
physical type can be divided by another physical type, in which case the result is an
This is the exponentiation operator. The left operand must be of an integer type or a
floating point type, and the right operand (the exponent) must be of an integer type. The
result is of the same type as the left operand.
Signals are objects that are used to connect concurrent elements (such as components, processes and concurrent assignments), similar to the way that wires are used to connect components on a circuit board or in a schematic. Signals can be declared globally in an external package or locally within architecture, block or other declarative region.
To declare a signal, you write a signal statement such as the following:
architecture arch1 of my_design is
signal Q: std_logic;
. . .
In this simple example, the signal Q is declared within the declaration section of the arch1 architecture. At a minimum, a signal declaration must include the name of the signal (in this case Q) and its type (in this case the standard type std_logic). If more than one signal of the same type is required, multiple signal names can be specified in a single declaration:
architecture arch2 of my_design is
signal Bus1, Bus2: std_logic_vector(7 downto 0);
. . .
In the first example above, the declaration of Q was entered in the declaration area of architecture arch1. Thus, the signal Q will be visible anywhere within the arch1 design unit, but it will not be visible within other design units. To make the signal Q visible to the entire design (a global signal), you would have to move the declaration into an external package, as shown below:
package my_package is
signal Q: std_logic; -- Global signal
. . .
use work.my_package.Q; -- Make Q visible to the architecture
architecture arch1 of my_design is
. . .
In this example, the declaration for Q has been moved to an external package, and a use statement has been specified, making the contents of that package visible to the subsequent architecture.
In addition to creating one or more signals and assigning them a type, the signal declaration can also be used to assign an initial value to the signal, as shown below:
signal BusA: std_logic_vector(4 downto 0) := “0000”;
Variables are objects used to store intermediate values between sequential VHDL statements. Variables are only allowed in processes, procedures and functions, and they are always local to those functions. Variables in VHDL are much like variables in a conventional software programming language. They immediately take on and store the value assigned to them and they can be used to simplify a complex calculation or sequence of logical operations.
Using Constants and Literals
Constants are objects that are assigned a value once, when declared, and do not change their value during simulation. Constants are useful for creating more readable design descriptions, and they make it easier to change the design at a later time. The following code fragment provides a few examples of constant declarations:
architecture sample1 of consts is
constant SRAM: bit_vector(15 downto 0) := X"F0F0";
constant PORT: string := "This is a string";
constant error_flag: boolean := True;
. . .
process( . . .)
constant CountLimit: integer := 205;
. . .
Constant declarations can be located in any declaration area in your design description. If you want to create constants that are global to your design description, then you will place the constant declarations into external packages. If a constant will be used only within one segment of your design, you can place the constant declaration within the architecture, block, process or subprogram that requires it.
Explicit data values that are assigned to objects or used within expressions are called literals. Literals represent specific values, but they do not always have an explicit type. (For example, the literal '1' could represent either a bit data type or a character.) Literals do, however, fall into a few general categories.
Character literals are 1-character ASCII values that are enclosed in single-quotes, such as the values '1', 'Z', '$' and ':'. The data type of the object being assigned one of these values (or the type implied by the expression in which the value is being used) will dictate whether a given character literal is valid. The literal value '$', for example, is a valid literal when assigned to a character type object, but it is not valid when assigned to a std_logic or bit data type.
String literals are collections of one or more ASCII characters enclosed in double-quote characters. String literals may contain any combination of ASCII characters, and they may be assigned to appropriately sized arrays of single-character data types (such as bit_vector or std_logic_vector) or to objects of the built-in type string.
Bit string literals
Bit string literals are special forms of string literals that are used to represent binary, octal, or hexadecimal numeric data values. When representing a binary number, a bit string literal must be preceded by the special character 'B', and it may contain only the characters '0' and '1'. For example, to represent a decimal value of 36 using a binary format bit string literal, you would write
When representing an octal number, the bit string literal must include only the characters '0' through '7', and it must be preceded by the special character 'O', as in O"446".
When representing a hexadecimal value, the bit string literal must be preceded by the special character 'X', and it may include only the characters '0' through '9' and the characters 'A' through 'F', as in X"B295". (Lower-case characters are also allowed, so 'a' through 'f' are also valid.)
The underscore character '_' may also be used in bit string literals as needed to improve readability. The following are some examples of bit string literals representing a variety of numeric values:
B"0111_1101" (decimal value 253)
O"654" (decimal value 428)
O"146_231" (decimal value 52,377)
X"C300" (decimal value 49,920)
Note: In VHDL standard 1076-1987, bit string literals are only valid for the built-in type bit_vector. In 1076-193, bit string literals can be applied to any string type, including std_logic_vector.
There are two basic forms of numeric literals in VHDL, integer literals and real literals. Integer literals are entered as you would expect, as decimal numbers preceded by an optional negation character ('-'). The range of integers supported is dependent on your particular simulator or synthesis tool, but the VHDL standard does specify a minimum range of -2,147,483,647 to +2,147,483,647 (32 bits of precision, including the sign bit).
Real literals are entered using an extended form that requires a decimal point. For large numbers, scientific notation is also allowed using the character 'E', where the number to the left of the 'E' represents the mantissa of the real number, while the number to the right of the 'E' represents the exponent. The following are some examples of real literals:
The minimum and maximum values of real numbers are defined by the simulation tool vendor, but they must be at least in the range of -1.0E38 to +1.0E38 (as defined by the standard). Numeric literals may not include commas, but they may include underscore characters ("_") to improve readability, as in:
1_276_801 -- integer value 1,276,801
Type checking is strict in VHDL, and this includes the use of numeric literals. It is not possible, for example, to assign an integer literal of 9 to an object of type real. (You must instead enter the value as 9.0.)
Based literals are another form of integer or real values, but they are written in nondecimal
form. To specify a based literal, you precede the literal with a base specification (such as 2, 8, or 16) and enclose the non-decimal value with a pair of '#' characters as shown in the examples below:
2#10010001# (integer value 145)
16#FFCC# (integer value 65,484)
2#101.0#E10 (real value 5,120.0)
Physical literals are special types of literals used to represent physical quantities such as time, voltage, current, distance, etc. Physical literals include both a numeric part (expressed as an integer) and a unit specification. Physical types will be described in more detail later in this chapter. The following examples show how physical literals can be expressed:
300 ns (300 nanoseconds)
900 ps (900 picoseconds)
40 ma (40 milliamps)
A unique feature of VHDL is that it can execute concurrent as well as sequential statements. This feature is explained in the following sections.
Before we go any further, let’s define some of the terms that we use throughout the book. These are the basic VHDL building blocks that are used in almost every description, along with some terms that are redefined in VHDL to mean something different to the average designer.
_ Entity. All designs are expressed in terms of entities. An entity is the most basic building block in a design. The uppermost level of the design is the top-level entity. If the design is hierarchical, then the top-level description will have lower-level descriptions contained in it. These lower-level descriptions will be lower-level entities contained in the top-level entity description.
_ Architecture. All entities that can be simulated have an architecture description. The architecture describes the behavior of the entity. A single entity can have multiple architectures. One architecture might be behavioral while another might be a structural description of the design.
_ Configuration. A configuration statement is used to bind a component instance to an entity-architecture pair. A configuration can be considered like a parts list for a design. It describes which behavior to use for each entity, much like a parts list describes which part to use for each part in the design.
Package. A package is a collection of commonly used data types and subprograms used in a design. Think of a package as a toolbox that contains tools used to build designs.
_ Driver. This is a source on a signal. If a signal is driven by two sources, then when both sources are active, the signal will have two drivers.
Bus. The term “bus” usually brings to mind a group of signals or a particular method of communication used in the design of hardware. In VHDL, a bus is a special kind of signal that may have its drivers turned off.
_ Attribute. An attribute is data that are attached to VHDL objects or predefined data about VHDL objects. Examples are the current drive capability of a buffer or the maximum operating temperature of the device.
_ Generic. A generic is VHDL’s term for a parameter that passes information to an entity. For instance, if an entity is a gate level model with a rise and a fall delay, values for the rise and fall delays could be passed into the entity with generics.
_ Process. A process is the basic unit of execution in VHDL. All operations that are performed in a simulation of a VHDL description are broken into single or multiple processes.
Describing Hardware in VHDL
VHDL Descriptions consist of primary design units and secondary design units. The primary design units are the Entity and the Package. The secondary design units are the Architecture and the Package Body. Secondary design units are always related to a primary design unit. Libraries are collections of primary and secondary design units. A typical design usually contains one or more libraries of design units.
A VHDL entity specifies the name of the entity, the ports of the entity, and entity-related information. All designs are created using one or more entities.
Let’s take a look at a simple entity example:
ENTITY mux IS
PORT ( a, b, c, d : IN BIT;
s0, s1 : IN BIT;
x, : OUT BIT);
The keyword ENTITY signifies that this is the start of an entity statement. In the descriptions shown throughout the book, keywords of the language and types provided with the STANDARD package are shown in ALL CAPITAL letters. For instance, in the preceding example, the keywords are ENTITY, IS, PORT, IN, INOUT, and so on. The standard type provided is BIT. Names of user-created objects such as mux, in the example above, will be shown in lower case.
The name of the entity is mux. The entity has seven ports in the PORT clause. Six ports are of mode IN and one port is of mode OUT. The four data input ports (a, b, c, d) are of type BIT. The two multiplexer select inputs, s0 and s1, are also of type BIT. The output port is of type BIT.The entity describes the interface to the outside world. It specifies the number of ports, the direction of the ports, and the type of the ports.A lot more information can be put into the entity than is shown here,but this gives us a foundation upon which we can build more complex