VHDL

Introducción al lenguaje para programación y modelado de circuitos

Lenguajes de Descripción de Hardware

Los lenguajes de descripción de hardware (HDLs) son utilizados para describir la arquitectura y comportamiento de un sistema electrónico los cuales fueron desarrollados para trabajar con diseños complejos. Comparando un HDL con los lenguajes para el desarrollo de software vemos que en un lenguaje de este tipo un programa que se encuentra en un lenguaje de alto nivel (VHDL) necesita ser ensamblado a código máquina (compuertas y conexiones) para poder ser interpretado por el procesador. De igual manera, el objetivo de un HDL es describir un circuito mediante un conjunto de instrucciones de alto nivel de abstracción para que el programa de síntesis genere (ensamble) un circuito que pueda ser implementado físicamente.


VHDL

História

En los últimos diez años la industria electrónica ha tenido una gran evolución en el desarrollo de sistemas digitales; desde computadoras personales, sistemas de audio y vídeo hasta dispositivos de alta velocidad para las comunicaciones. Esto ha sido posible gracias a la implementación de herramientas de diseño asistidos por computadora, conocidas como herramientas CAD (Computer Aided Design), aunque específicamente se hace uso de herramientas EDA (Electronic Design Automation), que es el nombre que se le da a todas las herramientas CAD para el diseño de sistemas electrónicos. Además de facilitar el trabajo, el uso de herramientas EDA también aceleró los procesos de diseño. Esta situación condujo a adoptar nuevas metodologías para el diseño y evaluación de los circuitos electrónicos. El uso de las herramientas EDA junto con los dispositivos lógicos programables, que pueden ser utilizados en diferentes aplicaciones e inclusive reprogramados, cambiaron bastante el concepto de diseño de circuitos digitales.

VHDL es un lenguaje que se creó para el diseño, modelado y documentación de circuitos complejos. Actualmente se le utiliza para la síntesis de circuitos digitales utilizando dispositivos lógicos programables. Es así como los dispositivos lógicos programables y VHDL, Very High Speed Integrated Circuit (VHSIC) Hardware Description Language, constituyen los elementos fundamentales para estas nuevas metodologías de diseño.

VHDL es un lenguaje con una sintaxis amplia y flexible que permite el modelado estructural, en flujo de datos y de comportamiento hardware. VHDL permite el modelado preciso, en distintos estilos, del comportamiento de un sistema digital conocido y el desarrollo de modelos de simulación. Uno de los objetivos del lenguaje VHDL es el modelado. Modelado es el desarrollo de un modelo para simulación de un circuito o sistema previamente implementado cuyo comportamiento, por tanto, se conoce. El objetivo del modelado es la simulación.

Otro de los usos de este lenguaje es la síntesis automática de circuitos. En el proceso de síntesis, se parte de una especificación de entrada con un determinado nivel de abstracción, y se llega a una implementación mas detallada, menos abstracta. Por tanto, la síntesis es una tarea vertical entre niveles de abstracción, del nivel mas alto en la jerarquía de diseño se va hacia el más bajo nivel de la jerarquía.

El VHDL es un lenguaje que fue diseñado inicialmente para ser usado en el modelado de sistemas digitales. Es por esta razón que su utilización en síntesis no es inmediata, aunque lo cierto es que la sofisticación de las actuales herramientas de síntesis es tal que permiten implementar diseños especificados en un alto nivel de abstracción. La síntesis a partir de VHDL constituye hoy en día una de las principales aplicaciones del lenguaje con una gran demanda de uso. Las herramientas de síntesis basadas en el lenguaje permiten en la actualidad ganancias importantes en la productividad de diseño.



