Editor’s Note: In this series of articles based on his book – Design Recipes for FPGAs – Peter Wilson provides a basic quick overview of VHDL (VHSIC hardware description language) followed by examples of its use in describing – in HDL code form – functions familiar to most embedded software developers such as arithmetic logic units (ALUs) and finite state machines (FSMs). It is not intended as a comprehensive VHDL reference. For that, he recommends “Digital System Design with VHDL,” by Mark Zwolinski; ”VHDL: Analysis and modeling of digital systems,” by Zainalabedin Navabi or “Designer’s Guide to VHDL” by Peter Ashenden.
In hierarchical designs, functions are a simple way of encapsulating behavior in a model that can be reused in multiple architectures. Functions can be defined locally to an architecture or more commonly in a package.
In this part in the series, the basic approach of defining functions will be described. The simple form of a function is to define a header with the input and output variables as shown below:
function name (input declarations) return output_type is
... variable declarations
... function body
For example, a simple function that takes two input numbers and multiplies them together could be defined as follows:
function mult (a,b : integer) return integer is
begin return a * b;end;
Packages are a common single way of disseminating type and function information in the VHDL design community. The basic definition of a package is as follows:
package name is
...package header contents
package body name is
... package body contents
end package body;
As can be seen, the package consists of two parts, the header and the body. The header is the place where the types and functions are declared, and the package body is where the declarations themselves take place.
For example, a function could be described in the package body and the function is declared in the package header. Take a simple example of a function used to car ry out a simple logic function:
and10 = and(a,b,c,d,e,f,g,h,i,j)
The VHDL function would be something like the following:
function and10 (a,b,c,d,e,f,g,h,i,j : bit) return bit is
return a and b and c and d and e and f
and g and h
and i and j;
The resulting package declaration would then use the function in the body and the function header in the package header thus:
package new_functions is
function and10 (a,b,c,d,e,f,g,h,i,j : bit) return bit;
package body new_functions is
function and10 (a,b,c,d,e,f,g,h,i,j : bit) return
return a and b and c and d and e and f and g and h and i and j; end;end;
While procedures, functions and packages are useful in including behavioral constr ucts generally, with VHDL being used in a hardware design context, often there is a need to encapsulate design blocks as a separate component that can be included in a design, usually higher in the system hierarchy.
The method for doing this in VHDL is called a COMPONENT. Caution needs to be exercised with components as the method of including components changed radically between VHDL 1987 and VHDL 1993, as such care needs to be taken to ensure that the cor rect language definitions are used consistently.
Components are a way of incorporating an existing VHDL entity and architecture into a new design without including the previously created model. The first step is to declare the component ñ in a similar way that functions need to be declared. For example, if an entity is called and4, and it has 4 inputs (a, b, c, d of type bit) and 1 output (q of type bit), then the component declaration would be of the for m shown below:
port ( a, b, c, d : in bit; q : out bit );
Then this component can be instantiated in a netlist for m in the VHDL model architecture:
d1 : and4 port map ( a, b, c, d, q );
Note that in this case, there is no explicit mapping between port names and the signals in the current level of VHDL, the pins are mapped in the same order as defined in the component declaration. If each pin is to be defined independent of the order of the pins, then the explicit port map definition needs to be used:
d1: and4 port map ( a => a, b => b, c => c, d => d, q => q);
The final thing to note is that this is called the default binding. The binding is the link between the compiled architecture in the current library and the component being used. It is possible, for example, to use different architectures for different instantiated components using the following statement for a single specific device:
for d1 : and4 use entity work.and4(behaviour) port map
or the following to specify a specific device for all the instantiated components:
for all : and4 use entity work.and4(behaviour) port
Procedures are similar to functions, except that they have more flexibility in the parameters, in that the direction can be in, out or inout. This is useful in comparison to functions where there is generally only a single output (although it may be an array) and avoids the need to create a record structure to manage the return value.
Although procedures are useful, they should be used only for small specific functions. Components should be used to par tition the design, not procedures, and this is especially true in FPGA design, as the injudicious use of procedures can lead to bloated and inefficient implementations, although the VHDL description can be very compact. A simple procedure to execute a full adder could be of the form:
procedure full_adder (a,b : in bit; sum, carry : out bit)
sum := a xor b;
carry := a and b;
Notice that the syntax is the same as that for variables (NOT signals), and that multiple outputs are defined without the need for a return statement.Debugging Models
In VHDL’s debugging models, assertions are used to check if cer tain conditions have been met in the model and are extremely useful in debugging models. Some examples:
assert value <= max_value
report “Value too large”;
assert clock_width >= 100 ns
report “clock width too small”
VHDL has the following standard types defined as built in data types including the following basic types such as BIT, BOOLEAN, BIT_VECTOR, INTEGER and REAL.
BIT. The BIT data type is the simple logic type built into VHDL. The type can have two legal values ‘0’ or ‘1’. The elements def ined as of type BIT can have the standard VHDL built in logic functions applied to them. Examples of signal and variable declarations of type BIT follow:
signal ina : bit;
variable inb : bit := ‘0’;
ina <= inb and inc;
ind <= ‘1’ after 10 ns;
BOOLEAN. The Boolean data type is primarily used for decision-making, so the test value for ‘if ’ statements is a Boolean type. The elements defined as of type Boolean can have the standard VHDL built in logic functions applied to them. Examples of signal and variable declarations of type Boolean follow:
signal test1 : Boolean;
variable test2 : Boolean := FALSE;
INTEGER. The basic numeric type in VHDL is the integer and is defined as an integer in the range 2147483647 to 2147483647. There are obviously implications for synthesis in the definition of integers in any VHDL model, particularly the effective number of bits, and so it is quite common to use a specif ied range of integer to constrain the values of the signals or variables to within physical bounds. Examples of integer usage follow:
signal int1 : integer;
variable int2 : integer := 124;
There are two subtypes (new types based on the fundamental type) derived from the integer type which are integer in nature, but simply define a different range of values, natural and positive.
The natural integer subtype is used to def ine all integers greater than and equal to zero. They are actually defined with respect to the high value of the integer range as follows:
natural values : 0 to integer’high
The positive integer subtype is used to define all integers greater than and equal to one. They are actually defined with respect to the high value of the integer range as follows:
positive values : 1 to integer’high
CHARACTER . In addition to the numeric types inherent in VHDL, there are also the complete set of ASCII characters available for designers. There is no automatic conversion between characters and a numeric value per se ; however, there is an implied ordering of the characters defined in the VHDL standard (IEEE Std 1076-1993). The characters can be def ined as individual characters or ar rays of characters to create strings. The best way to consider characters is an enumerated type.
REAL. Floating point numbers are used in VHDL to define real numbers and the predefined floating point type in VHDL is called real. This defines a floating point number in the range 1.0e38 to 10e38. This is an important issue for many FPGA designs, as most commercial synthesis products do not suppor t real numbers – precisely because they are floating point.
In practice, it is necessary to use integer or fixed point numbers which can be directly and simply synthesized into hardware. An example of defining real signals or variables is shown below:
signal realno : real;
variable realno : real := 123.456;
Time values and types
Time values are defined using the special time type. These not only include the time value, but also the unit – separated by a space. The basic range of the time type value is between 2147483647 and 2147483647, and the basic unit of time is def ined as the femto-second (fs ). Each subsequent time unit is derived from this basic unit of the fs as shown below:
ps = 1000 fs;
ns = 1000 ps;
us = 1000 ns;
ms = 1000 us;
min = 60 sec;
hr = 60 min;
Examples of time definitions are shown below:
delay : time := 10 ns;
wait for 20 us;
y <= x after 10 ms;
z <= y after delay;
The very brief introduction to VHDL so far in this series is certainly not a comprehensive reference. It enables the reader, hopefully, to have enough knowledge to understand the syntax of the examples in later parts in this series.
The author strongly recommends that anyone serious about design with VHDL should also obtain a detailed and comprehensive reference book on VHDL. Zwolinski’s book is a useful introduction to digital design with VHDL – a common student textbook, while Ashenden’s book is a more heavy duty VHDL reference that is perhaps more comprehensive, but less easy for a beginner to VHDL.
Used with permission from Newnes, a division of Elsevier.Copyright 2007, from “Design Recipies for FPGAs,” by Peter Wilson. For moreinformation about this title and other similar books, please visit www.elsevierdirect.com.
Dr. Peter Wilson has worked for many years as a seniordesign engineer in the electronics industry with Ferranti plc and as an EDAtechnical specialist with Analogy Inc. before joining the Department ofElectronics and Computer Science at the University of Southampton, U.K., wherehe is senior lecturer in Electronics. He is also a consultant in various aspectsof embedded systems design, including design and modeling with VHDL, Verilog,Verilog-AMS and VHDL-AMS.