Diseño Digital Utilizando Lógicas Programables

    

 

Versión 0.6

 Junio 29, 2005

 

 

 

 

 

 

 

 

 

 

 

Guillermo Güichal

 

Universidad Tecnológica Nacional

Facultad Regional Bahía Blanca


Í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

7.6       Librerías y Paquetes. 75

7.6.1        Librerías. 75

7.6.2        Paquetes (Packages) 75

7.6.3        Paquetes de Lógica Estándar del IEEE. 77

7.6.3.1     Lógica estándar std_logic y std_ulogic definidos en std_logic_1164. 78

7.6.3.2     Detección de flancos de señales definidos en std_logic_1164. 79

7.6.4        Aritmética sobre lógica estándar 79

7.7       Construcciones Básicas de VHDL. 81

7.7.1        Declaración de señales. 82

7.7.2        Operaciones Concurrentes. 83

7.7.2.1     Flujo de datos. 83

7.7.2.2     Palabra reservada AFTER.. 85

7.7.2.3     Expresión with … select 86

7.7.2.4     Expresión when, else. 87

7.7.3        Operaciones secuenciales. 88

7.7.3.1     Instrucción WAIT. 88

7.7.3.2     Expresión if… elsif… else. 90

7.7.3.3     Expresión null 92

7.7.3.4     Expresión case. 92

7.7.3.5     Procesos (process) 94

7.7.4        Operaciones secuenciales, retardos delta y síntesis. 98

7.7.5        Visibilidad de las declaraciones de objetos en VHDL. 99

8      Más VHDL. 101

8.1       Introducción. 101

8.2       Parámetros Genéricos. 101

8.2.1        Declaración de parámetros genéricos. 101

8.2.2        Uso de componentes con parámetros genéricos. 104

8.3       Subprogramas: FUNCTION y PROCEDURE. 108

8.3.1        Procedimientos. 108

8.3.2        Funciones. 111

8.3.3        Asociación de parámetros por posición y por nombre. 113

8.4       Instrucción GENERATE. 113

8.5       Componentes Básicos de Diseño (Primitivas - Primitives) 114

8.5.1        Utilización de Primitivas desde VHDL. 114

8.5.2        Librerías de Primitivas (componentes) Específicos para Simulación. 116

8.5.3        Memoria. 116

Inferencia de Memorias. 118

Instancia de Memorias. 124

8.5.4        Definición de Nuevos Componentes de Diseño. 125

8.6       Máquinas de Estado. 129

8.6.1        Codificación de Estados. 133

8.6.2        División de la Señal de Reloj (Clock Enable) 134

9      VHDL para Simulación y Verificación. 135

9.1       Introducción. 135

9.2       Bancos de Prueba. 135

9.2.1        Vectores de prueba. 136

9.2.2        Diseño de un Banco de Pruebas. 136

9.2.3        Manejo de tiempo en simulaciones usando VHDL. 137

9.2.3.1     Uso del WAIT y AFTER.. 137

9.2.3.2     Función NOW... 138

9.3       VHDL (Generalmente) No Sintetizable. 139

9.3.1        Instrucciones de lazo FOR, WHILE y LOOP, NEXT y EXIT. 139

9.3.2        Instrucciones ASSERT y REPORT. 142

9.3.3        Manejo de Archivos y Paquete TEXTIO.. 143

9.3.4        Palabra reservada ALIAS. 145

9.3.5        Ejemplos de Componentes para Bancos de Prueba. 146

9.3.5.1     Generación de Señal de Reloj 146

9.3.5.2     Generación de una Señal de Reset 147

9.3.5.3     Temporizado de la Interfase de un Bus de Microcontrolador 148

9.4       Que Falta sobre VHDL…... 152

10        Buenas Prácticas de Diseño. 153

10.1     Introducción. 153

10.2     Documentación. 153

10.3     Guía de estilo para el código HDL. 153

10.4     Programación para Diseños Sintetizables. 156

10.4.1      Diferencias entre Síntesis y Simulación. 156

10.4.2      División de la Frecuencia Mediante Habilitación del Reloj 156

10.5     Guía de Estilo Para un Buen Diseño de Hardware. 159

11        SoCs, Cores y Propiedad Intelectual 162

11.1     Introducción. 162

11.2     Presentación de un Core. 162

11.3     Diseño para Verificación (Design For Test) 162

11.4     Reutilización de Propiedad Intelectual 162

12        Notas Sobre Síntesis con FPGAs. 163

12.1     Introducción. 163

12.2     Diseño y Optimización Para Síntesis. 163

12.3     Formato Edif 163

12.4     Estructuras Recomendadas para Diseños Sintetizables. 163

12.4.1      Estructuras de Decisión Jerárquicas y Concurrentes (IF vs. CASE) 163

12.4.2      Procesos sincrónicos. 163

12.4.3      etc. 163

12.4.4      etc. 163

12.4.5      etc. 163

12.5     Ejemplos de estructuras sintetizadas. 163

13        Notas sobre Verificación. 165

13.1     Introducción. 165

14        Uso de las Herramientas. 166

14.1     Manejo Básico de Xilinx Project Manager 166

14.2     Manejo Básico de Altera Quartus II 166

14.3     Manejo Básico de Actel Libero (o la que sea gratuita) 166

14.4     Manejo Básico de ModelSim.. 167

15        Referencias. 169

15.1     Dispositivos Lógicos Programables. 169

Bibliografía. 169

Links de Interés. 169

15.2     Diseño Digital con PLDs. 170

Bibliografía. 170

Links de Interés. 170

15.3     VHDL. 170

Bibliografía. 170

Links de Interés. 170

15.4     Buenas Prácticas de Diseño. 171

Bibliografía. 171

15.5     Síntesis. 171

Bibliografía. 171

Links de Interés  (síntesis) 171

16        Ejemplos. 172

16.1     Ejemplos de Lógica Combinacional 172

16.2. 172

16.3     Ejemplos de Lógica Secuencial 172

16.4     Divisor Reloj 172

16.5     Control display 7 segmentos. 172

16.6     ... otros ejemplos de laboratorios hechos en clase... 172

16.6.1      Interfase Mouse. 172

16.6.2      Controlador VGA.. 172

16.7     Ejemplo Completo: UART. 172

16.8     etc, etc. 172

 

 


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.

 

Salvador Eduardo Tropea, del Instituto Nacional de Tecnología Industrial de Argentina (INTI - www.inti.gov.ar) me dio algunas sugerencias y me hizo notar algunos puntos que podían mejorarse. Gracias a esas sugerencias y sus ejemplos reescribí la sección sobre memorias, agregué algunos comentarios a la sección de VHDL  no sintetizable (que en muchos casos sí es sintetizable) y cambié algunos ejemplos que eran muy específicos de Xilinx.

 

 

 

 


2       Versiones

Ver 0.5 (27/06/2005)
Publicación inicial en www.fpga.com.ar  

 

Ver 0.6 (29/06/2005)
Sección de Agradecimientos y Versiones.
Fuentes en las figuras y tablas de terceros
Cambios en la implementación de máquinas de estado (no se si aclaran algo o no:)
Cambios en la descripción de memorias y su uso en VHDL
Algunas notas sobre VHDL sintetizable y no sintetizable
Cambios en la sección sobre primitivas
Traté de usar términos aceptados en castellano en vez de mis "castellanizaciones"
Varias correcciones y cambios menores

 

 


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:

 

 

Esta es la primera versión de estas notas, y seguramente contiene errores, omisiones o temas que pueden presentarse de una manera más didáctica. Por favor hacer llegar cualquier duda, comentario o crítica que ayude a mejorarlas en el foro o wiki del sitio www.fpga.com.ar.

 

 


4       Temas Básicos de Diseño Digital

 

COMPLETAR CON ALGUNAS NOTAS SOBRE DISEÑO DIGITAL PARA PODER METER LAS FPGAS y HDLs EN CONTEXTO.

 

4.1       Diseño Combinacional y Secuencial

4.1.1       Flip-Flops y Latches

 

4.2       Diseño Secuencial Asincrónico y Sincrónico

 

4.3       Algunas Notas sobre Diseño Secuencial Sincrónico

4.3.1       Temporizado y Utilización de Registros

4.3.2       Distribución de Reloj

4.3.3       Máxima Frecuencia de Trabajo

4.3.4       Pipelines

4.3.5       Dominios de Reloj

4.3.6       Metaestabilidad en los Flip-Flops

 

4.4       Autómatas de Estados Finitos (Máquinas de estados finitos)

4.4.1       Máquinas de Mealy

4.4.2       Máquinas de Moore

4.4.3       Codificación de estados. Mínima, One-hot, One-cold, Grey, etc.

 

4.5       Integridad de Señal

4.5.1       Que afecta la integridad de señal y que es. Como afecta fuera y dentro del chip (FPGA?)

Ver nota Altera de PLD design line. Chip-level concerns include improper I/O buffer design and inadequate return-current paths. Package-level issues include high package inductance, mismatched traces, improper routing and inadequate return-current paths, while board-level issues include crosstalk, reflections, signal attenuation and EMI/EMC.

 

4.5.2       Terminaciones de Señales

Usar terminaciones para evitar rebotes en diseños de alta velocidad. Terminaciones internas en las FPGAs.

 

4.6       Interfaces Eléctricas

Estándares de interfase posibles con las FPGAs actuales. Resistencias de pull-up/down internas. Flancos lentos y rápidos. etc.,

 

4.7       Potencia y Consumo de los Circuitos

Puede ser importante. Potencia estática vs dinámica. Dificultoso de calcular para las FPGA. Hay herramientas que analizan y calculan. Hay que analizar los requerimientos de la aplicación para ver si la potencia es una limitación y/o diseñar las fuentes de alimentación (aplicaciones móviles con baterías, etc.).

 

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.

 

 

 

 


5       Diseño Digital con FPGAs y HDLs

Para poder atacar un problema complejo (sistema) la mejor manera que tenemos es dividirlo. De esta manera se pueden atacar problemas de menor complejidad y mas fáciles de analizar. Este es el camino que generalmente usamos  para diseñar un sistema digital. Las decisiones que se tomen al principio para dividir el problema pueden afectar el resultado final. En algunos casos debemos volver al principio y replantear la arquitectura después de haber resuelto el problema. La experiencia y conocimientos sobre el problema, las posibles soluciones y la tecnologías disponibles ayudarán a que la decisión que se tome sea la mas acertada. Este proceso se esquematiza en la Figura 1.

 

Figura 1 Esquema del proceso de diseño de un sistema complejo

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. 

 

Especificación - Arquitectura - Diseño lógico - Layout (disposición y conexionado)

 

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.

 

Un sistema digital y sus componentes pueden definirse a distintos niveles de abstracción y en tres dominios diferentes: Comportamiento, estructural y físico. En la Figura 2 se muestra el diagrama "Y" de Gajski y Kahn que representa los niveles de abstracción y dominios para un circuito.

 

Figura 2 Diagrama de Gajski - Kahn

 

Dominio Comportamiento: Describe lo que hace un sistema (funcionamiento)

            Nivel Algoritmo: Describe el comportamiento del sistema como operaciones sobre las entradas para producir las salidas deseadas sin detallar los cambios en el tiempo ni las señales internas.

            Nivel RTL: Describe el comportamiento de todas las señales (entradas, internas y salidas) en el tiempo (para cada ciclo de reloj en sistemas sincrónicos)

 

Dominio Estructural: Describe al sistema como una interconexión de componentes (esquemático)

            Nivel P-M-S (Processor Memory Switch): Describe la estructura como la interconexión de elementos de procesamiento, memoria e interconexión, sin mayores detalles de implementación.

            Nivel Registros: Describe la estructura como la interconexión de registros y lógica de interconexión.

 

Dominio Físico: Describe la implementación física del sistema (plano).

 

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.

 

5.1       Metodología General de Diseño Digital

