FONT SIZE : AAA
Functions
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 (discussed in Part 2 of this book), but in this section 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 here:
1 function name (input declarations) return output_type is
2 −− variable declarations
3 begin
4 −− function body
5 end
For example, a simple function that takes two input numbers and multiplies them together could be defined as follows:
1 function mult (a,b : integer) return integer is
2 begin
3 return a ∗ b;
4 end;
Packages
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:
1 package name is
2 −− package header contents
3 end package;
4 package body name is
5 −− package body contents
6 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 carry out a simple logic function:
1 and10 = and(a,b,c,d,e,f,g,h,i,j)
The VHDL function would be something like the following:
1 function and10 (a,b,c,d,e,f,g,h,i,j : bit) return bit is
2 begin
3 return a and b and c and d and e and f and g and h and i and j;
4 end;
The resulting package declaration would then use the function in the body and the function
header in the package header thus:
1 package new_functions is
2 function and10 (a,b,c,d,e,f,g,h,i,j : bit) return bit;
3 end;
4
5 package body new_functions is
6 function and10 (a,b,c,d,e,f,g,h,i,j : bit) return bit is
7 begin
8 return a and b and c and d and e and f and g and h and i and j;
9 end;
10 end;
While procedures, functions, and packages are useful in including behavioral constructs 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 correct 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 four inputs (a,b,c,d of type bit) and one output (q of type bit), then the component declaration would be of the form shown here:
1 component and4
2 port ( a,b,c,d : in bit; q : out bit );
3 end component;
Then this component can be instantiated in a netlist form in the VHDL model architecture:
1 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 independently of the order of the pins, then the explicit port map definition needs to be used:
1 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:
1 for d1 : and4 use entity work.and4(behavior) port map ( a,b,c,d,q);
or the following to specify a specific device for all the instantiated components:
1 for all : and4 use entity work.and4(behavior) port map ( a,b,c,d,q);
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 partition 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:
1 procedure full_adder (a,b : in bit; sum, carry : out bit ) is
2 begin
3 sum := a xor b;
4 carry := a and b;
5 end;
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.
Manufacturer:Xilinx
Product Categories:
Lifecycle:Active Active
RoHS: -
Manufacturer:Xilinx
Product Categories: FPGAs (Field Programmable Gate Array)
Lifecycle:Active Active
RoHS: No RoHS
Manufacturer:Xilinx
Product Categories: FPGAs (Field Programmable Gate Array)
Lifecycle:Active Active
RoHS: No RoHS
Manufacturer:Xilinx
Product Categories: FPGAs (Field Programmable Gate Array)
Lifecycle:Active Active
RoHS: No RoHS
Manufacturer:Xilinx
Product Categories: FPGAs
Lifecycle:Active Active
RoHS: No RoHS
Support