Una cuestión sobre la que surgen muchas dudas al aprender VHDL es el uso de valores enteros (integer) frente a los vectores de bits clásicos o std_logic_vector.

Esto es debido a que un diseño digital trabaja internamente únicamente con bits, por lo que cualquier otro tipo de datos que utilicemos sera una abstracción que luego será traducida a vectores de bits. Es por tanto imprescindible comprender el significado de cada tipo de datos y saber cómo se realiza la conversión desde los mismos a bits y viceversa.

El tipo de datos básico en VHDL cómo muchos ya sabréis es el std_logic y el std_logic_vector que representan uno o varios bits. El significado que tendrán estos bits dependerá de nuestro diseño y de las librerías que utilicemos. Por ejemplo si utilizamos la librería ieee.numeric_std luego podremos declarar si los valores utilizamos son números con signo o sin signo de la siguiente forma:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity numeric_ejemplo is
  port (
    a     : in std_logic_vector(7 downto 0);
    b     : in std_logic_vector(7 downto 0)
    );
end numeric_ejemplo;
 
architecture rtl of numeric_ejemplo is
  signal suma : signed(7 downto 0)   := (others => '0');
  signal resta : unsigned(7 downto 0) := (others => '0');

En ciertas ocasiones no quedará más remedio que trabajar de esta forma, pero en otras, donde no tengamos que manipular a nivel de bit, podemos utilizar el tipo de datos integer para trabajar de manera más cómoda.

Por ejemplo en el caso de un contador donde simplemente declaramos un registro y le incrementamos en 1 en cada ciclo de reloj. En ese caso podemos declarar la señal de tipo integer y olvidarnos de los signos y su manejo.

Para declarar un tipo integer tenemos que definir el rango en el que está definido. Si no lo hacemos estaremos utilizando mas bits de los necesarios, que luego se traducirán en recursos malgastados dentro de la FPGA. La forma de declararlo es utilizar la palabra clave integer y el rango que vayamos a utilizar.

--Contador
signal contador : integer range 0 to 1024;
--Otro ejemplo 
signal cuenta : integer range -128 to 127; 

A la hora de definir los rangos hay que tener en cuenta que los datos se representarán internamente en complemento a dos.

Una vez definidos los datos ya podemos trabajar con ellos, sumarlos, incrementarlos, o lo que queramos. Eso si, para poder operar con ellos, deben estar definidos sobre el mismo rango, ya que si no nos dará un error el compilador y debemos usar una librería que nos permita manejarlo.

Sobre las librerías existe confusión, VHDL soporta la librería numeric_std y std_logic_arith . Es preferible utilizar siempre la librería numeric_std ya que la otra es proporcionada por un fabricante de software (Synopsys) para diseño electrónico y no es tan portable, aunque ambas funcionarán bien.

Si estamos trabajando con integer, muchas veces será necesario traducirlos al tipo base std_logic_vector o traducir desde el tipo base a integer. En ese caso VHDL proporciona en las librerías funciones de conversión, a través de la librería numeric_std.

 library ieee;
 use ieee.std_logic_1164.all;	
 use ieee.numeric_std.all;

...

  signal contador : std_logic_vector(7 downto 0);
begin
  -- Almacena el valor decimal 15 representado con 8 bits
  contador <= std_logic_vector(15,8);

O en el caso contrario:

 library ieee;
 use ieee.std_logic_1164.all;	-- standard unresolved logic UX01ZWLH-
 use ieee.numeric_std.all; 

...  

  signal entero : integer;
  signal vector_bits : std_logic_vector(4 downto 0);
begin
  vector_bits <= "1001";
  entero <= to_integer(unsigned(vector_bits)); 

En este último ejemplo podéis ver como al pasar el valor a entero, tenemos que indicar si el vector es un número con signo o sin él para poder interpretarlo correctamente.