Al desarrollar cualquier sistema digital es importante seguir ciertas pautas de trabajo y tener en cuenta factores muy diversos para que el diseño pueda terminarse a tiempo y funcione correctamente. A medida que los diseños se hacen más complejos, la necesidad de seguir un método ordenado para lograr buenos resultados se hace más importante. Los lenguajes de descripción de hardware, si se utilizan correctamente, pueden utilizarse en varios pasos del proceso de desarrollo, no solo para diseñar sino también para especificar y documentar el sistema que se quiere desarrollar.

 

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.

 

Como ejemplo, en la Figura 3 se muestra un esquema de un método que permite ordenar el trabajo de diseño. Según su autor (ver Referencias), la "Metodología Universal de Diseño" define pasos que permiten:

 

·        Diseñar un dispositivo libre de defectos de manufactura, que funciona de manera adecuada y se integra con el sistema.

·        Diseñar el dispositivo de manera eficiente, sin malgastar recursos ni tiempo.

·        Planificar el diseño de manera eficiente, crear un cronograma razonable y asignar los recursos necesarios para las diferentes tareas de manera ordenada.

 

En muchos casos el proceso es no lineal. Si se descubren fallas o problemas en las especificaciones, se debe volver a iterar sobre los pasos anteriores para corregirlos.

 

El ciclo comienza con un conjunto de requerimientos para la fabricación de un dispositivo o sistema. Estos requerimientos pueden venir de un cliente, de otro grupo de trabajo dentro de la misma empresa o del mismo grupo de trabajo que necesita desarrollar una parte de un sistema mas grande.

 

Figura 3 - Metodología Universal de Diseño

 

5.1.1       Especificación y Diseño

Una especificación permite que todas las personas involucradas en un proyecto comprendan cual es el dispositivo que se va a desarrollar. Las personas que forman parte de un proyecto incluyen no solo a los desarrolladores, sino también a clientes, gerencia, personal de otras áreas de la empresa, etc.

 

Las especificaciones deberían describir la solución de manera de cumplir con los requerimientos que se piden para el dispositivo. Al haber una especificación formal, las bases sobre las que trabajar en un diseño quedan preestablecidas y se minimizan los errores por diferencias de apreciación o entendimiento entre los participantes.

 

Una especificación debería comprender los siguientes puntos:

 

·        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.

 

La especificación es un documento activo, que se modifica de acuerdo en los cambios de requerimientos y a medida que se tiene más información sobre el proyecto.

 

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:

 

 

5.1.3       Pasos Finales

Si todos los pasos se siguieron correctamente la revisión final debería ser solo una formalidad. Se verifica que el dispositivo está listo para ser entregado o integrado al sistema.

 

La integración y verificación en el contexto del sistema general es muy importante. Si los pasos se siguieron correctamente, cualquier modificación que surja de esta integración será en general pequeña y no requerirá grandes cambios.

 

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.

 

5.2       Diseño Digital Utilizando Lenguajes de Descripción de Hardware

Los lenguajes de descripción de hardware (HDLs) permiten modelar sistemas digitales completos. Mediante diferentes herramientas de software estos modelos pueden luego sintetizarse para implementarlos como circuitos reales. La utilización de HDLs para sintetizar sistemas digitales y la utilización de PLDs permiten crear prototipos funcionales en plazos relativamente cortos. Esto hace que todo el proceso de desarrollo de un sistema digital sea mucho más simple y rápido en comparación con metodologías clásicas (desarrollo con discretos sobre PCBs o el diseño de circuitos integrados).

Los modelos de hardware usando HDLs pueden ser estructurales, de comportamiento o una mezcla de estos dos. A nivel estructural se describe la interconexión y jerarquía entre componentes. A nivel de comportamiento de hardware se describe la respuesta entrada/salida de un componente. El comportamiento de un sistema puede modelarse a distintos niveles de abstracción o detalle: algoritmos y comportamiento general, nivel de transferencia de registros, nivel de compuertas, etc. El tipo de modelo más usado para síntesis es el denominado RTL (Register Transfer Level), o de nivel de transferencia de registros. Existen herramientas que permiten sintetizar circuitos a partir de modelos de abstracción más elevados, pero en general lo hacen llevando el diseño a un nivel de descripción como RTL antes de sintetizarlo.

La utilización de HDLs para síntesis puede tener como objetivo la creación de un circuito integrado de propósito específico (ASIC) o la implementación del circuito en alguna lógica programable (PLD). Independientemente del objetivo, no todas las construcciones posibles de los lenguajes de descripción de hardware pueden sintetizarse y transformarse en circuitos. Esto puede deberse a las limitaciones de las herramientas utilizadas o a que el circuito descrito por el modelo VHDL no puede implementarse físicamente. En general el diseñador debe seguir ciertas pautas de modelado, que dependerán de su objetivo y de las herramientas que utiliza, para que el modelo pueda sintetizarse. Esto es aún más importante para lograr implementaciones óptimas sobre la arquitectura para la que se está diseñando el circuito.

 

5.3       Flujo de Diseño para Lógicas Programables

Cuando se diseña con lógicas programables, cualquiera sea el método usado para diseñar el circuito (HDLs, esquemáticos, etc.), el proceso desde la definición del circuito por el desarrollador hasta tenerlo funcionando sobre un PLD implica varios pasos intermedios y en general utiliza una variedad de herramientas. A este proceso se lo denomina ciclo o flujo de diseño.

5.3.1       Flujo de Diseño (Design Flow)

Durante el proceso de creación de un sistema digital desde el código fuente (esquemáticos, VHDL, etc.) a la implementación en un PLD hay varios pasos intermedios. Para cada uno de estos pasos se utilizan herramientas de software diferentes que pueden o no estar integradas bajo un ambiente de desarrollo. En muchos casos las herramientas utilizadas en cada paso del diseño son provistas por diferentes empresas. La Figura 4 muestra el ciclo de diseño típico para lógicas programables. Dependiendo de las herramientas utilizadas, este ciclo puede tener variaciones o las tareas llamarse con otros nombres.

A continuación se describe cada uno de los pasos del ciclo de diseño. Se agrega su denominación en inglés entre paréntesis, ya que estos son los términos que se encontrarán en las herramientas de desarrollo.

·        Descripción del Diseño: este es el paso en el que se describe el diseño, muchas veces usando un lenguaje de descripción de hardware como el VHDL. Muchas herramientas permiten ingresar el diseño no solo como HDLs sino también como un diagrama esquemático o estructural, una representación gráfica de una máquina de estados o una tabla de entrada-salida. Estas herramientas simplifican en gran medida el diseño y simplifican mucho la tarea del diseñador. El código HDL puede ingresarse utilizando cualquier editor de texto, pero se recomienda uno que tenga coloreado automático de sintaxis ("syntax highlighting") ya que ayuda y hace más fácil esta etapa.

 

Figura 4 - Flujo de diseño para lógicas programables

 

·        Generación o Traducción (Generate, Translate): Este paso tiene sentido cuando el diseño se hace mediante algunas de los métodos mencionados anteriormente en vez de en VHDL. En este paso se traducen todos los módulos a VHDL. Para los módulos ingresados como VHDL, las herramientas generalmente hacen una copia a una librería interna. En esta etapa se hace un análisis del VHDL para verificar la sintaxis y semántica de los módulos. También se hace una elaboración de los archivos, que consiste en replicar los componentes que se utilizan más de una vez en el diseño para hacer copias únicas y definir un conexionado adecuado.

·        Compilado (Compile): Los simuladores actuales compilan el código VHDL a un formato que permite una simulación mas rápida y eficaz. Esto se hace en este paso.

·        Simulación y verificación: En este paso se simula el comportamiento del diseño y se evalúa su comportamiento. La simulación puede hacerse en tres etapas diferentes del diseño. La primera es sobre el código VHDL original para verificar el correcto funcionamiento del diseño. La segunda es después de sintetizar el circuito, y se simulan la implementación real sobre el PLD, ya sea con o sin la anotación de tiempos. La tercer etapa en la cual se puede simular el diseño es después de la Ubicación e Interconexión. Esta es la más exacta y la mas engorrosa y lenta, ya que incluye la información final lógica y temporal el diseño sobre el PLD.

·        Síntesis (Synthesis): En este paso se traduce el VHDL original a su implementación con lógica digital, utilizando los componentes específicos del PLD que va a utilizarse. Esta traducción puede llegar hasta el nivel más básico de elementos lógicos (CLBs, LUTs, FFs) o hasta un nivel superior, en el que el diseño se presenta en módulos básicos estándar provistos en una librería por el proveedor del PLD.

·        Ubicación e Interconexión (Place and Route): El PLD está compuesto por muchos bloques idénticos, como se presentó en las secciones anteriores. En este paso, cada componente del diseño sintetizado se ubica dentro del PLD específico. También se interconectan los componentes  entre sí y con los pines de entrada-salida.

·        Tareas Adicionales: Las tareas adicionales dependen del fabricante y las herramientas. Puede definirse la interconexión de las con los pines físicos del PLD ingresar condiciones de entorno físico para guiar a la herramienta de Ubicación e Interconexión, seleccionar áreas del PLD para ubicar los bloques lógicos, etc.

·        Anotación de Retardos: Como en todo circuito digital, las señales tendrán un retardo de propagación que influirá sobre su comportamiento. Con estos retardos puede anotarse el diseño compilado para una simulación que incluya información de temporizado mas cercana a la implementación real. Una vez sintetizado el diseño, puede hacerse una estimación de los retardos de propagación que habrá entre las señales. Después de la ubicación e interconexión, el cálculo de retardos es mucho mas exacto.

·        Generación de Binarios: Después de la Ubicación e Interconexión se genera algún archivo ya sea para poder utilizar el sistema en un diseño mas complejo o para programar un PLD.

·        Configuración de PLD: Con el archivo binario generado puede configurarse directamente un PLD a través de alguna de las opciones de configuración. Estas opciones dependerán de las herramientas y del PLD que se esté utilizando.

·        Programación de Memoria (PROM): Muchas FPGA no pueden configurarse de manera permanente y requieren algún tipo de memoria para leer la configuración cuando se les aplica tensión de alimentación. En la etapa de producción deben configurarse memorias PROM y conectarlas a la FPGA en el circuito impreso.

·        Verificación (automática): Una vez integrada la FPGA con su programación al sistema debe hacerse una verificación para controlar que el diseño sobre en la FPGA funciona bien (las FPGAs pueden tener fallas internas) y que la FPGA se integra bien al sistema en el que está. Pueden usarse técnicas y herramientas de verificación automáticas para evaluar si el dispositivo y el diseño están  funcionando como debieran.

 

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       Lenguajes de descripción de hardware

Los lenguajes de descripción de hardware (HDLs) permiten modelar sistemas digitales completos. Al utilizar un HDL para modelar un sistema, es importante recordar que se está modelando hardware, y no escribiendo software. El software se caracteriza por ser de secuencial, una CPU ejecutará cada instrucción después de la anterior. Los efectos de una instrucción dependen exclusivamente de los efectos de las instrucciones anteriores. En el hardware, sin embargo, hay muchas tareas que suceden de manera concurrente y la variable tiempo juega un papel predominante. Un cambio en el tiempo de  propagación de una compuerta, el retardo de una traza en una plaqueta, o el no cumplir con los tiempos de establecimiento de un circuito puede cambiar de manera radical el comportamiento de un sistema electrónico digital. Para poder modelar hardware los HDLs permiten describir la concurrencia y paralelismo que se observa en un sistema de hardware (muchas cosas y muchas señales cambian al mismo tiempo).

Usando HDLs, los sistemas digitales pueden describirse de diferentes maneras. Estos modelos pueden ir desde el nivel abstracto de un algoritmo o el comportamiento general de un circuito hasta un modelo al nivel de interconexión compuertas lógicas. En una descripción estructural, se definen de manera precisa las interfases de cada componente de un sistema y sus interconexiones. Así se arma un jerarquía de componentes, desde los más básicos hasta el nivel superior que describe el sistema completo. Los HDLs también permiten describir el comportamiento de los componentes. Para poder describir los procesos concurrentes que caracterizan un sistema de hardware. Utilizando un conjunto de instrucciones secuenciales puede modelarse el comportamiento de un sistema digital y controlar la variable tiempo en los modelos.