Ventajas del uso de VHDL para la descripción de hardware:

  • VHDL permite diseñar, modelar, y comprobar un sistema desde un alto nivel de abstracción bajando hasta el nivel de definición estructural de compuertas.
  • Circuitos descritos utilizando VHDL, siguiendo unas guías para síntesis, pueden ser utilizados por herramientas de síntesis para crear implementaciones de diseños a nivel de compuertas.
  • Al estar basado en un estándar (IEEE Std 1076-1987) los ingenieros de toda la industria de diseño pueden usar este lenguaje para minimizar errores de comunicación y problemas de compatibilidad.
  • VHDL permite diseño Top-Down, esto es, permite describir (modelado) el comportamiento de los bloques de alto nivel, analizándolos (simulación), y refinar la funcionalidad de alto nivel requerida antes de llegar a niveles mas bajos de abstracción de la implementación del diseño.
  • Modularidad: VHDL permite dividir o descomponer un diseño hardware y su descripción VHDL en unidades más pequeñas.

Un proyecto de VHDL puede contener muchos ficheros. El código VHDL usualmente se encuentra en los ficheros con extensión *.vhd. La estructura típica de uno de estos ficheros es:

  • Llamadas a librerías.
  • Entidad.
  • Arquitectura(s).


VHDL describe estructura y comportamiento

Existen dos formas de describir un circuito; por un lado se puede describir un circuito indicando los diferentes componentes que lo forman y su interconexión, de esta manera tenemos especificado un circuito y sabemos como funciona; esta es la forma habitual en que se han venido describiendo circuitos y las herramientas utilizadas para ello han sido las de captura de esquemas y las descripciones netlist.

La segunda forma consiste en describir un circuito indicando lo que hace o como funciona, es decir, describiendo su comportamiento. Naturalmente esta forma de describir un circuito es mucho mejor para un diseñador puesto que lo que realmente interesa es el funcionamiento del circuito más que sus componentes. Por otro lado, al encontrarse lejos de lo que un circuito es realmente puede plantear algunos problemas a la hora de realizar un circuito a partir de la descripción de su comportamiento. El VHDL va a ser interesante ya que va a permitir los dos tipos de descripciones:


  • Estructura: VHDL puede ser usado como un lenguaje de Netlist normal y corriente donde se especifican por un lado los componentes del sistema y por otro sus interconexiones.
  • Comportamiento: VHDL también se puede utilizar para la descripción comportamental o funcional de un circuito. Esto es lo que lo distingue de un lenguaje de Netlist. Sin necesidad de conocer la estructura interna de un circuito es posible describirlo explicando su funcionalidad. Esto es especialmente util en simulación ya que permite simular un sistema sin conocer su estructura interna, pero este tipo de descripción se esta volviendo cada día mas importante porque las actuales herramientas de síntesis permiten la creación automática de circuitos a partir de una descripción de su funcionamiento.


Ejemplo básico de descripción VHDL

Ejemplo: Describir en VHDL un circuito que multiplexe dos líneas (a y b) de un bit, a una sola línea (salida) también de un bit; la señal selec sirve para indicar que a la salida se tiene la línea a (selec='0') o b (selec='1').

En la figura 1 se muestra el circuito implementado con compuertas lógicas que realiza la función de multiplexación. Lo que se va a realizar a continuación es la descripción comportamental del circuito de la figura 1, y luego se realizara la descripción estructural para ver las diferencias. La sintaxis del VHDL no es sensible a mayúsculas o minúsculas por lo que se puede escribir como se prefiera.

Figura 1. Esquema del ejemplo básico en VHDL.


En primer lugar, sea el tipo de descripción que sea, hay que definir el símbolo o entidad del circuito. En efecto, lo primero es definir las entradas y salidas del circuito, es decir, la caja negra que lo define. Se le llama entidad porque en la sintaxis de VHDL esta parte se declara con la palabra clave ENTITY. Esta definición de entidad, que suele ser la primera parte de toda descripción VHDL, se expone a continuación:

-- Los comentarios empiezan por dos guiones
ENTITY mux IS
PORT ( a: IN bit;
b: IN bit;
selec: IN bit;
salida: OUT bit);
END mux;


