Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

VHDL

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 88

VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.

html

1.1 Dispositivos Lógicos Programables

Un dispositivo lógico programable, o PLD (Programmable Logic Device), es un dispositivo


cuyas características pueden ser modificadas y almacenadas mediante programación. El
principio de síntesis de cualquier dispositivo lógico programable se fundamenta en el hecho
de que cualquier función booleana puede ser expresada como una suma de productos. El
dispositivo programable más simple es el PAL (Programmable Array Logic). El circuito
interno de un PAL consiste en un arreglo, o matriz, de compuertas AND y un arreglo de
compuertas OR. El arreglo AND es programable mientras que el OR generalmente es fijo.
Mediante una matriz de conexiones se seleccionan cuales entradas serán conectadas al
arreglo AND, cuyas salidas son conectadas al arreglo OR y de esta manera obtener una
función lógica en forma de suma de productos. Una matriz de conexiones es una red de
conductores distribuidos en filas y columnas con un fusible en cada punto de intersección.
La mayoría de los PLDs están formados por una matriz de conexiones, una matriz de
compuertas AND, y una matriz de compuertas OR y algunos, además, con registros. Con
estos recursos se implementan las funciones lógicas deseadas mediante un software
especial y un programador. Las matrices pueden ser fijas o programables. El tipo más
sencillo de matriz programable, que data de los años 60, era una matriz de diodos con un
fusible en cada punto de intersección de la misma. En la figura 1.1 se muestran los
circuitos básicos para la mayoría de los PLDs.

Figura 1.1 Estructuras básicas de un PLD

1.1.1 Matriz Genérica Programable

Una Matriz Genérica Programable (GAL, Generic Array Logic) es una denominación que
utilizaba originalmente Lattice Semiconductor y que más tarde se licenció a otros
fabricantes. Un GAL en su forma básica es un PLD con una matriz AND reprogramable,
una matriz OR fija y una lógica de salida programable mediante una macrocelda. Esta
estructura permite implementar cualquier función lógica como suma de productos con un
numero de términos definido.

1 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

En los PLDs no reprogramables la síntesis de las ecuaciones lógicas se realiza mediante


quema de fusibles en cada punto de intersección de los pines de entrada con las
compuertas.
En el caso de un GAL es básicamente la misma idea pero en vez de estar formada por una
red de conductores ordenados en filas y columnas en las que en cada punto de intersección
hay un fusible, el fusible se reemplaza por una celda CMOS eléctricamente borrable
(EECMOS). Mediante la programación se activa o desactiva cada celda EECMOS y se
puede aplicar cualquier combinación de variables de entrada, o sus complementos, a una
compuerta AND para generar cualquier operación producto que se desee. Una celda
activada conecta su correspondiente intersección de fila y columna, y una celda
desactivada desconecta la intersección. Las celdas se pueden borrar y reprogramar
eléctricamente. A continuación se muestran la estructura típica de un GAL y la macrocelda
de salida del GAL22V10.

Figura 1.2 Estructura típica de un GAL

FIGURA 1.3 Macrocelda de un GAL22V10

1.2 CPLD

Un CPLD (Complex Programmable Logic Device) extiende el concepto de un PLD a un


mayor nivel de integración ya que permite implementar sistemas con un mejor desempeño

2 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

porque utilizan menor espacio, mejoran la confiabilidad en el circuito, y reducen costos. Un


CPLD se forma con múltiples bloques lógicos, cada uno similar a un PLD. Los bloques
lógicos se comunican entre sí utilizando una matriz programable de interconexiones lo cual
hace más eficiente el uso del silicio, conduciendo a un mejor desempeño y un menor costo.
A continuación se explican brevemente las principales características de la arquitectura de
un CPLD.

Figura 1.4 Arquitectura Básica de un CPLD

1.2.1 Matriz de Interconexiones Programables

La matriz de interconexiones programables (PIM) permiten unir los pines de entrada/salida


a las entradas del bloque lógico, o las salidas del bloque lógico a las entradas de otro
bloque lógico o inclusive a las entradas del mismo. La mayoría de los CPLDs usan una de
dos configuraciones para esta matriz: interconexión mediante arreglo o interconexión
mediante multiplexores.
El primero se basa en una matriz de filas y columnas con una celda programable de
conexión en cada intersección. Al igual que en el GAL esta celda puede ser activada para
conectar/desconectar la correspondiente fila y columna. Esta configuración permite una
total interconexión entre las entradas y salidas del dispositivo o bloques lógicos. Sin
embargo, estas ventajas provocan que disminuya el desempeño del dispositivo además de
aumentar el consumo de energía y el tamaño del componente.
En la interconexión mediante multiplexores, existe un multiplexor por cada entrada al
bloque lógico. Las vías de interconexión programables son conectadas a las entradas de un
numero de multiplexores por cada bloque lógico. Las líneas de selección de estos
multiplexores son programadas para permitir que sea seleccionada únicamente una vía de
la matriz de interconexión por cada multiplexor la cual se propagara a hacia el bloque
lógico. Cabe mencionar que no todas las vías son conectadas a las entradas de casa
multiplexor. La rutabilidad se incrementa usando multiplexores de mayor tamaño,
permitiendo que cualquier combinación de señales de la matriz de interconexión pueda ser

3 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

enlazada hacia cualquier bloque lógico. Sin embargo, el uso de grandes multiplexores
incrementa el tamaño de dispositivo y reduce su desempeño.

1.2.2 Bloques Lógicos

Un bloque lógico es similar a un PLD, cada uno pose un arreglo de compuertas AND y OR
en forma de suma de productos, una configuración para la distribución de estas sumas de
productos, y macroceldas. El tamaño del bloque lógico es una medida de la capacidad del
CPLD, ya que de esto depende el tamaño de la función booleana que pueda ser
implementada dentro del bloque. Los bloques lógicos usualmente tienen de 4 a 20
macroceldas.

Figura 1.5 Estructura de un Bloque Lógico en dispositivos de

las familias MAX340 y MAX5000

1.2.3 Distribución de Productos

Existen pequeñas diferencias en cuanto a las matrices de productos, esto dependerá del
CPLD y del fabricante. Obviamente el tamaño de las sumas sigue siendo el factor más
importante para la implementación de funciones booleanas. Cada fabricante distribuye los
productos de diferente forma. La familia MAX de CPLDs fue desarrollada por Cypress
Semiconductor junto con Altera Corporation, siendo los primeros en sacar al mercado unan
familia de CPLDs. Altera la llamó MAX5000 y Cypress por su parte la clasificó como
MAX340. En un dispositivo como el 22V10 tenemos que la suma de productos es fija por
cada macrocelda - 8, 10, 12, 14 o 16 -, en la familia MAX se colocan 4 productos por
macrocelda los cuales pueden ser compartidos con otras macroceldas. Cuando un producto
puede ser únicamente utilizado por una macrocelda se le conoce como termino - producto
dirigido, y cuando estos pueden ser utilizados por otras macroceldas se le llama termino -
producto compartido. Mediante estos productos compartidos se mejora la utilización del
dispositivo, sin embargo, esto produce un retardo adicional al tener que retroalimentar un
producto hacia otra macrocelda y con esto disminuye la velocidad de trabajo del circuito.
La forma en que son distribuidos los productos repercute en la flexibilidad que proporciona
el dispositivo para el diseñador. Además, que estos esquemas proporcionan también

4 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

flexibilidad para los algoritmos del programa de síntesis que es el que finalmente selecciona
la mejor forma en que deben ser distribuidas las funciones booleanas en el dispositivo.

Figura 1.6 Distribución de Productos en dispositivos de

las familias MAX340 y MAX5000

1.2.4 Macroceldas

Las macroceldas de un CPLD son similares a las de un PLD. Estas también están provistas
con registros, control de polaridad, y buffers para salidas en alta impedancia. Por lo general
un CPLD tiene macroceldas de entrada/salida, macroceldas de entrada y macroceldas
internas u ocultas (buried macrocells), en tanto que un 22V10 tiene solamente
macroceldas de entrada/salida. Una macrocelda interna es similar a una macrocelda de
entrada/salida, sólo que esta no puede ser conectada directamente a un pin de salida. La
salida de una macrocelda interna va directamente a la matriz de interconexión
programable. A continuación se muestra la estructura básica de las macroceldas de
entrada/salida y macroceldas ocultas para dispositivos de la familia FLASH 370 de Cypress
Semiconductors.

5 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Figura 1.7 Macroceldas de entrada/salida y macroceldas ocultas

en dispositivos de la familia FLASH 370

Las macroceldas de entrada, como la que se muestra en la siguiente figura, son utilizadas
para proporcionar entradas adicionales para las funciones booleanas. En el diagrama se
muestra la macrocelda de entrada de la familia FLASH 370. En general las macroceldas de
entrada incrementan la eficiencia del dispositivo al ofrecer algunos registros adicionales
con los que se pueden almacenar el valor del pin de entrada, lo cual puede ser útil al
momento de obtener las funciones booleanas.

Figura 1.8 Macrocelda de entrada en dispositivos de la familia FLASH 370

1.2.5 Celda de entrada/salida

En la figura 1.7 se puede apreciar una celda de entrada/salida, que bien podría considerarse
parte del bloque lógico, pero no necesariamente tienen que estar a la salida de un bloque
lógico. La función de una celda de entrada/salida es permitir el paso de una señal hacia
dentro o hacia el exterior del dispositivo. Dependiendo del fabricante y de la arquitectura

6 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

del CPLD estas celdas son pueden ser consideradas o no consideradas parte del bloque
lógico.

1.3 FPGA

La arquitectura de un FPGA (Field Programmable Gate Array) consiste en arreglos de


varias celdas lógicas las cuales se comunican unas con otras mediante canales de conexión
verticales y horizontales como se muestra en la siguiente figura.

Figura 1.9 Arquitectura básica de un FPGA

Cada celda lógica es similar a los bloques lógicos de un CPLD. La estructura de las celdas
lógicas y las formas en que estas pueden ser interconectadas, tanto salidas como entradas
de la celda, varían de acuerdo al fabricante. En general una celda lógica tiene menos
funcionalidad que la combinación de sumas de productos y macroceldas de un CPLD, pero
como cada FPGA tienen una gran cantidad de celdas lógicas es posible implementar
grandes funciones utilizando varias celdas lógicas en cascada.
Además de las celdas lógicas también es importante la tecnología utilizada para crear las
conexiones entre los canales, las más importantes son las siguientes.

ANTIFUSE

Al igual que la tecnología PROM son programables una sola vez y utilizan algo similar a un
fusible para realizar las conexiones, una vez que es programado éste ya no se puede
recuperar. Al contrario que un fusible normal, estos anti - fusibles cuando son
programados producen una conexión entre ellos por lo que normalmente se encuentran
abiertos. La desventaja es que no son reutilizables pero por el contrario disminuyen
considerablemente el tamaño y costo de los dispositivos.

SRAM

Celdas SRAM son implementadas como generadores de funciones para simular lógica
combinacional y, además, son usadas para controlar multiplexores e interconectar las
celdas lógicas entre si (similar a un CPLD).

1.3.1 Celdas Lógicas

7 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

La estructura de las celdas lógicas se ve fuertemente influida por la tecnología utilizada


para fabricar el FPGA. Un FPGA que tiene una gran cantidad de canales de interconexión
tiende a tener pequeñas celdas lógicas con muchas entradas y salidas en comparación con
el número de compuertas que tiene la celda, este tipo de FPGAs generalmente utilizan
tecnología ANTIFUSE.
Un FPGA que tiene una estructura pequeña en canales de interconexión tiende a tener
grandes celdas lógicas con pocas entradas y salidas en comparación con el número de
compuertas que hay en la celda. Este tipo de FPGA generalmente está hecho con
tecnología SRAM.
Una arquitectura con celdas lógicas pequeñas nos permite utilizar totalmente los recursos
del dispositivo. Sin embargo, si las celdas lógicas son demasiado pequeñas entonces sucede
que tendremos que utilizar un gran numero de estas en cascada para poder implementar
funciones booleanas grandes, lo cual afecta porque cada celda lógica en cascada agrega un
tiempo de retardo en la función implementada.
Cuando el tamaño de la celda lógica es grande sucede lo contrario. En este tipo de celdas
lógicas es posible utilizar un gran número de compuertas por lo que podemos implementar
funciones booleanas de varios términos con pocas celdas lógicas. El que el tamaño de la
celda sea grande no afecta la frecuencia máxima de trabajo porque estamos hablando de
que existe un gran numero de compuertas que pueden ser usadas en la función al mismo
tiempo, siendo el mismo tiempo de retardo para todas. En cambio cuando la celda lógica
tiene pocas compuertas es necesario utilizar las compuertas de otra celda para poder
implementar la misma función y se acumula el tiempo de retardo de las compuertas de la
otra celda. Sin embargo, cuando las funciones son pequeñas en comparación con el tamaño
de la celda no es necesario utilizar todas las compuertas de la celda, por lo que este tipo de
celdas no son precisamente las más indicadas para desempeñar pequeñas funciones.
La tecnología SRAM y ANTIFUSE son comúnmente utilizadas por la mayoría de los
fabricantes. La tecnología SRAM es utilizada por Altera, Lucent Technologies, Atmel,
Xilinx y otros. La tecnología ANTIFUSE es utilizada por Cypress, Actel, QuickLogic, y
Xilinx.
A continuación se muestran varias celdas lógicas con diferentes nombres de acuerdo al
fabricante.

(a) Bloque Lógico Configurable de la familia XC4000 de Xilinx, Inc.

8 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

(b) Modulo Lógico de la familia ACT3 de Actel Corporation

(c) Elemento Lógico de la familia APEX20K de Altera Corporation

Figura 1.10 Diferentes Celdas Lógicas

2.1 Antecedentes Históricos

9 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

VHDL es un lenguaje utilizado para describir circuitos en un nivel alto de abstracción el


cual está siendo rápidamente aceptado como un medio estándar de diseño. VHDL es
producto del programa Very High Speed Integrated Circuit (VHSIC) desarrollado por el
Departamento de Defensa de los Estados Unidos a finales de la década de los 70's. El
propósito era hacer un estándar para diseñar, modelar, y documentar circuitos complejos
de manera que un diseño desarrollado por una empresa pudiera ser entendido por otra,
además, que pudiera ser procesado por software para propósitos de simulación.
En diciembre de 1987 VHDL se estableció como el estándar IEEE-1076. En 1993 el
estándar IEEE-1076 se actualizó y un estándar adicional, el IEEE-1164, fue adoptado. En
1996, el estándar IEEE-1076.3 se convirtió en un estándar de VHDL para síntesis siendo
este el que se utiliza en el diseño de sistemas digitales.
En la actualidad VHDL es un estándar de la industria para la descripción, modelado y
síntesis de circuito digitales. El mercado entero de síntesis ha alcanzado aproximadamente
los 100 millones de dólares, con un crecimiento del 20% al 30% al año. Por esto, los
ingenieros de la mayoría de las áreas de electrónica, si no es que todas, deben aprender a
programar en VHDL para incrementar su eficiencia.
Lo que ha hecho que VHDL sea en un tiempo tan corto el lenguaje de descripción de
hardware mas utilizado por la industria electrónica, es su independencia con la metodología
de diseño utilizada por cada programador, su capacidad de descripción a diferentes niveles
de abstracción, y en definitiva la posibilidad de poder reutilizar en diferentes aplicaciones
un mismo código.

2.2 Usando VHDL para Síntesis

El proceso de diseño implementando VHDL se puede resumir en los siguientes seis pasos.

1. Definición de los requerimientos del sistema


Antes de comenzar a realizar la descripción del diseño, es muy importante que se tenga una
idea clara de los objetivos y requerimientos. Tales como: Funciones del circuito, máxima
frecuencia de operación, y los puntos críticos del sistema. Esto servirá para poder definir a
grandes rasgos cual será la arquitectura del circuito y así comenzar a realizar la
descripción.

2. Descripción del circuito en VHDL


Antes de comenzar a escribir el código es recomendable seleccionar alguna metodología de
diseño como: Top-Down, Bottom-Up, o Flat. Los dos primeros involucran la creación de
diseños jerárquicos que generalmente son grandes, el último es generalmente utilizado en
diseño de circuitos pequeños.
La metodología Top-Down consiste en dividir el sistema en varios bloques de manera que
se puedan resolver los problemas por separado. Cada bloque a su vez se puede dividir en
otros bloques si es necesario. El objetivo es que cada bloque tenga una función especifica
representada con un componente con entradas y salidas que desempeñan dicha función.
Bottom-Up es todo lo contrario, comenzamos por caracterizar los componentes básicos del
circuito y con estos formamos bloques de mayor tamaño que representen un circuito más
complejo que sus partes individuales.
La metodología Flat es comúnmente utilizada para diseños pequeños, donde los
requerimientos son pocos y no muy complejos por lo que no nos distraen y no perdemos de
vista la funcionalidad del circuito.
Después de decidir cual será la metodología que debemos implementar entonces
comenzamos a describir el circuito de acuerdo con lo que se había establecido. Es
recomendable utilizar algún tipo de diagrama a bloques con la descripción del
funcionamiento de cada bloque, diagramas de estado, o usar alguna tabla de
funcionamiento donde se resumen las funciones de un bloque en especial. Los errores más
comunes en VHDL son de sintaxis, como ";" al final de cada instrucción, o simplemente

10 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

por no utilizar adecuadamente alguna instrucción. La clave para describir correctamente


un circuito con VHDL es pensar en términos de compuertas y registros.

3. Simulación de la descripción en VHDL


La simulación del código nos permite detectar y corregir errores antes que se implemente
en el dispositivo. Lo cual es de gran ayuda en grandes diseños en los que es complicado
tratar de encontrar errores en el dispositivo una vez que es programado. La modularidad
implementada también ayuda a encontrar los errores rápidamente, porque así cuando
describimos el circuito por bloques podemos evaluar cada bloque por separado antes de
conjuntarlos. Sin embargo, con todas estas precauciones es necesario volver a evaluar el
código que "realmente" quedo en el dispositivo. Es decir, una compuerta XOR
generalmente no se puede implementar como tal, sino que necesitamos sustituir la función
XOR por su equivalente, A XOR B = A'B+AB'. Todas estas sustituciones o cambios
dependen del dispositivo implementado por lo que habrá funciones que tal vez se lleven
más tiempo de lo esperado en ejecutarse y esto afecte todo el diseño.

