Академический Документы
Профессиональный Документы
Культура Документы
Alfonso Urquía
Carla Martín Villalba
Departamento de Informática y Automática, UNED
Juan del Rosal 16, 28040 Madrid, España
{aurquia,carla}@dia.uned.es
http://www.euclides.dia.uned.es
Índice
1 Fundamentos 1
1.1. Lenguajes para la descripción de hardware . . . . . . . . . . . . . . 1
1.2. Ciclo de diseño de los circuitos digitales . . . . . . . . . . . . . . . 4
1.3. Propiedades de los circuitos digitales . . . . . . . . . . . . . . . . . 5
1.4. Simulación de eventos discretos . . . . . . . . . . . . . . . . . . . . 8
1.5. Test de los circuitos . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.6. Dos simuladores de VHDL’93: VeriBest y ModelSim . . . . . . . . 16
APÉNDICES 133
A VeriBest VB99.0 133
A.1. Instalación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
A.2. Circuito digital ejemplo: buffer triestado . . . . . . . . . . . . . . . 134
A.2.1. Modelo VHDL del buffer triestado . . . . . . . . . . . . . . 134
A.2.2. Banco de pruebas . . . . . . . . . . . . . . . . . . . . . . . 135
A.3. Edición y compilación de un modelo . . . . . . . . . . . . . . . . . 136
A.3.1. Arranque del simulador VeriBest VHDL . . . . . . . . . . . 136
A.3.2. Creación de un espacio de trabajo . . . . . . . . . . . . . . 136
A.3.3. Edición de un fichero . . . . . . . . . . . . . . . . . . . . . . 137
A.3.4. Añadir un fichero al espacio de trabajo . . . . . . . . . . . . 137
A.3.5. Compilación de un fichero . . . . . . . . . . . . . . . . . . . 138
A.3.6. Banco de pruebas . . . . . . . . . . . . . . . . . . . . . . . 140
A.4. Simulación y visualización de los resultados . . . . . . . . . . . . . 140
A.4.1. Establecer las condiciones de la simulación . . . . . . . . . 140
A.4.2. Activación del simulador . . . . . . . . . . . . . . . . . . . . 141
A.4.3. Simulación y visualización de resultados . . . . . . . . . . . 142
A.5. Depurado usando el debugger . . . . . . . . . . . . . . . . . . . . . 144
Bibliografía 169
Fundamentos
1
! " ! #$
Ejecución concurrente
Los módulos lógicos se ejecutan concurrentemente. Cuando cambia el valor de
una señal de entrada a varios módulos, todos estos módulos deben ser ejecutados
concurrentemente. Ası́ pues, los HDL deben ser capaces de describir de manera
precisa este comportamiento concurrente y el simulador debe ser capaz de si-
mularlo. La metodologı́a aplicada para ello por el simulador es la simulación de
eventos discretos.
Diseños marginales
Los retardos de los dispositivos dependen de la condiciones de fabricación del chip.
En general, existen variaciones en el valor de los retardos de los chips fabricados
Capı́tulo 1 Fundamentos 7
3. Todos los antiguos eventos sobre A cuya ejecución esté planificada que suce-
da en un instante de tiempo comprendido en el intervalo (tactual , tactual + ret)
y asignen a A un valor diferente de Anew se borran.
Caso práctico
Supongamos que se ha descrito el circuito mostrado en la Figura 1.3 usando un
HDL. La puerta NAND tiene un retardo de 1 ns y la puerta OR de 2 ns. Las
dos entradas, x1 y x2 , tienen el valor ‘1’ en el instante 0 ns. Las dos siguientes
asignaciones describen, respectivamente, el comportamiento de la salida de la
puerta NAND (s) y de la puerta OR (y) del circuito digital:
Señal Valor
Calendario de eventos
x1 ‘1’
E0 1 ns s ← 0
x2 ‘1’
E1 2 ns y ← 1
s ‘U’ (valor indefinido)
E2 5 ns x2 ← 0
y ‘U’ (valor indefinido)
Señal Valor
Calendario de eventos
x1 ’1’
E1 2 ns y ← 1
x2 ’1’
E3 3 ns y ← 1
s ’0’
E2 5 ns x2 ← 0
y ’U’ (valor indefinido)
Capı́tulo 1 Fundamentos 11
Señal Valor
x1 ’1’ Calendario de eventos
x2 ’1’ E3 3 ns y ← 1
s ’0’ E2 5 ns x2 ← 0
y ’1’
Señal Valor
x1 ’1’
Calendario de eventos
x2 ’1’
E2 5 ns x2 ← 0
s ’0’
y ’1’
Señal Valor
x1 ’1’ Calendario de eventos
x2 ’0’ E4 6 ns s ← 1
s ’0’ E5 7 ns y ← 0
y ’1’
Señal Valor
x1 ’1’
Calendario de eventos
x2 ’0’
E6 8 ns y ← 1
s ’1’
y ’1’
12 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
Test en manufactura
Un objetivo fundamental del test en manufactura es detectar problemas en el
proceso de fabricación. Las causas de mal funcionamiento de los chips más común-
mente observadas en la práctica son:
2. El segundo método consiste el usar en el diseño scan flip-flops, que son flip-
flops cuyo valor puede ser cargado desde las entradas al circuito (mientras
se realiza el test), o bien pueden ser usados del mismo modo que un flip-flop
sin modificar (durante el modo normal de funcionamiento del circuito). Los
scan flip-flops pueden construirse insertando multiplexores en la entrada D
de los flip-flops.
Test funcional
El test funcional se emplea en todas las etapas del proceso de diseño del circuito.
Su objetivo es verificar que el circuito realiza todas las operaciones como debiera.
En los diseños grandes, que normalmente se diseñan de manera jerárquica,
todos los subcircuitos de bajo nivel deben ser comprobados funcionalmente, usan-
do programas de test especı́ficos para cada uno, antes de ser incluidos en los
subcircuitos de más alto nivel.
Aunque todos los subcircuitos sean comprobados por separado, el subcircuito
obtenido de la composición de todos ellos debe también ser comprobado, usándose
para ello su propio programa de test.
A continuación, una vez se implementa el circuito usando alguna plataforma
hardware (ASIC, FPGA, etc.), debe volver a ser testeado de nuevo. Si es posible,
debe emplearse para testear el prototipo hardware el mismo conjunto de tests que
se ha usado en la fase de simulación. Habitualmente, el primer prototipo hardware
contiene errores. La comparación de los resultados del test, con los resultados de
las simulaciones para esos mismos tests, puede ayudar a identificar errores de
diseño y de fabricación.
Banco de pruebas
Muchas herramientas de simulación incluyen menús que permiten asignar valores
a las entradas del circuito. Sin embargo, el uso de este tipo de interfaces gráficas
de usuario puede resultar lento y el programa de test desarrollado puede no ser
exportable a otras herramientas de simulación.
16 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
UUT
? < 6: C D 8 :5 > 67E =
; <= < 8 >? :8 ? < ? < @: A 8 < A4 @9>? : A
@: A B < 69: 8 < A ? < 9 < A9
? < @ 9 < A9
Student Edition. Cualquiera de los dos puede emplearse para la simulación de los
modelos planteados en este texto.
El simulador VeriBest VHDL fue desarrollado por la compañı́a VeriBest Inc.
Cuando esta compañı́a pasó a formar parte de la corporación Mentor Graphics,
dejó de darse soporte al simulador VeriBest VHDL, siendo éste sustituido por el
simulador ModelSim.
La única ventaja de VeriBest es que funciona para casi todas las versiones de
Windows (Windows NT 4.0, Windows 95, Windows 98, etc.). Por tratarse de una
herramienta software del año 1998, resulta adecuada para su uso en ordenadores
con limitadas prestaciones. Si éste no es el caso, es preferible emplear ModelSim
en lugar de VeriBest.
Aparte de estos dos simuladores de VHDL’93, en Internet pueden encontrarse
otros. Asimismo, existen versiones gratuitas de herramientas orientadas no sólo
a la simulación, sino también a la sı́ntesis, entre las que cabe destacar Quartus II
Web Edition, que puede descargarse gratuitamente del sitio web de la compañı́a
Altera Corporation.
Se sugiere al alumno que escoja en este punto qué entorno de simulación va
a emplear. Si decide usar VeriBest, la guı́a de instalación y uso del Apéndice A
puede serle útil. Por el contrario, si decide usar ModelSim (lo cual recomendamos),
encontrará la correspondiente guı́a en el Apéndice B.
Conceptos básicos de VHDL
2
synthesis interoperability subset (estándar IEEE 1076.6), que contiene los tipos
de datos, operadores y otras capacidades de VHDL que deberı́an ser usados para
crear código VHDL sintetizable. Esto es, código a partir del cual las herramientas
de CAD puedan generar automáticamente circuitos hardware que funcionen.
Siguiendo estas reglas y centrándonos en prácticas “simples” para la codifi-
cación de alto nivel, en este capı́tulo se introducen los conceptos básicos para el
modelado y la simulación empleando VHDL.
2.2 Entity
La entity define la interfaz externa de la entidad de diseño. Incluye:
x0 x0
x0 y0 y0 y0
x1 x1
En VHDL, las palabras reservadas (por ejemplo, entity, is, port, in,
out, end) y los nombres definidos por el usuario (por ejemplo, not1, xor2,
and2, x0, x1, y) pueden escribirse indistintamente en mayúsculas o en minúsculas,
puesto que en VHDL no se diferencia entre los caracteres en mayúscula y en
minúscula. Por ejemplo, es equivalente escribir entity, ENTITY y EnTiTy, ası́
como también es equivalente escribir not1 y NoT1.
Los nombres definidos por el usuario deben comenzar por una letra, seguida
opcionalmente por cualquier secuencia de letras, números y caracteres guión bajo,
con la limitación de que ni pueden aparecer dos guiones bajos seguidos, ni el guión
bajo puede ser el último caracter del nombre.
2.3 Architecture
La architecture describe el comportamiento o la estructura de la entidad de
diseño. Esta definición puede emplear:
x0 x0
x0 y0 y0 y0
x1 x1
– O bien incluirse sentencias wait dentro del bloque process (esperar hasta
que ocurra cierto evento, o hasta que transcurra cierta cantidad de tiempo
simulado).
--------------------------------------------------
-- Biestable D con reset ası́ncrono activado en LOW
library IEEE;
use IEEE.std_logic_1164.all;
24 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
use IEEE.numeric_std.all;
X Y Z [ \]
ST
SU V
WT
^_ `_
Como puede observarse en la Figura 2.3b, este circuito multiplexor está com-
puesto por un inversor (inv_1), dos puertas AND de dos entradas (AND2_1,
AND2_2) y una puerta OR de dos entradas (OR2_1). Las señales n1, n2 y n3
tienen por objeto describir la conexión entre los componentes.
A continuación, se muestra la descripción de la estructura del circuito en
lenguaje VHDL. Obsérvese que al instanciar cada componente, se indica qué señal
debe asociarse a cada uno de sus puertos. Una misma señal asociada a diferentes
puertos indica el establecimiento de una conexión entre esos puertos.
----------------------------------------------
-- MUX 2:1 de 1 bit
library IEEE;
use IEEE.std_logic_1164.all;
entity Mux2_1bit is
port (
d : out std_logic;
i0, i1 : in std_logic;
s0 : in std_logic );
end entity Mux2_1bit;
26 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
component not1 is
port ( y0 : out std_logic;
x0 : in std_logic );
end component not1;
component or2 is
port ( y0 : out std_logic;
x0, x1 : in std_logic );
end component or2;
component and2 is
port ( y0 : out std_logic;
x0, x1 : in std_logic );
end component and2;
----------------------------------------------
-- MUX 2:1 de 4 bit
library IEEE;
use IEEE.std_logic_1164.all;
entity Mux2_4bit is
port ( d0, d1, d2, d3 : out std_logic;
a0, a1, a2, a3 : in std_logic;
b0, b1, b2, b3 : in std_logic;
s0 : in std_logic );
end entity Mux2_4bit;
abcdef
a3 i0 d3
b3 d
i1
s0
abcdef
a2 i0 d2
b2 d
i1
s0
abcdef
a1 i0 d1
b1 d
i1
s0
abcdef
a0 i0 d0
b0 d
i1
s0
s0
Figura 2.4: Multiplexor de 2 señales de 4 bit diseñado mediante la conexión
de 4 multiplexores de 2 señales de 1 bit.
component Mux2_1bit is
port ( d : out std_logic;
i0, i1 : in std_logic;
s0 : in std_logic );
end component Mux2_1bit;
begin
Mux2_0 : Mux2_1bit port map
( d => d0, i0 => a0, i1 => b0 , s0 => s0 );
Mux2_1 : Mux2_1bit port map
( d => d1, i0 => a1, i1 => b1 , s0 => s0 );
Mux2_2 : Mux2_1bit port map
( d => d2, i0 => a2, i1 => b2 , s0 => s0 );
Mux2_3 : Mux2_1bit port map
( d => d3, i0 => a3, i1 => b3 , s0 => s0 );
end architecture Mux2_4bit;
----------------------------------------------
28 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
2.4 Configuration
Se emplea una pareja entity-architecture para describir en VHDL las enti-
dades de diseño (es decir, circuitos y subcircuitos) que pueden ser compilados
separadamente.
El hecho de que se definan separadamente la interfaz (entity) y la arquitectura
(architecture) facilita la definición de varias arquitecturas para una misma
entidad de diseño (con una única interfaz). Por ejemplo, pueden definirse varias
arquitecturas de una misma entidad de diseño, correspondientes a diferentes
versiones del circuito: velocidad baja, media y alta.
En este caso, cuando se emplee esa entidad de diseño debe indicarse explı́-
citamente qué arquitectura hay que emplear. Esto puede hacerse mediante la
definición de una configuración (configuration).
– Emplear una variable cuando vaya a usarse sólo dentro de un bloque pro-
cess.
– Emplear una señal para datos a los que deba asignarse valor fuera del bloque
process, o para datos que necesitan ser transferidos desde un puerto de
entrada o a un puerto de salida. Esto último es equivalente a decir que los
port sólo pueden ser señales.
Para asignar valor a una variable o constante se emplea :=, mientras que
se emplea <= para asignar valor a una señal. Sólo puede asignarse valor a las
variables en los bloques process. Puede asignarse valor a las señales mediante
asignaciones concurrentes o en los bloques process.
La diferencia fundamental entre una asignación a una señal y una asignación a
una variable, ambas realizadas dentro de un bloque process, es que la asignación
a la señal se ejecuta concurrentemente con la siguiente sentencia del bloque
process, mientras que la asignación a la variable se ejecuta antes que la siguiente
sentencia del bloque process.
Dos ejemplos tı́picos de uso de las variables son los siguientes:
1. Cuando hace falta realizar una serie de cálculos para poder asignarle valor
a una señal, se definen nuevas variables, se hacen los cálculos usando esas
variables, y finalmente se asigna el resultado de los cálculos a la señal.
2. Puesto que una señal de salida (es decir, un puerto out) no puede ser leı́da,
puede ser necesario definir una variable, leer y escribir sobre esa variable
tantas veces como sea necesario, y finalmente asignar esa variable a la señal
de salida.
bit y std_logic
Una variable, señal o constante del tipo bit sólo puede tomar dos valores: 0 y
1 (obsérvese que los valores se escriben sin comillas). Ası́ pues, este tipo es útil
para realizar modelos sencillos de sistemas digitales.
Las variables, señales o constantes del tipo std logic pueden tomar nueve
valores. Además de los valores ’0’ y ’1’ (obsérvese que en este caso los valores se
escriben entre comillas simples), pueden tomar otros valores usados para modelar
valores intermedios o desconocidos de la señal. De estos valores, los más comunes
son los tres siguientes:
Los restantes posibles valores de una señal del tipo std logic son: ’W’ (des-
conocida débil), ’L’ (cero débil), ’H’ (uno débil) y ’-’ (don’t care).
Por lo general, en los modelos mostrados en este texto se empleará el tipo
std logic para representar las señales binarias.
bit_vector y std_logic_vector
Los conjuntos de señales pueden agruparse formando lo que se denominan buses.
Análogamente, los conjuntos de variables pueden agruparse en vectores. Los
buses y vectores pueden modelarse en VHDL mediante los tipos bit vector (un
Capı́tulo 2 Conceptos básicos de VHDL 31
conjunto de señales o variables de tipo bit) y std logic vector (un conjunto de
señales o variables de tipo std logic).
Una desventaja de los tipos de datos bit vector y std logic vector es que
no pueden realizarse operaciones aritméticas sobre este tipo de señales. Esto
es razonable, ya que en los circuitos digitales no pueden realizarse operaciones
aritméticas directamente sobre los buses de señales, sólo pueden realizarse opera-
ciones lógicas. La forma de representar los valores literales de estos tipos de datos
se muestran en la Tabla 2.1.
unsigned y signed
En aquellos casos en que resulte útil modelar operaciones aritméticas realizadas
sobre buses, pueden usarse los tipos de datos unsigned y signed. Ambos tipos
de datos están definidos usando como tipo de datos base std logic, con lo cual
son vectores de valores std logic.
Ası́ pues, la diferencia entre el tipo de datos std logic vector y los tipos
de datos unsigned y signed es que para el tipo de datos std logic vector
32 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
están definidas las operaciones lógicas, pero no las aritméticas, mientras que para
los tipos de datos unsigned y signed están definidas las operaciones lógicas y
aritméticas.
Puede cambiarse el tamaño (es decir, el número de bits) de los datos unsigned
y signed mediante la función resize. El parámetro size representa el nuevo
número de bits del dato.
real e integer
También existen tipos de datos estándar que no se corresponden necesariamente
con señales en los circuitos fı́sicos. Resultan útiles para realizar descripciones del
comportamiento de los circuitos y para modelar los tests. Los tipos de datos
integer (32 bits) y real (64 bits) se definen de manera similar a como se hace en
los lenguajes de programación. Lo mismo sucede con las operaciones aritméticas
para este tipo de datos. En la Tabla 2.1 se muestra la forma de representar los
valores literales de los tipos integer y real.
time y string
Los tipos de datos time y string son útiles, en el proceso de depuración (debug-
ging) del modelo, para mostrar mensajes que son generados durante la simulación.
Las variables del tipo time son usadas para representar el tiempo simulado. La
unidad por defecto de este tipo de variables es el fs (femtosegundo = 10−15 s). Los
valores del tiempo pueden representarse en otras unidades escribiendo la unidad
de tiempo tras el valor del tiempo, el cual es escrito como una constante entera
o real. Las unidades de tiempo disponibles son: fs, ps, ns, us (microsegundos),
ms, sec, min y hr (horas). Además, existe una función estándar (llamada now,
sin argumentos), que devuelve el valor actual del tiempo simulado.
Para mostrar mensajes de texto y valores de datos en la pantalla, es preciso
convertir todos los argumentos de la sentencia report (la sentencia “print” de
VHDL) a tipos de dato string. Como en la mayorı́a de los lenguajes de progra-
mación, un string se define simplemente como un array de caracteres.
Tipos enumerados
Además de los tipos estándar de datos descritos anteriormente, es posible definir
tipos enumerados de datos.
Por ejemplo, supongamos una señal llamada opcode, que representa el código
de operación de un circuito. Suponiendo que sólo puede tomar cuatro valores
Capı́tulo 2 Conceptos básicos de VHDL 33
(suma, resta, salto y parar), entonces es posible definir un nuevo tipo (type),
llamado, por ejemplo, opcode_type, de la manera siguiente:
Obsérvese en la Tabla 2.3 que en la conversión del tipo integer a los tipos
unsigned o signed, es preciso especificar el número de bits (size) de la señal
del tipo unsigned o signed resultante.
34 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
2.5.2 Atributos
Puede considerarse que los atributos son propiedades de los tipos de datos. Existen
conjuntos estándar de atributos que son soportados para diferentes propósitos.
No todos los atributos son soportados para sı́ntesis. En la Tabla 2.4 se muestra
un conjunto de atributos estándar que son soportados por la mayorı́a de las
herramientas de sı́ntesis.
unsigned’("00")
establece que el string "00" se usa como un vector del tipo unsigned, en lugar
de como bit vector o std logic vector.
Hay atributos para tipos escalares de datos, para arrays de una dimensión
(vectores), para arrays de n dimensiones, y para señales. En la Tabla 2.4 se ha
empleado la terminologı́a siguiente:
<tipo>’image(se~
nal)
que devuelve un string con el valor del tipo <tipo>de la señal <señal>. Este
atributo se usa para convertir el valor de una señal a un string, de modo que
pueda ser mostrado en la consola (con el fin de depurar o monitorizar).
La lista completa de atributos soportados por VHDL es bastante extensa. No
obstante, sólo son necesarios unos pocos para programar la mayor parte de los
tipos de circuitos digitales y bancos de pruebas.
Por ejemplo, en VHDL’87 se emplea
para modelar el flanco de subida de la señal de reloj. Sin embargo, puesto que
este predicado es también cierto cuando la señal clk cambia del valor U (no
inicializado) o del valor X (desconocido forzado) a 1, en VHDL’93 se usa
rising_edge(clk)
<tipo>’range
el cual se emplea para especificar (por ejemplo, en un bucle for) el rango completo
de ı́ndices de un determinado tipo de dato.
2.5.3 Operadores
Los operadores de VHDL’93 están resumidos en la Tabla 2.5.
En la Tabla 2.6 se muestra el tipo de dato obtenido al realizar operaciones
aritméticas entre operandos del tipo unsigned, signed, e integer.
Tabla 2.5: Operadores de VHDL’93
2.6 Librerías
En VHDL, una librerı́a de diseño contiene la definición de un conjunto de tipos
de datos, ası́ como la definición de los operadores y funciones que pueden aplicarse
sobre estos tipos de datos. Existe un buen número de librerı́as de diseño estándar
y de librerı́as especı́ficas, que son proporcionadas junto con las herramientas de
simulación.
A excepción de los tipos bit y bit vector, todos los demás tipos precisan de
la inclusión de alguna librerı́a de diseño. Por ejemplo, es necesario usar la librerı́a
de IEEE (que es proporcionada en todos los simuladores) para poder usar los
tipos de datos std logic, std logic vector, unsigned y signed.
VHDL permite organizar las librerı́as, estructurando su contenido en sub-
librerı́as denominadas packages. Un beneficio añadido de ello es que incluir
únicamente los tipos de datos necesarios para el diseño reduce el tamaño del
código y simplifica la simulación del programa en VHDL.
Por este motivo, además de especificar qué librerı́as deben ser incluidas,
conviene que el diseñador indique qué paquetes en concreto de la librerı́a son
usados en la definición del circuito. Si no se especifica el paquete, o si un mismo
objeto está definido en varios paquetes, es preciso referirse a él usando la notación
punto:
librerı́a.paquete.objeto
Entre los paquetes más comúnmente usados, cabe mencionar los siguientes, per-
tenecientes a la librerı́a IEEE:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
dentro de un bloque process, hace que la ejecución del bloque se detenga durante
10 nanosegundos.
Pueden usarse otras formas de la sentencia wait. Por ejemplo, la sentencia:
wait;
process (clk) is
begin
if rising_edge(clk) then
b <= a;
Capı́tulo 2 Conceptos básicos de VHDL 41
c <= b;
...
Puesto que b y c son señales, existe un retardo delta antes de que se produzca
la asignación del nuevo valor a b. Antes de que transcurra este retardo, se calcula
el nuevo valor de la variable c, usándose para ello el valor “antiguo” de b. En este
ejemplo, la señal c adquiere el valor que tenı́a la señal b en el anterior ciclo de
reloj, dado que el proceso es activado únicamente en los flancos de subida de la
señal de reloj.
La discusión anterior acerca del retardo delta no aplica a las asignaciones a
variables. De hecho, ni siquiera es posible asociar un retardo a una asignación
a una variable (no pueden usarse sentencias de la forma a := b after c ns;).
Las asignaciones a variables ocurren inmediatamente, sin retardos delta, lo cual es
razonable considerando que las variables en VHDL están ideadas para ser usadas
como las variables de los programas de los lenguajes de programación.
Ası́ pues, dada una cadena de asignaciones a variables contenida dentro de
un bloque process, estas asignaciones a variables se realizan de manera estric-
tamente secuencial (de la misma forma que se ejecutan las sentencias en C o en
Fortran).
-------------------------------------
-- Puerta NAND con retardo inercial
library IEEE;
use IEEE.std_logic_1164.all;
-------------------------------------------
-- Banco de pruebas de diferentes retardos
library IEEE;
use IEEE.std_logic_1164.all;
entity retardo_bp is
end entity retardo_bp;
2.8 Assert
La sentencia assert se usa para hacer comprobaciones de condiciones lógicas que,
dado el valor esperado en ese punto del estado del programa, deberı́an valer true.
Se emplea frecuentemente para depurar el código. Su sintaxis es:
note No es un error.
warning Aviso.
error Error.
failure Error severo que hace que termine la simulación.
44 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
– Los argumentos de la función deben ser de tipo in, con lo cual no es necesario
especificar su dirección.
Sin embargo, este tipo de descripción da lugar a la sı́ntesis de los tipos estándar
de circuitos aritméticos. Dependiendo de la opción seleccionada en la sı́ntesis, las
unidades aritméticas sintetizadas pueden ser circuitos lentos que usan un número
pequeño de puertas lógicas (si se escoge la opción “optimizar el área”) o bien
circuitos rápidos que utilizan gran número de puertas lógicas (se se escoge la
opción “optimizar la velocidad”).
Para crear tipos especı́ficos de unidades aritméticas, tales como tipos especia-
les de sumadores o multiplicadores rápidos, puede ser necesario describirlos o bien
indicando su estructura, o bien mediante una descripción de su comportamiento
a más bajo nivel, tal como se explica a continuación.
50 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
1. Todas las entradas del circuito deben estar incluidas en la lista de señales
a las que es sensible el bloque process.
F = a and b or not c
G = a and b or not b and c
F = ( a and b ) or not c
G = ( a and b ) or ( not b and c )
--------------------------------------
-- Funciones lógicas:
-- F = ab + c’
-- G = ab + b’c
Capı́tulo 3 Casos prácticos de diseño de circuitos combinacionales 51
La interfaz externa del circuito que implementa las funciones lógicas es des-
crita en la entity llamada funcLog_F_G. En ella se declaran los dos puertos de
salida (F, G) seguidos de los tres puertos de entrada (a, b, c). Todos los puertos
son del tipo std logic ya que representan señales transmitidas por el cableado
de los circuitos.
La definición de la architecture comienza especificando el nombre de la
entity. En este caso, se ha dado el mismo nombre a la entity y a la architecture.
En general se les puede dar nombres diferentes.
En el cuerpo de la architecture (es decir, a continuación de la palabra
reservada begin) se describe cómo se calculan los puertos de salida a partir de
los puertos de entrada.
--------------------------------------
-- Banco de pruebas
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity bp_funcLog_F_G is
end entity bp_funcLog_F_G;
begin
-- Instanciar y conectar UUT
uut : component funcLog_F_G port map
( F => y0, G => y1,
a => x0, b => x1, c => x2 );
gen_vec_test : process
Capı́tulo 3 Casos prácticos de diseño de circuitos combinacionales 53
gen_vec_test : process
variable ...
begin
...
end process gen_vec_test;
donde las variables se declaran antes de la palabra reservada begin, y las senten-
cias a ejecutar secuencialmente se escriben a continuación de la palabra begin.
Una variable (variable) es conceptualmente diferente a una señal (signal),
puesto que la variable puede no corresponder con una señal fı́sica. La variable
simplemente se usa como ayuda en la descripción de la operación del circuito. La
asignación a una variable se representa mediante :=, mientras que la asignación
a una señal se representa mediante <=.
En el código del banco de pruebas, la variable test_in se usa para almacenar
en un mismo vector de tres bits las entradas al UUT, de modo que este vector
pueda ser incrementado (con el fin de generar todas las posibles combinaciones de
vectores de test) empleando un bucle for. Observa que la variable test_in se ha
declarado de tipo unsigned ya que se emplea para realizar operaciones aritméticas.
La longitud del vector se especifica por el rango (2 downto 0). El primer número
del rango (2) indica el ı́ndice del bit más significativo del vector, y el segundo
número del rango (0) indica el ı́ndice del bit menos significativo del vector.
La sentencia for en VHDL tiene el formato siguiente:
donde <variable> es una nueva variable temporal, con un rango entero (<rango>),
que no necesita ser definida previamente.
54 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
para esperar hasta que el UUT pueda producir las salidas correspondientes a las
entradas aplicadas. En este caso, podrı́a haberse escogido cualquier otro tiempo
de espera, ya que en el modelo del UUT no se especificó ningún retardo.
La segunda sentencia wait, que está situada al final de código, no tiene
ninguna indicación acerca del tiempo que hay que esperar. Este tipo de sentencia
wait se emplea para detener el proceso, ya que “espera para siempre”.
Como resultado de la simulación del banco de pruebas, se obtienen las formas
de onda mostradas en la Figura 3.1.
En la Figura 3.2 se muestra un multiplexor de 4 entradas (i3, i2, i1, i0), dos
entradas de selección (s1, s0) y una salida (d). En esta sección se describen
diferentes maneras de modelar el multiplexor, ası́ como bancos de pruebas que
permite simular tests sobre los modelos del circuito.
ghi jkl
i0
i1
d
i2
i3 s0 s1
--------------------------------------
-- MUX 4x1
library IEEE; use IEEE.std_logic_1164.all;
Obsérvese que el bloque process es sensible a las señales i3, i2, i1, i0, s1,
s0. Esto significa que se ejecutará el contenido del bloque cada vez que alguna
de estas señales cambie de valor.
A continuación, se muestra el código de un banco de prueba que aplica algunos
vectores de test al multiplexor (es sólo un pequeño ejemplo, no se trata de un
programa de test exhaustivo para este circuito).
--------------------------------------
-- Banco de pruebas
library IEEE;
use IEEE.std_logic_1164.all;
56 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
use IEEE.numeric_std.all;
entity bp_mux_4x1 is
end entity bp_mux_4x1;
begin
-- Instanciar y conectar UUT
uut : component mux_4x1 port map
( d => d,
i0 => i0, i1 => i1, i2 => i2, i3 => i3,
s0 => s0, s1 => s1 );
gen_vec_test : process
begin
i0 <= ’0’; i1 <= ’0’; i2 <= ’1’; i3 <= ’0’;
s0 <= ’0’; s1 <= ’0’;
wait for 5 ns;
i0 <= ’1’;
wait for 5 ns;
s0 <= ’1’;
wait for 10 ns;
s0 <= ’0’; s1 <= ’1’;
wait for 10 ns;
s0 <= ’1’;
wait;
end process gen_vec_test;
end architecture bp_mux_4x1;
--------------------------------------
--------------------------------------
-- MUX 4x1
-- ERROR al definir la sensibilidad del bloque process
architecture mux_4x1 of mux_4x1 is
begin
process (s1, s0) -- Error: no se incluyen i3,i2,i1,i0
begin
if (s1=’0’and s0=’0’) then
d <= i0;
elsif (s1=’0’and s0=’1’) then
d <= i1;
elsif (s1=’1’and s0=’0’) then
d <= i2;
else
d <= i3;
end if;
end process;
end architecture mux_4x1;
--------------------------------------
--------------------------------------
-- MUX 4x1
library IEEE; use IEEE.std_logic_1164.all;
58 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
mn
on
d <= i2;
when others =>
d <= i3;
end case;
end process;
end architecture mux_4x1;
--------------------------------------
--------------------------------------
-- MUX 4x1
library IEEE; use IEEE.std_logic_1164.all;
--------------------------------------
-- MUX 4x1
library IEEE; use IEEE.std_logic_1164.all;
60 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
a b res acarreo
0 0 0 0
0 1 1 1
1 0 1 0
1 1 0 0
-----------------------------------------
-- Restador completo de 1 bit
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
porque cada elemento de una señal del tipo unsigned es del tipo std logic, que
es exactamente el tipo de las señales res y acarreo_out.
~
p r pss t u v u z {
t
~ ~
}
~
x u{v p
p ~
r
q st y
~
p r pss t u v wx ~
--------------------------------------
-- OR exclusiva de 2 entradas: xor2
library IEEE; use IEEE.std_logic_1164.all;
--------------------------------------
-- Inversor de 1 entrada: not1
library IEEE; use IEEE.std_logic_1164.all;
--------------------------------------
-- AND de 2 entradas: and2
library IEEE; use IEEE.std_logic_1164.all;
--------------------------------------
-- OR de 3 entradas: or3
library IEEE; use IEEE.std_logic_1164.all;
-----------------------------------
-- Restador completo de 1 bit
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
( y0 : out std_logic;
x0, x1 : in std_logic );
end component and2;
component or3 is port
( y0 : out std_logic;
x0, x1, x2 : in std_logic );
end component or3;
begin
-- Instanciación y conexión de los componentes
g0 : component xor2 port map (c, a, b);
g1 : component xor2 port map (res, c, acarreo_in);
-- g2 : component not1 port map (not_a, a);
g2 : component not1 port map (y0 => not_a, x0 => a);
g3 : component and2 port map (d, not_a, acarreo_in);
g4 : component and2 port map (e, not_a, b);
g5 : component and2 port map (f, b, acarreo_in);
g6 : component or3 port map (acarreo_out, d, e, f);
end architecture rest_completo_estruc;
-----------------------------------
--------------------------------------------------
-- Banco de pruebas del restador completo de 1 bit
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
begin
-- Instanciar y conectar UUT
uut : component rest_completo port map
(res, acarreo_out, a, b, acarreo_in);
-- Crear vectores de test y comprobar salidas del UUT
gen_vec_test : process
variable test_in : unsigned (2 downto 0); -- Vector de test
variable esperado : unsigned (1 downto 0); -- Salida esperada
variable num_errores : integer := 0; -- Numero de errores
begin
test_in := B"000";
for count in 0 to 7 loop
a <= test_in(2);
b <= test_in(1);
acarreo_in <= test_in(0);
wait for 10 ns;
esperado := (’0’ & a) - (’0’ & b) - (’0’ & acarreo_in);
if (esperado /= ( acarreo_out & res )) then -- Comprueba resultado
report "ERROR : Esperado (" & -- Report del error
std_logic’image(esperado(1)) &
std_logic’image(esperado(0)) &
") /= actual (" &
std_logic’image(acarreo_out) &
std_logic’image(res) &
") en el instante " &
time’image(now);
num_errores := num_errores + 1;
end if;
test_in := test_in + 1;
end loop;
report "Test completo. Hay " &
integer’image(num_errores) &
" errores.";
wait;
Capı́tulo 3 Casos prácticos de diseño de circuitos combinacionales 67
entity bp_rest_completo is
end entity bp_rest_completo;
Se han definido señales internas al banco de pruebas para todas las conexiones
al UUT. Aunque en este ejemplo si lo sean, los nombres de las señales no tienen
que ser idénticos a los nombres de los puertos del UUT.
Se ha definido un proceso (process) para generar las formas de onda de las
entradas al UUT, y en ese mismo proceso se han incluido las sentencias para
comprobar si las salidas del UUT coinciden con las esperadas.
Es esencial tener en cuenta que el método empleado para calcular las sali-
das “esperadas” del UUT debe ser diferente del método empleado en el propio
UUT para obtener las salidas. En este ejemplo, el UUT contiene una descripción
estructural de la arquitectura del restador, mientras que las salidas “esperadas”
(variable esperado) se calculan a partir de una descripción del comportamiento
del restador:
--------------------------------------------------
-- Banco de pruebas del restador completo de 1 bit
-- empleando un procedimiento
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
std_logic’image(esperado(1)) &
std_logic’image(esperado(0)) &
") /= actual (" &
std_logic’image(actual(1)) &
std_logic’image(actual(0)) &
") en el instante" &
time’image(now);
num_errores := num_errores + 1;
end if;
end procedure error_check;
begin
-- Instanciar y conectar UUT
uut : component rest_completo port map
(res, acarreo_out, a, b, acarreo_in);
-- Crear vectores de test y comprobar salidas del UUT
gen_vec_test : process
variable test_in : unsigned (2 downto 0); -- Vector de test
variable esperado : unsigned (1 downto 0); -- Salida esperada
variable num_errores : integer := 0; -- Numero de errores
begin
test_in := B"000";
for count in 0 to 7 loop
a <= test_in(2);
b <= test_in(1);
acarreo_in <= test_in(0);
wait for 10 ns;
esperado := (’0’ & a) - (’0’ & b) - (’0’ & acarreo_in);
error_check( esperado, acarreo_out & res, num_errores );
test_in := test_in + 1;
end loop;
report "Test completo. Hay " &
integer’image(num_errores) &
" errores.";
wait;
end process gen_vec_test;
end architecture bp_rest_completo_procedure;
--------------------------------------------------
70 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
--------------------------------------------------
-- Banco de pruebas del restador completo de 1 bit
-- empleando un procedimiento
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
begin
-- Instanciar y conectar UUT
uut : component rest_completo port map
(res, acarreo_out, a, b, acarreo_in);
-- Crear vectores de test y comprobar salidas del UUT
gen_vec_test : process
variable test_in : unsigned (2 downto 0); -- Vector de test
variable esperado : unsigned (1 downto 0); -- Salida esperada
variable num_errores : integer := 0; -- Numero de errores
begin
test_in := B"000";
for count in 0 to 7 loop
a <= test_in(2);
b <= test_in(1);
acarreo_in <= test_in(0);
wait for 10 ns;
esperado := (’0’ & a) - (’0’ & b) - (’0’ & acarreo_in);
num_errores := num_errores +
error_check( esperado, acarreo_out & res, now );
test_in := test_in + 1;
end loop;
report "Test completo. Hay " &
integer’image(num_errores) &
"errores.";
wait;
end process gen_vec_test;
end architecture bp_rest_completo_funcion;
--------------------------------------------------
ci xi yi ci+1 si
0 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 1 1 1 0
1 0 0 0 1
1 0 1 1 0
1 1 0 1 0
1 1 1 1 1
ci+1 = xi yi + xi ci + yi ci
si = xi ⊕ yi ⊕ ci
+
--------------------------------------
-- AND de 2 entradas con retardo
Capı́tulo 3 Casos prácticos de diseño de circuitos combinacionales 73
entity and2 is
generic ( DELAY : time := 10 ns );
port ( y0 : out std_logic;
x0, x1 : in std_logic );
end entity and2;
--------------------------------------
-- OR de 3 entradas con retardo
library IEEE; use IEEE.std_logic_1164.all;
entity or3 is
generic ( DELAY : time := 10 ns );
port ( y0 : out std_logic;
x0, x1, x2 : in std_logic );
end entity or3;
-----------------------------------------
-- OR exclusiva de 2 entradas con retardo
library IEEE; use IEEE.std_logic_1164.all;
entity xor2 is
generic ( DELAY : time := 10 ns );
port ( y0 : out std_logic;
x0, x1 : in std_logic );
end entity xor2;
------------------------------------------
-----------------------------------
-- package de componentes
-- Puertas lógicas
library IEEE;
use IEEE.std_logic_1164.all;
package puertasLogicas_package is
component xor2 is
generic ( DELAY : time := 10 ns );
port ( y0 : out std_logic;
x0, x1 : in std_logic );
end component xor2;
component and2 is
generic ( DELAY : time := 10 ns );
port ( y0 : out std_logic;
x0, x1 : in std_logic );
end component and2;
component or3 is
generic ( DELAY : time := 10 ns );
port ( y0 : out std_logic;
x0, x1, x2 : in std_logic );
end component or3;
-----------------------------------
-- Sumador completo de 1 bit
library IEEE;
use IEEE.std_logic_1164.all;
use work.puertasLogicas_package.all;
Capı́tulo 3 Casos prácticos de diseño de circuitos combinacionales 75
--------------------------------------------------
-- Banco de pruebas del sumador completo de 1 bit
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
component sum_completo is
port ( s, C_out : out std_logic;
x, y, C_in : in std_logic);
end component sum_completo;
begin
-- Instanciar y conectar UUT
uut : component sum_completo port map
(s => s, C_out => C_out, x => x, y => y, C_in => C_in);
-- Crear vectores de test y comprobar salidas del UUT
gen_vec_test : process
variable test_in : unsigned (2 downto 0); -- Vector de test
variable esperado : unsigned (1 downto 0); -- Salida esperada
variable num_errores : integer := 0; -- Numero de errores
begin
test_in := B"000";
for count in 0 to 7 loop
C_in <= test_in(2);
x <= test_in(1);
y <= test_in(0);
wait for 50 ns;
esperado := (’0’ & x) + (’0’ & y) + (’0’ & C_in);
if (esperado /= ( C_out & s )) then -- Comprueba resultado
report "ERROR : Esperado (" & -- Report del error
std_logic’image(esperado(1)) &
std_logic’image(esperado(0)) &
") /= actual (" &
std_logic’image(C_out) &
std_logic’image(s) &
") en el instante " &
time’image(now);
num_errores := num_errores + 1;
end if;
test_in := test_in + 1;
end loop;
report "Test completo. Hay " &
integer’image(num_errores) &
" errores.";
wait;
end process gen_vec_test;
end architecture bp_sum_completo;
Capı́tulo 3 Casos prácticos de diseño de circuitos combinacionales 77
--------------------------------------------------
¦¥ ¨§ ¦¥
 î ÅÄ Æº É ÇÈ
¿ÀÁ ¢¡ ¢¡ ¢¡ ©£ ¢¡
+ + + +
¤£ ¤£
¯ µ » ¾
® ´ º ½
Figura 3.9: Sumador binario paralelo de 4 bits con propagación del arrastre.
-------------------------------------------
-- Fuente de datos unidireccional (lectura)
library IEEE; use IEEE.std_logic_1164.all;
entity fuenteUnidireccional is
generic ( WORD_SIZE : integer := 8; -- Bits por palabra,
-- por defecto 8
READ_DELAY : time := 10 ns); -- Retardo en la lectura,
-- por defecto 10 ns
port ( data : out std_logic_vector(WORD_SIZE-1 downto 0);
-- Datos de salida
OE_n : in std_logic); -- Habilita lectura
end entity fuenteUnidireccional;
La sentencia
Capı́tulo 3 Casos prácticos de diseño de circuitos combinacionales 79
indica que debe asignarse al vector de señales data, una vez transcurrido el
retardo de tiempo READ_DELAY, una palabra del tamaño de data, con todos
sus bits igual a ’0’ excepto el menos significativo, que debe valer ’1’ (es decir,
data <= "00...01";). Esta palabra es la que se encuentra almacenada en la
memoria y es la que se lee cada vez que se habilita la operación de lectura.
Análogamente, la sentencia
asigna al vector de señales data una palabra, con el mismo número de bits que
data, con todos sus bits al valor ’Z’ (alta impedancia).
– Señal de entrada de 1 bit (OE_n). Cuando esta señal se pone a ’0’, habilita
la operación de lectura de la memoria. Cuando está a ’1’, la operación de
lectura está deshabilitada.
– Señal de entrada de 1 bit (WE_n). Cuando esta señal se pone a ’0’, habilita
la operación de escritura en la memoria. Cuando está a ’1’, la operación de
escritura está deshabilitada.
------------------------------------------------------
-- Fuente de datos bidireccional (lectura y escritura)
library IEEE; use IEEE.std_logic_1164.all;
entity fuenteBidireccional is
generic ( WORD_SIZE : integer := 8; -- Bits por palabra,
-- por defecto 8 bits
READ_DELAY : time := 10 ns; -- Retardo en la lectura,
-- por defecto 10 ns
WRITE_DELAY : time := 10 ns); -- Retardo en la escritura,
-- por defecto 10 ns
port ( data : inout std_logic_vector(WORD_SIZE-1 downto 0);
-- Se~
nal de datos bidireccional
OE_n : in std_logic; -- Habilita lectura
WE_n : in std_logic ); -- Habilita escritura
end entity fuenteBidireccional;
-----------------------------------------------
-- Conexión de la fuente de datos bidireccional
-- y la fuente unidireccional mediante un bus
library IEEE; use IEEE.std_logic_1164.all;
entity tb_bus is
constant WORD_SZ : integer := 16; -- Bits por palabra
constant PERIOD : time := 100 ns; -- Periodo ciclo reloj
end entity tb_bus;
component fuenteUnidireccional is
generic ( WORD_SIZE : integer := 8; -- Bits por palabra
READ_DELAY : time := 10 ns); -- Retardo en la lectura
begin
82 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
Una unidad aritmético lógica (ALU) es un circuito que, dependiendo del valor de
sus entradas de selección de función, realiza una operación lógica o aritmética, de
entre un conjunto de operaciones posibles, sobre uno o dos operandos.
Capı́tulo 3 Casos prácticos de diseño de circuitos combinacionales 83
Este tipo de circuito puede ser descrito mediante una asignación concurrente
a una señal, o bien mediante varias asignaciones incluidas dentro de un bloque
process.
En general, un circuito combinacional puede ser descrito mediante un bloque
process siempre que todas las señales de entrada al circuito combinacional sean
incluidas en la lista de variables a las que es sensible el bloque process.
A continuación, se muestran dos posibles formas de modelar una ALU: la
primera usando una asignación concurrente y la segunda usando un bloque pro-
cess. Ambas versiones dan lugar a circuitos combinacionales equivalentes. En la
Tabla 3.1 se muestran las operaciones entre los operandos A y B que realiza la
ALU, en función del valor de la entrada de selección de función de 3 bits mode.
----------------------------------------------
-- Definición de constantes globales de la ALU
package ALU_CONSTANTS is
constant WIDTH : integer := 16;
-- Núm. bits de los operandos
constant SEL_BITS :
integer := 3;
-- Núm. bits selección de operación
end package ALU_CONSTANTS;
----------------------------------------------
----------------------------------------------
-- ALU
-- architecture: sentencia concurrente
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.ALU_CONSTANTS.all;
entity ALU is
port ( C : out std_logic_vector (WIDTH-1 downto 0);
A, B : in std_logic_vector (WIDTH-1 downto 0);
mode : in std_logic_vector (SEL_BITS-1 downto 0) );
end entity ALU;
----------------------------------------------
-- ALU
-- architecture: bloque process
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.ALU_CONSTANTS.all;
begin
case mode is
when "000" => C <= std_logic_vector(signed(A)+signed(A));
when "001" => C <= std_logic_vector(signed(A)+signed(B));
when "010" => C <= std_logic_vector(signed(A)-signed(B));
when "011" => C <= std_logic_vector(-signed(A));
when "100" => C <= A and B;
when "101" => C <= A or B;
when "110" => C <= A xor B;
when others => C <= not A;
end case;
end process;
end architecture ALU_bloqueProcess;
----------------------------------------------
– Se escogen valores de los operandos entorno al cero. Por ejemplo: −2, −1,
0, 1 y 2.
----------------------------------------------
-- Definición de constantes globales
-- del banco de pruebas de la ALU
use work.ALU_CONSTANTS.all;
package TB_ALU_CONSTANTS is
constant SEL_MAX : integer := 2**SEL_BITS - 1;
constant MAX_POS_DATA : integer := 2**(WIDTH-1) - 1;
constant MIN_NEG_DATA : integer := -2**(WIDTH-1);
constant DELAY : time := 10 ns;
end package TB_ALU_CONSTANTS;
----------------------------------------------
----------------------------------------------
-- Banco de pruebas para la ALU
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.ALU_CONSTANTS.all;
use work.TB_ALU_CONSTANTS.all;
entity TB_ALU is
constant PERIOD : time := 100 ns;
end entity TB_ALU;
component ALU is
port ( C : out std_logic_vector (WIDTH-1 downto 0);
A, B : in std_logic_vector (WIDTH-1 downto 0);
mode : in std_logic_vector (SEL_BITS-1 downto 0) );
end component ALU;
begin
UUT : component ALU port map (C, A, B, mode);
A <= std_logic_vector(TO_SIGNED(41*i-273,WIDTH));
b <= std_logic_vector(TO_SIGNED(89*j-384,WIDTH));
mode <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait for DELAY;
check_ALU(41*i-273, 89*j-384, k, C, error_count);
end loop;
end loop;
end loop;
ser transformado en una secuencia de puertas lógicas, y por tanto puede ser
implementado usando un circuito combinacional.
------------------------------------------
-- Definición de constantes globales
package BCD_CONST is
constant LENGTH : integer := 16;
-- Longitud (# bits) del número BCD
end package BCD_CONST;
------------------------------------------
--------------------------------------
-- Circuito conversor de BCD a binario
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.BCD_CONST.all;
entity bcd_to_bin is
port( bin: out std_logic_vector(LENGTH-1 downto 0);
bcd: in std_logic_vector(LENGTH-1 downto 0) );
end entity bcd_to_bin;
begin
bcd_concat_bin := unsigned(bcd) & TO_UNSIGNED(0,LENGTH);
for i in 0 to LENGTH-1 loop -- Paso 2
bcd_concat_bin := bcd_concat_bin srl 1; -- Paso 2a
for j in 0 to (LENGTH/4)-1 loop -- Paso 2b
temp := bcd_concat_bin(LENGTH+j*4+3 downto LENGTH+j*4);
if (temp(3) = ’1’) then -- Si la secuencia de 4 bits
temp := temp - "0011"; -- es mayor que 7, se resta 3
end if;
bcd_concat_bin(LENGTH+j*4+3 downto LENGTH+j*4) := temp;
end loop; -- end for Paso 2b
end loop; -- end for Paso 2
bin <= std_logic_vector(bcd_concat_bin(LENGTH-1 downto 0));
end process;
end architecture bcd_to_bin;
--------------------------------------
----------------------------------------------
-- Banco de pruebas para el circuito conversor
-- de BCD a binario
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.BCD_CONST.all;
entity bp_bcd_to_bin is
constant MAX_BCD : integer := 9999; -- Valor máximo de entrada
constant DELAY : time := 10ns; -- Retardo usado en el test;
end entity bp_bcd_to_bin;
92 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
begin
-- Instancia la unidad a testear
UUT : component bcd_to_bin port map(bin,bcd);
-------------------------------------------
-- Codificador 4:2 con prioridad
library IEEE;
use IEEE.std_logic_1164.all;
entity codificador_4_2_prioridad is
port ( valida : out std_logic; -- ’1’ si hay entrada
codificada : out std_logic_vector(1 downto 0);
i3, i2, i1, i0 : in std_logic );
end entity codificador_4_2_prioridad;
94 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
end process;
end architecture codificador_4_2_prioridad;
-------------------------------------------
-----------------------------------------------------
-- Banco de pruebas del codificador 4:2 con prioridad
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity bp_codificador_4_2 is
constant MAX_COMB : integer := 16; -- Num. combinaciones entrada
constant DELAY : time := 10 ns; -- Retardo usado en el test
end entity bp_codificador_4_2;
component codificador_4_2_prioridad is
port ( valida : out std_logic;
codificada : out std_logic_vector(1 downto 0);
i3, i2, i1, i0 : in std_logic );
end component codificador_4_2_prioridad;
main : process is
variable temp : unsigned (3 downto 0); -- Usado en los cálculos
variable esperado_valida : std_logic;
variable esperado_codificada : std_logic_vector(1 downto 0);
variable error_count : integer := 0;
begin
report "Comienza la simulación";
-- Generar todos los posibles valores de entrada
for i in 0 to (MAX_COMB-1) loop
temp := TO_UNSIGNED(i,4);
i3 <= std_logic(temp(3));
i2 <= std_logic(temp(2));
i1 <= std_logic(temp(1));
i0 <= std_logic(temp(0));
-- Calcular el valor esperado
if (i=0) then
esperado_valida := ’0’;
esperado_codificada := "00";
else
esperado_valida := ’1’;
if (i=1) then esperado_codificada := "00";
elsif (i<=3) then esperado_codificada := "01";
elsif (i<=7) then esperado_codificada := "10";
else esperado_codificada := "11";
end if;
end if;
s0 ÌÍ Î
ÌÍ Î
ÊË Ê
ÊË Ê s1
s2
ÏË Ï
Cada estado del diagrama “recuerda” una porción de la secuencia 101. Las
transiciones entre los estados están etiquetadas x/y, donde x corresponde con el
valor de la entrada que produce la transición, e y corresponde con el valor de
la variable de salida dado el estado en el que empieza la transición y el valor
de entrada x. Dado que la salida depende del estado actual y de la variable de
entrada, este tipo de diagrama corresponde con una máquina de Mealy.
En este tipo de diagrama debe tenerse en cuenta que debe escribirse una
transición desde cada estado por cada posible valor que puede tomar la entrada
en ese estado.
Capı́tulo 4 Casos prácticos de diseño de circuitos secuenciales 101
Estado A B
S0 0 0
S1 0 1
S2 1 0
NA = x B (4.1)
NB = x (4.2)
y=xA (4.3)
process (enable, D) is
begin
if (enable = ’1’) then
q <= D;
end if;
end process;
Un motivo por el cual podrı́a pensarse en omitir el caso else, es que sea
indiferente el valor que se asigne a las señales en este caso (ya que en la práctica
nunca se producirá). Si no deseamos que el circuito se sintetice mediante un latch,
debemos incluir el caso else en la sentencia condicional y asignar a las señales el
valor ’X’ (don’t care).
4.2.3 Retardos
En la Sección 3.1 se explicó que en la descripción para sı́ntesis de los circuitos
combinacionales debe evitarse el uso de retardos. Lo mismo aplica a la descripción
de circuitos secuenciales. Los retardos en el hardware son dependientes de la
tecnologı́a empleada en su fabricación y están sujetos a la variabilidad del proceso
de fabricación, por ello es extremadamente difı́cil construir circuitos que presenten
un determinado retardo.
Ası́ pues, no es posible sintetizar sentencias tales como wait for x ns. Igual-
mente, no es posible sintetizar sentencias que empleen la cláusula after. Algunas
herramientas de sı́ntesis ignoran estas sentencias, mientras que otras muestran
mensajes de error.
Cuando es preciso emplear retardos para describir adecuadamente el circuito,
puede definirse un retardo constante en la parte superior del código
constant DEL : time := 1 ns;
y usar este retardo en el código del circuito. Por ejemplo:
A <= B after DEL; Puede asignarse un valor positivo a esta constante
de retardo para realizar la simulación del circuito y posteriormente asignarle el
valor cero cuando vaya a realizarse la sı́ntesis.
Obsérvese que esta discusión acerca de los retardos aplica a los circuitos, no
a los bancos de prueba, que no necesitan ser sintetizados.
4.2.4 Inicialización
Debe evitarse inicializar las variables y las señales al declararlas, ya que este tipo
de inicialización no puede ser sintetizada.
104 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
Para asignar valor a las salidas de los flip-flops y latches dentro de un bloque
process, pueden emplearse sentencias de asignación a señal (usan el operador
<=) y sentencias de asignación a variable (usan el operador :=). Las asignaciones
a variable tienen efecto inmediatamente, mientras que las asignaciones a señal
tienen efecto en un instante de tiempo delta unidades de tiempo posterior al
tiempo simulado actual (suponiendo que no se ha especificado el retraso en la
asignación empleando la cláusula after).
Cuando se emplean bloques process para describir un circuito secuencial,
debe indicarse la lista de sensibilidad de cada bloque process con el fin de con-
trolar cuándo se activa el bloque. Cuando se especifica una lista de sensibilidad,
el simulador no ejecuta el bloque process hasta que no se produce un cambio en
alguna de las señales que componen la lista.
Obsérvese que es posible controlar la ejecución del bloque process mediante
la lista de sensibilidad y también mediante el empleo de cláusulas wait dentro del
cuerpo el bloque process. Sin embargo, no es recomendable emplear este segundo
método (uso de cláusulas wait dentro del bloque process), ya que puede dar lugar
a circuitos no sintetizables.
Si un bloque process no tiene lista de sensibilidad, entonces ese bloque se
ejecuta continuamente, con lo cual su simulación es muy ineficiente. Por este
motivo, es recomendable que todo bloque process tenga su lista de sensibilidad.
Capı́tulo 4 Casos prácticos de diseño de circuitos secuenciales 105
4.3 Flip-flop JK
En esta sección se describe el diseño de un flip-flop JK con reset ası́ncrono activado
al nivel LOW. Este circuito puede encontrarse en dos estados: Q=’0’ y Q=’1’.
La tabla de verdad del circuito, considerando únicamente las entradas J (entrada
set), K (entrada reset), el estado actual (Qt ) y el siguiente estado Qt+1 es la
mostrada a continuación. Las transiciones de estado se producen en el flanco de
subida del reloj.
ÐÑ ÑÐ
ÓÒ
0 ÒÓ
1
Figura 4.3: Transición de estados de un flip-flop JK. En los arcos del
diagrama se muestra el valor de las señales JK. El bit ’X’ es“don’t care”(por
ejemplo, “0X” representa “00” ó “01”). La transición de reset se representa
mediante una lı́nea punteada.
Cuando la entrada de reset pasa de valer ’1’ a valer ’0’, el circuito pasa al
estado Q=’0’. Se denomina reset ası́ncrono porque la transición al estado ’0’ se
produce en el instante en que cambia la señal de reset, con independencia del
valor de la señal de reloj. La transición de reset se representa mediante una lı́nea
punteada en la Figura 4.3.
El circuito tiene dos salidas: Q y Q. La salida Q es igual al estado y la salida
Q es su inversa: Q = not Q.
------------------------------------------------
-- Biestable JK con reset ası́ncrono en nivel LOW
library IEEE;
use IEEE.std_logic_1164.all;
106 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
entity flipflop_JK is
port ( q, q_n : out std_logic;
clk, J, K, reset_n : in std_logic );
end entity flipflop_JK;
Ø ÔÔ Ý ÔÔ
Ù ÕÖ Þ ÖÕ
Û ÕÖ
ß ××
0 1
à
Ú ÖÕ
Ü ××
Figura 4.4: Orden en que el programa de test recorre los arcos del diagrama
de transiciones.
Obsérvese que la sentencia wait que hay al final del bloque process finaliza
la ejecución de dicho bloque, pero no la simulación, ya que la simulación de
las sentencias de asignación concurrente a las señales de reset y reloj se realiza
indefinidamente. Por tanto, la simulación del banco de pruebas no finaliza por sı́
misma, siendo preciso fijar su duración: 900 ns.
--------------------------------------
-- Banco de pruebas del flip-flop JK
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity bp_flipflopJK is
end entity bp_flipflopJK;
component flipflop_JK is
port ( q, q_n : out std_logic;
clk, J, K, reset_n : in std_logic );
end component flipflop_JK;
std_logic’image(esperado_q) &
"), estado actual (" &
std_logic’image(actual_q) &
"), instante: " &
time’image(now);
error_count := error_count + 1;
end if;
-- Comprueba q_n
if ( (not esperado_q) /= actual_q_n ) then
report "ERROR: q_n esperado (" &
std_logic’image((not esperado_q)) &
"), valor actual (" &
std_logic’image(actual_q_n) &
"), instante: " &
time’image(now);
error_count := error_count + 1;
end if;
end procedure comprueba_salidas;
begin
-- Instanciar y conectar UUT
uut : component flipflop_JK port map
(q, q_n, clk, J, K, reset_n);
gen_vec_test : process is
variable error_count : integer := 0; -- Núm. errores
begin
report "Comienza la simulación";
-- Informe final
if (error_count = 0) then
report "Simulación finalizada sin errores";
else
report "ERROR: Hay " &
integer’image(error_count) &
" errores.";
end if;
La simulación del banco de pruebas se realiza con cero errores. En la Figura 4.5
se muestra el resultado obtenido de la simulación.
Figura 4.5: Resultado de la ejecución del banco de pruebas del flip-flop JK.
del circuito, ya que este tipo de descripción suele ser menos propensa a errores
y las herramientas de sı́ntesis convertirán estos diseños en implementaciones
optimizadas.
En la Figura 4.6 se muestra una máquina de Moore sencilla. La transición
entre los tres estados depende del valor de la entrada, x. La salida del circuito, z,
vale 1 en el estado S2 y 0 en los demás estados. Este código puede ser adaptado
fácilmente para la descripción de otras máquinas de Moore.
Sá/ 0 1
0
1 Sâ /1
0
Sã / 0 0
-------------------------------------------------------
-- Paquete con la definición de las constantes globales
library IEEE;
use IEEE.std_logic_1164.all;
package STATE_CONSTANTS is
constant STATE_BITS: integer := 2; -- Bits codifican estado
constant S0: std_logic_vector(1 downto 0) := "00"; -- Estados
constant S1: std_logic_vector(1 downto 0) := "01";
constant S2: std_logic_vector(1 downto 0) := "10";
end package;
-------------------------------------------------------
------------------------------------------------------
-- Máquina de Moore
library IEEE;
Capı́tulo 4 Casos prácticos de diseño de circuitos secuenciales 111
use IEEE.std_logic_1164.all;
use work.STATE_CONSTANTS.all;
-- Definición de la entidad
entity maquinaMooreSimple is
port( z : out std_logic; -- Se~
nal de salida
state : out std_logic_vector(STATE_BITS-1 downto 0);
-- Estado actual de la máquina
reset_n : in std_logic; -- Se~nal reset activada en bajo
clk : in std_logic; -- Se~nal de reloj
x : in std_logic); -- Se~
nal de entrada
end entity maquinaMooreSimple;
-- Definición de la arquitectura
architecture maquinaMooreSimple of maquinaMooreSimple is
signal internal_state: std_logic_vector(STATE_BITS-1 downto 0);
begin
state <= internal_state; -- Muestra el estado
-- Genera la salida
salida: process(internal_state) is
begin
case internal_state is
when S0 => z <= ’0’;
when S1 => z <= ’0’;
when S2 => z <= ’1’;
when others => z <= ’X’;
end case;
end process salida;
– La interfaz del circuito está compuesta por dos puertos de salida (la salida
y el estado actual) y tres puertos de entrada (señal de reset ası́ncrono, reloj
y entrada). Cuando la señal de reset (reset_n) pasa de valer 1 a valer 0,
entonces la máquina pasa al estado S0 .
– Se ha añadido una cláusula when other al final de los dos bloques case,
con el fin de contemplar todos los casos posibles. Obsérvese que se asigna
Capı́tulo 4 Casos prácticos de diseño de circuitos secuenciales 113
el valor ’X’ (don’t care) a la señal de salida. Esta es una buena práctica,
ya que con ello se ayuda a la herramienta de sı́ntesis a optimizar el circuito
combinacional para la señal de salida (z).
Sä / 0
ëìí î
ñìí î
⋅
⋅
ðìí î
⋅ ïìí î
⋅
S å /1
ýþÿ
⋅
Sæ / 0
é ê
è ⋅
ç
------------------------------------------------------
-- Banco de pruebas para la máquina de Moore
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
114 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
use work.STATE_CONSTANTS.all;
-- Definición de la entity
entity bp_maquinaMooreSimple is
constant PERIODO : time := 100 ns; -- Periodo reloj
end entity bp_maquinaMooreSimple;
-- Definición de la architecture
architecture bp_maquinaMooreSimple of bp_maquinaMooreSimple is
signal z : std_logic;
signal state : std_logic_vector(STATE_BITS-1 downto 0);
signal reset_n : std_logic;
signal clk : std_logic := ’0’; -- Inicializada a ’0’
signal x : std_logic;
end if;
-- Comprueba la salida
if ( esperado_z /= actual_z ) then
report "ERROR: salida esperada (" &
std_logic’image(esperado_z) &
"), salida actual (" &
std_logic’image(actual_z) &
") en el instante " &
time’image(now);
error_count := error_count + 1;
end if;
end procedure comprueba_state_z;
-- Cuerpo de la architecture
begin
-- Instancia UUT
UUT : component maquinaMooreSimple port map
( z, state, reset_n, clk, x );
-- Genera se~
nal clk, asumiendo que se inicializó a 0
-- Flanco de subida en los instantes:
-- PERIODO/2, PERIODO+PERIODO/2, 2*PERIODO+PERIODO/2, ...
clock : clk <= not clk after ( PERIODO/2 );
-- main process:
-- genera vectores de test y comprueba resultados
main : process is
variable error_count : integer := 0; -- Num. errores
begin
report "Comienza la simulación";
x <= ’0’; -- Valor inicial de entrada a UUT
wait for PERIODO;
-- En el instante PERIODO, el estado deberı́a ser S0
comprueba_state_z(S0, ’0’, state, z, error_count);
wait for PERIODO;
-- En el instante 2*PERIODO, el estado deberı́a ser S2
comprueba_state_z(S2, ’1’, state, z, error_count);
x <= ’1’;
wait for PERIODO;
116 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
NA = x A + x A (4.4)
NB = x A (4.5)
z=A (4.6)
------------------------------------------------------
-- Máquina de Moore, dise~
no estructural
library IEEE;
use IEEE.std_logic_1164.all;
-- Definición de la arquitectura
architecture maquinaMooreSimple_estruc of maquinaMooreSimple is
signal A, B : std_logic; -- Variables de estado actuales
signal NA, NB : std_logic; -- Próximas variables de estado
118 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
-- Componente: flip-flop D
component flipflop_D is
port ( q, q_n : out std_logic;
d, clk, reset_n : in std_logic);
end component flipflop_D;
begin
state <= A & B; -- Muestra estado actual en el puerto de salida
S
S
S
S
----------------------------------------
-- Definición de las constantes globales
library IEEE;
use IEEE.std_logic_1164.all;
120 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
package seq0110_CONST is
constant STATE_BITS : integer := 2; -- Num. bits del estado
constant S0 : std_logic_vector(1 downto 0) := "00";
constant S1 : std_logic_vector(1 downto 0) := "01";
constant S2 : std_logic_vector(1 downto 0) := "10";
constant S3 : std_logic_vector(1 downto 0) := "11";
end package seq0110_CONST;
----------------------------------------
--------------------------------------------------
-- Máquina de Mealy detectora de la secuencia 0110
library IEEE;
use IEEE.std_logic_1164.all;
use work.seq0110_CONST.all;
-- Definición de la entity
entity seq0110 is
port ( z : out std_logic; -- Se~
nal de salida
state : out std_logic_vector(STATE_BITS-1 downto 0);
-- Estado actual
reset_n : in std_logic; -- Reset sı́ncrono activado LOW
clk : in std_logic; -- Se~
nal de reloj
x : in std_logic ); -- Bit de entrada
end entity seq0110;
-- Definición de la architecture
architecture seq0110 of seq0110 is
signal internal_state : std_logic_vector(STATE_BITS-1 downto 0);
begin
state <= internal_state;
-- Cálculo de la salida
calculo_salida: process (internal_state, x) is
begin
if ( (internal_state = S3) and (x = ’0’) ) then
z <= ’1’;
else
z <= ’0’;
Capı́tulo 4 Casos prácticos de diseño de circuitos secuenciales 121
end if;
end process calculo_salida;
que es activada cada vez que se produce un cambio en alguna de las señales de
la parte derecha de la asignación.
Puesto que éste es un bloque combinacional, la duración de la señal ’1’ de
salida puede ser más pequeña que un ciclo de reloj, ya que su duración depende
del tiempo durante el cual la entrada x siga valiendo ’0’ mientras la máquina
permanezca en el estado S3.
Para garantizar que la salida ’1’ tiene una duración de al menos un ciclo de
reloj, es necesario hacer pasar la señal de salida por un flip-flop D. Esto puede
hacerse añadiendo a la descripción de la arquitectura el siguiente bloque process:
y haciendo que z_long sea la salida del circuito. La definición del circuito, modi-
ficada de la forma descrita anteriormente, es mostrada a continuación.
--------------------------------------------------
-- Máquina de Mealy detectora de la secuencia 0110
library IEEE;
use IEEE.std_logic_1164.all;
use work.seq0110_CONST.all;
-- Definición de la entity
entity seq0110 is
port ( z_long : out std_logic; -- Se~
nal de salida
state : out std_logic_vector(STATE_BITS-1 downto 0);
-- Estado actual
reset_n : in std_logic; -- Reset sı́ncrono activado LOW
clk : in std_logic; -- Se~
nal de reloj
x : in std_logic ); -- Bit de entrada
end entity seq0110;
-- Definición de la architecture
architecture seq0110 of seq0110 is
signal internal_state : std_logic_vector(STATE_BITS-1 downto 0);
signal z : std_logic; -- Se~
nal de salida obtenida
Capı́tulo 4 Casos prácticos de diseño de circuitos secuenciales 123
-- Cálculo de la salida
-- z <= ’1’ when ( (internal_state = S3) and (x = ’0’) ) else ’0’;
calculo_salida: process (internal_state,x) is
begin
if ( (internal_state = S3) and (x = ’0’) ) then
z <= ’1’;
else
z <= ’0’;
end if;
end process calculo_salida;
when S2 =>
if (x = ’1’) then -- Tercer bit del patrón
internal_state <= S3;
else
internal_state <= S1;
end if;
when others =>
if (x = ’0’) then -- Cuarto bit del patrón
internal_state <= S1;
else
internal_state <= S0;
end if;
end case;
end if;
end process proximo_estado;
end architecture seq0110;
--------------------------------------------------
------------------------------------------------------
-- Banco de pruebas que introduce algunos vectores de
-- test en la máquina detectora de la secuencia 0110
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.seq0110_CONST.all;
entity bp1_seq0110 is
constant PERIODO : time := 100 ns; -- Periodo reloj
end entity bp1_seq0110;
begin
-- Instanciar UUT
UUT: component seq0110 port map
( z_long, state, reset_n, clk, x );
-- Generar la se~
nal de reloj,
-- asumiendo que ha sido inicializada a ’0’
clk <= not clk after ( PERIODO/2 );
Ejecutando este banco de pruebas durante 1200 ns, se obtienen las señales
mostradas en la Figura 4.11. Obsérvese que la señal z vale ’1’ mientras el circuito
se encuentra en el estado S3 y la entrada vale ’0’. La señal z está conectada a la
entrada de un flip-flop D, cuya salida es la señal z_long, que mantiene su valor a
’1’ durante un ciclo completo de reloj.
126 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
2
10 S 5 7 11
3
S S
1 6
13
9 S 8 12
Figura 4.12: Orden en que el programa de test recorre los arcos del diagrama
de estado de la máquina.
------------------------------------------------------
-- Banco de pruebas - Máquina detectora secuencia 0110
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.seq0110_CONST.all;
entity bp_seq0110 is
constant PERIODO : time := 100 ns; -- Periodo reloj
end entity bp_seq0110;
-- Estado actual
signal reset_n : std_logic; -- Reset sı́ncrono activado LOW
signal clk : std_logic := ’0’; -- Se~
nal de reloj
signal x : std_logic; -- Entrada a la máquina
-- Comprueba salida
assert( esperado_z = actual_z )
report "ERROR: Salida esperada (" &
std_logic’image(esperado_z) &
"), salida actual (" &
std_logic’image(actual_z) &
"), instante: " &
time’image(now);
if ( esperado_z /= actual_z ) then
128 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
error_count := error_count + 1;
end if;
end procedure comprueba_estado_salida;
begin
-- Instanciar UUT
UUT: component seq0110 port map
( z_long, state, reset_n, clk, x );
-- Generar la se~
nal de reloj,
-- asumiendo que ha sido inicializada a ’0’
clk <= not clk after ( PERIODO/2 );
if (error_count = 0) then
report "Simulación finalizada sin errores";
else
report "ERROR: Hay " &
integer’image(error_count) &
" errores.";
end if;
El test se ejecuta durante 1500 ns, sin que se produzca ningún error. En la
Figura 4.13 se muestra la evolución de las señales durante los primeros 1400 ns.
-------------------------------------------
-- Circuito detector de secuencia 0111 1110
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity detector_sec is
port ( detectado : out std_logic;
reset_n : in std_logic;
clk : in std_logic;
data_in : in std_logic );
end entity detector_sec;
-------------------------------------------
architecture detector_sec2 of detector_sec is
signal prev_data : unsigned (7 downto 0);
begin
process (reset_n, clk) is
begin
if (reset_n = ’0’) then
prev_data <= B"1111_1111";
elsif rising_edge(clk) then
prev_data <= (prev_data(6 downto 0) & data_in);
if ((prev_data(6 downto 0) & data_in) = B"0111_1110") then
detectado <= ’1’;
else
detectado <= ’0’;
end if;
end if;
end process;
end architecture detector_sec2;
-------------------------------------------
La sentencia
prev_data <= (prev_data(6 downto 0) & data_in);
realiza un desplazamiento lógico de un bit hacia la izquierda e inserta data_in en
el bit menos significativo.
Puesto que la asignación a señales no tiene efecto inmediatamente, sino un
delta de tiempo posterior al tiempo simulado actual, esta operación de des-
plazamiento se ejecuta concurrentemente con la sentencia if que comprueba la
igualdad con B"0111_1110". Puesto que el valor de prev_data todavı́a no ha sido
actualizado en el momento en que se realiza la comparación, es necesario realizar
la comparación usando el valor de prev_data anterior al desplazamiento.
VeriBest VB99.0
A
A.1 Instalación
La versión de evaluación VB99.0 presenta la limitación siguiente: el modelo no
puede superar las 2000 lı́neas o las 2000 referencias a componentes. Para instalar
Veribest VB99.0, pueden seguirse los pasos siguientes:
1. Ejecute el fichero setup.exe, que se encuentra dentro del directorio VHDL Si-
mulator.
E E Y
0 Z
d y
1 d
a) b)
-------------------------------------------
-- Buffer triestado
library IEEE;
use IEEE.std_logic_1164.all;
--------------------------------------
-- Banco de pruebas
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity bp_Buffer_TriEstado is
end entity bp_Buffer_TriEstado;
begin
-- Instanciar y conectar UUT
uut : component Buffer_TriEstado port map
( E => E, d => d, y => y);
gen_vec_test : process
begin
E <= ’0’;
d <= ’0’;
wait for 5 ns;
d <= ’1’;
wait for 5 ns;
E <= ’1’;
wait for 10 ns;
d <= ’0’;
wait;
end process gen_vec_test;
end architecture bp_Buffer_TriEstado;
--------------------------------------
136 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
Tras seguir una de estas dos opciones, se mostrará una ventana (véase la
Figura A.2). Teclee en dicha ventana el nombre del espacio de trabajo, que en
este caso se ha llamado bufferTriestado.
1. Haga clic con el puntero del ratón sobre el botón “+”, situado en la esquina
superior derecha de la ventana del espacio de trabajo bufferTriestado.vpd.
Tras realizar este paso obtendrá una ventana para la selección de un fichero.
Seleccione el fichero bufferTriestado.vhd. La ventana principal del simulador tiene
que quedar tal y como se muestra en la Figura A.4.
138 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
Compile el fichero. Para ello seleccione el comando “Compile”, que está situado
en el menú “Workspace”.
El resultado de la compilación se muestra en la ventana de información,
situada en la parte inferior de la ventana principal. Observe que la ventana de
información contiene las tres pestañas siguientes:
3. Despliegue la carpeta “WORK” para visualizar los elementos sobre los que
se puede realizar una simulación. Obtendrá las interfaces (entity) y ar-
quitecturas (architecture) que ha programado en los pasos anteriores.
Para realizar la prueba de la puerta lógica debe seleccionar la arquitectura
BP BUFFER TRIESTADO (que es la que contiene la prueba) y la interfaz
que lleva asociada esa arquitectura (BP BUFFER TRIESTADO). Para
ello, seleccione la arquitectura BP BUFFER TRIESTADO de la interfaz
BP BUFFER TRIESTADO con el cursor del ratón (haga clic sobre ella)
y pulse el botón “Set”. Tras esta acción, los campos “Entity” y “Arch” se
rellenarán automáticamente con los nombres de la interfaz y de la arqui-
tectura. Por último, activamos la opción “Trace On” (que nos permite vi-
sualizar las formas de onda resultantes). Esto también se logra desplegando
Simulate→Trace.
Add signals
– “Clear all breakpoints”: nos permite eliminar todos los puntos de ruptura
que estaban introducidos.
– “New watch window”: abre una ventana que nos permite observar la evolu-
ción de las señales de forma numérica. Esta ventana, mostrada en la Figura
A.13, dispone de hasta 4 paneles de observación independientes (“Watch1”
a “Watch4”).
Para añadir a uno de los cuatro paneles los elementos a observar, pulse el
botón “Add Watch...” y obtendrá una ventana cuyo tı́tulo es “Add watch”
(véase la Figura A.13), en la que puede seleccionar tanto las señales de
forma independiente (se selecciona la señal y se pulsa el botón “Watch”),
como todas las señales de un elemento (se selecciona el componente o bloque
en la parte izquierda de la ventana y se pulsa el botón “Watch block”).
– “Show Breakpoints”: abre una ventana que tiene como tı́tulo “Breakpoints”,
en la que se muestran todos los puntos de ruptura existentes. En la ventana
“Breakpoints” existe un botón denominado “Condition...” Pulsando este
botón se abre una ventana, denominada “Source Breakpoint Condition”, en
la que puede establecer condiciones de activación para un punto de ruptura
determinado.
Desde la ventana “Source Breakpoint Condition” podrá indicar que el punto
de ruptura permanezca activo únicamente para una instancia o proceso
especı́fico. De esta forma, cuando se establecen condiciones, el simulador
se detiene únicamente en el punto de ruptura que hay dentro del proceso
especificado, no en todos los procesos en los que está el punto de ruptura.
– “Call stack”: nos permite conocer la próxima lı́nea de código VHDL que se
ejecutará cuando se continúe con la simulación. Si se realiza doble clic sobre
146 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
una de las entradas que aparecen en la “Call Stack”, se obtendrá una nueva
ventana en la que se muestra el código fuente VHDL que se indica en la
entrada que ha seleccionado.
En el caso de que el diseño que está ejecutando contenga subprogramas
anidados, en el momento en que se entre a ejecutar un subprograma, la ven-
tana “Call Stack” se incrementará con una nueva entrada correspondiente a
la llamada al subprograma. Cuando concluya la ejecución del subprograma,
la correspondiente entrada en la ventana será eliminada.
Step Continue
B.1 Instalación
El grupo Mentor Graphics, desarrollador de ModelSim, ofrece de manera gratuita
una versión de evaluación temporal (180 dı́as) del simulador. El simulador Model-
Sim es una herramienta muy completa y potente, de hecho varias herramientas
de sı́ntesis desarrolladas por fabricantes de circuitos FPGA ofrecen la posibilidad
de simular los modelos usando ModelSim.
Los pasos a seguir para la descarga e instalación se describen a continuación.
Durante todo el proceso debe disponerse de conexión a Internet.
http://www.model.com/resources/student edition/download.asp
E
E Y
0 Z
d y
1 d
a) b)
-------------------------------------------
-- Buffer triestado
library IEEE;
use IEEE.std_logic_1164.all;
begin
if (E = ’1’ ) then
y <= d ;
else
y <= ’Z’;
end if;
end process;
end architecture Behavioral;
-------------------------------------------
--------------------------------------
-- Banco de pruebas
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity bp_Buffer_TriEstado is
end entity bp_Buffer_TriEstado;
begin
-- Instanciar y conectar UUT
uut : component Buffer_TriEstado port map
( E => E, d => d, y => y);
gen_vec_test : process
begin
E <= ’0’;
d <= ’0’;
wait for 5 ns;
d <= ’1’;
wait for 5 ns;
150 A. Urquı́a, C. Martı́n Villalba Casos Prácticos de Diseño de Circuitos Digitales con VHDL
E <= ’1’;
wait for 10 ns;
d <= ’0’;
wait;
end process gen_vec_test;
end architecture bp_Buffer_TriEstado;
--------------------------------------
Menús
Iconos
Workspace
Transcript
Se abrirá entonces la ventana principal del entorno (véase la Figura B.2), que
cuenta con los elementos siguientes:
Apéndice B ModelSim PE Student Edition 151
Barra de menús
Barra de iconos
– Se abre una ventana de diálogo denominada “Add items to the Project”. Es-
ta ventana, que permite añadir elementos al proyecto, incluye las siguientes
opciones (véase la Figura B.4):
Apéndice B ModelSim PE Student Edition 153
Errores de compilación
A continuación, se describe qué ocurre cuando existen errores de compilación en
un fichero. Para ello vamos a modificar el fichero bufferTriestado.vhd. Introduci-
mos un error quitando el ; de la lı́nea 15 del fichero. Al guardar el fichero su nuevo
“status” es ?. Al compilar el fichero su “status” cambia a X (véase la Figura B.9).
También aparece un mensaje de error en color rojo en el panel “Transcript”.
El mensaje de error del panel “Transcript” nos informa de que existen errores
de compilación en el fichero bufferTriestado.vhd. Si hacemos doble clic con el ratón
sobre el mensaje de error se muestra una ventana de diálogo (véase la Figura B.9).
Dicha ventana contiene en color rojo un mensaje con información sobre el tipo de
error que se ha producido y el número de lı́nea en que aparece. Si hacemos doble
clic con el ratón sobre dicho mensaje se abre la ventana de edición con la lı́nea del
código que ha producido el error marcada en color naranja (véase la Figura B.9).
En este caso, la lı́nea 16 aparece en color naranja debido a que hemos eliminado
el ; que debiera haber al final de la lı́nea 15.
Tras seguir estos pasos, el panel “Workspace” queda tal como se muestra
en la Figura B.10. La columna “Status” del fichero bp bufferTriestado.vhd
tiene el icono ?, ya que aún no ha sido compilado. El fichero tiene el
número 1 en la columna “Order”. Esto indica que si usamos la opción de
compilación Compile → Compile All, el fichero bp bufferTriestado.vhd se
compilará después que el fichero bufferTriestado.vhd. Compile el fichero
bp bufferTriestado.vhd siguiendo algunas de las opciones descritas en la
sección B.3.4.
Existen ocasiones en que el orden de compilación de los ficheros puede
no ser el correcto en función de la estructura del código VHDL y de las
reglas que el lenguaje impone. Por ejemplo, considere el caso de que haya
un fichero llamado paquete.vhd donde se defina un paquete, y otro fichero,
denominado uso paquete.vhd, que use dicho paquete. El fichero paquete.vhd
ha de ser compilado antes que el fichero uso paquete.vhd. En caso contrario,
se produce un error de compilación.
Se puede modificar el orden de compilación del siguiente modo:
– Aparece el panel “Objects”. Este panel muestra las variables, registros, etc.,
su valor y sus caracterı́sticas.
a) b)
– Seleccionar todas las señales que queremos visualizar del panel “Objects”.
Arrastrar la selección con el ratón y llevarla hasta el panel “Wave”.
– Pulsar sobre el panel “Objects” con el botón derecho del ratón. En el menú
que aparece podemos realizar las dos siguiente acciones:
Caben destacar las siguientes caracterı́sticas del panel “Wave” (véase la Figu-
ra B.14):
Zoom In Zoom Out Zoom Full Zoom In Insert Delete Find Find Next
On Active cursor cursor Previous Transition
Cursor Transition
Restart Run Length Run Continue Run All Step Step Over
Run
Para modificar los puntos de ruptura podemos acceder a una ventana de diá-
logo denominada “Modify Breakpoints”. Para ello, seguimos los pasos siguientes:
– Hacemos clic con el botón derecho del ratón en el área del panel donde se
muestra el código de la unidad de diseño seleccionada.
– Hacemos doble clic sobre la unidad de diseño uut. Aparece ası́ un panel que
muestra el código del fichero bufferTriestado.vhd.
– Hacemos clic con el ratón a la izquierda del número de lı́nea 15. Aparecerá
un cı́rculo rojo indicando la existencia del punto de ruptura. Para poder
modificar el punto de ruptura podemos situarnos con el ratón sobre el cı́rculo
y hacer clic con el botón derecho. Se despliega un menú de texto que nos
permite deshabilitar el punto de ruptura (“Disable Breakpoint”) y quitar el
punto de ruptura (“Remove Breakpoint”).
Figura B.16: Inserción de puntos de ruptura.
Índice alfabético
Glitch, 39 de 1 bit, 61
Retardo, 38, 103
HDL, 2 de Transporte, 39
ventajas, 3 Inercial, 39
if, 55, 102 scan flip-flops, 14
Inicialización, 103 Sumador
Latch, 102 completo de 1 bit, 72
Ley de Moore, 1 de 4 bits, 77
Librerı́as VHDL, 37 SystemC, 4
IEEE.math real, 37 Sı́ntesis, 4
IEEE.numeric std, 37 de lógica secuencial, 102
IEEE.std logic 1164, 37 Tabla de transición de estados, 100
Literales, 31 Test, 12
Memoria Calidad, 14
de lectura y escritura, 79 Cobertura de fallos, 13
de sólo lectura, 78 Funcional, 14
Modelo de fallos, 13 Manufactura, 14
Multiplexor, 48 Modelo de fallos, 13
4:1, 54 Programa, 12
Máquina de estado finito, 99 Programa de test, 3
de Mealy, 99, 119 Vector, 12
de Moore, 99, 109 Vector de test, 3
método de diseño, 99 Tipo de datos
bit, 30
Netlist, 4 enumerado, 32
now, 32, 67 integer, 59
std logic, 30
Operadores, 35 string, 32
package, 37, 74, 85, 90, 110 time, 32
Palabras reservadas, 21 Unidad Aritmético Lógica, 82
Parametrización, 28 UUT (Unit Under Test), 16
Procedimiento, 44, 68
procedure, 106 Verificación
process, 23, 50, 55, 84, 104 de tiempos, 4
Puerto, 20 funcional, 4
in, 20 Verilog HDL, 3
inout, 20 VHDL, 2
out, 20 VHDL sintetizable, 20
Lee, S. (2006), Advanced Digital Logic Design: Using VDHL, State Machines and
Syntesis for FPGAs, Thomsom Canada Limited.
Salcic, Z. & Smailagic, A. (2000), Digital Systems Design and Prototyping, Kluwer
Academic Publishers.