ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 13.06.2025

Просмотров: 3483

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Functions and Procedures

265

10y: OUT UNSIGNED(2*size-1 DOWNTO 0));

11END multiplier;

12 ---------------------------------------------

13 ARCHITECTURE behavior OF multiplier IS

14BEGIN

15y <= mult(a,b);

16END behavior;

17 ---------------------------------------------------------

11.3PROCEDURE

A PROCEDURE is very similar to a FUNCTION and has the same basic purposes. However, a procedure can return more than one value.

Like a FUNCTION, two parts are necessary to construct and use a PROCEDURE: the procedure itself (procedure body) and a procedure call.

Procedure Body

PROCEDURE procedure_name [<parameter list>] IS [declarations]

BEGIN

(sequential statements) END procedure_name;

In the syntax above, <parameter list> specifies the procedure’s input and output parameters; that is:

3parameter list4 ¼ [CONSTANT] constant_name: mode type;

3parameter list4 ¼ SIGNAL signal_name: mode type; or

3parameter list4 ¼ VARIABLE variable_name: mode type;

A PROCEDURE can have any number of IN, OUT, or INOUT parameters, which can be SIGNALS, VARIABLES, or CONSTANTS. For input signals (mode IN), the default is CONSTANT, whereas for output signals (mode OUT or INOUT) the default is VARIABLE.

As seen before, WAIT, SIGNAL declarations, and COMPONENTS are not synthesizable when used in a FUNCTION. The same is true for a PROCEDURE, with

TLFeBOOK

266

Chapter 11

the exception that a SIGNAL can be declared, but then the PROCEDURE must be declared in a PROCESS. Moreover, besides WAIT, any other edge detection is also not synthesizable with a PROCEDURE (that is, contrary to a function, a synthesizable procedure should not infer registers).

In section 11.5, a summary comparing FUNCTIONS and PROCEDURES will be presented.

Example: The PROCEDURE below has three inputs, a, b, and c (mode IN). a is a CONSTANT of type BIT, while b and c are SIGNALS, also of type BIT. Notice that the word CONSTANT can be omitted for input parameters, for it is the default object (recall, however, that for outputs the default object is VARIABLE). There are also two return signals, x (mode OUT, type BIT_VECTOR) and y (mode INOUT, type INTEGER).

PROCEDURE my_procedure ( a: IN BIT; SIGNAL b, c: IN BIT; SIGNAL x: OUT BIT_VECTOR(7 DOWNTO 0);

SIGNAL y: INOUT INTEGER RANGE 0 TO 99) IS

BEGIN

...

END my_procedure;

Procedure Call

Contrary to a FUNCTION, which is called as part of an expression, a PROCEDURE call is a statement on its own. It can appear by itself or associated to a statement (either concurrent or sequential).

Examples of procedure calls:

compute_min_max(in1, in2, 1n3, out1, out2); -- statement by itself

divide(dividend, divisor, quotient, remainder); -- statement by itself

IF (a>b) THEN compute_min_max(in1, in2, 1n3, out1, out2);

--procedure call associated to another statement

11.4Procedure Location

The typical locations of a PROCEDURE are the same as those of a FUNCTION (see figure 11.1). Again, though it is usually placed in a PACKAGE (for code parti-

TLFeBOOK


Functions and Procedures

267

inp1

min_out

min_max

inp2

max_out

ena

Figure 11.5

min_max circuit of example 11.9.

Figure 11.6

Simulation results of example 11.9.

tioning, code reuse, and code sharing purposes), it can also be located in the main code (either in the ENTITY or in the declarative part of the ARCHITECTURE). When placed in a PACKAGE, a PACKAGE BODY is then necessary, which must contain the body of each PROCEDURE declared in the declarative part of the PACKAGE. Examples of both cases are shown below.

Example 11.9: PROCEDURE Located in the Main Code

The min_max code below makes use of a PROCEDURE called sort. It takes two 8-bit unsigned integers as inputs (inp1, inp2), sorts them, then outputs the smaller value at min_out and the higher value at max_out (figure 11.5). The PROCEDURE is located in the declarative part of the ARCHITECTURE (main code). Notice that the PROCEDURE call, sort(inp1,inp2,min_out,max_out), is a statement on its own. Simulation results are shown in figure 11.6.