Aunque hay muchos lenguajes de descripción de hardware, dos predominan actualmente el mundo del desarrollo de hardware digital: Verilog y VHDL. De los demás lenguajes, muchos son propietarios, desarrollados por los distintos proveedores de herramientas o PLD. En la actualidad casi todos los fabricantes de PLD y proveedores de herramientas de desarrollo proveen soporte para VHDL y Verilog. En la actualidad están surgiendo nuevos lenguajes que incorporan mayores facilidades y prestaciones, de acuerdo a las nuevas tecnologías y necesidades de los desarrolladores. A continuación se presenta una breve introducción a cada lenguaje

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.

 

Muchos vendedores de FPGAs proveen herramientas o "toolboxes" que se integran a lenguajes de modelado como Matlab y Simulink. Una vez probado un algoritmo con estas herramientas se genera de manera automática el hardware necesario para implementarlo.

 

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       Herramientas de Desarrollo

La facilidad de desarrollo de sistemas sobre PLDs depende en gran medida del software y hardware que permite crear y probar los diseños de una manera simple y eficiente. Al conjunto de estas aplicaciones se los denomina herramientas de desarrollo. A continuación se describen algunas características de estas herramientas para los distintos pasos del ciclo de diseño.

5.5.1       Descripción del Diseño

En la creación de fuentes se usan diferentes herramientas para facilitar el diseño. Algunas herramientas comunes:

Estas herramientas incluyen: Modelos de comportamiento. Diferentes niveles. Interfases gráficas, etc.

5.5.2       Generación o Traducción

Se lleva todos los tipos de fuentes, tales como representaciones gráficas de máquinas de estado o diagramas esquemáticos. a un lenguaje de descripción de hardware. Los más comunes son VHDL o Verilog.

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.

5.5.4       Notas Manejo del tiempo en VHDL

La simulación en VHDL se basa en incrementos finitos de tiempo. El paso de simulación estará dado por el tiempo especificado en el código para cambios en las señales o por un factor denominado retardo delta ("delta delay"). Este retardo delta es un micro-paso de simulación que se utiliza cuando no se especifica un retardo en la asignación del valor de una señal. Puede haber una cantidad indefinida de retardos delta en un paso de simulación. En la descripción que sigue se mencionan de manera general algunas características de VHDL. Aunque todavía no se ha presentado ninguna característica específica del lenguaje, el lector con una base de diseño de hardware podrá seguirla sin problemas. Un proceso en VHDL es la descripción de un bloque de hardware que actúa de manera concurrente (al mismo tiempo) con todos los demás procesos.

 

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.

 

Al comenzar la simulación (tiempo de simulación cero) se asigna valores iniciales a las señales. Después de asignar los valores a las señales, se ejecutan todos los procesos hasta que estos lleguen a un estado de reposo. En general, los procesos incluirán asignaciones de nuevos valores para algunas señales. Estos cambios o asignaciones en los valores de las señales se agendan para un tiempo posterior. Las señales recién se actualizarán después de un retardo, nunca inmediatamente.

 

 

Figura 5 - Ciclo de simulación

 

 

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.

 

A continuación se presenta un ejemplo para explicar mejor el proceso de simulación en VHDL. La Figura 6 muestra un circuito digital y los valores iniciales de las señales A, B, 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’.

 

 

Figura 6 - Circuito digital combinacional

 

La siguiente tabla muestra los pasos en la simulación al cambiar la señal A de 1 a 0 a los 50 ns. Cuando cambia A se evalúan los procesos a los que afecta esa señal. El único proceso que se dispara es el inversor, y su salida X se agenda para cambiar de 0 a 1. En delta 2 se cambia la señal X y se observa a que procesos afecta. Se agendan para cambiar las señales Y y C. En delta 3 se cambian esas señales y se nota que solo se afecta el proceso AND de salida. Se agenda el cambio de C y en delta 4 se cambia C  a su valor final.

 

Tabla 1 Ejemplo del pasos de simulación y cambios en las señales

Tiempo

Delta

A

B

X

Y

C

Proceso

0 ns

 

1

1

0

1

0

Entrada y salidas estables

50 ns

0

0

1

0

1

0

Cambio en la entrada A. Evaluar inversor

 

1

0

1

1

1

0

Cambio en X. Evaluar NAND, Evaluar AND

 

2

0

1

1

0

1

Cambio en Y, C. Evaluar AND

 

3

0

1

1

0

0

Todos los procesos en reposo (actualización de salida definitiva)

 

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.

 

 

 


6       Dispositivos Lógicos Programables

Los dispositivos lógicos programables son circuitos integrados digitales que no tienen una función predefinida por el fabricante. Su función puede ser definida (o programada) por el usuario. Permiten reemplazar grandes diseños digitales que antes se implementaban con componentes discretos (como compuertas y flip-flops) por un solo integrado. Debido a la gran capacidad lógica que tienen los dispositivos modernos, sistemas completos pueden desarrollarse sobre un solo circuito integrado. Esto da lugar a las denominaciones System-on-a-Programmable Chip, o SoPC (sistema sobre un circuito integrado programable) y System-on-a-Reprogammable Chip (SoRC).

 

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:

 

 

En resumen, la facilidad de uso de herramientas de desarrollo para PLDs ayudan a que una gran cantidad de usuarios puedan rápidamente desarrollar un sistema utilizando PLDs.

 

6.1       Evolución de los Primeros Dispositivos Lógicos Programables

 

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.

 

Los primeros dispositivos diseñados específicamente para implementar funciones digitales programables fueron los PLA, introducidos al mercado en la década de 1970 por Philips.

 

Figura 7 - Esquema de un PLA

 

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.

 

Debido a las limitaciones en la velocidad de las conexiones programables y los problemas en el proceso de manufactura de las PLA, surgieron dispositivos con un solo nivel de lógica programable denominados PAL (recordar que los PLA tienen dos niveles programables: un nivel AND y un nivel OR). Los PAL se basan en el mismo principio que las PLA, pero tienen un nivel de lógica AND programable mientras el nivel de lógica OR es fijo. Esto limita la cantidad de funciones que pueden definirse con un dispositivo 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.

 

 

Figura 8 - Esquema 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 9 - Diagrama funcional de una GAL 22V10 de Lattice Semiconductors
(Fuente: hoja de datos de Lattice Semiconductors GAL 22V10 - www.latticesemi.com)

 

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.

 

 

Figura 11 - Estructura funcional de los CPLD MAX7000 de Altera
(Fuente: hoja de datos de Altera Familia MAX7000 - www.altera.com)

 

 

Figura 12 - Esquema de una macrocelda de los CPLD MAX7000 de Altera
(Fuente: hoja de datos de Altera Familia MAX7000 - www.altera.com)

 

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.

 

Figura 13 - Esquema básico de la arquitectura de una FPGA

 

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:

 

 

 Figura 14 - Diagrama en bloques de una FPGA Spartan IIe de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 2e www.xilinx.com)

 

En las siguientes figuras se muestran algunos ejemplos de la arquitectura general de algunas FPGAs de distintos fabricantes.

 

Figura 15 - Diagrama en bloques de una FPGA Cyclone II EP2C20 de Altera
(Fuente: hoja de datos Altera Familia Cyclone 2 www.altera.com)

 

Figura 16 - Arquitectura de una FPGA ProAsicPlus de Actel
(Fuente: hoja de datos Actel Familia ProAsicPlus www.actel.com)

 

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.

6.3.1       Bloque Lógico Programable

Todas las FPGA tienen algún tipo de bloque lógico programable. Este es el corazón de la FPGA, y permite implementar las diferentes funciones lógicas. En la Figura 17 se muestra un esquema del bloque lógico programable (CLB) de una FPGA de la familia Spartan IIe de Xilinx.

 

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 recursos para implementar circuitos secuenciales y operaciones aritméticas eficientes. La Figura 18 muestra estos componentes en más detalle para un ‘slice” del CLB.

 

 

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 elementos que permiten implementar lógica secuencial son los elementos de almacenamiento que se ven sobre las salidas del “slice”. Estos pueden configurarse como flip-flops D con reloj o como latches controlado por nivel.

 

Como ejemplos, y sin entrar en detalles, en la Figura 19 y Figura 20 se muestran dos ejemplos de bloques lógicos para otras FPGAs. Hay FPGAs que tienen bloques configurables mas simples y otras (especialmente las de última generación) cuyos bloques lógicos son bastante más complejos.

 

Figura 19 - Esquema del CLB de una FPGA Spartan 3 de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 3 www.xilinx.com)

Figura 20 - Esquema del Elemento Lógico de una FPGA Cyclone II de Altera
(Fuente: hoja de datos Altera Familia Cyclone II
www.altera.com)

 

6.3.2       Bloque  de Entrada / Salida

Las interfaces de entrada-salida son otro de los componentes particulares que tienen las FPGAs. La familia de FPGAs Spartan IIe de Xilinx, por ejemplo, divide las entradas/salidas del integrado en bancos que se pueden configurar para tener una interfase con lógica de diferentes estándares eléctricos de manera independiente. Los bancos se configuran aplicando diferentes tensiones de alimentación a los pines denominados VccO y VREF.  Al utilizar diferentes valores de VccO para los distintos bancos se podrá tener un sistema con interfase a diferentes familias lógicas dentro de la misma FPGA. Las entradas de reloj están asociadas a diferentes bancos de entrada-salida, para permitir que haya diferentes dominios de reloj con interfases eléctricas diferentes. La Figura 21 muestra un esquema de estos bancos de entrada-salida.

 

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.

 

Internamente, cada bloque de entrada-salida de la familia Spartan IIe de Xilinx tiene la estructura mostrada en la Figura 22.  Los elementos de entrada-salida de las FPGAs de Altera Cyclone II tienen la estructura mostrada en la Figura 23.

 

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)

 

Figura 23 - Esquema de un bloque de entrada-salida de una FPGA Cyclone II de Altera
(Fuente: hoja de datos Altera Familia Cyclone II www.altera.com)

 

 

Los bloques de entrada-salida de muchas FPGAs tienen elementos de almacenamiento integrados que permiten controlar mejor los tiempos de propagación entre las patitas (pines) del integrado y la lógica interna. Además cada bloque de entrada-salida cuenta con “buffers” programables que pueden configurarse para tres estados y colocar la salidas de la FPGA en alta impedancia (estado ‘Z’).

6.3.3       Bloque de Control de Reloj

El sistema de control del reloj consiste en bloques de control integrados a la red de distribución de reloj. La red de distribución de reloj en las FPGA asegura retardos parejos a todos los bloques lógicos de la FPGA. Cada fabricante utiliza una arquitectura diferente para el control y distribución de reloj. La siguiente  Figura 24 muestra el esquema de distribución de reloj para la familia Spartan IIe de Xilinx.

 

 

Figura 24 – Red global de distribución de reloj en la FPGA Spartan IIe de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 2e www.xilinx.com)

A continuación se presentan dos ejemplos de bloques de control para FPGAs de diferentes fabricantes.

 

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.

 

Figura 26 –Esquema de un bloque de control de reloj de la FPGA Stratix de Altera
(Fuente: hoja de datos Altera Familia Stratix www.altera.com)

 

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.

 

La Figura 27 muestra un esquema de una celda de memoria básica de la familia Spartan IIe de Xilinx. Este bloque se denomina BLOCK RAM y es una memoria de puerto dual (dual-port), que puede leerse y escribirse al mismo tiempo.

 

Figura 27 – Diagrama de un bloque de memoria de la FPGA Spartan IIe de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 2e www.xilinx.com)

 

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 datos (bits)

Profundidad de la memoria

Bus de direcciones

Bus de datos

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.

 

La Figura 28 muestra un bloque de memoria de Actel, que puede configurarse como memoria de puerto simple, dual o multi-puerto.