4. Síntesis
Síntesis consiste en reducir una descripción de alto nivel abstracción a un nivel de
compuerta que pueda ser implementado en el circuito. Dicho de otra manera, síntesis es el
proceso mediante el cual una descripción es convertida en un listado de conexiones
(netlist) entre las compuertas, registros, multiplexores, etc. de un CPLD o FPGA. Por
ejemplo, al igual que en el caso de una compuerta XOR, una instrucción IF puede ser una
compuerta AND, o una OR, o toda una función que involucre diferentes tipos de
componentes.
El proceso de síntesis depende del dispositivo utilizado. Por lo general una misma función
es implementada de diferentes formas de acuerdo al dispositivo que estemos utilizando,
esto no cambia para nada la descripción original por lo que el circuito trabajará igual en
cualquier componente seleccionado. Pero el componente seleccionado si afecta la
frecuencia máxima de trabajo del circuito descrito. El proceso utilizado para sintetizar un
código en un CPLD es conocido como Fitting o ajuste y consiste en tratar de acomodar las
ecuaciones booleanas en los diferentes bloques lógicos. Cuando se utiliza un FPGA el
proceso empleado se le llama Place and Route y consiste en adecuar las ecuaciones a
través de varias celdas lógicas. Aunque la finalidad es la misma, la manera en que se
sintetiza un código en un CPLD es totalmente distinta que cuando se utiliza un FPGA. Por
otro lado la optimización de la conversión del código en VHDL a ecuaciones booleanas
depende de tres cosas: la descripción del circuito, los recursos disponibles en el dispositivo
seleccionado, y las directivas de síntesis seleccionadas por el usuario.
La descripción es el punto más importante porque de esto depende los otros dos. En la
descripción no solamente tenemos que "decir" como funciona el circuito, además, debemos
describir en que forma debe de hacerlo. No es lo mismo describir un sumador de 4 bits
utilizando 4 bloques que van haciendo la suma por partes a describir un circuito que hace
todo a la vez. Finalmente suman pero no lo hacen igual. Los recursos por otro lado tienen
que ver en el que una función pueda o no ser implementada en el componente. Por
ejemplo, un contador de 4 bits con reset asíncrono no puede ser implementado en 16V8
porque el registro de la macrocelda de salida del dispositivo no tiene una entrada asíncrona
de reset. Las directivas de síntesis afectan el proceso de obtención de las ecuaciones.
Algunas de estas directivas son: sintetizar para maximizar velocidad, sintetizar para
optimizar el área, y algunas que son descritas en el mismo código, como por ejemplo
obligar a que un nodo no sea simplificado y pueda ser sintetizado a la salida de una
macrocelda. Cuando se sintetiza para maximizar la frecuencia generalmente quedan
funciones con varios términos e incluso hay términos que se repiten en las ecuaciones de
los nodos de salida pero esto se hace para evitar la retroalimentación. En general estas
restricciones afectan directamente el proceso para obtener las ecuaciones.

5. Simulación del código sintetizado

11 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Simular el código sintetizado en el circuito permite verificar los retrasos de tiempo de un


pin a otro, evaluar la máxima frecuencia de operación del circuito y verificar que funcione
adecuadamente. En caso de que el código no pueda ser sintetizado podemos tratar de
mejora la descripción, encontrar algún error en la descripción, cambiar las directivas de
síntesis o definitivamente seleccionar otro dispositivo.

6. Programación del dispositivo


Después de completar la descripción, sintetizar y simular con éxito el circuito, ahora el
siguiente paso es generar el archivo que nos permite programar el dispositivo. Todos los
programas de VHDL para síntesis generan un archivo con el que podemos programar el
dispositivo. Ya sea JEDEC o JTAG de acuerdo al dispositivo.

A continuación se discutirán algunos de los elementos fundamentales de VHDL que son


comúnmente utilizados para síntesis de circuitos. Comenzaremos por exponer un pequeño
ejemplo haciendo una comparación con otros programas para descripción de diseños
electrónicos por computadora, para posteriormente explicar los temas básicos del lenguaje,
tales como: identificadores, objetos de datos, tipos de datos, operadores, instrucciones y
sintaxis del lenguaje.

3.1 Descripción en VHDL de un Comparador

El código mostrado a continuación corresponde al comparador mostrado en la figura 3.1.


Las palabras en color azul corresponden a palabras reservadas en VHDL y los comentarios
comienzan con dos guiones (--) y se muestran en color rojo.

Figura 3.1

-- código de descripción en VHDL

ENTITY comparador IS

PORT ( x: IN bit_vector ( 3 DOWNTO 0 ) ;

y: IN bit_vector ( 3 DOWNTO 0 ) ;

equals: OUT bit ;

x_may_y: OUT bit ;

12 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

x_men_y: OUT bit ) ;

END comparador ;

ARCHITECTURE arch_comparador OF comparador IS

BEGIN

equals <= '1' WHEN x = y ELSE '0' ;

x_may_y <= '1' WHEN x > y ELSE '0' ;

x_men_y <= '1' WHEN x < y ELSE '0' ;

END arch_comparador ;

Las descripciones en VHDL son creadas a partir de dos estructuras que son fundamentales
para el lenguaje: la entidad y la arquitectura. Básicamente la entidad es la estructura en la
que se define cuales son las entradas y salidas del circuito que deseamos representar, la
cual podemos asociar con una "caja" en la que se que describen las interfaces de
comunicación con el exterior, siendo la arquitectura donde se define el comportamiento
interno de esa "caja".
Nótese que en la primera declaración de puertos, dentro de la entidad del comparador, se
definen 2 bus de entrada de 4 bits de magnitud (x, y), en cambio las salidas son de 1 bit. En
la entidad lo único que hacemos es describir como es el circuito, o aquello del circuito que
permite a la entidad comunicarse hacia otras entidades, sin mencionar para nada su
comportamiento interno. Es en la arquitectura, después del BEGIN, donde se realiza la
descripción del comportamiento del circuito.

El estilo de programación en VHDL

Haciendo una comparación con un lenguaje de programación de alto nivel podemos ver
que el código es similar en cuanto a las sentencias utilizadas, pero no es así en el flujo de
ejecución de las instrucciones. Un código de programación en VHDL no es precisamente
un "programa", ya que un programa es un conjunto de instrucciones que se ejecutan paso a
paso para llevar a cabo una tarea determinada, y en este caso no podemos decir que las
instrucciones se estén ejecutando de esta manera, porque esto no corresponde en la
realidad al comportamiento de un circuito. En VHDL las instrucciones se están ejecutando
en todo momento lo cual sí se asemeja al comportamiento real de un circuito, en este caso
de un comparador. Así cuando cambie algún bit de entrada cambiará inmediatamente la
salida y, por consiguiente, estamos describiendo cual es el verdadero funcionamiento del
circuito.
La forma en que se "programa" en VHDL al principio resultará un tanto extraña, pero si
asociamos éste código con el circuito que estamos describiendo, podemos darnos cuenta
que en él los componentes siempre están activos, y es esto es precisamente lo que
describimos mediante VHDL.
Alguna vez hemos utilizado Pspice o algún programa de entrada esquemática de diseño
para modelar y simular circuitos, estos también son para la descripción de circuitos. En
Pspice la descripción se realiza mediante un listado de conexiones (netlist) entre los
componentes, en tanto que en los otros lo hacemos de manera gráfica, y en ambos se
considera que todos los componentes siempre están funcionando para que la simulación o
modelado del diseño sea de acuerdo a la realidad. Por esto en VHDL el orden de las
instrucciones no es tan importante como en el caso de un lenguaje de programación de
software, porque las instrucciones siempre se están ejecutando y así sí se modela
adecuadamente un circuito.

13 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Otro punto importante es el dispositivo lógico programable que estemos utilizando, ya que
si éste no tiene la capacidad para realizar lo que "dice" nuestra descripción, nunca
podremos sintetizar el código. Por ejemplo, si en el dispositivo que usemos no es posible
que las salidas puedan ser programadas para que estén en alta impedancia, aún y cuando la
descripción sea correcta nunca podremos sintetizarla en el dispositivo.
Al principio generalmente se comete el error de tratar de "programar" como si fuera C++,
Pascal, Visual Basic o cualquier otro lenguaje de programación de software, además de
olvidar que el PLD, CPLD, o FPGA que utilicemos tiene características propias que deben
ser consideradas cuando se hace la descripción.
Posteriormente se explicarán los tipos de instrucciones y sus diferencias, ya que VHDL si
permite la programación "secuencializada" de instrucciones dentro una estructura llamada
PROCESS. Dentro de esta estructura las instrucciones se ejecutan "paso a paso" como en
los lenguajes de programación de software. Pero de cualquier manera esta estructura
siempre esta activa, como si fuera un componente o subcircuito del diseño, por lo que todo
lo que se obtenga dentro del proceso se ejecutará al mismo tiempo que el resto de las
instrucciones que están fuera de esta estructura.

3.2 Identificadores

Un identificador se define como un conjunto de caracteres con el cual podemos representar


diferentes elementos de programación. En VHDL un identificador está compuesto por una
secuencia de uno o más caracteres alfabéticos, numéricos, o del carácter de subrayado. Las
condiciones que debe de seguir un identificador son las siguientes:

VHDL permite la utilización de las letras mayúsculas (A.. Z), minúsculas (a....
z), dígitos (0...9), y el carácter de subrayado (_).
El primer caracter de un identificador debe ser una letra.
El ultimo caracter de identificador no puede ser el caracter de subrayado.
Además, el caracter de subrayado no puede aparecer dos o más veces
consecutivas.
Mayúsculas y minúsculas son consideradas idénticas. Así, Signal_A, signal_a, y
SIGNAL_A se refieren al mismo identificador.
Los comentarios en VHDL comienzan con dos guiones consecutivos (--), y se
extienden hasta el final de la línea. Los comentarios pueden aparecer en
cualquier lugar dentro de una descripción en VHDL.
VHDL define un grupo de palabras reservadas, llamadas "palabras clave"
(keywords), las cuales no pueden ser usadas como identificadores.

EJEMPLOS

-- Este es un comentario.

ENTITY contador IS -- comentario al final de una línea

14 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Los siguientes ejemplos son de identificadores válidos en VHDL.

Mi_entidad

Mux4a2

TTL_7490

A continuación se muestran ejemplos de identificadores no válidos en VHDL.

3er_Modulo -- un identificador no puede iniciar

-- con un dígito

_salida_x -- o con el caracter de subrayado

M__24xmax -- no se permiten dos caracteres

-- de subrayado seguidos

My_design_ -- un identificador no debe terminar

-- con un caracter de subrayado

Unidad& -- el caracter "&", no es un caracter

-- válido

SIGNAL -- palabra reservada

3.3 Objetos De Datos

Un objeto de datos en VHDL es un elemento que toma un valor de algún tipo de dato
determinado. Según sea este tipo de dato, el objeto poseerá un conjunto de propiedades
que se le podrán aplicar, como las operaciones en las que el objeto puede ser usado. En
VHDL los objetos de datos son generalmente de una de tres clases: constantes, variables o
señales.

3.3.1 Constantes

Una constante es un elemento que puede tomar un único valor de un tipo dado. A las
constantes se les debe asignar un valor en el momento de la declaración. Una vez que se le

15 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

ha asignado algún valor, éste no puede ser cambiado dentro de la descripción del diseño.
Las constantes pueden ser declaradas dentro de las entidades, arquitecturas, procesos o
paquetes. Las constantes que se declaren en un paquete pueden ser utilizadas en cualquier
descripción en la que se este utilizando dicho paquete. Por otra parte las constantes
declaradas dentro de una entidad pueden ser utilizadas por la o las arquitecturas en las que
se este haciendo la descripción de dicha entidad, y aquellas constantes que sean declaradas
dentro de una arquitectura o proceso, son validas únicamente dentro de la estructura
correspondiente.

DECLARACIÓN DE CONSTANTES

CONSTANT identificador [, identificador...]: tipo := valor;

[]: opcional

EJEMPLO

CONSTANT byte: integer := 8;

3.3.2 Variables

Los objetos de datos de la clase variable son similares a las constantes, con la diferencia
que su valor puede ser modificado cuando sea necesario. Las variables en VHDL son
similares a cualquier tipo de variable de un lenguaje de programación de alto nivel. A las
variables también se les puede asignar un valor inicial al momento de ser declaradas. Se
utilizan únicamente en los procesos y subprogramas (funciones y procedimientos). Las
variables generalmente se utilizan como índices, principalmente en instrucciones de bucle,
o para tomar valores que permitan modelar componentes. Las variables no representan
conexiones o estados de memoria.

DECLARACIÓN DE VARIABLES

VARIABLE identificador [, identificador...]: tipo [:=valor] ;

EJEMPLO

VARIABLE aux1, aux2: bit_vector ( 31 DOWNTO 0 ) ;

3.3.3 Señales

Un objeto de la clase señal es similar a un objeto de la clase variable, con una importante
diferencia: las señales si pueden almacenar o pasar valores lógicos, mientras que una
variable no lo puede hacer. Las señales, por lo tanto, representan elementos de memoria o
conexiones y si pueden ser sintetizadas.
Los puertos de una entidad son implícitamente declarados como señales en el momento de
la declaración, ya que estos representan conexiones. También pueden ser declaradas en las
arquitecturas antes del BEGIN, lo cual nos permite realizar conexiones entre diferentes

16 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

estructuras de programación. La asignación de valores a un objeto de datos del tipo señal


no es inmediata como en el caso de las variables, esto se explicará más detalladamente
cuando se exponga la estructura PROCESS y los tipos de instrucciones.

DECLARACIÓN DE SEÑALES

SIGNAL identificador [, identificador...]: tipo [:=valor] ;

EJEMPLOS

SIGNAL selec: bit := '0' ;

SIGNAL datos: bit_vector ( 7 DOWNTO 0 ) := B"11100010" ;

3.3.4 Alias

Un ALIAS no es precisamente un objeto de datos. La instrucción ALIAS permite que


utilicemos un identificador diferente para hacer referencia a un objeto de datos, o a parte
de él, ya existente. Este no es un objeto de datos nuevo, sino que nos permite manipular
fragmentos del objeto de datos original para facilitar la programación. Al modificar el
ALIAS se modifica el objeto de datos al que señala.

DECLARACIÓN DE ALIAS

ALIAS identificador [, identificador...]: tipo IS identificador_objeto ( rango ) ;

EJEMPLO

ALIAS instr: std_logic_vector ( 3 DOWNTO 0 ) IS dato ( 7 DOWNTO 4 ) ;

3.4 Tipos De Datos

Un tipo de dato especifica el grupo de valores que un objeto de datos puede tomar así
como las operaciones que son permitidas con esos valores. En VHDL es sumamente
importante el tipo de dato, los objetos de datos no pueden tomar o no se les puede asignar
un objeto de datos de otro tipo, y no todas las operaciones se pueden utilizar con los
diferentes tipos de datos a menos que se utilicen las librerías adecuadas en las que estén
definidas funciones para la conversión de tipos.
Además, es posible que el usuario defina subtipos y tipos compuestos, modificando los
tipos básicos, así como definir tipos particulares con combinaciones de los diferentes tipos.
A continuación se discutirán las dos categorías de tipos de datos más utilizadas en síntesis:
escalares y compuestos.

3.4.1 Tipos Escalares

17 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Los tipos escalares tienen un orden especifico lo cual permite que sean usados con
diferentes operadores. Existen 4 clases de tipos escalares: enteros, reales o de punto
flotante, enumerados, y físicos.

Entero

VHDL permite especificar la gama del entero (integer) de manera diferente. Sin embargo,
la gama debe extender desde por lo menos -(2**31-1) a +(2**31-1), o - 2147483648 a
+2147483647. Una señal o variable que sea del tipo entero y que tenga que ser sintetizada
en elementos lógicos, debe ser limitada con un rango.

EJEMPLO

VARIABLE n: integer RANGE -15 TO 15 ;

Real

El rango de valores que puede tomar este tipo de dato se encuentra entre -1.038E38 a
+-1.038E38. El Real rara vez es usado en síntesis y en la mayoría de las herramientas de
software de VHDL para síntesis no es posible utilizar este tipo de dato.

Tipos Enumerados

Un tipo enumerado es un tipo de dato con un grupo de posibles valores asignados por el
usuario. Los tipos enumerados se utilizan principalmente en el diseño de maquinas de
estado.

DECLARACIÓN DE UN TIPO ENUMERADO

TYPE nombre IS ( valor [,valor...] ) ;

El orden en el que los valores son listados en la declaración del tipo enumerado define el
orden léxico para ese tipo.

EJEMPLOS

TYPE aritmetico IS ( add, sub, mul, div ) ;

En este ejemplo se define un tipo enumerado llamado aritmetico, y los posibles valores son
add, sub, mul, y div.

TYPE estados IS ( estado0, estado1, estado2, estado3 ) ;

Ahora se definió un tipo enumerado llamado estados, con 4 posibles valores: estado0,
estado1, estado2 y estado3.

18 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Existen varios tipos de datos (algunos predefinidos en los programas de síntesis) para el
lenguaje pero generalmente los siguientes tipos enumerados son los más comúnmente
utilizados para síntesis de circuitos.

boolean

bit

std_logic

Boolean

Los objetos de datos de este tipo pueden tomar los valores de falso o verdadero (TRUE,
FALSE).

Bit

Los objetos de este tipo pueden tomar los valores de '0' y '1'. El que estén entre comillas
simples es para indicar que son bits y no los números enteros 0 y 1.

std_logic

El tipo std_logic es similar al tipo bit pero con la excepción que éste no esta definido
dentro del lenguaje. El paquete std_logic_1164 de la IEEE define al std_logic como un tipo
de dato el cual puede tomar los valores 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-'.

'U' -- Uninitialized 'W' -- Weak Unknow

'X' -- Forcing 'L' -- Weak 0

'0' -- Forcing 0 'H' -- Weak 1

'1' -- Forcing 1 '-' -- Don't care

'Z' -- High Impedance

