Académique Documents
Professionnel Documents
Culture Documents
Programables
Versión 0.6
Junio 29, 2005
Guillermo Güichal
Índice
1 Agradecimientos ......................................................................................................... 7
2 Versiones..................................................................................................................... 8
3 Introducción ................................................................................................................ 9
4 Temas Básicos de Diseño Digital ............................................................................. 11
4.1 Diseño Combinacional y Secuencial ................................................................ 11
4.1.1 Flip-Flops y Latches ................................................................................. 11
4.2 Diseño Secuencial Asincrónico y Sincrónico ................................................... 11
4.3 Algunas Notas sobre Diseño Secuencial Sincrónico ........................................ 11
4.3.1 Temporizado y Utilización de Registros................................................... 11
4.3.2 Distribución de Reloj ................................................................................ 11
4.3.3 Máxima Frecuencia de Trabajo ................................................................ 11
4.3.4 Pipelines.................................................................................................... 11
4.3.5 Dominios de Reloj .................................................................................... 11
4.3.6 Metaestabilidad en los Flip-Flops............................................................. 11
4.4 Autómatas de Estados Finitos (Máquinas de estados finitos)........................... 11
4.4.1 Máquinas de Mealy................................................................................... 11
4.4.2 Máquinas de Moore .................................................................................. 11
4.4.3 Codificación de estados. Mínima, One-hot, One-cold, Grey, etc. ............ 11
4.5 Integridad de Señal ........................................................................................... 11
4.5.1 Que afecta la integridad de señal y que es. Como afecta fuera y dentro del
chip (FPGA?) ............................................................................................................ 11
4.5.2 Terminaciones de Señales......................................................................... 12
4.6 Interfaces Eléctricas .......................................................................................... 12
4.7 Potencia y Consumo de los Circuitos ............................................................... 12
5 Diseño Digital con FPGAs y HDLs.......................................................................... 13
5.1 Metodología General de Diseño Digital ........................................................... 15
5.1.1 Especificación y Diseño............................................................................ 17
5.1.2 Verificación............................................................................................... 18
5.1.3 Pasos Finales............................................................................................. 18
5.2 Diseño Digital Utilizando Lenguajes de Descripción de Hardware ................. 18
5.3 Flujo de Diseño para Lógicas Programables .................................................... 19
5.3.1 Flujo de Diseño (Design Flow)................................................................. 19
5.4 Lenguajes de descripción de hardware ............................................................. 22
5.4.1 VHDL ....................................................................................................... 23
5.4.2 Verilog ...................................................................................................... 23
5.4.3 Otros.......................................................................................................... 23
5.5 Herramientas de Desarrollo .............................................................................. 24
5.5.1 Descripción del Diseño ............................................................................. 24
5.5.2 Generación o Traducción.......................................................................... 24
5.5.3 Simulación ................................................................................................ 24
5.5.4 Notas Manejo del tiempo en VHDL ......................................................... 24
6 Dispositivos Lógicos Programables.......................................................................... 27
6.1 Evolución de los Primeros Dispositivos Lógicos Programables ...................... 28
6.2 CPLDs............................................................................................................... 31
6.3 FPGAs............................................................................................................... 32
6.3.1 Bloque Lógico Programable ..................................................................... 35
6.3.2 Bloque de Entrada / Salida....................................................................... 38
6.3.3 Bloque de Control de Reloj....................................................................... 41
6.3.4 Memoria.................................................................................................... 43
6.3.5 Bloque de Procesamiento de Señal ........................................................... 44
6.3.6 CPUs Embebidas ...................................................................................... 46
6.3.7 Matriz de Interconexión............................................................................ 47
6.4 Granularidad de los Dispositivos Lógicos Programables (PLDs) .................... 48
6.5 Tecnología de Configuración de los PLDs ....................................................... 53
6.6 Tendencias Actuales y Futuras ......................................................................... 54
6.7 Notas a Junio 2005............................................................................................ 54
7 Primeros Pasos con VHDL ....................................................................................... 56
7.1 Notas Preliminares Sobre Formato de VHDL y los Ejemplos ......................... 56
7.1.1 Formato del Código de Ejemplo ............................................................... 56
7.1.2 Capitalización en VHDL........................................................................... 56
7.1.3 Comentarios en VHDL ............................................................................. 56
7.1.4 Delimitadores de Código en VHDL ......................................................... 56
7.2 Estructura Básicas de un Modelo en VHDL..................................................... 57
7.2.1 Entidades y Arquitecturas ......................................................................... 57
7.2.2 Modelos de comportamiento..................................................................... 59
7.2.3 Modelos Estructurales............................................................................... 61
7.3 Elementos del Lenguaje VHDL........................................................................ 64
7.3.1 Palabras Reservadas.................................................................................. 64
7.3.2 Símbolos Especiales.................................................................................. 64
7.3.3 Identificadores........................................................................................... 66
7.3.4 Números.................................................................................................... 66
7.3.5 Cadenas de bits ......................................................................................... 66
7.4 Tipos en VHDL................................................................................................. 67
7.4.1 Tipos Comunes ......................................................................................... 67
7.4.2 Declaración de Tipos ................................................................................ 67
7.4.3 Tipos enumerados ..................................................................................... 68
7.4.4 Subtipos..................................................................................................... 68
7.4.4.1 Tipo Natural y Positivo......................................................................... 68
7.4.5 Tipos Físicos ............................................................................................. 69
7.4.5.1 Tipo Tiempo.......................................................................................... 69
7.4.6 Tipos compuestos...................................................................................... 69
7.4.6.1 Arreglos................................................................................................. 70
7.4.6.2 Arreglos sin Rangos Predeterminados .................................................. 71
7.4.6.3 Records ................................................................................................. 72
7.4.7 Calificación y Conversión de Tipos.......................................................... 72
7.5 Objetos en VHDL ............................................................................................. 73
7.5.1 Constantes ................................................................................................. 73
7.5.2 Señales ...................................................................................................... 73
7.5.3 Variables ................................................................................................... 74
1 Agradecimientos
Con la versión 0.6 llega el aporte de algunos colaboradores. Me gustaría aprovechar
entonces para agregar esta sección y agradecerles su ayuda.
Julio Amoedo de Invap S.E. (www.invap.com.ar) leyó la primer versión y me dio mucha
realimentación para mejorar estas notas. Se que hay secciones que pueden no estar muy
claras, pero traté de seguir sus sugerencias para que todo sea mas entendible.
2 Versiones
Ver 0.5 (27/06/2005)
Publicación inicial en www.fpga.com.ar
3 Introducción
Estas notas son una introducción al diseño digital utilizando lógicas programables y
lenguajes de descripción de hardware. La intención no es hacer un tratamiento exhaustivo
y completo de este tema, sino presentar el material que permitirá comenzar a trabajar lo
más rápido posible. Esto se intenta hacer limitando el contenido y focalizándolo sobre
aplicaciones y ejemplos para diseños sintetizables sobre FPGAs.
Los ejemplos de aplicaciones fueron desarrollados para la placa de desarrollo D2E, DIO1
y DIO2 de Digilent, Inc (www.digilentinc.com). La placa D2E contiene una FPGA
Spartan IIe 200 y varios conectores. Las otras placas se conectan a la D2E y contienen
periféricos, tales como botones, leds, display, conectores PS2 y VGA, etc. Por ese
motivo, en las secciones o ejemplos que utilicen o presenten herramientas de desarrollo, y
en los ejemplos en donde se presenten dispositivos específicos, se utilizarán herramientas
y dispositivos de Xilinx. En las secciones generales, sin embrago, se intentan presentar
dispositivos y herramientas de varios fabricantes para que el lector tenga una visión más
amplia de las alternativas existentes.
Se espera que el lector de estas notas tenga una base de diseño digital. Además se supone
que el lector conoce algún lenguaje de programación y esta familiarizado con la
utilización de herramientas de desarrollo de software. Para el que necesita estudiar los
conceptos básicos de diseño digital se recomienda el libro de John F. Wakerly detallado
al final de esta sección. Este libro, además, contiene una excelente introducción a los
dispositivos lógicos programables. Para el lector que no está familiarizado con ningún
ambiente de desarrollo de software también se da una lista de los documentos y manuales
de Xilinx que permitirán que se entienda rápidamente el uso de las herramientas de
desarrollo. En el futuro se completará una sección introductoria con un repaso de temas
de diseño, tecnologías y técnicas digitales.
Algunas características y limitaciones que deben tenerse en cuenta al leer estas notas son
las siguientes:
4.3.4 Pipelines
Las FPGA tienen grandes cantidades de entradas salidas que pueden requerir mucha
corriente. Se deben usar capacitores de desacople y tener en cuenta las especificaciones
de los fabricantes sobre la cantidad de salidas que pueden cambiar al mismo tiempo.
Un sistema puede estar compuesto por varios subsistemas, no todos ellos digitales o
electrónicos. La primer decisión será entonces que partes del sistema se implementarán
como subsistemas digitales. En el sistema digital, los siguientes pasos se siguen en cada
nivel de la jerarquía del diseño, cada vez con mayor nivel de detalle.
La especificación es muy importante pare definir bien los límites de lo que se quiere
fabricar. A partir de la especificación se puede definir una arquitectura con los diferentes
componentes que implementan cada función del sistema. Para el diseño se debe definir el
funcionamiento de cada uno de esos componentes.
Para lograr tiempo más rápidos de diseño, menos errores, y mayor productividad, lo ideal
sería poder trabajar al máximo nivel de abstracción posible (algoritmos), sin entrar en los
detalles de bajo nivel. Desafortunadamente, esto no es siempre posible con la tecnología
existente (pero esta cambia permanentemente). El nivel de abstracción dependerá
entonces de la aplicación y restricciones sobre el diseño. Si se debe diseñar un integrado
full-custom analógico es probable que se trabaje al nivel de ecuaciones diferenciales, al
nivel de transistores y haciendo el layout manual. Si se diseña un integrado digital con
bloques predefinidos (IP, Cores) y adquiridos a terceros se trabajará a un nivel de
abstracción mucho mayor (floorplanning, RTL). En el ciclo de diseño con FPGAs, gran
parte del aspecto físico ha sido solucionado por el fabricante. En general se trabaja al
nivel de transferencia de registros con algunas herramientas que ayudan a diseñar a
niveles de algoritmo.
Las grandes capacidades de los PLDs y herramientas de diseño disponibles permiten que
los diseños implementados sobre FPGAs sean cada vez mas complejos. En muchos casos
varias personas pueden estar trabajando sobre el mismo producto, incluso en localidades
separadas. Para poder atacar el problema del diseño de sistemas digitales complejos (ya
sea para desarrollos sobre FPGAs, ASICs o PCBs) es importante tener una metodología
de trabajo que permita planificar y ordenar el trabajo.
• Diagrama en bloques del sistema externo, que muestra como y donde encaja el
dispositivo dentro del sistema completo.
• Diagrama en bloques interno que muestra los principales bloques funcionales.
• Descripción de las entradas/salidas, incluyendo interfaces lógicas, eléctricas y
protocolos de comunicación.
• Estimaciones de tiempos que se deben cumplir, incluyendo tiempos de "setup" y
"hold" para las entradas/salidas y frecuencias de reloj.
• Estimación de la complejidad y/o magnitud del dispositivo, dado en número de
compuertas equivalentes o número de circuitos integrados necesarios.
• Especificación física del dispositivo. Tamaño, empaquetamiento, conectores, etc.
• Estimación del consumo de potencia del dispositivo.
• Precio estimado del dispositivo.
• Procedimientos de verificación y validación para el dispositivo.
Después de escribir las especificaciones es importante hacer una revisión con todos los
miembros del equipo. De esta revisión podrán surgir cosas que no se tuvieron en cuenta
individualmente y que produzcan modificaciones. La especificación también incluye la
metodología de verificación del dispositivo. Estas muchas veces se dejan para el final del
proyecto y no se definen ni llevan a cabo de manera adecuada.
Una vez que se escribe la especificación se puede utilizar para seleccionar componentes y
tecnologías que se utilizarán para el proyecto. El diseño deberá hacerse siguiendo
métodos aceptados y confiables. El proceso de diseño es en general un ciclo, e incluye
varios pasos intermedios.
5.1.2 Verificación
La verificación engloba varios pasos menores, y al revisar pueden surgir cosas que
obligan a volver atrás hacia pasos anteriores. Dependiendo del dispositivo y tecnología
utilizada, pero en general sigue los siguientes pasos:
Cualquier problema o falla que se encuentre debe ser documentarse y analizada para
poder corregirla en una próxima versión del dispositivo y evitarla en el futuro.
En la figura, las flechas de líneas punteadas que vuelven al comienzo indican las
iteraciones que muchas veces se dan al trabajar en un diseño nuevo. Después de simularlo
o configurar un PLD, pueden descubrirse fallas o haber cambios de requerimientos que
obligan al diseñador a volver y modificar la descripción del diseño.
5.4.1 VHDL
Las siglas VHDL provienen de “VHSIC Hardware Description Lenguaje” y a su vez
VHSIC quiere decir “Very High Speed Integrated Circuit”. O sea que VHDL significa
lenguaje de descripción de hardware para circuitos integrados de alta velocidad. Sus
orígenes datan de la década de 1980. El departamento de defensa de Estados Unidos y el
IEEE patrocinaron un programa de desarrollo para un lenguaje con el que se pudieran
modelar circuitos integrados de alta complejidad. Un lenguaje de estas características
permitiría describir los circuitos para su documentación y además modelarlos y
evaluarlos mediante simulaciones antes de incurrir en los grandes gastos de fabricación.
El VHDL nació entonces como un lenguaje de modelado y documentación de sistemas
electrónicos digitales. El lenguaje se estandarizó mediante el estándar 1076 del IEEE en
1987 (VHDL-87). Este estándar fue extendido y modificado en 1993 (VHDL-93) y 2002
(VHDL-2002).
En la actualidad, VHDL se utiliza no solo para modelar circuitos electrónicos sino
también para crear, o sintetizar, nuevos circuitos. La capacidad de sintetizar circuitos a
partir de los modelos en VHDL (u otro lenguaje de descripción de hardware) surgió
después de la creación del lenguaje, con la aparición de herramientas que traducen los
modelos VHDL a circuitos reales.
5.4.2 Verilog
El lenguaje Verilog fue desarrollado por Gateway Design Automation en 1984. En 1988
Synposis presentó la primera herramienta de síntesis basada en Verilog. Más tarde
Cadence Design Systems adquirió Gateway Design Automation y luego “abrió” el
lenguaje para que otros proveedores pudieran desarrollar herramientas de simulación y
síntesis utilizando Verilog. En 1995 el lenguaje Verilog se transformó en un estándar del
IEEE. Mientras que la sintaxis del VHDL es parecido a los lenguajes de programación
Ada y Pascal, el Verilog proviene del C y tiene una sintaxis mas parecida a este.
5.4.3 Otros
En la actualidad los dos lenguajes mencionados, VHDL y Verilog, son los mas utilizados
para la síntesis automática de hardware. Hay mucho esfuerzo de investigación y
desarrollo (e incluso algunas herramientas comerciales) que aceptan la descripción de
algoritmos en otros lenguajes con un mayor nivel de abstracción.
Una de las líneas de desarrollo principales es la de poder describir los sistemas con un
nivel de abstracción mayor al RTL en un único lenguaje Después se especificarían las
restricciones necesarias para los resultados y las herramientas decidirían que parte
conviene implementar en hardware y que partes en software.
En general todas las herramientas actuales, aunque permiten describir o modelar los
sistemas con un lenguaje mas abstracto que el RTL terminan generando alguna versión
de código RTL antes de sintetizar un circuito.
5.5.3 Simulación
La simulación de un sistema descrito de modelos en HDL merece algunos comentarios.
Los lenguajes de descripción de hardware modelan o describen, mediante instrucciones
secuenciales, bloques de hardware que funcionarán de manera concurrente, es decir, al
mismo tiempo. Las señales de los bloques pueden afectarse mutuamente. Simular esto
tiene su complejidad, y dentro de los estándares que definen los lenguajes de descripción
de hardware VHDL y Verilog se especifica como se deben simular los procesos
concurrentes.
Es importante tener en cuenta que ninguna asignación de valores a una señal en hardware
será inmediata. Es decir, si se utiliza la operación X <= ‘1’ que indica la asignación un
valor lógico ‘1’ a la señal X, este cambio nunca se producirá inmediatamente, sino que
habrá un retardo (como mínimo de un retardo delta) para la asignación. Con esto en
mente, puede analizarse un ciclo de simulación en VHDL que se comporta de la manera
mostrada en la Figura 5.
Cuando los procesos están en un estado de reposo (todos los procesos en VHDL tienen
un estado de reposo) se incrementa el tiempo de simulación como para cambiar la señal
que tiene la próxima transición. Este retardo será el menor tiempo de todas las
asignaciones de señal hecha por los procesos, y puede ser un retardo delta o un tiempo
especificado por el código. Después de cambiar la(s) señal(es) se examinan nuevamente
los procesos para ver si esos cambios estimulan o disparan el comportamiento de algún
proceso o puede continuar la simulación. Si se dispara algún proceso, este se evalúa
nuevamente de la manera descrita anteriormente. Si no se dispara ningún proceso se
procede a incrementar el tiempo hasta la próxima transición de señal. Esto se repite hasta
llegar a un tiempo en la que no hay ninguna transición de señal y todos los procesos están
en reposo. Este proceso de simulación permite obtener resultados determinísticos.
C, X e Y. Todas las compuertas están definidas para no tener retardo de propagación, por
lo que el simulador usará el valor de un retardo delta. A los 50 ns de simulación la
entrada A pasa de ‘1’ a ‘0’.
El pulso de un delta tiene sentido ya que al estar definidos los retardos sobre las
compuertas al valor por defecto de un retardo delta, el tiempo de propagación a través de
dos compuertas (NAND-AND) es mayor que a través de una sola(AND), generando el
pulso (o “glitch”) en la salida C.
Los dispositivos actuales (CPLD y FPGAs) tienen una capacidad lógica de hasta millones
de compuertas, incluyen interfaces programables para varios estándares de interfase
eléctrica y tienen bloques de funciones especiales embebidos entre la lógica programable
tales como memoria, multiplicadores o CPUs completas. Esta gran capacidad y variedad
de los dispositivos los hace sumamente útiles a la hora de crear prototipos, desarrollo
rápido de nuevos productos, para los productos que deben ser reconfigurables por
naturaleza o productos que se producen en bajos volúmenes y para los cuales no es
económicamente viable crear un integrado a medida.
Uno de los factores más importantes para el auge de las FPGA es el conjunto de
herramientas disponibles. Entre los puntos a destacar de las herramientas de software
disponibles en el mercado pueden nombrarse los siguientes:
Los primeros dispositivos lógicos programables fueron las memorias PROM. Para ello se
utilizan como entradas las líneas de dirección a la memoria. De esta manera la memoria
provee una tabla de decodificación completa de las entradas, y puede utilizarse para
implementar cualquier función lógica combinacional.
La base teórica de estos dispositivos es que cualquier ecuación lógica puede reducirse a
una suma de productos. El corazón electrónico de estos dispositivos consiste en un
bloque que permite negar las entradas y dos niveles de compuertas: un nivel de
compuertas AND y un nivel OR. Mediante fusibles pueden programarse las
interconexiones entre las entradas y la lógica. Así los PLA permiten implementar
cualquier suma de productos de sus entradas. La Figura 7 muestra un esquema básico de
un típico dispositivo PLA.
dado, así que los fabricantes de PAL los ofrecían en una variedad de configuraciones para
adecuarlos a las necesidades del usuario. Muchos PAL además incorporaron registros
sobre las salidas y realimentación para implementar circuitos secuenciales. La Figura 8
muestra un esquema de una posible configuración de un PAL.
Los dispositivos denominados GAL son un poco mas complejos que los PAL
mencionados anteriormente. Incluyen un nivel de lógica AND a la entrada y luego un
bloque lógico denominado macrocelda a la salida, en reemplazo del nivel OR. La
denominación GAL fue utilizada en principio por Lattice, y luego licenciada a otros
fabricantes. Las Figura 9 y Figura 10 muestran el diagrama funcional de una GAL
completa y de una macrocelda de un dispositivo GAL22V10 de Lattice Semiconductors.
La macrocelda de estas GAL se denomina OLMC, por "Output Logic Macro Cell".
Figura 10 - Diagrama funcional de una macrocelda del GAL 22V10 de Lattice Semiconductors
(Fuente: hoja de datos de Lattice Semiconductors GAL 22V10 - www.latticesemi.com)
6.2 CPLDs
Los CPLDs son dispositivos que combinan varios bloques lógicos similares a las PAL o
GAL con una matriz de interconexión programable. Estos dispositivos se fabrican con
distintas capacidades para adaptarlos a las necesidades del usuario. Como ejemplo, la
familia MAX7000 de alto rendimiento de Altera se manufactura en versiones desde 32
hasta 512 macroceldas, con 36 a 212 entradas/salidas según el dispositivo y
empaquetamiento (packaging) que se elija. Las Figura 11 y Figura 12 muestran la
estructura general y una macrocelda de estos CPLDs. Como se de las figura, estos
dispositivos incluyen además de las macroceldas, un arreglo de interconexión
programable (PIA), una red de distribución de reloj dedicada y bloques de entrada salida
que permiten interfases compatibles con diferentes estándares eléctricos. Los bloques
lógicos AND y OR están ambos incluidos en la macrocelda del dispositivo.
6.3 FPGAs
La arquitectura de una FPGA consiste en arreglos de bloques lógicos que se comunican
entre si a través de canales de conexión verticales y horizontales. La Figura 13 muestra
un esquema de esta estructura. La principal diferencia entre las FPGA y CPLDs es que en
general los bloques lógicos de las FPGA no implementan la lógica usando compuertas
sino con generadores de funciones. En la siguiente sección se estudiará en mayor detalle
la arquitectura de una FPGA típica.
En las Figura 14 se muestra la arquitectura general de una FPGA de la familia Spartan IIe
de Xilinx. Esta FPGA contiene cinco elementos principales:
Además de los bloques lógicos básicos, que ocupan la mayor parte de las FPGAs (CLBs,
Logic Array, Logic Tile, etc.), estos dispositivos constan de bloques que cumplen ciertas
funciones específicas. En las siguientes subsecciones se presentan en mayor detalle
algunos de los bloques o módulos específicos que pueden conformar una FPGA. No
todos los bloques se encuentran en todas las FPGA, aunque casi todas tienen la
estructura general presentada al principio de esta sección. La arquitectura específica de
cada FPGA dependerá del fabricante y la aplicación a la que está orientada.
Figura 17 –Esquema del bloque lógico configurable de una FPGA Spartan IIe de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 2e www.xilinx.com)
Cada CLB esta compuesto por dos bloques iguales denominados “slices”. Cada "slice"
contiene dos generadores de funciones y un multiplexor MUXF5. El multiplexor combina
los resultados de los generadores de funciones dentro de cada "slice" del CLB.
Las dos "slices" están unidas por un multiplexor MUXF6, que puede seleccionar la salida
de una u otra “slice” hacia la salida del CLB. Esto permite implementar cualquier función
de 6 entradas, un multiplexor de 8:1 o determinadas funciones lógicas de asta 19
entradas. Además de poder implementarse lógica combinacional, cada “slice” contiene
Figura 18 - Esquema interno de medio bloque lógico configurable de una Spartan 2e de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 2e www.xilinx.com)
En esta figura se ven los generadores de funciones, compuesto por una tabla de entrada-
salida (LUT o Look-Up Table) de cuatro entradas y una salida. Estas tablas pueden
implementar cualquier función lógica de cuatro entradas y una salida, así como también
utilizarse como memorias distribuidas de 16 x 1 bit. Las salidas de las LUT pasan a los
bloques de control, que contiene lógica que permite optimizar funciones aritméticas. Los
Figura 21 –Distribución de los bancos de entrada/salida en una FPGA Spartan IIe de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 2e www.xilinx.com)
La siguiente tabla muestra el valor de VccO para las diferentes interfases lógicas.
Tabla 2 - Tensión VccO para diferentes interfases lógicas de la familia Spartan IIe de Xilinx
Valor de VccO Lógica de interfase
3.3V PCI, LVTTL, SSTL3 I, SSTL3 II, CTT, AGP, LVPECL, GTL, GTL+
2.5V SSTL2 I, SSTL2 II, LVCMOS2, LVDS, Bus LVDS, GTL, GTL+
1.8V LVCMOS18, GTL, GTL+
1.5V HSTL I, HSTL III, HSTL IV, GTL, GTL+
Además de la tensión VccO, para varios de las interfases lógicas debe configurarse la
tensión de referencia VREF y agregarse resistencias de terminación sobre la plaqueta en
las entradas-salidas de la FPGA. Cada bloque de entrada-salida tiene una resistencia de
“pull-up” y “pull-down” configurables que permiten fijar el valor lógico mediante
programación.
Figura 22 - Esquema de un bloque de entrada-salida (IOB) de una FPGA Spartan IIe de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 2e www.xilinx.com)
La familia Spartan IIe de Xilinx tiene bloques específicos para control de reloj
denominados DLL (Delay Locked Loop). La Figura 25 muestra un esquema básico de la
estructura de un DLL. Estos bloques sincronizan el reloj interno al reloj externo del
sistema, controlan el desplazamiento de fase entre los relojes, sincronizan los diferentes
dominios de reloj y aseguran un retardo de distribución del reloj pareja para la lógica
interna de la FPGA.
Figura 25 –Esquema básico de un bloque de control de reloj de la FPGA Spartan IIe de Xilinx
(Fuente: hoja de datos Xilinx Spartan 2e www.xilinx.com)
La familia Stratix de Altera tiene los bloques de control de reloj que se muestran en la
Figura 26.
Estos bloques (Enhanced PLL) permiten controlar la fase y frecuencia del reloj, el
sistema de distribución de reloj y el estándar eléctrico de interfase entre otras cosas.
6.3.4 Memoria
La memoria es un componente muy utilizado en diseños digitales. Varias familias de
FPGA contienen bloques de memoria embebida integrados con la lógica programable. En
general estos bloques básicos de memoria pueden utilizarse en diferentes configuraciones
para generar RAMs y ROMs de diferentes tamaños. Además de memorias embebidas, las
FPGAs basadas en memoria SRAM pueden usar las tablas LUT de los bloques lógicos
como memoria.
Estos bloques de memoria pueden usarse como memorias de puerto dual, puerto simple,
RAMs o ROMs. Para entender la versatilidad de estos bloques de memoria, en la
siguiente tabla se muestran las opciones de configuración. Las interfases de dirección y
datos (ADDRA, ADDRB, DIA, DOB, DOA) se pueden configurar para diferentes
tamaños de memoria.
Tabla 3 - Posibles configuraciones de las celdas de BLOCK RAM de la familia Spartan IIe de Xilinx
Ancho de la palabra de Profundidad de Bus de Bus de datos
datos (bits) la memoria direcciones
1 4096 ADDR<11:0> DATA<0>
2 2048 ADDR<10:0> DATA<1:0>
4 1024 ADDR<9:0> DATA<3:0>
8 512 ADDR<8:0> DATA<7:0>
16 256 ADDR<7:0> DATA<15:0>
Además de poder configurar cada bloque, varios bloques pueden conectarse utilizando
lógica externa para implementar memorias de otros tamaños y colas FIFO o FILO.
lógica de propósito general. Al igual que los otros bloques, los bloques específicos
pueden interconectarse a los demás bloques utilizando la matriz de intercone3xión
programable de la FPGA.
Los recursos de interconexión local, mostrados en la Figura 31, permiten hacer las
conexiones entre los elementos internos de un bloque lógico o CLB, como las tablas de
búsqueda (LUT), los flip-flop y las realimentaciones dentro del CLB. Además, el
interconexionado a este nivel provee conexiones a la matriz de interconexionado general
y a los CLB adyacentes. Las conexiones a los CLB adyacentes permiten optimizar los
diseños al evitar los retardos y la utilización de recursos de la matriz general de
interconexionado.
Algunos dispositivos tienen arquitecturas con celdas lógicas que pueden implementar
funciones lógicas complejas, de varias entradas/salidas. A estas se las denomina de
granularidad gruesa. Otras arquitecturas están formadas por celdas básicas que solo
permiten implementar lógica muy simple. A estas se las denomina de granularidad fina..
Un bloque lógico grande puede implementar lógica más compleja y por lo tanto se
necesitan menos bloques para una función dada. Por otro lado cada bloque consume más
área que puede desaprovecharse.
Una arquitectura de granularidad fina será típicamente más densa y tendrá menor retardo
de interconexión entre celda y celda. Sin embargo, para una función dada, se deberán
conectar un mayor número de celdas. En general la mejor granularidad dependerá de la
aplicación y las restricciones que hay sobre el diseño. Para una FPGA basada en tablas de
búsqueda (Look Up Table o LUT) la mejor relación entradas salidas del bloque lógico es
4 a 1. Esto es lo que utilizan los dos fabricantes principales de FPGAs basados en
tecnología SRAM. Para mayor información ver la sección Referencias.
Arquitecturas mixtas
• Combinan celdas con granularidad fina y gruesa
• Muchas veces tienen recursos de interconexión dedicados para cada tipo de
celda
• Ejemplo: ispXPGA de Lattice Semiconductors
SRAM: Virtex II, Virtex4, Spartan2e, Spartan 3 de Xilinx. Stratix, Cyclone y Apex de
Altera
Flash: Actel ProAsic, ProAsicPlus
Antifusible: Actel A54SX, Quicklogic pAsic
EEPROM: Altera MAX7000, Cypress Ultra37000
EEPROM + SRAM: Lattice Semiconductor ispXPGA
En los primos años probablemente se verá una mayor incorporación de las lógicas
programables en los diseños, junto a una mayor variedad, diversidad, nuevas ideas y
diseños basados en lógicas y plataformas programables.
refiere al lector a los sitios web de los fabricantes de FPGAs listados al final de las notas.
La presentación anterior debería servir para poner en tema al lector y presentarle los
conceptos básicos sobre estas tecnologías. Para obtener mas detalles referirse a las
páginas web de los fabricantes (Ver referencias).
En general es una buena práctica mantener el mismo formato a través de todo el diseño y
por todos los miembros del equipo. En este texto se usarán palabras reservadas en
minúscula con algunas palabras especiales en mayúscula.
Ejemplos:
-- A<= ‘1’ Esto es un comentario de una línea completa. No hace nada
A <= ‘1’; -- Esto es una asignación de la señal a con un comentario al final
-- Esto es un comentario que me dará error porque
pasa a la otra línea y el analizador de VHDL no entiende la segunda línea
En VHDL no existen los comentarios multi-línea, y debe comentarse línea por línea si se
quiere comentar un bloque completo de código
Ejemplos:
A <= ‘1’; -- Una asignación a la señal A
Los bloques lógicos en VHDL se delimitan por las palabras reservadas begin y end.
Ejemplos:
-- Definición de una arquitectura
architecture Comportamiento of Contador is
begin
-- Instrucciones que modelan la arquitectura
end architecture Comportamiento;
-- Definición de un proceso
P_IncrementoCuenta : process(Clock_IN)
begin
-- Instrucciones que definen el proceso
end process; --Se debe cerrar con la palabra reservada process
entity Contador is
port(
Reset_IN : IN std_logic;
Clock_IN : IN std_logic;
Cuenta_OUT : OUT std_logic_vector(5 downto 0)
);
end Contador;
La palabra reservada entity especifica que comienza con la declaración de una entidad de
hardware. Esta entidad tendrá el nombre “Contador”.A continuación se definen las
señales de interfase mediante la palabra port.
Los tipos de señales de interfase o “ports” pueden tener los siguientes modos:
• IN Señal de entrada al componente
• OUT Señal de salida del componente
• INOUT Señal bidireccional. Usada para interfases de tres estados.
• BUFFER Señal de salida que puede leerse internamente. No recomendada
para diseños sintetizables.
En general, los tipos de los “ports” que se recomiendan para diseños sintetizables son
std_logic y std_logic_vector1, que definen señales de 1 bit o varios bits de ancho
respectivamente.
La entidad termina con la palabra reservada end. Notar el uso del “;” para terminar cada
instrucción y su uso en la separación de la declaración de las señales de interfase.
La descripción del funcionamiento del componente se define en la segunda sección de
definición del componente, denominada arquitectura. De la misma manera que una
función en hardware puede ser diseñada de diferentes maneras, el comportamiento de un
componente puede modelarse de muchas maneras diferentes en VHDL.
-- .........
1
Los tipos std_logic y std_logic_vector están definidos en librerías estándar de IEEE que se describirán
más adelante.
Para el siguiente ejemplo, se supone que hay una entidad “LogicaVaria” declarada que
tiene varias entradas y cuya salidas son funciones lógicas AND y OR de las entradas. A
continuación se muestran dos posibles arquitecturas de comportamiento para este
componente.
);
component CompuertaOr
port(EntradaOr1_IN : IN std_logic;
EntradaOr2_IN : IN std_logic;
SalidaOr_OUT : OUT std_logic;
);
ComponenteBasicoAnd : CompuertaAnd
port map (EntradaAnd1_IN => Entrada1_IN,
EntradaAnd2_IN => Entrada2_IN,
SalidaAnd_OUT => SalidaAnd_OUT
);
ComponenteBasicoAnd : CompuertaOr
port map (EntradaOr1_IN => Entrada1_IN,
EntradaOr2_IN => Entrada2_IN,
SalidaOr_OUT => SalidaOr_OUT
);
En este ejemplo se conectaron dos componentes básicos que implementan una compuerta
AND y una OR de dos entradas y una salida para definir el funcionamiento del
componente LogicaVaria. Notar el símbolo de conexión “=>” (diferente al de asignación
para señales “<=” ) y el uso de los separadores “,” entre los diferentes puertos de los
componentes básicos. Otra cosa que se debe destacar es que no hay ningún problema en
que las señales o puertos de varios componentes en la jerarquía tengan el mismo nombre,
como puede verse en la conexión de las señales de salida.
ComponenteBasicoAnd : CompuertaAnd
port map (EntradaAnd1_IN => Entrada1_IN,
EntradaAnd2_IN => Entrada2_IN,
SalidaAnd_OUT => open
);
abs, access, alter, alias, all, and, architecture, array, assert, attribute
begin, block, body, buffer, bus
case, component, configuration, constant
disconnect, downto
else, elsif, end, entity, exit
file, for, function
generate, generic, group2, guarded
if, impure2, in, inertial2, inout, in, is
label, library, linkage, literal2, loop
map, mod
nand, new, next, nor, not, null
of, on, open, or, others, out
package, port, postponed2, procedure, process, protected2,3, pure2
range, record, register, reject2, rem, report, return, rol2, ror2
select, severity, shared2, signal, sla2, sll2, sra2, srl2, subtype
then, to, transport, type
unaffected2, units, until, use
variable
wait, when, while, with
xnor2, xor
Cuadro 6 Palabras reservadas de VHDL
Los operadores pueden sobrecargarse y tener diferentes significados para diferentes tipos
en diferentes librerías.
2
Estas no son palabras reservadas en VHDL-87
3
Estas no son palabras reservadas en VHDL-93
7.3.3 Identificadores
Los identificadores se utilizan para dar nombre a los elementos de un diseño, ya sea
señales, variables o cualquier otro elemento del diseño.
Los identificadores pueden utilizar los caracteres alfanuméricos y el guión bajo “_”.
Deben comenzar con una letra y no pueden tener mas de dos guiones bajos seguidos ni
terminar con un guión bajo. Recordar que no deben usarse palabras reservadas como
identificadores y que VHDL no diferenciará identificadores solo por las mayúsculas.
Ejemplos:
constant UTN_CUENTA_MAXIMA : integer := 56; -- Una constante
signal CuentaDeReloj_REG : std_logic_vector(3 downto 0); -- Una señal
variable CuentaModulo1_VAR : std_logic_vector(3 downto 0); -- Una variable
7.3.4 Números
Los números pueden representarse en diferentes bases y formatos. Hay dos tipos básicos
de números, los enteros (integer) y reales (real). Se puede usar notación exponencial con
ambos tipos de número. Los números pueden representarse en cualquier base de 2 a 16
usando #.
Hay cuatro clases de objetos en VHDL: constantes, variables, señales y archivos. El tipo
de un objeto es muy importante, ya que no solo define que valores podrá tomar, sino
también que operaciones se pueden realizar sobre él.
4
A diferencia del C que tiene tipos débiles y en el que pueden asignarse valores de un tipo diferente al
declarado para las variables (tales como asignar a una variable del tipo float un valor int).
Ejemplos:
type tdDiaDelMes is range 0 to 31;
type tdHorasDelDia is range 0 to 23;
Mas ejemplos de tipos:
type tdMinutos is range 0 to 59;
type tdUnTipoRaro is range 59355 downto -456;
Ejemplos:
type tdCPUCycle is (fetch, decode, execute1, execute2);
type tdCicloLectura is (comienzo, lectura, fin);
type tdOctal is (‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ’6’, ‘7’);
type tdLogica3Estados is (‘0’, ‘1’, ‘Z’);
7.4.4 Subtipos
Así como se pueden definir nuevos tipos, fácilmente se pueden definir subtipos a partir
de tipos ya declarados. La siguiente expresión permite hacer esto.
7.4.6.1 Arreglos
Un arreglo (array) es una colección de valores todos del mismo tipo. Se describe la
declaración de tipos arreglos con varios ejemplos. Aunque todavía no se han descrito los
objetos variable y constant se usan para ayudar a entender como se accede a los
elementos de un arreglo.
Ejecucion => 0,
others => 0); -- Queda solo Espera
Cuadro 12 Arreglos
El valor de los índices o rango se dan al declarar un objeto como se muestra en los
ejemplos
Ejemplos:
-- string. No usado en diseños sintetizables
constant Cadena: string (0 to 10); -- Rango definido explicitamente
variable Cadena: string := “Cadena de caracteres “; -- Rango definido
-- de manera implícita
7.4.6.3 Records
Un record es una colección de valores que no deben ser todos del mismo tipo. Se
presentarán mediante un ejemplo en el cuadro siguiente.
Ejemplos:
unsigned’(“01001”) -- “01001” puede interpretarse como signed o unsigned
tdNivelLogico’(high) -- Si tdNivelLogico es un subtipo de tdNivelValido que
-- también puede tomar el valor high
Como VHDL es un lenguaje con tipos fuertes, cuando se necesita convertir de un tipo a
otro se debe especificar una conversión explícitamente. Esto se hace utilizando el tipo al
que se quiere convertir seguido del valor de otro tipo entre paréntesis.
Ejemplos:
real(3) -- Para convertir el entero 3 a real
integer (4.5) -- Para redondear el real 4.5 a entero
7.5.1 Constantes
Las constantes son tipos en las que se almacenan datos que no cambian. Como su nombre
lo indica, se mantienen constantes en el tiempo. Las constantes se utilizan para poder
asignar tipos definidos a valores. Se utilizan para parametrizar valores que se repetirán en
distintos lugares del diseño y evitar “números mágicos”, que aparecen en el código pero
no se entiende bien que significan ni que tipo tienen. En vez de esto, puede definirse un
paquete que contenga todas las constantes usadas en el proyecto, con tipos nombres que
tengan sentido al leer el código.
-- Declaración de constantes
-- El formato usado en este ejemplo para los
-- identificadores de constantes es el recomendado
-- en varias guías de código VHDL
7.5.2 Señales
Las señales son la representación de las conexiones de hardware que toman valores
lógicos. En general deben utilizarse señales al hacer un diseño que será sintetizado. Los
tipos de señales mas utilizados son los mostrados en las declaraciones del cuadro. Estos
tipos se han definido por un estándar del IEEE que se describe más adelante. EL
operador para asignación de valores a una señal es el símbolo “<=”.
En simulación las señales toman sus valores un delta de tiempo después de que se ejecuta
la instrucción, como se explicara en la sección 5.5.3. Al sintetizar un circuito, la
asignación puede verse como una conexión física, o un cable.
7.5.3 Variables
Las constantes pueden almacenar datos para utilizarlos en el modelo. Se asemejan a las
variables de otros lenguajes de programación. Las variables toman los valores
instantáneamente al asignarse en el código. El operador de asignación para las variables
es “:=”. Para diseños sintetizables se recomienda utilizar señales, pero las variables son
muy útiles al diseñar bancos de prueba.
-- Declaraciones de variables
variable A : integer;
variable B : integer := 56;
variable C : natural := 2#100_0111;
variable ValorMaximo_VAR : std_logic_vector(1 downto 0);
variable TiempoDeEspera : time := 0 ns;
7.6.1 Librerías
Una librería se define como una colección de unidades de librería. Dependiendo de la
herramienta y el sistema operativo de la computadora que se utilice una librería puede ser
una carpeta directorio o una base de datos que contenga los nombres de las entidades y
arquitecturas que le pertenecen. Esto significa que una librería es solo una manera de
agrupar diferentes unidades para organizarlas, darles una jerarquía y poder reutilizarlas de
una manera ordenada. VHDL reserva el nombre de librería work para la librería del
diseño actual.
library CompuertasBasicas;
La localización de la librería no está especificada por VHDL sino por la herramienta que
se está utilizando. Por ejemplo, la herramienta puede tener un menú donde se seleccionan
las librerías y se especifica el lugar dentro del disco rígido donde estas se localizan. Esa
información luego queda guardado en una base de datos para poder procesarla cuando el
analizador encuentra la directiva library en el VHDL.
-- Declaración de un paquete
package NombrePaquete is
-- Declaraciones de constantes
constant ... ;
-- Declaraciones de tipos
type ... ;
subtype ... ;
-- Declaraciones de señales
signal ...
-- Declaraciones de subprogramas
function F1(...) return ... ;
function F2(...) return ... ;
...
end package NombrePaquete;
-- ----------------------------------------------------- --
-- Definición del cuerpo del paquete
function F2(...) is
...
Las señales que se definen en un paquete serán globales y podrán accederse por cualquier
entidad que utilice el paquete. Lo mismo sucede con los tipos y constantes definidas en el
paquete. Estas podrán ser utilizadas en cualquier archivo en el que se incluya el paquete.
Para utilizar la lógica 1164 del IEEE o los paquetes numéricos estándar con las
operaciones aritméticas sobre la lógica estándar se debe agregar el use de los paquetes
adecuados.
A partir de esta lógica también se define el subtipo std_logic. Este tipo es lo que se
denomina lógica resuelta ya que incluye funciones que definen que pasa cuando varias
salidas se conectan a una señal.
Los valores débiles y forzados se incluyen para poder modelar hardware que tiene
diferentes capacidades de controlar una señal. Por ejemplo, si una señal tiene un buffer de
tres estados que la maneja (posibles valores ‘0’, ‘1’ y ‘Z’) y además una resistencia de
“pull-up” a la tensión de alimentación con un valor alto (valor ‘H’). Si la salida del buffer
es alta impedancia (‘Z’) el valor de la señal estará dado por la resistencia, pero si el buffer
tiene una salida lógica, esta forzará el valor de la señal mas allá de la resistencia de “pull-
up”.
Estos tipos se nos permite modelar señales y buses de diferentes anchos. Los tipos
std_logic y std_logic_vector son los recomendados para su uso y son los que se usarán
en los ejemplos de este texto.
En la arquitectura, antes de la palabra begin se definen todas las señales internas que se
utilizarán en el modelo. Después de la palabra begin recién comienza una serie de
operaciones que concurrentes que se ejecutarán en paralelo. Esto permite modelar el
verdadero funcionamiento del hardware ya que en general habrá muchas tareas
ejecutando en paralelo e interactuando entre sí.
entity Componente is
port(
…
Declaración de puertos de entrada salida
…
);
5
Si existe más de una arquitectura para una entidad todas deberían estar definidas en el mismo archivo.
end Componente;
-- ---------------------------------------------------- --
architecture Comportamiento of Componente is
…
Declaración de señales internas del componente
…
begin – Comienzo de la especificación del comportamiento
-- En esta sección se define el comportamiento
-- utilizando las construcciones de VHDL necesarias
-- según el modelo que se implemente
…
Serie de operaciones concurrentes:
…
Operación concurrente 1 (proceso u operación aislada)
…
Operación concurrente 2 (proceso u operación aislada)
…
proceso A
…
Declaración de variables internas del componente
begin -- Comienzo de las instrucciones secuénciales del proceso
…
operaciones secuenciales
…
end process;
proceso B
…
Declaración de variables internas del componente
begin -- Comienzo de las instrucciones secuénciales del proceso
…
operaciones secuenciales
…
end process;
…
end architecture Comportamiento;
Algo importante a tener en cuanta para diseños sintetizables sobre PLDs es que a una
señal se le debe asignar un valor en solo una operación concurrente. Es decir, dos
operaciones concurrentes no pueden tratar de asignar un valor a la misma señal. Si se
piense que significaría esto en hardware se vería que habría dos o mas componentes o
elementos lógicos con sus salidas conectadas a la misma señal.
Todas las operaciones mostradas dentro de la arquitectura del siguiente cuadro son
concurrentes, eso significa que no importa en que orden se escriban ya que se evaluarán
todas al mismo tiempo.
library ieee;
use ieee.std_logic_1164.all; -- Lógica estándar
entity Logica2Entrdas is
port (
Entrada1_IN : IN std_logic;
Entrada2_IN : IN std_logic;
SalidaAnd_OUT : OUT std_logic;
SalidaOr_OUT : OUT std_logic;
SalidaNand_OUT : OUT std_logic;
SalidaNor_OUT : OUT std_logic -- No hay ; aquí
);
end Logica2Entrdas;
begin
-- Operaciones concurrentes que modelan flujo de datos
SalidaAnd_OUT <= intSalidaAnd;
SalidaOr_OUT <= intSalidaOr;
SalidaNand_OUT <= not intSalidaAnd;
SalidaNor_OUT <= not intSalidaOr;
-- ----------------------------------------------------- --
library ieee;
use ieee.std_logic_1164.all; -- Lógica estándar
use ieee.std_logic_arith.all; -- Lógica estándar
entity Logica2Entrdas is
port (
Entrada1_IN : IN std_logic;
Entrada2_IN : IN std_logic;
SalidaAnd_OUT : OUT std_logic;
SalidaOr_OUT : OUT std_logic;
SalidaNand_OUT : OUT std_logic;
SalidaNor_OUT : OUT std_logic -- No hay ; aquí
);
end Logica2Entrdas;
begin
-- Operaciones concurrentes que modelan flujo de datos
SalidaAnd_OUT <= intSalidaAnd;
SalidaOr_OUT <= intSalidaOr;
SalidaNand_OUT <= not intSalidaAnd;
SalidaNor_OUT <= not intSalidaOr;
Deben especificarse todos los casos, y para ello es conveniente usar la palabra others
para asignar los valores que faltan y completar los casos. Se debe tener en cuenta que los
valores posibles de las señales del tipo std_logic no son solo ‘1’ y ‘0’, sino que hay otros
tales como ‘Z’, ‘U’. Eso hace que haya más combinaciones posibles en un select que las
esperadas. Como no tiene sentido preguntar por opciones como ‘Z’ o ‘U’ ya que esto no
es sintetizable y probablemente ni siquiera tenga sentido durante simulaciones, la palabra
others debe incluirse siempre para el último caso y así evitar problemas.
Otro puno importante es que muchas herramientas aceptan el valor ‘X’ para las señales
de salida. Esto se muestra en el Ejemplo 2, y permite que se optimice la lógica en el
momento de la síntesis.
En el ejemplo 1 se modela una lógica de asignación que toma decisiones sobre una sola
señal de control. Muchas herramientas reconocerán en esto un multiplexor y lo
sintetizarán como tal, pero no es la manera recomendable de modelarlo, ya que las
palabras else indican prioridad. En esta operación no es necesario especificar todos los
casos, pero debe tenerse en cuanta que al no hacerlo se inferirá un match para guardar el
valor de salida anterior.
Las condiciones de asignación a su vez no deben ser necesariamente sobre la misma señal
de control, y esto se muestra en el ejemplo 2. En este caso no se infiere un multiplexor
sino que se genera lógica combinacional con prioridades para implementar el circuito
modelado. La segunda condición se prueba solo si no se cumple la primera, la tercera si
no se cumplen ni la primera ni la segunda, y así hasta llegar a la última. Si ninguna de las
condiciones se cumple se mantendrá el valor anterior utilizando un “latch”. Para evitar
este “latch“ se debe incluir el último else sin condición final y asignar un valor por
defecto.
-- --------------------------------------------------------- --
-- wait on ...
SenalAccion_OUT <= ‘1’;
wait on PulsoRespuesta_IN; -- Espero un cambio en la entrada
-- --------------------------------------------------------- --
-- wait for ...
wait for 10 ns; -- Suspende 10 nanosegundos
wait for 40 ms; -- Suspende 40 milisegundos
-- --------------------------------------------------------- --
-- wait for y wait solo
--
-- Generación de un pulso de 200 ns
Reset_OUT <= ‘1’; -- Pulso de la señal reset en ‘1’
wait for 230 ns; -- Ancho del pulso es 230 ns
Reset_OUT <= ‘0’; -- Señal reset a ‘0’
wait; -- Suspende para siempre. El reset queda
-- en el ultimo valor asignado (‘0’)
-- --------------------------------------------------------- --
-- wait until ...
SenalAccion_OUT <= ‘1’;
wait until (PulsoRespuesta_IN = ‘1’); -- Espero que la entrada
-- se haga ‘1’
-- ... condiciones mas complejas...
wait until (Senal1 = ‘0’ and Entrada2 = ‘0’);
6
La expresión wait es sintetizable solo en procesos sincrónicos que usan el wait para esperar un evento en
la señal de reloj, como se detallará en la sección 0.
else
... –- Instrucciones que se ejecutan solo si no se da
-- ningún caso de las condiciones anteriores
end if;
-- Ejemplos de instrucciones if
-- --------------------------------------------------------- --
-- Una sola condición
-- --------------------------------------------------------- --
-- if, elsif
-- --------------------------------------------------------- --
-- if, else
-- Detecto el signo de una entrada y lo guardo a un registro
if (DatoEntrada_IN(MSB) = ‘0’) then
Signo_REG <= ‘0’;
else
Signo_REG <= ‘1’;
end if;
-- --------------------------------------------------------- --
-- if elsif else
-- Un ejemplo raro que no modela nada
if (Control_IN = “00”) then
Salida_REG <= Entrada0_IN;
elsif (Entrada1_IN = “0100”) then
Cualquiercosa_REG <= ”1100000”;
elsif (Cualquiercosa_REG = ”1111111”) then
TodosUnos_OUT <= ‘1’;
else
Salida_REG <= Entrada3_IN;
end if;
-- --------------------------------------------------------- --
-- if else anidados
if (Control_IN = CONTROL_LEO_SIGNO) then
if (DatoEntrada_IN(MSB) = ‘0’) then
Salida_REG <= ‘0’;
else
Salida _REG <= ‘1’;
end if;
elsif (Control_IN = CONTROL_LEO_LSB) then
Salida_REG <= DatoEntrada_IN(0);
else
Salida_REG <= ‘0’;
end if;
-- --------------------------------------------------------- --
-- Todos los casos
-- Esto implementa un multiplexor usando if (la instrucción
-- case es la mas recomendada en estos casos)
if (Control_IN = “00”) then
Salida_OUT <= Entrada0_IN;
elsif (Control_IN = “01”) then
Salida_OUT <= Entrada1_IN;
elsif (Control_IN = “10”) then
Salida_OUT <= Entrada2_IN;
else
Salida_OUT <= Entrada3_IN;
end if;
-- --------------------------------------------------------- --
-- Ejemplo para una máquina de estado
...
-- Declaración del tipo para estados
type tdEstado is (
EsperarDato,
LachearDato,
PulsoAlADC
);
...
-- Declaración de estado actual y siguiente
signal EstadoActual : tdEstado ;
signal EstadoSiguiente : tdEstado ;
...
-- CASE dentro de un proceso combinacional que asigna el
-- próximo estado según el estado actual y las entradas.
-- El estado inicial y la asignación de EstadoSiguiente a
-- EstadoActual se hacen en otro proceso sincrónico con reset
case EstadoActual is
when EsperarDato =>
if (ADCDataAvailable_IN = '1') then
El uso de null en la segunda expresión case significa no hacer nada. Se debe tener en
cuanta que no hacer nada significa mantener el valor de salida anterior, y esto implica
generar latches o realimentar señales adicionales. Si lo que realmente sucede es que no
importa que valor tenga la señal se con esa combinación del case, puede dejarse algún
caso deseado como caso por defecto y así simplificar la lógica generada.
7
La asignación de señales en simulación siempre tiene un retardo mínimo de al menos un retardo delta,
como se describe en la sección 5.5.3.
En simulación, los procesos permanecen inactivos hasta que algún evento los hace
ejecutar. Un evento se entiende como un cambio en el valor de una señal. Los procesos se
dicen que son “sensibles” a las señales que causan su ejecución, y hay varias maneras de
especificar cuales serán las señales que causan que un proceso ejecute. Al sintetizar el
diseño, los procesos se implementarán como circuitos combinacionales o secuenciales
que efectúan la operación modelada. Los circuitos implementados producirán cambios en
sus salidas ante eventos en las señales a las que son “sensibles”.
Instrucciones secuenciales: Estas están entre las palabras begin y end. Todas las
instrucciones secuenciales de un proceso se ejecutarán como un bloque en paralelo con
los otros procesos y demás expresiones concurrentes.
Al diseñar circuitos para sintetizar sobre lógicas programables (FPGAs, CPLDs u otros
PLDs) es mejor que los modelos en VHDL se adapten a la lógica básica de los PLDs. No
hacerlo significa en muchos casos generar lógica adicional que ocupará mayor cantidad
de recursos del PLD innecesariamente. En algunos casos puede ser que el proceso
directamente no pueda sintetizarse. El cuadro muestra los patrones (templates) de
procesos recomendados para diseños sintetizables.
-- --------------------------------------------------------- --
-- PROCESO 2
-- --------------------------------------------------------- --
-- Este proceso genera solo lógica combinacional
--
-- --------------------------------------------------------- --
-- PROCESO 3
-- --------------------------------------------------------- --
-- Este proceso se sintetiza como flip-flops + lógica
-- combinacional.
--
Proceso3 : process (Clock_IN) -- Solo el reloj en la
-- lista de sensibilidad
begin
if Rising_edge(Clock_IN) then -- Solo se evalúa flanco de reloj
...
... -- Instrucciones secuenciales sincrónicas
...
end if;
end process Proceso3;
-- --------------------------------------------------------- --
-- PROCESO 4
-- --------------------------------------------------------- --
-- Este proceso se sintetiza como flip-flops + lógica
-- combinacional.
-- Contiene solo lógica sincrónica. Es equivalente al Proceso 3
--
Proceso4 : process – Sin lista de sensibilidad
begin
wait until Rising_edge(Clock_IN); -- Espera un flanco de reloj
...
... -- Instrucciones secuenciales sincrónicas
...
end process Proceso4;
-- --------------------------------------------------------- --
-- PROCESO 5
-- --------------------------------------------------------- --
-- Este proceso se sintetiza como un latch transparente +
-- lógica combinacional.
--
Proceso5 : process (Entrada1, ...) –- Todas las entradas a la
-- lógica en la lista
begin
if Enable = '1' then
...
... -- Instrucciones secuenciales con latch
...
end if;
end process Proceso5;
X <= ‘1’;
if (X = ‘1’) then
Y <= ‘0’;
else
Y <= ‘1’;
end if;
X <= ‘0’;
Cuadro 35 Retardos delta en procesos secuenciales
‘0’ a X y ‘1’ a Y. Es decir, nunca se asigna el valor ‘1’ a X de la primer instrucción. Por
supuesto el circuito sintetizado de estas instrucciones se comportará de la misma manera.
En el siguiente capítulo se presentarán ejemplos de circuitos sintetizados para mostrar
como se implementa en hardware una secuencia de instrucciones como la recién
descriptas.
Los tipos, constantes y en general todas las declaraciones dentro de un paquete serán
visibles en todo el componente que los use. Para que sean visibles se deben usar antes de
la declaración de entidad o arquitectura respectivamente. Una excepción a esto es cuando
se usan dos paquetes que declaran un objeto con el mismo identificador. Por ejemplo, si
en el ejemplo anterior el usuario declara un tipo std_logic en el paquete “Constantes”, no
podrá usarse ese tipo sin declarar explícitamente a que librería se está haciendo
referencia. Esto se hace usando el nombre de la librería, paquete y tipo separado por “.”
de la siguiente manera:
Las constantes genéricas no han sido descriptas todavía, pero tienen una visibilidad que
abarca la declaración de interfase y toda la arquitectura del componente.
Las señales de interfase declaradas en la entidad con port serán visibles dentro de toda la
arquitectura definida para esa entidad.
Las declaraciones de tipos, constantes y señales hechas en una arquitectura serán visibles
para toda la arquitectura. Es decir que estas señales podrán usarse en cualquier proceso o
construcción concurrente dentro de la arquitectura.
Las variables declaradas en cada proceso tendrán una visibilidad local a cada proceso.
8 Más VHDL
8.1 Introducción
En la sección de introducción al VHDL se presentaron las estructuras y construcciones
básicas y se dieron ejemplos para poder comenzar a crear diseños sintetizables. En esta
sección se dan algunos otros conceptos de VHDL, se ahonda en el tema de optimización
para síntesis con ejemplos concretos y se presenta la metodología de prueba utilizada
para validar un diseño, los bancos de prueba (testbench).
-- -----------------------------------------------------------
-- EJEMPLO 1
-- Contador con bit más significativo dado por un parámetro
-- genérico
entity ContadorRollover is
generic(
MSBContador : positive := 31
);
port(
Reset_IN : IN std_logic;
Clock_IN : IN std_logic;
Cuenta_OUT : OUT std_logic_vector(MSBContador downto 0)
);
end ContadorRollover;
begin
-- La salida esta dada por un registro
Cuenta_OUT <= Cuenta_REG;
end Comportamiento;
-- -----------------------------------------------------------
-- EJEMPLO 2
-- Contador con número de bits y valor de la cuenta máxima dado
-- por parámetros genéricos
entity ContadorConLimite is
generic(
CuentaMaxima : positive := 128;
BitsContador : positive := 8
);
port(
Reset_IN : IN std_logic;
Clock_IN : IN std_logic;
Cuenta_OUT : OUT std_logic_vector((BitsContador-1) downto 0)
);
end ContadorConLimite;
begin
-- La salida esta dada por un registro
Cuenta_OUT <= Cuenta_REG;
-- -----------------------------------------------------------
-- EJEMPLO 3
-- Modelo de lógica múltiple con señales de ancho variable y
-- retardo entre entrada y salida
entity LogicaMultiple is
generic(
MSB : positive := 8;
TPropagacion : time := 25 ns
);
port(
Entrada1_IN : IN std_logic_vector(MSB downto 0);
Entrada2_IN : IN std_logic_vector(MSB downto 0);
SalidaAnd_OUT : OUT std_logic_vector(MSB downto 0);
SalidaOr_OUT : OUT std_logic_vector(MSB downto 0)
);
end LogicaMultiple;
end Comportamiento;
-- -----------------------------------------------------------
-- Utilización de un componente con constantes genéricas en un
-- diseño jerárquico
entity ContadorDualConLimite is
port(
ResetTop_IN : IN std_logic;
ClockTop_IN : IN std_logic;
Cuenta1_OUT : OUT std_logic_vector(3 downto 0);
Cuenta2_OUT : OUT std_logic_vector(4 downto 0)
);
end ContadorDualConLimite;
begin
-- Se crea una instancia del contador de 4 bits y limite
-- máximo = 12 con la salida a la salida 1 del contador dual
Contador12 : ContadorConLimite
generic map (
CuentaMaxima => 12,
BitsContador => 4
)
port map (
Reset_IN => ResetTop_IN,
Clock_IN => ClockTop_IN,
Cuenta_OUT => Cuenta1_OUT
);
port map (
Reset_IN => ResetTop_IN,
Clock_IN => ClockTop_IN,
Cuenta_OUT => Cuenta2_OUT
);
end Estructura;
-- -----------------------------------------------------------
-- Utilización de un componente con constantes genéricas en un
-- diseño jerárquico para generar otro componente con constante
-- genérica
entity CompuertaAnd3Entradas is
generic(
MSB : positive := 3
);
port(
Entrada1_IN : IN std_logic_vector(MSB downto 0);
Entrada2_IN : IN std_logic_vector(MSB downto 0);
Entrada3_IN : IN std_logic_vector(MSB downto 0);
SalidaAnd_OUT : OUT std_logic_vector(MSB downto 0)
);
end CompuertaAnd3Entradas;
port(
Entrada1_IN : IN std_logic_vector(MSB downto 0);
Entrada2_IN : IN std_logic_vector(MSB downto 0);
SalidaAnd_OUT : OUT std_logic_vector(MSB downto 0);
SalidaOr_OUT : OUT std_logic_vector(MSB downto 0)
);
end component;
end Estructura;
Del cuadro pueden verse las diferentes secciones. Por un lado está la declaración de la
entidad del nuevo componente (de nivel superior en la jerarquía del diseño). En esta
sección se declaran las constantes genéricas y las interfases o puertos.
Después de esto se declara la arquitectura y dentro de esta los componentes y señales que
se utilizarán. Después de la palabra begin se “instancian” o crean las dos instancias de
los componentes bases. Estos componentes se conectan a las entadas y salidas y entre sí
mediante los port map. El generic map da valores a las constantes genéricas de las
instancias de componentes bases. En este caso se propaga la constante MSB del
componente superior a los componentes base y se da un valor de 0 ns a los retardos. Las
salidas OR de los componentes base se dejan abiertas, y cualquier herramienta de síntesis
optimizará esto deshaciéndose de cualquier lógica no conectada e innecesaria.
8.3.1 Procedimientos
Los procedimientos se utilizan para agrupar instrucciones secuenciales. Un
procedimiento se declara con un nombre y opcionalmente un conjunto de parámetros.
Puede declararse al comienzo de una arquitectura, proceso o en un paquete. Su
visibilidad dependerá de donde está declarado. El Cuadro 42 muestra el formato de
declaración y descripción de un procedimiento
begin
...
... -- Instrucciones secuenciales
...
end procedure NombreProcedimiento;
begin
...
... -- Instrucciones secuenciales
...
end procedure NombreProcedimiento;
Los procedimientos sin parámetros actuarán sobre las señales o variables visibles para
ellos. En el ejemplo anterior, el procedimiento actúa y modifica directamente la señal
ADCValue_REG. Si se utilizan parámetros para declarar y llamar un procedimiento se
podrá utilizar o modificar diferentes variables o señales con cada llamado. Para declarar
un procedimiento con parámetros se utiliza el formato mostrado en el Cuadro 42. Esta es
similar a la declaración de los puertos de una entidad, con los siguientes elementos:
end if;
end procedure SaturarADC;
...
8.3.2 Funciones
Las funciones pueden verse como la generalización de expresiones. Son una manera de
definir nuevas operaciones que luego podrán ser utilizadas en expresiones. Estas
operaciones se describen como un conjunto de instrucciones secuénciales que calculan un
resultado. Su declaración, como se muestra en el Cuadro 45 es muy similar a los
procedimientos. La diferencia es que debe declararse un tipo que devolverá el llamado a
la función usando return en la declaración.
begin
...
... -- Instrucciones secuenciales
...
end function NombreFuncion;
A diferencia de los procedimientos las funciones deben devolver un valor del tipo
declarado en la declaración usando el formato de la instrucción return :
begin
if (Entrada1 > Entrada2) then
return Entrada1;
else
return Entrada2;
end if;
end function Mayor;
...
...
Cuadro 46 Ejemplo de declaración y uso de una función con parámetros de entrada solamente
En este ejemplo los parámetros de entrada no tienen un rango prefijado. Los rangos se
asignarán cuando se llame a la función con parámetros reales. El tipo de la salida no
puede tener un rango predeterminado. En el ejemplo, el rango estará dado por las señales
DatoADC_IN y LimiteUsuario_IN y la señal que se devuelve también dependerá de la
cantidad de bits de estas dos entradas.
-- ------------------------------------------------------ --
-- Ejemplo de la instrucción generarte para crear un inversor
-- de 16 bits a partir de un componente INV de 1 bit
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.all;
entity Inversor16 is
port(Entrada_IN : in std_logic_vector(15 downto 0);
Salida_N_OUT : out std_logic_vector(15 downto 0));
end Inversor16;
begin
CompGenerado : for índice in 15 downto 0 generate
CompBasico : INV port map (I => Entrada_IN(Indice),
O => Salida_N_OUT(Indice));
end generate;
end Estructura;
Por ejemplo, los fabricantes proveen una primitiva "sumador", que no existe directamente
en las FPGAs. Esta primitiva está formada por los elementos lógicos, lógica de acarreo,
etc., para cada familia de FPGAs en particular. Las herramientas detectan los sumadores
en el código VHDL y lo traducen a una interconexión del componente "sumador" con
otras primitivas.
Xilinx provee las denominadas “librerías unificadas”. Con ellas Xilinx unifica los
componentes para todos sus dispositivos programables. Los componentes de las librerías
El Cuadro 48 muestra un ejemplo en que se usa una primitiva de un buffer tipo “BUFG”.
Ese buffer es el buffer de entrada de las señales de reloj en las FPGA. Cuando se hace un
diseño con las herramientas de Xilinx ISE 5, este componente debe incorporarse como
una instancia explícitamente si se conecta una señal que no es una señal de reloj a uno de
estos pines. En la placa D2E de Digilent Inc, el botón está conectado a uno de estos pines,
y para todos los diseños debe agregarse una instancia de BUFG si se desea utilizar.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library unisim;
use unisim.vcomponents.all;
entity Componente is
port(
Clock_IN : in std_logic;
Reset_IN : in std_logic;
...
... –- Demás puertos de interfase al componente
);
end Componente;
component bufg
port ( I : in std_logic;
o : out std_logic);
end component;
begin
BufferReset : bufg
port map (I => Reset_IN,
O => intReset);
-- Resto de la descripción structural utiliza intReset
-- como señal de reset
...
Cuadro 48 Utilización de una instancia de un componente de librería BUFG en una estructura
De cualquier manera, un diseño que utilice primitivas debe poder simularse. Para ellos se
necesitan modelos de simulación de estas primitivas. Cada fabricante provee estos
modelos de simulación para sus primitivas. Por ejemplo, Xilinx provee estos modelos en
la librería unisim, Altera en la librería altera_mf y Actel tiene una librería para cada
familia de FPGAs. Si en un diseño se utiliza directamente alguna primitiva (componente)
de Xilinx, por ejemplo, se deben agregar a la lista de librerías las siguientes líneas
library unisim;
use unsim.vComponents.all;
En el ejemplo anterior del uso de BUFG estas líneas aparecen al comienzo del archivo,
antes de la declaración de la entidad.
library altera_mf;
use altera_mf.altera_mf_components.all;
8.5.3 Memoria
La memoria es un componente básico de muchos diseños digitales. Muchas FPGAs
incluyen bloques de memoria entre los elementos lógicos, lo que permite integrarla de
manera rápida y eficiente con los diseños lógicos. Además de la memoria embebida o en
bloque (la que está integrada en el chip junto a la lógica programable), las FPGAs
basadas en memoria SRAM para su configuración permiten usar parte de la lógica como
memoria. Dependiendo de las herramientas, su configuración y el estilo del código HDL,
las memorias pueden . En algunos casos pueden inferirse a partir de la descripción que se
hace en el HDL. En otros casos, si se desea usar un tipo de memoria con una
configuración particular, es posible que haya que crear una instancia explícitamente como
una primitiva.
Para utiliza cualquiera de los dos tipos de memoria deben inferir o crear una instancia de
alguna versión de ellos en una arquitectura estructural. Hay varias posibilidades de uso y
configuración de las memorias, ya sea con puerto simple, puerto dual, diferentes anchos
de palabra, etc. A continuación se presentarán algunos ejemplos de estos componentes,
tomados de la guía de librerías unificada de Xilinx.
La Figura 40 muestra una memoria RAM de puerto dual de 16 palabras por 1 bit de
ancho. Esta memoria tiene los siguientes puertos interfase.
Inferencia de Memorias
Ciertas estructuras en VHDL pueden modelar el comportamiento de memorias RAM o
ROM. Muchas herramientas detectan estas estructuras e infieren el uso de una memoria
interna de la FPGA (ya sea en bloque o distribuida). El tipo de estructura reconocida y las
memorias inferidas dependerán de las herramientas. Algunas herramientas infieren bien
ciertos tipos de memoria pero no otros (puerto simple vs. puerto dual) o no permiten
inicializar una memoria inferida. En lo siguientes cuadros y figuras se muestra código
VHDL con el cual se infieren distintos tipos de memoria y los resultados de la síntesis.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH. ALL;
use IEEE.STD_LOGIC_UNSIGNED. ALL;
entity infer_ram is
port (clk : in std_logic;
we : in std_logic;
a : in std_logic_vector(4 downto 0);
di : in std_logic_vector(3 downto 0);
do : out std_logic_vector(3 downto 0));
end infer_ram;
begin
process (clk)
begin
if Rising_Edge(clk) then
-- La memoria se escribe con un WE sincronico
if (we = '1') then
RAM(conv_integer(a)) <= di;
end if;
-- Datos de salida
do <= RAM(conv_integer(read_a));
end Comportamiento;
Cuadro 49 VHDL para inferir memoria en bloque BRAM en las herramientas de Xilinx
======================================================================
HDL Synthesis Report
Macro Statistics
# Block RAMs : 1
1024x4-bit single-port block RAM : 1
======================================================================
Device utilization summary:
---------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH. ALL;
use IEEE.STD_LOGIC_UNSIGNED. ALL;
entity infer_ram is
port (clk : in std_logic;
we : in std_logic;
a : in std_logic_vector(4 downto 0);
di : in std_logic_vector(3 downto 0);
do : out std_logic_vector(3 downto 0));
end infer_ram;
begin
process (clk)
begin
if Rising_Edge(clk) then
-- La memoria se escribe con un WE sincronico
if (we = '1') then
RAM(conv_integer(a)) <= di;
end if;
end if;
end process;
end Comportamiento;
======================================================================
HDL Synthesis Report
Macro Statistics
# LUT RAMs : 1
1024x4-bit single-port distributed RAM: 1
======================================================================
Device utilization summary:
---------------------------
Selected Device : 2s200epq208-7
En el siguiente ejemplo se infiere una memoria ROM. Notar en la figura que la memoria
ROM se implementa como una RAM con sus entradas de escritura deshabilitadas.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
begin
Cuadro 53 VHDL para inferir memoria ROM (usando BRAM) en las herramientas de Xilinx
======================================================================
HDL Synthesis Report
Macro Statistics
# Block RAMs : 1
16x8-bit single-port block RAM : 1
======================================================================
Device utilization summary:
---------------------------
Altera recomienda estructuras similares para inferir memorias en sus dispositivos desde
los HDLs. en el siguiente cuadro se muestra un ejemplo de VHDL para inferir una
memoria RAM de puerto dual.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY ram_dual IS
BEGIN
PROCESS (clock1)
BEGIN
IF (clock1'event AND clock1 = '1') THEN
IF (we = '1') THEN
ram_block(write_address) <= data;
END IF;
END IF;
END PROCESS;
PROCESS (clock2)
BEGIN
IF (clock2'event AND clock2 = '1') THEN
q <= ram_block(read_address_reg);
read_address_reg <= read_address;
END IF;
END PROCESS;
END rtl;
Cuadro 55 VHDL recomendado para inferir memoria RAM de puerto dual en FPGAs de Altera
Para entender bien como inferir memorias u otras primitivas desde el código HDL para
una FPGA y herramienta dada, referirse a los manuales de las herramientas y notas de
aplicación de los fabricantes de FPGAs. Las herramientas provistas por los fabricantes de
FPGAs tienen ayudas y plantillas que permiten generar código HDL de manera rápida.
Instancia de Memorias
Hay muchos casos en los que se desea controlar en detalle el tipo de memoria (u otra
primitiva) a utilizar. En estos casos se debe colocar una instancia (instantiate) del
componente usando port map . Para esto hay que referirse a la documentación de los
fabricantes y entender las interfaces de las primitivas. Una vez definido el componente se
instancia como cualquier otra primitiva. En el siguiente ejemplos e muestra el uso de una
memoria del tipo ram_32x8_dp en una FPGA de Altera. Para modelar el
comportamiento de la memoria se debe incluir al proyecto el VHDL correspondiente al
componente ram_32x8_dp provisto por Altera. Mas adelante se muestra el uso de
memorias de Xilinx para crear una cola FIFO.
…
ARCHITECTURE rtl_text OF fifo_1clk_32x8 IS
clock : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0));
END COMPONENT;
BEGIN
-------------------------------------
-- Altera RAM instantiation for FIFO.
-------------------------------------
RamFifo : ram_32x8_dp
PORT MAP (
data => Writedata_IN,
wren => WriteEnable_IN,
wraddress => WriteAddress_REG(4 DOWNTO 0),
rdaddress => ReadAddress_REG(4 DOWNTO 0),
clock => Clock_IN,
q => Readdata_OUT);
...
END ARCHITECTURE rtl_text;
entity DRamDual16xN is
generic (
MSB_MEMORIA_RAM : positive := 15;
);
port (
Clock_IN : in std_logic;
WriteEnable_IN : in std_logic;
WriteAddress_IN : in std_logic_vector(3 downto 0);
WriteData_IN : in std_logic_vector(MSB_MEMORIA_RAM downto 0);
ReadAddress_IN : in std_logic_vector(3 downto 0);
ReadData_OUT : out std_logic_vector(MSB_MEMORIA_RAM downto 0)
);
end DRamDual16xN;
component RAM16X1D
port (
WCLK : in std_logic;
WE : in std_logic;
A0 : in std_logic;
A1 : in std_logic;
A2 : in std_logic;
A3 : in std_logic;
D : in std_logic;
SPO : out std_logic;
DPRA0 : in std_logic;
DPRA1 : in std_logic;
DPRA2 : in std_logic;
DPRA3 : in std_logic;
DPO : out std_logic);
end component;
begin
--------------------------------------------
-- Instancia de RAM
--------------------------------------------
G1: for I in MSB_MEMORIA_RAM downto 0 generate
L: RAM16X1D port map (
WCLK => Clock_IN,
WE => WriteEnable_IN,
A0 => WriteAddress_IN(0),
A1 => WriteAddress_IN(1),
A2 => WriteAddress_IN(2),
A3 => WriteAddress_IN(3),
D => WriteData_IN(I),
SPO => open,
DPRA0 => ReadAddress_IN(0),
DPRA1 => ReadAddress_IN(1),
DPRA2 => ReadAddress_IN(2),
DPRA3 => ReadAddress_IN(3),
DPO => ReadData_OUT(I));
end generate G1;
end Estructura;
En el siguiente ejemplo se define una cola tipo FIFO de 16 palabras por 16 bits. Se utiliza
como bloque básico para guardar los datos la primitiva RAM16X1D. Este componente
tiene una entrada y una salida de datos y dos señales que indican si se desea leer el dato
de la cola o escribir el dato a la cola. LA salida de lectura siempre tiene el primer dato de
salida disponible, y al leerlo se incrementa un puntero y se pasa al siguiente. El dato de
escritura se escribe sobre la memoria en el lugar indicado por el puntero de escritura. Otra
salida indica el número de datos disponibles en la cola. El correcto funcionamiento
depende de que la lógica que se conecta a este componente no actúe de manera no
prevista. Es decir, solo se deberá leer un dato si hay datos disponibles y solo se deberá
escribir un dato si los datos disponibles no llenan la cola.
entity FifoDRam16x16 is
port (
Clock_IN : in std_logic;
Reset_IN : in std_logic;
WriteEnable_IN : in std_logic;
ReadEnable_IN : in std_logic;
WriteData_IN : in std_logic_vector(15 downto 0);
ReadData_OUT : out std_logic_vector(15 downto 0);
DatosDisponibles_OUT : out std_logic_vector(4 downto 0)
);
end FifoDRam16x16;
component RAM16X1D
port (
WCLK : in std_logic;
WE : in std_logic;
A0 : in std_logic;
A1 : in std_logic;
A2 : in std_logic;
A3 : in std_logic;
D : in std_logic;
SPO : out std_logic;
DPRA0 : in std_logic;
DPRA1 : in std_logic;
DPRA2 : in std_logic;
DPRA3 : in std_logic;
DPO : out std_logic);
end component;
begin
--------------------------------------------
-- Instancia de RAM 16 x 16
--------------------------------------------
G1: for I in 15 downto 0 generate
L: RAM16X1D port map (
WCLK => Clock_IN,
WE => WriteEnable_IN,
A0 => WriteAddress_REG (0),
A1 => WriteAddress_REG (1),
A2 => WriteAddress_REG (2),
A3 => WriteAddress_REG (3),
D => WriteData_IN(I),
SPO => open,
DPRA0 => ReadAddress_REG (0),
DPRA1 => ReadAddress_REG (1),
DPRA2 => ReadAddress_REG (2),
DPRA3 => ReadAddress_REG (3),
DPO => ReadData_OUT(I));
end generate G1;
end Mixta;
En los diagramas de burbujas se detallan los estados mediante burbujas y las transiciones
entre ellos con flechas que las unen. Sobre las flechas se especifican las condiciones
necesarias para esas transiciones. Existen muchas herramientas gráficas con las que se
pueden diseñar máquinas de estado. En general se grafican diagramas de burbujas y la
condiciones de transición y salidas. Estas representaciones gráficas son luego traducidas a
VHDL por las herramientas. La Figura 44 muestra esta máquina de estados como un
diagrama de burbujas.
8
Las máquinas de estado infinitas no tienen sentido práctico para las aplicaciones que se tratan en este
texto
Aunque es muy práctico diseñar una máquina de estados con una interfase gráfica como
la provista por StateCad de Xilinx, HDL Designer de Mentor Graphics, o cualquier otra
herramienta de ese estilo, también se puede desarrollar directamente en VHDL9. EL estilo
preferido para describir una máquina de estados en VHDL es mediante dos procesos.
Uno es combinacional y calcula el próximo estado a partir del estado actual y las
entradas. El otro es sincrónico y asigna el estado actual y define las salidas. El ejemplo
presentado es una manera de modelar máquinas de estado, pero existen una variedad de
combinaciones de procesos y lógica concurrente que pueden ser utilizadas.
9
Las herramientas traducen los diseños gráficos a VHDL o Verilog antes de sintetizarlos.
begin
-- -------------------------------------------------------- --
-- Asignaciones e instrucciones concurrentes
-- -------------------------------------------------------- --
Salida <= Salida_REG;
-- -------------------------------------------------------- --
-- Proceso sincrónico de asignación de estado actual y señales
-- -------------------------------------------------------- --
ProcesoSincronico : process(Clock_IN, Reset_IN)
begin
if (Reset_IN = '1') then
EstadoActual <= Inicial;
-- Valores de reset
Salida_REG <= “001”;
elsif (Rising_Edge(Clock_IN) then
-- Paso al próximo estado de manera sincrónica
EstadoActual <= EstadoSiguiente;
-- Acciones para la asignación de señales y salidas
case EstadoActual is
when Inicial =>
Salida_REG <= “001”;
when Estado1 =>
Salida_REG <= “010”;
when Estado2 =>
Salida_REG <= “011”;
when Estado3 =>
Salida_REG <= “100”;
when Estado4 =>
Salida_REG <= “111”;
when others =>
null; -- Mantiene las salidas actuales con un registro
end case;
end if;
end process ProcesoSincronico;
-- -------------------------------------------------------- --
-- Proceso combinacional de asignación de estados
-- -------------------------------------------------------- --
AsignacionProximoEstado : process (Entrada1,
Entrada2,
EstadoActual
)
begin
-- Acciones combinadas de asignación de estado siguiente
case EstadoActual is
when Inicial =>
if (Entrada1_IN = ‘1’) then
EstadoSiguiente <= Estado1;
else
EstadoSiguiente <= Inicial;
end if;
when Estado1 =>
if (Entrada1_IN = ‘0’) then –- Entrada1= ‘1’, Entrada2= ‘X”
EstadoSiguiente <= Estado4;
elsif (Entrada2_IN=‘0’) then –- Entrada1= ‘1’, Entrada2= ‘0’
EstadoSiguiente <= Estado2;
else -- Entrada1= ’1’, Entrada2= ‘1’
EstadoSiguiente <= Estado3;
end if;
when Estado2 =>
EstadoSiguiente <= Estado3;
when Estado3 =>
if (Entrada2_IN = ‘0’) then
EstadoSiguiente <= Estado4;
else
EstadoSiguiente <= Estado3;
end if;
when others => -- Estado4
EstadoSiguiente <= Inicial;
end case;
end ComportamientoFSM;
En el proceso combinacional todas las señales que producen cambios deben estar en la
lista de sensibilidad. Además, al evaluar las entradas para el próximo estado en las
instrucciones if.. else deben evaluarse todos los casos de combinaciones de entradas para
evitar que se infieran “latches”.
un registro de n bits pueden codificarse 2n estados, pero muchas veces es más eficiente
utilizar codificación “one-hot” o “one-cold”. En este tipo de codificación se usan tantos
bits como estados haya y un solo bit está en ‘1’ (one hot) o ‘0’ (one cold) en un momento
dado. Esto permite simplificar la lógica combinacional que determina en que estado se
encuentra la máquina para asignar las salidas y el próximo estado.
En general hay dos niveles de interfase que se desean probar. Por un lado se quiere ver si
las formas de onda de la interfase responden a lo esperado. A un nivel superior se desea
probar si los datos de entrada/salida cumplen con lo esperado. Es decir si el diseño hace
lo que debería con los datos de entrada y responde con los datos de salida adecuados. En
el primer caso una observación de las formas de onda en general alcanza para analizar la
interfase. Para el análisis de funcionamiento a nivel datos probablemente se requerirá una
metodología mas estructurada, con algún algoritmo de prueba más sofisticado y
posiblemente leer y guardar datos de y a un archivo para su posterior análisis.
con hardware “real” ya que podemos generar cualquier combinación de señales solo
cambiando un poco de código. Algunos de estos casos son que sucede cuando los
contadores llegan a sus valores finales, que sucede cuando se sobrepasan los límites
esperados para las entradas, que sucede con combinaciones de entradas no esperadas,
utilizar un número significativo de datos de entrada, usar números aleatorios para ver el
funcionamiento, etc.
port (
Reset_IN : IN std_logic;
Clock_IN : IN std_logic;
Enable_IN : IN std_logic;
Mode_IN : IN std_logic_vector(2 downto 0);
Dato_OUT : IN std_logic_vector(7 downto 0)
);
los vectores de prueba serian el conjunto de señales que prueban diferentes
combinaciones de las entradas Reset_IN, Clock_IN, Enable_IN, Mode_IN para que se
permita evaluar, mediante observaciones de la salida Dato_OUT si el diseño está
funcionando bien.
Estos vectores pueden generarse mediante VHDL secuencial que explícitamente genera
la secuencia de señales deseadas, usando ciclos y arreglos de valores o leyendo los datos
de un archivo. Este último método es recomendable porque es muy flexible y permite
redefinir fácilmente los vectores de prueba sin tocar el código VHDL.
Algunas pautas y guías para hacer un buen banco de pruebas son las siguientes:
• No se necesitan seguir las estructuras presentadas para síntesis: como los bancos
de prueba no serán sintetizados, sino que solo sirven para las simulaciones, no es
necesario seguir las estructuras presentadas para diseños sintetizables.
• Usar las mismas guías en el código, nombres, etc. Es bueno seguir las mismas
pautas de código y nombres ya que eso hace que el banco de pruebas sea mas fácil
de entender, modificar e incluso reutilizar.
• Los procesos de prueba deberán tener un valor de reposo ya que esto es lo que
indica que se terminó la simulación y facilita la tarea al simulador (ayuda a
ejecutar la simulación más rápido).
P_PruebaReadEnable : process
variable Dato1_VAR, Dato2_VAR : std_logic_vector(7 downto 0);
begin
-- Comienzo de la simulación
ReadEnable_N_OUT <= ‘1’; -- Comienzo sin lectura
wait for 1 ms; -- Espero x transitorio
TCambioAnterior := TCambioActual;
TCambioActual := now;
...
-- Verifico si hay suficiente tiempo entre cambios
En el Cuadro 62 se dan ejemplos de lazos for . El lazo for puede usar un índice que se
incrementa o reduce según se usa la palabra to o downto. Esto dependerá de la tarea que
deba llevar a cabo el lazo. El lazo se termina con end loop y en el cuerpo se describen las
tareas que se deben realizar usando instrucciones secuénciales.
...
-- --------------------------------------------------------- --
-- Formato de la instrucción LOOP, NEXT y EXIT
loop
... -- Instrucciones secuenciales
next (when Condición); -- Reinicia el lazo
... -- Instrucciones secuenciales
exit (when Condición); -- Sale del lazo (salta después
-- del “end loop”)
... -- Instrucciones secuenciales
end loop;
-- --------------------------------------------------------- --
-- Ejemplo de lazo loop con condiciones de salida
--
Indice := 0; -- Inicialización del índice
loop -- Comienzo del lazo
Indice := Indice + 1; -- Incremento del índice
...
... -- Instrucciones secuenciales que se ejecutarán
... –- para todos los valores de Indice
...
next when Indice <= 5; -- Reinicia el lazo si Indice < 5
...
... -- Instrucciones secuenciales que se ejecutan solo si
... -- Indice es mayor que 5
...
• next;
• if (Condición buleana) then
exit;
end if;
• if (Condición buleana) then
next;
end if;
• exit when (Condición buleana);
• next when (Condición buleana);
La instrucción report puede usarse por si sola para generar mensajes que ayuden en la
depuración del código. La expresión tiene la forma
Al escribir datos a un archivo estos se guardarán con un formato binarios que dependerá
del sistema sobre el que se está trabajando. En general estos no pueden ser analizados
directamente por el desarrollador. En muchos casos es importante que se puedan escribir
o leer los datos directamente de los archivos. De esta manera se hace fácil especificar los
datos de entrada a un modelo o verificar sus resultados. Para simplificar la escritura y
lectura de archivos en un formato entendible para el usuario, la librería std provee el
paquete textio. Este paquete permite acceder a archivos que contienen cadenas de
caracteres. Así, todos los datos serán cadenas de texto. Pueden usarse funciones de
conversión para guardar o escribir cualquier tipo de dato en estos archivos. En lo que
resta de esta sección se presentará el paquete textio y su utilización para leer y guardar
datos de simulación. El lector puede referirse a la bibliografía para estudiar el uso de
otros tipos de archivo.
library std;
use std.textio.all;
Esto hace accesible el paquete textio que incluye los tipos y procedimientos mostrados en
la Tabla 14. También incluye los archivos que pueden utilizarse directamente "input" y
"output" asociados a los archivos físicos "std_input" y "std_output". Estos se proveen
para poder acceder a los dispositivos estándar de entrada / salida, que en general están
definidos como la pantalla y el teclado en casi todos los sistemas.
Las operaciones de entrada salida sobre los archivos utilizando textio se hacen línea a
línea. Esto permite que varios procesos accedan a un mismo archivo. Como la secuencia
de escritura a un archivo de varios procesos concurrentes es impredecible, al escribir
líneas completas no se entremezclarán los datos sino que a lo sumo se alternan líneas de
un proceso y otro. Si cada proceso marca de alguna manera las líneas que escribe es fácil
descifrar el funcionamiento del modelo en su conjunto al analizar el archivo.
Para leer datos usando textio se debe declarar una variable del tipo line y abrir un
archivo de subtipo text. Mediante una instrucción secuencial readline se lee una línea del
archivo. Esa línea luego se procesa usado las diferentes variantes de read para extraer los
datos.
Para escribir una línea a un archivo primero se escriben los datos a una variable del tipo
line utilizando las diferentes variantes de write y luego se escribe la línea al archivo
usando writeline.
Esta palabra permite definir nuevos nombres para datos y otros objetos. En el caso más
simple un alias se refiere a un dato con otro nombre. El Cuadro 65 muestra algunos
ejemplos. La capacidad de sintetizar o no diseños que utilizan alias depende de las
herramientas, y se recomienda no utilizarlas para diseños que se sintetizarán para FPGAs.
library ieee;
use ieee.std_logic_1164.all;
entity tbGeneradorReloj is
generic (
PERIODO_NS : time := 20 ns
);
port (
SimmulacionActiva_IN : IN std_logic;
Reloj_OUT : OUT std_logic
);
end tbGeneradorReloj ;
P_Reloj : process
begin
wait for 1 ns;
while (SimmulacionActiva_IN = '1') loop
end Comportamiento;
library ieee;
use ieee.std_logic_1164.all;
entity tbGeneradorReset is
generic (
TIEMPO_RESET : time := 250 ns
);
port (
Reset_OUT : OUT std_logic
);
end tbGeneradorReset ;
P_Reset : process
begin
Reset_OUT <= ‘1’; -- Reset activo
wait for TIEMPO_RESET; -- Se mantiene reset activo
Reset_OUT <= ‘0’; -- Reset baja. Comienza a funcionar
-- el circuito
wait; -- Proceso en espera permanente
end process P_Reset;
end Comportamiento;
Clock
tClock
tSWData tHWData
tSRData
tHRData
Data
tHAddress
tSAddress tHAddress tSAddress
Address
tSRead tHRead
ReadEnable tHWrite
tSWrite
WriteEnable
-- ------------------------------------------------------- --
-- Ejemplo de ciclo de temporizado de un bus de uC
...
... -- Declaración de librerías y uso de paquetes.
...
begin
SimulacionDeMicro : process
procedure EscribirDato is
begin
end EscribirDato;
-- Valores iniciales
ReadEnable_OUT <= '1';
WriteEnable_OUT <= '1';
Address_OUT <= (others => '0');
Data_IO <= (others => 'Z');
Por otro lado, las FPGAs permiten el desarrollo de sistemas muy complejos en un solo
componente. Estos diseños pueden llegar a ser bastante sofisticados y tener una jerarquía
que utilice componentes desarrollados por diferentes personas. Para poder manejar esto
de manera controlada es bueno tener pautas o guías de diseño que ayuden a la interacción
y reutilización de la propiedad intelectual. En esta sección se presentarán de manera
básica una serie de puntos y recomendaciones relacionadas con estos temas.
10.2 Documentación
Si se pretende tener un producto (re)utilizable, vendible, o que pueda entenderse después
de tenerlo archivado unos meses es imprescindible crear buena documentación.
COMPLETAR CON PAUTAS SOBRE DOCUMENTACIÓN.
• Programación en VHDL
o No mezclar estándares de programación. Usar sintaxis VHDL 87 o 93
exclusivamente)
o Usar un archivo por entidad (“entity”) que defina su interfase y arquitectura.
El nombre del archivo deberá ser igual al de la entidad.
o Usar tipos std_logic para todas los puertos de interfase externa
o Nunca asignar un valor desconocido ‘X’ o verificar un don’t care ‘-‘
(producen resultados inesperados en la síntesis y las simulaciones)
o No usar los valores por defecto para señales y variables. Asignarles un valor
inicial durante el estado de Reset.
o Tratar de usar el mismo nombre para las señales a través de toda la jerarquía
de diseño, quizás agregando prefijos o sufijos.
o Definir todas las constantes para un diseño en un solo “package”
o Usar constantes y parámetros genéricos para definir el tamaño de los buffers y
buses. (Ayuda a reutilizar el código)
o No utilizar puertos del tipo “BUFFER” para leer un valor de salida. En vez de
eso usar tipos “OUT” y agregar otra señal interna a la que se le asigna el
mismo valor.
• Comentarios
o Usar los comentarios para describir la lógica y el motivo del programa. No
comentar lo obvio.
o Usar líneas completas comentadas para dividir grandes bloques lógicos del
programa
o Usar comentarios para especificar que condición está cerrando un comando
END
o Siempre debe agregarse un comentario para describir lógica que no es obvia o
tiene particularidades que son difíciles de entender a simple vista.
Ejemplos:
-- -----------------------------------------------------------------------------
-- SEÑALES
-- -----------------------------------------------------------------------------
signal ADCdataBus : std_logic_vector(12 downto 0);
signal ADCReady : std_logic;
signal ADCRead : std_logic;
• Usar:
signal DatoDeEntrada_N_REG : std_logic_vector(2 downto 0);
signal DatoDeSalida_REG : std_logic_vector(2 downto 0);
...
P_umaDeEntradas : PROCESS(Clock_IN, Reset_IN)…
P_RestaDeEntradas : PROCESS(Clock_IN, Reset_IN)…
y no:
signal datodeentrada_N_REG : std_logic_vector(2 downto 0); -- No hay un estándar
-- para los nombres
signal salida : std_logic_vector(2 downto 0); -- alinear los espacios
...
SumaDeEntradas : PROCESS(Clock_IN, Reset_IN)… -- no hay consistencia en
Proceso_Entradas_Resta : PROCESS(Clock_IN, Reset_IN)… -- el formato de los nombres
recomienda generar una señal de habilitación de reloj. Esta es una señal con la que se
habilita el reloj por un ciclo solo cada N ciclos. Esto hace que un proceso sincrónico se
ejecute solamente a la frecuencia deseada (cada N flancos de reloj) en vez de con cada
flanco del reloj. La Figura 48 muestra el método de división de frecuencia recomendado
para diseños sobre FPGAs.
Figura 48 División de frecuencia recomendada para FPGAs usando habilitación de reloj (CE)
Hay muchos errores comunes que pueden evitarse facilmente siguiendo este tipo de
pautas Por ejemplo, si algunos desarrolladores utilizan una señal de reset positiva y otros
negativa, o si algunos no proveen un estado de reset conocido o si algunos nombran los
buses del bit más significativo al menor y otros al revés, esto puede causar errores al
integrarlos en un diseño. A continuación se da como ejemplo una lista de algunas
recomendaciones para diseños utilizando VHDL tomado de guías de desarrollo de
organizaciones reales. Estos son las pautas que se ha tratado de utilizar a través de este
texto para todos los ejemplos.
• Señal de Reset
Proveer una señal de Reset porque hace que un diseño sea determinístico y evita
que se llegue a estados prohibidos
o Todos los Flip-Flop deberán tener un Reset de lógica positiva, asincrónico.
Este Reset deberá estar conectado a la pata de Reset global de la FPGA o
CPLD de ser posible.
o El Reset asincrónico se usará a nivel local en todos los módulos. Este se
sincronizará con el reloj al nivel lógico mas alto de la jerarquía de diseño.
(Evita des-sincronización por caminos de diferente longitud de la señal de
Reset).
o Durante el estado de Reset todos los puertos bidireccionales deberán colocarse
en el estado de entrada. (Esto es lo que espera el “boundary scan” y evita tener
valores )
• Reloj
o Todas las señales que cruzan dominios de reloj deberán muestrearse antes y
después de cruzar dominios (previene estados meta-estables).
o Se deberán usar la mínima cantidad de dominios de reloj posibles.
o No usar señales de reloj o Reset como Enable o dato. No usar un dato como
reloj o Reset. (los resultados durante simulaciones pueden diferir del circuito
sintetizado y causar problemas de temporizado)
• Buses
o Comenzar los buses en el bit 0. (Algunas herramientas no aceptan buses que
no comienzan en 0)
o Usar (MSB downto LSB) para todos los buses. (para evitar interpretaciones
diferentes y provocar malos conexionados)
o Para lógica sincrónica con “enable”, tratar de definirla en un proceso solo con
el siguiente formato
(así las herramientas de síntesis utilizarán así la señal de enable interna de los
bloques lógicos de la FPGA y no generarán lógica externa)
o No utilizar largas cadenas de if.. else sino que utilizar una instrucción
case. (esto evita que se genere lógica de prioridad grande, lenta e
innecesaria)
12.4.3 etc.
12.4.4 etc.
12.4.5 etc.
• Multiplexores
-- with (Seleccion_IN & Datos3_IN(0)) select
with Seleccion_IN select
Salida1_OUT <= Datos1_IN when "00",
Datos2_IN when "01",
"010101" when others;
-- "XXXXXX" when others;
• Las herramientas infieren decodificadores para with select, when else, process if, -
else if y case
• Que pasa con if (if else) elsif…
• Máquina de estados. Mostrar Flip-Flops, quizás con diferentes “encoding”
Para poder instalar y ejecutar Xilinx Project Navigator y Modelsim la PC debe tener
instalados el sistema operativo Windows 2000 o Windows XP
• Para poder invocar a ModelSim desde Project Navigator debe estar bien definido
el “path” al ejecutable. Para el ModelSim versión XE gratuito es
Edit/Preferences/Partner Tools/ C:\Modeltech_xe-starter\win32xoem
o el path adecuado incluyendo el directorio win32xoem
Menús de ModelSim
Comandos de línea
• Para ver solo los nombres de las señales (sin path) poner “1” en la casilla:
Tools/Windows Preferences/ Display Signal Path [] # of elements
15 Referencias
15.1 Dispositivos Lógicos Programables
Bibliografía
• Spartan IIe Device Family, Hoja de datos de Xilinx DS077, www.xilinx.com, 2002.
• Virtex II Pro Data Sheet, Hoja de datos de Xilinx DS083, www.xilinx.com, 2002
• MAX 7000 Programmable Device Family, Hoja de datos de Altera DS-MAX7000-6.5,
www.altera.com.
• Stratix FPGA Family Data Sheet, Hoja de datos de Altera DS-STXFAMLY-3.0,
www.altera.com, 2002
• Excalibur Device Overview Data Sheet, Hoja de datos de Altera DS-EXCARM-2.0,
www.altera.com.
• GAL22V10 Data Sheet, Hoja de datos de Lattice Semiconductors, www.vantis.com,
Junio 2000
• Using Delay Locked Loops in Spartan II Devices, Nota de aplicación de Xilinx XAPP174,
www.xilinx.com, 2000
• Introduction to GAL Devices, Nota de aplicación de Lattice Semiconductors,
www.vantis.com, 2002
• CPLD Package and I/O Matriz, Guía de selección de Altera SA-CPLDMTRX-1.0,
www.altera.com, 2002
• FPGA and CPLD Architectures: A Tutorial, Stephen Brown & Jonathan Rose, IEEE
Design and Test of Computers, 1996.
• Diseño Digital Principios y Prácticas Tercera Edición, John F. Wakerly, Editorial Prentice
Hall, 2001.
• Síntesis y Descripción de Circuitos Digitales Utilizando VHDL, IEC Francisco Javier
Torres Valle, Universidad Autónoma de Guadalajara, 2001.
• Low-cost programmable logic: How low should you go?, Brian Dipert, EDN, 16/3/2001
• Programmable Logic Device Review. Lattice Introduces FPGA, Murray Disman,
www.chipcenter.com, 2002.
• The Effect of LUT and Cluster Size on Deep-Submicron FPGA Performance and Density,
Elias Ahmed a& Jonathan Rose, IEEE Transactions on VLSI Systems, March 2004
• FPGA Performance vs Cell Granularity, Jack Kouloheris & Abbas El Gamal, IEEE
Custom Integrated Circuits Conference, 1991
Links de Interés
• Sitio web de Altera: www.altera.com
• Sitio web de Xilinx: www.xilinx.com
• Sitio web de Actel: www.actel.com
• Sitio web de Cypress Semiconductor: www.cypress.com
• Sitio web de Quicklogic: www.quicklogic.com
• Sitio web de Atmel: www.atmel.com
Links de Interés
• What is Behavioral Synthesis? http://www.forteds.com/pub/bd/whatisbd.asp
15.3 VHDL
Bibliografía
• The Designer’s Guide to VHDL 2nd Edition, Peter J. Ashenden, Editorial Morgan Kaufman,
2002
• Diseño Digital Principios y Prácticas Tercera Edición, John F. Wakerly, Editorial Prentice
Hall, 2001
• Synthesis and Simulation Design Guide, Xilinx
• Development System Reference Guide ISE 5 , Xilinx
• The VHDL Golden Reference Guide version 1.1, Doulos, 1995
• In Search of the Origins of VHDL’s Delta Delays, Sumit Gosh, Proceedings of the IEEE
International Symposium on Quality Electronic Design, 2002.
• Código VHDL de los paquetes.de lógica estándar IEEE: std_logic_1164.vhd,
std_logic_arith.vhd, std_logic_signed.vhd y std_logic_unsigned.vhd.
• Synthesis and Simulation Design Guide, Xilinx
• Libraries Guide, Xilinx
• Rapid Prototyping of Digital Systems, James O. Hamlen Michael D. Furman, Kluwer
Academic Publishers, 2000
• The VHDL Golden Reference Guide version 1.1, Doulos, 1995
• VHDL Style Guidelines for Performance, Model Technology, Oct 1999.
Links de Interés
15.5 Síntesis
Bibliografía
• Xilinx Synthesis Technology (XST) User Guide, Xilinx
16 Ejemplos