Escolar Documentos
Profissional Documentos
Cultura Documentos
VHDL
orientado a síntesis
en FPGAs
índice - iii
4. SENTENCIAS SECUENCIALES IV - 1
4.1 SENTENCIAS IF 1
4.1.1 Inferencias básicas de sentencias IF en síntesis VHDL 4
4.2 SENTENCIAS CASE 8
4.3 SENTENCIAS NULL 9
4.4 SENTENCIAS LOOP 10
4.4.1 LOOP SIMPLE 10
4.4.2 LOOP FOR 10
4.4.3 LOOP WHILE 10
4.5 SENTENCIAS NEXT 11
4.6 SENTENCIAS EXIT 12
4.7 SENTENCIAS ASSERT 13
4.8 SENTENCIAS WAIT 14
4.7.1 WAIT ON señales 14
4.7.2 WAIT UNTIL condición 14
4.7.3 WAIT FOR especificación de tiempo 14
5. SUBPROGRAMAS IV - 1
5.1 FUNCIONES 1
5.1.1 FUNCIONES DE RESOLUCIÓN 5
5.1.2 TIPOS STD_LOGIC. EMPAQUETAMIENTO IEEE 1164 9
6. MODELOS ESTRUCTURALES VI - 1
6.1 ESPECIFICACIONES DE CONFIGURACIÓN 1
6.2 DECLARACIÓN DE CONFIGURACIÓN 3
6.3 APLICACIÓN DE SENTENCIAS GENERATE 5
6.4 DESARROLLO DE PROBADORES 8
BIBLIOGRAFÍA
índice - iv
INTRODUCCIÓN
En VHDL, como en cualquier idioma o lenguaje, no es preciso ser un experto para poder
expresarse y realizar modelos que sean aceptados por los compiladores poco tiempo después de
conocer los conceptos básicos. El primer pequeño problema es que, como en tantos otros
conocimientos, hay que aprenderlo secuencialmente mientras que para utilizarlo bien deberían
aprenderse muchos conceptos concurrentemente, dicho en términos VHDL que pronto se verán.
Al parecer, las opiniones de diversos autores no son coincidentes en el orden de presentar
conceptos y ejemplos, según se deduce al comparar los índices de temas en distintos libros sobre
VHDL. En cualquier caso, practicar con un programa de simulación y analizar las respuestas
ayudará mucho en la fase de aprendizaje, tanto para resolver las dudas iniciales como para ver
defectos de diseño y plantearse diseños más eficientes, un concepto poco claro que debiera
entenderse como en cualquier proyecto por la calidad o robustez del modelo, seguido del coste y
del tiempo para su desarrollo.
Esta publicación, titulada “VHDL orientado a síntesis en FPGAs”, sin hacer una
cobertura amplia y detallada con muchas páginas más, pretende ser algo más que una simple
introducción al VHDL “a complementar con los mensajes de error que dará el compilador” que,
sin duda, también enseñan, aunque no sean el mejor método para aprenderlo.
En la redacción se han considerado los conceptos fundamentales del VHDL para entender
las secciones 6, 7 y 8 y desarrollar los modelos que, a nivel académico, serán suficientes para la
realización de proyectos de sistemas digitales basados en FPGAs, utilizando herramientas de
síntesis. También se ha considerado que el aprendizaje y la práctica del VHDL requieren ya
bastante esfuerzo de abstracción como para tener que hacerlo en un idioma distinto del materno.
Solo resta desearle al lector que la publicación le resulte útil y la presentación eficiente.
El Autor
v
vi
1 - Modelos y unidades de diseño en VHDL
El modelo de un sistema varía según el estado del diseño y el uso a que se destina el
modelo. Inicialmente, el modelo de un sistema es un conjunto de especificaciones generales
de diversa índole. A partir de esas especificaciones generales, por una estrategia de diseño
top-down, el sistema se particiona en una serie de niveles sucesivos, siguiendo una
estructura jerárquica o árbol que representa al sistema. El proceso posterior de integración
del sistema consistirá en el ensamble o interconexión de los subsistemas siguiendo una
estrategia bottom-up. Normalmente, el desarrollo de modelos de un sistema moderno
consiste en una mezcla de las dos estrategias: descomponer el sistema en bloques en un
proceso top-down e integrar en los subsistemas modelos de nuevo desarrollo junto con otros
disponibles como resultado de desarrollos previos.
En cualquier caso, al plantearse el desarrollo del modelo de un subsistema, a cualquier
nivel dentro de la jerarquía del sistema, se consideran dos aspectos básicos:
Componentes son elementos - puerta, chip, módulo, etc. - cuya complejidad estará
relacionada al nivel del subsistema dentro de la estructura del sistema.
Puertos son las interfaces por los que el elemento se interconecta a los puertos de otros
elementos para formar la estructura del nivel jerárquico que lo contiene.
Señales son los nombres asignados a las rutas que interconectan componentes a través
de sus puertos, relacionando estructuras y comportamientos de los modelos.
En VHDL, un sistema digital se representa como una ENTITY en la que se aplican los
conceptos anteriores al modelarla. Para esto se la considera definida con dos unidades de
diseño o descripciones interrelacionadas: la declaración de ENTITY y la descripción
funcional o ARCHITECTURE. Estos son los dos pilares básicos sobre los que se construyen
todas las descripciones en VHDL.
Las unidades de diseño son bloques de código que pueden ser compiladas y
almacenadas separadamente en alguna biblioteca - o LIBRARY- por lo que, a veces, se las
conoce como library units. Además de ENTITY y ARCHITECTURE, obligatorias en cualquier
descripción VHDL, existen otras tres unidades de diseño: PACKAGE, PACKAGE BODY y
CONFIGURATION, pero estas tres son opcionales.
I-1
1 - Modelos y unidades de diseño en VHDL
ENTITY identificador IS
PORT (lista_de_señales: modo tipo);
END identificador;
Por ejemplo, la declaración de ENTITY para unas puertas AND y OR podría ser:
Nótese que, aparte de la diferencia de nombres de las ENTITYs, las interfaces definidas
tras las cláusulas PORT son iguales, es decir, no se hace referencia alguna a la función o
comportamiento de los elementos.
Los puertos pueden ser de cuatro modos:
Los puertos modo IN pueden ser leídos dentro de la ENTITY que los contiene, es decir,
puede tomarse su valor para aplicarlo y obtener resultados, pero no pueden ser escritos
internamente, ya que ello supondría alterar el valor externo con el que acceden las señales a
la ENTITY, como resultado del valor que les asignaron sus drivers
.
Los puertos modo INOUT, al ser bidireccionales, pueden ser escritos o leídos. Es el
caso típico de los puertos conectados a un bus, o los puertos de datos de una memoria RAM.
Los puertos modo OUT tienen una restricción similar a los modo IN: El valor de un
puerto modo OUT puede ser escrito internamente, es decir, se le puede asignar un valor por
medio de unos drivers, que será el valor que sale del puerto de la ENTITY y, por tanto, el que
la ENTITY aporta al nodo o red a la que el puerto esté conectado. Sin embargo, los puertos
modo OUT no pueden ser leídos internamente dentro de la ENTITY en la que están
declarados. Existen dos razones para esto: la primera es que no habría diferencia entre un
puerto modo OUT y otro modo INOUT y la segunda razón, relacionada a lo que se
denomina valor efectivo o resuelto de una señal. Este concepto distingue entre el valor
individual que un puerto lleva al nodo donde se conecta y el valor presente en ese nodo
como consecuencia de los diferentes puertos que acceden a él. Según la fuerza de las señales
y el valor de las mismas, resultará un valor efectivo de la señal presente en el nodo, que será
I-2
1 – Modelos y unidades de diseño en VHDL
el valor real que puede ser leído. Así, el valor individual presente en una puerta de modo
OUT solo puede garantizar su inalterabilidad si al nodo al que se conecta no llega ninguna
otra señal. Esta restricción es la que define a los puertos de modo BUFFER.
Los puertos de modo BUFFER son puertos de salida cuyo valor está determinado por
un único driver y que no pueden aplicarse a nodos en los que confluya más de una señal, por
ejemplo, una salida tri-estado. Como consecuencia de esta restricción, los puertos BUFFER
pueden ser leídos dentro de la ENTITY en que se les asigna valor. Sin embargo, la restricción
hace que el empleo de este tipo de puertos sea poco frecuente.
BEGIN BEGIN
PROCESS (e1, e2) PROCESS (e1, e2)
BEGIN BEGIN
IF (e1 = ‘1’) AND (e2 = ‘1’) THEN IF (e1 = ‘0’) AND (e2 = ‘0’) THEN
sal <= ‘1’; sal <= ‘0’;
ELSE sal <= ‘0’; ELSE sal <= ‘1’;
END IF; END IF;
END PROCESS; END PROCESS;
END comport; END comport;
ENTITY sumador IS
PORT ( x,y,ci : IN BIT; sum, co : OUT BIT);
END sumador;
I-3
1 - Modelos y unidades de diseño en VHDL
Hay una correspondencia directa entre la descripción VHDL y las puertas con las que
se realiza el sumador, según el circuito adjunto. Como se verá con detalle más adelante, se
declaran las señales internas s1,s2,s3 indicando su tipo -BIT- , en una zona reservada a
declarar objetos locales a la ARCHITECTURE e inmediatamente se describe la funcionalidad
de la ENTITY, expresando por medio del delimitador <= utilizado para asignar valor a
señales, la relación entre señales de salida, sum y co , con las señales internas s1,s2,s3
queestán relacionadas a las de entrada x, y, ci utilizándo las funciones XOR, AND y OR.
COMPONENT AND_2 PORT (e1,e2 : IN BIT; sal: OUT BIT); END COMPONENT;
COMPONENT OR_2 PORT (e1,e2 : IN BIT; sal: OUT BIT); END COMPONENT;
COMPONENT XR_2 PORT (e1,e2 : IN BIT; sal: OUT BIT); END COMPONENT;
BEGIN
P1: xr_2 PORT MAP (x,y,s1); -- instantiation statements
P2: xr_2 PORT MAP (s1,ci,sum); -- sentencias de colocación o
P3: and_2 PORT MAP (s1,ci,s2); -- sentencias de mapeo posicional
P4: and_2 PORT MAP (x,y,s3);
P5: or_2 PORT MAP (sal => co, e1 =>s2, e2 => s3);
END estructural;
Es la que describe con más detalle la estructura del sumador, ya que indica a nivel de
puertas una realización concreta del circuito:
Obsérvese que declara las mismas señales internas - s1, s2, s3- que se declararon en la
ARCHITECTURE funcional.
Es evidente que este tipo de ARCHITECTURE requiere un diseño previo de hardware, para
establecer las interconexiones entre señales de ENTITY sumador - x, y, ci, sum, co -, las
señales internas o locales - s1, s2, s3 - y las interfaces de las ENTITY s primitivas que se
utilizan como componentes disponibles, sobre las que aquí se hace un mapeo posicional
de todas las señales por medio de las sentencias con las cláusulas PORT MAP.
I-4
1 – Modelos y unidades de diseño en VHDL
Aunque las tres ARCHITECTUREs son del mismo sumador, es interesante comparar las
inferencias de síntesis de cada una, es decir, los recursos requeridos al sintetizar con la
misma herramienta y la misma FPGA, y si ésta es “de grano fino”, mejor la comparación.
I-5
1 - Modelos y unidades de diseño en VHDL
Léxico: Solo puede tener caracteres permitidos: No puede haber Ñ o ñ, por ejemplo.
Sintaxis: Por ejemplo, si se ha utilizado BEGIN o IF, debe existir un END o END IF.
Semántica: Se buscan inconsistencias en la descripción, por ejemplo, a un objeto de
tipo BIT, se puede asignar ‘1’ o ‘0’, pero no 1 ni 0, ya que estos son tipo INTEGER.
La cláusula USE puede utilizarse de tres formas, con la notación de punto (.):
USE LIBRARY. paquete; USE chips. puertas;
USE paquete. objeto; USE puertas. and2;
USE LIBRARY. paquete. objeto; USE chips.puertas.and2;
en las que el nombre -sufijo- que sigue al punto (.) debe estar declarado o contenido en el
paquete o biblioteca -prefijo- que precede al mismo punto. Como alternativa para evitar
referencias largas o listas de objetos, es posible usar la cláusula .ALL; que visualiza todo lo
declarado o contenido en su prefijo.
I-6
1 – Modelos y unidades de diseño en VHDL
haría visibles los componentes xr2, or2 y and2 declarados en el paquete denominado
“modelos” dentro de la biblioteca WORK , con el siguiente formato:
PACKAGE modelos IS
COMPONENT and_2 PORT (e1,e2 : IN BIT; sal: OUT BIT); END COMPONENT;
COMPONENT or_2 PORT (e1,e2 : IN BIT; sal: OUT BIT); END COMPONENT;
COMPONENT xr_2 PORT (e1,e2 : IN BIT; sal: OUT BIT); END COMPONENT;
END modelos;
La cláusula ALL visualiza todos los componentes del paquete, pero también pueden
utilizarse los formatos siguientes:
USE WORK.modelos. and2;
LIBRARY componentes; USE componentes.modelos.ALL;
I-7
1 - Modelos y unidades de diseño en VHDL
Al ser el VHDL un lenguaje en el que el uso de tipos es una característica que afecta a
todos los objetos que contienen un valor, los tipos deberán estar declarados antes de su uso.
Por otra parte, la compatibilidad entre modelos se sustenta en que los objetos usados por los
distintos ficheros y unidades empleen los mismos tipos. Por esto es casi obligado que los
distintos diseñadores implicados en un desarrollo común compartan los paquetes y que estos
sean la primera unidad compilada.
El paquete STANDARD está dentro de la biblioteca STD y contiene la declaración de
los tipos básicos, tales como BIT, BIT_VECTOR, CHARACTER, INTEGER y REAL sin los que
sería imposible escribir código. Por esto, el paquete STANDARD está predefinido y visible
por la cláusula implícita:
Dado que el paquete STANDARD contiene un número muy reducido de tipos, existe
otro paquete estándar del IEEE: el std_logic_1164, contenido en la biblioteca IEEE. Su
uso requiere el empleo de USE y, por su importancia, se verá con algún detalle más
adelante.
I-8
1 – Modelos y unidades de diseño en VHDL
y si después de una etiqueta hasta el resto de ellas, todas las referencias están configuradas
para la misma ENTITY/ARCHITECTURE, puede usarse la cláusula OTHERS:
FOR OTHERS: semisum
USE ENTITY WORK. semisum (lenta); -- pareja entity (architecture x)
END FOR;
I-9
2- Características generales del VHDL
En los apartados que se exponen a continuación se revisan las características generales
del lenguaje VHDL en referencia a su léxico, clases, formato y tipos de datos, así como
aquellos conceptos significativos del lenguaje por su orientación para modelar hardware.
Mayúsculas :ABCDEFGHIJKLMNOPQRSTUVWXYZ
Minúsculas :abcdefghijklmnopqrstuvwxyz
Números :0123456789
Caracteres especiales : “ # & ‘ ( ) * + , - . / : ; < = > _ | $ % @ ? \ ^ ` ~
Códigos de formato : Espacio (20), LF(0A), CR(0D), FF(0C), HT(09), VT(0B)
2.1.1 SEPARADORES
Se permite un número variable de separadores entre elementos léxicos adyacentes,
antes del primero y después del último en una línea de texto. Son los códigos de formato.
2.1.2 DELIMITADORES
Caracteres que se usan para separar elementos léxicos y que tienen algún significado
específico en VHDL. Son los caracteres:
& ‘ ( ) * + , - . / : ; < = > |
por ejemplo, todas las sentencias en VHDL terminan con el carácter delimitador ; .
Cuando se habla de delimitadores compuestos se hace referencia a secuencias de
delimitadores con un significado especial en VHDL, por ejemplo:
=> ** := /= >= <= <> --
2.1.3 COMENTARIOS
Son elementos léxicos precedidos del delimitador -- y que finalizan con la línea
donde están. Los comentarios son los últimos elementos léxicos de una línea. Pueden seguir
a una sentencia VHDL existente en la línea o ser el único elemento léxico en la línea.
código VHDL -- comentarios precedidos de doble guión
2.1.4 IDENTIFICADORES
Son palabras reservadas en VHDL o bien los nombres que el diseñador asigna a los
objetos que utiliza en sus descripciones, por ejemplo, para nombrar constantes, variables,
señales, ENTITYs, ARCHITECTUREs, bloques, subprogramas, etc.
Los identificadores son secuencias de caracteres que empiezan por una letra, pueden
incluir letras, números y caracteres de subrayado aislados o sin duplicar
En el código VHDL no se diferencian letras mayúsculas y minúsculas, salvo que estén
entre comillas, en cuyo caso son elementos diferentes de cadenas literales. Debe evitarse el
uso de palabras acentuadas, incluso en los comentarios.
II-1
2 – Características generales del VHDL
II - 2
2 – Características generales del VHDL
La interpretación de las cadenas binarias queda al criterio del diseñador: “1010” puede
interpretarse como (+10) o como (-6), en función del contexto del dato. Dos ejemplos de
cadenas bits equivalentes son:
B”11110000” B”1111_0000” X”F0”
B”100011001” B”100_011_001” O”431”
Ejemplos correctos:
7 2E5 007 2e1 262_144 3.1416 03.1416 0.31416E1 0.31416e+1
31.416 E-1 0#255# 16#fF# 2#1111_1111#
Ejemplos incorrectos:
1,000 .5 3E-2 5E -1 0.5 e0 16# fF # 2# 1111 1111 #
2.2.1 CONSTANTES
Tienen un valor fijo, asignado al compilarlas, no alterable durante la simulación.
Deben ser declaradas con el siguiente formato:
2.2.2 VARIABLES
Son objetos normalmente utilizados como portadores temporales de valor alterable.
Solo son declarables en áreas secuenciales, como en procesos y subprogramas.
Deben declararse con el siguiente formato:
VARIABLE nombre1,.. nombre_n : TIPO [RESTRICCIONES][:= VALOR INICIAL];
II - 3
2 – Características generales del VHDL
Ejemplos:
VARIABLE temporal: INTEGER RANGE 0 TO 10 := 5;
VARIABLE frecuencia, ganancia: REAL RANGE 1.0 TO 10.0;
VARIABLE octeto: BIT_VECTOR (0 TO 7) := X”FF”;
Las variables, a diferencia de las señales, no pueden pasar valores entre subprogramas.
2.2.3 SEÑALES
Son portadores del valor de un parámetro común a varias unidades de diseño,
utilizándose en descripciones para comunicar cambios del parámetro, normalmente
asociados a un tiempo de simulación. Su relación con el hardware es evidente y, a diferencia
de las variables, solo pueden ser declaradas en áreas concurrentes.
Su formato de declaración y algunos ejemplos son como sigue:
SIGNAL nombre: tipo [ restricciones ][:= valor inicial]; SIGNAL clk: BIT := '0';
SIGNAL databus: BIT_VECTOR ( 7 DOWNTO 0) := B”0000_1111” ;
SIGNAL dos_bytes: octales(0 TO 1) := (B”0000_1111”, B”1111_1111”) ;
Las señales no deben declararse dentro de Procesos, pero se usan dentro de ellos y
como objetos para pasarles valores. Estos aspectos se verán al estudiar los Procesos .
octeto := b”1111_1110”;
frecuencia := 2.0;
temporal := temporal + 1;
clk <= ‘0’; clk <= ‘1’ after 5 ns; databus <= x”0f” after 10 ns;
El valor asignado a la señal debe ser del tipo con el que la señal fue declarada.
Dada la importancia del concepto señal en cualquier circuito a modelar, las sentencias
de asignación de valor a señales son elementos clave y con importantes matices que se verán
al estudiar con más detalle este tipo de sentencias.
II - 4
2 – Características generales del VHDL
1. tipos escalares
Son tipos con valores simples y aislados.
Existen tres tipos escalares: ENUMERADOS, NUMÉRICOS y FÍSICOS.
2. tipos compuestos
Tienen valores compuestos por conjuntos de valores. Son los ARRAYS y RECORDS.
3. tipos fichero
Son tipos especiales utilizados para definir objetos relacionados con la escritura y
lectura de ficheros o archivos de datos contenidos en el sistema donde se hace la
simulación del modelo. Estos ficheros, cuyo formato puede ser especial o de texto,
pueden utilizarse como entradas para simulación del modelo o como ficheros en los
que se archivan las salidas del mismo. Por su relación al paquete TextIO, se verán en
detalle al estudiar este paquete en una sección posterior.
4. tipos acceso
Se usan en descripciones complejas. Su estudio no se considera en este documento.
donde '0' es el valor por defecto, 'Z' = 'alta impedancia' y 'X' = 'valor indefinido'.
Para poder utilizar el tipo cuad en las descripciones se puede:
- Declararlo en la parte declarativa de la ARCHITECTURE.
- Incluirlo en un paquete, al que se llamaría con USE para habilitarlo.
II - 5
2 – Características generales del VHDL
2.4.4 ARRAYS
Son tipos compuestos por elementos homogéneos, con igual subtipo. Un ejemplo se
tiene en los tipos STRING y BIT_VECTOR del PACKAGE.STD. STRING es un array de
caracteres y BIT_VECTOR es un array de bits. Los arrays se puede considerar y definir como
tipos indexables y multidimensionales, pudiendo dejarse sin definir sus dimensiones o
rangos. El formato y algunos ejemplos son como sigue:
Nótese que los elementos del array pueden indexarse de dos formas, en las que se
especifica el índice dentro del rango de ( izquierda a derecha ).
El array puede tener dimensiones abiertas, útil para describir diseños genéricos:
El delimitador compuesto <> indica que es un array con rango abierto, cuyos límites
vendrán especificados posteriormente en la aplicación que use el tipo así declarado.
Pueden declararse tipos enumerados en relación a los índices de un array, por ejemplo:
II - 6
2 – Características generales del VHDL
que nos indica que los valores almacenados de “uno” a “cinco” son enteros, que el primer
elemento del array tiene por nombre “uno” y que con él nos podemos referir a ese elemento,
sea para asignarle un valor o para leerlo después.
Una vez que los arrays están declarados, o llamado el paquete en que se hayan
incluido, se puede asignar valores a los elementos de los arrays o utilizar estos elementos
para asignar valores a objetos de tipo compatible, por ejemplo:
"ZZZZZZZZ" es el valor inicial forzado en la declaración, en lugar del valor “00000000” que
tendría si no hubiese inicialización, ya que el valor por defecto del tipo cuad es '0'.
En los ejemplos que siguen pueden verse posibles formas de asignación de valores a señales
relacionadas con los tipos array declarados anteriormente:
este TYPE estará definido por una tabla de (4 x 4), siendo el orden de filas y columnas el
definido para el tipo cuad, es decir , ('0','1','Z','X') , ('0','1','Z','X').
La inicialización de los valores de una señal del tipo array multidimensional se efectúa
dentro de paréntesis anidados, separados por comas, en el mismo orden o dirección en que
están declarados los elementos del array.
el array bidimensional memdato puede sustituirse por dos arrays unidimensionales como
II - 7
2 – Características generales del VHDL
Con lo visto hasta aquí, y suponiendo que se tienen declarados los tipos anteriores
apropiadamente en el paquete “modelos” sería posible modelar una sencilla memoria ROM
como sigue:
USE WORK. modelos. ALL;
ENTITY memrom IS
PORT ( direc : IN INTEGER;
datos : OUT palabras);
END memrom;
ARCHITECTURE minima OF memrom IS
CONSTANT romdatos : memdato := ( (‘0’, ‘0’, ’0’, ‘0’, ‘0’, ‘1’, ‘1’, ‘1’),
(‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘0’, ‘0’, ‘0’),
(‘0’, ‘0’, ‘0’, ‘1’, ‘1’, ‘0’, ‘0’, ‘0’),
(‘1’, ‘1’, ‘1’, ‘0’, ‘0’, ‘1’, ‘1’, ‘1’) );
BEGIN
datos <= romdatos( direc ) AFTER 25 ns;
END minima;
2.5 SUBTIPOS
Son subconjuntos de los valores de un tipo predefinido, al que se llama tipo base, del
cual se obtienen fijando alguna restricción. Los distintos subtipos obtenidos de una misma
base son totalmente compatibles entre sí y con su base, lo que permite usar con ellos todas
las funciones definidas para el tipo base.
Todos los tipos son subtipos de ellos mismos, por lo que subtipo se usa a veces para
referirse a todos los tipos y subtipos declarados de una misma base.
Los subtipos se declaran de forma similar a los tipos, indicando después de la palabra
clave SUBTYPE el nombre que se le asigna, seguido de IS y del nombre del tipo base del
que se derivan, por ejemplo :
SUBTYPE cuarteto IS bit_vector ( 3 DOWNTO 0);
SUBTYPE decadas IS integer RANGE 0 TO 9;
II - 8
2 – Características generales del VHDL
para asignar el valor de un objeto de ese tipo a otro del tipo BIT_VECTOR, sería necesario
hacer una conversión para pasar los elementos del tipo "semibyte" al tipo BIT_VECTOR, lo
cual sería innecesario si el objeto driver fuese del tipo “cuarteto” definido arriba.
La asignación de valores de un subtipo a objetos de su tipo base es siempre posible, ya
que es un subconjunto de la base. Por razón similar, un valor del tipo base puede no ser
asignable a un objeto del subtipo, por ejemplo, si se tienen los subtipos :
SUBTYPE triple IS cuad RANGE '0' TO 'Z' ;
SUBTYPE binar IS cuad RANGE '0' TO '1' ;
los objetos del subtipo "binar" son directamente asignables a objetos "triple"o "cuad" y
viceversa, pero cuidando no provocar asignaciones que sobrepasen la dimensión definida
para el subtipo destino, ya que se tendría un mensaje de error por asignación fuera de rango.
Nótese, por contra, que el subtipo "binar" no es compatible con el tipo BIT definido en
el paquete STANDARD. Aunque sus elementos son los mismos, en "binar" la base es "cuad".
Es evidente que para modelar o simular hardware digital, el tipo BIT del paquete
STANDARD es insuficiente ya que solo dispone de los valores 0 y 1. Por otra parte, si cada
usuario define sus propios tipos y paquetes resultarán incompatibilidades que dificultarán
los desarrollos compartidos o reutilizables. Para evitar estos inconvenientes, el IEEE
desarrolló un nuevo paquete denominado STD_LOGIC_1164, donde se declara el tipo
std_ulogic con nueve valores.
El paquete STD_LOGIC_1164 está dentro de una biblioteca denominada IEEE, por lo
que, a diferencia de los tipos bit y bit_vector, que por estar en el paquete y biblioteca
STANDARD siempre están visibles, para usar los tipos std_ulogic es necesario iniciar la
descripción con las sentencias:
libarary IEEE;
use IEEE. std_logic_1164.all;
que, al hacer visibles la biblioteca y el paquete, permiten utilizar los tipos allí declarados.
El tipo base declarado en el paquete std_logic_1164 es el tipo std_ulogic, conocido
también como MVL9 - multi value logic - y tiene sus nueve valores declarados como:
II - 9
2 – Características generales del VHDL
Los atributos son valores específicos tales como datos, funciones, tipos o rangos
asociados con los objetos a que se refieren. Los atributos permiten un uso más eficiente del
lenguaje al disponer de codificaciones adicionales que simplifican las descripciones
El formato tipo es :
Otros ejemplos se obtienen del paquete STANDARD, a partir de los tipos CHARACTER y BIT:
character’POS(NUL) = 0 ; character’POS(‘0’) = 48
bit’LEFT = ‘0’ bit’RIGHT = ‘1’ bit’POS(‘0’) = 0 bit’VAL(0) = ‘0’
Nótese que NUL va directamente, mientras que el carácter ‘0’ va entre apóstrofos.
II - 10
2 – Características generales del VHDL
De forma similar, para tipos INTEGER como los subir y bajar definidos a
continuación, se tienen los ejemplos siguientes, en los que deben apreciarse las diferencias
que existen :
nombre_de_array ’ atributo[(n)]
Existen los siguientes atributos de arrays:
se tendría
II - 11
2 – Características generales del VHDL
Asociados en grupos en los que todos los operadores tienen igual prioridad y
ordenados los grupos por relación de precedencia, se tiene la clasificación siguiente:
Nótese que los operadores AND y OR, por ser asociativos, permiten escribir indistintamente
a := b AND c AND o bien a := c AND d AND b
z := b OR c OR d o bien z := c OR b OR d
mientras que los operadores NAND y NOR, no asociativos, requieren el empleo del
operador NOT con más de dos operandos, por ejemplo, para representar la función NOR de
tres entradas, no se puede formular como :
z <= x NOR y NOR w -- es ilegal
ni tampoco como
z <= ( x NOR y ) NOR w -- legal, pero no es la función NOR
debiendo expresarse como
z <= NOT ( x OR y OR w )
que justifica la mayor prioridad de NOT.
II - 12
2 – Características generales del VHDL
En este último ejemplo puede verse el doble significado del delimitador compuesto <= ,
cuyo sentido correcto es deducido por el contexto de la expresión donde figure.
II - 13
2 – Características generales del VHDL
NOT Operador lógico NOT, para tipos BIT y booleanos. Algunos ejemplos son :
VARIABLE X,Y,Z: INTEGER := 10;
VARIABLE A: REAL := 5.0;
SIGNAL S1,S2,S3 : BIT := ‘1’;
w <= ( x AND y ) OR z;
II - 14
2 – Características generales del VHDL
Si posteriormente las mismas variables se tuviesen de tipo cuad, definido previamente, sería
posible mantener la expresión anterior si antes se hubieran definido los operadores AND y
OR para los tipos cuad, ya que estos operadores solo están predefinidos para los tipos BIT
y BOOLEAN. La expansión o sobrecarga de los operadores AND y OR, se hace
definiendo un nuevo operador, con igual nombre, por medio de una función que devuelve
resultados de tipo cuad a partir de operandos cuad . La función o subprograma hará el efecto
de un macrooperador, como se verá con más detalle en la sección 4 sobre subprogramas.
Las situaciones de sobrecarga se resuelven en VHDL por contexto, es decir, si los
operandos son, por ejemplo, del tipo cuad y hay una expresión donde se llama a un
subprograma existente para aplicarles la función AND u OR, el VHDL aplicará la función
sobrecargada para dichos tipos y devolverá un resultado que será acorde con el que se
espera que, puede ser de tipo BIT, INTEGER, cuad u otro cualquiera definido, siempre que
exista la función o subprograma sobrecargado que corresponda al tipo de parámetros de
entrada y salida especificados al invocarlo. Es decir, el concepto de sobrecarga se extiende
a tipos, operadores y subprogramas.
Cuando se sobrecargan operadores, al declararlos y definirlos, estos van entre
comillas, por ejemplo “AND” y “OR”, para diferenciarlos de las funciones. La razón es que
los operadores van entre los operandos mientras que los subprogramas se llaman con los
parámetros entre paréntesis. En el paquete “modelos” se tienen algunos ejemplos de
operadores sobrecargados.
A veces, existen expresiones en las que puede existir una ambigüedad que VHDL no
puede resolver por la sobrecarga que tengan los objetos, por ejemplo, en la expresión
y en un contexto donde están visibles los tipos cuad, aparte de los CHARACTER, siempre
visibles por ser declarados en el paquete STANDARD, se tendría una situación cuyo
resultado depende del tipo que se considere para los elementos sobrecargados, por ejemplo:
( ‘Z’ < ‘X’ ) es TRUE si los elementos son del tipo cuad ( ‘0’, ‘1’, ‘Z’, ‘X’)
(‘Z’ < ‘X’ ) es FALSE si los elementos son del tipo CHARACTER
Para evitar situaciones como la del ejemplo, se deben cualificar las expresiones
susceptibles de ambigüedad. Esto se hace por marcado de tipos o expresiones cualificadas
que consisten en forzar el tipo de los elementos según el formato de expresión siguiente:
II - 15
3. Sentencias Concurrentes
Son las sentencias que se usan directamente dentro del cuerpo de las ARCHITECTUREs
y, a diferencia de lo habitual en los lenguajes de programación, estas sentencias no se
ejecutan en el orden en que están escritas sino que solo se ejecutan cuando cambia alguna de
las señales de las que dependen los resultados que se computan en las sentencias. Otra
característica es que todas las sentencias se ejecutan una vez al principio de la simulación.
Algunas de las sentencias que se ven en esta sección pueden ser concurrentes o
secuenciales, dependiendo del área en la que estén. Entre éstas están las ASSERT, vistas en
la sección de secuenciales, las asignaciones simples de valor a señales y las llamadas a
procedimientos.
En VHDL, los componentes son elementos que se declaran como una caja negra y de
la que solo se describe su interfaz. El formato de declaración de componentes es:
COMPONENT nombre_de_componente -- no incluye la palabra reservada IS
PORT (local1, local2,... localn : modo y tipo);
END COMPONENT;
Tanto en los componentes como en las ENTITYs, los puertos locales se asocian a
señales físicas y, aunque similares en formato, hay diferencias importantes entre ambos:
III - 1
3 – Sentencias concurrentes
que, aunque tiene el mismo formato que la asignación concurrente, es una sentencia de
asignación secuencial. Las asignaciones condicionales y selectivas de señal son sentencias
exclusivamente concurrentes por lo que no podrán utilizarse dentro de los procesos.
Si hay varias asignaciones secuenciales a una misma señal dentro de un proceso, la única
asignación efectiva será la última y lo será cuando el proceso haya terminado, ejecutándose
todas las sentencias secuenciales que lo componen.
III - 2
3 – Sentencias concurrentes
la señal reloj se activará una vez al comienzo de la simulación del modelo y posteriormente
siempre que haya un cambio en las señales impulsos y permiso, por ser la señal reloj sensible a
las señales impulsos y permiso o, expresado en otra forma habitual en VHDL, porque éstas
constituyen su lista de sensibilidad.
Siempre que un cambio en las señales drivers, escritas a la derecha del delimitador
compuesto <=, provoca un cambio en el valor de la señal destino, a la izquierda del
delimitador, se tiene un evento en la señal a la que se asigna valor. Sin embargo, pueden
ocurrir cambios en los drivers que no provoquen eventos en la señal destino, por ejemplo, si
la señal permiso fuese ‘0’, los cambios de ‘0’ a ‘1’ o de ‘1’ a ‘0’ en la señal impulsos no
ocasionarían eventos en la señal reloj. En estos casos, en la literatura americana, se dice que
en la señal destino, en lugar de eventos, hay transactions.
Dejamos aparte cualquier consideración de retardos que, aunque pueden ser necesarios para
describir el comportamiento de un circuito, carecen de interés a la hora de sintetizar un
modelo cuyos retardos dependerán de las características de la FPGA o el ASIC donde se
vaya a implementar el circuito. El compilador, aunque no rechace la especificación de un
retardo, no obedece a expresiones del tipo: “after XX ns; ” o similares.
III - 3
3 – Sentencias concurrentes
Su formato es
[etiqueta :] nombre <= onda1 WHEN condición1 ELSE
onda2 WHEN condición2 ELSE
....
ondaN WHEN condiciónN ELSE
ondaX;
Tan pronto una de las condiciones se cumple, es TRUE, la sentencia se ejecuta y termina. Si
no se cumple ninguna de las condiciones, se asigna el valor por defecto - ondaX -, como
muestra el ejemplo para un inversor triestado, con especificación de parámetros genéricos:
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
ENTITY inv_triestado IS
PORT ( e1, en: IN BIT; sal: OUT std_logic);
END inv_triestado; -- RETARDOS IGNORADOS EN SÍNTESIS
Nótese que en el ejemplo los valores ‘1’, ‘0’ y ‘Z’ son fijos, pero podrían ser ondas
especificadas como una relación de valores en tiempos definidos en cada caso, por ejemplo:
En este ejemplo, la condición es de tipo INTEGER y la salida es una forma de onda que
cambia según el valor de la señal ent. La sentencia se ejecuta cada vez que cambia el valor
de la señal ent o cuando haya un cambio en la señal driver de la salida. El caso más general
III - 4
3 – Sentencias concurrentes
es que las formas de onda descritas en el ejemplo con valores discretos sean expresiones de
otras señales de entrada, por ejemplo:
ENTITY selector IS
PORT( a,b, sel1,sel2 : IN BIT; sal: OUT BIT);
END selector;
En este ejemplo, la asignación a la señal sal ocurre siempre que cambien a o b, así como
cuando cambie cualquiera de las señales de selección sel1 o sel2, además de la asignación
que siempre ocurre una vez al comienzo de la simulación.
Ejemplos:
III - 5
3 – Sentencias concurrentes
ENTITY decoder_3_a_8 IS
PORT ( adr : IN BIT_VECTOR ( 2 DOWNTO 0 );
sal : OUT BIT_VECTOR ( 7 DOWNTO 0 ) ) ;
END decoder_3_a_8;
ARCHITECTURE directa OF decoder_3_a_8 IS
BEGIN
WITH adr SELECT
sal <= "00000001" WHEN "000", -- atención a "comas" (,)
"00000010" WHEN "001",
"00000100" WHEN "010",
"00001000" WHEN "011",
"00010000" WHEN "100",
"00100000" WHEN "101",
"01000000" WHEN "110",
"10000000" WHEN "111"; -- atención: "punto y coma" (;)
END directa;
ENTITY mux_cuatro_a_1 IS
PORT (i0,i1,i2,i3, s0,s1: IN std_logic; z:OUT std_logic);
END mux_cuatro_a_1;
III - 6
3 – Sentencias concurrentes
Dado que la señal clk es de tipo std_logic en este ejemplo, si se considera como no
admisible la posible transición de ‘X’ a ‘1’ en la señal clk, se podría modificar la sentencia
reforzando la condición de flanco ascendente con el atributo ‘LAST_VALUE como sigue
IF ( clk = ‘1’) AND ( clk’EVENT ) AND ( clk’ LAST_VALUE = ‘0’ ) THEN
q <= d; -- ATRIBUTO NO RECONOCIDO EN MAX+plus II
END IF; -- RECONOCIDO Y SINTETIZADO EN QUARTUS II
III - 7
3 – Sentencias concurrentes
Existen otros cuatro atributos de señal que suministran nuevas señales a partir de la
señal a que se refieren, lo que permite usarlas igual que aquellas de las que se derivan,
aportando información no disponible directamente en las señales originales. Esos atributos
son los que siguen:
señal’DELAYED ( tiempo) Proporciona una señal del mismo tipo que la referencia, con un
retraso respecto a la referencia indicado en el campo opcional.
señal’TRANSACTION Proporciona una señal de tipo BIT que cambia de valor con
cada TRANSACTION o “cambio en drivers” .
CAMBIOS en DRIVERS ▓ ▓ ▓
SEÑAL ORIGINAL ( orig ) ej.: bit ░ ░ ░
▓ ▓ ▓
SEÑAL’EVENT boolean valor eventos
0 10 20 30
S
S’delayed( 5ns )
S’delayed(15ns)
III - 8
3 – Sentencias concurrentes
Es similar a la sentencia ASSERT secuencial, con la diferencia de que puede tener una
etiqueta que no está permitida en la sentencia secuencial y que, al ser concurrente, no puede
ir dentro de una sentencia PROCESS, pero equivale a un proceso de tipo pasivo, es decir,
uno que NO asigna valor a señales, aunque sea sensible a ellas. Al igual que la sentencia
secuencial, se emplea para verificar la ocurrencia de condiciones que se desea hacer patentes
por medio de un mensaje durante la simulación, por ejemplo, detectar valores fuera de
rangos permitidos, violación de márgenes de diseño, de tiempos de guarda tales como setup,
hold, duración de impulsos, etc. Su formato es el siguiente:
Una aplicación particular de esta sentencia es que puede usarse como proceso pasivo
dentro de un formato más complejo de la ENTITY donde está permitida una región para
sentencias concurrentes, lo que permite realizar comprobaciones aplicables a cualquiera de
las ARCHITECTUREs que describan la ENTITY, por ejemplo:
III - 9
3 – Sentencias concurrentes
ENTITY SRlatch IS
PORT ( s,r : IN BIT; q,qn : OUT BIT);
BEGIN
verificar : ASSERT NOT ( ( S = ‘1’) AND ( R = ‘1’) ) -- sentencia concurrente
REPORT “S = R = ‘1’ simultáneamente “
SEVERITY ERROR;
END Srlatch;
Para permitir que el modelo sea adaptable a la dimensión deseada, se puede hacer uso
de la opción GENERIC permitida al declarar ENTITYs con el formato siguiente:
ENTITY identificador IS
GENERIC (dimension : NATURAL := número de iteraciones );
PORT ( );
END identificador;
III - 10
3 – Sentencias concurrentes
LIBRARY IEEE;
USE IEEE. STD_LOGIC_1164.ALL;
BEGIN
cuenta(WIDTH) <= Serial_in;
dff_gen:
FOR i in (WIDTH-1) downto 0 GENERATE
process (clk)
begin -- Modelo de D flipflop
if (clk'event and clk ='1') THEN -- iterado con la sentencia
cuenta(i) <= cuenta_next(i); -- FOR GENERATE
end if ;
end process;
cuenta_next(i) <= cuenta(i+1); --Salidas a señal interna
END GENERATE;
salidas <= cuenta(WIDTH-1 downto 0);
END convertidor;
III - 11
4. Sentencias secuenciales
Se utilizan para modelar comportamiento por procedimientos algorítmicos, por lo que
su uso está permitido únicamente dentro de sentencias Process o subprogramas.
4.1 Sentencias IF
Este formato general contiene tres estructuras básicas como muestran los ejemplos :
IV - 1
4 – Sentencias secuenciales
El uso de cláusulas ELSIF es una alternativa al uso de IFs anidados que, aún siendo
legales en VHDL, tienen una lectura e interpretación más complejas que las resultantes con
cláusulas ELSIF. El resultado de usar cláusulas ELSIF o IFs anidados no es normalmente el
mismo. No hay equivalencia directa, aunque las descripciones hechas con IFs anidados
puedan sustituirse con sentencias basadas en ELSIFs. Vease un ejemplo:
Otro aspecto importante es el uso u omisión de las cláusulas ELSE, que puede dar
lugar a descripciones con comportamientos imprevistos. El siguiente ejemplo permite ver la
importancia de las cláusulas ELSE al modelar circuitos:
IF ( c = ‘1’ ) THEN
IF ( a = ‘1’ OR b = ‘1’ ) THEN a a
s <= ‘1’; b
b s
ELSE c
s <= ‘0’; s
END IF;
ELSE
s <= ‘0’;
END IF;
IV - 2
4 – Sentencias secuenciales
c
IF ( c = ‘1’ ) THEN a
IF ( a = ‘1’ OR b = ‘1’ ) THEN a b ss
salida <= ‘1’; b c
END IF; c
END IF; s
se infiere otro elemento donde se almacena la salida OR para todos los casos no incluidos en
la sentencia IF interna Así pues, para evitar imprevistos, conveniente incluir siempre la
cláusula ELSE o, al menos, revisar con atención los efectos de su omisión.
IV - 3
4 – Sentencias secuenciales
4.1.1 INFERENCIAS BÁSICAS DE SENTENCIAS “IF” EN SÍNTESIS VHDL
ENTITY inf_AND_LATCH IS
PORT(permiso, dato : IN BIT;
sal_AND, sal_latch, sal_dato : OUT BIT);
END inf_AND_LATCH;
ARCHITECTURE inferencias OF inf_AND_LATCH is … sobre la importancia de la cláusula ELSE
BEGIN
PROCESS (PERMISO, DATO)
BEGIN
IF ( permiso = '1' ) THEN
IF dato = '1' THEN
sal_AND <= '1';
ELSE
sal_AND <= '0';
END IF;
ELSE
sal_AND <= '0';
END IF;
END PROCESS;
PROCESS (PERMISO, DATO)
BEGIN
IF ( permiso = '1' ) THEN
IF dato = '1' THEN
sal_latch <= dato;
ELSE
sal_latch <= '0';
END IF;
END IF;
END PROCESS;
PROCESS (PERMISO, DATO)
BEGIN
IF ( permiso = '1' ) THEN -- TODO “IF” DEBERÍA LLEVAR UNA CLÁUSULA “ELSE” EXPLÍCITA, PORQUE, por ejemplo:
IF dato = '1' THEN -- SI dato = ‘1’ sal_dato <= dato, … PERO si dato /= ‘1’, VHDL mantendrá el valor de sal_dato que hubiera anteriormente,
sal_dato <= dato; -- lo que implica la existencia de un elemento de memoria
END IF; -- LA AUSENCIA DE “ELSE” EQUIVALE A MANTENER EL VALOR PREVIAMENTE ASIGNADO, ES DECIR, A INCLUIR UNA SENTENCIA DE FORMA:
END IF; -- ELSE
END PROCESS; -- sal_dato <= sal_dato;
END inferencias; -- equivalente a una realimentación con bucle cerrado, es decir, un elemento de memoria que conviene no olvidar…
IV - 4
4 – Sentencias secuenciales
LIBRARY ieee; USE IEEE.STD_LOGIC_1164.all; -- Flip-flop
ENTITY inf_FpFp IS
PORT (permiso, dato, reloj : IN STD_LOGIC;
salida, sal_AND : OUT STD_LOGIC);
END inf_FpFp;
ARCHITECTURE inf_FF OF inf_FpFp is
BEGIN
PROCESS ( dato, reloj )
BEGIN
IF ( reloj'EVENT AND reloj = '1' ) THEN
salida <= dato;
END IF;
END PROCESS;
sal_AND <= permiso AND dato;
end inf_FF;
IV - 5
4 – Sentencias secuenciales
…
“salida” conmuta, por acción de CLEAR o PRESET, con el siguiente flanco ↑ clk
IV - 6
4 – Sentencias secuenciales
ENTITY if_multiplexer IS
PORT(a,b,c,d: IN BIT;
sel: IN BIT_vector(1 downto 0);
salida: OUT BIT);
END if_multiplexer;
IV - 7
4 – Sentencias secuenciales
ENTITY others_shift_register IS
PORT(clk, SI, CLR : in std_logic;
SO : out std_logic);
END others_shift_register;
(OTHERS => '0') asigna valor ‘0’ a todos los elementos del array “temp” a los que
no se ha asignado valor anteriormente; puede hacerlo de forma asíncrona o síncrona.
Se usan cuando, a partir de los valores de una expresión, se desea seleccionar alguna
de las opciones posibles, lo que equivale en comportamiento al de la sentencia de asignación
selectiva de valor a señales. Su formato básico es :
CASE expresión IS
W HEN selección => secuencia de sentencias;
{ W HEN selección => secuencia de sentencias
END CASE;
cuyo significado es que si el valor de una selección es alguno de los posibles que se indican
de la expresión, deberán ejecutarse las sentencias que sigan a la correspondiente cláusula
W HEN. Es importante a tener en cuenta que deberán especificarse las acciones a tomar para
todos los casos posibles o valores que pueden tenerse para la expresión en la sentencia.
IV - 8
4 – Sentencias secuenciales
El siguiente ejemplo permite comparar la sentencia CASE con la asignación selectiva del
ejemplo en apartado 3.3.3 o la sentencia IF del modelo IF_decoder en la sección anterior.
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
ENTITY case_decoder_3a8 IS
PORT ( adr : IN std_logic_VECTOR (2 DOW NTO 0);
fin : OUT std_logic;
sal : OUT std_logic_VECTOR (7 DOW NTO 0)) ;
END case_decoder_3a8;
CASE dato_triestado IS
W HEN '0' => entrada <= '0';
W HEN '1' | 'Z' => entrada <= '1';
END CASE;
CASE x + y + z IS
W HEN 0 => suma <= “ cero “;
W HEN 1|2 => suma <= “ bajo “;
W HEN 9|10 => suma <= “ alto” ;
W HEN (3 to 8) => suma <= “ medio” ;
W HEN OTHERS => NULL;
END CASE;
Indican que no debe realizarse acción alguna, como al final del ejemplo anterior.
IV - 9
4 – Sentencias secuenciales
Se emplean para repetir una acción que, en la mayoría de los casos, ocurre mientras se
mantiene o cumple una determinada condición. Los LOOP pueden anidarse. Existen tres
tipos de sentencias LOOP con los formatos genéricos que se indican:
Dentro del bucle no hay regiones declarativas. Las variables que intervengan en la
condición booleana deben ser declaradas previamente para que el programa pueda evaluar la
condición la primera vez que la encuentra. Las variables se alteran dentro del bucle y, al no
ser locales a él, es necesario tener presente si el valor con que quedan puede afectar a otras
secciones del área secuencial donde está el bucle y actuar en consecuencia. El ejemplo sería:
x := 1;
WHILE x <= 10 LOOP
y := x**2;
x:= x + 1;
END LOOP;
IV - 10
4 – Sentencias secuenciales
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
BEGIN
PROCESS(clk)
BEGIN
IF(clk'EVENT and clk ='1') THEN
FOR i IN 0 to 6 LOOP --bucle FOR LOOP
temp(i+1) <= temp(i);
END LOOP;
temp(0) <= SI;
END IF;
END PROCESS;
SO <= temp(7);
END serie;
Se emplean dentro de LOOPs para saltar la ejecución de las sentencias que siguen
dentro del paso iterativo en curso o, simplemente, para continuar en el inicio del siguiente
ciclo iterativo si la variable de iteración sigue dentro del rango del bucle, ya que si no
finalizará el bucle. Su formato es:
NEXT [ etiqueta_de_LOOP] [W HEN condición ] ;
Nótese que el hecho de poner la etiqueta de un bucle permite actuar con la sentencia
NEXT dentro de bucles anidados. Si no se incluye la etiqueta, por defecto se reinicia el bucle
interno donde está la sentencia NEXT cuando se cumple la condición adjunta a W HEN.
IV - 11
4 – Sentencias secuenciales
solo que en lugar de saltar a la siguiente iteración, salta fuera del bucle a que se refiere la
etiqueta opcional o, por defecto, fuera del bucle que incluye la sentencia EXIT, continuando
el programa en la sentencia que sigue a la sentencia END LOOP del bucle del que se sale al
cumplirse la condición fijada a la cláusula WHEN . Si la condición no existe, la salida del
bucle se ejecuta siempre que se accede a EXIT.
bucle_1 : LOOP
i := i + 1;
j := 200;
bucle_2: LOOP
IF j < ( i * i ) THEN
EXIT bucle_2;
END IF;
j := j - i;
END LOOP bucle_2;
IV - 12
4 – Sentencias secuenciales
ASSERT NOT ( set ='1' AND rst = '1') -- verifica si (set = rst = '1') es TRUE
REPORT " set y reset son '1' " -- mensaje del fallo a evitar detectado
SEVERITY ERROR; -- y detiene la simulación
El “mensaje” , que debe ir entre comillas, reportará un aviso cuyo significado conoce
el diseñador. En cuanto al nivel del tipo SEVERITY enviado, determinará si la simulación
debe continuar o no.
Normalmente la simulación se detiene con los niveles ERROR y FAILURE y será el
creador del modelo quien deba prejuzgar la gravedad del posible error o condición que
quiera verificar.
El nivel NOTE puede considerarse como un simple aviso, tal vez solo para avisar de
que se ha cubierto una fase o etapa de la verificación.
El nivel WARNING tiene un nivel de importancia más alto. No detiene la simulación
porque, por ejemplo, los resultados pendientes de obtener siguen siendo significativos e
inafectados, tal vez, por la causa que motivó el mensaje de nivel WARNING. No obstante, el
mensaje indica que hay algo que debe subsanarse. En cualquier caso la acción que se deriva
de un nivel de severidad, está relacionado a la herramienta CAD en que se hace la
simulación y , posiblemente, a los parámetros que determinen su acción.
Existe también una sentencia ASSERT concurrente, que actúa cuando alguna señal
referida en la condición a verificar tiene un evento o cambio de valor. El formato es idéntico
al de la sentencia secuencial, pero su ocurrencia viene determinada por el contexto de
ejecución dentro del área concurrente donde se ubica.
IV - 13
4 – Sentencias secuenciales
Por su relación con el parámetro tiempo, las sentencias WAIT son elementos clave en
las descripciones VHDL, empleándose en procesos y subprogramas en los que la suspensión
temporal de su ejecución permite modelar retardos, sincronismos, etc. El formato más
complejo de la secuencia es:
Las opciones pueden combinarse, pero siempre debe existir al menos una de ellas. Si
la palabra WAIT está aislada la simulación se detiene indefinidamente. Los formatos
elementales de la sentencia son:
El proceso continúa en la sentencia que sigue a WAIT. Esta opción de W AIT es utilizada
para descripción de sincronismos y flancos de señal. Es una opción normalmente soportada
para modelar sincronismos en herramientas de síntesis.
El uso de W AIT FOR es frecuente para modelar retardos máximos o “time out”.
IV - 14
4 – Sentencias secuenciales
ENTITY generador IS
GENERIC (tiempo_uno: TIME := 10 ns; tiempo_cero: TIME := 20 ns);
PORT ( sincro : IN BIT ; pulsos : OUT BIT ) ;
END generador;
IV - 15
5. Subprogramas
Los subprogramas son secuencias de declaraciones y sentencias con los que se
realizan operaciones o algoritmos que se aplican en zonas diferentes de una descripción o
que se repiten a lo largo de ella. Para evitar la repetición de código, al igual que en otros
lenguajes, el VHDL permite invocar a las subrutinas desde sentencias o expresiones
colocadas en la zona del programa donde se necesitan los resultados que suministran los
subprogramas. Existen dos tipos de subprogramas: Funciones y PROCEDUREs.
En los subprogramas cabe distinguir una declaración y un cuerpo, lo que equivale a
declarar una interfaz y describir el algoritmo que le corresponde. Posteriormente, desde
algún punto de la descripción se invoca o llama al subprograma de acuerdo con la interfaz o
estructura de su declaración. Mientras la llamada a funciones es parte de una expresión
VHDL, la llamada a PROCEDUREs es una sentencia en sí. Tanto unas como otras se pueden
considerar concurrentes o secuenciales, según el área desde la que se llaman.
Los PROCEDUREs son recursos de escaso uso en VHDL. Su estructura es compleja y
su uso en modelos sintetizables es, prácticamente, nulo, por lo que cae fuera de los objetivos
de este documento.
5.1 Funciones
Las funciones tienen siempre un cuerpo donde se define la operación que realizan a
partir de los parámetros de entrada para devolver un único valor como resultado. Aunque
no es preceptivo declarar las funciones, es conveniente hacerlo porque simplifica la
generación de código y se evitan las restricciones que conlleva la ausencia de declaración.
Hay dos situaciones en las que la declaración de la función es necesaria:
V-1
5 - Subprogramas
V-2
5 - Subprogramas
Se puede probar una función simulando un modelo cuya ENTITY tenga señales de
interfaz equivalentes a las de la función, y una ARCHITECTURE que contenga a la función
en su zona declarativa y la llame en su zona activa, por ejemplo:
ENTITY binario_a_entero IS
port (entrada: in bit_vector(7 downto 0);
salida:out integer range 0 to 255);
END binario_a_entero;
BEGIN
salida <= bin_a_int(entrada);
END conv;
V-3
5 - Subprogramas
V-4
5 - Subprogramas
ENTITY nodoand IS
PORT ( a,b,c :IN cuad ; z :OUT cuad);
END nodoand;
Para modelar un circuito de ese tipo es necesario resolver el conflicto entre drivers
con una función de resolución que determine el valor a asignar a la señal.
La función de resolución tiene como entrada un array abierto formado por los valores
de los drivers, actúa automáticamente al ocurrir un evento en cualquiera de ellos y devuelve
el valor resuelto que estará determinado por la función en base a la fuerza de las señales
drivers.
Si, por ejemplo, el tipo de las señales que vamos a utilizar en un diseño fuera
TYPE cuad IS ( ‘0’,’1’,’Z’,’X’);
V-5
5 - Subprogramas
ejemplo anterior, con tres drivers a, b y c del tipo cuad definido arriba, deberá cumplirse
que
a AND b AND c = ( a AND b) AND c = ( a AND c) AND b = ( b AND c) AND a
ya que de otra forma, habría que considerar un posible resultado diferente en función del
orden en la aplicación de drivers, lo que ni corresponde a situaciones reales ni tampoco se
especifica en VHDL al considerar arrays abiertos.
a 0 1 Z X
b
0 0 0 0 0 CONSTANT tabla_and : cuad_2 := ( ('0','0','0','0'),
('0','1','Z','X'),
1 0 1 Z X
('0','Z','1','X'),
Z 0 Z 1 X ('0','X','X','X'));
X 0 X X X
Dado que el tipo cuad es declarado por el usuario, no hay definido para él ningún
operador y, en consecuencia, todas las operaciones o funciones a realizar con él deberán ser
definidas previamente a su uso, ya sea por inclusión en un paquete al que se tiene acceso por
empleo de la cláusula USE, o por declaración y definición en la región declarativa del
bloque donde se vaya a usar la función.
Las tablas y constantes asociadas, es decir, los contenidos de las tablas, se establecen
por el usuario y su asociación a la AND-cableada es voluntaria y caprichosa, como un
ejemplo de sobrecarga de la función AND predefinida. Se pueden definir otras funciones
cuyas tablas representen otras funciones lógicas más complejas.
V-6
5 - Subprogramas
De forma similar a la función “AND”, se puede definir una función cuya tabla
bidimensional es similar a la anterior, pero donde el elemento de mayor fuerza será ahora el
‘1’ cuad y que, por esta fuerza del elemento ‘1’, se asocia a la función “OR” :
a 0 1 Z X
b
0 0 1 1 X CONSTANT tabla_or : cuad_2 := ( ('0','1','1','X'),
('1','1','1','1'),
1 1 1 1 1
('1','1','1','1'),
Z 1 1 1 1 ('X','1','1','X'));
X X 1 1 X
Una vez definida la función de resolución, existen al menos dos posibles métodos para
obtener el valor de la señal resuelta obtenido por la función:
V-7
5 - Subprogramas
V-8
5 - Subprogramas
y una vez definida la función de resolución en la forma que se ve en el PACKAGE BODY, por
medio de la tabla resolution_table , se pasa a definir los tipos y subtipos siguientes:
V-9
5 - Subprogramas
Dado que estos tipos son resueltos ya, no se les puede aplicar una función de resolución.
Además de las declaraciones del tipo std_ulogic y los subtipos derivados, de los que
quizá el más importante sea el std_logic, el paquete define las funciones lógicas AND,
NAND, OR, NOR, XOR y NOT para los tipos declarados, ya que de otra forma no podrían
aplicarse esas funciones lógicas, predefinidas solo para los tipos BIT, es decir, hace
sobrecarga de dichos operadores.
También se definen en ese paquete funciones de conversión entre tipos de los paquetes
STANDARD Y STD_LOGIC_1164 :
bit y std_ulogic
bit_vector y std_ulogic_vector o std_logic_vector
std_logic_vector y std_ulogic_vector
ENTITY triestados IS
PORT (enab_1, sig_1,enab_2, sig_2: IN std_logic ; sal : OUT std_logic);
END triestados;
V - 10
5 - Subprogramas
y otra posible ARCHITECTURE de esa misma ENTITY, con descripción en estilo funcional o
de flujo de datos puede ser :
ARCHITECTURE flujdats OF triestados IS
BEGIN
sal <= sig_1 WHEN ( enab_1 = '1' ) ELSE 'Z';
sal <= sig_2 WHEN ( enab_2 = '1' ) ELSE 'Z';
END flujdats;
V - 11
6. Modelos estructurales
Contienen una descripción de los componentes que forman el sistema y las conexiones
entre ellos, reflejando de manera precisa la estructura del circuito que describen.
Las sentencias básicas de este tipo de descripciones son las de colocación de
componentes utilizadas para incluir o poner un componente en una ARCHITECTURE y las
sentencias de especificación de configuración, identificados con ENTITYs. Las declaraciones
de componentes pueden ser locales o estar en un paquete al que se accede.
Los modelos estructurales son la base del diseño jerárquico.
Los significados o referencias de cada uno de los campos anteriores son como sigue:
VI - 1
6 – Modelos estructurales
ENTITY nand_3 IS
PORT ( e1,e2,e3 : IN BIT; sal : OUT BIT);
END nand_3;
ARCHITECTURE veloz OF nand_3 IS
BEGIN
sal <= NOT ( e1 and e2 and e3 ) AFTER 5 NS;
END veloz;
a s3
m
s4 amb
b
s5
a A
s1
b B s6
igl
m > A>B amb i
s7
i = A=B igl s2
n < A<B bma s8
s9 bma
n s10
VI - 2
6 – Modelos estructurales
donde las líneas FOR -iguales a las especificaciones de configuración internas- y las END
FOR se repiten con el mismo criterio que las especificaciones de configuración internas. Si
en el ejemplo anterior existieran ARCHITECTUREs ”lenta”, “normal”, y “veloz” para las tres
puertas, se podría modelar el comparador del ejemplo con una ARCHITECTURE única:
USE WORK.puertas.ALL;
ARCHITECTURE config_exter OF compbit IS
-- No existen Especificaciones internas de Configuración
SIGNAL s1,s2,s3,s4,s5,s6,s7,s8,s9,s10 : BIT;
BEGIN
p0 : inver PORT MAP (b,s1);
p1 : inver PORT MAP (a,s2);
p2 : nand_2 PORT MAP (a,m,s3);
p3 : nand_2 PORT MAP (m,s1,s4);
p4 : nand_2 PORT MAP (a,s1,s5);
p5 : nand_3 PORT MAP (s3,s4,s5,amb);
p6 : nand_3 PORT MAP (a,b,i,s6);
p7 : nand_3 PORT MAP (s1,i,s2,s7);
p8 : nand_2 PORT MAP (s6,s7,igl);
p9 : nand_2 PORT MAP (s2,b,s8);
p10 : nand_2 PORT MAP (s2,n,s9);
p11 : nand_2 PORT MAP (b,n,s10);
p12 : nand_3 PORT MAP (s8,s9,s10,bma);
END config_exter;
VI - 3
6 – Modelos estructurales
Cuando se utiliza un par ENTITY ARCHITECTURE en que los puertos –PORT- han
cambiado sus nombres y no se cambia la declaración del componente que los asocia, quizá
porque está declarado en un paquete que probablemente no se desea alterar para no afectar a
otros diseños que lo utilicen, dado que el mapeo se hace referenciando la etiqueta del
componente al que se asocia la nueva ENTITY, será necesario hacer una asociación de
puertos interna en la configuración, por ejemplo, si la situación fuese :
VI - 4
6 – Modelos estructurales
X0 X1 X2 Xn-1 Xn
D Q + D Q D Q D Q
+ +
El circuito de la figura se denomina “LFSR con XOR internas”. Está compuesto por
DFFs y puertas XOR insertadas entre las salidas y las entradas de los DFFs. Nótese que la
inserción de puertas XOR es configurable. Es interesante mencionar de estos LFSRs que:
n n-1 n-2 1 0
El polinomio característico es del tipo: X + Cn-1. X + Cn-2. X +…. + C1. X + X
Para modelar el LFSR con XOR internas, se parte de las XORs y DFFs utilizados y se
define un módulo con una puerta AND de dos entradas, una de las cuales si está a ‘1’ fija la
existencia de la conexión de realimentación a la puerta XOR y, si está a ‘0’ transforma la
función XOR en un buffer, es decir, se define el coeficiente del polinomio correspondiente.
VI - 5
6 – Modelos estructurales
pr
d xro
D Q Nótese que si e2 = 0
clk qd xro = qd
Los DFFs son inicializados a ‘1’ por activación de la entrada PRESET ( pr = ‘1’ ).
La entrada e2 de las puertas AND se usa para aplicar el polinomio del LFSR, mientras
que la entrada e1 está permanentemente conectada al lazo de realimentación.
A partir del componente XRF se puede modelar un LFSR de cuatro XRFs como :
ENTITY lfsr IS
PORT( clk : IN BIT;
pr, poly : IN BIT_VECTOR (0 TO 3) ;
qd : OUT BIT_VECTOR (0 TO 3) ) ;
END lfsr;
La señal poly se deriva de los coeficientes del polinomio característico: los de Xn y X0 son
siempre ‘1’, indicando que se realimenta siempre desde la última salida (coeficiente 1 en
Xn) a la primera entrada (coeficiente 1 en X0). Como el último DFF nunca está cargado con
XOR, su salida equivale a un buffer obtenido con una AND cerrada por su e2=’0’, es decir,
siempre será el elemento poly(N) = ’0’.
VI - 6
6 – Modelos estructurales
que puede generalizarse para LFSRs con N XRFs usando GENERIC y sentencias GENERATE
por medio de la descripción siguiente :
ENTITY lfsr_gen IS
GENERIC ( N : POSITIVE := 4 ); -- particularización al grado del lfsr
PORT( clk : IN BIT;
pr : IN BIT_VECTOR (0 TO (N-1)); -- Hay N DFFs
poly : IN BIT_VECTOR (0 TO (N-2)); -- Hay (N-1) puertas XOR internas
qd : OUT BIT_VECTOR (0 TO (N-1)) );
END lfsr_gen;
ff0 : xrf PORT MAP(xr(N-1), clk, pr(0), xr(N-1), XORen (0), qd(0), xr(0));
GEN : FOR i IN 1 TO (N-2) GENERATE
Ffi : xrf PORT MAP( xr(i-1), clk, pr(i), xr(N-1), XORen (i), qd(i), xr(i));
END GENERATE;
ffN : xrf PORT MAP(xr(N-2), clk, pr(N-1), xr(N-1), XORen (N-1), qd(N-1), xr(N-1));
END cuad;
Nótese que por medio del array pr(i) de PRESET se inicializa la cadena de DFFs con
una determinada combinación; poco después se debe desactivar PRESET para que el
sistema evolucione libremente con las señales de reloj que conmutan a los DFFs. Esta
descripción ha de ser acorde con el modelo de los DFFs descrito por la ENTITY XRF.
La señal XORen se deriva del polinomio característico del LFSR y, a través de las
puertas AND, configura a las XOR que actúan como tales o como buffers. El polinomio
está prefijado y no cambiará durante el funcionamiento del LFSR, ya que no tendría sentido
desde un punto de vista funcional. Por tal razón, así se ha previsto en la lista de sensibilidad
del proceso que describe los DFFs.
VI - 7
6 – Modelos estructurales
Una vez desarrollado el modelo VHDL del circuito, es necesario simularlo para ver
si su funcionamiento es el esperado. El procedimiento que se sigue es desarrollar una
ENTITY de nivel superior al modelo bajo prueba, donde éste será englobado como un
componente. El conjunto formado por la unidad bajo prueba y las descripciones
adicionales para probarla constituyen lo que se denomina test_bench en la literatura
americana, que podríamos llamar banco de pruebas o simplemente probador.
El probador es un modelo simulable, pero NO S INTETIZAB LE, que genera
internamente los estímulos que necesita para probar el modelo y donde se generan
como señales, también internas, las respuestas del modelo a los estímulos. Por tanto,
el conjunto probador tiene una ENTITY sin señales de interfaz, que se declara como:
ENTITY nombre_de_probador IS
END nombre_de_probador;
Las pautas básicas para desarrollar arquitecturas de probadores son las siguientes:
VI - 8
6 – Modelos estructurales
ENTITY decoder_3_a_8 IS
PORT ( adr : IN BIT_VECTOR ( 2 DOW NTO 0 );
sal : OUT BIT_VECTOR ( 7 DOW NTO 0 ) ) ;
END decoder_3_a_8;
ARCHITECTURE directa OF decoder_3_a_8 IS
BEGIN
WITH adr SELECT
sal <= "00000001" W HEN "000",
"00000010" W HEN "001",
"00000100" W HEN "010",
"00001000" W HEN "011",
"00010000" W HEN "100",
"00100000" W HEN "101",
"01000000" W HEN "110",
"10000000" W HEN "111";
END directa;
VI - 9
6 – Modelos estructurales
ENTITY decoder_BIST is
GENERIC ( N : POSITIVE := 3 ); -- particularización al grado del lfsr
PORT( clk : IN bit;
pr : IN bit_vector (0 TO (N-1)); -- Hay N DFFs
poly : IN bit_vector (0 TO (N-2)); -- Hay (N-1) puertas XOR internas
LFSR_Qs : OUT bit_vector (0 TO (N-1)); -- Testigo de salidas internas del LFSR_3
sal : OUT bit_vector (7 DOWNTO 0));
END decoder_BIST;
COMPONENT decoder_3_a_8
PORT ( adr : IN BIT_VECTOR (2 DOWNTO 0);
sal : OUT BIT_VECTOR (7 DOWNTO 0)) ;
END COMPONENT;
signal Qn : bit_vector(0 to 2);
signal adrn : bit_vector(2 downto 0);
BEGIN
adrn <= Qn(0 to 2);
DUT: decoder_3_a_8 PORT MAP(adrn(2 DOWNTO 0), sal(7 DOWNTO 0));
GEN: lfsr_3 PORT MAP(clk, pr(0 to 2), poly(0 to 1), Qn(0 to 2));
LFSR_Qs <= Qn; --Testigo de entradas al decoder
end BIST;
Dado que en LFSR_3 no se ha incluido modificación alguna para insertar el estado ‘000’
en su secuencia, las salidas del sistema serán todas las del decoder, excepto aquella
correspondiente a la “adr = 000”.
VI - 10
6 – Modelos estructurales
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- Paquete para operaciones aritméticas sin signo
ENTITY BIST_adder is
GENERIC ( N : POSITIVE := 9 ); -- particularización al grado del lfsr
PORT (clk: IN std_logic;
pr: IN std_logic_vector (0 TO (N-1)); -- Hay N DFFs
poly: IN std_logic_vector (0 TO (N-2)); -- Hay (N-1) puertas XOR internas
sum_A: OUT std_logic_vector (3 DOWNTO 0); --Testigos del LFSR
sum_B: OUT std_logic_vector (3 DOWNTO 0); --Testigos del LFSR
carry_in: OUT std_logic; --Testigos del LFSR
suma: OUT std_logic_vector (3 DOWNTO 0)); --salida del sumador sin carry_out
END BIST_adder;
COMPONENT adder_4b
port (A,B : in std_logic_vector(3 downto 0); CI : in std_logic;
SUM : out std_logic_vector(3 downto 0));
END COMPONENT;
DUT: adder_4b PORT MAP (As(3 DOWNTO 0), Bs(3 DOWNTO 0), CIs, SUMs(3 DOWNTO 0));
GEN: lfsr_9_mvld PORT MAP(clk, pr(0 to N-1), poly(0 TO N-2), Qn(N-1 downto 0));
VI - 11
7. Modelos de comportamiento
Describen el funcionamiento del sistema al que representan sin hacer referencia al detalle de
subelementos e interconexiones que caracterizan a los modelos estructurales. Si se considera el nivel
de abstracción con que se puede describir el comportamiento de sistemas se distinguen dos estilos:
Sin embargo, los modelos en sí carecen de sentido: cualquier modelo se desarrolla con vistas a
una determinada aplicación, siendo la síntesis aquella aplicación que exige mayor esfuerzo para el
desarrollo de modelos, por las restricciones y matices impuestos por las herramientas de síntesis. En
los apartados que siguen se indican las características de cada uno de estos estilos y se presentan
ejemplos de modelos de varios primitivos de uso frecuente, desarrollados en alguno de los niveles de
abstracción citados y que, siguiendo los pasos descritos anteriormente en modelos estructurales,
pueden ser declarados como componentes para su utilización en una configuración o estructura de
nivel más alto.
En este estilo se detallan las transferencias de datos a nivel de bloques - registros - lo que
implica un diseño previo a nivel de particionado del sistema en subelementos, así como del control de
las transferencias de datos. Esto supone que en estas descripciones se utilizarán, fundamentalmente,
sentencias concurrentes para asignaciones de señales de tipos condicionales y selectivas, así como la
estructura de la descripción en bloques cuyo comportamiento está directamente asociado a este tipo
de sentencias, por lo que estas descripciones se caracterizan por :
Utilización de tipos con relación directa al hardware, fundamentalmente los tipos BIT,
BIT_VECTOR, STD_LOGIC, STD_LOGIC_VECTOR, o similares definidos por el usuario.
Este tipo de descripciones corresponde a un nivel de abstracción más alto que aquel de las
descripciones estructurales a nivel de puertas o componentes, pero sigue precisando una labor de
análisis -diseño top-down- para descomponer el sistema y controlar las interacciones entre los
subelementos.
Algunos ejemplos de este tipo de modelos con estilo flujo de datos son los siguientes:
VII - 1
7. Modelos de comportamiento
Con un nivel de abstracción más elevado que en los modelos estructurales, se puede describir el
funcionamiento del sistema por el flujo de datos entre registros y buses del mismo. El movimiento de
datos se controla por señales que pueden ser generadas, por ejemplo, por máquinas de estados o
FSMs. En ese estilo de descripción, las asignaciones de valor a señales son la base del modelo VHDL
correspondiente, que implica un diseño del sistema en bloques funcionales y buses, organizados en lo
que se suele llamar data path y control path. Sin embargo, cualquier modelo se desarrolla con vistas
a un determinado fin y, en tal sentido, la síntesis es la aplicación que impone más restricciones por
las limitaciones implícitas en las herramientas de síntesis. Con esa orientación, al considerar el nivel
de abstracción de los modelos de comportamiento de sistemas sintetizables, se distinguen dos estilos:
En los apartados que siguen se indican las características de cada uno de estos dos estilos y se
presentan ejemplos de modelos de varios primitivos de uso frecuente, desarrollados en alguno de los
niveles de abstracción citados y que, siguiendo los pasos descritos anteriormente en modelos
estructurales, pueden ser declarados como componentes para su utilización en una configuración o
estructura de nivel jerárquico más alto.
En este estilo se detallan las transferencias de datos a nivel de bloques - registros - lo que
implica un diseño previo a nivel de particionado del sistema en subelementos, así como del control de
las transferencias de datos. Esto supone que en estas descripciones se utilizarán, fundamentalmente,
sentencias concurrentes para asignaciones de señales de tipos condicionales y selectivas, así como la
estructura de la descripción en bloques cuyo comportamiento está directamente asociado a este tipo
de sentencias, por lo que estas descripciones se caracterizan por :
Utilización de tipos con relación directa al hardware, fundamentalmente los tipos BIT,
BIT_VECTOR, STD_LOGIC, STD_LOGIC_VECTOR, o similares definidos por el usuario.
Este tipo de descripciones corresponde a un nivel de abstracción más alto que aquel de las
descripciones estructurales a nivel de puertas o componentes, pero sigue precisando una labor de
análisis -diseño top-down- para descomponer el sistema y controlar las interacciones entre los
subelementos.
Algunos ejemplos de este tipo de modelos con estilo flujo de datos son los siguientes:
VII - 1
7 – Modelos de comportamiento
entity MUX_16a4 is
port (S1, S0 : in std_logic;
A, B, C, D: in std_logic_vector(3 downto 0);
Z: out std_logic_vector(3 downto 0));
end MUX_16a4;
ENTITY mux_32a8_sel IS
PORT (A, B, C, D : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
SEL : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
Z : OUT STD_LOGIC_VECTOR (7 DOWNTO 0));
END mux_32a8_sel;
ARCHITECTURE registrada OF mux_32a8_sel IS
BEGIN
WITH sel SELECT -- asignación SELECTIVA
Z <= A WHEN "00", -- acaba en "," no hay ELSE
B WHEN "01", -- acaba en "," no hay ELSE
C WHEN "10", -- acaba en "," no hay ELSE
D WHEN OTHERS; -- la última asignación acaba en ";"
END registrada;
3- Sumador de bytes
ENTITY sumabin IS
PORT ( a, b : IN BIT_VECTOR ( 7 DOWNTO 0 );
sum : OUT BIT_VECTOR ( 7 DOWNTO 0 );
carry : OUT BIT);
END sumabin;
ARCHITECTURE funcional OF sumabin IS
SIGNAL carry_vector : BIT_VECTOR ( 8 DOWNTO 0);
SIGNAL temp : BIT_VECTOR ( 7 DOWNTO 0);
BEGIN
temp <= a XOR b;
carry_vector <= ((A AND B) OR ( temp AND carry_vector( 7 DOWNTO 0))) & '0' ;
sum <= temp XOR carry_vector( 7 DOWNTO 0) ;
carry <= carry_vector(8);
END funcional;
VII - 2
7 – Modelos de comportamiento
Si comparamos esta descripción con la del apartado 6.1 resulta evidente que usando subprogramas, es
decir, estableciendo modularidad en los diseños, los modelos de VHDL, aparte de tener una mejor
estructura, serán más reducidos y más fácilmente interpretables.
2 - Usar PROCESSs con lista de sensibilidad y estructura lo más simple posible para:
- Circuitos secuenciales, en general: contadores, registros, registros de desplazamiento, máquinas
de estados (FSMs), donde existe la presencia de alguna señal de reloj.
- Crear generic ENTITYs para los circuitos repetitivos y colocar los COMPONENTs
correspondientes a nivel jerárquico más alto, usando GENERIC MAP PORT MAP.
- Suplementar los componentes secuenciales con sentencias concurrentes para describir la lógica
combinacional adjunta a los bloques secuenciales.
VII- 3
7 – Modelos de comportamiento
El estilo algorítmico considera al sistema como una caja negra cuya descripción se centra
fundamentalmente en relacionar entradas y salidas, sin entrar en el detalle de cómo se obtienen unas a
partir de otras. Mientras el estilo flujo de datos indica cómo opera el sistema, el estilo algorítmico
describe qué hace el sistema, por lo que este tipo de descripciones se encuentran organizadas en
PROCESS por su capacidad de uso de sentencias secuenciales y estructuras algorítmicas del tipo IF-
THEN-ELSE, etc. A diferencia de los otros estilos de descripción, el planteamiento previo al
desarrollo del modelo consiste en:
Todo lo anterior equivale a particionar el sistema en módulos operativos cuya acción viene
determinada por la actividad de unos procesos que controlan a otros.
Si en los estilos de descripción estructural o de flujo de datos es fácil asociar hardware al
modelo, en el estilo algorítmico es típico acudir a representaciones por medio de diagramas de flujo o
grafos, tablas de estados, etc. lo que supone un nivel de abstracción por encima del utilizado en los
otros estilos de modelado de sistemas.
Si bien no existe un estilo óptimo para todas las aplicaciones donde haya descripción de
hardware, y aunque el VHDL se utilice para describir sistemas con diferentes niveles de abstracción,
la existencia de los estilos descritos anteriormente está en parte relacionada al control que se desea
tener sobre la operación del sistema, las restricciones que se desea imponer al diseño y, también, a la
potencia o capacidad de las herramientas para síntesis.
Por síntesis se entiende, en este contexto, la capacidad de transformar de forma automática una
descripción desde un nivel de abstracción a otro de nivel inferior. Esta capacidad, hasta tiempo muy
reciente, ha estado limitada a transformaciones desde el nivel RTL hasta el de puertas lógicas, lo que
forzaba al empleo de descripciones a nivel flujo de datos cuando el destino final del modelo era un
proceso de síntesis lógica.
La síntesis algorítmica es de uso relativamente reciente y, por tanto, las limitaciones actuales
dependen no solo de la herramienta, sino también de su versión, condicionando el desarrollo de
modelos al soporte ofrecido por la herramienta y, más particularmente, a su estilo de inferencias, es
decir, la forma en que diseña hardware a partir del código VHDL.
VII - 4
7 – Modelos de comportamiento
Reducción de los tiempos para diseñar e introducir nuevos sistemas en el mercado y reducción
de los costes de diseño, en gran medida relacionados a tiempos de diseño.
Reducción de los errores de diseño, especialmente cuando el tamaño de los proyectos o su
complejidad crece, aumentando la probabilidad de errores, así como la dificultad de depurar los
diseños, con incidencia en el tiempo y coste del diseño.
Posibilidad de obtener varios diseños o alternativas para un juego de especificaciones. Esto
permite elegir la más conveniente después de simular, así como fijar estrategias de gamas o
familias de productos o actualización sin hacer rediseños básicos.
Posibilidad de introducir cambios de especificaciones y alterar los diseños sin cambios
importantes en la planificación o en los costes.
Dado que una de las aplicaciones más importantes del VHDL es la síntesis en ASICs y FPGAs,
aun suponiendo que las ventajas citadas arriba presumiblemente condicionarán no solo el estilo de
diseño o modelado de sistemas, sino también las herramientas elegidas al efecto, se exponen algunos
modelos algorítmicos desarrollados con esa orientación.
Dos de los factores de mérito que se consideran para valorar la eficiencia de un circuito son su
tamaño y su velocidad. Por tanto, el diseño y el modelo deberán enfocarse a fin de reducir tamaño y
maximizar velocidad, dentro de los márgenes que fijen especificaciones como el consumo de
potencia, el coste, etc. En consecuencia, hay que modelar utilizando aquellas sentencias que infieran
el hardware deseado, pero no más, lo que supone utilizar apropiadamente las sentencias a partir de las
que se infieren los elementos básicos, es decir, puertas y registros. Registrar señales
innecesariamente, en general, implica componentes innecesarios -tamaño- y retardos -velocidad-, por
lo que interesa saber que tipo de sentencias infieren registros, ya sean sensibles a nivel - latches - o
disparados por flancos, - flip-flops -, y evitar inferencias innecesarias de registros.
Normalmente, las sentencias empleadas para detectar flancos de subida son:
todas secuenciales y, por tanto, incluidas en PROCESSs, y de las que se inferirán flip-flops en el caso
de WAIT y flip-flops o latches según se construya la sentencia IF. La elección de un tipo de sentencia
u otro puede ser una recomendación de la herramienta de síntesis, pero, normalmente, la sentencia IF
permite mejor control de las inferencias y admite más posibilidades. También, consecuentemente,
exige más cuidado en la descripción.
Los procesos síncronos, que computan valores solamente en los instantes de flancos, deben ser
sensibles a la señal de reloj utilizada.
Los procesos asíncronos, que computan valores con los flancos de reloj y cuando se cumplen
las condiciones asíncronas, deben ser sensibles a la señal de reloj, si existe, y a las señales que
afectan al comportamiento asíncrono.
VII- 5
7 – Modelos de comportamiento
ENTITY up_dwn_counter IS
PORT(c, clr, up_down : IN std_logic;
Q : OUT std_logic_vector(3 DOWNTO 0));
END up_dwn_counter;
ARCHITECTURE simple OF up_dwn_counter IS
SIGNAL tmp: std_logic_vector(3 DOWNTO 0);
BEGIN
PROCESS (c, clr)
BEGIN
IF (clr='1') THEN -- CLEAR ASÍNCRONO
tmp <= "0000";
ELSIF (c'event and c='1') THEN
IF (up_down='1') THEN -- UP_DOWN SÍNCRONO
tmp <= tmp + 1;
ELSE
tmp <= tmp - 1;
END IF;
END IF;
END PROCESS;
Q <= tmp;
END simple;
VII - 6
7 – Modelos de comportamiento
estado siguiente
estado actual
DD Q Lógica de
siguiente estado
reset reset D
Lógica de salidas
ck ck
entradas salidas
Las FSMs se definen como sistemas compuestos por conjuntos de entradas, salidas y estados
que determinan la evolución de la máquina en base a una función de transición entre estados.
Los estados son valores que representan los pasos o etapas por los que la FSM puede avanzar.
Las salidas están determinadas por funciones de salidas que en las FSMs de Mealy dependen
directamente de estados y entradas, mientras en las FSMs de Moore solo dependen directamente de
los estados. Hay equivalencias entre máquinas de Mealy y de Moore, pero existen diferencias en su
comportamiento y velocidad, pues su estructura y el tiempo de respuesta de las salidas es diferente.
La función de transición prepara el siguiente estado para que sea el nuevo estado actual,
activado por el flanco de la señal de reloj -ck- que provoca las transiciones de estados. La función de
transición puede determinar que el siguiente estado sea el mismo que el estado actual. La activación
de reset hará que la FSM salte a un estado inicial predeterminado.
Los cambios de entradas entre flancos de reloj pueden provocar cambios inmediatos en las
salidas de las FSM Mealy, si así lo determinan las correspondientes funciones de salida, mientras que
en las FSM Moore las salidas solo cambian con las transiciones de estados.
En VHDL, para modelar FSMs se pueden considerar los tres bloques de la figura de forma
aislada, asociar dos de ellos o considerar un único bloque para toda la FSM. Según el particionado
que se elija, se aplicarán metodologías apropiadas de síntesis para lógica combinacional y registros,
sin olvidar las restricciones de las herramientas de síntesis. Normalmente, para los estados se definen
tipos “ad hoc”, haciendo uso de los “tipos enumerados” que permite VHDL, por ejemplo:
TYPE estado_ascensor IS
(planta0, planta1, planta2, planta3);
donde se definen señales de nombre significativo, a las que se puede aplicar valores como:
Para describir el comportamiento de una FSM se acude a diagramas de transición y tablas donde se
representan la evolución y las salidas asociadas a cada estado o transición en función de las entradas.
En los diagramas de transición cada estado se representa por un círculo o “burbuja” etiquetada con el
nombre del estado. Por medio de flechas se representa la evolución entre estados o burbujas,
indicando sobre cada flecha los valores de las entradas que provocan ese salto o transición; si no se
indican, la transición entre los dos estados es forzosa o independiente de los valores de las entradas.
En las FSM de Moore, dentro de cada burbuja se indican los valores de las salidas en ese estado.
En los apartados siguientes se verán detalles y alternativas de descripciones para ambas FSMs.
VII- 7
7 – Modelos de comportamiento
1/1
Si la FSM se considera con el diagrama general de tres bloques de una FSM, para describirla
con tres PROCESS, la descripción VHDL podría ser la siguiente:
ENTITY mealyfsm_TRS IS
PORT ( X, CLK, reset : IN BIT;
Z : OUT BIT);
END mealyfsm_TRS;
VII - 8
7 – Modelos de comportamiento
VII- 9
7 – Modelos de comportamiento
Finalmente, si toda la FSM se considera como un bloque para modelarla solo con un PROCESS, la
descripción podría ser la siguiente, donde puede verse que el PROCESS único agrupa las dos
sentencias que iban separadas en la descripción con dos PROCESS
ENTITY mealyfsm_uno IS
PORT ( X, CLK, reset : IN BIT;
Z : OUT BIT);
END mealyfsm_uno;
BEGIN
UNO: PROCESS (clk, reset, X)
BEGIN
CASE estado_actual IS -- Bloques “salidas y siguiente_estado” fusionados
WHEN s0 => IF X = '0' THEN estado_sigte <= s2; Z <= '1';
ELSE estado_sigte <= s0; Z <= '1';
END IF;
WHEN s1 => IF X = '0' THEN estado_sigte <= s3; Z <= '1';
ELSE estado_sigte <= s1; Z <= '0';
END IF;
WHEN s2 => IF X = '0' THEN estado_sigte <= s4; Z <= '0';
ELSE estado_sigte <= s2; Z <= '0';
END IF;
WHEN s3 => IF X = '0' THEN estado_sigte <= s3; Z <= '0';
ELSE estado_sigte <= s0; Z <= '1';
END IF;
WHEN s4 => IF X = '0' THEN estado_sigte <= s1; Z <= '0';
ELSE estado_sigte <= s4; Z <= '1';
END IF;
END CASE; -- Fin del bloque “salidas y siguiente_estado” fusionados
IF reset = '1' THEN -- Bloque de asignación de estado_actual
estado_actual <= s0;
ELSIF (clk'EVENT AND clk = '1') THEN
estado_actual <= estado_sigte;
END IF;
END PROCESS;
END comport;
VII - 10
7 – Modelos de comportamiento
Se repite la presentación de modelos hecha en el apartado anterior para la FSM-Mealy, con una
descripción de una FSM-Moore con tres PROCESS:
ENTITY moorefsm_TRS IS
PORT (X, CLK, reset : IN BIT;
Z : OUT BIT);
END moorefsm_TRS;
ARCHITECTURE comport OF moorefsm_TRS IS
TYPE tipo_estado IS ( s1,s2,s3,s4, s5);
SIGNAL estado_actual, estado_sigte : tipo_estado;
BEGIN
conmutacion: PROCESS(clk, reset)
BEGIN
IF reset = '1' THEN
estado_actual <= S1;
ELSIF (clk'EVENT AND clk = '1') THEN
estado_actual <= estado_sigte;
END IF;
END PROCESS;
VII- 11
7 – Modelos de comportamiento
WHEN s4 =>
IF X = '0' THEN estado_sigte <= s4;
ELSE estado_sigte <= s1;
END IF;
WHEN s5 =>
IF X = '0' THEN estado_sigte <= s2;
ELSE estado_sigte <= s5;
END IF;
END CASE;
END PROCESS;
salidas: PROCESS (estado_actual)
BEGIN
CASE estado_actual IS
WHEN s1 => Z <= '0';
WHEN s2 => Z <= '1';
WHEN s3 => Z <= '1';
WHEN s4 => Z <= '0';
WHEN s5 => Z <= '1';
END CASE;
END PROCESS;
END comport;
ENTITY moorefsm_DOS IS
PORT ( X, CLK, reset : IN BIT; Z : OUT BIT);
END moorefsm_DOS;
VII - 12
7 – Modelos de comportamiento
Por último, una descripción en un único PROCESS, en la que se hace una agrupación de las
sentencias separadas en PROCESS independientes en el modelo moorefsm_dos.vhd:
ENTITY moorefsm_UNO IS
PORT (X, CLK, reset : IN bit;
Z : OUT bit);
END moorefsm_UNO;
VII- 13
8. Introducción a los modelos aritméticos
El uso de funciones y operadores aritméticos es frecuente en los sistemas electrónicos
y, por tanto, en VHDL se consideran tipos y operadores apropiados para modelar y
sintetizar sistemas que incorporan sumadores, comparadores, contadores, multiplicadores y
otros módulos capaces de realizar operaciones aritméticas. Sin embargo, por la dependencia
del VHDL en los tipos de sus objetos, la descripción y síntesis de esos módulos se presta a
confusión al considerar las posibles mezclas de tipos incompatibles en los operandos y en
los resultados esperados, que dependen de las funciones que VHDL define o permite en
cada operación aritmética con los tipos en uso. Los apartados siguientes solo pretenden
hacer una presentación de los tipos y funciones de uso más frecuente, así como de los
paquetes donde tales tipos y funciones están declarados y definidos.
Los paquetes STANDARD y STD_LOGIC no definen funciones aritméticas para los tipos
INTEGER o STD_LOGIC_VECTOR definidos en ellos, lo que hace necesario acudir a otros
paquetes donde se definen nuevos tipos y funciones que es preciso conocer para modelar
convenientemente las operaciones aritméticas.
Los primeros paquetes aritméticos fueron desarrollados por Synopsys e incorporados
como estándares “de facto” a la biblioteca o library IEEE con los nombres std_logic_arith,
std_logic_unsigned y std_logic_signed, donde se definen los tipos unsigned y signed, una
serie de operadores aritméticos para ellos y funciones para conversión a otros tipos como
std_logic_vector. Poco después, el IEEE publicó el estándar numeric_std, recomendado para
nuevos desarrollos, aunque por razones históricas y de compatibilidad no está en la library
IEEE de algunas de las primeras herramientas CAD de VHDL. Así, es frecuente que los
ficheros *.vhd de contenido aritmético se inicien con encabezamientos como:
Debe evitarse el uso simultáneo de los paquetes “arith” y “numeric”, para evitar operaciones
ambiguas. Como puede verse en los paquetes numeric_std y std_logic_arith, los nuevos tipos
se definen como:
VIII - 1
8 – Introducción a los modelos aritméticos
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY comparador_unsigned IS
port( A,B : IN unsigned(7 downto 0);
CMP : OUT STD_LOGIC);
END comparador_unsigned;
VIII - 2
8 – Introducción a los modelos aritméticos
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL; -- necesaria para sumar INTEGERs
ENTITY contador_unsigned IS
port(C, CLR, UP_DOWN : in std_logic;
Q : out UNSIGNED(3 downto 0));
END contador_unsigned;
Otra alternativa podría ser si los tipos de Q y tmp fuesen STD_LOGIC_VECTOR, es decir:
En este caso, manteniendo las sentencias del anterior modelo contador_unsigned, excepto las
asignaciones del IF interno que se cambian como sigue:
IF (UP_DOWN='1') THEN
tmp <= unsigned(tmp) + 1; -- ¡suma de INTEGER y UNSIGNED !
ELSE
tmp <= unsigned(tmp) - 1; -- ¡suma de INTEGER y UNSIGNED !
END IF;
con unsigned(tmp) se realiza un cambio llamado “type casting” que convierte el tipo de la
señal tmp de STD_LOGIC_VECTOR a tipo UNSIGNED, al utilizar una de las funciones que
define STD_LOGIC_ARITH para tipos UNSIGNED. La expresiones aritméticas se interpretan
como sumas de una señal tipo UNSIGNED y una constante tipo INTEGER, para devolver un
resultado tipo STD_LOGIC_VECTOR al llamar a una de las funciones definidas en
STD_LOGIC_ARITH. En la página siguiente se muestra un ejemplo más de esa particular
conversión de tipos con igual formato, como son STD_LOGIC_VECTOR y UNSIGNED.
VIII- 3
8 – Introducción a los modelos aritméticos
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_unsigned.all;
ENTITY suma_incr IS
PORT ( A,B : IN std_logic_vector(7 downto 0);
C,D :OUT std_logic_vector(7 downto 0));
END suma_incr;
Otra descripción simple del mismo ejemplo, pero utilizando ahora el paquete
STD_LOGIC_ARITH, permite ver las sutilezas de las funciones definidas en algunos paquetes
y ausentes de otros:
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_arith.all; -- cambio respecto al ejemplo anterior
ENTITY sumar_incrm IS
PORT ( A,B : IN std_logic_vector(7 downto 0);
C,D :OUT std_logic_vector(7 downto 0));
END sumar_incrm;
BEGIN
C <= unsigned(A) + 1;
D <= unsigned(A) + unsigned(B);
END simple;
El ejemplo hace uso del “type casting” comentado en la página anterior, aprovechando
la definición de tipos UNSIGNED y SIGNED y las funciones definidas para ellos en el paquete
STD_LOGIC_ARITH. Al tener igual formato que STD_LOGIC_VECTOR, todos pueden tener los
mismos caracteres y es posible la conversión de un tipo a otro con el “type casting”.
VIII - 4
8 – Introducción a los modelos aritméticos
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL; -- sustituible por use ieee.numeric_std.all;
ENTITY add_sub_unsigned IS
port ( a, b : in unsigned(7 downto 0);
modo : in std_logic;
s : out unsigned(7 downto 0);
ovf, unf : out std_logic);
END add_sub_unsigned;
VIII- 5
8 – Introducción a los modelos aritméticos
A la vista de la tabla anterior, como un ejemplo de las posibilidades que ofrecen las
funciones de conversión de tipos residentes en los paquetes ARITH y UNSIGNED, el modelo
siguiente suma_byte.vhd muestra una descripción algorítmica sintetizable y relativamente
sencilla, porque incorpora varias funciones de conversión de tipos definidas en los paquetes
y “transparentes” en la descripción. De no haberlo hecho, aparte de la imposibilidad de usar
dos veces la función “+”, la descripción hubiera sido más complicada por conflictos entre
los tipos que se utilizan en ella:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL; -- los dos paquetes son necesarios
USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- los dos paquetes son necesarios
ENTITY suma_byte IS
PORT ( A,B : IN STD_LOGIC_VECTOR(7 downto 0);
CI : IN STD_LOGIC;
SUM : OUT STD_LOGIC_VECTOR(7 downto 0);
CO : OUT STD_LOGIC);
END suma_byte;
En los modelos UNSIGNED se pueden utilizar valores positivos dentro del rango permitido.
VIII - 6
8 – Introducción a los modelos aritméticos
Lo primero que cabe decir es que los tipos SIGNED y UNSIGNED son incompatibles y
que cualquier operación con ellos requiere la oportuna conversión. Por la misma razón, dada
la semejanza de los paquetes STD_LOGIC_SIGNED y STD_LOGIC_UNSIGNED, así como de
las funciones definidas en ellos, no deben llamarse ambos paquetes en un mismo modelo,
porque es probable que la sobrecarga de operadores cause llamadas ambiguas o mezclas de
tipos que darían errores de compilación.
Los tipos SIGNED están codificados en “complemento a 2”, que representa números
enteros de forma binaria en base a una suma de potencias de 2 y coeficientes binarios ,
lo que permite expresar un número X de n bits como:
X=− 2 + 2 + 2 + …+ 2 + 2
Esta expresión supone las siguientes propiedades de los números así codificados:
1- El número más negativo es −2 ; tiene = 1 y todos los demás coeficientes son 0’s.
2- El número más positivo es 2 − 1; tiene = 0 y todos los demás bits son 1’s.
3- El coeficiente, o bit, = 1 determina que el número es negativo, ya que la suma de
todas las potencias de 2 siguientes a 2 es menor que 2 .
4- Por razonamiento similar, el coeficiente = 0 determina que el número es positivo.
5- El rango de números así codificados es asimétrico respecto a 0, siendo uno mayor el de
los negativos, debido al coeficiente 0 para el 2 del “imposible” número más positivo.
Se presentan unas consideraciones básicas para el uso de tipos SIGNED, todas ellas en el
supuesto de una llamada previa al paquete IEEE.NUMERIC_STD.
VIII- 7
8 – Introducción a los modelos aritméticos
u <= s; -- por ser tipos diferentes no se pueden asignar uno a otro directamente
Otras declaraciones y conversiones para usar simultáneamente diversos tipos podrían ser:
n <= TO_INTEGER(a);
m <= n + TO_INTEGER(b);
z <= TO_SIGNED(m, z’LENGTH); -- referencia al atributo ’LENGTH de un array
z_signo <= z(z’LEFT); -- referencia al atributo LEFT de un array
sería posible hacerlo con función resize, tal como indican las asignaciones siguientes:
pero habría que llamar al paquete NUMERIC_STD, porque los otros paquetes aritméticos no
tienen la función resize, aunque ya se ha visto que la concatenación permite fácilmente
hacer las extensiones de forma independiente a los paquetes utilizados. También se puede
hacer, por supuesto, extendiendo el bit de signo con el operador de concatenación &.
VIII - 8
8 – Introducción a los modelos aritméticos
Comparación: en el bloque de funciones BOOLEAN del paquete SIGNED se puede ver que
están definidas en él todas las posibles combinaciones de los delimitadores /, =, <, >, para
realizar las comparaciones que se deseen entre valores de tipo SIGNED.
ENTITY contador_signed is
port(C, CLR, UP_DOWN : in std_logic;
Q : out SIGNED(3 downto 0)); -- cambio a tipo SIGNED
END contador_signed;
VIII- 9
8 – Introducción a los modelos aritméticos
Sumas y Restas: son operaciones binarias en las que se considera el signo indicado por los
bits más significativos de los operandos y los procedimientos para operar con sus valores
negativos y positivos. Los paquetes STD_LOGIC_ARITH Y STD_LOGIC_SIGNED permiten
descripciones sintetizables simples.
A +66 0 1 0 0 0 0 1 0 A +67 0 1 0 0 0 0 1 1
B +61 0 0 1 1 1 1 0 1 B +61 0 0 1 1 1 1 0 1
S +127 0 1 1 1 1 1 1 1 S +128 1 0 0 0 0 0 0 0
El desbordamiento positivo hace ‘1’ al bit de signo de la suma S, distinto a los bits de signo
de los sumandos A y B. En el caso de rango SIGNED (7 downto 0) puede expresarse:
Condición de desbordamiento positivo: NOT A(7) AND NOT B(7) AND S(7)
El desbordamiento negativo hace ‘0’ al bit de signo de la suma S, opuesto a los bits de signo
de los sumandos A y B. En el caso de rango SIGNED (7 downto 0) puede expresarse:
No hay otras condiciones de desbordamiento en sumas, porque si los sumandos tienen signo
diferente nunca puede haber desbordamiento por la limitación de representar sumandos con
valores que superen los máximos positivos o negativos “en complemento a 2”.
Si solo importa saber si hay desbordamiento, como aviso de sumas incorrectas, +128
o -129 en los ejemplos anteriores, la condición completa de desbordamiento es:
(NOT A(7) AND NOT B(7) AND S(7)) OR (A(7) AND B(7) AND NOT S(7))
VIII - 10
8 – Introducción a los modelos aritméticos
A -34 1 1 0 1 1 1 1 0 A -34 1 1 0 1 1 1 1 0
B +94 0 1 0 1 1 1 1 0 B +95 0 1 0 1 1 1 1 1
R -128 1 0 0 0 0 0 0 0 R -129 0 1 1 1 1 1 1 1
Condición de desbordamiento negativo: A(7) AND NOT B(7) AND NOT S(7)
Para los desbordamientos positivos en restas, ocurre lo contrario con los bits de signo:
A +58 0 0 1 1 1 0 1 0 A +58 0 0 1 1 1 0 1 0
B -69 1 0 1 1 1 0 1 1 B -70 1 0 1 1 1 0 1 0
R +127 0 1 1 1 1 1 1 1 R +128 1 0 0 0 0 0 0 0
Desbordamiento <= (A(7) AND NOT B(7) AND NOT S(7)) OR (NOT A(7) AND B(7) AND S(7));
De forma similar a lo indicado para las sumas, no hay otros casos de desbordamientos
en las operaciones de resta, ya que si los bits de signo de minuendo y sustraendo negado son
diferentes, sería imposible tener desbordamientos por la limitación de representar operandos
superiores a los límites de desbordamiento.
Dado que las condiciones de desbordamiento se expresan con referencia a los bits de
signo de operandos y resultados, podría utilizarse una constante genérica N que debería
declararse para el rango (N downto 0) utilizado en los modelos. De esa forma, las
condiciones de desbordamiento serían expresiones genéricas que se autodefinirían al dar
valor al genérico N.
VIII- 11
8 – Introducción a los modelos aritméticos
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY sumador_restador_SIGNED IS
port ( A, B : IN signed(7 downto 0);
modo : IN std_logic;
s : OUT signed(7 downto 0);
ovf : OUT std_logic;
unf : OUT std_logic);
END sumador_restador_SIGNED;
VIII - 12
8 – Introducción a los modelos aritméticos
Simulación post-síntesis del modelo sumador_restador_signed, con base SIGNED DECIMAL en señales A, B y S
(Herramienta Quartus II de ALTERA)
Nótense los valores incorrectos de la salida S en aquellos intervalos en los que ovf = ‘1’ o unf = ‘1’
VIII- 13
Apéndice A
Las razones para utilizar MAX+plus II como herramienta de simulación de modelos VHDL en
nuestro entorno son, en primer lugar, la sencillez de su utilización; en segundo lugar, la potencia más
que suficiente para soportar los diseños de un curso de iniciación al VHDL y, finalmente, los detalles de
retardos observables en la simulación post-síntesis y la información que suministran sus “reports”
sobre los recursos de FPGAs utilizados en la síntesis para comparación de alternativas, porque en
simples medidas de la eficiencia de un diseño, lo primero a observar puede ser el tamaño o volumen
de recursos utilizados, es decir, el coste, y también, la velocidad relacionada de alguna forma con los
retardos. No está de más que, desde el principio, el usuario de VHDL sea consciente de tales
consideraciones fundamentales en la ingeniería.
Con la tecnologías han evolucionado tanto las herramientas CAD como el VHDL; por ejemplo, el
nuevo “1076.6 IEEE Standard for VHDL Register Transfer Level (RTL) Synthesis” fue publicado en 2004.
No es extraño que, dentro de la dispersión de recursos VHDL soportados por las herramientas de
síntesis, falten en MAX+plus II algunos incorporados desde hace poco las herramientas modernas,
aunque con variable aceptación por diseñadores que rechazan algunas inferencias de síntesis de las
nuevas sentencias o construcciones soportadas. En tales casos, siguiendo la recomendación de
ALTERA, es posible simular con Quartus II que, en honor a los valores de MAX+plus II, mantuvo hasta
su versión 9.1 una presentación en “modo MAX+plus II”. La versión Quartus II 9.1, con Service pack 2,
se puede descargar de forma gratuita de la web de ALTERA y su instalación no requiere licencia,
aunque precise más de 3GB en el HD. MAX+plus II solo pide 500 MB, lo que también es una razón
para elegirlo ante otras opciones de docencia del VHDL.
MARCAR OPCIONES:
Dispositivos: FLEX 8000, MAX3000, 7000 y 9000
TUTORIAL MAX+ plus II, MAX+ plus HELP
7º - LICENSE SET UP
a - Preparar un directorio, p.ej. C:\flexlm, donde se instalará el fichero de licencia “license.dat”
b – Abrir el menú OPTIONS de la pantalla inicial de MAX+plus II y elegir “license set up”
Aparecerán las opciones que están como “unlicensed features”
c – Seleccionar el fichero de licencia “license.dat” que se había instalado, p.ej, en C:\flexlm
Todas las opciones se moverán a la ventana “licensed features”
En las páginas siguientes, vea un breve Tutorial sobre Síntesis y Simulación con MAX + plus II
Si el proceso de análisis y síntesis es correcto aparecerá un mensaje informando de ello. “Aceptar” para continuar.
Como resultado, se generan una serie de ficheros en el directorio “work” donde, supuestamente, estaba el fichero xxx.vhd compilado.
Todos los ficheros tienen el mismo nombre que el .vhd, con extensiones codificadas que indican la información que contiene cada fichero.
El fichero xxx.rpt, por ejemplo, es un report o informe de cómo se ha sintetizado y encajado el diseño en un dispositivo EPM7032LC44-6.
El fichero xxx.snf , Simulator Netlist File, permitirá obtener datos para ver la simulación de las señales del diseño implementado en la FPGA.
Los ficheros xxx.pof y xxx.sof son ficheros para programar o configurar dispositivos directamente desde el entorno MAX+plus II
Para simular es preciso crear un fichero de estímulos, a partir del fichero xxx.snf, haciendo lo siguiente:
2º Pedir en el menú Node la opción “Enter nodes from SNF” y en la ventana emergente pedir el Tipo de señales de interés
3º En la ventana “Enter Nodes from SNF” que aparece, picar en List para que se muestren señales a visualizar en el “Waveform editor”
4º Seleccionar las señales de interés y pasarlas a la ventana derecha, picando en el botón de transferencia =>
Después de hacer la selección y dar OK, las señales a simular aparecen en el “Waveform editor”.
Síntesis y simulación VHDL con MAX+plus II 5/7
5º En el menú “File”, picar en “Save as”. Aceptar el nombre del fichero propuesto: xxx.scf (Simulator Chanel File)
Para realizar la simulación se deben definir los estímulos de todas las señales de entrada y los detalles de la simulación, por ejemplo:
6º Para simular, picar el botón del simulador y esperar la finalización del proceso, leer los mensajes del simulador y ver los resultados.
Manejando botones de zoom, deslizadores de pantalla, moviendo las transiciones de estímulos a los puntos que desee o colocando el cursor en las
zonas de interés, etc. se podrán analizar en detalle las respuestas del circuito, modificar los estímulos para repetir la simulación y, si procede, cambiar el
diseño para que las respuestas sean las esperadas, porque NO OLVIDE QUE…
Sintetizar no es sinónimo de haber diseñado/descrito correctamente: puede indicar solo que la sintaxis VHDL era correcta
Simular y ver formas de onda no supone que el funcionamiento sea el esperado o deseado: solo representa un comportamiento
HAY QUE ANALIZAR LAS RESPUESTAS A LOS ESTIMULOS Y, QUIZÁS, PENSAR EN POSIBLES CAMBIOS O MEJORAS
Y si todo le parece correcto, archive el fichero que ha obtenido para editarlo posteriormente. Quedará guardado en “work” y podrá abrirlo
directamente, si lo llama desde “Abrir fichero”.
Desde: https://www.altera.com/download/software/quartus-ii-we/9.1
17 – En la ventana “Node finder” hay que seleccionar con “Filter” el tipo de señales a poner en la ventana “Waveforms”
Por ejemplo, “inputs”, y después de esa selección, picar en botón “List” para que se muestre la lista de “inputs”
20 – Abrir el menú “File” y hacer “Save as…” para dar nombre al fichero de formas de onda “xxx.vwf”
27 – Seleccionando una señal en su número identificador, en la ventana “Node properties” se podrá elegir la base de presentación
de la señal: binary, hex, Signed decimal, etc.
modelos_TRES
decoder_3a8_doble.vhd *
d_flip_flop.vhd *
generador_serie.vhd *
inv_triestado.vhd *
mux_cuatro_a_1.vhd *
process_selectivo.vhd *
sap_convertidor.vhd *
selector_doble.vhd *
modelos_CUATRO
case_decoder_3a8.vhd *
generador.vhd *
if_decoder.vhd *
if_multiplexer.vhd *
inf_and.vhd *
inf_and_latch.vhd *
inf_fpfp.vhd *
inf_fpfp_asinc.vhd *
inf_fpfp_sinc.vhd *
inf_latch_clear.vhd *
others_shift_register.vhd *
serial_shift_register.vhd *
modelos_CINCO
binario_a_entero.vhd *
decrm_func.vhd *
entero_a_binario.vhd *
func_incremento.vhd *
incrm_func.vhd *
triestados.vhd *
triestados_flujdats.vhd *
Apéndice C 1/2
modelos_SEIS
adder_4b.vhd *
bist_adder.vhd *
compbit.vhd *
compbit_dos.vhd *
decoder_3_a_8.vhd *
decoder_bist.vhd *
decoder_bist_plus.vhd *
inver.vhd *
lfsr.vhd *
lfsr_3.vhd *
lfsr_4.vhd *
lfsr_8.vhd *
lfsr_9.vhd *
lfsr_9_mvld.vhd *
lfsr_gen.vhd *
nand_2.vhd *
nand_3.vhd *
puertas.vhd *
puertas_plus.vhd *
xrf.vhd *
xrf_IEEE.vhd *
modelos_SIETE
compbit_funciones.vhd *
mealyfsm.vhd *
mealyfsm_trs.vhd *
mealyfsm_uno.vhd *
moorefsm.vhd *
moorefsm_trs.vhd *
moorefsm_uno.vhd *
mux_4a1_conc.vhd *
mux_4a1_cond.vhd *
mux_4a1_sel.vhd *
shift_reg_mix.vhd *
sumabin.vhd *
up_dwn_counter.vhd *
modelos_OCHO
add_sub_unsigned.vhd *
comparador_unsigned.vhd *
contador_signed.vhd *
contador_stdlogic.vhd *
contador_unsigned.vhd *
contador_unsigned_typecasted.vhd *
sumador_restador_signed.vhd * *
sumar_incrm.vhd *
suma_byte.vhd *
suma_incr.vhd *
2/2 Apéndice C
Bibliografía
ALTERA Corp. "MAX+PLUS II Getting started", Version 6.0, 2000
Ashenden, P. J., "The Designer's Guide to VHDL” , 3rd Edition, Elsevier, 2008
Ashenden, P. J., “Digital Design: An Embedded Systems Approach Using VHDL”, Elsevier, 2008
Chu, Pong P., “FPGA prototyping by VHDL examples”, Wiley Interscience, 2008
Chu, Pong P., “RTL hardware design using VHDL”, Wiley Interscience, 2006
Navabi, Z., “VHDL Analysis and Modeling of Digital Systems”, McGraw-Hill, 1993
Rushton, A., “VHDL for Logic Synthesis”, 3rd Edition, Wiley, 2011