Esta porción del lenguaje indica que la entidad mux (que es el nombre que se le ha dado al circuito) tiene tres entradas de tipo bit, y una salida también del tipo bit. Los tipos de las entradas y salidas se verán mas adelante. El tipo bit simplemente indica una línea que puede tomar los valores '0' y '1'. La entidad de un circuito es única, sin embargo, se mostró que un mismo símbolo, en este caso entidad, podrá tener varias vistas o en el caso de VHDL arquitecturas. Cada bloque de arquitectura, que es donde se describe el circuito, puede ser una representación diferente del mismo circuito. Por ejemplo, puede haber una descripción estructural y otra comportamental, ambas son descripciones diferentes, pero ambas descripciones corresponden al mismo circuito, símbolo, o entidad. Veamos entonces la descripción comportamental:

ARCHITECTURE comportamental OF mux IS
BEGIN
PROCESS (a,b,selec)
BEGIN
IF (selec='0') THEN
salida<=a; ELSE salida<=b; END IF; END PROCESS; END comportamental;


Mas adelante se vera lo que hace un bloque PROCESS, de momento, y como primera aproximación, se considerara que es una especie de subrutina cuyas instrucciones se ejecutan secuencialmente cada vez que algunas de las señales de la lista sensible cambia. Esta lista sensible es una lista de señales que se suele poner junto a la palabra clave PROCESS, y en el caso del ejemplo es (a,b,selec).

Esta descripción comportamental es muy sencilla de entender ya que sigue una estructura parecida a los lenguajes de programación convencionales. Lo que se esta indicando es simplemente que si la señal selec es cero, entonces la salida es la entrada a, y si selec es uno, entonces la salida es la entrada b. Esta forma tan sencilla de describir el circuito permite a ciertas herramientas sintetizar un circuito a partir de una descripción comportamental como esta. La diferencia con un Netlist es directa: en una descripción comportamental no se están indicando ni los componentes ni sus interconexiones, sino simplemente lo que hace, es decir, su comportamiento o funcionamiento. La descripción anterior era puramente comportamental, de manera que con una secuencia sencilla de instrucciones podamos definir el circuito. Naturalmente, a veces resulta mas interesante describir el circuito de forma que este mas cercano a una posible realización física del mismo. En ese sentido VHDL posee una forma de describir circuitos que además permite la paralelización de instrucciones y que se encuentra mas cercana a una descripción estructural del mismo. A continuación se muestran dos ejemplos de una descripción concurrente o tambien llamada de transferencia entre registros:

/----(1)----/
ARCHITECTURE transferencia OF mux IS
SIGNAL nosel,ax,bx:bit;
BEGIN
nosel<=NOT selec; ax<=a AND nosel; bx<=b AND selec; salida<=ax OR bx; END transferencia; /----(2)----/ ARCHITECTURE transferencia OF mux IS BEGIN salida<=a WHEN selec='0' ELSE b; END transferencia;


En la descripción (1) hay varias instrucciones, todas ellas concurrentes, es decir, se ejecutan cada vez que cambia alguna de las señales que intervienen en la asignación. Este primer caso es casi una descripción estructural ya que de alguna manera se están definiendo las señales (cables) y los componentes que la definen, aunque no es comportamental ya que en realidad se trata de asignaciones a señales y no una descripción de componentes y conexiones. El segundo caso (2) es tambien una descripción de transferencia aunque basta una unica instrucción de asignación para definir el circuito.

Aunque no es la caracteristica más interesante del VHDL, tambien permite ser usado como Netlist o lenguaje de descripción de estructura. En este caso, esta estructura tambien estará indicada dentro de un bloque de arquitectura, aunque la sintaxis interna es completamente diferente:

ARCHITECTURE estructura OF mux IS

COMPONENT and2
PORT(e1,e2: IN bit; y: OUT bit);
END COMPONENT