Los valores '0', '1', 'L' y 'H', se utilizan en síntesis de circuitos, los valores 'Z' y '-' tienen
restricciones sobre como y donde pueden ser usados. Los valores 'U', 'W' y 'X' se utilizan
únicamente para simulación y evaluación de diseños mas no para síntesis. Para la mayoría
de los diseños se utiliza este tipo de dato ya que es más completo que el tipo bit por
proporcionar los valores 'Z' y '-'.

Tipos Físicos

19 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Los tipos físicos son usados para especificar unidades de medida, ya sea de tiempo o para
determinar medidas eléctricas. El único tipo predefinido es el time, mediante el cual se
pueden establecer medidas para simular los retardos de tiempo o para generar diferentes
señales que nos permitan simular nuestro diseño.
La unidad básica del tipo time es el femtosegundo, y de éste se forman diferente múltiplos.

TYPE time IS RANGE -2147483647 TO 2147483647

UNITS

fs ;

ps = 1000 fs ;

ns = 1000 ps ;

us = 1000 ns ;

ms = 1000 us ;

sec = 1000 ms ;

min = 60 sec ;

hr = 60 min ;

END UNITS ;

Los tipos físicos no tienen ningún significado en síntesis, sólo son utilizados para
simulación de circuitos.

3.4.2 Tipos Compuestos

Un tipo compuesto es un tipo de dato formado con elementos de otros tipos. Existen dos
formas de tipos compuestos: ARRAYS y RECORDS.

DECLARACIÓN DEL TIPO ARRAY

TYPE nombre IS ARRAY ( rango ) OF tipo_base ;

DECLARACION DEL TIPO RECORD

TYPE nombre IS RECORD

elemento: tipo_de_dato ;

[;elemento: tipo_de_dato...] ;

20 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END RECORD ;

Un arreglo es un objeto de datos que consiste en una "colección" de elementos del mismo
tipo. Los arreglos pueden ser de una o más dimensiones. Los elementos individuales de un
arreglo pueden ser utilizados especificando un valor dentro del arreglo. Elementos
múltiples de un arreglo pueden ser utilizados especificando más valores.
Un registro es un objeto de datos que consiste en una "colección" de elementos de
diferentes tipos. La estructura RECORD en VHDL es análoga a los records utilizados en
Pascal o a las estructuras en C. Los campos individuales de un RECORD pueden ser
utilizados usando los nombres de los elementos. También se puede utilizar más de un
campo.

EJEMPLOS

Las siguientes líneas corresponden a la declaración de un tipo ARRAY.

TYPE palabra IS ARRAY ( 0 TO 35 ) OF std_logic ;

TYPE matriz IS ARRAY ( 0 TO 13, 0 TO 18 ) OF std_logic ;

TYPE valores IS ARRAY ( 0 TO 127 ) OF integer ;

A continuación se muestra como declarar objetos de datos utilizando estos tipos.

SIGNAL mensaje1,mensaje2: palabra ;

SIGNAL arreglo_matriz: matriz ;

VARIABLE valor_actual: valores ;

Algunas posibles maneras de asignar valores a elementos de estos objetos son:

mensaje1( 0 ) <= '1' ; -- asignación de valor al elemento '0' de

-- mensaje1

mensaje( 5 ) <= '0' ; -- asignación de valor al quinto elemento

-- de mensaje1

mensaje2 <= mensaje1 ; -- hace mensaje1 igual a mensaje2, esto es

21 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

-- permitido ya que se trata de dos objetos

-- de datos del mismo tipo

mensaje2 ( 63 ) <= arreglo_matriz ( 5, 13 ) ; -- transfiere el valor de un


elemento

-- de arreglo_matriz a un elemento de

-- mensaje2, ambos son arreglos del tipo

-- std_logic_vector

A continuación se muestra un ejemplo de una declaración del tipo RECORD.

TYPE operacion IS ( add, sub, mul, div ) ;

TYPE instruccion IS RECORD

operador: operacion ;

op1: integer ;

op2: integer ;

END RECORD ;

Aquí está la declaración de dos objetos usando la declaración del tipo RECORD anterior.

VARIABLE instruccion1, instruccion2: instruccion ;

A continuación se muestran algunas posibles maneras de asignar valores a elementos de


estos objetos de datos.

instruccion1.operador := add ; -- asigna un valor a "operador" del

-- RECORD instruccion1

instruccion2.operador := sub ; -- asigna un valor a "operador" de

-- instruccion2

22 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

instruccion1.op1 := instruccion2.op2 ;

instruccion2 := instruccion1 ;

A continuación se exponen los tipos compuestos que son comúnmente utilizados en síntesis
de circuitos utilizando VHDL.

bit_vector signed

std_logic_vector unsigned

Bit_Vector

El tipo bit_vector es arreglo del tipo bit, en orden ascendente o descendente. Un bit_vector
se declara como se muestra a continuación.

ORDEN ASCENDENTE

SIGNAL vector1, vector2: bit_vector ( 0 TO 3 ) ; -- vector1(0) y vector2(0)


son

-- el bit más significativo

ORDEN DESCENDENTE

SIGNAL x2, y2: bit_vector ( 3 DOWNTO 0 ) ; -- x2(3) es el bit más


significativo

-- del vector x2 al igual que

-- y2(3) del vector y2

Los valores asignados al tipo bit_vector deben ser especificados con comillas dobles (" ") y
los valores asignados al tipo bit simple son asignados con comillas simples (' ').
El prefijo 'X' o 'x' denota un valor hexadecimal; los prefijos 'O' y 'o' denotan un valor octal;
el prefijo 'B' o 'b' denota un valor binario. Si ningún prefijo es especificado, se asume el
prefijo binario.
Las asignaciones en hexadecimal y octal deben usarse únicamente si el valor puede
combinarse directamente con el tamaño del vector. Por ejemplo, sí 'a' es un bit_vector ( 0
TO 6 ), entonces la asignación a <= x"B", no podrá hacerse porque el numero hexadecimal
'B' usa cuatro de bits y no equipara el tamaño del vector al que está siendo asignado.

EJEMPLOS

x1 <= "0001" ;
std_logic_vector

23 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

signed y unsigned

El estándar 1076.3 de la IEEE es un paquete para VHDL en el cual se definen nuevos tipos
de datos además de funciones aritméticas y lógicas para ser utilizadas por herramientas de
síntesis. Éste define dos paquetes: el numeric_std y el numeric_bit en los que se define dos
nuevos tipos de datos: signed y unsigned. Estos tipos son parecidos a los tipos
std_logic_vector o bit_vector y son parte de una norma emergente (IEEE 1076.3) para
desempeñar operaciones numéricas sobre señales vectorizadas. El paquete numeric_bit
define a estos tipos (unsigned y signed) como un vector cuyos elementos son del tipo bit y
el paquete numeric_std define los mismos pero con elementos del tipo std_logic.
El propósito de estos dos tipos es el de representar números enteros positivos y negativos
en forma binaria. Para ambos tipos, el bit más significativo está a la izquierda. El tipo
signed se utiliza para representar un número entero con signo en forma binaria con
complemento a dos, y el unsigned es solamente un número entero sin signo en forma
binaria. El paquete numeric_std define funciones y operadores aritméticos, relacionales,
lógicos y de asignación para ser utilizados con estos tipos de datos. Signed, unsigned y
std_logic_vector son tipos diferentes por lo que no se pueden mezclar. Sin embargo, varias
funciones de conversión, tales como to_unsigned, son definidas para la conversión entre
los tipos.

3.4.3 Subtipos

Un subtipo es un "subgrupo" de un tipo predefinido. Los subtipos son útiles para crear tipos
de datos con limitaciones sobre tipos mayores.

DECLARACIÓN DE SUBTIPOS

SUBTYPE identificador IS tipo_base RANGE valor ( DOWNTO / TO ) valor ;

EJEMPLOS

SUBTYPE byte IS std_logic_vector ( 7 DOWNTO 0 ) ;

SUBTYPE digito IS integer RANGE ( 0 TO 9 ) ;

Estos ejemplos definen dos subtipos llamados byte y digito. Las señales o variables que son
declaradas como byte son del tipo std_logic_vector de 8 bits en orden descendente. Las
señales o variables que sean declaradas como tipo digito serán del tipo entero, consistiendo
de los posibles valores de los enteros del 0 al 9, inclusive.
En los siguientes ejemplos se muestra como se pueden crear subtipos de datos a partir de
aquellos tipos que sean definidos por el usuario.

EJEMPLOS

TYPE aritmetico IS ( add, sub, mul, div ) ;

SUBTYPE add_op IS arith_op RANGE add TO sub;

24 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

SUBTYPE mul_op IS arith_op RANGE mul TO div;

3.5 Operadores
Un operador nos permite construir diferentes tipos de expresiones mediante los cuales
podemos calcular datos utilizando los diferentes objetos de datos con el tipo de dato que
maneja dicho objeto. En VHDL existen distintos operadores de asignación con lo que se
transfieren valores de un objeto de datos a otro, y operadores de asociación que relacionan
un objeto de datos con otro, lo cual no existe en ningún lenguaje de programación de alto
nivel.
El uso de los operadores que aquí son expuestos dependerá del software utilizado, ya que
no es regla que los utilicen todos. Para conocer las operaciones que pueden ser utilizadas
así como los paquetes incluidos en el software, es recomendable revisar las librerías del
programa. De no encontrarse algún operador especial para ser utilizado con algún tipo de
dato especifico, es necesario sobrecargar los operadores o en ocasiones crearlo. Como
sobrecargar operadores y como crear funciones se expone dentro del tema de
subprogramas. Para poder utilizar la mayoría de estos operadores con los tipos signed,
unsigned y std_logic_vector, basta con utilizar el paquete donde se encuentran declarados
estos tipos, porque dentro de los mismos paquetes ya se encuentran sobrecargada varias
funciones aritméticas y lógicas para que sean utilizadas con estos tipos, en temas
posteriores se incluyen las funciones que se encuentran en los paquetes std_logic_1164,
numeric_std y numeric_bit.

TIPOS DE OPERADORES

Lógicos
AND, OR, NAND, NOR, XOR, XNOR, NOT
Comparación =, /=, <, >, <=, >=
Adición +, -, &
Multiplicación *, /, MOD, REM
Misceláneo abs, **
Asignación <=, :=
Asociación =>

Corrimiento
SLL, SRL, SLA, SRA, ROL, ROR

3.5.1 Operadores Lógicos

Los operadores lógicos AND, OR, NAND, NOR XOR, XNOR, y NOT están definidos para
ser usados con los tipos bit y boolean. Para utilizar estos operadores, excepto el operador
NOT, los operandos deben ser del mismo tamaño.
Los operadores lógicos no tiene orden de precedencia por lo que para expresiones en las
que se utilice más de un operador lógico es necesario indicar mediante paréntesis cual es el
orden en que se debe realizar el cálculo.

25 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

EJEMPLO

-- esta forma de utilizar los operadores

-- lógicos, es incorrecta y producirá


x <= y AND z OR w
-- un error cuando sea compilado

-- el código

-- forma correcta de utilizar los operadores


x <= y AND ( z OR w )
-- lógicos

3.5.2 Operadores de Comparación

Estos tipos de operadores se utilizan para ejecutar pruebas de igualdad, desigualdad, o de


magnitud entre dos objetos de datos. Los operandos que participen en la prueba deben ser
del mismo tipo y el resultado de la operación es del tipo boolean. Los operadores de
igualdad y desigualdad (= y /=) pueden ser utilizados para todos los tipos de datos
predefinidos en el lenguaje Los operadores de magnitud ("<" menor que, ">" mayor que,
"<=" menor o igual que, y ">=" mayor o igual que) están definidos para ser utilizados con
tipos escalares.

EJEMPLO

SIGNAL x, y: bit_vector ( 3 DOWNTO 0)

SIGNAL z : bit;

···

z <= '1' WHEN x >= z ELSE '0';

3.5.3 Operadores de Adición

Los operadores + y - son frecuentemente utilizados para describir sumas y restas además
de signos positivo y negativo. Están definidos para ser utilizados con el tipo entero y
también para el tipo bit. El operador "&" permite concatenar cadenas de bits obteniendo
una de mayor tamaño. Los tres operadores tienen la misma precedencia, por lo que para
instrucciones en la que se utiliza más de un operador de este tipo es recomendable indicar
mediante paréntesis el orden de las operaciones. Para poder realizar operaciones de suma o
resta entre un entero y un objeto de datos que represente una cadena de bits, lo mejor es
declarar este objeto de datos como signed o unsigned e incluir el paquete numeric_std o el
numeric_bit, ya que en estos se sobrecargaron los operadores "+" y "-" para que pudieran

26 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

ser utilizados de esta manera. De lo contrario resultaría en un error de compilación al


realizar dichas operaciones. Por otra parte no es posible realizar sumas entre bit_vectors de
diferente tamaño, y tampoco podremos asignar el resultado de una suma o resta entre dos
bit_vectors a un bit_vector de diferente longitud. Si se desea obtener el acarreo de la suma
del resultado de una operación aritmética entre dos bit_vectors de la misma longitud, a un
bit_vector que sea de mayor longitud en un bit, se permite utilizar el operador de
concatenación para incrementar el tamaño solamente en el primer bit_vector que participa
en la operación, con lo cual se indica que deseamos obtener el acarreo de la suma.

EJEMPLOS

SIGNAL conteo: integer RANGE 0 TO 255;

SIGNAL x, y, z: signed( 7 downto 0);

SIGNAL r, m: signed( 8 downto 0);

···

conteo <= conteo + 1;

x <= y + z + 5;

-- de esta manera se obtiene el acarreo


r <= '0'z + x;
-- de la suma

m <= r +1;

3.5.4 Operadores de Multiplicación

Son los operandos "*" y el "/" que se utilizan para la multiplicación y para la división
respectivamente. Los dos operandos tienen el mismo orden de precedencia al igual que los
operandos MOD y REM.

Todos los operandos de multiplicación están definidos para ser utilizados con operandos
del mismo tipo, siendo estos del tipo entero o bit_vector. El resultado es entonces del
mismo tipo que los operandos por lo que también el objeto de datos que recibe el resultado
de la operación deberá ser del mismo tipo que los operandos.

La operación REM se define como se muestra a continuación:

A REM B = A-(A/B)*B

La división es entera, por lo que los operandos deben ser del tipo entero. El resultado toma

27 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

el signo de A.

MOD, calcula el modulo de dos números. Se define como:

A MOD B = A-B*N

Donde N es un entero. El resultado toma el signo de B.

3.5.5 Operadores Misceláneos

En esta categoría se encuentran los operadores "abs" y "**". El operador "abs" devuelve el
valor absoluto de un operando del tipo entero. El operador "**" se utiliza para elevar el
primer operador a una potencia definida por el segundo operando, ambos deben ser del
tipo entero.

EJEMPLO

CONSTANT r: integer := 2;

VARIABLE i: integer;

···

FOR n IN 0 TO 5 LOOP

···

i := i + r**n;

···

END LOOP;

3.5.6 Operadores de Asignación

En VHDL existen dos tipos de operadores de asignación los cuales son: "<=" y ":=". El
operador ":=" se utiliza para asignar un valor inicial a constantes, variables y señales en el
momento de la declaración, pero para el resto de la descripción únicamente utilizaremos
":=" para ser usado con variables y "<=" para ser usado con señales.

ASIGNACIÓN A VARIABLES

nombre_variable := expresión;

ASIGNACIÓN A SEÑALES

28 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

nombre_señal <= expresión;

Las asignaciones a variables solamente pueden ocurrir dentro de los procesos (PROCESS),
las asignaciones a señales pueden ocurrir en cualquier lugar dentro de la descripción.
Para realizar asignaciones a objetos de datos de tipos compuesto, se pueden realizar
utilizando agregados. Los agregados son una lista de varios valores encerrados entre
paréntesis y separados mediante comas de tal forma que el primer elemento de la lista es
asignado al primer elemento del objeto, el segundo elemento de la lista es asignado al
segundo elemento del objeto de datos etc. Así mediante una sola instrucción se asignan
varios valores al objeto de datos.

EJEMPLOS

TYPE operacion IS ( suma, resta, mult, div );

TYPE reg_datos IS RECORD

operador: operacion.

x: integer;

y: bit;

END RECORD;

···

VARIABLE registro: reg_datos;

SIGNAL vector1, vector2: std_logic_vector( 0 TO 3 );

···

vector1 <= ( '0', '1', '1', '0' ); -- asignacion mediante agregados

-- tambien esta es una asignacion


vector2 <= vector1;
-- mediante agregados

-- asignacion a variable del tipo


registro := ( resta, 13, '1' );
-- record mediante agregados

-- en esta asignacion se hace '1'


vector2 <= ( '1', others => '0' );
--el elemento 0 de vector2 y el

29 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

resto

-- se hacen cero

3.5.7 Operadores de Asociación

En diseños jerárquicos generalmente se hace uso de varios componentes, los cuales son
entidades que realizan ciertas funciones especificas. Para poder especificar las conexiones
de puertos entre dichos componentes y con los puertos de la entidad principal es necesario
utilizar el operador de asociación "=>". El orden con el que se asocian dichas conexiones
depende del orden en el que fueron declarados los puertos del componente, además, deben
ser del mismo tipo y del mismo modo. Diseños jerárquicos y componentes se explicaran
detalladamente en temas posteriores. A continuación se muestra un ejemplo de cómo
utilizar este operador de asociación.

EJEMPLO

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

LIBRARY mi_libreria;

USE mi_libreria.sumadores.ALL;

ENTITY sumador IS

PORT ( ci: IN std_logic;

x: IN std_logic_vector( 3 DOWNTO 0 );

y: IN std_logic_vector( 3 DOWNTO 0 );

z: OUT std_logic_vector( 3 DOWNTO 0 );

co: OUT std_logic);

END sumador;

ARCHITECTURE a_sumador OF sumador IS

SIGNAL carry1: std_logic;

SIGNAL carry2: std_logic;

SIGNAL carry3: std_logic;

BEGIN

u0: add PORT MAP ( ci => ci,

x0 => x(0),

y0 => y(0),

z0 => z(0),

30 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

co => carry1 );