1 ------------------------------------------------------

2LIBRARY ieee;

3 USE ieee.std_logic_1164.all;

TLFeBOOK

268

Chapter 11

4 ------------------------------------------------------

5ENTITY min_max IS

6 GENERIC (limit : INTEGER := 255);

7PORT ( ena: IN BIT;

8inp1, inp2: IN INTEGER RANGE 0 TO limit;

9

min_out, max_out: OUT INTEGER RANGE 0 TO limit);

10

END min_max;

11

------------------------------------------------------

12

ARCHITECTURE

my_architecture OF min_max IS

13

--------------------------

14PROCEDURE sort (SIGNAL in1, in2: IN INTEGER RANGE 0 TO limit;

15SIGNAL min, max: OUT INTEGER RANGE 0 TO limit) IS

16BEGIN

17IF (in1 > in2) THEN

18max <= in1;

19min <= in2;

20ELSE

21max <= in2;

22min <= in1;

23END IF;

24END sort;

25 --------------------------

26BEGIN

27PROCESS (ena)

28BEGIN

29IF (ena='1') THEN sort (inp1, inp2, min_out, max_out);

30END IF;

31END PROCESS;

32END my_architecture;

33 ------------------------------------------------------

Example 11.10: PROCEDURE Located in a PACKAGE

This example is similar to example 11.9, with the only di¤erence being that now the PROCEDURE (called sort) is placed in a PACKAGE (called my_ package). Thus the PROCEDURE can now be reused and shared with other designs. The code below can be compiled as two separate files, or can be compiled as a single file (called min_max.vhd, which is the ENTITY’s name).

TLFeBOOK


Functions and Procedures

269

1 ------------

Package: ---------------------------

2LIBRARY ieee;

3

USE ieee.std_logic_1164.all;

4

-------------------------------------

5PACKAGE my_package IS

6CONSTANT limit: INTEGER := 255;

7 PROCEDURE sort (SIGNAL in1, in2: IN INTEGER RANGE 0 TO limit; 8 SIGNAL min, max: OUT INTEGER RANGE 0 TO limit);

9 END my_package;

10 -------------------------------------

11 PACKAGE BODY my_package IS

12PROCEDURE sort (SIGNAL in1, in2: IN INTEGER RANGE 0 TO limit;

13SIGNAL min, max: OUT INTEGER RANGE 0 TO limit) IS

14BEGIN

15IF (in1 > in2) THEN

16max <= in1;

17min <= in2;

18ELSE

19max <= in2;

20min <= in1;

21END IF;

22END sort;

23END my_package;

24

-------------------------------------------------

1 ---------

Main code: ----------------------------

2LIBRARY ieee;

3 USE ieee.std_logic_1164.all;

4 USE work.my_package.all;

5 -------------------------------------

6ENTITY min_max IS

7 GENERIC (limit: INTEGER := 255);

8PORT ( ena: IN BIT;

9

inp1, inp2: IN INTEGER RANGE 0 TO limit;

10min_out, max_out: OUT INTEGER RANGE 0 TO limit);

11END min_max;

12 -------------------------------------

TLFeBOOK

270

Chapter 11

13 ARCHITECTURE my_architecture OF min_max IS

14BEGIN

15PROCESS (ena)

16BEGIN

17IF (ena='1') THEN sort (inp1, inp2, min_out, max_out);

18END IF;

19END PROCESS;

20END my_architecture;

21----------------------------------------------

The simulation results are obviously the same as those of example 11.9 (figure 11.6).

11.5FUNCTION versus PROCEDURE Summary

A FUNCTION has zero or more input parameters and a single return value. The input parameters can only be CONSTANTS (default) or SIGNALS (VARIABLES are not allowed).

A PROCEDURE can have any number of IN, OUT, and INOUT parameters, which can be SIGNALS, VARIABLES, or CONSTANTS. For input parameters (mode IN) the default is CONSTANT, whereas for output parameters (mode OUT or INOUT) the default is VARIABLE.

A FUNCTION is called as part of an expression, while a PROCEDURE is a statement on its own.

In both, WAIT and COMPONENTS are not synthesizable.