COMPONENT or2
PORT(e1,e2: IN bit; y: OUT bit);
END COMPONENT;


COMPONENT inv
PORT(e: IN bit; y: OUT bit);
END COMPONENT;


SIGNAL ax,bx,nosel: bit;

BEGIN
u0: inv PORT MAP(e=>selec,y=>nosel);
u1: and2 PORT MAP(e1=>a,e2=>nosel,y=>ax);
u2: and2 PORT MAP(e1=>b,e2=>sel,y=>bx);
u3: or2 PORT MAP(e1=>ax,e2=>bx,y=>salida);
END estructura;


Se observa facilmente que esta descripción es mas larga y encima menos clara que las anteriores. Dentro de la arquitectura se definen en primer lugar los componentes que se van a utilizar. Esto se realiza mediante la palabra clave COMPONENT, donde se indican ademas las entradas y salidas mediante la clausula PORT. Estos componentes deben tener una entidad y arquitectura propia indicando su comportamiento. Normalmente estas entidades se suelen poner en una libreria separada. Al igual que ocurre en cualquier netlist, las señales o conexiones deben tener un nombre. En el esquema se le han puesto nombres a las líneas de conexión internas al circuito. Estas lineas hay que declararlas como SIGNAL en el cuerpo de la arquitectura y delante del BEGIN. Una vez declarados los componentes y las señales que intervienen se procede a conectarlos entre si. Para ello la sintaxis es muy simple. Lo primero es identicar cada componente, es lo que comunmente se conoce como instanciación, es decir, asignarle a cada componente concreto un simbolo. En este ejemplo se le ha llamado u a cada componente y se le ha añadido un número para distinguirlos, en principio el nombre puede ser cualquier cosa y la única condición es que no haya dos nombres iguales. A continuación del nombre viene el tipo de componente que es, en nuestro caso puede ser una and2, una or2, o una puerta inversora inv. Despues se realizan las conexiones poniendo cada señal en su lugar correspondiente con las palabras PORT MAP. Asi, los dos primeros argumentos en el caso de la puerta and2 son las entradas, y el último es la salida. De esta forma tan simple se va creando el netlist o definición de la estructura.



Elementos sintácticos del VHDL

El lenguaje VHDL tiene sus elementos sintácticos, sus tipos de datos, y sus estructuras como cualquier otro tipo de lenguaje. El hecho de que sirva para la descripción hardware lo hace un poco diferente de un lenguaje convencional. Una de estas diferencias es probablemente la posibilidad de ejecutar instrucciones a la vez de forma concurrente. Algunos de estos elementos sintácticos son:

  • Comentarios: Cualquier linea que empieza por dos guiones "--" es un comentario.
  • Identicadores: Son cualquier cosa que sirve para identicar variables, señales, nombres de rutina, etc. Puede ser cualquier nombre compuesto por letras incluyendo el simbolo de subrayado "_". Las mayúsculas y minúsculas son consideradas iguales, así que JOSE y jose representan el mismo elemento. No puede haber ningún identicador que coincida con alguna de las palabras clave del VHDL.
  • Números: Cualquier número se considera que se encuentra en base 10. Se admite la notación cientifica convencional para números en coma flotante. Es posible poner números en otras bases utilizando el símbolo del sostenido "#". Ejemplo: 2#11000100# y 16#C4# representan el entero 196.
  • Caracteres: Es cualquier letra o carácter entre comillas simples: 'l','3','t'.
  • Cadenas: Son un conjunto de caracteres englobados por comillas dobles: "Esto es una cadena".
  • Cadenas de bits: Los tipos bit y bit vector son en realidad de tipo carácter y matriz de caracteres respectivamente. En VHDL se tiene una forma elegante de definir números con estos tipos y es mediante la cadena de bits. Dependiendo de la base en que se especifique el número se puede poner un prefijo B (binario), O (octal), o X (hexadecimal). Ejemplo: B"11101001", O"126", X"FE".



