síntesis y descripción de circuitos digitales utilizando vhdl

Anuncio
SÍNTESIS Y DESCRIPCIÓN DE
CIRCUITOS DIGITALES
UTILIZANDO VHDL
IEC FRANCISCO JAVIER TORRES VALLE
2001
SINTESIS Y DESCRIPCIÓN DE CIRCUITOS DIGITALES UTILIZANDO VHDL
A N T E C E D E N T E S
En los últimos diez años la industria
electrónica ha tenido una gran evolución en el
desarrollo de sistemas digitales; desde
computadoras personales, sistemas de audio y
vídeo hasta dispositivos de alta velocidad para las
comunicaciones. Productos hechos con una alta
tecnología que permite aumentar la funcionalidad,
disminuir costos, mejorar el aprovechamiento de
la energía, así como una marcada tendencia hacia
la miniaturización. Esto ha sido posible gracias a
la implementación de herramientas de diseño
asistidos por computadora, conocidas como
herramientas CAD (Computer Aided Design),
aunque específicamente se hace uso de
herramientas
EDA
(Electronic
Design
Automation), que es el nombre que se le da a
todas las herramientas CAD para el diseño de
sistemas electrónicos. Este software de diseño
electrónico que facilita a los ingenieros el
desarrollo de circuitos es cada vez mas sofisticado
y, además, contamos con computadoras cada vez
más veloces y de mayor capacidad de
procesamiento. Ambos, hardware y software,
constituyen actualmente herramientas muy
importantes que simplifican el trabajo de diseño
electrónico. Además de facilitar el trabajo, el uso
de herramientas EDA también aceleró los
procesos de diseño. Esta situación condujo a
adoptar nuevas metodologías para el diseño y
evaluación de los circuitos electrónicos. El uso de
las herramientas EDA junto con los dispositivos
lógicos programables, que pueden ser utilizados
en
diferentes
aplicaciones
e
inclusive
reprogramados, cambiaron bastante el concepto
de diseño de circuitos digitales.
El presente trabajo considera los dispositivos
lógicos programables, enfocándonos en los PLDs,
CPLDs y FPGAs. Ya que el principal motivo por
el que debemos aprender a utilizar VHDL es el de
diseñar circuitos lógicos utilizando este tipo de
dispositivos. Se expondrán los estilos elementales
de codificación, exponiendo las principales
características de VHDL como lenguaje para
síntesis de circuitos. Finalmente se desarrolla la
implementación de filtros digitales utilizando
FPGAs.
VHDL es un lenguaje que se creó para el
diseño, modelado y documentación de circuitos
complejos. Actualmente se le utiliza para la
síntesis de circuitos digitales utilizando
dispositivos lógicos programables. Es así como
los dispositivos lógicos programables y VHDL,
Very High Speed Integrated Circuit (VHSIC)
Hardware Description Language, constituyen los
elementos fundamentales para estas nuevas
metodologías de diseño.
IEC FRANCISCO JAVIER TORRES VALLE
i
SINTESIS Y DESCRIPCIÓN DE CIRCUITOS DIGITALES UTILIZANDO VHDL
Í N D I C E
ANTECEDENTES
i
1.
LENGUAJES DE DESCRIPCIÓN DE HARDWARE
1
1.1. INTRODUCCIÓN.
2
1.2. EL CONCEPTO DE HERRAMIENTAS CAD-EDA.
2
1.3. LENGUAJES DE DESCRIPCIÓN DE HARDWARE.
4
1.3.1.
2.
VENTAJAS DE LOS HDLS
1.4. VHDL
5
1.5. METODOLOGÍA DE DISEÑO UTILIZANDO VHDL
6
DISPOSITIVOS LÓGICOS PROGRAMABLES
9
2.1. CONCEPTOS FUNDAMENTALES
10
2.2. DISPOSITIVOS LÓGICOS PROGRAMABLES
10
2.2.1.
MATRIZ GENÉRICA PROGRAMABLE
2.3. COMPLEX PROGRAMMABLE LOGIC DEVICES
10
11
2.3.1.
MATRIZ DE INTERCONEXIONES PROGRAMABLES
11
2.3.2.
BLOQUES LÓGICOS
11
2.3.3.
DISTRIBUCIÓN DE PRODUCTOS
12
2.3.4.
MACROCELDAS
12
2.3.5.
CELDA DE ENTRADA/SALIDA
13
2.4. FIELD PROGRAMMABLE LOGIC DEVICES
2.4.1.
3.
5
CELDAS LÓGICAS
13
14
SINTAXIS DEL LENGUAJE
17
3.1. INTRODUCCIÓN A LA DESCRIPCIÓN EN VHDL DE CIRCUITOS
DIGITALES
18
3.1.1.
MULTIPLEXORES
18
3.1.2.
COMPARADORES
19
3.1.3.
EL ESTILO DE “PROGRAMACIÓN” EN VHDL
20
3.2. IDENTIFICADORES
21
3.3. OBJETOS DE DATOS
21
3.3.1.
CONSTANTES
IEC FRANCISCO JAVIER TORRES VALLE
21
ii
SINTESIS Y DESCRIPCIÓN DE CIRCUITOS DIGITALES UTILIZANDO VHDL
3.3.2.
VARIABLES
22
3.3.3.
SEÑALES
22
3.3.4.
ALIAS
22
3.4. TIPOS DE DATOS
22
3.4.1.
TIPOS ESCALARES
22
3.4.2.
TIPOS COMPUESTOS
25
3.4.3.
SUBTIPOS
27
3.4.4.
TIPOS PREDEFINIDOS EN VHDL
27
3.4.5.
TIPOS NO SOPORTADOS EN VHDL PARA SÍNTESIS
27
3.5. OPERADORES
28
3.5.1.
OPERADORES LÓGICOS
28
3.5.2.
OPERADORES DE COMPARACIÓN
28
3.5.3.
OPERADORES DE ADICIÓN
28
3.5.4.
OPERADORES DE MULTIPLICACIÓN
29
3.5.5.
OPERADORES MISCELÁNEOS
29
3.5.6.
OPERADORES DE ASIGNACIÓN
29
3.5.7.
OPERADORES DE ASOCIACIÓN
30
3.5.8.
OPERADORES DE CORRIMIENTO
31
3.5.9.
OPERACIONES CON VECTORES
31
3.6. ATRIBUTOS
32
3.7. ENTIDADES
32
3.7.1.
GENÉRICOS
33
3.7.2.
PUERTOS
33
3.7.3.
MODOS
33
3.8. ARQUITECTURAS
34
3.9. DESCRIPCIONES DE FLUJO DE DATOS
34
3.9.1.
INSTRUCCIONES CONCURRENTES
35
3.9.2.
ESTRUCTURAS DE EJECUCIÓN CONCURRENTE
35
3.9.3.
ALU
35
3.10. DESCRIPCIONES COMPORTAMENTALES
38
3.10.1. INSTRUCCIONES SECUENCIALES
38
3.10.2. PROCESOS
38
3.10.3. DIFERENCIAS ENTRE SEÑALES Y VARIABLES
39
3.10.4. ESTRUCTURAS DE EJECUCIÓN SECUENCIAL
40
3.11. DESCRIPCIONES ESTRUCTURALES
IEC FRANCISCO JAVIER TORRES VALLE
42
iii
SINTESIS Y DESCRIPCIÓN DE CIRCUITOS DIGITALES UTILIZANDO VHDL
3.11.1. COMPONENTES
42
3.11.2. INSTANCIACIÓN DE COMPONENTES
43
3.11.3. SENTENCIAS DE GENERACIÓN
44
3.12. SUBPROGRAMAS
3.12.1. PROCEDIMIENTOS
47
3.12.2. FUNCIONES
47
3.12.3. LLAMADO A SUBPROGRAMAS
48
3.12.4. SOBRECARGA DE OPERADORES
50
3.13. LIBRERÍAS
4.
50
3.13.1. SÍNTESIS DE LIBRERÍAS EN WARP
50
3.13.2. PAQUETES
52
DESCRIPCIÓN DE CIRCUITOS DIGITALES
54
4.1. PROYECTOS EN WARP 5.0
55
4.2. SIMULACIÓN DE PROYECTOS
57
4.2.1.
PROCESO DE SIMULACIÓN
57
4.3. COMPARADORES
60
4.4. MULTIPLEXORES
65
4.4.1.
DESCRIPCIÓN DE FLUJO DE DATOS
65
4.4.2.
DESCRIPCIÓN COMPORTAMENTAL
66
4.4.3.
DESCRIPCIÓN ESTRUCTURAL
67
4.5. SUMADORES
5.
47
68
4.5.1.
SUMADOR TOTAL
68
4.5.2.
SUMADOR DE CUATRO BITS
69
4.5.3.
SYNTHESIS OFF
70
4.6. REGISTROS
71
4.7. CONTADORES
73
4.8. ALU DE CUATRO BITS
76
4.8.1.
DESCRIPCIÓN ESTRUCTURAL
77
4.8.2.
DESCRIPCIÓN COMPORTAMENTAL
78
4.9. MÁQUINAS DE ESTADO
79
IMPLEMENTACIÓN DE FILTROS DIGITALES EN FPGA'S
83
5.1. INTRODUCCIÓN
84
5.2. ANTECEDENTES
84
IEC FRANCISCO JAVIER TORRES VALLE
iv
SINTESIS Y DESCRIPCIÓN DE CIRCUITOS DIGITALES UTILIZANDO VHDL
5.3. MARCO TEÓRICO
84
5.3.1.
FILTROS FIR
84
5.3.2.
FILTROS IIR
85
5.3.3.
METODOLOGÍA DE DISEÑO PARA FILTROS DIGITALES
86
5.4. IMPLEMENTACIÓN EN FPGA'S
86
5.5. DISEÑO DE UN FILTRO PASA-BAJAS
86
5.6. RESULTADOS
93
CONCLUSIONES
95
BIBLIOGRAFÍA
97
IEC FRANCISCO JAVIER TORRES VALLE
v
CAPÍTULO I: LENGUAJES DE DESCRIPCIÓN DE HARDWARE
I
IEC FRANCISCO JAVIER TORRES VALLE
LENGUAJES DE
DESCRIPCIÓN DE
HARDWARE
1
CAPÍTULO I: LENGUAJES DE DESCRIPCIÓN DE HARDWARE
1.1
INTRODUCCIÓN
A mediados de los años setenta se produce una
fuerte evolución en los procesos de fabricación de
los circuitos integrados, promoviendo el desarrollo
de circuitos digitales hasta la primera mitad de los
años ochenta. En aquellas épocas el esfuerzo de
diseño se concentraba en los niveles eléctricos para
establecer características e interconexiones entre
los componentes básicos al nivel de transistor. El
proceso de diseño era altamente manual y tan sólo
se empleaban herramientas como PSPICE para
simular esquemas eléctricos con modelos
previamente caracterizados a cada una de las
distintas tecnologías. A medida que pasaban los
años, los procesos tecnológicos se hacían más y
más complejos. Los problemas de integración iban
en aumento y los diseños eran cada vez más
difíciles de depurar y de dar mantenimiento.
Inicialmente los circuitos MSI (Medium Scale
Integration) y LSI (Low Scale Integration) se
diseñaron mediante el desarrollo de prototipos
basados en módulos simples. Cada uno de estos
módulos estaba formado por compuertas ya
probadas, pero este método poco a poco iba
quedándose obsoleto conforme aumentaba la
complejidad y tamaño de los circuitos. A finales de
los años setenta se constata el enorme desfase que
existía entre tecnología y diseño.
La considerable dificultad que puede llegar a
tomar el fabricar un circuito de alta escala de
integración, involucra riesgos y costos de diseño
desmesurados e imposibles de asumir por las
empresas. Es entonces, cuando diversos grupos de
investigadores empiezan a crear y desarrollar los
llamados “lenguajes de descripción de hardware”,
lenguajes en los que no fuera necesario
caracterizar eléctricamente cada componente del
circuito al nivel de transistor para así enfocarse
solamente en el funcionamiento lógico del sistema.
Empresas tales como IBM con su IDL, el TI-HDL
de Texas Instruments, ZEUS de General Electric,
etc., así como los primeros prototipos empleados
en las universidades, empezaron a desarrollarse
buscando una solución a los problemas que
presentaba el diseño de sistemas complejos. Sin
embargo, estos lenguajes nunca alcanzaron el nivel
de difusión y consolidación necesarios por motivos
distintos. Unos, los industriales, por ser propiedad
de la empresa permanecieron encerrados en ellas y
no estuvieron disponibles para su estandarización y
mayor difusión, en tanto que los universitarios
IEC FRANCISCO JAVIER TORRES VALLE
perecieron por no disponer de soporte ni
mantenimiento adecuado.
1.2
EL CONCEPTO DE
HERRAMIENTAS CAD-EDA
CAD son las siglas de Computer Aided Design,
o diseño asistido por computadora el cual
constituye todo un proceso de trabajo utilizando
técnicas de análisis apoyadas en gráficos mediante
sofisticadas herramientas de software las cuales
facilitan el estudio de los problemas asociados con
el diseño en cuestión. El concepto CAD se
relaciona con el dibujo como parte importante en
el proceso de diseño pero, además, el diseño de un
circuito debe cumplir con los requerimientos
especificados por el equipo de diseño, por las
normas de calidad existentes, los costos, etc. por lo
que las herramientas CAD intervienen en todas las
fases del diseño. Ya que no sólo son importantes
por acelerar el desarrollo del sistema al permitir
que
varias
personas
puedan
trabajar
simultáneamente en distintas etapas del diseño
sino que, además, es posible verificar el
funcionamiento del circuito mediante la
simulación del sistema. Todo esto simplifica la
tarea del equipo de diseño y conduce a la
conclusión del prototipo en menos tiempo. EDA,
Electronic Design Automation, es el nombre que
se le da a todas las herramientas de hardware y
software en el diseño de sistemas electrónicos.
Porque no sólo el software es importante, también
lo es el hecho de que las computadoras cada día
son más veloces y de mayor capacidad de
procesamiento, lo cual influye en el proceso de
diseño de circuitos electrónicos.
El diseño de hardware tiene un problema
fundamental, que no existe en desarrollo de
software. Este problema es el alto costo del ciclo
diseño
desarrollo del prototipo
pruebas
reinicio del ciclo, ya que el costo del prototipo
generalmente suele ser bastante elevado. Se
impone la necesidad de reducir este ciclo de diseño
para no incluir la fase de desarrollo del prototipo
más que al final del proceso, evitando la repetición
de varios prototipos que es lo que encarece el
ciclo. Para ello se introduce la fase de simulación y
verificación de circuitos utilizando herramientas
EDA, de tal forma que no sea necesario
implementar físicamente un prototipo para
comprobar el funcionamiento del circuito.
2
CAPÍTULO I: LENGUAJES DE DESCRIPCIÓN DE HARDWARE
En el ciclo de diseño de circuitos, las
herramientas EDA están presentes en todas las
fases. Primero en la fase de generación del sistema
que puede representarse mediante un diagrama
esquemático, a bloques o de flujo.
A continuación se mencionan las principales
características y finalidad de algunas herramientas
EDA que intervienen en el diseño de circuitos.
Se encuentran también en la fase de simulación
y comprobación de circuitos, donde diferentes
herramientas permiten verificar el funcionamiento
del sistema. Estas simulaciones pueden ser de
eventos, funcionales, digitales o eléctricas, de
acuerdo al nivel de simulación requerido. Después
están las herramientas EDA utilizadas en la
síntesis y programación de circuitos digitales en
dispositivos lógicos programables. Existen,
además, las herramientas EDA orientadas a la
fabricación de circuitos. En el caso del diseño de
hardware estas herramientas sirven para la
realización de PCBs (Printed Circuit Boards o
placas de circuito impreso), o para desarrollar
circuitos integrados de aplicación especifica
conocidos como ASICs (Application Specific
Integrated Circuits). Este ciclo de diseño de
hardware se muestra en la figura 1.1.
Son lenguajes mediante los cuales es posible
describir el funcionamiento y estructura de un
circuito eléctrico o digital. La descripción puede
ser mediante bloques donde se muestra la
arquitectura del diseño, o de comportamiento, es
decir, se describe el funcionamiento del circuito en
vez de especificar los elementos de los que está
compuesto.
SÍNTESIS
SIMULACIÓN
FUNCIONAL
ANÁLISIS
TEMPORAL
¿FUNCIONA?
¿FUNCIONA?
II.
si
no
III.
Grafos y diagramas de flujo.
Simulación de eventos.
Estas herramientas se usan para la simulación de
circuitos a grandes rasgos. En esta simulación, los
componentes más importantes son elementos de
alto nivel como discos duros, buses de
comunicaciones, memorias RAM etc.
si
PROGRAMACIÓN
DEL
DISPOSITIVO
no
¿FUNCIONA?
Diagramas esquemáticos.
Es la forma clásica de describir un diseño
electrónico y la más extendida ya que era la única
usada antes de la aparición de las herramientas de
EDA. La descripción está basada en un “plano”
donde se muestran los diferentes componentes
utilizados en el circuito.
IV.
no
Lenguajes de descripción de circuitos.
Es posible describir un circuito o sistema
mediante diagramas de flujo, redes de Petri,
máquinas de estados, etc. En este caso sería una
descripción
gráfica
y
además
sería
comportamental, porque no es una descripción
mediante componentes.
IDEA
DESCRIPCIÓN
DEL CIRCUITO
I.
PRUEBAS AL DISEÑO
ELABORACIÓN
DEL PROTOTIPO
si
FINALIZA EL
PROCESO DE
DISEÑO
Figura 1.1 Flujo de diseño en el desarrollo de
sistemas electrónicos
IEC FRANCISCO JAVIER TORRES VALLE
V.
Simulación funcional.
Bajando al nivel de compuertas digitales se
puede realizar una simulación funcional de las
mismas. Este tipo de simulación comprueba la
operación de circuitos digitales a partir del
comportamiento lógico de sus elementos con el fin
de comprobar el funcionamiento en conjunto del
circuito mediante unos estímulos dados. Similar a
lo que se realiza en un laboratorio.
VI.
Simulación digital.
Esta simulación, también exclusiva de los
circuitos digitales, es como la anterior con la
diferencia de que se tienen en cuenta los retardos
3
CAPÍTULO I: LENGUAJES DE DESCRIPCIÓN DE HARDWARE
de propagación de cada compuerta. Es una
simulación muy cercana al comportamiento real
del circuito y prácticamente garantiza el
funcionamiento correcto del circuito en cuestión.
En las herramientas EDA este tipo de simulación
se conoce como análisis temporal o timing.
VII.
Simulación eléctrica.
Es la simulación de más bajo nivel donde las
respuestas del sistema se verifican al nivel de
transistor. Sirven tanto para circuitos analógicos
como digitales y su respuesta es prácticamente
idéntica a la realidad ya que se prueban retardos de
tiempo, niveles de voltaje, disipación de potencia,
etc.
VIII.
Diseño de PCBs
Con estas herramientas es posible realizar el
trazado de pistas para la fabricación de placas de
circuitos impresos.
IX.
Diseño de circuitos integrados
Son herramientas EDA que sirven para la
realización de circuitos integrados. Las
capacidades gráficas de estas herramientas
permiten la realización de las diferentes máscaras
que intervienen en la realización de éstos.
X.
Diseño con dispositivos programables.
Estas herramientas facilitan la programación de
dispositivos, ya sean PALs, PLDs, CPLDs o
FPGAs.
1.3
LENGUAJES DE
DESCRIPCIÓN DE
HARDWARE
Los lenguajes de descripción de hardware
(HDLs) son utilizados para describir la
arquitectura y comportamiento de un sistema
electrónico los cuales fueron desarrollados para
trabajar con diseños complejos.
Comparando un HDL con los lenguajes para el
desarrollo de software vemos que en un lenguaje
de este tipo un programa que se encuentra en un
lenguaje de alto nivel (VHDL) necesita ser
ensamblado a código máquina (compuertas y
conexiones) para poder ser interpretado por el
procesador. De igual manera, el objetivo de un
HDL es describir un circuito mediante un conjunto
de instrucciones de alto nivel de abstracción para
IEC FRANCISCO JAVIER TORRES VALLE
que el programa de síntesis genere (ensamble) un
circuito que pueda ser implementado físicamente.
La forma más común de describir un circuito es
mediante la utilización de esquemas que son una
representación gráfica de lo que se pretende
realizar. Con la aparición de herramientas EDA
cada vez más complejas, que integran en el mismo
marco de trabajo las herramientas de descripción,
síntesis, simulación y realización; apareció la
necesidad de disponer de un método de
descripción de circuitos que permitiera el
intercambio de información entre las diferentes
herramientas que componen el ciclo de diseño. En
principio se utilizó un lenguaje de descripción que
permitía, mediante sentencias simples, describir
completamente un circuito. A estos lenguajes se
les llamó Netlist puesto que eran simplemente eso,
un conjunto de instrucciones que indicaban las
interconexiones entre los componentes de un
diseño. A partir de estos lenguajes simples, que ya
eran auténticos lenguajes de descripción hardware,
se descubrió el interés que podría tener el describir
circuitos utilizando un lenguaje en vez de usar
esquemas. Sin embargo, se siguieron utilizando
esquemas puesto que desde el punto de vista del
ser humano son mucho más sencillos de entender,
aunque un lenguaje siempre permite una edición
más rápida y sencilla.
Conforme las herramientas de diseño se
volvieron más sofisticadas, y la posibilidad de
desarrollar circuitos digitales mediante dispositivos
programables era más viable, apareció la necesidad
de poder describir los circuitos mediante un
lenguaje de alto nivel de abstracción. No desde un
punto de vista estructural, sino desde el punto de
vista funcional. Este nivel de abstracción se había
alcanzado ya con las herramientas de simulación,
ya que para poder simular partes de un sistema era
necesario disponer de modelos que describieran el
funcionamiento de bloques del circuito o de cada
componente si fuera necesario. Estos lenguajes
estaban sobre todo orientados a la simulación, por
lo que poco importaba que el nivel de abstracción
fuera tan alto que no fuera sencillo una realización
o síntesis a partir de dicho modelo. Con la
aparición de técnicas para la síntesis de circuitos a
partir de lenguajes de alto nivel de abstracción, se
comenzaron a utilizar los lenguajes de simulación
para sintetizar circuitos. Que si bien alcanzan un
altísimo nivel de abstracción, su orientación era
básicamente la de simular, por lo que los
resultados de una síntesis a partir de descripciones
4
CAPÍTULO I: LENGUAJES DE DESCRIPCIÓN DE HARDWARE
con estos lenguajes no eran siempre las más
optimas.
Además, los lenguajes de descripción de
hardware al formar parte de las herramientas EDA
permiten el trabajo en equipo. Así, al estructurar el
desarrollo del proyecto, cada integrante del equipo
de diseño puede trabajar en subproyectos antes de
integrar todas las partes del sistema.
•
Un circuito hecho mediante una descripción
en un HDL puede ser utilizado en cualquier
tipo de dispositivo programable capaz de
soportar la densidad del diseño. Es decir, no es
necesario adecuar el circuito a cada
dispositivo porque las herramientas de síntesis
se encargan de ello.
•
Una descripción realizada en un HDL es más
fácil de leer y comprender que los netlist o
circuitos esquemáticos.
1.3.1 VENTAJAS DE LOS HDLS
Una metodología de diseño que utiliza un HDL
posee varias ventajas sobre la metodología
tradicional de diseño a nivel compuerta. Algunas
de estas ventajas son listadas a continuación.
•
Es posible verificar el funcionamiento del
sistema dentro del proceso de diseño sin
necesidad de implementar el circuito.
•
Las simulaciones del diseño, antes de que éste
sea implementado mediante compuertas,
permiten probar la arquitectura del sistema
para tomar decisiones en cuanto a cambios en
el diseño.
•
Las herramientas de síntesis tienen la
capacidad de convertir una descripción hecha
en un HDL, VHDL por ejemplo,
a
compuertas lógicas y, además, optimizar dicha
descripción de acuerdo a la tecnología
utilizada.
•
Esta metodología elimina el antiguo método
tedioso de diseño mediante compuertas,
reduce el tiempo de diseño y la cantidad de
errores producidos por el armado del circuito.
•
Las herramientas de síntesis pueden
transformar automáticamente un circuito
obtenido mediante la síntesis de un código en
algún HDL, a un circuito pequeño y rápido.
Además,
es
posible
aplicar
ciertas
características al circuito dentro de la
descripción para afinar detalles (retardos,
simplificación de compuertas, etc.) en la
arquitectura del circuito y que estas
características se obtengan en la síntesis de la
descripción.
•
Las descripciones en un HDL proporcionan
documentación de la funcionalidad de un
diseño independientemente de la tecnología
utilizada.
IEC FRANCISCO JAVIER TORRES VALLE
1.4
VHDL
VHDL es un lenguaje de descripción de
hardware utilizado para describir circuitos en un
alto nivel 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 tal manera que un diseño
desarrollado por una empresa pudiera ser
entendido por otra y, además, pudiera ser
procesado por software con propósitos de
simulación.
VHDL es reconocido como un estándar de los
lenguajes HDL por el Instituto de Ingenieros en
Electricidad y Electrónica – IEEE – como su
estándar 1076 el cual fue ratificado en 1987, y por
parte del Departamento de Defensa de los Estados
Unidos como el estándar MIL-STD-454L En 1993
el estándar IEEE-1076 se actualizó y un estándar
adicional, el IEEE-1164, fue adoptado. Para 1996
el estándar IEEE-1076.3 se convirtió en un
estándar de VHDL para síntesis siendo éste el que
se utiliza en el diseño de sistemas digitales. Los
estándares más utilizados en síntesis de circuitos
por la mayoría de las herramientas de diseño son el
IEEE-1164 y el IEEE-1076.3. En la actualidad
VHDL es un estándar de la industria para la
descripción, modelado y síntesis de circuitos
digitales. 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.
VHDL divide los circuitos en dos “vistas”
entidades y arquitecturas. La entidad modela al
circuito, componente o sistema externamente
5
CAPÍTULO I: LENGUAJES DE DESCRIPCIÓN DE HARDWARE
definiendo a este mediante un nombre y sus
conexiones que vienen siendo las entradas y
salidas del circuito. En tanto que la arquitectura,
que es la vista interna, define el funcionamiento
del circuito. Después de definir las interfaces de la
entidad, otras entidades pueden utilizar a la
primera como un subcircuito, al mismo tiempo que
todas están siendo desarrolladas, es decir, están
siendo detalladas en su funcionamiento. Este
concepto de vistas externas e internas es propio de
VHDL y permite segmentar un sistema en bloques.
Así, una entidad es relativa a otras entidades a
través de sus conexiones y comportamiento. Por lo
que es posible experimentar cada entidad con
diferentes arquitecturas sin necesidad de cambiar
el resto del diseño. Y obviamente cada entidad
puede ser reutilizada en otros sistemas aunque no
hayan sido diseñadas específicamente para estos.
Un modelo de hardware de VHDL es mostrado
en la siguiente figura.
Una señal posee una fuente (driver) y uno más
destinos (receptores) y un tipo de dato que le
proporciona características de interconexión. Por
ejemplo, una señal que se define como tipo bit
puede manejar los valores binarios ‘0’ y ‘1’
solamente, en tanto que una señal que se define
como bit_vector puede manejar mas de una
posición binaria.
La forma de diseñar circuitos en VHDL se
divide en tres categorías de acuerdo a su
complejidad: flujo de datos, comportamental, y
estructural. Estos tres estilos de diseño se detallan
a continuación.
•
FLUJO DE DATOS
En este estilo el diseño del circuito no es
complicado por lo que basta con describir como
fluyen los datos través de la entidad, de las
entradas hacia las salidas. La operación del sistema
está definida en términos de un conjunto de
transformaciones de datos expresadas como
instrucciones concurrentes.
•
COMPORTAMENTAL
El diseño es un poco más complicado ya que
requiere de varias decisiones antes de definir los
datos de salida correctos. Por lo que se requiere de
una descripción algorítmica del funcionamiento
del circuito para facilitar el diseño del sistema. En
VHDL esto se obtiene expresando el
funcionamiento del diseño mediante una estructura
PROCESS la cual se compone de instrucciones
secuénciales.
Figura 1.2 Modelo de Hardware de VHDL
Una entidad en VHDL, que ya es todo un
diseño, posee una o más conexiones hacia los
sistemas que la rodean. Una entidad puede estar
compuesta de otras entidades, de procesos y por
componentes,
todos
ellos
trabajando
concurrentemente. Cada entidad está definida por
su arquitectura la cual se forma de instrucciones en
VHDL, ya sean aritméticas, asignaciones a señales
o de simples instanciaciones de componentes.
Los PROCESS en VHDL son utilizados para
modelar tanto circuitos secuénciales como
combinacionales utilizando un estilo de
descripción secuencial. Para interconectar procesos
distintos se utilizan SIGNALS que no son otra
cosa que simples cables.
IEC FRANCISCO JAVIER TORRES VALLE
•
ESTRUCTURAL
Una descripción estructural se utiliza en
circuitos que requieren de más de una función,
hablando en términos de hardware, para realizar la
finalidad del sistema. Para ello segmentamos el
sistema en subcircuitos o componentes para
facilitar el diseño. Cada componente es
caracterizado en particular ya sea utilizando una
descripción de flujo de datos o comportamental. Y
a la entidad donde se describen las interconexiones
de estos componentes recibe el nombre de
descripción estructural.
Lo que ha hecho que VHDL sea en un tiempo
tan corto el lenguaje de descripción de hardware
más utilizado por la industria electrónica, es su
independencia con la metodología utilizada por
cada diseñador, su capacidad de descripción a
diferentes niveles de abstracción, y en definitiva la
6
CAPÍTULO I: LENGUAJES DE DESCRIPCIÓN DE HARDWARE
posibilidad de poder reutilizar en diferentes
aplicaciones un mismo código.
1.5
I.
METODOLOGÍA DE DISEÑO
UTILIZANDO VHDL
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.
II.
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, y el
último es utilizado normalmente en el diseño de
circuitos pequeños.
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 cada bloque en
particular. Obviamente existe la posibilidad de
cometer errores en VHDL, pero generalmente
estos son de son de sintaxis, como ";" al final de
cada instrucción, o simplemente por no utilizar
adecuadamente alguna instrucción. Algunas
ocasiones se podrán tener problemas al tratar de
sintetizar el código y esto se debe a que se comete
el error de pensar en términos de programación en
vez de enfocarnos en la descripción del circuito.
Cuando se utiliza VHDL el objetivo principal es
el diseño de hardware y para ello debemos de
utilizar técnicas de síntesis apropiadas al lenguaje,
ya que se suele cometer el error de comenzar a
programar en vez de describir y esto provoca que
nos olvidemos del objetivo que es el hardware.
LA CLAVE PARA DESCRIBIR Y SINTETIZAR
FÁCILMENTE CIRCUITOS DIGITALES CON
VHDL ES PENSAR EN TÉRMINOS DE
COMPUERTAS Y REGISTROS Y NO EN
FUNCIÓN DE VARIABLES Y SUBRUTINAS
III.
Simulación de la descripción en VHDL.
La metodología Top-Down consiste en dividir
el sistema en varios bloques de tal manera que se
puedan resolver los problemas por separado,
además, 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 mediante un componente que
desempeñe 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.
Este método de diseño es el que utilizamos
cotidianamente en el diseño de circuitos digitales,
y se le llama Flat por que no es necesario
seccionar el circuito para poder diseñarlo.
Síntesis consiste en reducir una descripción
realizada en un lenguaje de alto nivel de
abstracción a un nivel de compuerta que pueda ser
implementada en un 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 dispositivo lógico
programable.
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
Por ejemplo, una compuerta XOR puede ser
sustituido por su equivalente: A XOR B =
A'B+AB', o una instrucción IF puede ser en
algunas ocasiones una compuerta AND, en otras
IEC FRANCISCO JAVIER TORRES VALLE
La simulación del código, o simulación
funcional, nos permite detectar y corregir errores
antes que se implemente en el dispositivo. La
modularidad implementada facilita la evaluación
del circuito, porque al describir el circuito por
bloques podemos analizar cada uno por separado
antes de unirlos. Esta simulación equivale a la
depuración de programas en los lenguajes de
computación.
IV.
Síntesis
7
CAPÍTULO I: LENGUAJES DE DESCRIPCIÓN DE HARDWARE
una OR, o inclusive toda una función booleana que
involucra diferentes tipos de compuertas. Por lo
que el proceso de síntesis depende del dispositivo
utilizado. Generalmente una misma función es
implementada de diferentes formas de acuerdo al
dispositivo que estemos utilizando y esto no
cambia la funcionalidad del diseño y será la
misma si se selecciona el componente adecuado a
la complejidad del diseño. El proceso utilizado
para sintetizar un código en un CPLD es conocido
como Fitting o ajuste y consiste en adaptar las
ecuaciones booleanas en los diferentes bloques
lógicos del dispositivo. 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 a la síntesis de
circuitos utilizando FPGAs.
Por otro lado la optimización en la conversión
del código VHDL a ecuaciones booleanas depende
de tres factores:
I.
La descripción del circuito.
II. Los recursos disponibles en el dispositivo
seleccionado.
III. Las directivas de síntesis seleccionadas por el
diseñador.
La descripción es el punto más importante
porque de esto dependen los otros dos. En la
descripción no solamente tenemos que “decir”
como funciona el circuito, además, tenemos que
describir en que “forma” debe de hacerlo. No es lo
mismo describir el diseño de un sumador de cuatro
bits utilizando cuatro módulos que realizan la
suma basándose en propagación de bits de acarreo
entre estos, a describir un circuito que realice la
suma de manera paralela sin utilizar
retroalimentaciones. Finalmente suman pero no lo
hacen igual. Los recursos afectan la forma en que
son implementadas las ecuaciones lógicas en el
dispositivo. Por ejemplo, un contador de 4 bits con
borrado asíncrono no puede ser implementado en
un 16V8, porque el registro de la macrocelda de
salida del dispositivo no cuenta con esta
característica. Finalmente las directivas de
síntesis influyen directamente en el proceso de
cálculo de las ecuaciones que son implementadas
en el dispositivo. Algunas de estas directivas son:
asignación de pines, sintetizar para maximizar
velocidad, sintetizar para optimizar área, y algunas
IEC FRANCISCO JAVIER TORRES VALLE
que son descritas en el mismo código, como por
ejemplo forzar a que un nodo no sea simplificado o
eliminado y pueda ser retenido 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.
V.
Simulación del código sintetizado
Aún y cuando la simulación funcional se haya
realizado con éxito, debemos volver a evaluar el
circuito que realmente quedó sintetizado en el
dispositivo. Ya que las sustituciones de funciones,
como el caso de la compuerta XOR, dependerán de
las características del dispositivo utilizado. Y es
posible que ciertas funciones se ejecuten en más
tiempo de los esperado y esto altere el
funcionamiento del resto del diseño. Simular el
código sintetizado en el circuito permite verificar
los retrasos de tiempo de un nodo a otro, evaluar la
máxima frecuencia de operación del circuito y
verificar que éste funcione adecuadamente. En
dado caso que el código no pudiera ser sintetizado
podemos tratar de mejorar la descripción, es decir,
mejorar el diseño tratando de eliminar registros,
compuertas, buffers, etc., encontrar algún error en
la descripción, cambiar las directivas de síntesis o
definitivamente seleccionar otro dispositivo.
VI.
Programación del dispositivo
Después de completar la descripción, la síntesis
y la simulación del circuito con éxito, el siguiente
paso es generar el archivo que nos permite
implementar físicamente nuestro diseño en un
dispositivo programable. Todos los programas de
VHDL para síntesis generan un archivo con el que
podemos programar el dispositivo. Ya sea JEDEC,
JTAG, BITSTREAM, etc. de acuerdo al tipo
dispositivo y fabricante.
8
CAPÍTULO II: DISPOSITIVOS LÓGICOS PROGRAMABLES
II
DISPOSITIVOS LÓGICOS
PROGRAMABLES
IEC FRANCISCO JAVIER TORRES VALLE
9
CAPÍTULO II: DISPOSITIVOS LÓGICOS PROGRAMABLES
2.1
CONCEPTOS
FUNDAMENTALES
muestran los circuitos básicos para la mayoría de
los PLDs.
La fabricación de dispositivos de lógica
programable se basa en los siguientes dos
conceptos.
•
FUNCIONALIDAD COMPLETA
La cual se fundamenta en el hecho de que
cualquier función lógica se puede realizar
mediante una suma de productos.
•
CELDAS DE FUNCIONES UNIVERSALES.
También
denominadas
generadores
de
funciones, son bloques lógicos configurados para
procesar cualquier función lógica, similares en su
funcionamiento a una memoria. En estas celdas se
almacenan los datos de salida del circuito
combinacional en vez de implementar físicamente
la ecuación booleana.
2.2
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
dispositivo programable más simple es el PAL
(Programmable Array Logic). El circuito interno
de un PAL consiste en una matriz de conexiones,
un matriz de compuertas AND y un arreglo de
compuertas OR. Una matriz de conexiones es una
red de conductores distribuidos en filas y columnas
con un fusible en cada punto de intersección,
mediante la cual se seleccionan cuales entradas del
dispositivo 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.
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. Las matrices pueden ser
fijas o programables. Con estos recursos se
implementan las funciones lógicas deseadas
mediante un software especial y un programador
de dispositivos. 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 2.1 se
IEC FRANCISCO JAVIER TORRES VALLE
Figura 2.1 Estructuras comúnmente utilizadas en
PLDs
2.2.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 en forma de suma de
productos con un numero de términos definido. En
los PLDs no reprogramables la síntesis de las
ecuaciones lógicas se realiza mediante la quema de
fusibles en cada punto de intersección de los pines
de entrada con las compuertas. En un GAL el
fusible se reemplaza por una celda CMOS
eléctricamente borrable (EECMOS) y mediante
programación se activa o desactiva cada celda
EECMOS. Una celda activada conecta su
correspondiente intersección de fila y columna, y
una celda desactivada desconecta dicha
intersección. Con esta estructura 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.
A continuación se muestran las estructuras típicas
de un dispositivo GAL y la macrocelda de salida
del GAL22V10.
10
CAPÍTULO II: DISPOSITIVOS LÓGICOS PROGRAMABLES
Figura 2.2 Estructura típica de un GAL
FIGURA 2.3 Macrocelda de un GAL22V10
2.3
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 más eficientes porque
utilizan menos 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 y conduce a un mejor
desempeño. A continuación se explican
brevemente las principales características de la
arquitectura de un CPLD.
2.3.1
multiplexores. La primera se basa en una matriz
de filas y columnas con una celda EECMOS 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 de los 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 fijo de multiplexores por cada bloque
lógico. Las entradas de selección de estos
multiplexores son programadas para permitir que
sea seleccionada únicamente una vía de la matriz
de interconexiones por cada multiplexor, la cual se
propaga hacia el bloque lógico. Cabe mencionar
que estos multiplexores no tienen acceso a todas
las vías de la matriz por lo que la rutabilidad se
incrementa usando multiplexores de mayor
tamaño,
permitiendo
así
que
cualquier
combinación de señales de la matriz de
interconexión pueda ser enlazada hacia cualquier
bloque lógico. Sin embargo, el uso de grandes
multiplexores incrementa el tamaño de dispositivo
y reduce su desempeño.
MATRIZ DE INTERCONEXIONES
PROGRAMABLES
La matriz de interconexiones programables,
PIM Programmable Interconect Matrix (véase la
figura 2.4), permite 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 bloque. La
mayoría de los CPLDs usan una de dos
configuraciones para esta matriz: interconexión
mediante arreglo o interconexión mediante
IEC FRANCISCO JAVIER TORRES VALLE
Figura 2.4 Arquitectura Básica de un CPLD
2.3.2
BLOQUES LÓGICOS
Un bloque lógico es muy similar a un PLD, cada
uno de ellos poseen generalmente una matriz de
compuertas AND, una matriz de compuertas OR y
una configuración para la distribución de los
11
CAPÍTULO II: DISPOSITIVOS LÓGICOS PROGRAMABLES
productos en las diferentes macroceldas del boque.
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 cuatro a veinte
macroceldas. La cantidad de bloques lógicos que
puede poseer un CPLD depende de la familia y
fabricante del dispositivo.
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 flexibilidad para los
algoritmos del programa de síntesis que es el que
finalmente selecciona la mejor forma en que deben
ser distribuidas las ecuaciones lógicas en el
componente.
Figura 2.5 Estructura de un Bloque Lógico en
dispositivos de las familias MAX340 y MAX5000
2.3.3
DISTRIBUCIÓN DE PRODUCTOS
Existen pequeñas diferencias en cuanto a la
distribución de los productos en un CPLD, esto
dependerá de la familia del dispositivo y del
fabricante. Obviamente el tamaño de las sumas
sigue siendo el factor más importante para la
implementación de funciones lógicas. Pero cada
fabricante distribuye los productos de diferente
forma.
La familia MAX de CPLDs que fue
desarrollada por Cypress Semiconductor
conjuntamente 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, la
distribución de productos no es igual a la de un
PLD. En un dispositivo como el 22V10 tenemos
que la suma de productos es fija por cada
macrocelda -8, 10, 12, 14 o 16 productos-, en la
IEC FRANCISCO JAVIER TORRES VALLE
Figura 2.6 Distribución de Productos en
dispositivos de las familias MAX340 y MAX5000
2.3.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
utilizar salidas con 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 una terminal
del dispositivo. La salida de una macrocelda
12
CAPÍTULO II: DISPOSITIVOS LÓGICOS PROGRAMABLES
interna va conectada directamente a la matriz de
interconexiones programable. Por lo que es posible
manejar ecuaciones y almacenar el valor de salida
de estas internamente utilizando los registros de
estas macroceldas.
En la figura 2.7 se muestran la arquitectura
interna de un CPLD de la familia FLASH 370 de
Cypress Semiconductors. En esta podemos
apreciar las macroceldas de entrada/salida,
macroceldas ocultas y celdas de entrada/salida con
las que cuenta el dispositivo.
Figura 2.7 Macroceldas de entrada/salida, macroceldas ocultas y celdas de entrada/saliad en dispositivos
de la familia FLASH 370
Las macroceldas de entrada, como la que se
muestra en la figura 2.8, son utilizadas para
proporcionar entradas adicionales para las
funciones lógicas. 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 de la terminal de entrada.
2.3.5
En la figura 2.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 del CPLD estas
celdas son pueden ser consideradas o no parte del
bloque lógico.
2.4
Figura 2.8 Macrocelda de entrada en dispositivos
de la familia FLASH 370
IEC FRANCISCO JAVIER TORRES VALLE
CELDA DE ENTRADA/SALIDA
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
13
CAPÍTULO II: DISPOSITIVOS LÓGICOS PROGRAMABLES
y horizontales tal y como se muestra en la figura
2.9.
éste es programado ya no se puede recuperar. La
diferencia radica en que en un fusible normal se
desactiva deshabilitando la conexión, en tanto que
en estos anti - fusibles cuando son programados se
produce una conexión por lo que normalmente se
encuentran abiertos. La desventaja obvia es que no
son reutilizables, pero por el contrario disminuyen
considerablemente el tamaño y costo de los
dispositivos.
•
Figura 2.9 Arquitectura básica de un FPGA
2.4.1
CELDAS LÓGICAS
Cada celda lógica es funcionalmente similar a
los bloques lógicos de un CPLD. La diferencia
está en que un FPGA normalmente utiliza
generadores de funciones en vez de compuertas.
Cada uno de estos generadores es como una
memoria en donde en vez de implementar la
función lógica mediante compuertas, se precalcula
el resultado y se almacena en el generador. Las
entradas al generador funcionan como un bus de
direcciones,
y
mediante
las
diferentes
combinaciones de las entradas al generador se
selecciona el resultado correcto. Esto le da una
gran densidad al dispositivo ya que se maneja un
gran número de generadores, pero el tiempo de
propagación al implementar una función lógica en
estos generadores es menor al que se necesitaría si
utilizáramos compuertas. 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, un FPGA que
utiliza este tipo de tecnología sólo se puede
programar una sola vez y utilizan algo similar a un
fusible para realizar las conexiones. Una vez que
IEC FRANCISCO JAVIER TORRES VALLE
SRAM
Las celdas SRAM son implementadas como
generadores de funciones para remplazar la lógica
combinacional mediante compuertas y, además,
son usadas para controlar multiplexores e
interconectar las celdas lógicas entre ellas. En estas
el contenido se almacena mediante un proceso de
configuración en el momento de encendido del
circuito que contiene al FPGA. Ya que al ser
SRAM, el contenido de estos bloques de memoria
se pierde cuando se deja de suministrar la energía.
La información binaria de las celdas SRAM
generalmente se almacena en memorias seriales
EEPROM conocidas como memorias de
configuración. En el momento de encendido del
circuito toda la información binaria es transferida a
las celdas del FPGA mediante el proceso de
configuración el cual es generalmente automático
y el propio FPGA contiene un circuito interno que
se encarga de hacer todo el proceso.
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á fabricado con
tecnología SRAM. Una arquitectura con celdas
lógicas pequeñas permite utilizar todos los
recursos del dispositivo. Sin embargo, si las celdas
lógicas son muy pequeñas entonces tendremos que
utilizar un gran número de estas para poder
implementar funciones lógicas de varios términos,
lo cual agrega un tiempo de retardo por cada celda
lógica 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
14
CAPÍTULO II: DISPOSITIVOS LÓGICOS PROGRAMABLES
implementar funciones lógicas 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 paralelamente, siendo el mismo
tiempo de retardo para todas. 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 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
algunas celdas lógicas de distintos fabricantes.
Figura 2.10 Bloque Lógico Configurable de la familia XC4000 de Xilinx, Inc.
IEC FRANCISCO JAVIER TORRES VALLE
15
CAPÍTULO II: DISPOSITIVOS LÓGICOS PROGRAMABLES
Figura 2.11 Elemento Lógico de la familia APEX20K de Altera Corporation
Figura 2.12Modulo Lógico de la familia ACT3 de Actel Corporation
IEC FRANCISCO JAVIER TORRES VALLE
16
CAPÍTULO III: SINTAXIS DEL LENGUAJE
III
IEC FRANCISCO JAVIER TORRES VALLE
SINTAXIS DEL
LENGUAJE
17
CAPÍTULO III: SINTAXIS DEL LENGUAJE
3.1
INTRODUCCIÓN A LA
DESCRIPCIÓN EN VHDL DE
CIRCUITOS DIGITALES
En este capítulo se discutirán los elementos
fundamentales de VHDL que son comúnmente
utilizados en síntesis de circuitos. Primero se
exponen el diseño de multiplexores y
comparadores
con VHDL para hacer una
analogía con la metodología convencional de
diseño. Ya que es muy importante comprender
porque VHDL es un lenguaje para describir y no
para programar. Posteriormente se expondrán los
elementos básicos del lenguaje, tales como:
identificadores, objetos de datos, tipos de datos,
operadores y tipos de instrucciones.
3.1.1
z0
1
1
1
Utilizando cualquier técnica de simplificación
de ecuaciones obtenemos: z0 = s0’·x0+s0·x1. Y el
circuito quedaría como se muestra en la figura
3.2.
Figura 3.2 Circuito del Multiplexor 2 a 1
MULTIPLEXORES
Antes de examinar la descripción en VHDL de
multiplexores, analizaremos el funcionamiento
interno y la metodología tradicional de diseño
utilizada en este tipo de circuitos para después
realizar la descripción del circuito en VHDL. En
la figura 3.1 se describe externamente a un
multiplexor y la tabla resume su funcionalidad.
x0
x1
1
ENTRADA SALIDA
s0
z0
0
x0
1
x1
s0
Figura 3.1 Multiplexor 2 a 1
La tabla de verdad completa sería la siguiente.
ENTRADAS
SALIDA
s0
x0
x1
z0
0
0
0
0
0
0
1
0
0
1
0
1
0
1
1
1
1
0
0
0
1
0
1
1
1
1
0
0
IEC FRANCISCO JAVIER TORRES VALLE
En VHDL podemos describir el circuito ya sea
mediante la descripción completa de todas las
combinaciones de las entradas, utilizando la tabla
simplificada de funcionamiento o si lo deseamos
es posible realizar la descripción compuerta por
compuerta del circuito. Al primer estilo se le
conoce como de flujo de datos y en este debemos
describir como fluyen los datos de entrada hacia
la salida. A continuación se muestra la
descripción de flujo de datos del multiplexor con
VHDL utilizando la tabla completa de
funcionamiento del mismo. Las palabras en
negritas son palabras reservadas en VHDL y los
comentarios comienzan con dos guiones (--).
ENTITY multiplexor IS
PORT (s0, x0, x1: IN bit;
z0: OUT bit);
END multiplexor;
ARCHITECTURE data_flow OF multiplexor IS
SIGNAL temp: bit_vector (2 DOWNTO 0);
BEGIN
z0 <= '0' WHEN temp = "000" ELSE
'0' WHEN temp = "001" ELSE
'1' WHEN temp = "010" ELSE
'1' WHEN temp = "011" ELSE
'0' WHEN temp = "100" ELSE
'1' WHEN temp = "101" ELSE
'0' WHEN temp = "110" ELSE
'1';
temp <= s0 & x0 & x1; -- Concatenación
-- de las entradas en un
-- solo bus.
END data_flow;
Las descripciones en VHDL son creadas a
partir de dos estructuras que son fundamentales
18
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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
precisan cuales son las interfaces de
comunicación con el exterior, siendo la
arquitectura donde se detalla el comportamiento
interno de esa “caja”. Observe que en la
descripción anterior se utilizó un objeto de datos
llamado SIGNAL para crear el bus “temp” y
concatenar “s0”, “x0” y “x1” en un solo objeto y
así facilitar la descripción. A continuación
utilizaremos la tabla simplificada para diseñar el
multiplexor, ya que si observamos la salida
depende fundamentalmente de la entrada de
selección “s0”, por lo que atendiendo a esta
característica la descripción de flujo de datos
quedaría tal y como se muestra a continuación.
ENTITY multiplexor IS
PORT (s0, x0, x1: IN bit;
z0: OUT bit);
END multiplexor;
ARCHITECTURE data_flow OF multiplexor IS
BEGIN
z0 <= x0 WHEN s0 = '0' ELSE x1;
END data_flow;
En ambas descripciones hemos definido el
funcionamiento de la salida apoyándonos en las
entradas. Note que existe cierto “paralelismo” de
las entradas hacia las salidas, es decir, no importa
cual combinación de entradas se dé, sólo una
opción será asignada a la salida. Por lo que no
importa cual orden se haya seguido en la
descripción del circuito. Y esta es una de las
principales características de VHDL, es decir, no
importa tanto el orden de las instrucciones, lo cual
no es así en lenguaje de programación de
software. Tal vez este “paralelismo” se perciba
con mayor detalle realizando la descripción del
circuito compuerta por compuerta utilizando la
ecuación
simplificada del circuito obtenida
anteriormente.
not_s0 <= NOT s0;
and2 <= s0 AND x1;
END data_flow;
La descripción anterior también es de flujo de
datos y no sigue ningún orden en particular en el
uso de las instrucciones y esto se ha hecho para
destacar el comportamiento paralelo o
concurrente de VHDL. Observe que cada
ecuación describe a cada una de las compuertas
que se muestran en la figura 3.2, por lo cual no
hubiera importado el orden que hayamos seguido
siempre y cuando se realicen las conexiones
correctamente.
Pensemos en el circuito implementado
físicamente en el laboratorio. Cada una de estas
compuertas posee características eléctricas que les
asignan un funcionamiento definido. Estas
particularidades eléctricas cumplen con leyes
físicas que se están cumpliendo todo momento y,
entonces, no importa como se hayan ordenado
los circuitos entre sí lo importante es realizar
correctamente las conexiones para obtener la
función deseada. En VHDL se trata de emular ese
comportamiento, por lo tanto el orden que se haya
seguido en cada una de las instrucciones
anteriores no es importante, ya que hicimos
correctamente la interconexión entre las
compuertas.
3.1.2
COMPARADORES
La figura 3.3 representa a un comparador y la
siguiente tabla resume su funcionalidad.
ENTRADAS
SALIDAS
x_may_y equals x_men_y
x>y
1
0
0
x=y
0
1
0
x<y
0
0
1
ENTITY multiplexor IS
PORT (s0, x0, x1: IN bit;
z0: OUT bit);
END multiplexor;
ARCHITECTURE data_flow OF multiplexor IS
SIGNAL not_s0, and1, and2: bit;
BEGIN
z0 <= and1 OR and2;
and1 <= not_s0 AND x0;
IEC FRANCISCO JAVIER TORRES VALLE
19
CAPÍTULO III: SINTAXIS DEL LENGUAJE
Figura 3.3 Comparador
En el diseño convencional de un comparador
tendríamos que realizar una tabla de todos los
posibles valores lógicos de las salidas respecto a
las entradas. Lo cual en este caso sería de 256
combinaciones, dado que tenemos ocho bits de
entrada para obtener las tres ecuaciones de salida.
En VHDL basta con describir de una forma
general el funcionamiento del hardware y el
sintetizador se encargará de generar toda esta
tabla de 256 combinaciones y obtener las
ecuaciones lógicas de las tres salidas. El código
mostrado a continuación corresponde al
comparador mostrado en la figura 3.3.
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 data_flow 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 data_flow;
Nótese que en la primera declaración de
puertos, dentro de la entidad del comparador, se
definen dos bus de entrada de cuatro bits de
magnitud (x, y), en cambio las salidas son de
solamente un 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. Y es en la
arquitectura, después del BEGIN, es donde se
realiza la descripción del comportamiento del
circuito atendiendo únicamente a la funcionalidad
del mismo, es decir, no es necesario analizar cada
caso en particular de las 256 posibles
combinaciones.
3.1.3
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, sin embargo, no es así en el flujo de
ejecución de las instrucciones. Un código de
programación en VHDL no es precisamente un
IEC FRANCISCO JAVIER TORRES VALLE
“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. Así cuando
cambie alguna señal 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. Tal vez alguna vez
ha 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 se están
ejecutando al mismo tiempo y así sí se modela
adecuadamente un circuito. Posteriormente se
explicarán los tipos de instrucciones y sus
diferencias, ya que VHDL si permite la
“descripción secuencial” utilizando instrucciones
de esta naturaleza dentro de una estructura
llamada PROCESS. En 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á paralelamente con
el resto de las instrucciones que están fuera de
esta estructura.
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
20
CAPÍTULO III: SINTAXIS DEL LENGUAJE
sintetizar el código. Por ejemplo, si en el
dispositivo que usemos no es posible que las
salidas puedan ser programadas para que trabajen
con alta impedancia, aún y cuando la descripción
sea correcta nunca podremos sintetizarla en el
dispositivo.
EJEMPLOS
-- Este es un comentario.
ENTITY contador IS -- comentario al final
-- de una línea
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. Pero basta con
recordar que estamos diseñando hardware y que
por lo tanto no se trata de un lenguaje secuencial
de programación para software.
Los siguientes ejemplos son de identificadores
válidos en VHDL.
3.2
3er_Modulo
IDENTIFICADORES
Un identificador se define como un conjunto de
caracteres con el cual podemos representar
diferentes elementos dentro de una descripció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 carácter de un identificador debe
ser una letra.
•
El ultimo carácter de identificador no puede
ser el carácter de subrayado. Además, el
carácter 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.
IEC FRANCISCO JAVIER TORRES VALLE
Mi_entidad
Mux4a2
TTL_7490
A continuación se muestran ejemplos de
identificadores no válidos en VHDL.
-- un identificador no
-- puede iniciar con un
-- dígito
_salida_x
-- o con el carácter de
-- subrayado
M__24xmax
-- no se permiten dos
-- caracteres de
-- subrayado seguidos
My_design_ -- un identificador no
-- debe terminar con un
-- carácter de subrayado
Unidad&
SIGNAL
3.3
-- el caracter "&", no
-- es un carácter válido
-- palabra reservada
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 ha asignado algún
valor, éste no puede ser cambiado dentro de la
descripción del diseño. Las constantes pueden ser
21
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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 válidas
únicamente
dentro
de
la
estructura
correspondiente.
DECLARACIÓN DE CONSTANTES
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
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.
CONSTANT identificador: tipo := valor;
EJEMPLO
DECLARACIÓN DE SEÑALES
SIGNAL identificador: tipo [:=valor];
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: tipo [:=valor];
EJEMPLO
EJEMPLOS
SIGNAL A, B: bit := '0';
-- el valor
-- inicial es
-- opcional
SIGNAL dato: bit_vector (7 DOWNTO 0);
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 identif: tipo IS identif2 <rango>;
VARIABLE aux1, aux2: bit;
EJEMPLO
3.3.3
ALIAS instr: bit_vector (3 DOWNTO 0) IS
dato (7 DOWNTO 4);
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,
IEC FRANCISCO JAVIER TORRES VALLE
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
22
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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
Los tipos escalares tienen un orden especifico
lo cual permite que sean usados con diferentes
operadores. Existen cuatro 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 declarada como 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 gran mayoría de las herramientas de
software de VHDL para síntesis no es posible
utilizar este tipo de dato.
•
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.
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
a) En este ejemplo se define un tipo enumerado
llamado “arith”, y los posibles valores son add,
sub, mul, y div.
TYPE arith IS (add, sub, mul, div);
b) Ahora se define un tipo enumerado llamado
“estados”, con 4 posibles valores: estado0,
estado1, estado2 y estado3.
TYPE estados IS ( estado0, estado1,
estado2, estado3 );
Existen varios tipos de datos enumerados,
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
El tipo BOLEAN es un tipo enumerado con
dos valores, FALSE y TRUE, donde FALSE <
TRUE. Las funciones lógicas y de comparación
retornan siempre un valor booleano.
Cuando en una operación lógica o de
comparación se utilza un tipo de dato no
booleano, el bit por ejemplo, existen funciones de
conversión que permiten realizar dichas
operaciones con distintos tipos de datos. En el
caso del bit se utiliza la siguiente función.
boolean_var := (bit_var = '1');
BIT
El bit es un tipo enumerado que representa
valores binarios: '0' y '1'. Las operaciones lógicas
en las participa este tipo de dato regresan valores
binarios mediante las siguiente función.
IF (boolean_var) THEN
bit_var := '1';
ELSE
bit_var := '0';
END IF;
DECLARACIÓN DE UN TIPO ENUMERADO
IEC FRANCISCO JAVIER TORRES VALLE
23
CAPÍTULO III: SINTAXIS DEL LENGUAJE
CHARACTER
El tipo character es un tipo enumerado que
contiene el conjunto de los símbolos contenido
en el ASCII.
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', '-'. Para poder utilizar este tipo de dato es
necesario incluir el paquete dentro de la
descripción utilizando las siguientes dos líneas
antes de la declaración de la entidad.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
TYPE color is (red, green, yellow, blue,
violet);
TYPE primary_color IS (red, yellow, blue);
. . .
SIGNAL A: color;
SIGNAL B: primary_color;
SIGNAL C: bit;
SINAL D: std_logic;
. . .
A <= color'(red); -----
B <= blue; -- Posiblemente el
-- programa de síntesis
-- marque error en este
-- caso
C <= '1';
El significado de los valores del std_logic se
muestra en la siguiente tabla.
'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 '-'.
SOBRECARGA DE UN TIPO ENUMERADO
Es posible cargar el valor de algún tipo
enumerado incluyendo dicho valor en la
definición de dos o más tipos enumerados.
Cuando se utilice en una descripción dos o más
tipos que usen el mismo valor generalmente el
programa de síntesis identifica de cual tipo
proviene, pero bajo ciertas condiciones esta
determinación es imposible. En estos casos es
necesario indicar explícitamente de cual tipo se
trata. En el siguiente ejemplo se muestra como
realizar esta indicación explicita.
IEC FRANCISCO JAVIER TORRES VALLE
Se indica a que
tipo estamos
haciendo
referencia
D <= '1';
-- En estas dos
-- asignaciones el
-- programa de síntesis
-- identifica de que
-- tipo se trata
CODIFICACIÓN DE LOS TIPOS ENUMERADOS
Los tipos enumerados se ordenan de acuerdo a
sus valores. Los programas de síntesis
automáticamente codifican binariamente los
valores del tipo enumerado para que estos puedan
ser sintetizados. Algunos programas los hacen
mediante una secuencia binaria ascendente, otros
buscan cual es la codificación que mejor conviene
para tratar de minimizar el circuito o para
incrementar la velocidad del mismo una vez que
la descripción es sintetizada. También es posible
asignar el tipo de codificación mediante directivas
de síntesis.
El siguiente ejemplo muestra la forma en que el
programa de síntesis Foundation de Xilinx, Inc.
codifica un tipo enumerado de cinco posibles
valores.
TYPE color IS (red, green, yellow, blue,
violet);
La codificación sería la siguiente: red="000",
green="001",
yellow="010",
blue="011",
violet="100".
Para realizar la codificación manualmente se
deben utilizar directivas de síntesis que son
propias de cada programa. Para ver ejemplo de
cómo se utilizan consulte la ayuda del programa y
24
CAPÍTULO III: SINTAXIS DEL LENGUAJE
busque la sección de "directivas de síntesis" o
"codificación de tipos enumerados".
•
FÍSICOS
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.
IEC FRANCISCO JAVIER TORRES VALLE
25
CAPÍTULO III: SINTAXIS DEL LENGUAJE
VARIABLE valor_actual: valores;
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.
Algunas posibles maneras de asignar valores a
elementos de estos objetos son:
mensaje1(0) <= '1'; -- asignación de valor
-- al elemento '0' de
-- mensaje1
DECLARACIÓN DEL TIPO ARRAY
TYPE nombre IS ARRAY ( rango ) OF tipo;
mensaje(5) <= '0'; -- asignación de valor
-- al quinto elemento de
-- mensaje1
DECLARACION DEL TIPO RECORD
TYPE nombre IS RECORD
elemento: tipo_de_dato;
[;elemento: tipo_de_dato...];
END RECORD;
Un ARRAY 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 RECORD 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
declaraciones de un tipo ARRAY.
TYPE word IS ARRAY (0 TO 15) 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: word;
SIGNAL arreglo_matriz: matriz;
IEC FRANCISCO JAVIER TORRES VALLE
mensaje2 <= mensaje1; -- hace mensaje1
-- igual a mensaje2,
-- esto es 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,
-- noté que 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 inst1, inst2: instruccion;
A continuación se muestran algunas posibles
maneras de asignar valores a elementos de estos
objetos de datos.
inst1.operador := add; -- asigna un valor
-- a "operador"del
-- RECORD inst1
inst2.operador := sub; -- asigna un valor
-- a "operador" de
-- inst2
inst1.op1 := inst2.op2;
26
CAPÍTULO III: SINTAXIS DEL LENGUAJE
inst2 := inst1;
ARREGLOS RESTRINGIDOS
y1 <= B"1011";
x2 <= x"A";
y2 <= x"7";
z_octal <= o"2";
un_bit <= '1';
Un arreglo restringido (Constrained Array) es
aquel que está explícitamente definido mediante
rango entero especifico de un tipo de datos ya
existente. Cuando se declara un objeto de datos
con arreglo restringido, el objeto posee el mismo
rango.
El tipo std_logic_vector al igual que el
bit_vector es simplemente un arreglo de
elementos del tipo std_logic. La forma de
utilizarlo es similar a la del bit_vector.
EJEMPLO:
SIGNED & UNSIGNED
TYPE byte IS ARRAY (7 DOWNTO 0) OF bit;
-- Este es un arreglo restringido cuyo
-- rango es: (7, 6, 5, 4, 3, 2, 1, 0)
ARREGLOS INDEFINIDOS
Un arreglo indefinido o sin restricciones
(Unconstrained Array) es aquel que no está
delimitado mediante un rango entero especifico.
Un objeto de datos declarado con arreglo
indefinido deberá ser delimitado o de lo contrario
no podrá ser sintetizado.
EJEMPLO
TYPE bit_vector IS ARRAY
(integer RANGE <>) OF bit;
VARIABLE v: bit_vector(5 DOWNTO -5);
A continuación se exponen algunos tipos
compuestos comúnmente utilizados en síntesis de
circuitos utilizando VHDL.
BIT_VECTOR
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.
STD_LOGIC_VECTOR
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.
EJEMPLOS
x1 <= "0001";
IEC FRANCISCO JAVIER TORRES VALLE
27
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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 identif IS tipobase RANGE <rango>;
EJEMPLOS
SUBTYPE byte IS bit_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 el siguiente ejemplo se muestra como se
pueden crear subtipos de datos a partir de aquellos
tipos que sean definidos por el usuario.
EJEMPLOS
TYPE arith IS (add, sub, mul, div);
SUBTYPE add IS arith RANGE add TO sub;
SUBTYPE mul IS arith RANGE mul TO div;
paquete STANDAR, que es utilizado por la
mayoría de las herramientas de síntesis, no es
utilizado por completo. A continuación se
muestra una parte del paquete STANDAR donde
se encuentran los tipos y subtipos predefinidos
más utilizados.
PACKAGE standard IS
TYPE boolean IS (FALSE, TRUE);
TYPE bit IS ('0', '1');
TYPE character IS (
NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL,
BS, HT, LF, VT, FF, CR, SO, SI,
DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB,
CAN, EM, SUB, ESC, FSP, GSP, RSP, USP,
' ', '!', '"', '#', '$', '%', '&', ''',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\', ']', '^', '_',
''', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'x', 'y', 'z', '{', '|', '}', '~', DEL);
TYPE integer IS RANGE -2147483647 TO
2147483647;
SUBTYPE natural IS integer RANGE 0 TO
2147483647;
SUBTYPE positive IS integer RANGE 1 TO
2147483647;
TYPE string IS ARRAY (positive RANGE <>)
OF character;
TYPE bit_vector IS ARRAY (natural RANGE
<>) OF bit;
END standard;
Los únicos subtipos predefinidos son el natural
y el positive.
3.4.5
3.4.4 TIPOS PREDEFINIDOS EN VHDL
Algunos tipos no son muy utilizados aunque
existen dentro del lenguaje, como el characer o el
string, y hay otros que no son soportados por las
herramientas de síntesis. Los tipos no soportados
son ignorados y por lo tanto no pueden ser
sintetizados. Cada herramienta de síntesis define
cuales son los tipos, objetos o estructuras de
lenguaje que son o no soportados por la misma, a
continuación se muestran lo tipos y objetos no
soportados por el FOUNDATION.
Dentro del estándar VHDL de la IEEE se
describen dos paquetes en los que se especifica el
conjunto de tipos de datos y operaciones en las
que dichos tipos de datos pueden ser utilizados,
estos paquetes son: STANDARD y TEXTIO.
El paquete STANDAR de tipos de datos esta
incluido en todos archivos fuente de VHDL, es
decir, que no es necesario declararlo dentro de
código para poder utilizarlo. El paquete TEXTIO
define tipos de datos y operaciones para estos
tipos para la comunicación con el software de
síntesis que se este utilizando. Este no es
necesario para la síntesis de circuitos y algunos
programas de síntesis no lo soportan. De hecho, el
IEC FRANCISCO JAVIER TORRES VALLE
TIPOS NO SOPORTADOS EN VHDL
PARA SÍNTESIS
- Tipos físicos
- Tipos reales o flotantes.
- Objetos de datos ACCESS. Un ACCESS
equivale a un apuntador y no es soportado por que
no tiene ningún sentido en hardware.
28
CAPÍTULO III: SINTAXIS DEL LENGUAJE
- Objetos de datos FILE. Estos se utilizan para
almacenar datos en RAM o ROM de la
computadora.
IEC FRANCISCO JAVIER TORRES VALLE
29
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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
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.
EJEMPLOS
x <= y
-----
AND z OR w
esta forma de utilizar los
op. lógicos, es incorrecta y
producirá un error cuando sea
compilado el código
x <= y AND ( z OR w )
-- forma correcta de utilizar los
-- op.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;
AND, OR, NAND, NOR, XOR,
XNOR, NOT
COMPARACIÓN
=, /=, <, >, <=, >=
ADICIÓN
+, -, &
MULTIPLICACIÓN *, /, MOD, REM
MISCELÁNEOS
ABS, **
ASIGNACIÓN
<=, :=
ASOCIACIÓN
=>
CORRIMIENTO
SLL, SRL, SLA, SRA, ROL, ROR
LÓGICOS
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.
IEC FRANCISCO JAVIER TORRES VALLE
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. 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.
30
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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 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;
r <= '0'z + x; -- de esta manera se
-- obtiene el acarreo 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:
IEC FRANCISCO JAVIER TORRES VALLE
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 el
signo de A. MOD calcula el módulo 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
nombre_señal <= expresión;
Las asignaciones a variables solamente pueden
ocurrir dentro de los procesos o subrutinas, las
asignaciones a señales pueden ocurrir en
cualquier lugar dentro de la descripción.
31
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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 op IS (suma, resta, mult, div);
TYPE reg_datos IS RECORD
operador: op;
x: integer;
y: bit;
END RECORD;
. . .
VARIABLE registro: reg_datos;
SIGNAL vec1, vec2: bit_vector(0 TO 3);
. . .
vec1 <= ('0', '1', '1', '0');
-- asignación mediante agregados
vec2 <= vec1;
-- también esta es una asignación
-- mediante agregados
registro := ( resta, 13, '1' );
-- asignación a variable del tipo
-- record mediante agregados
vec2 <= ( '1', OTHERS => '0' );
-- en esta asignación se hace '1'
-- el elemento 0 de vector2 y el 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.
IEC FRANCISCO JAVIER TORRES VALLE
EJEMPLO
LIBRARY mi_libreria;
USE mi_libreria.sumadores.ALL;
ENTITY sumador IS
PORT ( ci: IN bit;
x: IN bit_vector(3 DOWNTO 0);
y: IN bit_vector(3 DOWNTO 0);
z: OUT bit_vector(3 DOWNTO 0);
co: OUT bit);
END sumador;
ARCHITECTURE a_sumador OF sumador IS
SIGNAL carry1: bit;
SIGNAL carry2: bit;
SIGNAL carry3: bit;
BEGIN
u0: add PORT MAP ( ci => ci,
x0 => x(0),
y0 => y(0),
z0 => z(0),
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_libreria”,
y esta declarado de la siguiente manera.
------------------------------------------- SUMADORES
------------------------------------------- paquete compilado en la librería
-- "mi_librería"
PACKAGE sumadores IS
· · ·
COMPONENT add
PORT ( ci: IN bit;
x0: IN bit;
y0: IN bit;
z0: OUT bit;
co: OUT bit );
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
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
32
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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 mismo.
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 del tipo signed o
unsigned.
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.
ROL
ROR
Figura 3.4 Instrucciones ROR y ROL
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
- 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 incluir
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
IEC FRANCISCO JAVIER TORRES VALLE
33
CAPÍTULO III: SINTAXIS DEL LENGUAJE
----------
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
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.
ATRIBUTOS PARA ARREGLOS
'left
Obtiene el valor que se encuentra a la
izquierda de un arreglo.
´right
Regresa el dato que se encuentra a la
derecha del arreglo.
´high
Permite obtener el mayor elemento de
un objeto de arreglo.
´low
Proporciona el valor más pequeño del
arreglo.
'lenght
Con este atributo se obtiene el número
de elementos de un arreglo.
Un arreglo es un objeto de datos que esta
compuesto por varios elementos de un tipo
sencillo, como lo son los bit_vector y
std_logic_vector.
ATRIBUTOS DE SEÑALES
'event
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 se
mencionan algunos que son útiles en
descripciones para síntesis.
IEC FRANCISCO JAVIER TORRES VALLE
El atributo event es del tipo boolean y
retorna un valor verdadero cuando
ocurre una transición en la señal a la
que 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.
34
CAPÍTULO III: SINTAXIS DEL LENGUAJE
DECLARACION DE ENTIDADES
ENTITY identificador IS
GENERIC ( cte_1: tipo := valor;
cte_2: tipo := valor;
· · ·
cte_n: tipo := valor
);
PORT ( puerto_1: modo tipo;
puerto_2: modo tipo;
· · ·
puerto_n: modo tipo
) ;
END identificador ;
Note que la ultima línea de declaración de
puerto o de genéricos no lleva punto y coma al
final de la línea.
EJEMPLO
En este ejemplo se realiza la entidad de un
multiplexor 4 a 1 que se muestra en la figura 3.5.
ENTITY mux_4_1 IS
PORT (a, b, c, d: IN bit;
mux_signal: IN bit_vector(1 DOWNTO 0);
x: OUT bit );
END mux_4_1;
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
Figura 3.5 Multiplexor de 4 bits a 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.
EJEMPLO
ENTITY comparador IS
GENERIC(msb: integer := 3);
PORT( x: IN bit_vector(msb DOWNTO 0);
IEC FRANCISCO JAVIER TORRES VALLE
- 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. 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
35
CAPÍTULO III: SINTAXIS DEL LENGUAJE
como un puerto del modo BUFFER lo hace
internamente no puede ser usado como
bidireccional.
Figura 36 Modos de direccionamiento para
puertos
IEC FRANCISCO JAVIER TORRES VALLE
36
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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.
Figura 3.7 Entidad, Símbolo Esquemático
EJEMPLO
ENTITY mux_4_1 IS
PORT ( a, b, c, d: IN bit;
mux_signal: IN bit_vector(1 DOWNTO 0);
x: OUT bit );
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
Figura 3.8 Arquitectura, Estructura Interna
DECLARACIÓN DE ARQUITECTURA
ARCHITECTURE identificador OF entidad IS
-- declaraciones de la arquitectura
BEGIN
-- Código de Descripción
-- instrucciones concurrentes
-- ecuaciones booleanas
-- PROCESS
-instrucciones secuenciales
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.
IEC FRANCISCO JAVIER TORRES VALLE
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.
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 tipo 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.
37
CAPÍTULO III: SINTAXIS DEL LENGUAJE
En este estilo de descripción se utilizan
únicamente asignaciones mediante expresiones en
las que se indica como cambian los 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
comprador utilizado en el primer tema de este
capítulo, en éste los datos son los que indican la
forma en que cambian las salidas y por esto 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.
EJEMPLO
gray <= "00" WHEN binario = x"0" ELSE
"01" WHEN binario = x"1" ELSE
"11" WHEN binario = x"2" ELSE
"10";
•
ASIGNACIÓN WHIT... SELECT... WHEN
SINTAXIS
WITH identificador SELECT
signal_name1 <= expresión
valor_a WHEN
valor_b WHEN
· · ·
valor_n WHEN
WHEN valor1,
valor2,
valor3,
OTHERS ;
EJEMPLO
WITH states SELECT
salida <= "000" WHEN state0,
"001" WHEN state1,
"010" WHEN state2,
"100" WHEN state3,
"000" WHEN OTHERS;
No olvidar la coma al final de cada línea,
excepto en la ultima que lleva punto y coma.
•
ECUACIONES BOOLEANAS
signal_name <= ecuación_booleana;
EJEMPLOS
x <= y AND z;
a <= ( b OR c OR d ) AND e ;
-- cuando se utilice más de un operador
-- lógico es necesario utilizar paréntesis
op1 <= op2 NOR op3 NOR op4;
3.9.2
•
ESTRUCTURAS DE EJECUCIÓN
CONCURRENTE
ASIGNACIÓN CONDICIONAL WHEN... ELSE
SINTAXIS
signal_name <= valor_a WHEN condición ELSE
valor_b WHEN condición ELSE
valor_c WHEN condición ELSE
valor_d WHEN condición ELSE
· · ·
valor_n WHEN condición ELSE
otro_valor;
3.9.3
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
s1
IEC FRANCISCO JAVIER TORRES VALLE
ALU
s0
SALIDAS
z
co
38
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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
CÓDIGO 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;
instrucciones no importa dentro de una
descripción, recordemos que VHDL describe
circuitos y por lo tanto todas las asignaciones
(conexiones) siempre están funcionando al igual
que todos los dispositivos dentro de un circuito.
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.
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",
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
IEC FRANCISCO JAVIER TORRES VALLE
Figura 3.9 Diagrama a bloques de la ALU
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
39
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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
Summary:
Error Count = 0 Warning Count = 0
Completed Successfully
------------------------------------------
-----------------------------------------PLD Compiler Software: MAX2JED.EXE
02/APR/1999 [v4.02 ] 5.2 IR 17
-----------------------------------------UTILIZACIÓN
DESIGN EQUATIONS (05:56:54)
-----------------------------------------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
------------------------------------------
-----------------------------------------PIN – OUT
-----------------------------------------PLD Compiler Software: PLA2JED.EXE
02/APR/1999 [v4.02 ] 5.2 IR 17
PINOUT INFORMATION (06:15:24)
Completed Successfully
------------------------------------------
Messages:
Information: Checking for duplicate NODE
logic.
None.
IEC FRANCISCO JAVIER TORRES VALLE
40
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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, 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;
IEC FRANCISCO JAVIER TORRES VALLE
La lista sensible 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, 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
41
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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.10.
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 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';
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 comparador;
Figura 3.10 Comparador
Este ejemplo corresponde al mismo comprador
utilizado en el tema 3.1.2. 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
IEC FRANCISCO JAVIER TORRES VALLE
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_vector(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;
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 de la
siguiente forma:
y_tmp = s(0)'·s(1)' + s(0)·s(1)
42
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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
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'
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; -- 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 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 no_valida1 OF senial IS
BEGIN
z <= x AND y;
z <= x OR y;
END no_valida1;
ARCHITECTURE 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 no_valida2;
ARCHITECTURE valida1 OF senial IS
BEGIN
PROCESS(x, y)
BEGIN
z <= x AND y; -- driver de z = x AND y
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 valida1;
z_var := x AND z_var;
-- z_var = x AND '1'
-- z_var = x
z_sig <= x AND y;
-- driver de z_sig = x AND y
IEC FRANCISCO JAVIER TORRES VALLE
43
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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 =>
· · ·
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;
IEC FRANCISCO JAVIER TORRES VALLE
EJEMPLO
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 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
44
CAPÍTULO III: SINTAXIS DEL LENGUAJE
y <= (OTHERS => '0');
ELSE
y <= y + 1;
END IF;
END PROCESS;
IEC FRANCISCO JAVIER TORRES VALLE
45
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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.11.
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.
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.
Figura 3.11 Descripciones Estructurales
LIBRARY mi_librería;
USE mi_libreria.compuertas.ALL;
ENTITY structural IS
PORT ( x, y: IN bit;
z: OUT bit);
END structural;
ARCHITECTURE estructural OF structural IS
SIGNAL nodo1: bit;
SIGNAL nodo2: bit;
SIGNAL nodo3: bit;
SIGNAL nodo4: bit;
SIGNAL nodo5: bit;
BEGIN
U1: not_gate PORT MAP(x, nodo1);
-- (entrada, salida)
U2: not_gate PORT MAP(y, nodo2) ;
-- (entrada, salida)
U3: and_gate PORT MAP(nodo1, y, nodo3);
-- (entrada, entrada, salida)
U4: and_gate PORT MAP(nodo3, nodo2,
nodo4 );
U5: and_gate PORT MAP(nodo2, x, nodo5);
U6: or_gate PORT MAP(nodo4, nodo5, z);
-- (entrada, entrada, salida)
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.
IEC FRANCISCO JAVIER TORRES VALLE
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.
SINTAXIS
COMPONENT identificador
PORT( senial { , senial}: modo tipo;
senial { , senial}: modo tipo;
senial: { , senial}: modo tipo
);
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
GENERICS( generico{ , generico }:
[ modo ] tipo [ := valor ];
· · ·
generico{ , generico }:
[ modo ] tipo [ := valor ]
);
PORT( senial { , senial}: modo tipo;
46
CAPÍTULO III: SINTAXIS DEL LENGUAJE
· · ·
senial: { , senial}: modo tipo
);
END COMPONENT;
EJEMPLO
COMPONENT add_n
GENERICS(w: integer := 8);
PORT(a, b: IN bit_vector(w-1 DOWNTO 0);
ci: IN bit;
suma: OUT bit_vector(w-1 OWNTO 0 );
co: OUT std_logic
) ;
END COMPONENT;
3.11.2 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 PORT MAP(
puerto_componente => señal,
puerto_componente => variable,
puerto_componente => expresion,
puerto_componente => OPEN,
· · ·
puerto_componente => señal
);
OPEN indica cuando un puerto de salida del
componente no se conecta a nada.
EJEMPLO
ARCHITECTURE a_reg8 OF reg8 IS
SIGNAL clock, reset, enable: std_logic;
SIGNAL data_in: std_logic_vector(7
IEC FRANCISCO JAVIER TORRES VALLE
DOWNTO 0);
SIGNAL data_out: std_logic_vector(7
DOWNTO 0);
BEGIN
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 GENERIC MAP (
identificador_generico => señal,
identificador_generico => variable,
identificador_generico => expresión,
identificador_generico => OPEN
· · ·
identificador_generico => señal
);
PORT MAP(
puerto_componente => señal,
puerto_componente => variable,
puerto_componente => expresion,
puerto_componente => OPEN,
· · ·
puerto_componente => señal
);
ASOCIACIÓN POR POSICIÓN
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 PORT MAP (
señal, variable, OPEN, señal,
variable, OPEN, ..., señal );
EJEMPLO
ARCHITECTURE a_reg8 OF reg8 IS
SIGNAL clock, reset, enable: std_logic;
SIGNAL data_in: std_logic_vector(7
DOWNTO 0);
SIGNAL data_out: std_logic_vector(7
DOWNTO 0);
BEGIN
reg_1: register8 PORT MAP(clock, reset,
47
CAPÍTULO III: SINTAXIS DEL LENGUAJE
enable, data_in, data_out);
END a_reg8;
IEC FRANCISCO JAVIER TORRES VALLE
48
CAPÍTULO III: SINTAXIS DEL LENGUAJE
ASOCIACIÓN POR POSICIÓN CON GENÉRICOS
etiqueta: identificador GENERIC
señal, variable, expresión,
..., señal);
PORT MAP ( señal, variable,
señal, variable, OPEN, ...,
MAP(
OPEN,
OPEN,
señal);
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);
END a_reg8;
3.11.3 SENTENCIAS DE GENERACIÓN
Las sentencias de generación de componentes
permiten crear una o más copias de un conjunto
de interconexiones, lo cual facilita el diseño de
circuitos mediante descripciones estructurales.
•
FOR.. GENERATE
Esta instrucción genera un número finito de
conexiones o de instrucciones concurrentes
mediante rango discreto.
SINTAXIS
c(2*i + 1) <= a(i) NOR x;
c(2*i)
<= b(i) NOR x;
END GENERATE;
Figura 3.12 For... Generate
El uso más común de las instrucciones de
generación es para crear múltiples copias de
componentes y procesos. En el siguiente ejemplo
se muestra como utilizar estas instrucciones con
componentes y en la figura 3.13 se muestra el
circuito resultante.
COMPONENT comp
PORT (x : IN bit;
y : OUT bit);
END COMPONENT;
· · ·
SIGNAL a, b: bit_vector(0 TO 7);
. . .
gen: FOR i IN a'RANGE GENERATE
u: comp PORT MAP (x => a(i),
etiqueta: FOR indice IN rango GENERATE
{ instucciones_concurrentes }
END GENERATE;
La etiqueta es necesaria y el índice de bucle es
una variable del tipo entero que no necesita ser
declarada anteriormente.
EJEMPLO
El siguiente ejemplo muestra como conectar
dos arreglos de cuatro bits un tercer arreglo de
ocho bits.
SIGNAL a, b
SIGNAL c
SIGNAL x
. . .
genera: FOR
: bit_vector(3 DOWNTO 0);
: bit_vector(7 DOWNTO 0);
: bit;
i IN 3 DOWNTO 0 GENERATE
IEC FRANCISCO JAVIER TORRES VALLE
y => b(i));
49
CAPÍTULO III: SINTAXIS DEL LENGUAJE
END GENERATE gen;
Figura 3.13 Instaniación de Componentes
utilizando la inst. For... Generate
•
PROCESS(clk, s)
BEGIN
IF clk'EVENT AND clk='1' THEN
convert(i) <= s(i-1);
END IF;
END PROCESS;
END GENERATE;
IF.. GENERATE
If... Generate realiza la instrucción de
instanciación o la instrucción concurrente sólo si
la condición de prueba es válida.
SINTAXIS
etiqueta: IF condición GENERATE
{ instucciones_concurrentes }
END GENERATE;
El uso es similar a la instrucción secuencial
IF... THEN, la diferencia es que en esta no se
pueden utilizar la condiciones extras ELSE o
ELSIF. El siguiente ejemplo muestra la
descripción de un registro de conversión serieparalelo de N bits. La información serial DATA
es almacenada en los registros CONVERT a
través de cnexiones mediante la señal S, en cada
transición positiva del reloj. El circuito resultante
se muestra en la figura 3.14.
-- Almacena el bit de entrada DATA en el
-- primer registro
g3: IF (i = convert'RIGHT) GENERATE
PROCESS(clk,s)
BEGIN
IF clk'EVENT AND clk='1' THEN
convert(i) <= data;
END IF;
END PROCESS;
s(i) <= convert(i);
END GENERATE;
END GENERATE;
END behavior;
Como podrá observar en la figura 3.14 las
retroalimentaciones en algunas ocasiones se
realizaron desde la salida Q de cada registro y en
otros usando la salida negada. Esto dependerá del
programa de síntesis utilizado y del dispositivo
empleado.
ENTITY converter IS
GENERIC(n: integer := 8);
PORT(clk, data:
IN bit;
convert: BUFFER bit_vector(n-1
DOWNTO 0));
END converter;
ARCHITECTURE behavior OF converter IS
SIGNAL s: bit_vector(convert'RANGE);
BEGIN
g: FOR i IN convert'RANGE GENERATE
-----
Desplaza el bit del registro (N-2)
en el registro superior (N-1).
Ya que el bit N-1 se pierde en
cada transición del reloj.
g1: IF (i = convert'LEFT) GENERATE
PROCESS(clk, s)
BEGIN
IF clk'EVENT AND clk='1' THEN
convert(i) <= s(i-1);
END IF;
END PROCESS;
END GENERATE;
-- Desplaza los bits intermedios
-- hacia arriba
g2: IF (i > convert'RIGHT AND
i < convert'LEFT) GENERATE
s(i) <= s(i-1) AND convert(i);
IEC FRANCISCO JAVIER TORRES VALLE
50
CAPÍTULO III: SINTAXIS DEL LENGUAJE
Figura 3.14 Diseño de circuitos utilizando la inst. If... Generate
IEC FRANCISCO JAVIER TORRES VALLE
51
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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
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
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;
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.
PACKAGE BODY ejemplo IS
-- cuerpo del procedimiento
PROCEDURE procedimiento ( a: IN bit ;
b: INOUT bit) IS
BEGIN
b := a AND b ;
END;
END ejemplo;
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.
3.12.2 FUNCIONES
Los procedimientos pueden ser utilizados de
manera concurrente o secuencial, es decir, ya sea
fuera o dentro de un proceso. Si alguno de los
IEC FRANCISCO JAVIER TORRES VALLE
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
47
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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;
CUERPO DE LA FUNCIÓN
FUNCTION identificador (lista de
parámetros) RETURN tipo IS
-- declaraciones
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.3 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.
- INOUT: 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
IEC FRANCISCO JAVIER TORRES VALLE
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.
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.
SINTAXIS
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: INOUT bit_vector(1 DOWNTO 0);
entB: INOUT bit_vector(1 DOWNTO 0);
entC: INOUT bit_vector(1 DOWNTO 0);
sal0: INOUT bit_vector(1 DOWNTO 0);
sal1: INOUT bit_vector(1 DOWNTO 0));
END proc_ejemplo;
ARCHITECTURE 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 => sal0);
procedimiento(entA, entC, sal1) ;
END ejemplo;
48
CAPÍTULO III: SINTAXIS DEL LENGUAJE
EJEMPLO
El siguiente ejemplo muestra un procedimiento
local (declarado dentro de un proceso) llamado
SWAP el cual compara y ordena dos elementos de
un arreglo. El procedimiento es llamado varias
veces para acomodar todos los elementos del
arreglo.
PACKAGE data_types IS
TYPE dat_element IS integer RANGE 0 TO 3;
TYPE data_array IS ARRAY (1 TO 3) OF
dat_element;
END data_types;
USE work.data_types.ALL;
ENTITY sort IS
PORT(in_array:
IN data_array;
out_array: OUT data_array);
END sort;
ARCHITECTURE example OF sort IS
BEGIN
PROCESS(in_array)
PROCEDURE swap(data: INOUT data_array;
low, high: IN integer)
IS
VARIABLE temp: data_element;
BEGIN
IF (data(low) > data(high)) THEN
temp := data(low);
data(low) := data(high);
data(high) := temp;
END IF;
END swap;
VARIABLE my_array: data_array;
BEGIN
my_array := in_array;
swap(my_array, 1, 2);
swap(my_array, 2, 3);
swap(my_array, 1, 2);
out_array <= my_array;
END PROCESS;
END example;
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.
SINTAXIS
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
IEC FRANCISCO JAVIER TORRES VALLE
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.
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;
49
CAPÍTULO III: SINTAXIS DEL LENGUAJE
ARCHITECTURE funcion OF uso_funcion IS
BEGIN
valor_de_retorno <= ejemplo_func(in1,
in2, in3);
END funcion;
En el siguiente ejemplo, la función OPERATE
realiza las funciones AND y OR con los operandos
de entrada A y B. LA operación realizada depende
del valor del parámetro OPERATION. El circuito
resultante se muestra en la figura 3.15.
FUNCTION operate(a, b, operation: bit)
RETURN bit IS
BEGIN
IF (operation = '1') THEN
RETURN (a AND b);
ELSE
RETURN (a OR b);
END IF;
END operate;
-- 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 " " para que el programa de
síntesis lo interprete como operador. 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;
Figura 3.15 Circuito generado mediante el uso de
funciones
3.12.4 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. También es posible crear
operadores para ser utilizados con los tipos de
datos definidos por el usuario.
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:
1. – Dentro de Galaxy selecciona: File > New >
Project [ Target - Library ]
EJEMPLO
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
IEC FRANCISCO JAVIER TORRES VALLE
50
CAPÍTULO III: SINTAXIS DEL LENGUAJE
2. – 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 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.
3. – 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.
IEC FRANCISCO JAVIER TORRES VALLE
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".
51
CAPÍTULO III: SINTAXIS DEL LENGUAJE
RETURN tempo ;
END;
END swap ;
-- instanciación de un paquete que se
-- encuentra en el mismo proyecto
USE work.swap.ALL;
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;
4. – 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.
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:
USE libreria.identificador_paquete.ALL ;
Donde identificador_paquete es el nombre del
paquete que creaste en el mismo proyecto.
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.
EJEMPLO
DECLARACIÓN DEL PAQUETE
USE work.identificador_paquete.ALL;
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);
IEC FRANCISCO JAVIER TORRES VALLE
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
52
CAPÍTULO III: SINTAXIS DEL LENGUAJE
-- 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
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;
END v3_tbl;
-- convierte un entero entre 0 y 7 en un
-- vector de 3 bits
PACKAGE BODY v3_tbl IS
FUNCTION int2v3 (ia: integer) RETURN v3
IS
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);
y: IN std_logic_vector
(msb DOWNTO 0);
z: OUT std_logic_vector
(msb DOWNTO 0));
END COMPONENT;
END multiplexores;
IEC FRANCISCO JAVIER TORRES VALLE
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);
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: std_logic_vector
(3 DOWNTO 0);
SIGNAL 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 ;
53
CAPÍTULO III: SINTAXIS DEL LENGUAJE
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.
IEC FRANCISCO JAVIER TORRES VALLE
54
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
IV
IEC FRANCISCO JAVIER TORRES VALLE
DESCRIPCIÓN DE
CIRCUITOS
DIGITALES
54
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
4.1
PROYECTOS EN WARP 5.0
El objetivo de este capítulo es enseñarte a crear
proyectos en VHDL utilizando Warp de Cypress
Semiconductors. Así como diferentes métodos
prácticos para la síntesis de los circuitos digitales
más comunes.
Figura 4.2
3. Posteriormente debe aparecer un cuadro de
dialogo como el que se muestra a continuación.
Para crear un proyecto con el que quieres
programar un dispositivo debes de seleccionar la
segunda opción (Project [Target - Device]).
PROCEDIMIENTO
1. Una vez en Windows haz click en el botón de
inicio, selecciona Programas > Warp R5.0 >
Galaxy.
4. Cuando selecciones la opción de Project
[Target - Device] aparecerá una ventana que te
pide que pongas un nombre a tu proyecto, escribe
el nombre de nuevo. En el segundo cuadro de texto
te pide que especifiques el directorio en donde
debe de guardar tu proyecto, puedes hacer un
directorio nuevo desde esa misma ventana con solo
escribir el nombre, por ejemplo c:\nuevo, o puedes
buscar una carpeta ya existente con la opción
Browse. Cuando hayas terminado de especificar
los nombres haz click en el botón de Siguiente.
Figura 4.1
2. Cuando te encuentres dentro del Galaxy,
selecciona File > New.
Figura 4.3
5. Aparecerá una ventana con título Add Files to
Project, esta ventana se usa cuando ya tienes
archivos que quieres agregar a tu proyecto, pero en
esta ocasión por tratarse de un proyecto totalmente
nuevo no es necesario especificar nada dentro de
esta ventana. Solo haz click en el botón de
Siguiente.
IEC FRANCISCO JAVIER TORRES VALLE
55
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
7. Luego de lo anterior, aparecerá una ventana
que te pregunta si deseas guardar tu nuevo
proyecto, solo haz click en Sí.
8. Ahora ya tienes un nuevo proyecto donde se
encuentra suficiente información para que el
compilador te genere el archivo .jed. Pero te falta
agregar el código que habrá de compilarse.
Selecciona File > New > Text File, o puedes hacer
click en el icono de nuevo. Escribe lo siguiente
dentro del archivo de texto:
library ieee;
Figura 4.4
6. La siguiente ventana lleva el título de Select
Target Device, esta ventana es muy importante ya
que es aquí donde debes de especificar el PLD en
el que vas a trabajar. Los PLD's que se usan
cuando se está aprendiendo son los pequeños
(generalmente 16V8, 22V8 ó 22V10), estos PLD's
están en la ventana como SPLD. Haz doble click
sobre este texto, te aparecerá una lista de los
SPLD's más comunes, selecciona el SPLD que te
interese y nuevamente aparecerá una lista donde
hay varios tipos del mismo SPLD, por ejemplo
PALCE16V8-10PC/PI. Esta parte es importante,
ya que debes de seleccionar un SPLD que tenga un
encapsulado de tipo PDIP, para que lo puedas
montar en tu protoboard. En la parte inferior
aparece información sobre el SPLD que te interese.
Cuando escojas el SPLD adecuado haz click en
Finalizar.
Elige File > Save As y en la opción de Guardar
en, selecciona el nombre de la carpeta que usaste
en el paso número 4 (c:\nuevo). Una vez que hayas
seleccionado el directorio, escribe el nombre de
archivo, se sugiere el nombre nuevo, con la
extensión .vhd, ya que de esta manera se especifica
un archivo que contiene un código en VHDL.
Luego de hacer esto, guarda tu archivo.
9. Cierra el archivo de texto.
10. Selecciona Project > Add Files, te aparecerá
una ventana que debe de tener tu archivo
nuevo.vhd , haz click en Add, y posteriormente en
OK.
Figura 4.6
Figura 4.5
IEC FRANCISCO JAVIER TORRES VALLE
11. Tu archivo de texto se ha convertido en un
archivo de VHDL y está dentro de tu proyecto,
todo lo que programes, será compilado en el
dispositivo que especificaste. En tu ventana de
proyecto (si no se encuentra abierta, la puedes
activar haciendo View > Project Window) debe de
aparecer un icono en forma de hoja que tiene el
nombre de tu proyecto. Haz click en esta hoja y te
debe de aparecer un archivo con la instrucción:
library ieee; solo que ahora la palabra library está
56
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
en color azul porque es una palabra reservada. Esto
demuestra que haz hecho correctamente el
procedimiento.
1. Una vez que se ha creado un nuevo proyecto
en Galaxy, dentro del menú Project selecciona
Compiler Options.
Figura 4.7
12. Si la configuración de colores es la normal,
notarás que todas las palabras reservadas se
muestran en color azul y los comentarios en color
rojo. Ahora ya puedes comenzar a hacer tu
descripción en VHDL.
4.2
SIMULACIÓN DE
PROYECTOS
Figura 4.8
2. Lo anterior abrirá la ventana de opciones de
compilación, dentro de esta se encuentra una
sección para elegir el formato de los retardos para
simular el circuito Simulation—Timing Model.
Aquí es donde debes de seleccionar el formato
1164/VHDL.
Active - HDL de la empresa Aldec Inc. es un
simulador que utiliza un archivo de post - síntesis
creado por WARP. Éste es un archivo .vhd con los
retardos de tiempo del código sintetizado en el
dispositivo seleccionado. Este tema tiene por
objetivo dar una pequeña introducción a este
simulador de VHDL en las siguientes tres
secciones.
1. Formato de simulación 1164/VHDL.
2. Simulación.
3. Tipos de señales de estimulación.
FORMATO DE SIMULACIÓN 1164/VHDL
El archivo de entrada para Active - HDL es un
modelo de simulación post - síntesis generado
cuando se compila un archivo .vhd en el
dispositivo elegido. En WARP es posible crear
archivos con diferentes formatos para simulación
post - síntesis. Active - HDL requiere de un archivo
con el formato de simulación IEEE - 1164 / VHDL.
Para crear este archivo post - síntesis debes
seguir el siguiente procedimiento.
IEC FRANCISCO JAVIER TORRES VALLE
Figura 4.9
3. Asegúrate que se encuentre habilitado el
cuadro de Enable Testbench Output.
4.2.1
PROCESO DE SIMULACIÓN
El proceso de simulación lo podemos resumir en
los siguientes siete pasos.
57
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
1. Cargar un archivo con el formato de
simulación 1164/VHDL.
2. Iniciación de la simulación.
3. Agregar señales.
4. Asignar señales de estimulación.
5. Correr la simulación.
6. Observación de la simulación.
7. Guarda la simulación.
1. - CARGA DEL ARCHIVO
El primer paso es abrir el programa Active-HDL
Sim que normalmente se encuentra en Menu Inicio
> Programas > Warp > Active-HDL Sim. Para
cargar el archivo selecciona Open Vhdl dentro del
Menú File.
2. - INICIACIÓN DE LA SIMULACIÓN
Para iniciar la simulación, activa el simulador
utilizando la opción Initialize Simulation, dentro
del menú Simulation. Después abre una ventana
para el análisis de señales Waveform Window, si es
que no se encontrara ya una abierta.. Para crear
una nueva ventana de este tipo, haz clic en el icono
dentro de la barra estándar de trabajo o selecciona
File > New Waveform..
3. - AGREGANDO SEÑALES
El siguiente paso es agregar señales a la ventana
de análisis, para esto selecciona Add Signals...en el
menú Waveform. La ventana para agregar señales
aparecerá con una lista de todas las señales de
entrada, salida, entrada/salida y nodos internos de
conexión disponibles en el diseño. Para agregar
alguna de las señales que se encuentran en esta
lista basta con hacer doble clic sobre el nombre de
la señal. Si deseas agregar varias señales al mismo
tiempo, puedes seleccionarlas mediante la tecla
control y haciendo clic sobre cada señal que deseas
agregar para después hacer clic sobre el botón Add
que se encuentra en la parte inferior de la ventana.
Figura 4.10
Es importante mencionar que el archivo con el
formato 1164/VHDL se crea en el subdirectorio
vhd dentro del directorio de trabajo del proyecto
una vez que éste es compilado. Si se selecciona por
accidente el archivo .vhd creado por el usuario, el
compilador del programa generará varios errores y
no podrá ser simulado. Una vez que el archivo
apropiado es cargado, se desplegarán una serie de
mensajes dentro de la ventana de compilación.
Uno de los mensaje que debería aparecer cuando el
archivo es compilado correctamente es el
siguiente:
Figura 4.11
4. - TIPOS DE SEÑALES DE ESTIMULACIÓN
Las señales de estimulación son utilizadas para
definir diferentes impulsos a los puertos de entrada
del diseño que esta siendo simulado. Para
seleccionar alguno de estos tipos primero
selecciona la señal y después selecciona Waveform
> Stimulators..., a continuación se describe
brevemente los diferentes tipos de señales de
estimulación de Active-HDL Sim.
-- Compile success 0 Errors 0 Warnings
Analysis time: 3.0 [s].
IEC FRANCISCO JAVIER TORRES VALLE
58
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
VALOR
Con este tipo de estimulador asignamos un valor
constante a la señal especificada.
HOTKEY
Con este estimulador podemos estar cambiando
el valor de la señal presionando una tecla. Cuando
asignamos este tipo de estimulador es conveniente
asignar una lista de valores. Cada que presionemos
la tecla asignada, estaremos cambiando entre los
valores de esta lista.
Figura 4.12
CLOCK
Sirve para definir señales de reloj definidas con
los siguientes parámetros: frecuencia, valor inicial,
ciclo de trabajo y tiempo de inicio.
CUSTOM
Un estimulador personalizado se crea editando
los valores deseados en la ventana de simulación.
Estado en el modo de edición, al estimulador de
entrada se le puede asignar un estado bajo o un
estado alto presionando '1' o '0' respectivamente.
FORMULA
Un estimulador del tipo formula produce una
señal definida por una simple sintaxis. La señal es
definida con secuencias pares de valor - tiempo.
Con la componente tiempo indicamos el momento
en el que la señal asume el valor especificado. La
unidad del tiempo es en picosegundos. Para repetir
durante un periodo especificado, se agrega el
modificador -r. La sintaxis del estimulador tipo
formula se muestra a continuación.
<valor> <tiempo> [,<valor> <tiempo>,
<valor> <tiempo>, ...] [ -r <periodo>]
Para una descripción más completa de las
características del simulador consulta la ayuda del
programa.
5. - CORRIENDO LA SIMULACIÓN
Para correr la simulación selecciona Simulation
> Run. La simulación se detendrá después que la
duración especificada haya sido terminada. En este
momento las señales de estimulación para los
puertos de entrada pueden ser alterados y
producirán efectos sobre la simulación cuando esta
continué. Para volver a iniciar la simulación
selecciona Simulation > Restart Simulation.
6. - OBSERVANDO LA SIMULACIÓN
Varias propiedades pueden ser manipuladas
para mejorar la apariencia de la simulación. A
continuación se describen brevemente algunas de
estas propiedades.
BUS
La líneas individuales que forman un bus
pueden ser mostradas y editadas. Para mostrarlas
haz clic sobre "+" que se encuentra a junto al
nombre el bus. Las señales de estimulación pueden
ser asignadas a cada línea del bus o al bus
completo.
COLOR
EJEMPLO
'0000' 0 ps, '1111' 100000 ps, '0011'
200000 ps -r 300000
PREDEFINIDOS
Los estimuladores predefinidos son una serie de
señales tipo clock con diferentes frecuencias o
señales del tipo formula que pueden ser asignados
a las señales. Para agregar un nuevo estimulador a
esta lista, lo puedes hacer en la misma ventana
dentro del cuadro Predefined.
IEC FRANCISCO JAVIER TORRES VALLE
Las señales de la simulación pueden ser de
diferentes colores para una mejor claridad cuando
varias señales son desplegadas. Para agregar color
a todas las señales visibles, selecciona Waveform >
Colorize Waveforms, esto asignará diferentes
colores, arbitrariamente a cada señal dentro de la
ventana de simulación. Para asignar color a cada
señal, haz clic con el boton derecho sobre el
nombre de la señal y selecciona la opción
Properties..
59
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
ZOOM
Para aumentar o reducir la escala de tiempo de
la simulación, selecciona View > Zoom >
In/Out/Full.
BOOKMARKS
Para colocar marcas sobre la ventana de
simulación primero selecciona Waveform > Select
Mode. Cuando este modo se encuentra
seleccionado, es posible colocar marcas sobre
diferentes puntos de la simulación para una rápida
referencia a ciertos puntos importantes de la
misma. Para colocarlas primero haz clic con el
botón izquierdo en donde deseas colocar una
marca, después selecciona Search > Toggle
Bookmark. Utilizando Next/Previous Bookmark
del mismo menú puedes cambiar entre una marca y
otra dentro de la simulación. Las marcas son
desplegadas como un triángulo azul sobre la escala
de tiempo en la ventana de simulación. Para
eliminar alguna marca selecciona Waveform > Edit
Mode y después haz clic con el botón izquierdo
sobre la marca que deseas eliminar.
ventas de simulación abiertas. La extensión de los
archivos de simulación en Active-HDL Sim es
.awf.
4.3
COMPARADORES
El objetivo de este tema es crear, sintetizar, y
simular la descripción de circuitos comparadores
de magnitud utilizando WARP.
PROCEDIMIENTO
1. Primero crearemos un proyecto para el
ejemplo del comparador visto en el tema 3.1.2
Antes que nada debemos crear el proyecto dentro
de un directorio en el que se encontrarán todos los
archivos del proyecto (.pfg, .vhd, .jed, .rpt, etc. ).
Se sugiere crear primero una carpeta para todos los
proyectos VHDL y dentro de esa carpeta crear otra
carpeta para el presente proyecto, por ejemplo
c:\vhdl_proj\comparador_1, con el nombre
comparador_1.
MODO DE MEDICIÓN
Para entrar al modo de medición selecciona
Waveform > Measurement Mode. En este modo es
posible desplegar el tiempo exacto entre dos
eventos de la simulación. Para obtener esta
información coloca el puntero sobre una transición
negativa o positiva, cuando el puntero es colocado
sobre alguna transición debe cambiar a color
verde, presiona el botón izquierdo sobre la
transición y arrastra el puntero hasta otra transición
de cualquier señal dentro de la ventana de
simulación y entonces suelta el botón. La medida
exacta entre estas dos transiciones se desplegara
como una etiqueta entre las dos transiciones. Si la
etiqueta no es mostrada o no se ve completa,
amplia el alto de la fila haciendo clic con el botón
derecho sobre alguna de las señales que
intervienen en la medición y después selecciona
Properties, dentro de la venta de propiedades
aumenta la altura modificando el valor del cuadro
de texto Height. Para eliminar alguna etiqueta de
medición selecciona Waveform > Edit Mode,
después seleciona la etiqueta y presiona suprimir
7. - GUARDANDO LA SIMULACIÓN
Existen dos formas de guardar la simulación.
Guardar solamente la simulación de la ventana
activa o guardar todas las simulaciones de las
IEC FRANCISCO JAVIER TORRES VALLE
Figura 4.13
2. Seleccionaremos un 22V10 con empaquetado
tipo DIP para sintetizar el código.
3. Ahora creamos un nuevo archivo de texto
para editar el código (File > New > Text File).
Este archivo debe ser guardado con extensión .vhd
y en la misma carpeta del proyecto. Se sugiere
guardarlo como:
c:\vhdl_proj\comparador_1\comparador1.vhd
4. A continuación se muestra la tabla de
funcionamiento de este comparador y basándose
en ella haremos el código de descripción en
VHDL. Primero utilizaremos el estilo de
60
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
descripción de flujo de datos, que es el mismo que
se utilizó cuando se expuso el ejemplo en el tema
3.1.2.
TABLA DE FUNCIONAMIENTO
ENTRADAS
SALIDAS
x<y
x_men_y
'1'
x<y
equals
'0'
x<y
x_may_y
'0'
x=y
x_men_y
'0'
x=y
equals
'1'
x=y
x_may_y
'0'
x>y
x_men_y
'0'
x>y
equals
'0'
x>y
x_may_y
'1'
a agregarlo al presente proyecto. Para agregarlo lo
hacemos desde el menú Project y dentro de éste
hacemos clic en Add Files... (Project > Add
Files...). Una vez que aparece la ventana para
agregar archivos al proyecto, seleccionamos el
archivo comprador_1.vhd y presionamos el botón
"Add".
Si por error hacemos clic en la opción Add All
Files, todos los archivos .vhd dentro de la carpeta
del proyecto se agregaran al mismo. En este caso
el único archivo .vhd que debería estar dentro de la
carpeta del proyecto es comparador_1.vhd, lo cual
en esta ocasión no nos afectará. En caso de que
hubiera más de un archivo .vhd y no deseamos
tenerlo dentro del proyecto basta con seleccionarlo
en la ventana de proyecto y presionar la tecla
suprimir, o también desde Project > Remove
Selected Source File(s). Si la ventana de proyecto
no está visible entonces seleccionamos View >
Reset Docking Windows.
5. Abajo se muestra el listado del comparador
correspondiente al estilo de descripción de flujo de
datos. Este listado debemos editarlo dentro del
archivo comparador_1.vhd.
ENTITY comparador IS
PORT ( x: IN bit_vector(3 DOWNTO 0);
y: IN bit_vector(3 DOWNTO 0);
x_may_y: OUT bit;
equals: OUT bit;
x_men_y: OUT bit
);
END comparador;
ARCHITECTURE 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 comparador;
6. Como se puede observar no se cargó ninguna
librería, y no es necesario hacerlo porque el tipo bit
es un tipo predefinido en WARP y en muchos
otros sintetizadores de VHDL. Por esto no
necesitamos de ninguna librería para poder
utilizarlo.
Además, recuerde que la última
declaración de puertos no lleva ;
Una vez que se terminó de editar el código,
procedemos a guardar los cambios en el archivo y
IEC FRANCISCO JAVIER TORRES VALLE
Figura 4.14
7. Una vez editado y agregado el archivo al
proyecto se procede a sintetizar el código en el
22V10. Seleccionamos Compile > Project o
también lo podemos hacer presionado el icono de
compilación.
Figura 4.15
Si el archivo tiene errores, estos aparecerán en
la ventana de salida (Output Window). Dentro de
"Errors & Warnings" en la ventana de salida se
61
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
muestra una lista completa de los errores así como
una descripción de cada error. Para acceder
rápidamente a la línea en la cual ocurrió el error,
basta con hacer doble clic sobre el error e
inmediatamente el programa se colocará sobre la
línea en donde se encuentra dicho error. Los
errores pueden ser algunos de los siguientes: omitir
algún punto y coma, no escribir correctamente
algún identificador, sintaxis incorrecta de las
instrucciones utilizadas, o uso incorrecto de los
operadores. Recordemos que VHDL es un
lenguaje en el que los tipos de datos son
sumamente importantes y no se pueden mezclar a
menos que se utilicen las librerías adecuadas.
8. La ventana de proyecto tiene 3 modos o
vistas: "Source Files View", "Hierarchy View", y
"Output Files View". En la primera se muestran los
archivos que se han agregado al proyecto. La
"Vista de Jerarquía" es útil cuando se hacen
diseños jerárquicos, ya que en esta se muestra cual
es el orden de importancia que hay entre ellos.
Dentro de la "Vista de Archivos de Salida"
aparecen los archivos que se generaron durante la
compilación, los cuales fueron creados dentro de la
carpeta del proyecto. Tales archivos de salida son:
.jed, .rpt y un .vhd que se encuentra dentro de la
carpeta "vhd" que está en la misma carpeta del
proyecto (ver tema 4.2).
las ecuaciones que resultaron durante el proceso de
síntesis, la asignación de pines, y un informe de
utilización del dispositivo. En ocasiones es
complicado realizar algunas descripciones y,
aunque el código se sintetiza, durante la
simulación hace algo diferente a lo que
esperábamos. La función del sintetizador, en este
caso WARP, es la de interpretar nuestra
descripción en VHDL para generar la lógica de
salida. En estos casos posiblemente la descripción
no corresponde exactamente a lo que queremos.
Para corregir la descripción es útil consultar las
ecuaciones, ya que en estas nos podemos dar
cuenta que es lo que estamos describiendo
realmente. En temas posteriores se presentan
algunos ejemplos en los que se exponen con más
detalle este tipo de problemas.
SIMULACIÓN
9. Ahora que ya hemos logrado sintetizar el
código y obtenido los archivos .jed y .vhd de
postsíntesis procedemos a simular la descripción.
Las simulaciones las haremos en Active-HDL Sim
como se explicó en tema 4.2. Podemos abrir el
programa desde Galaxy desde Tools > Active-HDL
Sim.
Figura 4.17
10. Una vez iniciado el simulador, ahora
abrimos el archivo .vhd de postsíntesis como se
explica a continuación. Primero seleccionamos
File > Open VHDL.
Figura 4.16
En el archivo .rpt se muestra un informe de los
resultados de la compilación. En éste se encuentran
IEC FRANCISCO JAVIER TORRES VALLE
62
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
Figura 4.18
Para después abrir el archivo .vhd de
postsíntesis, el cual debería estar (si seguiste
correctamente todos los pasos) en el subdirectorio:
c:\vhdl_proj\comparador_1\vhd\comparador1.
vhd
7 us, 1000 8 us, 1001 9 us, 1010 10 us,
1011 11 us, 1100 12 us, 1101 13 us, 1110
14 us, 1111 15 us -r 16 us
Y al bus "y" también le asignaremos un
estimulador del mismo tipo con la siguiente
formula.
0000 0 ns, 1111 1 us, 1110 2 us, 1101 3
us, 1100 4 us, 1011 5 us, 1010 6 us, 1001
7 us, 1000 8 us, 0111 9 us, 0110 10 us,
0101 11 us, 0100 12 us, 0011 13 us, 0010
14 us, 0001 15 us -r 16 us
13. Una vez que asignamos los estimuladores
iniciamos la simulación seleccionando: Simulation
> Initialize Simulation.
Figura 4.19
11. Hecho lo anterior ahora agregamos las
señales y/o puertos que deseamos simular.
Seleccionamos Waveform > Add Signals...
14. Una vez iniciada la simulación ahora
corremos la simulación. Para poder correrla
existen tres opciones: correr completamente la
simulación (el máximo es de 2ms+3), correrla y
que se detenga en un momento especifico, o
adelantar la simulación solamente por algún
tiempo. Para correr la simulación completamente
seleccionamos Simulation > Run. Si queremos
correr la simulación y especificar un tiempo en el
que debe detenerse seleccionamos Simulation >
Run Until... . Para correr la simulación "por pasos"
o por tiempos especificados, seleccionamos
Simulation > Run For. El tiempo de paso se
especifica a un lado del icono de Run For. Esta
última opción es la más practica al momento de
simular descripciones.
Figura 4.21
Figura 4.20
Ahora seleccionamos los puertos como se
explicó en el tema 4.2. En este ejercicio
seleccionaremos solamente los puertos declarados
en la entidad, tal y como se muestra en la figura
4.22
12. Lo siguiente es asignar señales de estimulo a
los puertos de entrada. Al bus "x" le asignaremos
un estimulador tipo formula usando la siguiente
formula.
0000 0 ns, 0001 1 us, 0010 2 us, 0011 3
us, 0100 4 us, 0101 5 us, 0110 6 us, 0111
IEC FRANCISCO JAVIER TORRES VALLE
Si deseas utilizar Run For cerciórate que el
tiempo de "paso" sea de 1 us. Ya que cuando
asignamos los estimuladores el valor de los buses
de entrada cambia cada 1 us. Si deseas utilizar Run
Until... bastara con especificar un tiempo de 32 us
para observar como se comporta el ciclo de
asignaciones que especificamos mediante la
formula, el tiempo mínimo para comprobar todos
los valores (por lo menos un ciclo) es de 16 us.
15. A continuación en la figura 4.23 se muestran
los resultados de la simulación. Si seguiste
correctamente todos los pasos deberías obtener
algo similar a lo mostrado en la siguiente figura.
63
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
Figura 4.22
Figura 4.23
Figura 4.24
IEC FRANCISCO JAVIER TORRES VALLE
64
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
4.4
00
a
01
b
10
c
descripción de circuitos digitales utilizando
WARP. De esta librería se llamó el paquete
std_arith, el cual contiene muchas funciones que
facilitan el uso de vectores tipo std_logic con
enteros. De no haber utilizado este paquete no
podríamos hacer ninguna de la comparaciones que
están en la asignación condicional WHEN... ELSE.
Es decir, no es posible hacer la comparación "selec
= 3" porque "selec" es del tipo std_logic_vector y
"3" es un número entero. El paquete
std_logic_1164 contiene los tipos de datos
std_logic y std_logic_vector que comúnmente
utilizamos por lo que es necesario cargar el
paquete para poder utilizar estos tipos, sin
embargo, no contiene funciones de comparación
entre tipos std_logic (o arreglos de este) y enteros.
Como la librería es de propia del sintetizador, es
decir, que siempre esta cargada dentro del área de
trabajo del proyecto o "work", podemos llamar el
paquete como se muestra a continuación.
11
d
USE work.std_arith.ALL;
MULTIPLEXORES
En este tema el objetivo es elaborar
descripciones de circuitos multiplexores utilizando
los tres estilos de descripción de VHDL.
PROCEDIMIENTO
Para la síntesis utilizaremos un 22V10 siguiendo
la siguiente tabla de funcionamiento en los tres
estilos de descripción.
TABLA DE FUNCIONAMIENTO
selec salida
SIMULACIÓN
4.4.1
DESCRIPCIÓN DE FLUJO DE DATOS
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY cypress;
USE cypress.std_arith.ALL ;
ENTITY multiplexor IS
PORT(a, b, c, d: IN std_logic_vector
(3 DOWNTO 0);
selec: IN std_logic_vector
(1 DOWNTO 0);
salida: OUT std_logic_vector
(3 DOWNTO 0));
END multiplexor;
Para la simulación se sugiere que asignes un
estimulador tipo formula a los vectores de entrada,
y al vector "selec" le asignes un estimulador tipo
"HOTKEY". Una vez que agregaste las señales a
la simulación, selecciona con el puntero el vector
"selec", después seleccionas Waveform >
Stimulators..., cuando aparezca el cuadro de
estimuladores selecciona "HOTKEY" dentro de
"Stimulator type", y en "Press new hotkey" escribe
la letra "s" o cualquier otra.
ARCHITECTURE data_flow OF multiplexor IS
BEGIN
salida <= a WHEN selec = 0 ELSE
b WHEN selec = 1 ELSE
c WHEN selec = 2 ELSE
d WHEN selec = 3 ;
END data_flow;
El listado anterior corresponde a un multiplexor
4 a 1. El bus de salida es seleccionado mediante las
señales de selección selec(1) y selec(0)
(std_logic_vector es un arreglo de datos del tipo
std_logic). Como habrás notado se hizo el llamado
a una librería no mencionada anteriormente, la
librería "cypress". Esta librería es de Cypress
Semiconductors y fue desarrollada para facilitar la
IEC FRANCISCO JAVIER TORRES VALLE
Figura 4.25
Cada que presiones la tecla "s" el vector s estará
cambiando de valor, por omisión la lista de valores
de asignación incluye el '0' y el '1' solamente, en
65
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
este caso necesitamos generar valores para un
vector de 2 bits. Para poder hacerlo, en el mismo
cuadro de dialogo cámbiate a la sección de
"Hotkeys". En esta parte aparecerán las teclas que
ya han sido asignadas dentro del archivo para ser
utilizadas como estimuladores, así como la lista de
valores de asignación de cada tecla. Para modificar
la lista de valores de la tecla "s" (la que estamos
utilizando), con el puntero colócate en el cuadro de
secuencia y escribe la nueva lista de valores.
4.4.2
DESCRIPCIÓN COMPORTAMENTAL
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.std_arith.ALL;
Figura 4.26
Ahora puedes correr la simulación poco a poco
utilizando Simulation > Run For, o presionando la
tecla "F5". Y cada que lo desees presionas la tecla
"s" para cambiar el valor del vector "selec". En la
figura 4.24 se muestran los resultados de la
simulación.
A continuación se muestran las ecuaciones
obtenidas utilizando el estilo de descripción de
flujo de datos. Estas ecuaciones deben ser las
mismas para cualquier estilo que utilicemos, ya
que estamos describiendo el mismo multiplexor
sólo que de manera diferente y esto no implica que
las ecuaciones vayan a ser distintas. Cuando
compiles este multiplexor, en cualquiera de los tres
estilos, consulta las ecuaciones dentro del archivo
.rpt y verifica que sean iguales.
IEC FRANCISCO JAVIER TORRES VALLE
ENTITY multiplexor IS
PORT(a: std_logic_vector
(3 DOWNTO 0);
b: std_logic_vector
(3 DOWNTO 0);
c: std_logic_vector
(3 DOWNTO 0);
d: std_logic_vector
(3 DOWNTO 0);
selec: std_logic_vector
(1 DOWNTO 0);
salida: OUT std_logic_vector
(3 DOWNTO 0));
END multiplexor;
ARCHITECTURE behavorial OF multiplexor IS
BEGIN
PROCESS(selec, a, b, c, d)
VARIABLE selec_int: integer;
BEGIN
selec_int := to_integer(selec);
CASE selec_int IS
WHEN 0 =>
salida <= a ;
WHEN 1 =>
salida <= b ;
WHEN 2 =>
salida <= c ;
WHEN 3 =>
salida <= d ;
WHEN OTHERS =>
NULL;
END CASE;
END PROCESS;
END behavorial;
66
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
Dentro del proceso se hace uso de un objeto de
datos del tipo variable declarado como entero. Al
inicio del proceso se hace la asignación "selec_int
<= to_integer ( selec ) ;", esto es para poder usar
enteros en la instrucción CASE, de otra manera
tendríamos que indicar todos los casos utilizando
los valores naturales de un vector, es decir, "00",
"01", "10", y "11" para este ejemplo. Esto es
solamente para facilitar la descripción y no
significa que obtengamos una mejor síntesis del
código en el dispositivo. Es necesario que
"selec_int" sea una variable para que se le asigne
inmediatamente el valor actual del vector "selec" y
estemos describiendo el correctamente el
funcionamiento del multiplexor. Si quisiéramos
utilizar una señal en vez de una variable tenemos
que hacerlo de la siguiente manera.
ARCHITECTURE behavorial2 OF multiplexor IS
SIGNAL selec_int:integer;
BEGIN
selec_int <= to_integer( selec );
PROCESS(selec_int, a, b, c, d)
BEGIN
CASE selec_int IS
WHEN 0 =>
salida <= a ;
WHEN 1 =>
salida <= b ;
WHEN 2 =>
salida <= c ;
WHEN 3 =>
salida <= d ;
WHEN OTHERS =>
NULL;
END CASE;
END PROCESS;
END behavorial2;
Si observas con cuidado podrás ver que
seguimos describiendo exactamente los mismo.
Tanto el procesos como la asignación son de
naturaleza concurrente, por lo que selec_int tiene
siempre el valor actual de selec y lo convertimos a
un tipo entero para facilitar la descripción. Trata de
imaginar la asignación "selec_int <= to_integer (
selec )" como un circuito combinacional cuya
función es cambiar el tipo de datos con el estamos
manejando el vector selec y cuya salida (selec_int)
se la conectamos (piensa en señales como cables)
al proceso, que viene siendo otro circuito que
"procesa" la información que se le suministra y
obtiene finalmente la lógica de salida. A
continuación se muestra un diagrama a bloques
que trata de representar lo que estamos haciendo
en la arquitectura anterior (behavorial2).
IEC FRANCISCO JAVIER TORRES VALLE
Figura 4.27
4.4.3
DESCRIPCIÓN ESTRUCTURAL
Para la descripción estructural primero debemos
realizar la descripción de un multiplexor 2 a 1 para
después interconectar tres de ello como se muestra
en la figura siguiente.
Figura 4.28
Para realizar descripciones estructurales lo
recomendable es utilizar varios archivos .vhd, cada
uno para una entidad o paquete en particular. Crea
un proyecto para la descripción estructural del
multiplexor 4 a 1. Ahora crea un nuevo archivo de
texto y copia la siguiente descripción.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
PACKAGE multiplexor IS
COMPONENT mux_2_a_1
PORT( in1: IN std_logic_vector
(3 DOWNTO 0);
in2: IN std_logic_vector
(3 DOWNTO 0);
sel: IN std_logic;
out1: OUT std_logic_vector
(3 DOWNTO 0));
67
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
END COMPONENT;
END multiplexor;
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
funcionamiento. Dentro de la ventana de proyecto
en la "vista de jerarquía" (Hierarchy View) aparece
el orden en que los componentes están siendo
utilizados dentro del diseño jerárquico.
ENTITY mux_2_a_1 IS
PORT (in1, in2: IN std_logic_vector
(3 DOWNTO 0);
sel: IN std_logic;
out1: OUT std_logic_vector
(3 DOWNTO 0));
END mux_2_a_1;
ARCHITECTURE data_flow OF mux_2_a_1 IS
BEGIN
out1 <= in1 WHEN sel = '0' ELSE
in2;
END data_flow;
Guarda este archivo como mux_2_a_1.vhd
dentro de la carpeta de trabajo del proyecto. Como
podrás ver estamos creando un paquete con
nombre "multiplexor" el cual se agrega a la librería
del proyecto work. Además se tienen que llamar
las librerías que se necesiten antes del paquete y
antes de la entidad. Ahora abre un nuevo archivo
de texto y copia en él la siguiente descripción.
-- mux_structural.vhd
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.multiplexor.ALL;
-- llamado al paquete multiplexor que se
-- encuentra en la librería
-- del proyecto
ENTITY multiplexor IS
PORT ( a,b,c,d: IN std_logic_vector
(3 DOWNTO 0);
selec: IN std_logic_vector
(3 DOWNTO 0);
salida: OUT std_logic_vector
(3 DOWNTO 0));
END multiplexor;
ARCHITECTURE structural OF multiplexor IS
SIGNAL salida1, salida2:
std_logic_vector(3 DOWNTO 0);
BEGIN
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 structural;
Guarda este archivo como mux_structural.vhd,
y agrega ambos archivos al proyecto (Proyect >
Add Files...). Compila el proyecto y comprueba
que las ecuaciones de salida siguen siendo las
mismas ya que estamos describiendo el mismo
IEC FRANCISCO JAVIER TORRES VALLE
Figura 4.29
Una vez que has compilado y simulado este
multiplexor utilizando los tres estilos podrás ver
que no hay ninguna diferencia entre usar un estilo
u otro. Lo importante es describir el mismo
funcionamiento para obtener los mismo resultados.
De hecho, mientras estemos describiendo
exactamente lo mismo no importa el número de
líneas que se hagan, porque VHDL no es un
lenguaje de programación de software.
4.5
SUMADORES
El diseño de circuitos aritméticos eficientes es
un tema fundamental en el diseño de circuitos
digitales, por lo que es importante para el
diseñador estar familiarizado con las opciones
disponibles en la selección de algoritmos eficientes
en sus aplicaciones. Está práctica tiene por
objetivo familiarizarte en el diseño de circuitos
sumadores utilizando algoritmos eficientes en
VHDL.
4.5.1
SUMADOR TOTAL
El componente básico usado en la adición de
dos operandos es conocido como "sumador total".
Este sumador total representa el componente con
el cual podemos formar sumadores de cualquier
número de bits. A continuación se muestra la tabla
de funcionamiento y la representación esquemática
de un sumador total, y basándose en la tabla se
hará la descripción de sumador total en VHDL,
para posteriormente diseñar un circuito sumador de
4 bits utilizando un 22V10.
68
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
"10" WHEN entradas = 5 ELSE
"10" WHEN entradas = 6 ELSE
"11" WHEN entradas = 7;
sum <= salidas(0);
co <= salidas(1) ;
END data_flow;
Si conoces las ecuaciones del circuito también
puedes utilizarlas para hacer la descripción.
Figura 4.30
TABLA DE FUNCIONAMIENTO
ENTRADAS
a
b
0
0
0
0
0
1
0
1
1
0
1
0
1
1
1
1
ci
0
1
0
1
0
1
0
1
SALIDAS
co
suma
0
0
0
1
0
1
1
0
0
1
1
0
1
0
1
1
LIBRARY ieee; -- full_adder.vhd
USE ieee.std_logic_1164.ALL;
PACKAGE adder IS
COMPONENT full_adder
PORT(ci: IN std_logic;
a, b: IN std_logic;
sum: OUT std_logic;
co: OUT std_logic);
END COMPONENT;
END adder;
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.std_arith.ALL;
ARCHITECTURE data_flow OF full_adder IS
BEGIN
sum <= a XOR b XOR C;
co <= (a AND b) OR
(a AND ci) OR
(b AND ci);
END data_flow;
Crea un nuevo proyecto en c:\vhdl_proj\prac5\
y llámalo sumador. Después crea un nuevo archivo
de texto y copia en él la descripción anterior.
Guarda el archivo de texto como full_adder.vhd
dentro de la carpeta de trabajo del proyecto.
Agrega el archivo al proyecto y compila el
proyecto utilizando la arquitectura data_flow. Abre
el reporte de compilación y observa las ecuaciones.
Ahora compila el proyecto utilizando la segunda
arquitectura data_flow. Vuele a abrir el proyecto y
observa las ecuaciones. ¿Por qué son las mismas
ecuaciones? porque estamos describiendo el
mismo funcionamiento y el estilo o el número de
líneas que utilices no importa siempre y cuando
este describiendo exactamente el mismo circuito.
4.5.2
SUMADOR DE CUATRO BITS
Para hacer la descripción utilizaremos cuatro
unidades del sumador total (u1 a u4) y las
conectaremos como se muestra continuación.
ENTITY full_adder IS
PORT(ci: IN std_logic;
a, b: IN std_logic;
sum: OUT std_logic;
co: OUT std_logic);
END full_adder;
ARCHITECTURE data_flow OF full_adder IS
SIGNAL entradas: std_logic_vector
(2 DOWNTO 0);
SIGNAL salidas: std_logic_vector
(1 DOWNTO 0);
BEGIN
entradas <= a&b&ci ;
salidas <= "00" WHEN entradas = 0 ELSE
"01" WHEN entradas = 1 ELSE
"01" WHEN entradas = 2 ELSE
"10" WHEN entradas = 3 ELSE
"01" WHEN entradas = 4 ELSE
IEC FRANCISCO JAVIER TORRES VALLE
Figura 4.31
Abre un nuevo archivo de texto y copia en él la
siguiente descripción.
-- sumador de 4 bits utilizando
-- un sumador total
69
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.std_arith.ALL;
USE work.adder.ALL;
ENTITY sumador IS
PORT (ci: IN std_logic;
a, b: IN std_logic_vector
(3 DOWNTO 0);
sum: OUT std_logic_vector
(3 DOWNTO 0);
co: OUT std_logic);
END sumador;
ARCHITECTURE structural OF sumador IS
SIGNAL c1, c2, c3: std_logic;
BEGIN
u1: full_adder PORT MAP (ci, a(0), b(0),
sum(0), c1 ) ;
u2: full_adder PORT MAP (c1, a(1), b(1),
sum(1), c2 ) ;
u3: full_adder PORT MAP (c2, a(2), b(2),
sum(2), c3);
u4: full_adder PORT MAP (c3, a(3), b(3),
sum(3), co);
END structural;
Guarda el archivo de texto en la carpeta de
trabajo del proyecto (c:\vhdl_proj\prac5) como
sumador.vhd. Compila el proyecto y observa lo
que sucede. Si estas usando la versión 5.0 o 5.2 de
WARP, la compilación te indicará los siguientes
errores.
Error: Logic equation has too many product
terms on signal co.
Error: Logic equation has too many product
terms on signal sum(2).
Error: Logic equation has too many product
terms on signal sum(3).
Abre el reporte de compilación y observa las
ecuaciones. La descripción no se pudo compilar
porque las ecuaciones tienen demasiadas sumas de
productos. El sintetizador de WARP siempre trata
de evitar retroalimentaciones para que el circuito
funcione con la mayor velocidad posible. Nosotros
deseamos que los nodos c1, c2, y c3 queden en un
pin de salida del 22V10 para de esta forma hacer
las conexiones como se muestran en el diagrama a
bloques del sumador de 4 bits. Para lograrlo basta
con describir la entidad como se muestra a
continuación.
ENTITY sumador IS
PORT ( ci: IN std_logic;
a, b: IN std_logic_vector
(3 DOWNTO 0);
sum: OUT std_logic_vector
(3 DOWNTO 0);
IEC FRANCISCO JAVIER TORRES VALLE
co, c1, c2, c3: INOUT std_logic);
END sumador;
De esta forma enviamos los nodos c1, c2, y c3 a
la salida de una macroceldas, en el caso del 22V10
a un pin de salida, y así evitamos que el
sintetizador elimine el nodo porque ya lo
declaramos como puerto.
4.5.3
SYNTHESIS OFF
Otra forma de evitar que se simplifique el nodo
es utilizando directivas de síntesis. En este caso
utilizaremos la directiva synthesis_off que está
incluida en WARP. Esta directiva nos permite
controlar la forma en que el sintetizador factoriza y
obtiene las ecuaciones de salida y de esta manera
evitar que la ecuación de un nodo se incluya en la
ecuación de otro nodo y así evitar
retroalimentaciones. Para entender como funciona
esta directiva observe el siguiente ejemplo.
ENTITY synthesis_off IS
PORT ( a, b, c: IN bit;
y: OUT bit);
END synthesis_off;
ARCHITECTURE simplifica_nodo OF
synthesis_off IS
SIGNAL x: bit;
BEGIN
x <= a AND b;
y <= x OR c;
END simplifica_nodo;
Cuando compilemos el archivo la ecuación del
nodo "x" se sustituye en la ecuación del puerto "y"
como se muestra abajo.
y = a * b + c
Lo que trataríamos de hacer entonces sería
declara el nodo "x" como puerto y no como señal
de interconexión, pero observa que es lo que
sucede.
x = a * b
y = a * b + c
La ecuación de "x" se sigue sustituyendo en la
ecuación del puerto "y". Como habíamos
mencionado, el sintetizador siempre busca que el
circuito que le estamos describiendo funcione a la
mayor frecuencia posible. Al obtener las
ecuaciones de la forma anterior evitamos que
exista una retroalimentación desde el pin del
puerto "x", ya que si retroalimentamos tenemos
que esperar el tiempo de retardo de las compuertas
70
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
que intervienen en las ecuaciones de "x" para que
después el valor de "x" se incorpore a las
ecuaciones del puerto "y". Por lo que el tiempo de
retardo para el puerto "y" sería mayor. Sin
embargo, aunque lo mejor es que nuestro circuito
funcione a mayor velocidad, en ocasiones
necesitamos que el nodo quede en una macrocelda
para que después se retroalimente hacia otras
ecuaciones. Ya sea por que lo necesitamos en el
diseño del circuito o por las limitaciones del
dispositivo programable. Es aquí donde las
directivas de síntesis nos permiten controlar el
proceso de síntesis. Observa el siguiente ejemplo
en el que se muestra como utilizar la directiva
synthesis_off.
ENTITY synthesis_off IS
PORT ( a, b, c: IN bit;
y: OUT bit);
END synthesis_off;
ARCHITECTURE no_simplifica_nodo OF
synthesis_off IS
SIGNAL x: bit;
ATTRIBUTE synthesis_off OF x: SIGNAL IS
true;
BEGIN
x <= a AND b;
y <= x OR c;
END no_simplifica_nodo;
Las ecuaciones que resultan del proceso de
síntesis son las siguientes.
/y = /c * /x
x = a * b
Ahora las ecuaciones tienen menos términos y
obligamos a que el nodo "x" quede en una
terminal, obligándolo a quedar en una macrocelda
para que después se retroalimente. Para el circuito
sumador de cuatro bits podemos utilizar esta
directiva de la siguiente forma.
ARCHITECTURE structural OF sumador IS
SIGNAL c1, c2, c3: std_logic;
ATTRIBUTE synthesis_off OF c1, c2, c3:
SIGNAL IS true;
BEGIN
u1: full_adder PORT MAP (ci, a(0), b(0),
sum(0), c1 ) ;
u2: full_adder PORT MAP (c1, a(1), b(1),
sum(1), c2 ) ;
u3: full_adder PORT MAP (c2, a(2), b(2),
sum(2), c3);
u4: full_adder PORT MAP (c3, a(3), b(3),
sum(3), co);
END structural;
IEC FRANCISCO JAVIER TORRES VALLE
Esta directiva sólo puede ser aplicada a señales,
para una explicación más detallada de esta y otras
directivas de síntesis consulta la ayuda del
programa (Help > Help Topics). Para diseño de
circuitos aritméticos y no aritméticos que sean
grandes o complejos, lo mejor es hacer
descripciones estructurales y utilizar las directivas
de síntesis cuando sea necesario.
4.6
REGISTROS
Existen dos métodos para implementar lógica
registrada en VHDL: mediante instanciación de
registros (utilizando librerías de componentes) o
utilizando procesos para realizar la descripción
comportamental del registro.
Por ejemplo, si se desea utilizar un registro D y
un contador de 4 bits, basta con realizar la
instanciación de dichos componentes después de
incluir los paquetes apropiados.
EJEMPLO
USE work.rtlpkg.ALL; -- paquetes de WARP
USE work.lpmpkg.ALL;
. . .
-- DSRFF: definido en rtlpkg
d1: dsrff PORT MAP(d, s, r, clk, q ;
-- Mcounter: definido en lpmpkg
c1: Mcounter GENERIC MAP (4)
PORT MAP (data, clk, one,
one, one, count, zero, rst,
zero, zero, zero, zero zero,
zero, OPEN);
Otra forma de registrar elementos es incluir un
proceso que sea sensible a las transiciones de una
señal de reloj o que espere una transición de reloj
utilizando la instrucción WAIT, de esta manera el
compilador asigna un registro a las señales
afectadas dentro del proceso. Existen 4 formas
básicas para describir registros, cada una de ellas
se explica a continuación.
PROCESS
BEGIN
WAIT UNTIL clk = '1';
. . .
END PROCESS;
Este proceso no tiene lista sensible, por lo que
comienza con una instrucción WAIT. Las
instrucciones dentro del proceso se comenzarán a
ejecutar cuando exista una transición positiva de la
71
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
señal de reloj "clk". Todas las asignaciones a
señales dentro del proceso serán registradas, ya
que estas sólo cambian de valor en las transiciones
de reloj y lo retienen por lo menos hasta la
siguiente transición.
PROCESS (clk)
BEGIN
IF ( clk'event AND clk ='1' ) THEN
. . .
END IF;
END PROCESS;
Este proceso es sensible solamente a los
cambios en la señal "clk", como se indica en la
lista sensible. La primera instrucción, IF... THEN,
dentro del proceso restringe al resto de las
instrucciones a ser ejecutadas únicamente durante
la transición positiva de la señal "clk", por lo que
ahora también todas las señales que reciban una
asignación dentro de la instrucción IF... THEN
serán registradas y mantendrán dicho valor
recibido por lo menos hasta la siguiente transición
de reloj.
PROCESS(rst, clk)
BEGIN
IF rst = '1' THEN
. . .
ELSIF(clk'event AND clk='1') THEN
. . .
END IF;
END PROCESS;
Este proceso es sensible a los cambios en la
señal de reloj "clk" y la señal de reinicio "rst",
como es indicado en la lista sensible. Mediante
este método de descripción comportamental es
posible registrar señales y además tener un "reset"
asíncrono. La primera instrucción checa primero el
estado de la señal "rst". Las señales que son
asignadas dentro de esta porción de la estructura
IF... THEN... ELSIF, se asume que son registradas
asíncronamente con la señal de "reset" asignada, y
serán sintetizadas en registros con capacidad para
realizar dicha acción. Si la condición de "reset" no
se cumple, el resto de la instrucción IF... THEN...
ELSIF, funciona como el proceso explicado
anteriormente.
PROCESS(rst, pst, clk)
BEGIN
IF rst = '1' THEN
. . .
ELSIF pst = '1' THEN
. . .
ELSIF (clk'event AND clk='1') THEN
IEC FRANCISCO JAVIER TORRES VALLE
. . .
END IF;
END PROCESS;
Este proceso es sensible a los cambios en la
señales "clk", "rst" y "pst", como se indica en la
lista sensible. De esta forma es posible realizar la
descripción de registros con "preset" y "reset"
asíncronos. La primera instrucción dentro del
proceso checa el estado de la señal "rst". Todas las
señales que son asignadas dentro de la primera
porción de la estructura, se asume que serán
registradas mediante la señal de "rst" asíncrono. La
segunda condición checa el estado de la señal
"pst", y todas las señales que sean asignadas dentro
de esta porción del proceso son registradas
asíncronamente mediante la señal de "preset"
asíncrono "pst". Si las dos primeras condiciones no
se cumplen, el resto de la instrucción IF... THEN...
ELSIF, representa el funcionamiento síncrono del
registro.
EJEMPLO
A continuación se muestra una forma de realizar
la descripción de un registro de 32 bits con "reset"
asíncrono.
PROCESS(r, clk2)
BEGIN
IF (r = '1') THEN
q <= x"123DEABC" ;
ELSIF (clk2'event AND clk2='1') THEN
q <= d;
END IF;
END PROCESS;
Asumiendo que "q" y "d" son declarados como
señales o puertos de 32 bits, entonces este código
ejemplifica la implementación de un registro de 32
bits con d(i) como entrada, q(i) como salida, "clk2"
como la señal de reloj, y "r" como la señal de
"reset" asíncrono para algunos registros y también
como señal de "preset" asíncrono para otros. Esto
significa que cuando se cumple la condición: r =
'1', la asignación q <= x"ABC123DE" provocará
que algunos registros sean puestos en alto mientras
que otros van a quedar en un estado de cero lógico.
EJEMPLOS
A continuación realice la descripción de los
siguientes registros de acuerdo con su tabla de
funcionamiento.
72
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
REGISTRO NO. 1
Elabore la descripción del registro utilizando un
22V10 y posteriormente trate de implementar la
descripción en un 16V8, simule la descripción y
obtenga sus conclusiones.
TABLA DE FUNCIONAMIENTO
ENTRADAS
reset d
SALIDAS
clk
q
1
0 transición positiva
0
1
1 transición positiva
1
0
-
0
-
ENTITY reg1 IS
PORT(reset: IN bit;
d: IN bit;
clk: IN bit;
q: OUT bit);
END reg1;
ARCHITECTURE areg2 OF reg2 IS
BEGIN
PROCESS(clk, reset, d)
BEGIN
IF clk'event AND clk = '1' THEN
IF reset = '0' THEN
q <= '0';
ELSE
q <= d;
END IF;
END IF;
END PROCESS;
END areg2;
REGISTRO NO. 3
Elabore la descripción del siguiente registro
utilizando un 22V10, simule la descripción y
obtenga sus conclusiones.
TABLA DE FUNCIONAMIENTO
ENTRADAS
enable d
ARCHITECTURE areg OF reg1 IS
BEGIN
PROCESS(clk, reset, d)
BEGIN
IF reset = '0' THEN
q <= '0';
ELSIF clk'event AND clk = '1' THEN
q <= d;
END IF;
END PROCESS;
END areg;
REGISTRO NO. 2
Elabore la descripción del registro utilizando un
22V10 y posteriormente utilice un 16V8, simule la
descripción en ambos casos y obtenga sus
conclusiones.
SALIDAS
clk
q
1
0 transición positiva
0
1
1 transición positiva
1
0
-
Z
-
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY reg2 IS
PORT(enable: IN std_logic;
d: IN std_logic;
clk: IN std_logic;
q: OUT std_logic);
END reg2;
ARCHITECTURE areg2 OF reg2 IS
SIGNAL q_tmp: std_logic;
BEGIN
TABLA DE FUNCIONAMIENTO
ENTRADAS
reset d
clk
SALIDAS
q
1
0 transición positiva
0
1
1 transición positiva
1
0
- transición positiva
0
ENTITY reg2 IS
PORT(reset, d,clk: IN bit;
q: OUT bit);
END reg2;
IEC FRANCISCO JAVIER TORRES VALLE
-- lógica registrada
PROCESS(clk, reset, d)
BEGIN
IF clk'event AND clk = '1' THEN
q_tmp <= d;
END IF;
END IF;
END PROCESS;
-- buffer
q <= q_tmp WHEN enable = '1' g
'Z';
END areg2;
73
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
4.7
CONTADORES
La finalidad de un contador es computar el
número de ocurrencias de un evento que se da en
intervalos aleatorios o uniformes. En los siguientes
ejemplos se muestran diferentes tipos de
contadores y la forma más común de describir su
comportamiento con VHDL.
EJEMPLOS
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY counter IS
PORT( clk, load: IN std_logic;
data: IN unsigned(3 DOWNTO 0);
count: BUFFER unsigned(3 DOWNTO 0));
END counter;
ARCHITECTURE archcounter OF counter IS
BEGIN
PROCESS( clk, load, count, data )
BEGIN
IF( clk'event AND clk= '1' ) THEN
IF load = ’1’ THEN
count <= data;
ELSE
count <= count + 1;
END IF;
END IF;
END PROCESS;
END archcounter;
La instrucción USE ieee.numeric_std.ALL es
para incluir el tipo de datos unsigned, así como las
funciones aritméticas y lógicas que nos permiten
manipular objetos de datos que manejen este tipo.
En este ejemplo en particular nos interesa la
función "+" definida para ser utilizada con el tipo
unsigned y enteros. Ya que el operador "+" en
VHDL originalmente está definido únicamente
para ser utilizado con enteros. La arquitectura que
describe
al
contador
utiliza
el
estilo
comportamental. En este diseño el contador
funciona ascendentemente y, además, realiza carga
paralela de datos síncronamente con la señal de
reloj dependiendo del valor del puerto de control
"load".
Dentro del proceso, la instrucción IF ( clk’event
AND clk= ’1’ ) THEN... implica que el
funcionamiento del contador, conteo y carga
paralela, tome lugar durante la transición positiva
de la señal de reloj "clk". La siguiente instrucción
IF... THEN... define la operación de conteo o de
carga paralela del circuito dependiendo de la
condición: load = '1'. A continuación se expone un
contador similar pero con reset síncrono.
IEC FRANCISCO JAVIER TORRES VALLE
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY counter IS
PORT (clk, load, reset: IN std_logic;
data: IN unsigned(3 DOWNTO 0);
count: BUFFER unsigned(3 DOWNTO 0));
END counter;
ARCHITECTURE archcounter OF counter IS
BEGIN
PROCESS(clk, reset, load, count, data)
BEGIN
IF ( clk’event AND clk= '1' ) THEN
IF reset = '1' THEN
count <= (OTHERS => '0');
ELSIF load = '1' THEN
count <= data;
ELSE
count <= count + 1;
END IF;
END IF;
END PROCESS;
END archcounter;
En este ejemplo se describe un contador
ascendente, con reset síncrono dependiendo de la
entrada "reset", además, con capacidad de carga
paralela de datos mediante el puerto de control
"load". Al igual que el ejemplo anterior, la
instrucción IF (clk'event AND clk = '1' ) aparece al
principio e implica que todas las operaciones del
contador se ejecuten durante la transición positiva
de la señal de reloj "clk". La subsecuente
instrucción IF describe la operación de reset
síncrono durante la transición positiva del reloj. El
resto de las operaciones, el conteo y la carga
paralela, son descritas en las siguientes cláusulas
ELSIF y ELSE dentro de la misma instrucción IF,
por lo que podemos observar que la operación de
reset tiene precedencia sobre las operaciones de
carga y conteo. Así, si reset no es '1', entonces la
operación de conteo depende de la señal "load".
Como podemos ver las operaciones de carga y
conteo son identificas al contador en el ejemplo
anterior.
Ahora se expone a continuación un contador
con reset asíncrono y con capacidad para salida en
alta impedancia.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY cnt_oe IS
PORT(clk, reset, oe: IN std_logic;
count_io: INOUT std_logic_vector
(7 DOWNTO 0));
74
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
END ldcnt;
1
0
ARCHITECTURE arch_cnt_oe OF cnt_oe IS
SIGNAL count: std_logic_vector
(7 DOWNTO 0);
BEGIN
PROCESS(clk, reset, count)
BEGIN
IF reset = '0' THEN
count <= (OTHERS => '0');
ELSIIF ( clk’event AND clk=’1’ ) THEN
count <= count + 1;
END IF;
END PROCESS;
count_io <= count WHEN oe = ’1’ ELSE
(OTHERS => 'Z');
END arch_cnt_oe;
0
-
Este diseño desempeña un contador ascendente
con reset asíncrono. Cuando se cumple la
condición: reset = '0', se produce un reset
asíncrono en el contador. Cuando esta condición
no se satisface, la operación de conteo funciona
síncronamente con la señal de reloj "clk". Además,
independientemente de las señal de reset, el uso de
los buffers de tres estados en los pines de I/O es
posible mediante el uso del puerto de entrada "oe".
Así, cuando se satisface la condición oe = '1', el
conteo es conducido hacia los pines de salida. De
lo contrario presentarán alta impedancia en los
pines del circuito. Conceptualmente, el código en
VHDL del contador se implementa de la siguiente
manera.
Figura 4.32
A continuación se elabore la descripción en
VHDL para los siguientes contadores de cuatro
bits de acuerdo a su tabla de funcionamiento y
posteriormente realice las simulaciones. Elija el
dispositivo que más convenga.
CONTADOR NO. 1
ENTRADAS
reset up_down
1
1
SALIDAS
clk
conteo
transición positiva ascendente
IEC FRANCISCO JAVIER TORRES VALLE
transición positiva descendente
-
0
ENITTY counter IS
PORT(reset: IN bit;
ud: IN bit;
clk: IN bit;
conteo: INOUT integer RANGE 0 TO 15
);
END counter;
ARCHITECTURE counter OF counter IS
BEGIN
PROCESS(reset,ud,clk)
BEGIN
IF reset = '1' THEN
conteo <= 0;
ELSIF (clk'event AND clk = '1') THEN
IF ud = '1' THEN
conteo <= conteo + 1;
ELSE
conteo <= conteo - 1;
END IF;
END IF;
END counter;
CONTADOR NO. 2
ENTRADAS
reset up_down
clk
SALIDAS
conteo
1
1
transición positiva ascendente
1
0
transición positiva descendente
0
-
transición positiva
0
ENITTY counter IS
PORT(reset: IN bit;
ud: IN bit;
clk: IN bit;
conteo: INOUT integer RANGE 0 TO 15
);
END counter;
ARCHITECTURE counter OF counter IS
BEGIN
PROCESS(reset,ud,clk)
BEGIN
IF (clk'event AND clk = '1') THEN
IF reset = '1' THEN
conteo <= 0;
ELSIF ud = '1' THEN
conteo <= conteo + 1;
ELSE
conteo <= conteo - 1;
END IF;
END IF;
END counter;
75
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
CONTADOR NO. 3
ENTRADAS
reset oe up_down
SALIDAS
clk
conteo
1
1
1
transición positiva ascendente
1
1
0
transición positiva descendente
0
1
-
-
0
0
0
-
-
Z
** NOTA
Aunque se encuentre la salida del circuito en
alta impedancia, el conteo y reset asíncrono deben
seguir funcionando internamente.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENITTY counter IS
PORT(reset: IN std_logic;
ud: IN std_logic;
oe: IN std_logic;
clk: IN std_logic;
conteo: INOUT unsigned (3 DOWNTO 0)
);
END counter;
ARCHITECTURE counter OF counter IS
SIGNAL count_tmp: unsigned(3 DOWNTO 0);
BEGIN
PROCESS(reset,ud,clk)
BEGIN
IF reset = '1' THEN
count_tmp <= (OTHERS => '0');
ELSIF (clk'event AND clk = '1') THEN
IF ud = '1' THEN
count_tmp <= count_tmp + 1;
ELSE
count_tmp <= count_tmp - 1;
END IF;
END IF;
-- instanciación de los buffers
conteo <= count_tmp WHEN oe = '1' ELSE
(OTHERS 'Z');
END counter;
CONTADOR NO. 4
ENTRADAS
reset oe up_down
1
1
1
SALIDAS
clk
conteo
transición
positiva
ascendente
0-9
IEC FRANCISCO JAVIER TORRES VALLE
1
1
0
transición
positiva
descendente
9-0
0
1
-
-
0
0
0
-
-
Z
** NOTA
Aunque se encuentre la salida del circuito en
alta impedancia, el conteo y reset asíncrono deben
seguir funcionando internamente. En el momento
de cambio de sentido ascendente/descendente, el
contador no debe de iniciar la cuenta, por ejemplo:
si el contador está funcionando ascendentemente y
se encuentra en el número 5 cuando se cambia a
descendente, en la siguiente transición positiva se
debe continuar la cuenta con un 4, después un 3...
etc.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENITTY counter IS
PORT(reset: IN std_logic;
ud: IN std_logic;
oe: IN std_logic;
clk: IN std_logic;
conteo: INOUT unsigned (3 DOWNTO 0)
);
END counter;
ARCHITECTURE counter OF counter IS
SIGNAL count_tmp: unsigned(3 DOWNTO 0);
BEGIN
PROCESS(reset,ud,clk)
BEGIN
IF reset = '1' THEN
count_tmp <= (OTHERS => '0');
ELSIF (clk'event AND clk = '1') THEN
IF ud = '1' THEN
count_tmp <= count_tmp + 1;
IF count_tmp = 9 THEN
count_tmp <= (OTHERS => '0');
END IF;
ELSIF ud = '0' THEN
count_tmp <= count_tmp - 1;
IF count_tmp = 0 THEN
count_tmp <= "1001";
END IF;
END IF;
END IF;
-- instanciación de los buffers
conteo <= count_tmp WHEN oe = '1' ELSE
(OTHERS 'Z');
END counter;
76
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
4.8
ALU DE CUATRO BITS
Realice la descripción en VHDL para la
siguiente unidad aritmético - lógica de acuerdo a
la tabla de funcionamiento utilizando un 22V10. El
circuito consta de 2 bus de entrada "a" y "b", de 4
bits cada uno y mediante el bus "s", de 3 bits, se
selecciona la operación a realizar en la ALU.
Dicha operación se realiza combinacionalmente y
en el momento que ocurre una transición positiva
en la señal de reloj el resultado de dicha operación
se registra en los flip-flop's tipo D del 22V10.
Además, la salida registrada será conducida hacia
los pines de salida (I/O pads) únicamente cuando
se habiliten los buffers de tres estados mediante la
entrada de control "oe", de lo contrario deberán
encontrarse en alta impedancia.
ENTRADAS
s(2) s(1) s(0)
clk
SALIDAS
oe output
cout
0
0
0
transición
positiva
0
a AND
b
0
0
0
1
transición
positiva
0 a OR b
0
0
1
0
transición
positiva
0
a XOR
b
0
0
1
1
transición
positiva
0 NOT a
0
1
0
0
transición
positiva
0
a+0
0
1
0
1
transición
positiva
0
a+b
acarreo de
la suma
1
1
0
transición
positiva
0
a + b'
acarreo de
la suma
1
1
1
transición
positiva
0
a-1
0
-
-
-
-
1
Z
0
** NOTA
b' = NOT b
4.8.1 DESCRIPCIÓN ESTRUCTURAL
La descripción se realiza utilizando tres
archivos, los cuales contienen: la entidad TOP, el
módulo y el paquete respectivamente. El módulo
realiza todas las operaciones dela ALU pero
IEC FRANCISCO JAVIER TORRES VALLE
solamente con un bit, y en la entidad TOP se
realiza la interconexión de cuatr de estos módulos
para formar la ALU de cuatro bits.
ENTIDAD TOP
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE work.modulo_alu.ALL;
ENTITY alu IS
PORT(a: IN std_logic_vector(3 DOWNTO 0);
b: IN std_logic_vector(3 DOWNTO 0);
cin: IN std_logic ;
clk: IN std_logic ;
reset: IN std_logic ;
oe: IN std_logic ;
s: IN std_logic_vector(2 DOWNTO 0);
cout: OUT std_logic;
output: OUT std_logic_vector(3 DOWNTO 0)
);
END alu ;
ARCHITECTURE a_alu OF alu IS
SIGNAL c2, c3, c4: std_logic;
SIGNAL salida_r: std_logic_vector
(3 DOWNTO 0);
ATTRIBUTE synthesis_off OF c2, c3, c4:
SIGNAL IS true;
BEGIN
x0: modulo PORT MAP(a(0), b(0), cin,
clk, reset, s, c2, salida_r(0));
x1: modulo PORT MAP(a(1), b(1), c2, clk,
reset, s, c3, salida_r(1));
x2: modulo PORT MAP(a(2), b(2), c3, clk,
reset, s, c4, salida_r(2));
x3: modulo PORT MAP(a(3), b(3), c4, clk,
reset, s, cout, salida_r(3));
-- instanciación de los biffers
output <= (OTHERS=>'Z') WHEN oe='1' ELSE
salida_r;
END a_alu;
MÓDULO
LIBRARY ieee ;
USE ieee.std_logic_1164.ALL;
ENTITY modulo IS
PORT (in1: IN std_logic;
in2: IN std_logic;
cin: IN std_logic;
clk: IN std_logic;
reset: IN std_logic;
selec: IN std_logic_vector(2 DOWNTO 0);
cout: OUT std_logic ;
salida_r: INOUT std_logic);
END modulo;
ARCHITECTURE a_modulo OF modulo IS
SIGNAL salida_comb: std_logic ;
BEGIN
PROCESS(in2, in1, selec, cin)
77
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
CONSTANT uno: std_logic := '1';
BEGIN
CASE selec IS
WHEN o"0" =>
salida_comb <= in1 AND in2;
cout <= '0';
WHEN o"1" =>
salida_comb <= in1 OR in2;
cout <= '0';
WHEN o"2" =>
salida_comb <= in1 XOR in2;
cout <= '0';
WHEN o"3" =>
salida_comb <= NOT in1;
cout <= '0';
WHEN o"4" =>
salida_comb <= in1;
cout <= '0' ;
WHEN o"5" =>
salida_comb<=in2 XOR in1 XOR cin;
cout <= ( in1 AND cin ) OR
( in2 AND cin ) OR
( in2 AND in1 );
WHEN o"6" =>
salida_comb<= (NOT in2) XOR in1
XOR cin;
cout <= (in1 AND cin) OR
(( NOT in2 ) AND cin) OR
(( NOT in2 ) AND in1);
WHEN o"7" =>
salida_comb<=uno XOR in1 XOR cin;
cout <= ( in1 AND cin) OR
(uno AND cin ) OR
( uno AND in1 ) ;
WHEN OTHERS =>
NULL;
END CASE;
END PROCESS;
PROCESS( salida_comb, clk, reset )
BEGIN
IF rising_edge( clk ) THEN
salida_r <= salida_comb;
END IF;
END PROCESS;
END a_modulo;
PAQUETE
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
PACKAGE modulo_alu IS
COMPONENT modulo
PORT(in1: IN std_logic;
in2: IN std_logic ;
cin: IN std_logic ;
clk: IN std_logic ;
reset: IN std_logic ;
selec: IN std_logic_vector(2 DOWNTO 0);
cout: OUT std_logic ;
salida_r: INOUT std_logic ) ;
END COMPONENT;
END modulo_alu;
IEC FRANCISCO JAVIER TORRES VALLE
4.8.2
DESCRIPCIÓN
COMPORTAMENTAL
LIBRARY ieee ;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY aluIS
PORT (in1: IN unsigned(3 DOWNTO 0);
in2: IN unsigned(3 DOWNTO 0);
cin, clk: IN std_logic;
oe: IN std_logic;
reset: IN std_logic;
selec: IN integer RANGE 0 TO 7;
cout: OUT std_logic ;
salida: INOUT unsigned(3 DOWNTO 0);
);
END alu;
ARCHITECTURE alu OF alu IS
SIGNAL comb, reg: unsigned(3 DOWNTO 0);
SIGNAL c: unsigned(4 DOWNTO 0);
SIGNAL c1,c2,c3
ATTRIBUTE synthesis_off OF c1, c2, c3:
SIGNAL IS true
BEGIN
c(0) <= cin;
cout <= c(4);
c1 <= c(1);
c2 <= c(2);
c3 <= c(3);
PROCESS(in2, in1, selec, cin)
CONSTANT uno: unsigned:= "0001";
BEGIN
FOR i IN in1'range LOOP
CASE selec IS
WHEN 0 =>
comb(i) <= in1(i) AND in2(i);
c(i+1) <= '0';
WHEN 1 =>
comb(i) <= in1(i) OR in2(i);
c(i+1) <= '0';
WHEN 2 =>
comb(i) <= in1(i) XOR in2(i);
c(i+1) <= '0';
WHEN 3 =>
comb(i) <= NOT in1(i);
c(i+1) <= '0';
WHEN 4 =>
comb(i) <= in1(i);
c(i+1) <= '0' ;
WHEN 5 =>
comb(i) <= in2(i) XOR in1(i) XOR
c(i);
c(i+1) <= (in1(i) AND c(i)) OR
(in2(i) AND c(i)) OR
(in2(i) AND in1(i);
WHEN 6 =>
comb(i) <= (NOT in2(i)) XOR
in1(i) XOR c(i);
c(i+1) <= (in1(i) AND c(i)) OR
((NOT in2(i)) AND c(i)) OR
((NOT in2(i)) AND in1(i));
WHEN 7 =>
comb(i) <= uno(i) XOR in1(i)
XOR c(i);
c(i+1) <= (in1(i) AND c(i)) OR
78
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
(uno(i) AND c(i)) OR
(uno(i) AND in1(i)) ;
1.
Este registro es un conjunto de n flip-flops
sincronizados con la misma señal de reloj
para almacenar el estado presente en la
máquina.
WHEN OTHERS =>
NULL;
END CASE;
END LOOP;
END PROCESS;
PROCESS( comb, clk, reset )
BEGIN
IF rising_edge( clk ) THEN
reg <= comb;
END IF;
END PROCESS;
2.
LÓGICA COMBINACIONAL PARA GENERAR EL
SIGUIENTE ESTADO.
3.
Una máquina de estados solamente puede
estar en un estado a un tiempo dado, es
decir no puede hacer dos cosas a la vez. La
lógica combinacional permite que en cada
transición activa del reloj, la máquina vaya
de un estado a otro o se mantenga en el
mismo dependiendo de las condiciones
definidas por el diseñador.
4.
LÓGICA COMBINACIONAL DE SALIDA.
salida <= reg WHEN oe = '0' ELSE
(OTHERS => 'Z');
cout <= '0' WHEN selec = 7 ELSE
c(4);
END alu;s
4.9
REGISTRO DEL ESTADO PRESENTE.
MÁQUINAS DE ESTADO
Una máquina de estados es un circuito
secuencial que es diseñado para seguir un patrón
de funciones previamente definidas. Existen dos
tipos de máquinas de estado: Mealy y Moore. En
una máquina de estados de Moore, las salidas están
únicamente en función del estado presente. Si es
una máquina de estados de Mealy, las salidas están
en función del estado presente y de las entradas.
Una máquina de estados se compone de tres partes:
Las salidas normalmente están en función del
estado presente y/o también en función de las
entradas (Máquina de Estados de Mealy). Es
común que en una máquina de estados de
Moore se desee que las salidas estén en
función del siguiente estado en vez de utilizar
el actual cuando se utiliza una señal de reloj
de alta frecuencia.
A continuación se muestran las estructuras para
máquinas de estados de Moore y Mealy
Figura 4.33 Máquina de Estados de Moore
Figura 4.34 Máquina de Estados de Mealy
IEC FRANCISCO JAVIER TORRES VALLE
79
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
El uso del reset garantiza un comportamiento
seguro del circuito. Esto asegura que la máquina
siempre comience en un estado conocido y válido
antes de la primera transición de reloj. Si no se
utiliza el reset, no existe una forma de predecir el
valor inicial de los flip-flops del registro de estado
durante el encendido del dispositivo en el que se
implementa la máquina de estados. Además existe
la posibilidad de que la máquina comience en un
estado no válido y entonces nunca comenzaría a
funcionar. Por lo que el reset siempre debe ser
implementado en una máquina de estados para
asegurar un correcto funcionamiento. Se prefiere el
uso de reset asíncrono sobre el síncrono porque un
reset asíncrono no requiere ser implementado
mediante ecuaciones, minimizando la lógica
combinacional del circuito. A continuación se
muestran las tres formas más comunes de codificar
los estados en una máquina, suponiendo que utiliza
ocho estados:
ESTADOS
SECUENCIA
BINARÍA
ONE HOT
ENCODIG
SECUENCIA
GRAY
S0
000
00000001
000
S1
001
00000010
001
S2
010
00000100
011
S3
011
00001000
010
S4
100
00010000
110
S5
101
00100000
100
S6
110
01000000
101
S7
111
10000000
111
Cuando se implementa una máquina de estados
en un FPGA se prefiere la codificación ONE
HOT ENCODING porque estos dispositivos
cuentan con bastantes flip-flops y una máquina de
estados codificada de esta manera es más
IEC FRANCISCO JAVIER TORRES VALLE
eficiente y las herramientas de síntesis generan
circuitos con área optimizada y mejor desempeño.
Aunque también es posible que el usuario asigne
los valores de los estado como mejor convenga.
80
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
EJEMPLO
Figura 4.35 Diagrama de Estados
-- Máquina de Estados del tipo Mealy
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY mealy IS
PORT ( clk: IN std_logic;
reset: IN std_logic;
entradas: IN std_logic_vector
(3 DOWNTO 0);
salidas: OUT std_logic_vector
(3 DOWNTO 0)) ;
END mealy;
ARCHITECTURE comportamental OF mealy IS
-- ONE HOT ENCODED state machine
TYPE states IS (S0, S1, S2, S3, S4);
ATTRIBUTE enum_encoding OF states: TYPE IS
"00001 " & -- S0 -- atributo de WARP
"00010 " & -- S1
"00100 " & -- S2
"01000 " & -- S3
"10000" ; -- S4
SIGNAL state, next_state: states ;
BEGIN
-- registro del estado presente
PROCESS(clk, reset)
BEGIN
IF reset='0' THEN
IEC FRANCISCO JAVIER TORRES VALLE
state <= S0;
ELSIF clk'event and clk = '1' THEN
state <= next_state ;
END IF;
END PRCESS;
-- lógica combinacional para definir el
-- siguiente estado
PROCESS(entradas, state)
BEGIN
CASE state IS
WHEN S0 =>
IF entradas = "0001" THEN
next_state <= S1;
END IF;
WHEN S1 =>
IF entradas = "1001" THEN
next_state <= S1;
ELSIF entradas <= "1011" THEN
next_state <= S4;
ELSIF entradas = "0101" THEN
next_state <= S2;
END IF;
WHEN S2 =>
IF entradas = "0111" THEN
next_state <= S1;
ELSIF entradas = "0010" THEN
next_state <= S2 ;
79
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
ELSIF entradas = "1100" THEN
next_state <= S3;
END IF;
WHEN S3 =>
IF entradas = "0101" THEN
next_state <= S4;
END IF;
WHEN S4 =>
IF entradas = "0011" THEN
next_state <= S2;
ELSIF entradas = "0100" THEN
next_state <= S3;
ELSIF entradas = "0110" THEN
next_state <= S4;
ELSIF entradas = "1110" THEN
next_state <= S0 ;
END IF;
WHEN OTHERS =>
NULL;
END CASE;
END PROCESS;
-- lógica combinacional de salida
salidas <= "1000" WHEN (state= S1) ELSE
"0110" WHEN (state=S1 AND
entradas="1001") ELSE
"1100" WHEN (state=S2) ELSE
"0000" WHEN (state= S2 AND
entradas="0010") ELSE
"0011" WHEN (state=S3) ELSE
"0111" WHEN (state=S4) ELSE
"0101" WHEN (state= S4 AND
entradas="0110") ELSE
"1011"; -- asignación en el estado de
-- reset S0
END comportamental;
EJEMPLO
Elabore la descripción en VHDL del siguiente
problema mediante máquina de estados definiendo
su diagrama de estados, frecuencia de trabajo y
dispositivo a utilizar. Se desea diseñar el circuito
de control para lavadora de la siguiente figura.
Figura 4.36
El ciclo de lavado es de la siguiente manera:
1. - Suponiendo que esta vacía al principio,
cuando se presione el botón de "INICIO", activo
en ALTO, se enciende la válvula de agua fría.
2. - En el momento que el nivel del agua llegue
al SENSOR, activo en ALTO, se apaga la válvula
de agua fría y se enciende la de agua caliente
durante dos minutos.
3. - Después se apaga la válvula de agua caliente
y se enciende el motor durante cuatro minutos.
4. - Transcurridos los cuatro minutos, se apaga
el motor y se enciende la válvula de desagüe
durante tres minutos.
5. - Una vez que se ha vaciado la lavadora se
cierra la válvula de desagüe y el ciclo de lavado
comenzará nuevamente cuando se vuelva a
presionar el botón de inicio.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY lavadora IS
PORT( clk: IN std_logic;
inicio: IN std_logic;
sensor: IN std_logic;
vaf: OUT std_logic;
vac OUT std_logic;
motor: OUT std_logic;
des: OUT std_logic
);
END lavadora;
ARCHITECTURE state_machine OF lavadora IS
TYPE states IS
(S0,S1,S2,S3,S4,S5,S6,S7,S8,S9,S10);
SIGNAL state, nex_state: states;
SIGNAL outputs: std_logic_vector
(3 DOWNTO 0);
CONSTANT vaf_on: std_logic_vector
(3 DOWNTO 0):="0001";
CONSTANT vac_on: std_logic_vector
(3 DOWNTO 0):="0010";
CONSTANT mot_on: std_logic_vector
(3 DOWNTO 0):="1000";
CONSTANT des_on: std_logic_vector
(3 DOWNTO 0):="0100";
CONSTANT all_off: std_logic_vector
(3 DOWNTO 0):="0000";
BEGIN
-- REGISTRO DE ESTADO
PROCESS(clk, inicio, next_state)
BEJÍN
IF inicio = '0' THEN
state <= S10; -- todo apagado
ELSIF clk'event AND clk = '1' THEN
state <= next_state;
END IF;
END PROCES;
-- LÓGICA COMBINACIONAL PARA DEFINIR EL
IEC FRANCISCO JAVIER TORRES VALLE
81
CAPÍTULO IV: DESCRIPCIÓN DE CIRCUITOS DIGITALES
-- SIGUIENTE ESTADO
PROCESS(clk, state, sensor)
BEGIN
CASE state IS
WHEN S0 =>
IF sensor='0' THEN
next_state <= S0;
ELSIF sensor='1' THEN
next_state <= S1;
END IF;
WHEN S1 =>
next_state <= S2;
WHEN S2 =>
next_state <= S3;
WHEN S3 =>
next_state <= S4;
WHEN S4 =>
next_state <= S5;
WHEN S5 =>
next_state <= S6;
WHEN S6 =>
next_state <= S7;
WHEN S7 =>
next_state <= S8;
WHEN S8 =>
next_state <= S9;
WHEN S9 =>
next_state <= S10;
WHEN S10 =>
IF inicio = '0' THEN
next_state <= S10;
ELSE
next_state <= S0;
END IF;
WHEN OTHERS =>
NULL;
END CASE;
END IF;
END PROCESS;
-- LÓGICA COMBINACIONAL DE SALIDA
outputs <= all_off WHEN (state=S10) ELSE
vaf_on WHEN (state=S0 AND
sensor='0') ELSE
vac_on WHEN (state=S1) ELSE
vac_on WHEN (state=S2) ELSE
mot_on WHEN (state=S3) ELSE
mot_on WHEN (state=S4) ELSE
mot_on WHEN (state=S5) ELSE
mot_on WHEN (state=S6) ELSE
des_on WHEN (state=S7) ELSE
des_on WHEN (state=S8) ELSE
des_on WHEN (state=S9) ELSE
all_off;
END state_machine;
IEC FRANCISCO JAVIER TORRES VALLE
82
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
V
IMPLEMENTACIÓN DE
FILTROS DIGITALES
EN FPGA'S
IEC FRANCISCO JAVIER TORRES VALLE
83
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
5.1
INTRODUCCIÓN
Un FPGA es un dispositivo cuyas características
pueden ser modificadas, manipuladas o
almacenadas
mediante
programación.
La
arquitectura de un FPGA (Field Programmable
Gate Array) consiste en arreglos de múltiples
celdas lógicas las cuales se comunican unas con
otras mediante canales de conexión verticales y
horizontales. Cada celda lógica contiene arreglos
de compuertas lógicas AND y OR, así como un
número definido de registros y multiplexores.
Mediante estos recursos es posible implementar
funciones matemáticas y de almacenamiento de
datos. Dada la gran densidad de compuertas con
las que cuenta un FPGA, es posible implementar
sistemas digitales muy complejos, entre los que
destaca el filtrado digital. Además, en un FPGA es
posible realizar modificaciones de último minuto
sin que esto implique grandes alteraciones en el
hardware o en el software.
5.2
ANTECEDENTES
En las últimas tres décadas la ingeniería se ha
visto revolucionada en el campo del procesamiento
digital de señales, donde los filtros digitales
forman un apartado muy importante, ya que estos
se encuentran en una extensa gama de
aplicaciones. Desde procesamiento de audio y
vídeo hasta control de motores; donde la
utilización del filtrado digital incluye ventajas
como:
5.3
MARCO TEÓRICO
El término filtro se utiliza comúnmente para
describir un dispositivo que discrimina aquello que
pasa a través de él. Así, por ejemplo, un filtro de
aire permite que sólo pase aire a través de éste,
evitando que las partículas de polvo presentes en el
aire lo atraviesen. Un filtro digital es un sistema
lineal e invariante en el tiempo (LTI) que modifica
el espectro en frecuencia de la señal de entrada
X(w), según la respuesta que tenga en frecuencia
H(w) (conocida como función de transferencia),
para dar lugar a una señal de salida con espectro:
Y(w) = H(w) * X(w). En cierto sentido, H(w)
actúa como una función de ponderación o función
de conformación espectral para las diferentes
componentes frecuenciales de la señal de entrada.
Los sistemas LTI se clasifican como: FIR (finite
impulse response) que se caracterizan pos ser
sistemas no recursivos, e IIR (infinite impulse
response) que se distinguen por tener
retroalimentación en la señal salida.
5.3.1
FILTROS FIR
Un filtro FIR de orden M se describe mediante
la ecuación en diferencias: y(n) = b0 x(n) + b1 x(n1) + b2 x(n-2) + bM x(n-M), donde la secuencia
bk son los coeficientes del filtro. En este tipo de
filtrado no existe retroalimentación. Además, la
respuesta al impulso H(w), es de duración finita ya
que si la entrada se mantiene en cero durante M
periodos consecutivos la salida también será cero.
Algunas de las ventajas de este tipo de filtros son
las siguientes:
1)
El ancho de banda y la calidad del filtro no
están necesariamente relacionadas.
2)
Al utilizar dispositivos programables, la
función de transferencia de el filtro puede
ser transformada sin más modificaciones
que el cambio de los coeficientes en
memoria.
1) Un filtro FIR puede ser diseñado para
tener fase lineal.
3)
Variables como temperatura o alteraciones
en el voltaje no afectan la funcionalidad
del circuito.
4)
El costo de la aplicación es relativamente
bajo.
3) Los errores por desbordamiento no son
problemáticos porque la suma de
productos en un filtro FIR es
desempeñada por un conjunto finito de
datos.
2) Siempre son estables porque son hechos
únicamente con ceros en el plano
complejo.
4) Un filtro FIR es fácil de comprender e
implementar.
IEC FRANCISCO JAVIER TORRES VALLE
84
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
Figura 5.1 Estructura para la realización de filtros IIR
5.3.2
FILTROS IIR
Los filtros IIR corresponden directamente al
equivalente analógico. Una forma de diseñar filtros
IIR es creando la función de transferencia deseada
en el dominio analógico para transformarla al
dominio z y después calcular los coeficientes del
filtro IIR mediante los cuales se obtiene la
siguiente ecuación en diferencias: y(n) = b0 x(n)
+ b1 x(n – 1) + b2 x(n – 2) + ... bM x(n –M) - a1 y(n
– 1) - a2 y(n – 2) - ....- aN y(n – N), donde las
variables ak y bk son los coeficientes del filtro.
Dentro de las ventajas que ofrecen los filtros IIR
sobre los tipo FIR encontramos:
1) Los filtros IIR requieren menos memoria y
menos instrucciones para implementar su
función de transferencia.
2) Un filtro IIR se diseña mediante el calculo
de polos y ceros en el plano complejo. El
uso de polos confieren a un filtro IIR la
capacidad de implementar funciones de
transferencia que es imposible realizar
mediante filtros FIR.
Sin embargo, algunas consideraciones que se
deben considerar en la implementación de filtros
IIR son las siguientes:
1) Los filtros IIR no son necesariamente
estables, es tarea del diseñador buscar la
estabilidad del sistema.
2) Los filtros IIR producen en general
distorsión de fase.
3) La
posibilidad
desbordamiento
de
resultados en la operaciones realizadas
deben ser consideradas ya que un filtro IIR
se implementa mediante sumas de
productos que están basadas en una suma
infinita.
La implementación de filtros IIR puede hacerse de
varias formas. Asumiendo el comportamiento
lineal e invariante en el tiempo del sistema, la
ecuación en diferencias de un filtro puede ser
manipulada matemáticamente para obtener una
realización con N elementos de memoria, (N + M
+ 1) multiplicadores y N sumadores, conocida
como Forma Directa II Transpuesta.
3) Es posible trasladar un filtro IIR a un
modelo analítico.
IEC FRANCISCO JAVIER TORRES VALLE
85
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
Figura 5.2 Implementación de filtros IIR mediante FDII-T
1) Establecer las especificaciones del filtro,
como lo son: ancho de banda, atenuaciones,
ganancias, etc.
(retraso de una unidad), z -2 (dos unidades), etc. Por
lo que los filtros digitales pueden realizarse usando
los elementos correspondientes a las operaciones
de multiplicación, adición y almacenaje de datos
en el FPGA, utilizando alguna de las estructuras
para la realización de sistemas LTI. Una correcta
elección de la estructura a implementar puede
optimizar significativamente la eficacia del
sistema.
2) Determinar la función de transferencia que
cumpla las especificaciones.
5.6
5.4
METODOLOGÍA DE DISEÑO
PARA FILTROS DIGITALES
El proceso de diseño de un filtro digital requiere
de los siguientes pasos.
3) Elaborar un diagrama a bloques con las
operaciones a realizar, el cual especifica en
hardware los elementos del circuito y sus
interconexiones.
5.5
IMPLEMENTACIÓN EN
FPGA'S
El almacenaje de un dato significa retrasar su
uso una cantidad normalmente igual al periodo de
muestreo. Este retraso se representa mediante z -1
IEC FRANCISCO JAVIER TORRES VALLE
DISEÑO DE UN FILTRO
PASA-BAJAS
Un filtro pasa - bajas ideal es aquel que permite
pasar todas aquellas frecuencias que se encuentran
por debajo de una frecuencia de corte especificada
(fc), atenuando las que se encuentran por encima
de esta. La siguiente ecuación en diferencias
corresponde a un filtro IIR pasa - bajas tipo
butteworth de orden 5, frecuencia de muestreo de
48.8 kHz y con una frecuencia de corte a 5 kHz:
86
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
y(n) = 0.0014*x(n) + 0.0071*x(n-1) +
0.0142*x(n-2) + 0.0142*x(n-3) + 0.0071*x(n-4) +
0.0014*x(n-5) + 2.9272*y(n-1) - 3.7016*y(n-2) +
2.4521*y(n-3) - 0.8422*y(n-4) + 0.1191*y(n-5)
A continuación se muestra la respuesta en
frecuencia del sistema en magnitud y fase.
F U N C I Ó N D E T R A N SF E R E N C I A
1 .2
1
|H(F)|
0 .8
0 .6
0 .4
0 .2
0
10
1
10
2
10
3
10
4
10
5
10
3
10
4
10
5
F
3
2
<) H(F)
1
0
-1
-2
-3
10
1
10
2
F
Figura 5.3 Respuesta del filtro en magnitud y fase
La gráfica anterior sería la función de
transferencia ideal del filtro a implementar, pero
en un sistema digital todo se trabaja en el sistema
binario por lo que debemos convertir los
coeficientes obtenidos a dicho sistema. Dicha
conversión implica una cantidad considerable de
bits si es que se desea obtener la misma calidad.
Pero el utilizar más bits implica la utilización de
mayor cantidad de recursos del FPGA, el cual en
el presente trabajo es un XC4010XLPC84. De
hecho un multiplicador de 20 bits requiere del
65% de los recursos de este dispositivo, por lo
que se opto por implementar el filtro utilizando la
función de transferencia H(ω) del filtro anterior
con las primeras once muestras de la respuesta al
impulso del sistema LTI y realizar el diseño del
filtro utilizando la estructura FIR.
Los
coeficientes utilizados son los siguientes: b(n) = (
1, 2, 3, 4, 4, 3, 2, 1, -1, -1, -1 ), los cuales cuando
se digitalizan utilizando el formato complemento
a dos quedan de la siguiente manera: bk = ( 0001,
.
IEC FRANCISCO JAVIER TORRES VALLE
0010, 0011, 0100, 0100, 0011, 0010, 0001, 1111,
1111, 1111 )
El diseño de la estructura FIR se realizo con
VHDL para lo cual se describieron utilizando
once registros en una configuración FIFO para
realizar los retardos z-1 y cuyas salidas se
multiplican por el coeficiente respectivo. EL
dispositivo convertidor analógico - digital
utilizado es el AK4520A el cual tiene una
longitud de palabra de 20 bits con salida en
complemento a dos. Por lo que el filtrado se
realizo con once multiplicaciones de 20x4 y un
acumulador de dichas operaciones. La
cuantización de los coeficientes afecta la
respuesta en frecuencia del sistema, a
continuación se muestra la respuesta en
frecuencia en magnitud del filtro con lo
coeficientes cuantizados
87
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
FU N C IÓ N D E T R A N SFE R E N C IA
20
18
16
14
|H(F)|
12
10
8
6
4
2
0
10
1
10
2
10
3
10
4
F
Figura 5.4 Respuesta del filtro en magnitud utilizando los coeficientes cuantizados
A continuación se muestra la descripción en
VHDL de la estructura FIR.
-------------------------------------- FIR
------------------------------------library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package fir_coef is
subtype coef_word is signed
(3 downto 0);
subtype coef_range is integer range
0 to 10;
type coef_table is array
(0 to 10) of coef_word;
constant coef_rom: coef_table:= (
("0001"),
("0010"),
("0011"),
("0100"),
("0100"),
("0011"),
("0010"),
("0001"),
("1111"),
("1111"),
("1111"));
end fir_coef;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.fir_coef.all;
IEC FRANCISCO JAVIER TORRES VALLE
entity fir is
port(clk,reset,load: in std_logic;
data_in: in signed
(19 downto 0);
data_out: out signed
(19 downto 0));
end fir;
architecture a_fir of fir is
type fifo_array is array
(0 to 10) of signed
(19 downto 0);
signal fifo: fifo_array;
begin
process (reset,clk,fifo,data_in)
begin
if reset = '0' then
for i in 0 to 10 loop
fifo(i) <= (others => '0');
end loop;
elsif clk'event and clk = '1'
then
if load = '1' then
for i in 1 to 10 loop
fifo(i) <= fifo(i-1);
end loop;
fifo(0) <= data_in;
end if;
end if;
end process;
process (fifo)
88
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
variable prod,data_tmp: signed
(23 downto 0);
begin
data_tmp := (others => '0');
for i in 0 to 10 loop
prod := fifo(i) * coef_rom(i);
data_tmp := data_tmp + prod;
end loop;
data_out <=
data_tmp(23)&data_tmp(18 downto 0);
end process;
end a_fir;
El diseño del circuito se basa en el siguiente
diagrama.
IEC FRANCISCO JAVIER TORRES VALLE
89
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
Figura 5.5 Filtro FIR implementado en el FPGA
IEC FRANCISCO JAVIER TORRES VALLE
90
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
A continuación se muestra las salidas obtenidas de
la implementación del diseño, como señales de
prueba se utilizaron senoidales de 1 Vpp aprox. a
diferentes frecuencias. A la frecuencia de corte del
filtro se debe obtener aprox. 0.5 Vpp lo
cual es necesario para poder decidir si el filtro está
bien
diseñado.
Figura 5.6 Salida del filtro a 1.027 kHz
Figura 5.6 Salida del filtro a 2.024 kHz
IEC FRANCISCO JAVIER TORRES VALLE
91
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
Figura 5.6 Salida del filtro a 3.021 kHz
Figura 5.6 Salida del filtro a 5 kHz
IEC FRANCISCO JAVIER TORRES VALLE
92
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
Figura 5.6 Salida del filtro a 6.061 kHz
Figura 5.6 Salida del filtro a 7.092 kHz
5.7
hardware de un filtro digital puede
implementar una gran variedad de filtros, sin
que esto implique modificaciones en el
circuito.
RESULTADOS
•
Los filtros digitales cuentan con muchas
ventajas que los hacen más atractivos que sus
predecesores analógicos.
•
Al utilizar dispositivos programables, como
un FPGA, la función de transferencia del
filtro puede ser transformada sin más
modificaciones que la reprogramación del
dispositivo. Por lo que un simple diseño en
IEC FRANCISCO JAVIER TORRES VALLE
•
Las funciones de transferencia de los filtros
digitales
cuentan
con
rigurosas
especificaciones, como que las frecuencias
que se desea sean rechazadas pueden ser
extremadamente atenuadas sin sacrificar el
ancho de banda que se está filtrando.
93
CAPÍTULO V: IMPLEMENTACIÓN FILTROS DIGITALES EN FPGA's
V o (d b )
5
0
1 .0 0 E + 0 0
1 .0 0 E + 0 1
1 .0 0 E + 0 2
1 .0 0 E + 0 3
1 .0 0 E + 0 4
-5
-1 0
db
-1 5
-2 0
-2 5
-3 0
-3 5
-4 0
-4 5
F r e c u e n c ia (H z )
Frecuencia
Vo (Volts)
Vo
(Hertz)
(db)
1.00E-00
1
0
1.03E+03
1.044
0.374009
2.02E+03
0.981
-0.166619
3.02E+03
0.818
-1.744933
5.00E+03
0.475
-6.466127
6.06E+03
0.281
-11.02587
7.09E+03
0.168
-15.49381
1.00E+04
0.01
-40
Figura 5.7 Respuesta en frecuencia del filtro
IEC FRANCISCO JAVIER TORRES VALLE
94
CONCLUSIONES
CONCLUSIONES
IEC FRANCISCO JAVIER TORRES VALLE
95
CONCLUSIONES
CONCLUSIONES
•
•
•
Es posible verificar el funcionamiento del
sistema dentro del proceso de diseño sin
necesidad de implementar el circuito.
La cual se apoya en el hecho de que
cualquier función lógica se puede realizar
mediante una suma de productos.
Las simulaciones del diseño, antes de que éste
sea implementado mediante compuertas,
permiten probar la arquitectura del sistema
para tomar decisiones en cuanto a cambios en
el diseño.
•
Las herramientas de síntesis tienen la
capacidad de convertir una descripción hecha
VHDL a compuertas lógicas y, además,
optimizar dicha descripción de acuerdo a la
tecnología utilizada.
•
Esta metodología elimina el antiguo método
tedioso de diseño mediante compuertas,
reduce el tiempo de diseño y la cantidad de
errores producidos por el armado del circuito.
•
Las herramientas de síntesis pueden
transformar automáticamente un circuito
obtenido mediante la síntesis de un código en
VHDL, a un circuito pequeño y rápido.
Además,
es
posible
aplicar
ciertas
características al circuito dentro de la
descripción para afinar detalles (retardos,
simplificación de compuertas, etc.) en la
arquitectura del circuito y que estas
características se obtengan en la síntesis de la
descripción.
•
Las descripciones en VHDL proporcionan
documentación de la funcionalidad de un
diseño independientemente de la tecnología
utilizada.
•
Un circuito hecho mediante una descripción
en VHDL puede ser utilizado en cualquier tipo
de dispositivo programable capaz de soportar
la densidad del diseño. Es decir, no es
necesario adecuar el circuito a cada
dispositivo porque las herramientas de síntesis
se encargan de ello.
•
Una descripción realizada en VHDL es más
fácil de leer y comprender que los netlist o
circuitos esquemáticos.
•
La fabricación de dispositivos de lógica
programable se basa en los siguientes dos
conceptos.
IEC FRANCISCO JAVIER TORRES VALLE
FUNCIONALIDAD COMPLETA
•
CELDAS DE FUNCIONES UNIVERSALES.
También denominadas generadores de
funciones, son bloques lógicos configurados
para procesar cualquier función lógica,
similares en su funcionamiento a una
memoria. En estas celdas se almacenan los
datos de salida del circuito combinacional en
vez de implementar físicamente la ecuación
booleana.
•
En la descripción de circuitos con VHDL el
dispositivo utilizado es de vital importancia,
ya que de este depende el proceso de síntesis
mediante el cual se obtiene la funcionalidad
lógica implementada en el mismo.
•
Lo que ha hecho que VHDL sea en un tiempo
tan corto el lenguaje de descripción de
hardware más utilizado por la industria
electrónica, es su independencia con la
metodología utilizada por cada diseñador, 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.
•
La clave para describir y sintetizar fácilmente
circuitos digitales con VHDL es pensar en
términos de compuertas y registros y no en
función de variables y subrutinas.
•
WARP y Foundation son herramientas de
síntesis que utilizan VHDL como su lenguaje
de descripción de circuitos, cada uno con sus
propias restricciones del lenguaje. Por lo que
es necesario consultar el manual de referencia
de cada herramienta para conocer dichas
restricciones.
•
Al utilizar dispositivos programables, como
un FPGA, la función de transferencia de un
filtro puede ser transformada sin más
modificaciones que la reprogramación del
dispositivo. Por lo que un simple diseño en
hardware de un filtro digital puede
implementar una gran variedad de filtros, sin
que esto implique modificaciones en el
circuito.
96
BIBLIOGRAFÍA
BIBLIOGRAFÍA
IEC FRANCISCO JAVIER TORRES VALLE
97
BIBLIOGRAFÍA
VHDL FOR PROGRAMMABLE LOGIC
THE PROGRAMMABLE LOGIC DATA BOOK
KEVIN SKAHILL
XILINX, INC.
CYPRESS SEMICONDUCTOR &
1999
ADDISON WESLEY
1996
CYPRESS PROGRAMMABLE LOGIC DATA
BOOK
VHDL
DOUGLAS L. PERRY
CYPRESS SEMICONDUCTOR
1997
MCGRAW HILL
2ª EDICIÓN
DIGITAL SIGNAL PROCCESING
JOHN G. PROAKIS,
VHDL, LENGUAJE PARA SÍNTESIS Y
DIMITRIS G. MANOLAKIS
MODELADO DE CIRCUITOS
PRENTICE HALL
FERNANDO PARDO, JOSÉ A. BOLUDA
1992
EDITORIAL RA-MA
1999
DISCRETE-TIME SIGNAL PROCCESING
A. V. OPPENHEIM
VHDL REFERENCE GUIDE
R. W. SCHAFFER
XILINX, INC.
PRENTICE HALL
1999
1989
ACTEL HDL CODING, STYLE GUIDE
VHDL LENGUAJE PARA SÍNTESIS Y
ACTEL CORPORATION
MODELADO DE CIRCUITOS
1999
http://bugs.uv.es/dpt/atc/asignat
uras/ti/curso/curso.html
WARP, LANGUAGE REFERENCE MANUAL
CYPRESS SEMICONDUCTOR
1998
MAX+PLUS II, GETTING STARTED
MANUAL
ALTERA CORPORATION
1999
VHDL LENGUAJE PARA SÍNTESIS Y
MODELADO DE CIRCUITOS (2)
http://tapec.uv.es/VHDL/libro.ht
ml
IZQUIERDA DE LENGUAJES DE DESCRIPCIÓN
DE HARDWARE VHDL
http://cseg.inaoep.mx/~ariasm/arqcomp/v
hdlweb/indexiz.htm
IEC FRANCISCO JAVIER TORRES VALLE
98
BIBLIOGRAFÍA
LÓGICA PROGRAMABLE DE ALTA DENSIDAD
HUMBERTO DE JESÚS OCHOA
DOMÍNGUEZ
http://intranet.uacj.mx/
SYNTHESIS USING VHDL
http://www.cedcc.psu.edu/ee497f/rassp_6
0/index.htm
RASSP TECHNOLOGY BASE VHDL
MODELING DEVELOPMENT
http://www.erc.msstate.edu/mpl/
rassp/modeling/html/modeling.ht
ml
THE HAMBURG VHDL ARCHIVE
http://tech-www.informatik.unihamburg.de/vhdl/vhdl.html
VHDL EXAMPLES FOR SYNTHESIS
http://eecad.sogang.ac.kr/~chang/vhdl/We
lcome.html
EXAMPLES FOR VHDL
VHDL AND VERILOG REFERENCES AND
TUTORIALS
http://www.optimagic.com/tutori
als.html
http://www.eej.ulst.ac.uk/exa/exam.html
NORTHEASTERN UNIVERSITY VHDL DESIGN
& DEVELOPMENT
http://www.ece.neu.edu/info/vhd
l/vhdl.html
VHDL COOKBOOK (C) 1990, PETER J.
ASHENDEN
http://www.fastsys.co.kr/~jwpar
k/Outside/Comp/EDA/Cookboo
k.html
VHDL INTERNATIONAL HOME PAGE
AN INTRODUCTION TO VHDL
http://www.vhdl.org/
http://www.acceda.com/h_intro.htm
VHDL RESOURCE PAGE
DOULOS VHDL TRAINING VERILOG
TRAINING DOULOS HOME PAGE
http://www.doulos.co.uk/thewin
ningedge/index.htm
http://www.ece.uc.edu/~rmiller/
VHDL/intro.html
VHDL-ONLINE MAIN FRAME
http://www.vhdl-online.de/
RASSP HOME PAGE
http://rassp.scra.org/
ACTEL CORPORATION'S HOME PAGE
http://www.actel.com/
ACTEL DESKTOP HOME
http://www.acteldesktop.com/
IEC FRANCISCO JAVIER TORRES VALLE
99
BIBLIOGRAFÍA
CYPRESS SEMICONDUCTOR CORPORATION
http://www.cypress.com/
ALTERA WEB SITE
http://www.altera.com/
XILINX HOME PAGE
http://www.xilinx.com/
INTECTRA INC.
http://www.intectra.com/
VHDL, LEGUAJE PARA LA SÍNTESIS Y
DESCRIPCIÓN DE HARDWARE
http://www.gdl.uag.mx/214/inicio.htm
IEC FRANCISCO JAVIER TORRES VALLE
100
Descargar