The possible locations of FUNCTIONS and PROCEDURES are the same (figure 11.1). Though they are usually placed in PACKAGES (for code partitioning, code sharing, and code reuse purposes), they can also be located in the main code (either inside the ARCHITECTURE or inside the ENTITY). When placed in a PACKAGE, then a PACKAGE BODY is necessary, which should contain the body of each FUNCTION and/or PROCEDURE declared in the PACKAGE.

11.6ASSERT

ASSERT is a non-synthesizable statement whose purpose is to write out messages (on the screen, for example) when problems are found during simulation. Depending

TLFeBOOK


Functions and Procedures

271

on the severity of the problem, the simulator is instructed to halt. Its syntax is the following:

ASSERT condition [REPORT "message"]

[SEVERITY severity_level];

The severity level can be: Note, Warning, Error (default), or Failure. The message is written when the condition is FALSE.

Example: Say that we have written a function to add two binary numbers (like in example 11.6), where it was assumed that the input parameters must have the same number of bits. In order to check such an assumption, the following ASSERT statement could be included in the function body:

ASSERT a'LENGTH = b'LENGTH

REPORT "Error: vectors do not have same length!"

SEVERITY failure;

Again, ASSERT does not generate hardware. Synthesis tools will simply ignore it or give a warning.

11.7Problems

The purpose of the problems proposed in this section is to reinforce the main aspects related to the construction and use of subprograms (FUNCTIONS and PROCEDURES).

Problem 11.1: Conversion to std_logic_vector

Write a function capable of converting an INTEGER to a STD_LOGIC_VECTOR value. Call it conv_std_logic( ). Then write an application example, containing a call to your function, in order to test it. Construct two solutions: one with the function in the main code itself, and one with it in a package.

Problem 11.2: Overloaded ‘‘not’’ Operator

The NOT operator allows the inversion of binary values. For example, if x ¼ ‘‘1000’’ is a STD_LOGIC_VECTOR value, then NOT x could be used, producing ‘‘0111’’.

TLFeBOOK

272

Chapter 11

However, if x had been declared as an INTEGER, such operation would not be allowed. Write a ‘‘not’’ function capable of inverting integers. (Suggestion: See section 4.4 and example 11.6.)

Problem 11.3: Logic Shift of std_logic_vector

The pre-defined shift operators (specified in VHDL93, section 4.1) work only with type BIT_VECTOR. Write a function capable of logically shifting a STD_LOGC_ VECTOR signal to the left by a specified amount. Two arguments must be passed to the function: the value to be shifted (STD_LOGIC_VECTOR), plus a NATURAL value specifying the amount of shift. Place your function in a package. Then write an application with a call to your function in order to test it (suggestion: review example 11.7).

Problem 11.4: Logic Shift of an Integer

This problem is an extension of problem 11.3. Write a function capable of shifting an INTEGER value to the left by an specified amount. Place your function in a package. Then write an application with a call to your function in order to test it.

Problem 11.5: Signed Multiplier

Write a function similar to that of example 11.8. However, it should now operate with SIGNED input and output values.

Problem 11.6: Two-digit Counter with SSD Output

In example 6.7, a progressive 2-digit decimal counter (0 ! 99 ! 0), with external asynchronous reset plus binary-coded decimal (BCD) to seven-segment display (SSD) conversion, was designed. In it, a routine to convert a signal from BCD to SSD format was used twice. This kind of repetition can be avoided with a FUNCTION. Write a function (call it bcd_to_ssd) capable of making such a conversion and place it in a PACKAGE. Then redo the design of example 6.7, using a call to your function whenever such conversion is needed. Then synthesize and test your solution.

Problem 11.7: Statistical Procedure

Write a PROCEDURE that receives eight signed values and returns their average, the largest value, and the lowest value. Call the return values ave, max, and min. Place your procedure in a package. Then write an application with a call to it in order to test its functionality.

TLFeBOOK


Functions and Procedures

273

Problem 11.8: Overloaded ‘‘B’’ Operator

In example 11.6, a function that overloads the ‘‘þ’’ (addition) operator was presented. Its purpose was to allow the direct addition of STD_LOGIC_VECTOR values. In that example, the return parameter had the same number of bits as the two input parameters. Write a similar function, but with the return vector having one extra bit corresponding to the carry out bit such that overflow can then be easily detected.

TLFeBOOK

TLFeBOOK