Figura 28 -Esquema de un bloque de memoria de Actel configurada como memoria multi-puerto
(Fuente: Nota de Aplicación de Actel: "Implementing Multi-Port
Memories in Actel ProAsicPlus Devices" - www.actel.com)

6.3.5       Bloque de Procesamiento de Señal

Varias FPGA contienen bloques específicos que optimizan en hardware ciertas funciones especiales. Las FPGA de la familia Stratix de Altera, por ejemplo, contienen uno o más módulos de procesamiento de señal entre los bloques de lógica programable de propósito general. Estos bloques permiten desarrollar ciertas funciones específicas típicas de las aplicaciones de procesamiento de señal de manera muy eficiente. Pueden configurarse de varias maneras diferentes según las necesidades del usuario. Como muestra la Figura 29, este bloque contiene lógica para implementar operaciones de multiplicación-acumulación que requerirían de muchos recursos y ciclos de reloj si se implementaran utilizando 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.

 

Figura 29 – Bloque de procesamiento de señal de la familia Stratix de Altera
(Fuente: hoja de datos Altera Familia Stratix www.altera.com)

6.3.6       CPUs Embebidas

La familia de FPGAs de Xilinx Virtex II-PRO contiene una CPU Power PC 405 de IBM y lógica de interconexión embebida dentro de lógica programable. Esto permite utilizar toda la potencia de una CPU integrada con la flexibilidad de los periféricos diseñados mediante lógica programable. Los bloques específicos integrados en el silicio de las FPGAs se denominan "hardcores". La Figura 30 muestra un esquema de la arquitectura del Virtex II-PRO.

 

Figura 30 - CPU PC405 embebida en una Virtex II Pro de Xilinx
(Fuente: hoja de datos Xilinx Familia Virtex 2 Pro www.xilinx.com)

 

 

Altera ofrece la FPGA Excalibur que contiene un microcontrolador ARM922T integrado a un costado de lógica programable. La lógica programable del Excalibur  puede ser de hasta un millón de compuertas. El micro es de arquitectura RISC de 32 bits, y puede correr a una frecuencia de reloj de hasta 200 MHz.

 

Por otro lado también pueden diseñarse microcontroladores o procesadores usando solamente la lógica de configuración de las FPGAs. Altera ofrece el microcontrolador Nios, de tecnología RISC de 16 bits que puede utilizarse sobre varias de las FPGA de Altera. A este tipo de diseño se lo denomina "softcore", ya que a FPGA no tiene ningún bloque específico para la CPU implementado sobre el circuito integrado. Hay muchos micros "softcore" públicos y propietarios. Xilinx ofrece el Microblaze y Actel ofrecerá un micro de la familia ARM.

 

6.3.7       Matriz de Interconexión

Para poder implementar circuitos lógicos, los elementos lógicos presentados en las secciones anteriores no solo deben configurarse adecuadamente sino que también deben conectarse entre si. La estructura de interconexión interna de un PLD consiste en un conjunto de alambres o trazas que pueden conectarse mediante elementos de conexión programables. Las herramientas de “localización e interconexión” (place and route) son las encargadas de decidir en que elementos lógico se implementará la lógica diseñada por el usuario y como deben programarse las interconexiones para que el diseño funcione según las especificaciones de tiempo y retardos que se han definido.

 

A modo de ejemplo, se describirá a continuación la arquitectura de interconexión de las FPGA Spartan IIe de Xilinx. Estas FPGA tienen dos niveles de interconexión. Por un lado tienen una interconexión de propósito general a través de la matriz de interconexionado general o GRM por sus siglas en inglés. Por otro lado contienen recursos de interconexión local. Además de los ya mencionados, las FPGA Spartan IIe contienen recursos de interconexión dedicados a señales de tres estados, de entrada-salida y recursos de interconexión global para la distribución de reloj y señales específicas.

 

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.

 

La mayor parte de las señales se conectarán a través de la matriz general de interconexionado (GRM). Los elementos de la GRM se encuentran entre los CLB, en los canales de interconexión horizontales y verticales de la FPGA. Permiten hacer la interconexión entre las trazas horizontales y verticales y hacia los CLB. A través de ellos se configuran las conexiones entre CLBs no adyacentes y hacia los bloques de entrada/salida.

 

Los recursos de interconexionado global que no forman parte de la GRM permiten distribuir señales con un fan-out grande, como son las señales de reloj y posiblemente las señales de reset. La Figura 32 muestra un esquema de la red dedicada de distribución de señales de alto “fan-out”. Esta red de distribución global tiene dos niveles y puede llevar las señales de reloj a todos los bloques lógicos con poca diferencia de tiempo (skew) entre ellos.

 

Figura 31 - Caminos de interconexión local en la FPGA Spartan IIe de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 2e www.xilinx.com)

Figura 32 - Red dedicada de distribución de reloj en la FPGA Spartan IIe de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 2e www.xilinx.com)

 

6.4       Granularidad de los Dispositivos Lógicos Programables (PLDs)

La granularidad de un dispositivo lógico programable está dada por la funcionalidad básica que provee cada bloque de configuración lógica, o la relación entre las celdas lógicas y los recursos de interconexionado. Algunos parámetros para definir la granularidad de un dispositivo programable son:

·   Número de funciones que puede implementar cada celda lógica

·   Número de compuertas NAND de dos entradas equivalente por cada celda lógica

·   Número total de transistores por celda lógica

·   Área total normalizada de lógica configurable (relación de área  lógica/área de interconexionado)

·   Número de entradas y salidas por celda lógica

 

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..

 

La granularidad de un dispositivo lógico influirá en la manera que se implemente una función lógica dada, en su frecuencia máxima de funcionamiento y en la utilización que se hace del dispositivo.

 

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.

 

Algunas características de cada tipo de arquitectura son las siguientes:

 

Arquitecturas con granularidad fina

·   Celdas implementan funciones lógicas parciales de n entradas

·   Relación de entradas a registros por celda muy baja (2/4 a 1)

·   Ejemplo: ProAsicPlus de Actel

 

Figura 33 Bloque Lógico (Logic Tile) de la ProAsicPlus de Actel
(Fuente: hoja de datos Actel Familia ProAsicPlus -
www.actel.com)

Arquitecturas con granularidad media

·   Celdas implementan funciones completas de n entradas

·   Relación de entradas a registros por celda de 6/8 a 1

·   Buenas para implementar máquinas de estado y lógica secuencial compleja

·   Ejemplo: Xilinx Spartan 3:

 

Figura 34 Slice de Spartan 3 de Xilinx
(Fuente: hoja de datos Xilinx Familia Spartan 3
www.xilinx.com)

 

 

 

 

 

 

Arquitecturas con granularidad gruesa

·   Celdas estilo PLD de arreglos de términos

·   Relación de entradas a registros de 32 a 1

·   Buenas para lógica combinacional como decodificación de direcciones, funciones aritméticas,

·   Pobres para arquitecturas con colas (pipelines)

·   Ejemplo: Altera MAX 3000

 

Figura 35 Macrocelda de un CPLD MAX3000 de Altera
(Fuente: hoja de datos Altera Familia MAX3000
www.altera.com)

 

 

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

 

Figura 36 Unidad Funcional Programable PFU del ispXPGA de Lattice
(Fuente: hoja de datos Lattice Semiconductors Familia ispXPGA - 
www.latticesemi.com)

 

 

 

 

 

 

 

6.5       Tecnología de Configuración de los PLDs

La tecnología .utilizada para configurar los elementos de un PLD, ya sean los bloques lógicos o las interconexiones, dependen del fabricante y el dispositivo. Entre los dispositivos reprogramables, se destacan las tecnologías EEPROM, SRAM y Flash. Los dispositivos que solo pueden configurarse una vez en general utilizan tecnologías de antifusible. Cada tecnología tiene sus ventajas y desventajas respecto a las otras. En la Tabla 4 se resumen algunas de estas características

 

Tabla 4 Características de las Tecnologías de Configuración de PLDs

Tecnología

Ventajas

Desventajas

EEPROM

·      No volátil

·      Puede probarse en un 100%

·      Software simple

·      Tecnología base muy conocida

·      Requiere tensiones altas para configurar y borrar

·      Requiere programador

·      Mayor consumo de potencia

·      Tolerancia media a la radiación

·      Requiere mucha área para implementarse (integrados grandes)

SRAM

·      Reconfigurable. Puede cambiarse el diseño solo cambiando la PROM de configuración en la placa final

·      No requiere programador

·      Proceso de manufactura igual que la lógica

·      Puede probarse en un 100%

·      Tecnología integrada con la lógica (manufactura fácil, menor costo)

·      Volátil. Se debe reprogramar después de cortar la alimentación

·      Requiere memoria (PROM) externa

·      Tiempo de encendido “lento” (debe configurarse)

·      Mayor utilización de área en el integrado

·      No muy tolerante a la radiación

Flash

·      No volátil

·      Tiempo de encendido rápido

·      Menor potencia que SRAM

·      Menor área que SRAM y antifusible

·      Programable sobre la placa (no tan fácil)

·      Requiere programador

·      Requiere tensiones altas

·      La misma velocidad que SRAM

·      Menor cantidad de reprogramaciones

Antifusible

·      No volátil

·      Mayor densidad

·      Mucha tolerancia a la radiación (aplicaciones espaciales)

·      Tiempo de encendido muy rápido

·      Baja potencia

·      No pueden reconfigurarse

·      Requiere programador

·      No puede evaluarse. Si se comete un error, se pierde el integrado

 

A continuación se dan algunos ejemplos de dispositivos que utilizan cada tecnología.

 

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

 

6.6       Tendencias Actuales y Futuras

A continuación se nombran algunas tendencias que pueden observarse en la industria de de las lógicas programables, no solo de los dispositivos en sí sino de las herramientas y usos de estos dispositivos.

 

 

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.

 

6.7       Notas a Junio 2005

Estas notas se comenzaron a escribir en el 2003, y a Junio del 2005 muchos de los aspectos tecnológicos están des actualizados respecto de los dispositivos actuales, y algunos  comentarios sobre tendencias son una realidad. Parece imposible tratar de actualizar la información para reflejar las últimas tendencias en estas notas. Para eso se 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).

 

 

 


7       Primeros Pasos con VHDL

7.1       Notas Preliminares Sobre Formato de VHDL y los Ejemplos

Antes de continuar se describirán algunos puntos básicos para poder comprender los ejemplos y explicaciones que se presentan en las siguientes secciones.

7.1.1       Formato del Código de Ejemplo

En los ejemplos presentados en este texto se tratará de mantener las siguientes reglas para facilitar su comprensión y el aprendizaje de VHDL.

7.1.2       Capitalización en VHDL

VHDL no es sensible a la capitalización y no distinguirá las palabras que solo se diferencian por letras mayúsculas. Por ejemplo, las palabras begin, BEGIN, Begin y bEGin serán tratadas de la misma manera por el analizador de VHDL

 

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.

 

7.1.3       Comentarios en VHDL

Los comentarios en VHDL se indican con un doble guión “--". Abracan desde “--" hasta el final de la línea

 

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

 

7.1.4       Delimitadores de Código en VHDL

Las instrucciones en VHDL se terminan con “;” y aunque se pueden escribir varias instrucciones por línea esa práctica no se recomienda y no se usará en este texto.

 

Ejemplos:

            A <= ‘1’; -- Una asignación a la señal A

            B <= ‘0’; -- Una asignación a la señal B

            C <= ‘0’; D <= ‘1’; -- Doble asignación en una línea NO RECOMENDADO

 

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

 

 

7.2       Estructura Básicas de un Modelo en VHDL

Con VHDL, un módulo o componente de hardware se modela en dos secciones. Una es la interfase del componente, denominado entidad y la otra es la arquitectura que describe su funcionamiento interno. Este modelo permite esconder los detalles internos de implementación e incluso definir varias implementaciones para un componente sin afectar la interfase externa.