Operadores y expresiones

Las expresiones en VHDL son prácticamente iguales a como pudieran ser en otros lenguajes de programación o descripción, por lo que se expondrán brevemente algunos de los existentes en VHDL y su utilización.

Operadores varios

& (concatenación) Concatena matrices de manera que la dimensión de la matriz resultante es la suma de las dimensiones de las matrices sobre las que opera: punto<=x&y mete en la matriz punto la matriz x en las primeras posiciones, y la matriz y en las últimas.

Operadores aritméticos

** (exponencial) Sirve para elevar un número a una potencia: 4**2 es 4^2. El operador de la izquierda puede ser entero o real, pero el de la derecha solo puede ser entero.

ABS() (valor absoluto) Como su propio nombre indica esta función devuelve el valor absoluto de su argumento que puede ser de cualquier tipo numérico.

* (multiplicación) Sirve para multiplicar dos números de cualquier tipo (los tipos bit o bit vector no son numéricos).

/ (división) Tambien funciona con cualquier dato de tipo numérico.

MOD (módulo) Calcula en módulo de dos números. Exactamente se define el módulo como la operación que cumple: a=b*N+(a MOD b) donde N es un entero. Los operandos solo pueden ser enteros. El resultado toma el signo de b.

REM (resto) Calcula el resto de la división entera y se define como el operador que cumple: a=(a/b)*b+(a REM b), siendo la división entera. Los operandos solo pueden ser enteros. El resultado toma el signo de a.

+ (suma y signo positivo) Este operador sirve para indicar suma, si va entre dos operandos, o signo, si va al principio de una expresión. La precedencia es diferente en cada caso. Opera sobre valores numéricos de cualquier tipo.

- (resta y signo negativo) Cuando va entre dos operandos se realiza la operación de sustracción, y si va delante de una expresión le cambia el signo. Los operandos pueden ser numéricos de cualquier tipo.


Operadores de desplazamiento

SLL, SRL (desplazamiento lógico a izquierda y a derecha) Desplaza un vector un número de bits a izquierda (SLL) o derecha (SRL) rellenando con ceros los huecos libres. Se utiliza en notación infija de manera que la señal a la izquierda del operador es el vector que se quiere desplazar y el de la derecha es un valor que indica el número de bits a desplazar. Por ejemplo dato SLL 2 desplaza a izquierda el vector dato, es decir, lo multiplica por 4.

SLA, SRA (desplazamiento aritmético a izquierda y derecha)

ROL, ROR (rotación a izquierda y a derecha) Es como el de desplazamiento pero los huecos son ocupados por los bits que van quedando fuera.


Operadores relacionales

Devuelven siempre un valor de tipo booleano (TRUE o FALSE). Los tipos con los que pueden operar dependen de la operación:

=, /= (igualdad) El primero devuelve TRUE si los operandos son iguales y FALSE en caso contrario. El segundo indica desigualdad, funciona justo al revés. Los operandos pueden ser de cualquier tipo con la condición de que sean ambos del mismo tipo.

<,<=,>,>= (menor mayor) Tienen el signi cado habitual. La diferencia con los anteriores es que los tipos de datos que pueden manejar son siempre de tipo escalar o matrices de una sola dimensión de tipos discretos.


Operadores lógicos

Son NOT, AND, NAND, OR, NOR y XOR. El funcionamiento es el habitual para este tipo de operadores. Actuan sobre los tipos bit, bit vector y boolean. En el caso de realizarse estas operaciones sobre un vector, la operación se realiza bit a bit, incluyendo la operación NOT.


1 comentario:

Unknown dijo...

Excelente aporte, investigo el empleo de HDL para crear hardware adaptable.Agradeceria el intercambio de informacion para poder crear un excelente articulo de investigacion sobre el tema.