# Programación en VHDL/Elementos básicos del lenguaje

Antes de comenzar es preciso conocer algunos elementos básicos del lenguaje VHDL.

## Comentarios

Los comentarios van precedidos de dos guiones. En una línea se ignorará todo aquello que vaya después de dos guiones seguidos. Ejemplo:

## Identificadores

Son cualquier cadena de caracteres que sirven para identificar variables, señales, procesos, etc. Puede ser cualquier nombre compuesto por letras (aux) o números y letras (aux1, aux2, aux3, ...), incluyendo el símbolo de subrayado "_". Las mayúsculas y minúsculas son consideradas iguales, por lo tanto los identificadores TMP y tmp representan el mismo elemento. No es posible crear un identificador que coincida con alguna palabra reservada del lenguaje.

## Números

Cualquier número se representa en base 10. Aunque es posible poner los números en otras bases utilizando diferentes símbolos, como se muestra en la siguiente sección.

### Bases

Para escribir un número se puede hacer en binario, octal, decimal y hexadecimal.
* Para vectores de bits:
** "01111" binario
** O"17" octal
** X"F" hexadecimal
* Para enteros y reales:
** 2#1100# binario
** 12 decimal
** 16#C# hexadecimal
l

## Tipos de datos

Como en cualquier lenguaje de programación existen varios tipos de datos, en VHDL se pueden diferenciar dos: escalares y compuestos.

### Tipos escalares

Son tipos simples que contienen algún tipo de magnitud.
* Enteros: Son datos con un valor numérico entero. La forma de definirlos es con la palabra RANGE. Realmente se dice que un número está en un límite establecido.
* Físicos: Se trata de datos que corresponden con magnitudes físicas, que tienen un valor y unas unidades.
* Reales o coma flotante: Se definen igual que los enteros con la diferencia que los límites son números reales.
* Enumerados: Son datos que puede tomar siempre que se encuentre en una lista o conjunto finito. Es idéntico a las enumeraciones en C (enum).

### Tipos compuestos

Son tipos de datos compuestos por los que se han visto anteriormente.
* Matrices: Se trata de un conjunto de elementos del mismo tipo, accesibles mediante un índice. Los hay de dos tipos: monodimensionales o multidimensionales.
En este punto es necesario explicar la palabra reservada OTHERS, donde es posible asignar un determinado valor a todos los elementos de la matriz.
Las palabras reservadas TO y DOWNTO sirven para indicar los índices de una matriz. El primero indica un rango ascendente (de x a y), mientras que el segundo es descendente (desde x hasta y).
Dependiendo de la opción elegida el bit más significativo corresponderá al primer bit (0) o al último (31). También es posible obtener un trozo de una matriz para poder realizar operaciones con ella.
Además, es posible asignar a una matriz una lista separada por comas, de forma que el primer elemento de la lista corresponde al primero de la matriz.
* Registros: Es equivalente al tipo record de otros lenguajes.
Para acceder a algún atributo del registro se utilizará el punto.

### Subtipos de datos

En VHDL se pueden definir subtipos, los cuales corresponden a tipos ya existentes. Se pueden diferenciar dos tipos dependiendo de las restricciones que se apliquen.
* Restricciones de un tipo escalar a un rango:
* Restricciones del rango de una matriz:
La ventaja de utilizar subtipos se basa a la hora de sintetizar un circuito, ya que si se utiliza el propio tipo, como puede ser el integer, se interpretará como un bus de 32 líneas, pero realmente sólo harán falta muchas menos.

### Conversión de tipos

En ocasiones puede ser necesario convertir unos tipos a otros, esta operación es conocida como casting. Algunas de las conversiones son automáticas, como puede ser el paso de entero a real, otras conversiones deben realizarse de forma explícita, indicando el nombre del tipo al que se quiere pasar seguido del valor entre paréntesis.
En muchos diseños es necesario realizar conversiones entre bits y enteros. A continuación se muestran varias funciones de conversión entre ambos tipos.

## Constantes, señales y variables

En VHDL existen tres tipos de elementos: señales, constantes y variables. Estas dos últimas tienen un significado similar a cualquier otro lenguaje de programación.
Todos estos elementos son diferentes. Las variables sólo tienen sentido dentro de los procesos o subprogramas, mientras que las señales pueden ser declaradas en arquitecturas, paquetes o bloques concurrentes. Las constantes pueden ser declaradas en los mismos sitios que las variables y señales.

### Constantes

Es un elemento que se inicializa con un valor determinado, el cual no puede ser modificado, es decir siempre conserva el mismo valor. Esto se realiza con la palabra reservada CONSTANT.
También es posible no asociar un valor a una constante, siempre que el valor sea declarado en otro sitio.

### Variables