7.2.1       Entidades y Arquitecturas

La siguiente Figura 37 ilustra el concepto de definición de un componente en dos secciones y  presenta las palabras clave (en negritas) utilizadas por VHDL para definirlas. La primer sección declara el componente o entidad y define las señales de interfase Para declarar la entidad se utiliza la palabra reservada entity.

 

Figura 37 Declaración de un componente en VHDL

 

La estructura básica mas simple de la declaración se muestra con el siguiente ejemplo de la declaración de un contador de 6 bits.

 

 

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;

Cuadro 1 Declaración  de Entidad

 

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:

·        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_vector[1], 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.

 

En general la sección de arquitectura tendrá la estructura mostrada a continuación.

 

 

architecture Comportamiento of Contador is
  -- En esta sección se declaran las señales usadas en

  -- el modelo

 

  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

  

    -- .........

 

  end architecture Comportamiento;

Cuadro 2 Declaración  de arquitectura

 

El modelado del comportamiento puede ser de muchas maneras diferentes, pero en general pueden dividirse en dos categorías principales. Los modelos de comportamiento y los estructurales. Estos modelos se presentan por separado a continuación, pero debe tenerse en cuenta que VHDL no impone restricciones a mezclar los tipos de modelo dentro de una arquitectura, aunque esta no es una práctica recomendada.

7.2.2       Modelos de comportamiento

En los modelos de comportamiento el funcionamiento del componente se modela a través del comportamiento de las señales a través de compuertas y registros internos. Este modelo de funcionamiento puede ser en la forma de un algoritmo general, al nivel de transferencia de registros (register transfer level o RTL), flujo de datos o una mezcla de ellos. El elemento de construcción básico en el modelo de comportamiento en VHDL es el proceso (process).

 

En el siguiente ejemplo se muestra un proceso y una asignación concurrente que definen el comportamiento del contador de 6 bits declarado más arriba.

 

 

architecture Comportamiento of Contador is
  -- Declaración de las señales usadas en la arquitectura

  signal Cuenta_REG : std_logic(5 downto 0);

 

  begin – Comienzo de la especificación del comportamiento

  -- Conexión del registro con el puerto de salida

  Cuanta_OUT <= Cuenta_REG;

 

  -- Este proceso cuenta los ciclos de reloj en

  -- cada flanco ascendente de Clock_IN

  P_IncrementaCuenta : process(Reset_IN, Clock_IN)

    begin

    if Reset_IN = ‘1’ then

      Cuenta_REG <= “000000”; -- Reset vuelve todo a 0

    elsif (Clock_INevent and Clock_IN = ‘1’) then

      Cuenta_REG <= Cuenta_REG + 1; -- Incrementa cuenta

      end if;         -- Fin if(Reset, Clock)

    end process;      -- Fin de Proceso Incrementa Cuenta

  end architecture Comportamiento;

 

Cuadro 3 Modelo de comportamiento para un contador

 

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.

 

En el primer ejemplo se utilizan instrucciones concurrentes para asignar las salidas directamente. En el segundo ejemplo se utiliza un proceso que se disparará ante un cambio de cualquiera de las entradas. Este proceso  cambia el valor de las señales internas que actúan solo como cables hacia los puertos de salida. El funcionamiento de ambos modelos es exactamente el mismo y pueden definirse una variedad de modelos con el mismo comportamiento.

 

 

architecture Comportamiento1 of LogicaVaria is
  -- No hay señales internas que declarar

 

  begin – Comienzo de la especificación del comportamiento

  SalidaAnd_OUT <= Entrada1_IN and Entrada2_IN;

  SalidaOR_OUT <= Entrada1_IN or Entrada2_IN;

 

  end architecture Comportamiento1;

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

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

 

architecture Comportamiento2 of LogicaVaria is
  intSalidaAnd : std_logic; -- Señales internas declaradas

  intSalidaOr  : std_logic; -- solo para aclarar la lógica

 

  begin – Comienzo de la especificación del comportamiento

  SalidaAnd_OUT <= intSalidaAnd;

  SalidaOr_OUT  <= intSalidaOr;

 

  ProcesoCalculoLogica : process(Entrada1_IN, Entrada2_IN)

    begin

    intSalidaOr  <= Entrada1_IN or Entrada2_IN;

    intSalidaAnd <= Entrada1_IN and Entrada2_IN;

 

    end process; -- Fin de ProcesoCalculoLogica

 

  end architecture Comportamiento2;

 

Cuadro 4 Modelos de comportamiento

 

7.2.3       Modelos Estructurales

Como al armar una plaqueta con diferentes componentes e interconectarlos, VHDL permite armar modelos estructurales y así dar una jerarquía al diseño. En los modelos estructurales se interconectan diferentes componentes utilizando un mapeo de componentes básicos mediante señales que actúan como cables de interconexión. Las interconexiones se hacen “mapeando” los puertos definidos en las declaraciones de las entidades de los componentes básicos.

 

Para el siguiente ejemplo se supone que existen dos componentes CompuertaAnd y CompuertaOr predefinidos en la misma librería, ambas con dos entradas y una salida. Siguiendo el ejemplo anterior para la entidad “LogicaVaria”, una arquitectura estructural para este componente se muestra en el Cuadro 5.

 

 

architecture Estructura of LogicaVaria is
  -- Declaración de los componentes básicos utilizados en

  -- la arquitectura. Solo es necesario si se utiliza

  -- VHDL-87.

  component CompuertaAnd

    port(EntradaAnd1_IN : IN  std_logic;

         EntradaAnd2_IN : IN  std_logic;

         SalidaAnd_OUT  : OUT std_logic;

         );

  component CompuertaOr

    port(EntradaOr1_IN : IN  std_logic;

         EntradaOr2_IN : IN  std_logic;

         SalidaOr_OUT  : OUT std_logic;

         );

 

  begin – Comienzo de la especificación de estructura

 

  -- La instrucción “port map” conecta las señales con los

  -- puertos de los componentes básicos.

  -- El símbolo => indica conexión. A la izquierda

  -- están los puertos de los componentes básicos y

  -- a la derecha señala las señales o puertos de la entidad

  -- superior (en este caso LogicaVaria)

 

  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

              );

 

  end architecture Estructura;

 

Cuadro 5 Modelo estructural

 

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.

 

En el modelo estructural pueden apreciarse dos partes principales. Una es la declaración de los componentes antes del comienzo (begin) de la arquitectura utilizando la palabra component. La otra es crear una "instancia" (instantiation) de los componentes dentro de la arquitectura. Instancia se refiere a crear una copia de un componente, dándole un nombre único dentro del diseño. Puede verse la instancia de un componente como la creación de una copia del componente dentro del componente actual. Los puertos del componente se conectan a diferentes señales mediante el mapeo con las palabras port map. En el ejemplo todos los puertos de los componentes se interconectan de manera explícita a señales declaradas anteriormente. También pueden dejarse señales abiertas, por ejemplo cuando no se utilizan algunas salidas. Esto se hace usando la palabra open en la “instancia”. Por ejemplo, si no se quiere conectar la salida de la compuerta AND, puede usarse

 

  ComponenteBasicoAnd : CompuertaAnd

    port map (EntradaAnd1_IN => Entrada1_IN,

              EntradaAnd2_IN => Entrada2_IN,

              SalidaAnd_OUT  => open

              );

 

lo que dejará desconectada la salida. No pueden dejarse desconectadas las entradas.

 

En el ejemplo presentado se interconectan los puertos de los componentes con señales usando una asociación por nombre. Una asociación por nombre es el uso de la expresión (Puerto => SeñalALaQueSeConecta) que se utiliza para cada señal del puerto del componente. También puede hacerse una asociación por lugar, pero eso no es recomendable y no se presentarán ejemplos de ello en este texto.

 

Muchas herramientas de desarrollo permiten armar un componente con una arquitectura estructural de manera gráfica. Esto se hace representando cada componente básico por un símbolo gráfico que tiene indicadas sus puertos de entrada y salida. Estos puertos se  interconectan con líneas como se haría al diseñar un circuito con una herramienta de captura de esquemáticos (como Orcad o PowerLogic). La herramienta de diseño traduce luego el diagrama esquemático a su representación en VHDL para el análisis y elaboración. En la Figura 38 se muestra un ejemplo de representación grafica de un esquemático tomado de la herramienta ISE 6.2 de Xilinx.

 

Figura 38 Representación gráfica de un modelo estructural con las herramientas de Xilinx
(Fuente: Captura de pantalla de Herramienta Esquemática ECS de Xilinx)


7.3       Elementos del Lenguaje VHDL

En esta sección se presentan los elementos básicos del lenguaje VHDL para familiarizar al lector con algunas expresiones y operadores antes de comenzar con los elementos y construcciones mas complejas del lenguaje.

7.3.1       Palabras Reservadas

Las siguientes son las palabras reservadas en VHDL. No deberán utilizarse como nombres de ningún tipo que no sea como instrucciones de VHDL.

 

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, group[2], 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

 

7.3.2       Símbolos Especiales

Algunos símbolos especiales usados por VHDL y sus y ejemplos se dan en la siguiente tabla

 

Los operadores pueden sobrecargarse y tener diferentes significados para diferentes tipos en diferentes librerías.

 

 

 

 

Tabla 5 Símbolos especiales de VHDL

Símbolo

Significado

Ejemplos de uso

Agrupa valores de bits

Forma cadenas de texto

std_logic_vector := “001000”

“Una cadena”

“una cadena con “”comillas””.”

#

Divisor para números en base 2 a 16

2#1001000# -- número binario

16#af125f#  -- número hexadecimal

&

Operador de concatenación

“001” & “111” -- equivalente a “001111”

‘ (comilla simple)

Atributos

Calificación de tipo ambiguo

Caracteres

Valores de dígitos de bit

Clock’event      A’left        B’high

unsigned’(“10001”)

‘A’  ’c’  ‘ ’

‘0’ ‘1’ ‘Z’ (alta impedancia)

(  )

Subprogramas, para agrupar operadores y dar prioridad en expresiones, etc.

function ()

(A + B) * 4

*

Multiplicación

A := A * 4;

+

Suma o identidad

A + B

Cuenta_REG + 1

-

Resta o negación

A – B

Cuenta_REG – 1

, (coma)

Separa listas de parámetros

port map(A => A, B => B)

. (punto)

Punto decimal

Jerarquía en librerías

0.5     2#0.100#

use ieee.std_logic_1164.all

/

División

A := A / 4;

:

Especificación de tipo

signal      A : std_logic;

constant  C : integer;

;

Fin de instrucción

A_REG <= ‘1’;

<

Menor en comparaciones

if (A < B) then

=

Igual en comparaciones

if (A = ‘0’) then

>

Mayor en comparaciones

if (A > 0) then

[    ]

 

 

| (barra vertical)

Múltiples opciones en una condición

when 1 | 2 | 3 => -- Cuando la expresión sea

                             -- 1 o 2 o 3

=>

Opciones case, when

Mapeo de puertos en arquitecturas estructurales

Para dar valor a bits no asignados de vectores

when “000” =>

port map(A => A, B => B)

 

(others => ‘0’)

 

**

Exponencial

 

:=

Asignación para variables

VariableA := 1

/=

No igual en comparaciones

if (A /= ‘0’) then

>=

Mayor o igual en comparaciones

if (A >= 2) then

<=

Asignación para señales

Menor o igual en comparaciones

A <= ‘1’; -- A toma el valor ‘1’

if (A <= 3) then

<>

Usado para indicar rango indefinidos

(natural range  <>)

\

Usado para definir identificadores extendidos

\C:\\Xilinx\CarpetaProyecto\

_ (Guión bajo)

Usado para separar números o cadenas de bits largas

124_321                2#0110_1100#

b”0100_0110”       X”12FD_C46B_4567”

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

 

A partir de VHDL-93 se permite definir identificadores extendidos utilizando el símbolo “\”. Estos identificadores extendidos pueden tener cualquier símbolo sin las limitaciones de los identificadores básicos de VHDL. Esto se hace para poder comunicarse con herramientas de desarrollo que aceptan identificadores con formatos diferentes a los de VHDL.

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 #.

 

