2.7. Procedimientos y funciones

En los lenguajes de programación estructurados, como es el caso del C, es posible separar porciones de código y colocarlas dentro de funciones. Esto permite evitar repeticiones innecesarias y obtener un código más simple de mantener.

En VHDL existen conceptos equivalentes. El lenguaje define dos tipos de elementos, las funciones (function) y los procedimientos (procedure), llamados subprogramas. La principal diferencia entre ellos es que los primeros retornan un valor y los segundos no. Podemos comparar a los procedimientos como funciones de C definidas con valor de retorno void. Decimos que se trata de un concepto equivalente ya que hay diferencias importantes entre una función de C y un subprograma de VHDL. Lo primero que debemos comprender es que pueden ser sintetizables, por lo tanto no existen llamados a función en un circuito, no se trata de algo secuencial. Como consecuencia su implementación es comparable a lo que normalmente se conoce como macro.

En el curso ya se han utilizado funciones, tal es el caso de rising_edge o to_integer, pero en ningún caso se mostró como definirlas o se explicó sus limitaciones. Es el objetivo de esta sección explicar las nociones básicas para que sea posible comprender algunos ejemplos de funciones que usaremos en los ejemplos.

Los subprogramas se declaran en la arquitectura, antes del begin. Cabe destacar que, al igual que el caso del component, es más práctico declararlas en un paquete (package). De esta manera es más simple utilizarlas, esto es lo que hacemos con las funciones como rising_edge. Pero este concepto aún no ha sido explicado, por lo que las veremos declaradas en la arquitectura.

La forma básica que toman los subprogramas se puede observar en el Ejemplo 2-8. En el caso de las funciones se debe especificar el tipo de datos que retornan (por ejemplo: integer). Las mismas deben incluir una o más sentencias return que deben retornar un valor del tipo especificado.

Ejemplo 2-8. Sintaxis básica para funciones y procedimientos

procedure NOMBRE_PROCEDIMIENTO(LISTADO_ARGUMENTOS) is
   -- Declaraciones de variables, constantes, etc.
begin
   -- Cuerpo del procedimiento
end procedure NOMBRE_PROCEDIMIENTO;

function NOMBRE_FUNCION(LISTADO_ARGUMENTOS) return TIPO is
   -- Declaraciones de variables, constantes, etc.
begin
   -- Cuerpo de la función
   return EXPRESIÓN;
end function NOMBRE_FUNCION;

Se puede invocar un procedimiento o función tanto desde un proceso implícito como desde un proceso explícito. Sólo tenemos que tener el cuenta que su funcionamiento es más similar al que esperaríamos de un macro, es decir que debe poder resolverse en el momento de su análisis, y que no existirá en nuestro circuito nada parecido a un llamado a función.

2.7.1. Declaración de argumentos

La lista de argumentos usa el punto y coma como separador, se parece bastante a un listado de puertos de una entidad.

Los argumentos tienen asociados una clase y un modo. Como referencia tengamos en cuenta que en una declaración de puertos la clase es signal y el modo puede ser in, out, inout, etc. En este caso las posibles clases son constant, variable, signal y file. A su vez, los posibles modos son in, out e inout. No todas las combinaciones son válidas. En el Ejemplo 2-9 se muestra la forma genérica que toma la declaración de un argumento y algunos ejemplos posibles. Es posible omitir tanto la clase como el modo, lo que se asume depende mucho del contexto.

Ejemplo 2-9. Sintaxis básica para los argumentos

[CLASE] NOMBRE_DEL_ARGUMENTO : [MODO] TIPO
signal entrada : in std_logic
variable salida : out integer

La clase limitará el tipo de elemento que podremos usar al invocar la función o procedimiento. Al mismo tiempo indicará el mecanismo de uso dentro de nuestro subprograma. Esto significa que si declaramos un argumento como signal sólo podremos usar una señal para ese argumento, por otro lado una asignación será hecha con <=.

El modo indicará si el valor será leído, escrito o leído y escrito por el subprograma. En el caso de los file no hay modo asociado. Por defecto se asume el modo in. En el caso de las funciones sólo se puede utilizar el modo in, y como el mismo es el valor por defecto se puede omitir por completo en estos casos.

Cuando el modo es in (explícita o implícitamente) y se omite la clase, se asume que la misma es constant. Por otro lado, si el modo es out o inout y se omite la clase, se asume que es variable. En el Ejemplo 2-10 se muestran algunos ejemplos en los que se ha omitido la clase y/o el tipo.

Ejemplo 2-10. Declaraciones de argumentos omitiendo la clase y/o el modo

entrada : in std_logic     -- equivale a constant entrada : in std_logic
entrada : std_logic        -- equivale a constant entrada : in std_logic
signal entrada : std_logic -- equivale a signal entrada   : in std_logic
salida  : out integer      -- equivale a variable salida  : out integer
Copyright © 2011 UTN FRBA - INTI - Ing. Salvador E. Tropea