Es lo mismo que una constante, pero con la diferencia que puede ser modificada en cualquier instante, aunque también es posible inicializarlas. La palabra reservada VARIABLE es la que permite declarar variables.
Es posible, dado un elemento cambiarle el nombre o ponerle nombre a una parte mediante la palabra reservada ALIAS.

### Señales

Las señales se declaran con la palabra reservada SIGNAL, a diferencia con las anteriores este tipo de elementos pueden ser de varios tipos: normal, register o bus. Es posible asignarles un valor inicial.

## Atributos

Los elementos como señales y variables pueden tener atributos, éstos se indican a continuación del nombre, separados con una comilla simple " ' " y pueden incluir información adicional de algunos objetos desarrollados en VHDL, que servirán a las herramientas de diseño para obtener información a la hora de realizar una síntesis.
Existen muchos atributos, como LEFT, RIGHT, LOW, HIGH, RANGE, LENGTH... Pero el atributo más usado es EVENT, que indica si una señal ha cambiado de valor. Por ejemplo la siguiente sentencia captura un flanco de subida de una señal (clk).

### Definición de atributos

Un atributo definido por el diseñador siempre devolverá un valor constante. En primer lugar se debe declarar el atributo, mediante la palabra reservada ATTRIBUTE, indicando el tipo de elemento que se devuelve, seguidos el valor que se retornará. La sintaxís para definir atributos sería la siguiente.
Donde nombre es el identificador del atributo, id_elemento corresponde al identificador de un elemento del lenguaje definido previamente (señal, variable, etc.), la clase es el tipo de elemento al que se le va añadir dicho atributo, es decir si es señal, constante, etc. y el valor será lo que devuelva al preguntar por dicho atributo. Un ejemplo de todo esto puede ser el siguiente.

## Operadores

Los operadores que proporciona el lenguaje son:
* Lógicos: Actúan sobre los tipos bit, bit_vector y boolean. En el caso de utilizar este tipo de operadores en un vector, la operación se realizará bit a bit.
Operadores: AND, OR, NAND, NOR, XOR, XNOR y NOT.
* Aritméticos:
** + (suma o signo positivo): Sirve para indicar una suma entre dos números. También puede actuar como símbolo si se sitúa delante de una expresión.
** - (resta o signo negativo): Sirve para indicar la resta entre dos números. Si va delante de una expresión modifica el signo de la expresión.
** * (multiplicación): Multiplica dos números de cualquier tipo.
** / (división): Divide dos números de cualquier tipo.
** ** (exponencial): Eleva un número a una potencia. El número de la izquierda puede ser entero y real, pero el de la derecha sólo puede ser entero. Ejemplo: 4**2 sería 4².
** ABS (valor absoluto): Devuelve el valor absoluto de su argumento.
** MOD (módulo): Calcula el módulo de dos números.
** REM (resto): Calcula el resto de la división.
* Relacionales: Siempre devuelven un valor booleano (true o false).
** ==, /= (igualdad): El primero devuelve verdadero si los operando son iguales y falso en caso contrario. El segundo indica desigualdad, funcionando al revés que el anterior.
** >, >=, <, <= (menor mayor): Poseen el significado habitual (mayor que, mayor o igual que, menor que, menor o igual que, respectivamente). La diferencia con los anteriores reside en su uso, en este caso los tipos de datos que pueden manejar son siempre de tipo escalar o matrices.
* Desplazamientos: (incluidas en la revisión de 1993)
** SLL (Shift Left Logic) y SRL (Shift Right Logic), desplazamiento lógico a la izquierda y desplazamiento lógico a la derecha, respectivamente, rellenando de ceros los huecos.
** SLA (Shift Left Arithmetic) y SRA (Shift Right Arithmetic), desplazamiento aritmético a la izquierda y derecha respectivamente.
** ROL (ROtate Left) y ROR (ROtate Right), rotación a la izquierda y a la derecha respectivamente. En este caso los huecos son ocupados por los bits que van quedando fuera.
A continuación se muestran ejemplos sobre los operadores de desplazamiento:
* Otros:
** & (concatenación): Concatena vectores de manera que la dimensión de la matriz resultante es la suma de las dimensiones de las matrices con las que se opera.
Hay que decir que no todos los operadores pueden funcionar sobre todos los tipos de datos. También hay operadores que en determinadas circunstancias no pueden ser utilizados, por ejemplo al hacer código sintetizable no es recomendable usar multiplicadores (excepto si uno de los operadores es potencia de dos, puesto que se trataría de un simple desplazamiento de bits).
El orden de preferencia, de mayor a menor es:
* **, ABS, NOT
* *, /, MOD, REM
* +, - (signo)
* +, -, & (operaciones)
* AND, OR, NAND, NOR, XOR