Los reales son números representan aproximaciones a números fraccionarios y contienen un punto decimal con al menos un número antes y uno después. En general los reales no se utilizan en diseños para síntesis.

 

Ejemplos de números reales:

            1.23     1.2e4     1.23e-4    0.5    2#0.10#    8#0.4#

 

Ejemplos de números enteros:

            1     2  3467   2#01110#     16#0AFD24#

 

7.3.5       Cadenas de bits

Para poder representar los valores básicos binarios de señales de diferentes anchos VHDL define las cadenas de bits. Estas pueden estar definidas en base binaria, octal o hexadecimal

 

Ejemplos de cadenas de bits

B”1100000”  (8 bits)    b”100_000” (7 bits)       o” 530” (9 bits)    O”54” (6 bits)

x”FA” (8 bits)              x”A3B6C1”  (24 bits)     X”F160_1234” (32 bits) 

 

7.4       Tipos en VHDL

VHDL es un lenguaje de tipos fuertes (strong typing) como el Ada o Pascal[4]. Esto significa que no pueden asignarse valores a señales o variables que no sean del tipo declarado para esa señal o variable. Para poder asignar un tipo diferente, el programador debe llamar explícitamente a una función de conversión de tipo.

 

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.

 

7.4.1       Tipos Comunes

VHDL tiene solo unos cuantos tipos predefinidos. También está diseñado para que haya mucha flexibilidad para definir nuevos tipos. En algunos casos los tipos más utilizados no son los predefinidos sino tipos estándares definidos por el usuario. La tabla presenta algunos de los tipos más utilizados.

 

Tabla 6 Tipos más utilizados en VHDL

Tipo

Comentario

bolean

Tipo buleano,  toma los valores TRUE o FALSE

carácter

Contiene todos los caracteres ISO de 8 bits

integer

Valores enteros. Como mínimo deben incluir los valores desde el (- 231 + 1) hasta el (231-1)

real

Usado para representar valores fraccionarios

time

Usado para controlar tiempo en los modelos. Especialmente importante durante las simulaciones.

std_logic

Usada para señales

std_logic_vector

Definido a partir de std_logic, permite tener señales de un ancho de varios bits

 

7.4.2       Declaración de Tipos

Como ya se mencionó, es muy simple definir nuevos tipos en VHDL. Un tipo que toma un rango de valores se declara de la siguiente manera

 

 

type IdentificadorDeTipo is range MenorValor to MayorValor;

type IdentificadorDeTipo is range MayorValor downto MenorValor;

 

Cuadro 7 Declaración de tipos

 

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;

 

7.4.3       Tipos enumerados

También pueden declararse tipos que toman un número discreto de valores usando la declaración:

 

 

type IdentificadorDeTipo is (Valor1, Valor2, Valor2, ...);

 

Cuadro 8 Declaración de tipo enumerado

 

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.

 

 

subtype Subtipo is Tipo range ValorMenor to ValorMayor;

 

Cuadro 9 Declaración de subtipos

 

7.4.4.1       Tipo Natural y Positivo

El estándar VHDL incluye dos subtipos definidos de la siguiente manera. Un tipo muy

 

subtype natural is integer range 0 to EnteroMasAlto;  -- Los enteros de 0 al mas alto

subtype positive is integer range 1 to EnteroMasAlto; -- Los enteros de 1 al mas alto

 

7.4.5       Tipos Físicos

VHDL puede definir tipos físicos para representar valores de cantidades físicas del mundo real. Al declarar un tipo físico se define una unidad primaria y unidades secundarias. El cuadro muestra algunos ejemplos de declaraciones de tipos físicos.

 

 

-- Declaración de un tipo para medidas

type tdLongitud is range 0 to 1E9;

  units

    um;

    mm = 1000 um;

    cm = 10  mm;

    m  = 100 cm;

    pulgada = 25400 um; -- Multiplicador debe ser entero

                        -- No puede ser pulgada = 25.4 mm

    pie = 12 pulgada;

  end units tdLongitud;

 

Cuadro 10 Declaración de tipo físico

 

7.4.5.1       Tipo Tiempo

El tipo físico predeterminado tiempo (time) es muy importante ya que es muy usado al modelar retardos. La declaración de time es la siguiente.

 

 

type time is (rango depende de la implementación);

  units

    fs;

    ps = 1000 fs;

    ns = 1000 ps;

    us = 1000 ns;

    ms = 1000 us;

    sec = 1000 ms;

    min = 60 sec;

    hour = 60 min;

  end units time;

 

Cuadro 11 Tipo físico tiempo (time)

7.4.6       Tipos compuestos

VHDL permite declarar tipos compuestos por mas de un valor. Un tipo compuesto es un conjunto o agrupación de valores que se trata como una unidad. Los tipos compuestos en VHDL pueden ser arreglos (array) o records (record).

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.

 

 

type tdByteC is array (0 to 7) of std_logic;     -- Indice

                                                 -- creciente

type tdByteD is array (7 downto 0) of std_logic; -- Indice

                                            -- decreciente

-- Tipo auxiliar para los siguientes ejemplos

type tdEstadosControlador is (Inicial, Espera, Ejecucion,

                              Abrir, Cerrar, Fin);

 

-- Tipos arreglos a partir de un tipo enumerado

type tdContadorEstados is array (Inicial to Ejecucion)

                  of natural;

-- O lo mismo pero especificando el tipo original

type tdContadorEstados is array (tdEstadosControlador range

                       Inicial to Ejecucion) of natural;

 

-- Una vez que se ha definido un tipo arreglo se pueden definir

-- objetos de esa clase y se direccionan de la siguiente manera

 

constant PalabraDeControl : tdByteC := (‘0’, ‘1’, ‘0’, ‘0’,

                                        ‘1’, ‘0’, ‘1’, ‘0’);

-- La palabra reservada others se refiere a todos los elementos

-- que no han sido nombrados explicitamente

variable PalabraDeControl : tdByteD;

PalabraDecontrol (1) := ‘1’;

PalabraDecontrol (4) := ‘1’;

PalabraDecontrol (6) := ‘1’;

PalabraDeControl  := (others => ‘0’); -- Todos los elementos !!!

-- Ahora uso others para definir los elementos 0,2,3,5 y 7

PalabraDecontrol := (1 =>‘1’, 4 =>‘1’, 6 =>‘1’, others => ‘0’);

 

variable ContadorEstados : tdContadorEstados;

ContadorEstados(Inicial) := 0;

ContadorEstados(Espera)  := 0;

ContadorEstados(Inicial) := ContadorEstados(Inicial) + 1;

 

variable ContadorPrincipio : tdContadorEstados;

-- Ejemplo de asignación por posición

ContadorPrincipio := (0, 0 ,0);      

 

-- Ejemplo de asignaciones nombrada (named)

ContadorPrincipio := (Inicial to Ejecucion => 0);

-- Otro ejemplo

ContadorPrincipio := (Inicial   => 0,

                      Ejecucion => 0,

                      others    => 0); -- Queda solo Espera

 

Cuadro 12 Arreglos

 

Del ejemplo pueden destacarse varias cosas.

 

7.4.6.2       Arreglos sin Rangos Predeterminados

VHDL permite definir tipos de arreglos sin rangos predeterminados. Estos arreglos se denominan unconstrained arrays. El rango se da al declarar un objeto de ese tipo. A continuación se muestran dos ejemplos de arreglos de este tipo muy utilizados en VHDL.

 

 

type std_logic_vector is array (natural range <> ) of std_logic;

 

type string is array (natural range <> ) of character;

 

Cuadro 13 Arreglos sin rango predeterminado

 

El primero es std_logic_vector, definido en el paquete std_logic_1164 y es el tipo más utilizado para señales de ancho de más de un bit. Los paquetes se presentan más adelante.

 

El segundo es un tipo predefinido de VHDL, string, y permite definir cadenas de caracteres. No se utilizan para diseños sintetizables

 

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

            -- std_logic_vector. Buena práctica siempre definirla como (MSB downto 0)

            constant PalabraControl : std_logic_vector (3 downto 0) := “1001”;

            constant PalabraControl : std_logic_vector (15 downto 0) := X“F5D6”;

            signal     PalabraEntrada : std_logic_vector (3 downto 0);

 

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.

 

-- Un record que agrupa varios valores para llevar un

-- control de tiempo en horas, minutos y segundos

type tdTiempo is record

  seg     : integer range 0 to 59;

  min     : integer range 0 to 59;

  horas   : integer range 0 to 23;

  end record tdTiempo;

 

-- Declaración y asignación para un objeto del tipo tdTiempo

constant Espera : tdTiempo := (seg => 4, min => 21, horas => 0);

 

Cuadro 14 Declaración de un record

 

7.4.7       Calificación y Conversión de Tipos

Si varios tipos definen el mismo valor posible puede ser que un valor se pueda interpretar de manera ambigua. Para especificar el tipo explícitamente se usa la comilla simple.

 

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       Objetos en VHDL

Como se mencionara anteriormente, hay cuatro clases de objetos que pueden declararse en . En esta sección se presentarán las constantes, variables y señales. Los archivos no pueden usarse para diseños sintetizables y se describirán en otra sección.

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.

 

Las constantes se declaran como se muestra en el cuadro.

 

 

  -- 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

 

  constant ADC_VALOR_MAXIMO : integer :=  3000;

  constant ADC_VALOR_MINIMO : integer := -3000;

 

  constant CONTADOR_ANCHO_DE_CUENTA : natural := 2;

 

  constant TIEMPO_SIMULACION_MAXIMO : time = 200 ns;

 

Cuadro 15 Declaración de constantes

 

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 “<=”.

 

 

  -- Declaración de señales usadas en un modelo

 

  signal Reloj           : std_logic;

  signal Reset           : std_logic;

  signal InterrupcionCPU : std_logic;

 

  signal Cuenta_REG  : std_logic_vector(5 downto 0);

  signal ADCData_REG : std_logic_vector(ADC_MSB downto 0);

 

 

  -- Asignación de valores de señales.

  Cuenta_REG  <= “0111111”;

  ADCData_REG <= ADCData_IN;

  Reloj <= ‘1’;

  Reloj <= ‘0’;

  BufferSalida <= “ZZZZZZZZ”;     -- Señal a tres estados

  BufferSalida <= (others => ‘Z’) -- Señal a tres estados

 

  -- Asignación de valores de señales con retardo.

  Cuenta_REG  <= “0111111” after 1 ms;

  ADCData_REG <= ADCData_IN after 2 ps;

  Reloj <= ‘1’ after 20 ns;

  Reloj <= ‘0’ after 20 ns;

  BufferSalida <= (others => ‘Z’) after 40 ns;

 

Cuadro 16 Declaración y uso de señales

 

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;

 

  -- Asignación de valores de variables

  A := 45;   -- El tipo de A debe aceptar el valor 45

  C := B;    -- Ambas variables del mismo tipo

  TiempoViejo := TiempoActual;

 

Cuadro 17 Declaración de variables

7.6       Librerías y Paquetes

En VHDL los componentes se describen utilizando entidades y definiendo arquitecturas por separado. Estos bloques se denominarán unidades de diseño. Al analizar el código, cada unidad se asigna a una librería de una manera dependiente de las herramientas utilizadas. A esto se lo denominará unidad de librería.

 

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.

 

Si se necesita acceder a entidades, declaraciones o funciones de otra librería se debe utilizar la instrucción library. La librería work se agrega al diseño en el que se está trabajando de manera implícita. Supongamos que hay un conjunto de componentes que se quieren reutilizar y han sido asignados a una librería llamada CompuertasBasicas en algún diseño anterior. Para utilizar esos componentes se debe agregar lo siguiente antes de la especificación de una arquitectura.

 

 

-- Para usar las compuertas básicas se debe agregar la

-- librería que las contiene

 