u1: add PORT MAP ( ci => carry1,

x0 => x(1),

y0 => y(1),

z0 => z(1),

co => carry2 );

u2: add PORT MAP ( carry2, x(2), y(2), z(2), carry3 );

u3: add PORT MAP ( carry3, x(3), y(3), z(3), co );

END a_sumador;

El componente "add" esta declarado dentro del paquete "sumadores" de la librería


"mi_librería", y esta declarado de la siguiente manera.

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

-- SUMADORES

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

-- paquete compilado en la librería "mi_librería"

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

PACKAGE sumadores IS

···

COMPONENT add

PORT ( ci: IN std_logic;

x0: IN std_logic;

y0: IN std_logic;

z0: OUT std_logic;

co: OUT std_logic );

END COMPONENT;

···

END PACKAGE;

Observe como los puertos de la entidad "sumador" y las conexiones entre los bloques u0,
u1, u2 y u3, se hicieron de acuerdo al orden en que los puertos están declarados en el

31 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

componente. En el bloque u0 primero se hace la conexión del puerto "ci" del componente
con el puerto "ci" de la entidad mediante le operador de asociación "=>", después se hace
la conexión del puerto x0 del componente con el elemento 0 (LSB) del vector x de la
entidad, y así sucesivamente hasta realizar todas las conexiones del componente "add"
utilizado en el bloque u0. Lo mismo se hace con el bloque u1. En los bloques u2 y u3, las
conexiones se realizaron con una notación equivalente pero simplificada. Los nombres no
tienen que ser necesariamente los mismos e inclusive pueden ser diferentes, ya que cada
puerto es un objeto de datos local para la entidad en la que fue declarado. Es importante
mencionar que dentro del paquete "sumadores" se encuentra la entidad y la arquitectura
correspondiente al componente "add", en los que se describe el componente "add".

3.5.8 Operadores de Corrimiento

Incluidos en los paquetes numeric_std y numeric_bit, estos operadores realizan


operaciones de desplazamiento o de rotación con los elementos de un vector.

DESPLAZAMIENTOS LÓGICOS SLL y SRL


Desplazan los bits de un vector n veces a la izquierda (SLL) o a la derecha (SRL),
introduciendo ceros en los lugares que quedan libres.

EJEMPLO

x SRL 3 -- desplaza 3 lugares a la derecha los

-- bits del vector "x"

DESPLAZAMIENTOS ARITMÉTICOS SLA y SRA


También desplazan los bits de un vector n veces a la izquierda (SLA) o a la derecha
(SRA), introduciendo ceros en los lugares que quedan libres, pero conservan el signo.

ROTACIONES ROL y ROR


Se desplazan los bits de un vector n veces a la izquierda (ROL) o a la derecha (ROR),
introduciendo los bits que son desplazados en los lugares que van quedando libres.

3.5.9 Operaciones con Vectores

Todas las herramientas de síntesis proporcionan algún tipo de paquete en el que se


encuentre definidas funciones que facilitan la descripción del diseño. Dentro de estos
paquetes se encuentran funciones que están hechas específicamente para ser utilizadas con
vectores y como por lo general es preferible utilizar vectores estos paquetes son de gran
ayuda.
Synopsys desarrolló paquetes basados en el paquete std_logic_1164, que son utilizados por
varias herramientas de síntesis existentes en el mercado, como por ejemplo
FOUNDATION de Xilinx, Inc. y MAX+PLUS II de Altera Corporation. Estos paquetes
son:

std_logic_arith

32 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

std_logic_signed

std_logic_unsigned

La compañía Actel también desarrolló su propio paquete de síntesis:

asyl.arith

Y los paquetes que fueron desarrollados por la IEEE específicamente para síntesis de
circuitos digitales.

numeric_bit

numeric_std

Además del paquete que es el más utilizado por la mayoría de los paquetes de síntesis.

std_logic_1164

Todos estos paquetes son los más conocidos y utilizados para síntesis de circuitos, por lo
que para poder utilizarlos primero debemos de llamar la librería en que fueron compilados
para posteriormente hacer referencia al paquete que deseamos utilizar (una librería puede
tener más de un paquete) como se muestra a continuación.

EJEMPLO

LYBRARY ieee; -- llamado a la librería

USE ieee.std_logic_1164.ALL; -- referencia o carga del paquete

-- std_logic_1164

-- "all" es para indicar que deseamos utilizar

-- todos los tipos de datos y funciones

-- incluidas en el paquete

USE ieee.numeric_std.ALL; -- referencia al paquete numeric_std

3.6 Atributos

33 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Un atributo es una propiedad que es asociada a señales, entidades o arquitecturas. Estos


atributos proporcionan información que nos puede ser útil dentro de una descripción en
VHDL. Los atributos se utilizan mediante la comilla simple, por ejemplo el atributo 'event,
que probablemente sea el más utilizado, nos permite detectar cuando sucede una transición
de estado en una señal, por lo que es muy útil en descripciones de circuitos secuenciales.

REFERENCIA A ATRIBUTOS

nombre_objeto'nombre_atributo

EJEMPLO