library CompuertasBasicas;

architecture Estructural of LogicaCompleja is

  begin

  -- Aquí pueden utilizarse los componentes declarados en

  -- la librería CompuertasBasicas

 

  end architecture Estructural;

Cuadro 18 Uso de una librería

 

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.

7.6.2       Paquetes (Packages)

Un paquete (package) en VHDL es otras unidad de diseño además de las entidades y arquitecturas que contiene definiciones de objetos que pueden ser utilizados por otros módulos. Las clases de objetos  que se puede colocarse en un paquete incluyen declaraciones de señales, tipos, constantes, funciones, procedimientos y componentes.

 

 

-- 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

 

package body NombrePaquete is

  function F1(...) is

    ...

 

  function F2(...) is

    ...

 

  end package body NombrePaquete;

 

Cuadro 19 Declaración de paquetes

 

La estructura de definición de paquete tiene primero una declaración en la que se define la interfase con el paquete. En esta sección se deben especificar todas las declaraciones de los ítems que luego serán visibles a las unidades en las que se incluya el paquete. La segunda sección del paquete es el cuerpo (body) en el cual se implementan los subprogramas. Esto permite esconder la implementación del funcionamiento de los ítems del paquete. En el cuadro se muestra el formato general de  un paquete.

 

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.

 

La expresión utilizada para utilizar un paquete de una librería dada redescribe a continuación

 

 

 

-- Para agregar un item declarado como NombreItem

-- en un paquete NombrePaquete de una librería

-- NombreLibreria debe usarse la instrucción use

 

library NombreLibreria; -- Declara que se usara la libreria
use NombreLibreria.NombrePaquete.NombreItem; -- Uso del

                                             -- paquete

 

-- Para agregar todos los tipos y constantes de

-- una libreria
library NombreLibreria; -- Declara que se usara la libreria
use NombreLibreria.NombrePaquete.all; -- Uso del paquete

 

Cuadro 20 Uso de un paquete

 

7.6.3       Paquetes de Lógica Estándar del IEEE

Como puede verse de la sección donde se describen los tipos en VHDL el lenguaje tiene una gran capacidad para extender los tipos y definir y sobrecargar operadores y funciones. Para estandarizar el IEEE desarrolló un paquete lógico estándar denominado std_logic_1164. Aunque no es realmente parte de VHDL, este paquetes es tan utilizado que casi podría considerarse un aparte del lenguaje. Se recomienda siempre usar los tipos definidos en estos paquetes, como se detallará mas adelante.

 

Además de definir el paquete std_logic_1164, el IEEE definió un paquete con operaciones aritméticas  para números representados por vectores de bits. Este paquete se denomina numeric_std y es el recomendado para diseños sintetizables.

 

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.

 

-- Utilización de los paquetes lógicos estándar del IEEE

library ieee;
use ieee.std_logic_1164.all; -- Lógica estándar

use ieee.numeric_std.all;    -- Operaciones aritméticas

 

Cuadro 21 Uso de los  paquetes estándar IEEE

 

 

 

 

 

7.6.3.1       Lógica estándar std_logic y std_ulogic definidos en std_logic_1164

El paquete std_logic_1164 dentro de la librería ieee define un tipo std_ulogic con nueve valores posibles.

 

Tabla 7 Valores posibles para lógica std_logic

Valor

Descripción

Valor

Descripción

‘U’

Sin inicializar

‘W’

Desconocido débil

‘X’

Desconocido forzado

‘L’

0 débil

‘0’

0 forzado

‘H’

1 débil

‘1’

1 forzado

‘-‘

No importa

‘Z’

alta impedancia

 

 

 

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”.

 

Del tipo std_logic se define el tipo std_logic_vector que es un arreglo (array) de std_logic. std_logic_vector es un arreglo sin límites, y el valor de los índices máximo y mínimo se dan al declarar el objeto de ese tipo.

 

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.

 

Ejemplo de uso del tipo std_logic en la declaración de una entidad :

            entity Contador is

              port(

                    Clock_IN      : IN  std_logic;

                    Reset_IN       : IN  std_logic;

                    Cuenta_OUT : OUT std_logic_vector (31 downto 0)

         );

 

Ejemplo de uso del tipo std_logic en la declaración de señales en una arquitectura

            signal Cuenta_REG        : std_logic_vector (31 downto 0);

            signal intFinDeCuenta    : std_logic;

 

7.6.3.2       Detección de flancos de señales definidos en std_logic_1164

El paquete std_logic_1164 contiene las siguientes funciones que son muy útiles para simplificar la sintaxis en los procesos para síntesis, como ya se verá mas adelante.

 

Tabla 8 Funciones de detección de flanco de señales

Función

Tipo que devuelve

Descripción

rising_edge(S)

boolean

Devuelve TRUE si hay un flanco ascendente sobre S, sino devuelve  FALSE.

falling_edge(S)

boolean

Devuelve TRUE si hay un flanco descendente sobre S, sino devuelve  FALSE.

 

7.6.4       Aritmética sobre lógica estándar

El paquete numeric_std define dos nuevos tipos a partir de la std_logic. Estos son signed y unsigned, usados para representar números enteros con y sin signo respectivamente. Además de esos dos tipos, define las operaciones dadas en la siguiente tabla. En la tabla se enumeran las operaciones y el resultado de operar sobre los distintos tipos.

 

Los paquetes std_logic_arith, std_logic_unsigned y std_logic_signed son paquetes de Synopsis, Inc. que se distribuyen como parte de la librería IEEE. Estos paquetes cumplen  la misma función para cadenas de bits del tipo std_logic_vector. En std_logic_arith se definen las operaciones sobre tipos del tipo signed y unsigned, mientras que en los otros dos se definen conversiones para poder usar las funciones aritméticas con tipos std_logic_vector. Si se desea utilizar estos paquetes, se debe incluir el paquete std_logic_arith  y solo uno de los otros dos paquetes. Así las señales del tipo std_logic_vector serán tratadas como con signo o sin signo según cual paquete se haya incluido. Estos paquetes surgieron antes de la librería estandarizada numeric_std. Como se mencionó antes, este paquete numeric_std no define operaciones  sobre los vectores estándar, sino que obliga al programador a declarar explícitamente las cadenas de bits como del tipo signed o unsigned antes de poder realizar operaciones aritméticas sobre ellos. Al utilizar los paquetes std_logic_arith junto a std_logic_signed o std_logic_unsigned se puede operar directamente sobre std_logic_vector, por lo que resultan más prácticos.

 

A continuación se resumen las opciones de encabezamientos recomendados para usar diferentes paquetes. Las siguientes líneas deben incluirse de la manera especificada en los diseños para usar los tipos std_logic_vector.

 

-- Encabezamiento para usar los tipos std_logic y std_logic_vector sin operaciones aritméticas

library ieee;

use std_logic_1164.all;

 

-- Encabezamiento para usar los tipos std_logic y std_logic_vector y tratarlos como

--  números con signo (complemento a dos) en las operaciones aritméticas

library ieee;

use std_logic_1164.all;

use std_logic_arith.all;

use std_logic_signed.all;

 

-- Encabezamiento para usar los tipos std_logic y std_logic_vector y tratarlos como

--  números sin signo en las operaciones aritméticas

library ieee;

use std_logic_1164.all;

use std_logic_arith.all;

use std_logic_unsigned.all;

 

Tabla 9 Resumen de tipos de las operaciones aritméticas

Oper.

Operación

Tipo del operando izquierdo

Tipo del operando derecho

Tipo del resultado

Longitud del resultado

abs

-

valor absoluto

negación

 

signed

signed

Longitud del operando

+

-

*

/

rem

mod

suma

resta

multiplicación

división

resto

módulo

unsigned

signed

unsigned

natural

signed integer

unsigned

signed

natural

unsigned

integer

signed

unsigned

signed

unsigned

unsigned

signed

signed

La mas grande de los dos operandos

Suma de las longitudes

Longitud del izquierdo

Longitud de operando derecho

=

/=

<

<=

>

>=

igualdad

diferente

menor

menor o igual

mayor

mayor o igual

unsigned

signed

unsigned

natural

signed

integer

unsigned

signed

natural

unsigned

integer

signed

boolean

boolean

boolean

boolean

boolean

boolean

 

sll

srl

rol

ror

corrimientos

     lógicos

rotaciones

unsigned

signed

integer

integer

unsigned

signed

Longitud del operando del tipo vector de bits

not

negación

 

unsigned

signed

unsigned

signed

Longitud del operando

and

or

nand

nor

xor

xnor

operaciones lógicas

unsigned

signed

unsigned

signed

unsigned

signed

Longitud de los operandos.

Ambos deben ser de igual longitud.

 

7.7       Construcciones Básicas de VHDL

En esta sección se presentarán las construcciones básicas de modelado. Como se ha visto de las secciones anteriores El VHDL es muy flexible y una misma tarea o función  puede modelarse de muchas maneras diferentes. Las descripciones y ejemplos dados estarán orientados a diseños sintetizables. Los ejemplos se presentarán siguiendo prácticas recomendadas para el código que facilitan su entendimiento y reutilización. Esto no significa que no haya otras estructuras y maneras diferentes de definir la misma funcionalidad para un modelo, o que las presentadas sean las únicas estructuras sintetizables.

 

Como se ha visto anteriormente, un componente en VHDL se define utilizando dos unidades de diseño: entity y architecture. Es buena práctica incluir ambas unidades[5] para un componente en un solo archivo que tenga  el mismo nombre que la entidad, separadas de otras declaraciones de entidades y arquitecturas. Esto facilita la comprensión del diseño, ayuda a localizar rápidamente los componentes y ayuda a reutilizar el código.

 

En términos generales, la arquitectura de un componente puede ser un modelo de comportamiento o estructural. No conviene mezclar ambos modelos y no se hará en este texto. Un modelo estructural incluye todos los componentes básicos y las señales que los interconectan. Utiliza las palabras port map para logar esta interconexión, como se mostró en la sección 7.2.3. Es importante destacar que en VHDL-87 se deben declarar los componentes básicos que se usarán usando la palabra component  antes del begin de la arquitectura. En VHDL-93 pueden usarse componentes directamente destacando explícitamente a que librería pertenecen. En los apéndices pueden consultarse ejemplos de este tipo de modelo que servirán como guía para nuevos diseños.

 

La estructura general de un componente en el que se modela su comportamiento es la mostrada en el cuadro. En este esquema se van las declaraciones de la entidad y arquitectura, y dentro de la arquitectura varias secciones básicas.

 

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

            

    );

  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;

Cuadro 22 Esquema básico de un componente en VHDL

 

7.7.1       Declaración de señales

Todas las señales que se utilizan internamente en el componente deben declararse. Los tipos recomendados de señales  para diseños sintetizables son std_logic, std_logic_vector, signed y unsigned, como se explicara en la descripción de paquetes en secciones anteriores. Para diseños sintetizables no se deben asignar valores iniciales a las señales ya que estos no tienen sentido en una implementación de  hardware real.

 

 

Ejemplos:         signal intCuenta                    : unsigned(5 downto 0);

                        signal ADCData_REG          : signed(11 downto 0);

                        signal Reloj                           : std_logic;

                        signal FinDeCuenta_REG     : std_logic;

 

7.7.2       Operaciones Concurrentes

Las operaciones concurrentes modelan procesos que suceden en paralelo en el hardware. En VHDL todas las operaciones concurrentes se ejecutan al mismo tiempo. VHDL tienen varias instrucciones concurrentes y un mecanismo para agrupar instrucciones secuenciales para que funcionen como una sola instrucción concurrente. Este mecanismo se denomina proceso (process)

 

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.

7.7.2.1       Flujo de datos

La manera más simple de modelar una operación concurrente es usando las asignación para señales “<=”. Este operador indica que el resultado de la expresión a la derecha debe asignarse a la señal de la izquierda. Obviamente la señal y el resultado de la evaluación de la expresión deben ser del mismo tipo.  Estas asignaciones se sintetizarán como lógica combinacional. La expresión de la derecha debe utilizar operadores que estén definidos para las señales utilizadas y que además sean sintetizables. Los operadores lógicos LISTA, de suma “+” y resta “–“ y la multiplicación y división por factores de 2 son en general sintetizables.

 

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;

 

 

architecture Comportamiento of Logica2Entrdas is

  -- Señales internas utilizadas

  signal intSalidaAnd : std_logic;

  signal intSalidaOr  : std_logic;

 

  begin

  -- Operaciones concurrentes que modelan flujo de datos

  SalidaAnd_OUT  <= intSalidaAnd;

  SalidaOr_OUT   <= intSalidaOr;

  SalidaNand_OUT <= not intSalidaAnd;

  SalidaNor_OUT  <= not intSalidaOr;

 

  intSalidaAnd <= Entrada1_IN and Entrada2_IN;

  intSalidaOr  <= Entrada1_IN or Entrada2_IN;

 

  end architecture Comportamiento;

 

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

 

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;

 

architecture Comportamiento of Logica2Entrdas is

  -- Señales internas utilizadas

  signal intSalidaAnd : std_logic;

  signal intSalidaOr  : std_logic;

 

  begin

  -- Operaciones concurrentes que modelan flujo de datos

  SalidaAnd_OUT  <= intSalidaAnd;

  SalidaOr_OUT   <= intSalidaOr;

  SalidaNand_OUT <= not intSalidaAnd;

  SalidaNor_OUT  <= not intSalidaOr;

 

  intSalidaAnd <= Entrada1_IN and Entrada2_IN;

  intSalidaOr  <= Entrada1_IN or Entrada2_IN;

  end architecture Comportamiento;

Cuadro 23 Ejemplo de arquitectura definida como flujo de datos

 

Otras manera de definir la misma lógica se muestra en el siguiente cuadro. En este ejemplo no se utilizan señales internas, sino que todas las salidas se definen como funciones de las entradas. En general las herramientas de síntesis son los suficientemente “inteligentes” como para optimizar esta lógica y sintetizar ambas arquitecturas a la misma implementación. Esta implementación dependerá del PLD que se esté utilizando.

 

 

architecture Comportamiento of Logica2Entrdas is

  begin

  -- Operaciones concurrentes que modelan flujo de datos

  SalidaAnd_OUT  <= Entrada1_IN and Entrada2_IN;

  SalidaOr_OUT   <= Entrada1_IN or Entrada2_IN;

  SalidaNand_OUT <= not (Entrada1_IN and Entrada2_IN);

  SalidaNor_OUT  <= not (Entrada1_IN or Entrada2_IN);

 

  end architecture Comportamiento;

 

Cuadro 24 Otro ejemplo de flujo de datos

 

7.7.2.2       Palabra reservada AFTER

En los siguientes ejemplos se presentan asignaciones de señal que utilizan la palabra clave palabra clave after.

 

 

  -- Operaciones concurrentes que modelan flujo de datos

  -- con retardo entre cambios en las entradas y salidas

  -- a la lógica

  Salida1_OUT  <= Entrada1_IN and Entrada2_IN after 20 ns;

 

  Logica1   <= Entrada1_IN or Entrada2_IN after 40 ps;

 

  Registro_REG <= not (Entrada1_IN and Entrada2_IN) after 4 ps;

 

  Salida_OUT  <= not (Entrada1_IN or Entrada2_IN) after 2 ms;

 

Cuadro 25 Uso de la palabra AFTER

 

Como VHDL permite modelar el comportamiento eventos en el tiempo, incluye la palabra reservada after que en el contexto presentado significa “después de” “luego de”. Esta palabra permite modelar retardos entre el evento que provoca los cambios en una señal y la actualización de la señal. Mediante esta palabra se pueden modelar retardos en compuertas, tiempos de repuesta de componentes, etc. La palabra after no es tenida en cuanta al sintetizar un diseño, ya que los retardos en un circuito sintetizados dependerán del PLD y de cómo se haya implementado la lógica.

La palabra reservada alter puede ser utilizada en cualquier asignación de señal, ya sea en una instrucción concurrente o secuencial.

7.7.2.3       Expresión with … select

 

La expresión withselect  modela un multiplexor, en el que de acuerdo a alguna señal de control puede seleccionarse el valor a aplicar a una señal . El formato y algunos ejemplos se muestran en el cuadro.

 

 

  -- Formato general de la expresión "with... select"

  with SenalDeControl select

    SenalDeDestino  <= Fuente1 when Condicion1,

                       Fuente2 when Condicion2,

                       ...

                       FuenteN when others;

 

  -- Ejemplo 1 – Con SenalDeControl de 2 bits

  with SenalDeControl select

    SenalDeDestino_OUT  <= Fuente1_IN when “00”,

                           Fuente2_IN when “01”,

                           Fuente4_IN when “10”,

                           Fuente5 when others;

 

  -- Ejemplo 2 - Operación concurrente with ... select

  with Seleccion_IN select

    Salida1_OUT <= Datos1_IN when "001",

                   Datos2_IN when "010",

                   “010101”  when "100",

                   "XXXXXX" when others;

 

Cuadro 26 Uso de la expresión WITH … SELECT

 

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.

7.7.2.4       Expresión when, else

La expresión whenelse  es otra operación concurrente que puede usarse para modelar lógica con prioridades.

 

 

-- Formato de when... else

SenalDeDestino  <= Fuente1 when Condicion1 else

                   Fuente2 when Condicion2 else

                   ...

                   OtraFuente when Condicion3 else

                   FuenteN ;                -- Caso por defecto

 

-- Ejemplo 1 de when... else con la misma señal de control

SenalDeDestino_OUT  <= Fuente1 when SenalDeControl=”00” else

                       Fuente2 when SenalDeControl=”01” else

                       Fuente3 when SenalDeControl=”10” else

                       Fuente4 ; -- Caso por defecto

 

-- Ejemplo 2 de when... else con condiciones varias

SenalDeDestino_OUT  <= Fuente1 when Control  = ”00” else

                       Fuente2 when Control /= ”01” else

                       Fuente3 when OtroControl = ”101” else

                       Fuente4 ; -- Caso por defecto

 

-- Ejemplo 3 de when... con una condición compleja

SenalDeDestino    <= ‘1’ when X = ‘0’ and Y = ‘1’;  

 

-- Ejemplo 3 de when... con una condición compleja y ejemplos de

-- la palabra after

OtraSenal    <= ‘1’ after 4 ns when X = ‘0’ and Y = ‘1’

               else ‘0’ after 3 ns;

 

Cuadro 27 Uso de la expresión WHEN… ELSE

 

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.

7.7.3       Operaciones secuenciales

Antes de presentar los procesos, que son la operación concurrente clave, se deben presentar las operaciones secuenciales. Las instrucciones secuenciales se ejecutarán una tras otra, de manera similar a las instrucciones de un lenguaje de programación convencional. La principal diferencia es que el bloque de instrucciones secuenciales agrupadas por un proceso se ejecutarán en paralelo con los otros procesos y operaciones concurrentes. En la sección sobre procesos se explicará este mecanismo en más detalle.

 

7.7.3.1       Instrucción WAIT

Además de la palabra reservada after presentada anteriormente, la otra instrucción que modela el tiempo en VHDL es la instrucción wait. Esta instrucción es una instrucción secuencial, y por lo tanto solo se utilizará dentro de un proceso.  Permite suspenderlo por un período determinado de tiempo o hasta que se cumpla alguna condición. Los usos de la instrucción wait  y algunos ejemplos se muestran en el cuadro.

 

 

  -- Formatos posibles para la instrucción wait

 

  wait;               -- Suspende el proceso para siempre

 

  wait on Señal;      -- Suspende el proceso hasta que ocurra

                      -- un evento sobre la señal

 

  wait for Tiempo;    -- Suspende el proceso un intervalo

                      -- fijo de tiempo

 

  wait until (Expresión buleana);

                      -- Suspende el proceso hasta que se la

                      -- evaluación de la expresión devuelva TRUE

 

 

 

  -- Ejemplos de uso de la instrucción wait. En general se

  -- utiliza para modelos NO SINTATIZABLES

 

 

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

  -- wait on ...

  SenalAccion_OUT <= ‘1’;

  wait on PulsoRespuesta_IN;  -- Espero un cambio en la entrada

 

 

  -- Instrucciones secuenciales en un proceso de suma de 1 bit

  -- con acarreo

  Resultado <= A xor B after 20 ns;

  Carry     <= A and B after 20 ns;

  wait on A, B; Suspende hasta que cambie A o B

 

 

   

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

  -- wait for ...

  wait for 10 ns; -- Suspende 10 nanosegundos

  wait for 40 ms; -- Suspende 40 milisegundos

 

  -- usando una constante predefinida

  wait for ADC_TIEMPO _CONVERSION;

 

 

 

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

  -- 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’);

 

  wait until (((Entrada1 and Entrada2) xor Entrada3 )= ‘0’);

 

 

Cuadro 28 Uso de la palabra WAIT

 

Pueden armarse expresiones más complejas con la instrucción wait utilizando combinaciones  de los tres formatos for, on, until. Como en general la expresión wait no es sintetizable[6] y lo presentado alcanza para armar bancos de prueba simples, estas expresiones no se presentarán de manera exhaustiva en este texto. Puede consultarse la bibliografía para una mayor explicación y ejemplos varios.

 

7.7.3.2       Expresión if… elsif… else

La expresión if permite condicionar la ejecución de instrucciones secuenciales. Cuando la condición buleana de la instrucción if se evalúa a TRUE se ejecutarán las instrucciones secuénciales que la siguen. Sino se saltearán.  La instrucción elsif permite anidar condiciones, generando una lógica de prioridad. Si no se da primer condición se evalúa la segunda, y así sucesivamente. La condición else permite que se de un caso por defecto, que se ejecutará solo si no se cumple ninguna de las condiciones anteriores. Siempre se debe cerrar un lazo if con una instrucción  end if. Los cuadros muestran el formato general y dan ejemplos para la utilización de las instrucciones if, elsif, else.

 

 

 

  -- Formato general de la instrucción secuencial if

  -- Solo es necesario que haya una condición if...los elsif y

  -- else son optativos

  if (Condición 1) then

    ... -- Instrucciones secuenciales que se ejecutan si

        -- se cumple la condición 1

  elsif (Condición 2) then

    ... -- Instrucciones secuenciales que se ejecutan si

        -- se cumple la condición 2 (y no se cumplió la

        -- condición 1)

  elsif (Condición 3) then

    ... -- Instrucciones secuenciales que se ejecutan si

        -- se cumple la condición 3 (y no se cumplieron las

        -- condiciones 1 ni 2)

  elsif (Condición 4) then

    ... -- Instrucciones secuenciales que se ejecutan si

        -- se cumple la condición 4 (y no se cumplieron las

        -- condiciones 1, 2 ni 3)

    ...

    ...

    ...

 

  else

    ... –- Instrucciones que se ejecutan solo si no se da

        -- ningún caso de las condiciones anteriores

 

    end if;

 

Cuadro 29 Uso de la expresión IF, ELSIF, ELSE

 

 

-- Ejemplos de instrucciones if

 

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

-- Una sola condición

 

  -- Si la cuenta llega a su valor final volver a cero

  if (Contador_REG = VALOR_MAXIMO) then

    Contador_REG <= (others => ‘0’);

    end if;

 

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

-- if, elsif

 

  -- Reset asincrónico y ejecución sincrónica

  if (Reset_IN = ‘1’) then

    -- Dar valores iniciales a los registros

    Registro_REG <= (others => ‘0’);

  elsif (Rising_Edge(Clock_IN)) then

    .. -- Instrucciones secuenciales sincrónicas

    end if;

 

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

-- if, else

  -- Detecto el signo de una entrada y lo guardo a un registro

  if (DatoEntrada_IN(MSB) = ‘0’) then

    Signo_REG <= ‘0’;

  else