IF ( clk'event and clk = '1' ) THEN

A <= '1' ;

END IF ;

En el ejemplo anterior se utiliza el atributo 'event, indicado en color verde, para detectar
una transición en la señal clk, y al mismo tiempo comprobamos si esta transición fue
positiva. Si ambas condiciones se cumplen entonces se asigna un '1' lógico a "A". El
atributo 'event se utiliza solo para señales de clk ya que de otra manera no es posible
sintetizar una transición en un dispositivo lógico programable, por lo que también debemos
indicar que tipo de transición estamos utilizando.
Existen más atributos y a continuación mencionaremos algunos que son útiles en
descripciones para síntesis.

ATRIBUTOS DE VALOR

'left -- obtiene el valor que se

-- encuentra a la izquierda de un

-- objeto de datos

´right -- regresa el dato que se encuentra a

-- la derecha del objeto

´high -- permite obtener el mayor elemento

-- de un objeto de datos

´low -- proporciona el valor más

-- pequeño

ATRIBUTOS DE VALOR EN ARREGLOS

34 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

´lenght -- con este atributo se obtiene el

-- número de elementos de un objeto

Un arreglo (array) es un objeto de datos que esta compuesto por varios elementos de un
tipo sencillo, como lo son los bit_vectors, std_logic_vectors etc.

ATRIBUTOS DE SEÑALES

'event -- el atributo event es del tipo

-- boolean y retorna un valor

-- verdadero cuando ocurre

-- una transición en la señal a

-- la que se hace referencia

EJEMPLOS

TYPE secuencia IS integer RANGE 0 TO 10

SIGNAL conteo: secuencia ;

conteo'left = 0

conteo'rigth = 10

conteo'lenght = 11

conteo'high = 10

conteo'low = 0

3.7 Entidades

Una entidad es la abstracción de un circuito, ya sea desde un complejo sistema electrónico


hasta una simple compuerta lógica. La entidad únicamente describe la forma externa del
circuito, aquí se enumeran las entradas y salidas del diseño. Una entidad es análoga a un
símbolo esquemático de los diagramas electrónicos, el cual describe las conexiones del
dispositivo hacia el resto del diseño.

DECLARACION DE ENTIDADES

35 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

ENTITY identificador IS

GENERIC ( cte_1: tipo := valor

cte_2: tipo := valor

···

cte_n: tipo := valor


-- IMPORTANTE
);
-- Nótese que la ultima línea de

-- declaración de puerto o de
PORT ( puerto_1: modo tipo ;
-- genéricos no lleva punto y coma
puerto_2: modo tipo ; -- al final de la línea
···

puerto_n: modo tipo

);

END identificador ;

EJEMPLO

Figura 3.2 Multiplexor de 4 bits a 1

-- mux_4_1

ENTITY mux_4_1 IS

PORT ( a, b, c, d: IN bit; -- bits de entrada

mux_signal: IN bit_vector ( 1 DOWNTO 0 ) ; -- bus para la

-- multiplexacion

x: OUT bit ) ; -- bit de salida

END mux_4_1 ;

3.7.1 Genéricos
Esta instrucción es opcional y se utiliza para declarar propiedades y constantes del circuito.
Estas constantes se utilizan al igual que las que se declaran por el usuario, por lo que nos
permiten modelar circuitos en los que se pueden cambiar propiedades, tamaños de los
buses de entrada o salida del circuito. Se utilizan generalmente en paquetes.

36 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

EJEMPLO

ENTITY comparador IS

GENERIC ( msb: integer := 3 );

PORT( x: IN bit_vector( msb DOWNTO 0 ) ;

y: IN bit_vector( msb DOWNTO 0 ) ;

equals: OUT bit ;

x_may_y: OUT bit ;

x_men_y; OUT bit );

END comparador;

3.7.2 Puertos

Cada entrada y salida de la entidad se declara dentro de la región puertos (PORT), en el


momento de la declaración se debe indicar el modo y tipo del puerto. Los puertos los
podemos asociar con los pines de un símbolo esquemático y, al igual que estos, algunos son
únicamente entradas, otros salidas, o incluso bidirecionales. Un puerto es implícitamente
un objeto de datos del tipo señal porque representa conexiones en el diseño, y puede ser
utilizado en expresiones de programación dentro de la arquitectura que describe a dicha
entidad. Cada puerto debe tener un nombre, un modo y se debe especificar el tipo de dato
mediante el cual manipularemos dicho puerto en la descripción.

3.7.3 Modos

El modo indica la forma en que los datos fluyen a través del circuito. Estos pueden ser de
uno de cuatro tipos:

IN

OUT

INOUT

BUFFER

Si no se indica ningún modo en la declaración, se asume que es del tipo IN.


Un puerto del modo IN describe un pin del circuito que únicamente puede ser utilizado
como entrada por lo que solamente podremos leer datos de dicho puerto y nunca escribir
sobre él. Por el contrario, un puerto que sea declarado del modo OUT podrá ser utilizado
para escribir datos pero no para ser leído, este representa un pin que únicamente es salida
del circuito y que en él no existe ningún tipo de retroalimentación hacia dentro del diseño.
Un puerto INOUT indica aquellos puertos que son pueden ser utilizados bidireccionalmente
mientras que un puerto del modo BUFFER es utilizado para salidas que tienen
retroalimentación interna.

37 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

La diferencia entre el modo BUFFER y el INOUT, es que el INOUT es retroalimentado


desde el pin de salida del circuito, en tanto que como un puerto del modo BUFFER lo hace
internamente no puede ser usado como bidireccional.

FIGURA 3.3 Modos de direccionamiento para puertos

3.8 Arquitecturas

Los pares de entidades y arquitecturas se utilizan para representar la descripción completa


de un diseño. Una arquitectura, describe el funcionamiento de la entidad a la que hace
referencia. Si una entidad la asociamos con una "caja" en la que se enumeran las interfaces
de conexión hacia el exterior, entonces la arquitectura representa la estructura interna de
esa caja. Por ejemplo, el símbolo esquemático de un 74LS04 representaría la entidad del
diseño, y la forma en que las compuertas son conectadas internamente corresponden a la
arquitectura del circuito, y así ambos describen completamente el circuito.

ENTIDAD

Símbolo Esquemático

ARQUITECTURA

Estructura Interna

FIGURA 3.4 74LS90

DECLARACION DE ARQUITECTURA

ARCHITECTURE identificador_arquitectura OF nombre_entidad IS

-- declaraciones de la arquitectura

BEGIN

38 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

-- código de descripción

END identificador_arquitectura ;

Antes del BEGIN se escriben todas las declaraciones que se necesiten dentro de la
descripción, tales como: señales, constantes, funciones, alias, componentes, tipos de datos
etc. Después del BEGIN es donde se realiza todo el código de descripción del circuito.

EJEMPLO

-- mux_4_1

ENTITY mux_4_1 IS

PORT ( a, b, c, d: IN bit ; -- bits de entrada

mux_signal: IN bit_vector( 1 DOWNTO 0 ) ; -- bus para la


multiplexación

x: OUT bit ) ; -- bit de salida

END mux_4_1 ;

ARCHITECTURE a_mux_4_1 OF mux_4_1 IS

BEGIN

x <= a WHEN mux_signal = "00" ELSE

b WHEN mux_signal = "01" ELSE

c WHEN mux_signal = "10" ELSE

d WHEN mux_signal = "11" ;

END a_mux_4_1 ;

Una arquitectura describe el comportamiento, estructura o flujo de datos de la entidad a la


que hace referencia. Una entidad puede tener más de una arquitectura, pero cuando se
compile se indica cual es la arquitectura que queremos utilizar. Para describir el
funcionamiento de la entidad se puede hacer uso de cualquiera de los tres estilos
siguientes:

DESCRIPCIÓN DE FLUJO DE DATOS

DESCRIPCIÓN COMPORTAMENTAL

DESCRIPCIÓN ESTRUCTURAL

Los tres estilos son diferentes, pero esto no significa que se tenga que utilizar únicamente
un estilo. De hecho lo mejor es tratar de utilizar los tres como mejor nos convenga. En el
siguiente tema se explica el estilo de descripción de flujo de datos, así como el tipo de
instrucciones que participan en este estilo.

39 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

3.9 Descripciones de Flujo de Datos


Una descripción de flujo de datos consiste en especificar como los datos son transferidos
de las entradas a las salidas. Cabe mencionar que algunos autores distinguen las
descripciones de flujo de datos de las comportamentales, en tanto que para otros ambos
estilos son del tipo comportamental. La principal diferencia entre estas es el tipos de
instrucciones que utilizan, además que en un estilo comportamental se utiliza el bloque
PROCESS en tanto que en el estilo en cuestión no se utiliza.

En este estilo de descripción se utilizan únicamente asignaciones mediante expresiones en


las que se indica como cambian las puertos de salida en función de los puertos de entrada,
ya sean asignaciones condicionales mediante instrucciones concurrentes o simples
ecuaciones. Un ejemplo de descripción de flujo de datos es el comparador utilizado en el
primer ejemplo, en éste los datos son los que indican la forma en que cambian las salidas y
es por esto que se le llama de flujo de datos.

3.9.1 Instrucciones Concurrentes

En lenguajes de programación como C o Pascal, cada instrucción de asignación es


ejecutada una después de otra en un orden especifico. El orden en el que las instrucciones
son ejecutadas es determinado por el orden de las instrucciones en el archivo. Dentro de
una arquitectura en VHDL, no existe un orden especifico de ejecución de las asignaciones.
El orden en el que las instrucciones son ejecutadas depende de los eventos ocurridos en las
señales, similar al funcionamiento de un circuito.
En VHDL todos los bloques son concurrentes, es decir que se están ejecutando en todo
momento. Después se explicará el bloque PROCESS, el cual está compuesto por una serie
de instrucciones que sí se ejecutan en el orden en el que fueron especificadas.
Las instrucciones concurrentes se utilizan fuera de un bloque PROCESS, a diferencia de
las instrucciones secuenciales que únicamente se utilizan dentro del bloque concurrente
PROCESS y en subprogramas.

3.9.2 Estructuras de Ejecución Concurrente

Asignación condicional WHEN... ELSE

SINTAXIS

EJEMPLO signal_identificador <= valor_aWHEN condición ELSE

valor_b WHEN condición ELSE


x <= '1' WHEN seleccion = x"4" ELSE '0' ;
×

×
Asignación WHIT... SELECT... WHEN
×
SINTAXIS
valor_n WHEN condición ELSE

otro_valor ;

40 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

WITH identificador SELECT

signal_identificador1 <= expresión WHEN valor1_identificador,

valor_a WHEN valor2_identificador,

valor_b WHEN valor3_identificador,

···

valor_n WHEN OTHERS ;

EJEMPLO

WITH states SELECT


-- IMPORTANTE
salida <= "000" WHEN state0,
-- no olvidar la coma al final de
"001" WHEN state1,
-- cada línea, excepto la ultima
"010" WHEN state2,
-- que lleva punto y coma
"100" WHEN state3,

"000" WHEN OTHERS ;

Ecuaciones Booleanas

signal_identificador <= ecuación_booleana ;

EJEMPLOS

x <= y AND z ;

a <= ( b OR c OR d ) -- cuando se utilice más de un operador

AND e ; -- lógico es necesario utilizar paréntesis

op1 <= op2 NOR op3

NOR op4;

3.9.3 Ejemplo

41 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

A continuación se muestra la tabla de funcionamiento de una pequeña unidad aritmético -


lógica la cual consta de dos bits de entrada, un bit de salida, acarreo de entrada y acarreo
de salida.

TABLA DE FUNCIONAMIENTO

ENTRADAS
SALIDAS
s1 s0 z co
0 0 x AND y 0
0 1 x OR y 0
1 0 x XOR y 0
1 1 x + y + ci acarreo de la
suma

CODIGO DE DESCRIPCIÓN

LIBRARY ieee ;

USE ieee.std_logic_1164.ALL ;

USE ieee.numeric_std.ALL ;

ENTITY alu IS

PORT ( x, y: IN std_logic ;

s0, s1: IN std_logic ;

ci: IN std_logic ;

z: OUT std_logic ;

co: OUT std_logic ) ;

END alu ;

ARCHITECTURE a_alu OF alu IS

SIGNAL seleccion: unsigned ( 1 DOWNTO 0 ) ;

SIGNAL suma: std_logic ;

SIGNAL and_op: std_logic ;

SIGNAL or_op: std_logic ;

SIGNAL xor_op: std_logic ;

SIGNAL acarreo: std_logic ;

BEGIN

and_op <= x AND y ;

WITH seleccion SELECT

z <= or_op WHEN "01",

42 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

and_op WHEN "00",

suma WHEN "11",

xor_op WHEN "10",

'0' WHEN OTHERS ;

seleccion <= s1 & s0 ;

suma <= x XOR y XOR ci ;

or_op <= x OR y ;

acarreo <= ( x AND y ) OR

(x AND ci ) OR

( y AND ci ) ;

xor_op <= x XOR y ;

co <= acarreo WHEN seleccion = 3 ELSE '0' ;

END a_alu ;

Este circuito se sintetizo en un GAL22V10 utilizando WARP 5.0 de Cypress


Semiconductors. Obsérvese que en el código de descripción de esta alu no existe ningún
orden en las ecuaciones, asignaciones o instrucciones, de hecho el orden en el que se
coloquen las instrucciones no importa dentro de una descripción, recordemos que VHDL
describe circuitos y por lo tanto todas las asignaciones siempre están funcionando al igual
que todos los dispositivos dentro de un circuito.

DIAGRAMA A BLOQUES

43 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Figura 3.5 Diagrama a bloques de la ALU

Las señales suma, acarreo, and_op, or_op y xor_op son las salidas de varios bloques del
circuito, cada uno con una función distinta. El bus "seleccion" se compone de los dos bits
de entrada s0 y s1, estas se juntan en este bus únicamente para facilitarnos la descripción.
Y mediante los bloques de la instrucción WITH... SELECT... WHEN y la instrucción
WHEN... ELSE se asignan los datos correspondientes a cada salida de a cuerdo a las
combinaciones de los bits s0 y s1.

El que hayamos realizado la descripción con tantos bloques no significa necesariamente


que cuando el compilador sintetice el código respete todos esos bloques y quede
exactamente como lo describimos dentro del dispositivo que seleccionamos. El compilador
de WARP interpreta nuestra descripción y la sintetiza dentro del dispositivo utilizando el
mínimo de compuertas posible al mismo tiempo que trata de respetar la descripción del
código, además, que por lo general trata de evitar retroalimentaciones para que el
dispositivo funcione a altas velocidades. De hecho en ocasiones es posible que existan
todavía macroceldas libres, pero como el compilador evita retroalimentaciones, entonces
no las usa. Como indicar que se usen esas macroceldas libres se explicará posteriormente,
ya que este circuito sí puede quedar dentro de un GAL16V8 utilizando directivas de
síntesis. A continuación se muestran las ecuaciones, la asignación de pines y el informe de
utilización del dispositivo obtenidos por el compilador de WARP.

ECUACIONES

----------------------------------------------------------------------------
PLD Compiler Software: MAX2JED.EXE 02/APR/1999 [v4.02 ] 5.2 IR 17

DESIGN EQUATIONS (05:56:54)

44 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Completed Successfully

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

PIN - OUT

----------------------------------------------------------------------------
PLD Compiler Software: PLA2JED.EXE 02/APR/1999 [v4.02 ] 5.2 IR 17

PINOUT INFORMATION (06:15:24)

Messages:

Information: Checking for duplicate NODE logic.

None.

Summary:

Error Count = 0 Warning Count = 0

45 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Completed Successfully
----------------------------------------------------------------------------

UTILIZACIÓN

----------------------------------------------------------------------------
PLD Compiler Software: PLA2JED.EXE 02/APR/1999 [v4.02 ] 5.2 IR 17

RESOURCE UTILIZATION (06:15:25)

Information: Macrocell Utilization.

Information: Output Logic Product Term Utilization.

Completed Successfully
----------------------------------------------------------------------------

3.10 Descripciones Comportamentales


Las descripciones comportamentales son similares a un lenguaje de programación de alto
nivel, por su alto nivel de abstracción. Mas que especificar la estructura o la forma en que
se deben conectar los componentes de un diseño, nos limitamos a describir su
comportamiento. Una descripción comportamental consiste de una serie de instrucciones,

46 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

que ejecutadas secuencialmente, modelan el comportamiento del circuito. La ventaja de


una descripción comportamental es que no necesitamos enfocarnos a un nivel de
compuerta para implementar un diseño. En VHDL una descripción comportamental
necesariamente implica el uso de por lo menos un bloque PROCESS.

3.10.1 Instrucciones Secuenciales

Las instrucciones secuenciales son aquellas que son ejecutadas serialmente, una después
de otra. La mayoría de los lenguajes de programación, como C o Pascal, utilizan este tipo
de instrucciones. En VHDL las instrucciones secuenciales son implementadas únicamente
dentro del bloque PROCESS

3.10.2 Procesos

Un proceso es el bloque básico concurrente de codificación secuencial. Contiene una serie


de instrucciones secuenciales que permiten modelar el comportamiento del circuito, sin
embargo, el bloque PROCESS equivale a una sola instrucción concurrente. Un proceso
puede ser utilizado dentro de cualquier arquitectura definiendo para si mismo una región de
declaraciones y otra para la codificación secuencial, similar a una arquitectura. La región
de codificación puede contener únicamente instrucciones secuenciales (IF, CASE, FOR,
etc.) en tanto que la región de declaraciones permite designar constantes, señales, tipos de
datos o algún alias.

SINTAXIS

PROCESS ( lista sensible )

-- declaraciones

BEGIN

-- instrucciones secuenciales

END PROCESS ;

La lista sensible es opcional y define cuales señales provocan que las instrucciones dentro
del bloque comiencen a ser ejecutadas. Los cambios en alguna de las señales provocan que
el proceso sea llamado. Un proceso que no tenga lista sensible debe utilizar una instrucción
WAIT para especificar cuando deben ser ejecutadas las instrucciones dentro del bloque.
La mayoría de las herramientas de síntesis tienen problemas si las lista sensible no está
completamente especificada. Estas consideran que mediante el proceso estamos
modelando lógica combinacional o secuencial. La lista sensible es parcialmente declarada
cuando alguna de las señales que intervienen en lado derecho de una ecuación o de alguna
instrucción secuencial no es mencionada dentro de la lista. El que la lista no este completa
generalmente produce que no sea posible modelar totalmente la funcionalidad del diseño y
por lo tanto no es posible obtener las ecuaciones durante el proceso de síntesis.
El funcionamiento del proceso es similar a un microprocesador que funciona únicamente
con interrupciones. La señales dentro de la lista sensible hacen a su vez de entradas de
interrupción y las instrucciones secuenciales se encuentran dentro de una rutina única de
servicio de interrupción. Cuando alguna de las señales de la lista sensible cambia, provoca
que el proceso comience a funcionar y a ejecutar toda esta rutina de ejecución secuencial
con la particularidad de que los que resulte de este procesamiento se asigne únicamente al
final de la estructura. Por lo que podemos manipular los valores de las señales y esto no
implica que cambien con cada asignación sino solamente hasta que se termina de ejecutar
todo el proceso. Y como las asignaciones a los nodos del circuito se hacen al final,

47 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

entonces todo la estructura del proceso es similar a un dispositivo de ejecución secuencial,


como un microprocesador, que forma parte del diseño. Esta comparación con un
microprocesador no implica que siempre debamos especificar una señal de reloj para el
funcionamiento de la estructura, o que únicamente nos permita modelar circuitos
secuenciales. De hecho, si suponemos que la frecuencia de trabajo de este
"microprocesador" es muy grande, entonces las instrucciones dentro de la estructura se
ejecutan tan rápido que prácticamente lo podríamos considerar combinacional. Si alguna
señal de reloj es especificada, entonces estamos limitando a que las instrucciones dentro
del proceso sean ejecutadas únicamente dentro de alguna transición de esta señal, lo cual
no permite describir circuitos secuenciales.

EJEMPLO

A continuación se muestra el código de descripción comportamental del comparador de la


figura 3.5.

Figura 3.5

ENTITY comparador IS

PORT( x: IN bit_vector( 3 DOWNTO 0 ) ;

y: IN bit_vector( 3 DOWNTO 0 ) ;

equals: OUT bit ;

x_may_y: OUT bit ;

x_men_y: OUT bit ) ;

END comparador ;

ARCHITECTURE arch_comparador OF comparador IS

BEGIN

PROCESS ( x, y )

BEGIN

equals <= '0' ;

x_may_y <= '0' ;

x_men_y <= '0' ;

IF x = y THEN

equals <= '1'

48 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END IF ;

IF x > y THEN

x_may_y <= '1',

END IF ;

IF x < y THEN

x_men_y <= '1' ;

END IF ;

END PROCESS ;

END arch_comparador ;

Este ejemplo corresponde al mismo comprador utilizado en el tema 3.1. Se definen 2


vectores de 4 bits y 3 salidas de 1 bit. Esta arquitectura únicamente tiene una instrucción
concurrente: el bloque PROCESS, el cual es sensible a los vectores de entrada. Siempre
que ocurra un cambio en alguno de estos, el proceso será llamado y generará la lógica de
salida. La lista sensible está completa porque, si observamos, el estado de las salidas
depende únicamente de las entradas.
Cada instrucción será ejecutada en orden secuencial y cuando todas hallan sido ejecutadas,
entonces se asigna el valor procesado a los nodos que se vieron afectados durante el
proceso. Una vez que se terminó de ejecutar el proceso, éste se mantendrá inactivo hasta
que alguno dos elementos de la lista sensible cambie.
Cuando se utilicen procesos se debe tener cuidado de no olvidar alguna combinación
posible de entradas y/o salidas retroalimentadas que tal vez no estemos considerando o que
no necesitamos. En estos casos es recomendable utilizar el tipo std_logic o, si son vectores,
algún tipo que se base en este. Los valores '-' y 'Z' del std_logic son permitidos en síntesis
siempre y cuando se utilicen correctamente.

EJEMPLO

ARCHITECTURE simplifica OF entidad_x IS

SIGNAL y_tmp: std_logic ( 1 DOWNTO 0 ) ;

BEGIN

PROCESS ( s )

BEGIN

IF s = 0 OR s = 3 THEN -- s es un vector del tipo unsigned

y_tmp <= '1' ;

ELSIF s = 1 THEN

y_tmp <= '0' ;

ELSE

y_tmp <= '-' ;

END IF ;

49 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END PROCESS ;

y <= y_tmp WHEN enable = '0' ELSE 'Z' ; -- "y" y "y_tmp" son tipo
std_logic;

END simplifica ;

En el ejemplo anterior únicamente nos importan las combinaciones s = 3, s = 1, y s = 0. En


algunos programas de VHDL para síntesis, y también dependiendo de la arquitectura del
dispositivo, la asignación de un "no importa" nos va a permitir que se simplifique la
ecuación de y_tmp, quedando como:

y_tmp = s(1) +s(0)'

De no utilizarla posiblemente quede como:

y_tmp = s(0)'·s(1)' + s(0)·s(1)

3.10.3 Diferencias entre Señales y Variables

Un objeto de datos del tipo señal es muy diferente a uno del tipo variable. Ya se había
mencionado que las señales pueden ser sintetizados en elementos lógicos y/o conexiones,
lo cual no es posible con un variable. Una señal representa un nodo de conexión entre
elementos lógicos (compuertas, registros, buffers, etc.). Inclusive un mismo nodo puede
recibir más de un nombre para facilitar la descripción, sin que esto implique más términos
en las ecuaciones de salida. Una señal que se vea involucrada dentro de un proceso no
recibe inmediatamente el valor asignado, sólo hasta el final del mismo. Una variable que
sea utilizada dentro de un proceso sí recibe el valor de forma inmediata, por lo que son
muy útiles para poder obtener el estado de salida deseado para alguna señal de salida. Una
variable funciona exactamente igual que cualquier variable de cualquier lenguaje de
programación de software.
Podemos decir que una señal está formada por dos partes: un valor actual y un valor futuro
(o valor en proceso). El valor futuro es el que se calcula dentro del proceso y una vez que
se termina el proceso, los valores futuros de todas las señales se convierten en valores
actuales. Al valor futuro se le conoce como driver. En VHDL para síntesis el driver nunca
es afectado fuera de un proceso, fuera de éste siempre estamos modificando el valor
actual.

EJEMPLO

ENTITY proceso IS

PORT ( x, y: IN bit;

z1, z2, z3: OUT bit );

END proceso;

ARCHITECTURE ejemplo_proceso OF proceso IS

BEGIN

50 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

PROCESS ( x, y )

VARIABLE z_var: bit;

SIGNAL z_sig: bit;

BEGIN

z_var := '1'; -- z_var = '1'

z_sig <= '1'; -- driver de z_sig = '1'

z_var := x AND z_var; -- z_var = x AND z_var ('1')

-- z_var = x AND '1'

-- z_var = x

z_sig <= x AND y; -- driver de z_sig = x AND y

z1 <= z_var; -- driver de z1 = z_var = x,

-- esto es valido porque son objetos

-- que manejan el mismo tipo de

-- datos

z2 <= z_sig; -- driver de z2 = z_sig = x AND y

END PROCESS; -- finalizado el proceso,

-- valor actual de z1 = x

-- valor actual de z2 = x AND y

z3 <= x OR y; -- valor actual de z3 = x OR y,

-- en todo momento

END ejemplo_proceso;

Otro detalle importante en VHDL para síntesis, es que el valor actual de una señal no
puede verse modificado más de una vez dentro de la arquitectura, porque las señales

51 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

representan conexiones y esto equivaldría a unir dos cables. Y esto generalmente resultará
en un error de compilación durante el proceso de síntesis.

EJEMPLOS

ARCHITECTURE modificacion_no_valida1 OF senial IS

BEGIN

z <= x AND y;

z <= x OR y;

END modificacion_no_valida1;

ARCHITECTURE modificacion_no_valida2 OF senial IS

BEGIN

PROCESS( x, y )

BEGIN

z <= x OR y; -- driver de z = x OR y

END PROCESS; -- finalizado el proceso,

-- valor actual de z = x OR y

z <= x AND y; -- ERROR, se vuelve a modificar el

-- valor actual de z

END modificacion_no_valida2;

ARCHITECTURE modificacion_valida1 OF senial IS

BEGIN

PROCESS( x, y )

BEGIN

z <= x AND y; -- driver de z = x AND y

52 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

z <= x OR y; -- se modifica el driver de z ,

-- driver de z = x OR y

END PROCESS; -- finalizado el proceso,

-- valor actual de z = x OR y

END modificacion_valida1;

3.10.4 Estructuras de Ejecución Secuencial

IF - THEN - ELSE

SINTAXIS

IF condición THEN

···

ELSIF condición THEN

···

END IF ;

EJEMPLO

SIGNAL conteo: unsigned ( 3 DOWNTO 0 ) ;

···

IF conteo = X"9" THEN

conteo <= ( OTHERS => '0' ) ;

ELSE

conteo <= conteo + 1 ;

END IF ;

CASE - WHEN

CASE expresión IS

WHEN alternativa1 =>

···

53 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

WHEN alternativa2 =>

···

WHEN OTHERS =>

···

END CASE ;

EJEMPLO

TYPE estados IS ( estado1, estado2, estado3, estado4 )

SIGNAL estado_maquina: estados ;

SIGNAL motor, alarma: bit ;

CONSTANT encendido: bit := '1' ;

CONSTANT apagado: bit := '0' ;

···

CASE estado_maquina IS

WHEN estado0 =>

motor <= apagado;

WHEN estado1=>

motor <= encendido;

WHEN ( estado3 OR estado4 ) =>

alarma <= encendido;

WHEN OTHERS =>

motor <= apagado;

alarma <= apagado;

END CASE ;

FOR - LOOP

FOR identificador IN rango LOOP

···

END LOOP ;

EJEMPLO

54 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

FOR i IN 3 DOWNTO 0 LOOP -- i es una variable y no necesita ser declarada

IF reset ( i ) = '1' THEN

data_out ( i ) <= '0' ;

END IF ;

END LOOP ;

WHILE - LOOP

WHILE condición LOOP

···

END LOOP ;

EJEMPLO

contador := 0 ;

resultado_tmp := 0 ;

WHILE contador > 0 LOOP

contador := contador - 1 ;

resultado_tmp := resultado_tmp + data_in ;

END LOOP ;

resultado <= resultado_tmp ;

WAIT

La instrucción WAIT es utilizada en procesos que no tienen una lista sensible, ya que esta
instrucción define implícitamente la lista sensible del proceso.
A continuación se muestran las 3 formas de utilizar la instrucción WAIT.

WAIT ON -- espera los cambios de las

-- señales especificada

WAIT UNTIL -- espera a que se cumpla la

-- condición especificada

WAIT FOR -- detiene la simulación durante

55 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

-- el tiempo especificado

La instrucción WAIT ON no es aceptada por la mayoría de los herramientas de síntesis,


WAIT FOR solo se utiliza para simulaciones. La única forma en que puede ser utilizada la
instrucción WAIT en síntesis sin tener problemas es utilizándola como WAIT UNTIL.

EJEMPLO

PROCESS

BEGIN

WAIT UNTIL rising_edge( clk ) ; -- la función rising_edge viene

-- incluida en el paquete

-- std_logic_1164 y

-- equivale a utilizar:

-- clk'event AND clk = '1'

IF reset = '1' THEN

y <= ( OTHERS => '0' ) ;

ELSE

y <= y + 1 ;

END IF ;

END PROCESS ;

3.11 Descripciones Estructurales


En el siguiente ejemplo se muestra el código para una descripción estructural
correspondiente al circuito de la figura 3.6

Figura 3.6

56 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

LIBRARY mi_librería ;

USE mi_libreria.compuertas.ALL ;

ENTITY ejemplo_structural IS

PORT ( x, y: IN bit ;

z: OUT bit ) ;

END ejemplo_structural ;

ARCHITECTURE estructural OF ejemplo_structural IS

SIGNAL nodo1: bit ;

SIGNAL nodo2: bit ;

SIGNAL nodo3: bit ;

SIGNAL nodo4: bit ;

SIGNAL nodo5: bit ;

BEGIN

U1: not_gate PORT MAP ( x, -- entrada de la compuerta

nodo1 ) ; -- salida de la compuerta

U2: not_gate PORT MAP ( y, -- entrada de la compuerta

nodo2 ) ; -- salida de la compuerta

U3: and_gate PORT MAP ( nodo1, y, -- entradas de la compuerta

nodo3 ) ; -- salida de la compuerta

U4: and_gate PORT MAP ( nodo3, nodo2, -- entradas de la compuerta

nodo4 ) ; -- salida de la compuerta

U5: and_gate PORT MAP ( nodo2, x, -- entradas de la compuerta

nodo5 ) ; -- salida de la compuerta

U4: and_gate PORT MAP ( nodo4, nodo5, -- entradas de la compuerta

z ) ; -- salida de la compuerta

END estructural ;

Esta descripción utiliza entidades descritas y compiladas previamente dentro del paquete
"compuertas" de la librería "mi_librería". Una descripción estructural es similar a un netlist
de PSPICE. Se declaran los componentes que se utilizan y después, mediante los nombres
de los nodos, se realizan las conexiones entre compuertas.
Las descripciones estructurales son útiles cuando se trata de diseños jerárquicos. Este
ejemplo pretende mostrar como son este tipo de descripciones, aunque no es una
aplicación práctica utilizar este estilo con circuitos sencillos como el anterior.

57 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

3.11.1 Componentes

Un componente representa a una entidad declarada en un diseño o librería, la utilización de


componentes es útil en diseños jerárquicos como se mostró en el ejemplo anterior. Para
poder utilizar una entidad que está dentro de otro diseño, es necesario llamar la librería y el
paquete dentro del cual se encuentra esta entidad.

Declaración de componentes

La declaración de componentes se realiza dentro de paquetes o en la región declarativa de


una arquitectura. Es preferible declarar componentes dentro de los paquetes ya que estos
son reutilizables, y por esta razón sólo se verán declaración de componentes dentro de
paquetes y no en arquitecturas, aunque también sea posible. A continuación se muestra la
sintaxis de declaración de componentes.

DECLARACIÓN DE COMPONENTES

COMPONENT identificador_componente

PORT ( identificador{ , identificador}: modo tipo_de_dato

{ ; identificador{ , identificador}: modo tipo_de_dato } ) ;

END COMPONENT ;

EJEMPLO

COMPONENT add

PORT ( a, b, ci: IN std_logic ;

suma, co: OUT std_logic ) ;

END COMPONENT;

DECLARACIÓN DE COMPONENTES CON GENÉRICOS

COMPONENT identificador _componente

GENERICS (identificador{ , identificador}: [ modo ] tipo_de_dato

[ := valor ]

{ ; identificador{ , identificador}: [ modo ] tipo_de_dato

[ := valor ] } ) ;

PORT ( identificador{ , identificador}: modo tipo_de_dato

{ ; identificador{ , identificador}: modo tipo_de_dato } ) ;

END COMPONENT ;

EJEMPLO

COMPONENT add_n

58 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

GENERICS ( size_bus: integer := 8 ) ;

PORT ( a, b: IN std_logic_vector ( size_bus - 1 DOWNTO 0 ) ;

ci: IN std_logic;

suma: OUT std_logic_vector ( size_bus - 1 DOWNTO 0 ) ;

co: OUT std_logic ) ;

END COMPONENT ;

Instanciación de Componentes

La instanciación de componentes es una instrucción concurrente que especifica la


interconexión de las señales del componente dentro del diseño en el que está siendo
utilizado. Existen dos formas de hacer la instanciación de componentes: por asociación de
identificadores o asociación por posición.

ASOCIACIÓN POR IDENTIFICADORES


En este tipo de instanciación es necesario utilizar el operador de asociación "=>" para
indicar como se conectan los puerto del componente con lo puertos o señales de la
arquitectura en la que está siendo utilizado dicho componente. Observe que en la
asociación " a => b ", "a" pertenece al componente y "b" es una señal, variable o incluso
una ecuación booleana en la que intervienen objetos de datos que pertenecen de la
arquitectura donde se usa el componente.

etiqueta: identificador _componente PORT MAP (

identificador_puerto_componente => identificador_señal

| identificador_variable -- | léase "o"

| expresión

| OPEN -- indica que este puerto del componente no se conecta

{ , identificador_puerto_componente => identificador_señal

| identificador_variable

| expresión

| OPEN

});

EJEMPLO

ARCHITECTURE a_reg8 OF reg8 IS

SIGNAL clock, reset, enable: std_logic ;

SIGNAL data_in, data_out: std_logic_vector ( 7 DOWNTO 0 ) ;

BEGIN

59 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

reg_1: register8 PORT MAP (

clk => clock,

rst => reset,

en => enable,

data => data_in,

q => data_out

);

END a_reg8 ;

ASOCIACIÓN POR IDENTIFICADORES CON GENÉRICOS

etiqueta: identificador_componente GENERIC MAP (

identificador_generico => identificador_señal

| identificador_variable -- | léase "o"

| expresión

| OPEN -- indica que este genérico del componente no se utiliza

{ , identificador_generico => identificador_señal

| identificador_variable

| expresión

| OPEN

});

PORT MAP (

identificador_puerto_componente => identificador_señal

| identificador_variable -- | léase "o"

| expresión

| OPEN -- indica que este puerto del componente no se conecta

{ , identificador_puerto_componente => identificador_señal

| identificador_variable

| expresión

| OPEN

});

ASOCIACIÓN POR POSICIÓN

60 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

En la asociación por posición no es necesario nombrar los puertos del componente. Sólo se
colocan las señales, variables, o expresiones en el lugar donde deseamos que sean
conectadas. Es importante considerar el orden en el que fueron declarados los puertos del
componente porque este orden es el debemos utilizar cuando se haga la instanciación del
componente.

etiqueta: identificador _componente PORT MAP ( identificador_señal

| identificador_variable | expresión | OPEN

{ , identificador_señal | identificador_variable | expresión | OPEN } ) ;

EJEMPLO

ARCHITECTURE a_reg8 OF reg8 IS

SIGNAL clock, reset, enable: std_logic ;

SIGNAL data_in, data_out: std_logic_vector ( 7 DOWNTO 0 ) ;

BEGIN

reg_1: register8 PORT MAP ( clock, reset, enable, data_in, data_out ) ;

END a_reg8 ;

ASOCIACIÓN POR POSICIÓN CON GENÉRICOS

etiqueta: identificador _componente GENERIC MAP ( identificador_señal

| identificador_variable | expresión | OPEN

{ , identificador_señal | identificador_variable | expresión | OPEN } ) ;

PORT MAP ( identificador_señal | identificador_variable | expresión | OPEN

{ , identificador_señal | identificador_variable | expresión | OPEN } ) ;

EJEMPLO

ARCHITECTURE a_sum4 OF sumador4 IS

SIGNAL carry_in, carry_out: std_logic ;

SIGNAL x, y, z: std_logic_vector ( 3 DOWNTO 0 ) ;

BEGIN

-- add_n es el componente de ejemplo en "declaración de componentes

-- con genéricos"

u1: add_n GENERIC MAP ( 4 ) ;

PORT MAP ( x, y, carry_in, z, carry_out ) ;

61 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END a_reg8 ;

3.12 Subprogramas

Los subprogramas son secuencias independientes de instrucciones y declaraciones que


pueden ser llamadas en repetidas ocasiones dentro de una arquitectura, proceso, o cuerpo
de un paquete en VHDL. Existen dos tipos de subprogramas: procedimientos y funciones.
Desde el punto de vista del hardware, un llamado a un subprograma es similar a la
instanciación de un componente, con la diferencia que el subprograma forma parte del
circuito en el cual esta siendo utilizado. La instanciación de un componente o módulo,
implica la síntesis de dos o más niveles de jerarquía en el diseño. Un subprograma
sintetizado generalmente es un único circuito combinacional (utilícese un proceso si se
desea crear un circuito secuencial).
Los subprogramas se declaran habitualmente en paquetes y los cuerpos de dichos
subprogramas son implementados en el cuerpo del paquete en el que fueron declarados.
Aunque es posible definir los subprogramas dentro de otras estructuras (arquitecturas y
procesos), no es común que se haga, además, que algunos sintetizadores restringen la
utilización de ellos sólo dentro de paquetes. Acerca de dichas restricciones en el uso de
subprogramas, consúltese los manuales de referencia de VHDL o manuales de usuario del
sintetizador que se este utilizando.

3.12.1 Procedimientos y Funciones

Procedimientos

Un procedimiento es un algoritmo que puede regresar uno o varios valores y que, además,
puede o no tener parámetros. Estos se utilizan generalmente para descomponer grandes
descripciones comportamentales en pequeñas secciones, las cuales a su vez pueden ser
utilizadas por distintos procesos dentro de la descripción.
Los parámetros que se utilizan en el llamado de un procedimiento deben ser constantes,
variables, o señales. Además, también debe especificarse el modo ya sea IN, OUT, o
INOUT. A menos que se especifique, un parámetro se considera como una constante si se
utiliza en el modo IN, y por omisión una variable si se utiliza el modo INOUT o OUT.
Los procedimientos pueden ser utilizados de manera concurrente o secuencial, es decir, ya
sea fuera o dentro de un proceso. Si alguno de los parámetros es un variable, entonces el
procedimiento puede ser utilizado sólo secuencialmente. Recordemos que las variables
solamente pueden ser declaradas dentro procesos, procedimientos y funciones y por esto
un procedimiento que utilice una variable como parámetro puede ser invocado únicamente
dentro del proceso en el que se encuentra declarada dicha variable.
Una variable declarada dentro de un procedimiento existe solamente en el momento de
ejecución del mismo, similar a la declaración de variables dentro de procesos.

DECLARACIÓN DE PROCEDIMIENTOS

PROCEDURE procedimiento ( lista de parámetros ) ;

CUERPO DEL PROCEDIMIENTO

62 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

PROCEDURE procedimiento ( lista de parámetros ) IS

-- declaraciones

BEGIN

-- instrucciones secuenciales

END procedimiento ;

EJEMPLO

PACKAGE ejemplo IS

-- declaración de procedimiento

PROCEDURE procedimiento ( a: IN bit ; b: INOUT bit ) ;

END ejemplo ;

PACKAGE BODY ejemplo IS

-- cuerpo del procedimiento

PROCEDURE procedimiento ( a: IN bit ; b: INOUT bit ) IS

BEGIN

b := a AND b ;

END ;

END ejemplo ;

Funciones

Una función es un algoritmo que retorna un único valor y puede o no tener parámetros de
entrada. Las funciones se utilizan generalmente para: (1) Convertir objetos de datos de un
tipo a otro; (2) Como simples funciones que realizan operaciones para las más frecuentes
situaciones de diseño. Los parámetros de una función siempre son del modo IN y deben ser
señales o constantes. Además, cualquier variable declarada dentro de la función existe
solamente dentro de la función.

DECLARACIÓN DE FUNCIONES

FUNCTION identificador ( lista de parámetros ) RETURN tipo_de_datos ;

CUERPO DE LA FUNCIÓN

FUNCTION identificador ( lista de parámetros ) RETURN tipo_de_datos IS

-- declaraciones

63 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

BEGIN

-- instrucciones secuenciales

END identificador ;

EJEMPLO

FUNCTION cuenta_unos ( vec1: std_logic_vector )

RETURN integer IS

VARIABLE temp: integer := 0 ;

BEGIN

FOR i IN vec1'low TO vec1'high LOOP

IF vec1 ( i ) = '1' THEN

temp := temp + 1 ;

END IF ;

END LOOP ;

RETURN temp ;

END cuenta_unos ;

3.12.2 Llamado a Subprogramas

Como ya mencionamos un subprograma puede tener o no tener parámetro. Además, en la


declaración de un subprograma se define el nombre, modo, y tipo de dato para cada
parámetro. Cuando el subprograma es llamado, cada parámetro recibe un valor. El valor
que recibe el parámetro (con su tipo correspondiente) puede ser el resultado de una
expresión, el valor de un variable, o de una señal.
El modo en el que es declarado el parámetro especifica la forma en que puede ser
utilizado, similar a los puertos en una entidad.

IN: lectura

OUT: escritura

IN: ambos, lectura y escritura

Un parámetro que es declarado en el modo OUT o INOUT debe ser una variable o una
señal, ya sea para tipos simples como el bit, o arreglos como el bit_vector.
Cuando el subprograma es un procedimiento, puede tener múltiples parámetros que pueden
utilizar los modos: IN, INOUT, o OUT. Los procedimientos son usados cuando se desea
actualizar o modificar algún dato. Un ejemplo puede ser un procedimiento con un
parámetro INOUT tipo bit_vector el cual invierte los bits del vector.

64 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Si por el contrario el subprograma es una función, esta puede tener múltiples parámetros,
todos del modo IN. Una vez que se ejecuta la función, esta retorna un único valor. Este
valor debe ser especificado con un tipo determinado. Un ejemplo es la función ABS que
regresa el valor absoluto del parámetro.

Llamado a Procedimientos

El llamado a un procedimiento se invoca por su nombre, y este utiliza los parámetros que le
son listados. La sintaxis es la siguiente:

identificador_procedimiento identificador expresión

identificador = expresión

Cada expresión puede ser el identificador de una señal, variable, o alguna operación. Al
igual que en la instanciación de componentes, la asociación de los parámetros puede ser
por el nombre o por posiciones.

EJEMPLO

ENTITY proc_ejemplo IS

PORT ( entA, entB, entC: INOUT bit_vector ( 1 DOWNTO 0 ) ;

salida0: INOUT bit_vector ( 1 DOWNTO 0 ) ;

salida1: INOUT bit_vector ( 1 DOWNTO 0 ) ) ;

END proc_ejemplo ;

ARCHITECTURE a_ proc_ejemplo OF proc_ejemplo IS

PROCEDURE procedimiento ( a: IN bit_vector ( 1 DOWNTO 0 ) ;

b: IN bit_vector ( 1 DOWNTO 0 ) ;

c: INOUT bit_vector ( 1 DOWNTO 0 ) ) IS

BEGIN

c := a AND b ; -- al no especificarse como señales

-- los parámetros INOUT son

-- variables por omisión

END ;

BEGIN

procedimiento ( a => ( entA AND entC ),

b => entB,

c => salida0 ) ;

procedimiento ( entA, entC, salida1 ) ;

65 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END a_ proc_ejemplo ;

Llamado a Funciones

Una función es llamada por su nombre y utiliza los parámetros que le son dados. Las
funciones regresan un único valor. La sintaxis es la siguiente:

identificador_función identificador expresión

identificador = expresión

Al igual que en los procedimientos es posible especificar los parámetros mediante


asociación de nombres, o asociación por posiciones

EJEMPLO

FUNCTION invert ( a : bit ) RETURN bit IS

BEGIN

RETURN ( not a ) ;

END ;

...

PROCESS

VARIABLE v1, v2, v3: bit ;

BEGIN

v1 := '1';

v2 := INVERT ( v1 ) XOR 1 ;

v3 := INVERT ( '0' ) ;

END PROCESS ;

Instrucción RETURN

La instrucción RETURN termina un subprograma. Si el subprograma es una función es


necesario utilizar la instrucción RETURN, en el caso de los procedimientos es opcional. La
sintaxis es la siguiente.

RETURN expresión ; -- Funciones

RETURN ; -- Procedimientos

En una función la expresión proporciona el valor de retorno de la función. Cada función


debe de tener al menos una instrucción de retorno. El tipo de datos que maneja la
expresión de retorno debe coincidir con el tipo de dato de retorno declarado en la función.

66 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

EJEMPLO

PACKAGE ejemplo_return IS

FUNCTION ejemplo_func ( a, b, c: bit ) RETURN bit ;

END ejemplo_return ;

PACKAGE BODY ejemplo_return IS

FUNCTION ejemplo_func ( a, b, c: bit ) RETURN bit IS

BEGIN

IF ( c = '1' ) THEN

RETURN ( a XOR b ) ;

ELSE

RETURN NOT ( a XOR b ) ;

END IF ;

END ejemplo_func ;

END ejemplo_return ;

LIBRARY ieee ;

USE ieee.std_logic_1164.ALL ;

USE work.ejemplo_return.ALL ; -- la librería "work" es la librería del presente proyecto

ENTITY uso_funcion IS

PORT ( SIGNAL in1, in2, in3: IN bit ;

SIGNAL valor_de_retorno: OUT bit ) ;

END uso_funcion ;

ARCHITECTURE a_uso_funcion OF uso_funcion IS

BEGIN

valor_de_retorno <= ejemplo_func ( in1, in2, in3 ) ;

END a_uso_funcion ;

3.12.3 Sobrecarga de Operadores

La sobrecarga de operadores consiste en definir nuevas funciones para utilizar tipos de


datos con los que no estaba definido anteriormente el operador. Así, por ejemplo el
operador AND no está definido de manera predeterminada para ser utilizado con los tipos
std_logic_vector, unsigned y signed. Pero dentro de los paquetes std_logic_1164,
numeric_std, y numeric_bit, que es donde se definen estos tipos de datos, se sobrecarga el
operador AND para poder utilizarlo con estos tipos de datos.

67 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

También es posible crear operadores para ser utilizados con los tipos de datos definidos por
el usuario.

TYPE mi_bit IS ( ‘0’, ‘1’, ‘x’ ) ; -- tipo de datos definido por el usuario

-- sobrecarga de los operadores AND y OR para ser utilizados

-- con el nuevo tipo de datos

FUNCTION "AND" ( input1, input2: IN mi_bit ) RETURN mi_bit ;

FUNCTION "OR" ( input1, input2: IN mi_bit ) return mi_bit ;

···

SIGNAL a, b, c: mi_bit ;

···

c <= ( a OR b ) AND c ;

Cuando se sobrecarga un operador en VHDL, es necesario que el nombre del operador se


encuentre entre comillas dobles "". Si no se hace así entonces se considera a la función
como tal y no como un operador sobrecargado.

3.13 Librerías

Una librería consiste en una colección de unidades de diseño analizadas previamente con
lo cual se facilita la utilización de estas en nuevos diseño. Para incluir una librería se utiliza
la siguiente sintaxis.

LIBRARY identificador_librería [,identificador_librería ] ;

La cláusula LIBRARY permite utilizar la librería especificada únicamente para la unidad


de diseño en la cual se declara. Una unidad de diseño es una entidad, paquete,
arquitectura, o cuerpo de paquete.

EJEMPLO

LIBRARY mi_libreria;

3.13.1 Síntesis de Librerías en WARP

Para sintetizar librerías en WARP de Cypress Semiconductors necesitas hacer lo siguiente:

a). - Dentro de Galaxy selecciona: File > New > Project [ Target - Library ]

b). - A continuación proporcionas la información del nombre de la librería, nombre del


proyecto, y localización del proyecto en disco duro. Cabe mencionar que es posible crear
cualquier número de proyectos dentro del mismo directorio, y todos compilando la misma

68 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

librería. Por ejemplo, podemos crear un proyecto con el nombre "multiplexores" para
compilar dentro de la librería "mi_libreria" en el directorio "c:\vhdl_proj\mi_libreria".
Diseñar todas las unidades de diseño deseadas dentro de esta librería y compilarlas en la
misma. Después podemos otro proyecto con el nombre "comparadores" para compilar en
la librería "mi_libreria" en el directorio "c:\vhdl_proj\mi_libreria". Diseñar otras
unidades de diseño y compilarlas. Cuando se incluya la librería "mi_librería" en otros
proyectos podemos utilizar cualquier unidad de diseño que se encuentre ya sea en el
proyecto de librería "multiplexores" o en el de "comparadores". Esto es posible porque
ambos proyectos se compilaron en una librería con el mismo nombre y en el mismo
directorio.

c). - Después aparece un cuadro de dialogo en el cual puedes agregar archivos .vhd al
proyecto de librería. Si ya los tienes, puedes copiarlos al directorio o buscarlos mediante el
botón Browse... agregarlos al proyecto. Si no los tienes sólo haz click en Finalizar y
posteriormente podrás crear los archivos del proyecto de librería.

Como ya se menciono anteriormente, en una librería puedes incluir todas las unidades de
diseño que desees, siendo unidades de diseños las estructuras: ENTITY,
ARCHITECTURE, PACKAGE, o PACKAGE BODY. Por lo general en los archivos de
librería se utilizan paquetes.
Para incluir una librería creada por el usuario en algún proyecto en particular necesitar
hacer lo siguiente:

1. - Seleccionas Project > Library Manager...

2. - Dentro del cuadro de dialogo del administrador de librerías, seleccionas Assign y


después haces click en el botón Add...

3. - Ahora se te pide el nombre de la librería que vas a incluir y la ruta en donde se


encuentran los archivos de la librería. Por ejemplo, en Library podrías poner la librería del
ejemplo anterior "mi_libreria". Y en el Path escribes la ruta del directorio donde se
encuentra compilada la librería. Debes escribir toda la ruta tal y como aparece en
MS-DOS. Esta librería se creo en el directorio "c:\vhdl_proj\mi_libreria", pero la librería
se compilo en el directorio "c:\vhdl_proj\mi_libreria\mi_libreria" y el nombre MS-DOS
del directorio es "C:\vhdl_p~1\mi_lib~1\mi_lib~1".

d). - Después que agregaste la librería, para incluirla basta con que escribas lo siguiente:

LIBRARY mi_libreria ;

Una vez declarada en la descripción podrás utilizar todas las unidades de diseño que se
hayan compilado en la librería.
El nombre de la librería de todo proyecto que estés realizando es "work". Por lo que si
deseas crear un paquete en particular en el proyecto puedes incluirlo en cualquier unidad
de diseño de la siguiente manera:

USE work.identificador_paquete.ALL ;

Donde identificador_paquete es el nombre del paquete que creaste en el mismo proyecto.

EJEMPLO

69 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

Crea un nuevo proyecto en WARP y en un archivo de texto copia toda la siguiente


descripción.

PACKAGE swap IS

FUNCTION swap4 ( data: IN bit_vector ( 3 DOWNTO 0 ) )

RETURN bit_vector ;

END swap ;

PACKAGE BODY swap IS

FUNCTION swap4 ( data: IN bit_vector ( 3 DOWNTO 0 ) )

RETURN bit_vector IS

VARIABLE tempo: bit_vector ( 3 DOWNTO 0 ) ;

BEGIN

tempo := data( 1 DOWNTO 0 ) & data( 3 DOWNTO 2 ) ;

RETURN tempo ;

END ;

END swap ;

USE work.swap.ALL ; -- instanciación de un paquete que se encuentra en

-- el mismo proyecto

ENTITY swap_ent IS

PORT ( x: IN bit_vector ( 3 DOWNTO 0 ) ;

y: OUT bit_vector ( 3 DOWNTO 0 )

);

END swap_ent ;

ARCHITECTURE swap_ent OF swap_ent IS

BEGIN

y <= swap4(x) ;

END swap_ent ;

3.13.2 Paquetes

Un paquete en VHDL es una colección de declaraciones que pueden ser utilizadas por
otras descripciones en VHDL. Un paquete en VHDL consiste de dos secciones: la
declaración del paquete y el cuerpo del paquete.
Para incluir un paquete en otra descripción se sigue la siguiente sintaxis:

70 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

USE libreria.identificador_paquete.ALL ;

De esta manera el paquete indicado es visible para la unidad de diseño en la cual está
siendo utilizado. Mediante "ALL" indicamos que deseamos incluir todas las declaraciones
de funciones, componentes, tipos de datos, subtipos de datos, procedimientos, etc. que
encuentren en dicho paquete.

DECLARACIÓN DEL PAQUETE

PACKAGE identificador IS

-- declaración de subprograma

-- declaración de tipo de datos

-- declaración de subtipos

-- declaración de constantes

-- declaración de señales

-- declaración de componentes

-- declaración de atributos

-- especificación de atributos

-- instrucción USE

END identificador ;

CUERPO DEL PAQUETE

PACKAGE BODY identificador IS

-- declaración de subprograma

-- cuerpo del subprograma

-- declaración de tipo de datos

-- declaración de subtipos

-- declaración de constantes

-- instrucción USE

END identificador ;

En la declaración del paquete se hace mención de todo aquello que puede ser utilizado por
otras descripciones cuando se incluye el paquete.
El cuerpo del paquete proporciona definiciones y declaraciones adicionales, así como la
descripción completa de funciones y procedimientos que fueron declarados previamente
en el paquete.

EJEMPLO

PACKAGE v3_tbl IS

71 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

SUBTYPE v3 IS std_logic_vector ( 0 to 2 ) ;

TYPE v3_array IS ARRAY ( 0 to 7 ) OF v3;

CONSTANT v3_table : v3_array := (

"000",

"001",

"010",

"011",

"100",

"101",

"110",

"111") ;

FUNCTION int2v3 ( ia: integer ) RETURN v3 ; -- declaración de función

END v3_tbl ;

PACKAGE BODY v3_tbl IS

FUNCTION int2v3 ( ia: integer ) RETURN vec3 IS

-- convierte un entero entre 0 y 7 en un vector de 3 bits

BEGIN

RETURN v3_table ( ia ) ;

END int2v3 ;

END v3_tbl ;

EJEMPLO

Para este ejemplo crea un proyecto para compilar la librería "mi_libreria". Crea un nuevo
archivo de texto y copia la siguiente descripción en él.

LIBRARY ieee ;

USE ieee.std_logic_1164.ALL ;

PACKAGE multiplexores IS

COMPONENT mux_2_a_1

GENERIC ( msb: integer ) ;

PORT ( selec: in std_logic ;

x: IN std_logic_vector( msb DOWNTO 0 ) ;

72 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

y: IN std_logic_vector( msb DOWNTO 0 ) ;

z: OUT std_logic_vector( msb DOWNTO 0 ) ) ;

END COMPONENT ;

END multiplexores ;

LIBRARY ieee ;

USE ieee.std_logic_1164.ALL ;

ENTITY mux_2_a_1 IS

GENERIC ( msb: integer := 3 ) ; -- debe declararse siempre un valor inicial

-- para que en caso de no ser especificado

-- en el momento de la instanciación,

-- el componente tome un valor por omisión

PORT ( selec: IN std_logic ;

x: IN std_logic_vector ( msb DOWNTO 0 ) ;

y: IN std_logic_vector ( msb DOWNTO 0 ) ;

z: OUT std_logic_vector ( msb DOWNTO 0 ) ) ;

END mux_2_a_1 ;

ARCHITECTURE a_mux_2_a_1 OF mux_2_a_1 IS

BEGIN

z <= x WHEN selec = '1' ELSE

y WHEN selec = '0' ;

END a_mux_2_a_1 ;

Sintetiza el proyecto y después crea otro para utilizar el paquete anterior. Para agregar la
librería a este nuevo proyecto hazlo desde el administrador de librerías. Crea un nuevo
archivo de texto y copia la siguiente descripción en él.

LIBRARY ieee;

USE ieee.std_logic_1164.ALL ;

USE mi_libreria.multiplexores.ALL ; -- referencia al paquete multiplexores

-- que se encuentra dentro

-- de la librería "mi_libreria"

ENTITY multiplexor IS

PORT ( a,b,c,d: IN std_logic_vector ( 3 DOWNTO 0 ) ;

73 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

selec: IN std_logic_vector ( 1 DOWNTO 0 ) ;

salida: OUT std_logic_vector ( 3 DOWNTO 0 ) ) ;

END multiplexor ;

ARCHITECTURE estructural OF multiplexor IS

SIGNAL salida1, salida2: std_logic_vector ( 3 DOWNTO 0 ) ;

BEGIN

-- instanciación del componente mux_2_a_1

u1: mux_2_a_1 PORT MAP ( a, b, selec(0), salida1 ) ;

u2: mux_2_a_1 PORT MAP ( c, d, selec(0), salida2 );

u3: mux_2_a_1 PORT MAP ( salida1, salida2, selec(1), salida ) ;

END estructural ;

Como se mencionó al principio una librería es una colección de unidades de diseño que
pueden ser incluidas es otras descripciones mediante el llamada a la respectiva librería.

3.13.3 Paquete std_logic_1164

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

--
-- Title : std_logic_1164 multi-value logic system
-- Library : This package shall be compiled into a library
-- : symbolically named IEEE.
-- :
-- Developers: IEEE model standards group (par 1164)
-- Purpose : This packages defines a standard for designers
-- : to use in describing the interconnection data types
-- : used in vhdl modeling.
-- :
-- Limitation: The logic system defined in this package may
-- : be insufficient for modeling switched transistors,
-- : since such a requirement is out of the scope of this
-- : effort. Furthermore, mathematics, primitives,
-- : timing standards, etc. are considered orthogonal
-- : issues as it relates to this package and are therefore
-- : beyond the scope of this effort.
-- :
-- Note : No declarations or definitions shall be included in,
-- : or excluded from this package. The "package declaration"
-- : defines the types, subtypes and declarations of
-- : std_logic_1164. The std_logic_1164 package body shall be
-- : considered the formal definition of the semantics of
-- : this package. Tool developers may choose to implement
-- : the package body in the most efficient manner available
-- : to them.
-- :
-- --------------------------------------------------------------------
-- modification history :
-- --------------------------------------------------------------------
-- version | mod. date:|

74 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

-- v4.200 | 01/02/92 |
-- --------------------------------------------------------------------

PACKAGE std_logic_1164 IS

-------------------------------------------------------------------
-- logic state system (unresolved)
-------------------------------------------------------------------
TYPE std_ulogic IS ( 'U', -- Uninitialized
'X', -- Forcing Unknown
'0', -- Forcing 0
'1', -- Forcing 1
'Z', -- High Impedance
'W', -- Weak Unknown
'L', -- Weak 0
'H', -- Weak 1
'-' -- Don't care
);
-------------------------------------------------------------------
-- unconstrained array of std_ulogic for use with the resolution function
-------------------------------------------------------------------
TYPE std_ulogic_vector IS ARRAY ( NATURAL RANGE <> ) OF std_ulogic;

-------------------------------------------------------------------
-- resolution function
-------------------------------------------------------------------
FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic;

-------------------------------------------------------------------
-- *** industry standard logic type ***
-------------------------------------------------------------------
SUBTYPE std_logic IS resolved std_ulogic;

-------------------------------------------------------------------
-- unconstrained array of std_logic for use in declaring signal arrays
-------------------------------------------------------------------
TYPE std_logic_vector IS ARRAY ( NATURAL RANGE <>) OF std_logic;

-------------------------------------------------------------------
-- common subtypes
-------------------------------------------------------------------
SUBTYPE X01 IS resolved std_ulogic RANGE 'X' TO '1'; -- ('X','0','1')
SUBTYPE X01Z IS resolved std_ulogic RANGE 'X' TO 'Z'; -- ('X','0','1','Z')
SUBTYPE UX01 IS resolved std_ulogic RANGE 'U' TO '1'; -- ('U','X','0','1')
SUBTYPE UX01Z IS resolved std_ulogic RANGE 'U' TO 'Z'; -- ('U','X','0','1','Z')

-------------------------------------------------------------------
-- overloaded logical operators
-------------------------------------------------------------------

FUNCTION "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01;


FUNCTION "nand" ( l : std_ulogic; r : std_ulogic ) RETURN UX01;
FUNCTION "or" ( l : std_ulogic; r : std_ulogic ) RETURN UX01;
FUNCTION "nor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01;
FUNCTION "xor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01;
-- function "xnor" ( l : std_ulogic; r : std_ulogic ) return ux01;
FUNCTION "not" ( l : std_ulogic ) RETURN UX01;

-------------------------------------------------------------------
-- vectorized overloaded logical operators
-------------------------------------------------------------------
FUNCTION "and" ( l, r : std_logic_vector ) RETURN std_logic_vector;
FUNCTION "and" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector;

FUNCTION "nand" ( l, r : std_logic_vector ) RETURN std_logic_vector;


FUNCTION "nand" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector;

FUNCTION "or" ( l, r : std_logic_vector ) RETURN std_logic_vector;


FUNCTION "or" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector;

75 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

FUNCTION "nor" ( l, r : std_logic_vector ) RETURN std_logic_vector;


FUNCTION "nor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector;

FUNCTION "xor" ( l, r : std_logic_vector ) RETURN std_logic_vector;


FUNCTION "xor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector;

-- -----------------------------------------------------------------------
-- Note : The declaration and implementation of the "xnor" function is
-- specifically commented until at which time the VHDL language has been
-- officially adopted as containing such a function. At such a point,
-- the following comments may be removed along with this notice without
-- further "official" ballotting of this std_logic_1164 package. It is
-- the intent of this effort to provide such a function once it becomes
-- available in the VHDL standard.
-- -----------------------------------------------------------------------
-- function "xnor" ( l, r : std_logic_vector ) return std_logic_vector;
-- function "xnor" ( l, r : std_ulogic_vector ) return std_ulogic_vector;

FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector;


FUNCTION "not" ( l : std_ulogic_vector ) RETURN std_ulogic_vector;

-------------------------------------------------------------------
-- conversion functions
-------------------------------------------------------------------
FUNCTION To_bit ( s : std_ulogic; xmap : BIT := '0') RETURN BIT;
FUNCTION To_bitvector ( s : std_logic_vector ; xmap : BIT := '0') RETURN BIT_VECTOR;
FUNCTION To_bitvector ( s : std_ulogic_vector; xmap : BIT := '0') RETURN BIT_VECTOR;

FUNCTION To_StdULogic ( b : BIT ) RETURN std_ulogic;


FUNCTION To_StdLogicVector ( b : BIT_VECTOR ) RETURN std_logic_vector;
FUNCTION To_StdLogicVector ( s : std_ulogic_vector ) RETURN std_logic_vector;
FUNCTION To_StdULogicVector ( b : BIT_VECTOR ) RETURN std_ulogic_vector;
FUNCTION To_StdULogicVector ( s : std_logic_vector ) RETURN std_ulogic_vector;

-------------------------------------------------------------------
-- strength strippers and type convertors
-------------------------------------------------------------------

FUNCTION To_X01 ( s : std_logic_vector ) RETURN std_logic_vector;


FUNCTION To_X01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector;
FUNCTION To_X01 ( s : std_ulogic ) RETURN X01;
FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_logic_vector;
FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector;
FUNCTION To_X01 ( b : BIT ) RETURN X01;

FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector;


FUNCTION To_X01Z ( s : std_ulogic_vector ) RETURN std_ulogic_vector;
FUNCTION To_X01Z ( s : std_ulogic ) RETURN X01Z;
FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_logic_vector;
FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_ulogic_vector;
FUNCTION To_X01Z ( b : BIT ) RETURN X01Z;

FUNCTION To_UX01 ( s : std_logic_vector ) RETURN std_logic_vector;


FUNCTION To_UX01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector;
FUNCTION To_UX01 ( s : std_ulogic ) RETURN UX01;
FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_logic_vector;
FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector;
FUNCTION To_UX01 ( b : BIT ) RETURN UX01;

-------------------------------------------------------------------
-- edge detection
-------------------------------------------------------------------
FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN;
FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN;

-------------------------------------------------------------------
-- object contains an unknown
-------------------------------------------------------------------
FUNCTION Is_X ( s : std_ulogic_vector ) RETURN BOOLEAN;
FUNCTION Is_X ( s : std_logic_vector ) RETURN BOOLEAN;
FUNCTION Is_X ( s : std_ulogic ) RETURN BOOLEAN;

76 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END std_logic_1164;

--3. Std_Logic_1164 Package Body

-- --------------------------------------------------------------------
--
-- Title : std_logic_1164 multi-value logic system
-- Library : This package shall be compiled into a library
-- : symbolically named IEEE.
-- :
-- Developers: IEEE model standards group (par 1164)
-- Purpose : This packages defines a standard for designers
-- : to use in describing the interconnection data types
-- : used in vhdl modeling.
-- :
-- Limitation: The logic system defined in this package may
-- : be insufficient for modeling switched transistors,
-- : since such a requirement is out of the scope of this
-- : effort. Furthermore, mathematics, primitives,
-- : timing standards, etc. are considered orthogonal
-- : issues as it relates to this package and are therefore
-- : beyond the scope of this effort.
-- :
-- Note : No declarations or definitions shall be included in,
-- : or excluded from this package. The "package declaration"
-- : defines the types, subtypes and declarations of
-- : std_logic_1164. The std_logic_1164 package body shall be
-- : considered the formal definition of the semantics of
-- : this package. Tool developers may choose to implement
-- : the package body in the most efficient manner available
-- : to them.
-- :
-- --------------------------------------------------------------------
-- modification history :
-- --------------------------------------------------------------------
-- version | mod. date:|
-- v4.200 | 01/02/91 |
-- --------------------------------------------------------------------

PACKAGE BODY std_logic_1164 IS


-------------------------------------------------------------------
-- local types
-------------------------------------------------------------------
TYPE stdlogic_1d IS ARRAY (std_ulogic) OF std_ulogic;
TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic;

-------------------------------------------------------------------
-- resolution function
-------------------------------------------------------------------
CONSTANT resolution_table : stdlogic_table := (
-- ---------------------------------------------------------
-- | U X 0 1 Z W L H - | |
-- ---------------------------------------------------------
( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U |
( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X |
( 'U', 'X', '0', 'X', '0', '0', '0', '0', 'X' ), -- | 0 |
( 'U', 'X', 'X', '1', '1', '1', '1', '1', 'X' ), -- | 1 |
( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X' ), -- | Z |
( 'U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X' ), -- | W |
( 'U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X' ), -- | L |
( 'U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X' ), -- | H |
( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - |
);

FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic IS


VARIABLE result : std_ulogic := 'Z'; -- weakest state default
BEGIN
-- the test for a single driver is essential otherwise the
-- loop would return 'X' for a single driver of '-' and that
-- would conflict with the value of a single driver unresolved

77 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

-- signal.
IF (s'LENGTH = 1) THEN RETURN s(s'LOW);
ELSE
FOR i IN s'RANGE LOOP
result := resolution_table(result, s(i));
END LOOP;
END IF;
RETURN result;
END resolved;

-------------------------------------------------------------------
-- tables for logical operations
-------------------------------------------------------------------

-- truth table for "and" function


CONSTANT and_table : stdlogic_table := (
-- ----------------------------------------------------
-- | U X 0 1 Z W L H - | |
-- ----------------------------------------------------
( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ), -- | U |
( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X |
( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 |
( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 1 |
( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | Z |
( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W |
( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L |
( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | H |
( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ) -- | - |
);

-- truth table for "or" function


CONSTANT or_table : stdlogic_table := (
-- ----------------------------------------------------
-- | U X 0 1 Z W L H - | |
-- ----------------------------------------------------
( 'U', 'U', 'U', '1', 'U', 'U', 'U', '1', 'U' ), -- | U |
( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | X |
( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 |
( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | 1 |
( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | Z |
( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | W |
( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L |
( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | H |
( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ) -- | - |
);

-- truth table for "xor" function


CONSTANT xor_table : stdlogic_table := (
-- ----------------------------------------------------
-- | U X 0 1 Z W L H - | |
-- ----------------------------------------------------
( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U |
( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X |
( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 |
( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 |
( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z |
( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W |
( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L |
( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H |
( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - |
);

-- truth table for "not" function


CONSTANT not_table: stdlogic_1d :=
-- -------------------------------------------------
-- | U X 0 1 Z W L H - |
-- -------------------------------------------------
( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' );

-------------------------------------------------------------------
-- overloaded logical operators ( with optimizing hints )

78 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

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

FUNCTION "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS


BEGIN
RETURN (and_table(l, r));
END "and";

FUNCTION "nand" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS


BEGIN
RETURN (not_table ( and_table(l, r)));
END "nand";

FUNCTION "or" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS


BEGIN
RETURN (or_table(l, r));
END "or";

FUNCTION "nor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS


BEGIN
RETURN (not_table ( or_table( l, r )));
END "nor";

FUNCTION "xor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS


BEGIN
RETURN (xor_table(l, r));
END "xor";

-- function "xnor" ( l : std_ulogic; r : std_ulogic ) return ux01 is


-- begin
-- return not_table(xor_table(l, r));
-- end "xnor";

FUNCTION "not" ( l : std_ulogic ) RETURN UX01 IS


BEGIN
RETURN (not_table(l));
END "not";

-------------------------------------------------------------------
-- and
-------------------------------------------------------------------
FUNCTION "and" ( l,r : std_logic_vector ) RETURN std_logic_vector IS
ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_logic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'and' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := and_table (lv(i), rv(i));
END LOOP;
END IF;
RETURN result;
END "and";
---------------------------------------------------------------------
FUNCTION "and" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS
ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'and' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := and_table (lv(i), rv(i));
END LOOP;
END IF;
RETURN result;

79 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END "and";
-------------------------------------------------------------------
-- nand
-------------------------------------------------------------------
FUNCTION "nand" ( l,r : std_logic_vector ) RETURN std_logic_vector IS
ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_logic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'nand' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := not_table(and_table (lv(i), rv(i)));
END LOOP;
END IF;
RETURN result;
END "nand";
---------------------------------------------------------------------
FUNCTION "nand" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS
ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'nand' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := not_table(and_table (lv(i), rv(i)));
END LOOP;
END IF;
RETURN result;
END "nand";
-------------------------------------------------------------------
-- or
-------------------------------------------------------------------
FUNCTION "or" ( l,r : std_logic_vector ) RETURN std_logic_vector IS
ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_logic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'or' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := or_table (lv(i), rv(i));
END LOOP;
END IF;
RETURN result;
END "or";
---------------------------------------------------------------------
FUNCTION "or" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS
ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'or' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := or_table (lv(i), rv(i));
END LOOP;
END IF;
RETURN result;

80 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END "or";
-------------------------------------------------------------------
-- nor
-------------------------------------------------------------------
FUNCTION "nor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS
ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_logic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'nor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := not_table(or_table (lv(i), rv(i)));
END LOOP;
END IF;
RETURN result;
END "nor";
---------------------------------------------------------------------
FUNCTION "nor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS
ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'nor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := not_table(or_table (lv(i), rv(i)));
END LOOP;
END IF;
RETURN result;
END "nor";
---------------------------------------------------------------------
-- xor
-------------------------------------------------------------------
FUNCTION "xor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS
ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_logic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'xor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := xor_table (lv(i), rv(i));
END LOOP;
END IF;
RETURN result;
END "xor";
---------------------------------------------------------------------
FUNCTION "xor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS
ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l;
ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r;
VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH );
BEGIN
IF ( l'LENGTH /= r'LENGTH ) THEN
ASSERT FALSE
REPORT "arguments of overloaded 'xor' operator are not of the same length"
SEVERITY FAILURE;
ELSE
FOR i IN result'RANGE LOOP
result(i) := xor_table (lv(i), rv(i));
END LOOP;
END IF;
RETURN result;

81 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END "xor";
-- -------------------------------------------------------------------
-- -- xnor
-- -------------------------------------------------------------------
-- -----------------------------------------------------------------------
-- Note : The declaration and implementation of the "xnor" function is
-- specifically commented until at which time the VHDL language has been
-- officially adopted as containing such a function. At such a point,
-- the following comments may be removed along with this notice without
-- further "official" ballotting of this std_logic_1164 package. It is
-- the intent of this effort to provide such a function once it becomes
-- available in the VHDL standard.
-- -----------------------------------------------------------------------
-- function "xnor" ( l,r : std_logic_vector ) return std_logic_vector is
-- alias lv : std_logic_vector ( 1 to l'length ) is l;
-- alias rv : std_logic_vector ( 1 to r'length ) is r;
-- variable result : std_logic_vector ( 1 to l'length );
-- begin
-- if ( l'length /= r'length ) then
-- assert false
-- report "arguments of overloaded 'xnor' operator are not of the same length"
-- severity failure;
-- else
-- for i in result'range loop
-- result(i) := not_table(xor_table (lv(i), rv(i)));
-- end loop;
-- end if;
-- return result;
-- end "xnor";
-- ---------------------------------------------------------------------
-- function "xnor" ( l,r : std_ulogic_vector ) return std_ulogic_vector is
-- alias lv : std_ulogic_vector ( 1 to l'length ) is l;
-- alias rv : std_ulogic_vector ( 1 to r'length ) is r;
-- variable result : std_ulogic_vector ( 1 to l'length );
-- begin
-- if ( l'length /= r'length ) then
-- assert false
-- report "arguments of overloaded 'xnor' operator are not of the same length"
-- severity failure;
-- else
-- for i in result'range loop
-- result(i) := not_table(xor_table (lv(i), rv(i)));
-- end loop;
-- end if;
-- return result;
-- end "xnor";

-------------------------------------------------------------------
-- not
-------------------------------------------------------------------
FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector IS
ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l;
VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X');
BEGIN
FOR i IN result'RANGE LOOP
result(i) := not_table( lv(i) );
END LOOP;
RETURN result;
END;
---------------------------------------------------------------------
FUNCTION "not" ( l : std_ulogic_vector ) RETURN std_ulogic_vector IS
ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l;
VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X');
BEGIN
FOR i IN result'RANGE LOOP
result(i) := not_table( lv(i) );
END LOOP;
RETURN result;
END;
-------------------------------------------------------------------

82 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

-- conversion tables
-------------------------------------------------------------------
TYPE logic_x01_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF X01;
TYPE logic_x01z_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF X01Z;
TYPE logic_ux01_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF UX01;
----------------------------------------------------------
-- table name : cvt_to_x01
--
-- parameters :
-- in : std_ulogic -- some logic value
-- returns : x01 -- state value of logic value
-- purpose : to convert state-strength to state only
--
-- example : if (cvt_to_x01 (input_signal) = '1' ) then ...
--
----------------------------------------------------------
CONSTANT cvt_to_x01 : logic_x01_table := (
'X', -- 'U'
'X', -- 'X'
'0', -- '0'
'1', -- '1'
'X', -- 'Z'
'X', -- 'W'
'0', -- 'L'
'1', -- 'H'
'X' -- '-'
);

----------------------------------------------------------
-- table name : cvt_to_x01z
--
-- parameters :
-- in : std_ulogic -- some logic value
-- returns : x01z -- state value of logic value
-- purpose : to convert state-strength to state only
--
-- example : if (cvt_to_x01z (input_signal) = '1' ) then ...
--
----------------------------------------------------------
CONSTANT cvt_to_x01z : logic_x01z_table := (
'X', -- 'U'
'X', -- 'X'
'0', -- '0'
'1', -- '1'
'Z', -- 'Z'
'X', -- 'W'
'0', -- 'L'
'1', -- 'H'
'X' -- '-'
);

----------------------------------------------------------
-- table name : cvt_to_ux01
--
-- parameters :
-- in : std_ulogic -- some logic value
-- returns : ux01 -- state value of logic value
-- purpose : to convert state-strength to state only
--
-- example : if (cvt_to_ux01 (input_signal) = '1' ) then ...
--
----------------------------------------------------------
CONSTANT cvt_to_ux01 : logic_ux01_table := (
'U', -- 'U'
'X', -- 'X'
'0', -- '0'
'1', -- '1'
'X', -- 'Z'
'X', -- 'W'
'0', -- 'L'

83 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

'1', -- 'H'
'X' -- '-'
);

-------------------------------------------------------------------
-- conversion functions
-------------------------------------------------------------------
FUNCTION To_bit ( s : std_ulogic; xmap : BIT := '0') RETURN BIT IS
BEGIN
CASE s IS
WHEN '0' | 'L' => RETURN ('0');
WHEN '1' | 'H' => RETURN ('1');
WHEN OTHERS => RETURN xmap;
END CASE;
END;
--------------------------------------------------------------------
FUNCTION To_bitvector ( s : std_logic_vector ; xmap : BIT := '0') RETURN BIT_VECTOR IS
ALIAS sv : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s;
VARIABLE result : BIT_VECTOR ( s'LENGTH-1 DOWNTO 0 );
BEGIN
FOR i IN result'RANGE LOOP
CASE sv(i) IS
WHEN '0' | 'L' => result(i) := '0';
WHEN '1' | 'H' => result(i) := '1';
WHEN OTHERS => result(i) := xmap;
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_bitvector ( s : std_ulogic_vector; xmap : BIT := '0') RETURN BIT_VECTOR IS
ALIAS sv : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s;
VARIABLE result : BIT_VECTOR ( s'LENGTH-1 DOWNTO 0 );
BEGIN
FOR i IN result'RANGE LOOP
CASE sv(i) IS
WHEN '0' | 'L' => result(i) := '0';
WHEN '1' | 'H' => result(i) := '1';
WHEN OTHERS => result(i) := xmap;
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_StdULogic ( b : BIT ) RETURN std_ulogic IS
BEGIN
CASE b IS
WHEN '0' => RETURN '0';
WHEN '1' => RETURN '1';
END CASE;
END;
--------------------------------------------------------------------
FUNCTION To_StdLogicVector ( b : BIT_VECTOR ) RETURN std_logic_vector IS
ALIAS bv : BIT_VECTOR ( b'LENGTH-1 DOWNTO 0 ) IS b;
VARIABLE result : std_logic_vector ( b'LENGTH-1 DOWNTO 0 );
BEGIN
FOR i IN result'RANGE LOOP
CASE bv(i) IS
WHEN '0' => result(i) := '0';
WHEN '1' => result(i) := '1';
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_StdLogicVector ( s : std_ulogic_vector ) RETURN std_logic_vector IS
ALIAS sv : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s;
VARIABLE result : std_logic_vector ( s'LENGTH-1 DOWNTO 0 );
BEGIN
FOR i IN result'RANGE LOOP
result(i) := sv(i);
END LOOP;
RETURN result;

84 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

END;
--------------------------------------------------------------------
FUNCTION To_StdULogicVector ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS
ALIAS bv : BIT_VECTOR ( b'LENGTH-1 DOWNTO 0 ) IS b;
VARIABLE result : std_ulogic_vector ( b'LENGTH-1 DOWNTO 0 );
BEGIN
FOR i IN result'RANGE LOOP
CASE bv(i) IS
WHEN '0' => result(i) := '0';
WHEN '1' => result(i) := '1';
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_StdULogicVector ( s : std_logic_vector ) RETURN std_ulogic_vector IS
ALIAS sv : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s;
VARIABLE result : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 );
BEGIN
FOR i IN result'RANGE LOOP
result(i) := sv(i);
END LOOP;
RETURN result;
END;

-------------------------------------------------------------------
-- strength strippers and type convertors
-------------------------------------------------------------------
-- to_x01
-------------------------------------------------------------------
FUNCTION To_X01 ( s : std_logic_vector ) RETURN std_logic_vector IS
ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s;
VARIABLE result : std_logic_vector ( 1 TO s'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
result(i) := cvt_to_x01 (sv(i));
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_X01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS
ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s;
VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
result(i) := cvt_to_x01 (sv(i));
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_X01 ( s : std_ulogic ) RETURN X01 IS
BEGIN
RETURN (cvt_to_x01(s));
END;
--------------------------------------------------------------------
FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_logic_vector IS
ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b;
VARIABLE result : std_logic_vector ( 1 TO b'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
CASE bv(i) IS
WHEN '0' => result(i) := '0';
WHEN '1' => result(i) := '1';
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS
ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b;
VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP

85 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

CASE bv(i) IS
WHEN '0' => result(i) := '0';
WHEN '1' => result(i) := '1';
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_X01 ( b : BIT ) RETURN X01 IS
BEGIN
CASE b IS
WHEN '0' => RETURN('0');
WHEN '1' => RETURN('1');
END CASE;
END;
--------------------------------------------------------------------
-- to_x01z
-------------------------------------------------------------------
FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector IS
ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s;
VARIABLE result : std_logic_vector ( 1 TO s'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
result(i) := cvt_to_x01z (sv(i));
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_X01Z ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS
ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s;
VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
result(i) := cvt_to_x01z (sv(i));
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_X01Z ( s : std_ulogic ) RETURN X01Z IS
BEGIN
RETURN (cvt_to_x01z(s));
END;
--------------------------------------------------------------------
FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_logic_vector IS
ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b;
VARIABLE result : std_logic_vector ( 1 TO b'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
CASE bv(i) IS
WHEN '0' => result(i) := '0';
WHEN '1' => result(i) := '1';
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS
ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b;
VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
CASE bv(i) IS
WHEN '0' => result(i) := '0';
WHEN '1' => result(i) := '1';
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_X01Z ( b : BIT ) RETURN X01Z IS
BEGIN
CASE b IS
WHEN '0' => RETURN('0');

86 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

WHEN '1' => RETURN('1');


END CASE;
END;
--------------------------------------------------------------------
-- to_ux01
-------------------------------------------------------------------
FUNCTION To_UX01 ( s : std_logic_vector ) RETURN std_logic_vector IS
ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s;
VARIABLE result : std_logic_vector ( 1 TO s'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
result(i) := cvt_to_ux01 (sv(i));
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_UX01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS
ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s;
VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
result(i) := cvt_to_ux01 (sv(i));
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_UX01 ( s : std_ulogic ) RETURN UX01 IS
BEGIN
RETURN (cvt_to_ux01(s));
END;
--------------------------------------------------------------------
FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_logic_vector IS
ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b;
VARIABLE result : std_logic_vector ( 1 TO b'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
CASE bv(i) IS
WHEN '0' => result(i) := '0';
WHEN '1' => result(i) := '1';
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS
ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b;
VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH );
BEGIN
FOR i IN result'RANGE LOOP
CASE bv(i) IS
WHEN '0' => result(i) := '0';
WHEN '1' => result(i) := '1';
END CASE;
END LOOP;
RETURN result;
END;
--------------------------------------------------------------------
FUNCTION To_UX01 ( b : BIT ) RETURN UX01 IS
BEGIN
CASE b IS
WHEN '0' => RETURN('0');
WHEN '1' => RETURN('1');
END CASE;
END;

-------------------------------------------------------------------
-- edge detection
-------------------------------------------------------------------
FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS
BEGIN
RETURN (s'EVENT AND (To_X01(s) = '1') AND
(To_X01(s'LAST_VALUE) = '0'));
END;

87 de 88 28/11/2010 09:12 a.m.


VHDL http://www.jimenez-ruiz.es/ernesto/II/VHDL/vhdl.html

FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS


BEGIN
RETURN (s'EVENT AND (To_X01(s) = '0') AND
(To_X01(s'LAST_VALUE) = '1'));
END;

-------------------------------------------------------------------
-- object contains an unknown
-------------------------------------------------------------------
FUNCTION Is_X ( s : std_ulogic_vector ) RETURN BOOLEAN IS
BEGIN
FOR i IN s'RANGE LOOP
CASE s(i) IS
WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE;
WHEN OTHERS => NULL;
END CASE;
END LOOP;
RETURN FALSE;
END;
--------------------------------------------------------------------
FUNCTION Is_X ( s : std_logic_vector ) RETURN BOOLEAN IS
BEGIN
FOR i IN s'RANGE LOOP
CASE s(i) IS
WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE;
WHEN OTHERS => NULL;
END CASE;
END LOOP;
RETURN FALSE;
END;
--------------------------------------------------------------------
FUNCTION Is_X ( s : std_ulogic ) RETURN BOOLEAN IS
BEGIN
CASE s IS
WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE;
WHEN OTHERS => NULL;
END CASE;
RETURN FALSE;
END;

END std_logic_1164;

88 de 88 28/11/2010 09:12 a.m.

También podría gustarte