Está en la página 1de 604

Los lenguajes para la descripción del hardware, tales como VHDL, juegan un papel fundamental en el ciclo de diseño de los

circuitos
digitales. Estos lenguajes facilitan la descripción del funcionamiento y la estructura de los circuitos, así como la codificación de sus
bancos de pruebas, que sirve como entrada para las herramientas software de simulación y síntesis.

En este texto se explican metodologías básicas para el diseño con VHDL de circuitos digitales combinacionales y secuenciales,
empleándose aquellas capacidades del lenguaje que son relevantes en el diseño para síntesis, así como en la programación de
bancos de pruebas. A lo largo del texto se muestran diferentes ejemplos de diseño y test de circuitos, y se plantean ejercicios prácticos,
proporcionándose en todos los casos el código VHDL completo, disponible también en el CD-ROM que acompaña al texto.

Alfonso Urquía Mora leda es licenciado en CC. Físicas por la Universidad Complutense de Madrid y doctor en CC. Físicas por la
UNED. Durante el periodo 1996-2001 ha trabajado como Ingeniero de I+D en la empresa AT&T Microelectrónica España (posteriormente
Lucent Technologies- Bell Labs y Agere Systems) en Tres Cantos (Madrid), puesto en el cual ha participado en numerosos proyectos
relacionados con la fabricación de circuitos integrados. Desde el año 1995 ha ocupado diferentes puestos docentes dentro del
Departamento de Informática y Automática de la UNED, en el cual actualmente es profesor titular de universidad.

Carla Martín Villalba se graduó en Ingeniería Electrónica por la Universidad Complutense de Madrid en 2001 y obtuvo su grado
de doctor en Informática con Mención Europea por la UNED en 2007. Desde el año 2004 ha ocupado diferentes puestos docentes
en el Departamento de Informática y Automática de la UNED. Desde 2010 es profesor contratado doctor y centra su labor investigadora
en el modelado, la simulación por ordenador y la enseñanza a distancia.

·¡ .LSBN: 978-84-362-6274-2
01201
colección
Editorial Grado
9 788436 262742

7101201 GR01A01

J
COLECCIÓN GRADO
Diseño y análisis
de circuitos digitales
con VHDL

ALFONSO URQUÍA MORALEDA


CARLA MARTÍN VILLALBA

UNIVERSIDAD NACIONAL DE EDUCACIÓN A DISTANCIA


DISEÑO Y ANALISIS DE CIRCUITOS DIGITALES CON VHDL
(71 01201 GR01A01)

Quedan rigurosamente prohibidas, sin la


autorización escrita de los titulares del
Copyright, bajo las sanciones establecidas
en las leyes, la reproducción total o
parcial de esta obra por cualquier medio
o procedimiento, comprendidos la reprografía
y el tratamiento informático, y la distribución
de ejemplares de ella mediante alquiler
o préstamos públicos.

© Universidad Nacional de Educación a Distancia


Madrid 2011

Librería UNED: el Bravo Murillo, 38- 28015 Madrid


Tels.: 91 398 75 601 73 73
e-mail: libreria@adm.uned.es

© Alfonso Urquía Moraleda y Carla Martín Villalba

Todas nuestras publicaciones han sido sometidas


a un sistema de evaluación antes de ser editadas

ISBN: 978-84-362-6274-2
Depósito legal: M. 33.404-2011

Primera edición: septiembre de 2011

Impreso en España - Printed in Spain


ÍNDICE

Prefacio 25

Organización de la Uni dad Didáctica 25

Cómo utilizar el libro . 26

Objetivos docentes 27

l. Fundamentos del diseño del hardware digital 29

1.1. Introducción . . . . . . . . . . . . . . 33

1.2. Lenguajes para la descripción de hardware 34

1.2.1. Usos de un programa HDL . . . 35

1.2.2. HDL más ampliamente usados . 35

1.3. Ciclo de diseño de los circuitos digitales . 36

1.4. Tecnologías de circuitos integrados .. 38

1.4.1. Clasificación de las tecnologías . 39


1.4.2. Comparación entre tecnologías . 42

1.5. Propiedades de los circuitos digitales 47


1.5.1. Retardo de los dispositivos 47
1.5.2. Ejecución concurrente 49

1.5.3. Diseños marginales .. 50

1.5.4. Fortaleza de las señales . 50

1.6. Test de los circuitos . . . . . 51

1.6.1. Test en manufactura 52

7
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

1.6.2. Test funcional . . . . .. 54

1.6.3. Programas de test funcional 55

1.6.4. Banco de pruebas . . . . 56

l. 7. Representaciones y niveles de abstracción . 57

l. 7.l. Representación del sistema . 57

1.7.2. Niveles de abstracción . . . 58


1.7.3. VHDL en el flujo de desarrollo . 63

1.8. Conceptos básicos a través de un ejemplo . 63


1.8.1. Comportamiento al nivel de funciones lógicas 64

1.8.2. Descripción de la estructura . . . . . . . . 70

1.8.3. Descripción abstracta del comportamiento 72

1.8.4. Banco de pruebas 76

1.8.5. Configuración .. 78

1.9. Dos simuladores de VHDL'93: VeriBest y ModelSim . 79

l. 9.l. Diseño de un buffer triestado 79

1.9.2. Diseño del banco de pruebas 80

1.10. Lecturas recomendadas . 82

1.11. Ejercicios de autocomprobación 83

1.12. Soluciones de los ejercicios 87

2. Conceptos básicos de VHDL 91


2.1. Introducción . . . . 95
2.2. Unidades de diseño 95

2.3. Entity . . . . . . . 97

2.3.1. Cláusula port 98

2.3.2. Cláusula generic . 100

2.3.3. Declaraciones 101

2.3.4. Sentencias . 101

8
ÍNDICE

2.3.5. Resumen de la sintaxis de la entity 101

2.4. Architecture . . . . . . . . 102

2.5. Asignaciones concurrentes 104

2.5.1. Asignaciones concurrentes simples . 104

2. 5. 2. Asignaciones concurrentes condicionales 107

2.5.3. Asignaciones concurrentes de selección . 110

2.5.4. Sensibilidad de las sentencias concurrentes 114

2.6. Sentencia generate . . . . . . . . . 115

2.6.1. Sentencia generate iterativa 115

2.6.2. Sentencia generate condicional . 116

2. 7. Bloque process . . . . 116

2.7.1. Sentencias wait 118

2. 7.2. Lista de sensibilidad 120

2. 8. Código secuencial . . . . . . 122

2.8.1. Asignación secuencial a una señal 122

2.8.2. Asignación secuencial a una variable 124

2.8.3. Sentencia if . . 124

2.8.4. Sentencia case . 128

2.8.5. Bucle for . . . . 132

2.9. Descripción de la estructura 135

2.9.1. Diseños con estructura regular . 139

2.10. Parametrización . . . . . . . . . . . . . 142

2.10.1. Parametrización del comportamiento 142

2.10.2. Parametrización de la estructura 142

2.11. Señales, variables y constantes 143

2.12. Tipos de datos y operadores . 145

2.12.1. Tipos predefinidos en VHDL . 146

9
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.12.2. Tipos del paquete IEEE.std_logic_1164 . . . . 149

2.12.3. Operadores sobre bit_vector y std_logic_vector 154

2.12.4. Tipos del paquete IEEE.numeric_std 156

2.12.5. Tipos time y string . . . . . . 163

2.12.6. Tipos definidos por el usuario 163

2.13. Atributos 166

2.14. Librerías 167

2.15. Assert . 169

2.16. Subprogramas 170

2.16.1. Funciones 170

2.16.2. Procedimientos 172

2.16.3. Diferencias entre funciones y procedimientos 175

2.17. Paquetes . . . . . . . . . 176

2.18. Lecturas recomendadas . 179

2.19. Ejercicios de autocomprobación 180

2.20. Soluciones de los ejercicios . 187

3. Simulación del código VHDL 201

3.1. Introducción . . . . . . . . . . 205

3.2. Procesamiento del código VHDL . . 206

3.3. Orden de compilación . . 207

3.4. Drivers . . . . . 208

3.5. Inicialización . 211

3.5.1. Ejemplo: señal con un driver . . 212

3.5.2. Ejemplo: señal con dos drivers . 213

3.6. Atributos de las señales . . 216

3.7. El retardo delta . . . . . . 219

3.8. Gestión de la cola de transacciones del driver . . 221

10
ÍNDICE

3.8.1. Ejemplo: simulación de formas de onda con retardo inercial .. 222

3.8.2. Ejemplo: simulación de formas de onda con retardo de transporte225

3.9. Ejemplo: simulación de un circuito sencillo 226

3.10. Lecturas recomendadas . . . . 230

3.11. Ejercicios de autocomprobación 231

3.12. Soluciones de los ejercicios .. 240

4. Diseño de lógica combinacional 273

4.1. Introducción . . ...... . 277

4.2. Diseño para síntesis de lógica combinacional 277

4.2.1. Empleo de sentencias concurrentes 278

4.2.2. Empleo de bloques process 280

4.3. Funciones lógicas . . . 280

4.3.1. Diseño del circuito 280

4.3.2. Programación del banco de pruebas 281

4.4. Multiplexor de 4 entradas . . . . 285

4.4.1. Diseño usando sentencias secuenciales . 285

4.4.2. Diseño usando sentencias concurrentes 286

4.5. Restador completo de 1 bit . . . . . 291

4.5.1. Descripción del comportamiento . 291

4.5.2. Descripción de la estructura 293

4.5.3. Programación del banco de pruebas 296

4.6. Sumador completo de 1 bit . 301

4.6.1. Diseño del circuito 302

4.6.2. Banco de pruebas 302

4. 7. U ni dad aritmético lógica 306

4.7.1. Diseño de la ALU . 306

4. 7.2. Programación del banco de pruebas 308

11
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4.8. Lecturas recomendadas . . . . . . 313


4.9. Ejercicios de autocomprobación 314

4.10. Soluciones de los ejercicios 321

5. Registros y memorias 353


5.1. Introducción . . . 357
5.2. Registro de 4 bits 357
5.2.1. Descripción del comportamiento . 358
5.2.2. Banco de pruebas 358
5.3. Registro multifunción .. 360
5.3.1. Descripción del comportamiento . 361

5.3.2. Banco de pruebas .. 364


5.4. Registro de desplazamiento . 368
5.4.1. Descripción del comportamiento . 368
5.4.2. Banco de pruebas . . . . . . . . . 369
5.4.3. Banco de pruebas con acceso a fichero 371

5.5. Register file . . . . . . . . 375


5.5.1. Registro triestado . 376
5.5.2. Descripción estructural del register file 378
5.5.3. Drivers y función de resolución 378
5.5.4. Banco de pruebas del register file 380
5.5.5. Descripción del comportamiento del register file 384
5.6. Bus bidireccional y memorias 386
5.6.1. Memoria de sólo lectura 386
5.6.2. Memoria de lectura y escritura 388
5.6.3. Bus bidireccional 389
5.7. Lecturas recomendadas . 391
5.8. Ejercicios de autocomprobación 392

12
ÍNDICE

5.9. Soluciones de los ejercicios .. . . . . . . . . . . . . . . . . . . . . . . 397

6. Diseño de lógica secuencial 415

6 .l. Introducción . . . . . . . . . 419

6.2. Diseño de máquinas de estado finito . . 419

6.2.1. Circuito detector de secuencias . 420

6. 3. Síntesis de lógica secuencial . . . . . . . 422

6.3.1. Sentencias condicionales incompletas . 423

6.3.2. Sentencias condicionales completas . 423

6.3.3. Retardos . . . . 423

6.3.4. Inicialización . 424

6.3.5. Bloques process . 424

6.4. Flip-flop JK . . . . . . . 425

6.4.1. Diseño del flip-flop . 426

6.4.2. Banco de pruebas . . 426

6.5. Máquinas de estado finito de Moore . . 430

6.5.1. Diseño de la máquina. . 430

6.5.2. Banco de pruebas . . . 433

6.5.3. Modelado estructural . 437

6.6. Máquinas de estado finito de Mealy . 439

6.6.1. Diseño de la máquina . . 439

6.6.2. Banco de pruebas . . . . 445

6. 7. Máquinas de estado finito seguras . 448

6.8. Lecturas recomendadas . . . . . . 451

6.9. Ejercicios de autocomprobación . 452

6.10. Soluciones de los ejercicios . . . . 463

7. Metodología de transferencia entre registros 513

13
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

7 .1. Introducción . . . . . . . . . . . . . . . 517

7.2. Operaciones de transferencia entre registros 518

7.2.1. Operación RT básica 518

7.2.2. Programa RT . . . . . 520

7.3. Máquinas de estado finito con camino de datos . . 522

7.3.1. Múltiples operaciones RT y camino de datos . 522

7.3.2. Lógica de control mediante FSM ... . 523

7.3.3. Diagrama de bloques básico de la FSMD . 523

7.4. Descripción del programa RT usando VHDL . 525

7.5. Circuito detector de secuencia . 528

7.6. Control de una máquina expendedora . . 530

7.6.1. Protocolo de handshaking . 531

7.6.2. Descripción del algoritmo . 532

7.6.3. Diseño del circuito de control . 532

7.6.4. Programación del banco de pruebas . 537

7. 7. Lecturas recomendadas . . . .. . 540

7.8. Ejercicios de autocomprobación . 541

7.9. Soluciones de los ejercicios . . . 545

APÉNDICES 561

A. VeriBest VB99.0 561

A.l. Instalación . . . 563

A.2. Edición y compilación de un modelo. . 563

A.2.1. Arranque del simulador VeriBest VHDL . 563

A.2.2. Creación de un espacio de trabajo . . 563

A.2.3. Edición de un fichero . . . . . . . . . 564

A.2.4. Añadir un fichero al espacio de trabajo . 565

14
ÍNDICE

A.2.5. Compilación de un fichero 566

A.2.6. Banco de pruebas . . . . . 569

A.3. Simulación y visualización de los resultados . 570

A.3.1. Establecer las condiciones de la simulación 570

A.3.2. Activación del simulador . . . . . . . . . . 571

A.3.3. Simulación y visualización de los resultados 571

A.4. Depurado usando el debugger . . . . . . . . . . . . 574

B. ModelSim PE Student Edition 577


B .l. Instalación . . . . . . . . . . . 579

B.2. Edición y compilación de un modelo. 579

B.2.1. Arranque del simulador . 580

B.2.2. Creación de un proyecto 581

B.2.3. Añadir ficheros al proyecto . 582

B.2.4. Compilación de los ficheros . 586

B.2.5. Banco de pruebas . . . . .. 588

B.3. Simulación, visualización y depurado 591

B.3.1. Activación del modo simulación 591

B.3.2. Visualización de los resultados . 593

B.3.3. Ejecución de la simulación . . . 594

B.3.4. Inserción de puntos de ruptura 595

15
CÓDIGO VHDL

1.1. Entity del circuito detector de paridad. . . . . . . . . . . . . . . . . 66


1.2. Architecture del detector de paridad describiendo el comportamien-
to mediante la función lógica. . . . . . . . . . . . . . . . . . . . . . . 66
1.3. Architecture del detector de paridad describiendo el comportamien-
to mediante la función lógica xor. . . . . . . . . . . . . . . . . . . . . 69
1.4. Puerta inversora. Puerta XOR con dos entradas. Architecture del
detector de paridad describiendo la estructura del circuito. . . . . . . 71
1.5. Architecture del detector de paridad descrita mediante una red XOR. 74
1.6. Architecture del detector de paridad descrita mediante un algoritmo. 75
1.7. Banco de pruebas del detector de paridad. . . . . . . . . . . . . . . . 77
1.8. Configuration para la simulación del banco de pruebas del detector
de paridad. . . . . . . . . . . . . . . . 78
1.9. Buffer triestado. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
1.10. Banco de pruebas del buffer triestado. . . . . . . . . . . . . . . . . . . 81
1.11. Diseño del circuito de control de la alarma de seguridad de un coche. 86
1.12. Diseño alternativo del circuito de control de la alarma de seguridad
de un coche. . . . . . . . . . . . . . . . . . . . . . . . . . 86
2.1. Circuito detector de paridad. . . . . . . . . . . . . . . . . . . 96
2.2. Código incorrecto, que produce un error de compilación. . . 99
2.3. Descripción correcta del circuito mostrado en la Figura 2.3. . 100
2.4. Multiplexor de 4 entradas de 8 bits. . 107
2.5. Decodificador binario de 2 entradas. . 108
2.6. Codificador 4 a 2 con prioridad. . . . 108
2.7. Multiplexor de 4 entradas de 8 bits. . 111
2.8. Decodificador binario de 2 entradas. . 112
2.9. Codificador 4 a 2 con prioridad. . . . 112
2.10. Biestable D con reset asíncrono activado al nivel LOW. 121
2.11. Multiplexor de 4 entradas de 8 bits. . 125
2.12. Decodificador binario de 2 entradas. . 126
2.13. Codificador 4 a 2 con prioridad. . . 126
2.14. Multiplexor de 4 entradas de 8 bits. . 129

17
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.15. Decodificador binario de 2 entradas. . . 130


2.16. Codificador 4 a 2 con prioridad . . . . . 130
2.17. XOR bit a bit de dos señales de 4 bits. 133
2.18. XOR de los bits de una señal de 4 bits. 134
2.19. Descripción estructural al nivel de puertas lógicas de un multiplexor
de dos señales de un bit. . . . . . . . . . . . . . . . . . . . . . . 137
2.20. Descripción estructural de un multiplexor de 2 señales de 4 bit. 138
2.21. Array de 8 puertas AND. . . . . . . . . . . . . . . . . . . . . . . 140
2.22. Detector de paridad de 8 bits. . . . . . . . . . . . . . . . . . . . 141
2.23. La función conv_integer convierte un parámetro del tipo std_logic_vector
a un entero. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
2.24. Procedimiento que devuelve dos parámetros de entrada ordenados. . 175
2.25. Definición de una función en un package. . 178
2.26. Uso de una función definida en un package. . . . . . . . . . 178
2.27. Diseño correspondiente al Ejercicio 2.3. . . . . . . . . . . . . 181
2.28. Diseño y banco de pruebas correspondientes al Ejercicio 2.1. 188
2.29. Diseño correspondiente al Ejercicio 2.2. . 189
2.30. Diseño del circuito "one-shof'. . . . . . . . . . . . . 191
2.31. Banco de pruebas del circuito "one-shof'. . . . . . . 192
2.32. Diseño de un decodificador 2:4 con entrada enable. . 193
2.33. Banco de pruebas de un decodificador 2:4 con entrada enable. 194
3.1. Código correspondiente al Ejercicio 3.1. 231
3.2. Código correspondiente al Ejercicio 3.2. 232
3.3. Diseño del Ejercicio 3.3. . . . . . . 232
3.4. Banco de pruebas del Ejercicio 3.3. 233
3.5. Diseño del Ejercicio 3.4. . . . . . . 234
3.6. Banco de pruebas del Ejercicio 3.4. 235
3. 7. Diseño correspondiente al Ejercicio 3.5. 236
3.8. Banco de pruebas correspondiente al Ejercicio 3.5. 237
3.9. Puerta NAND con retardo inercial y su banco de pruebas. 238
3.10. Diseño del Ejercicio 3.7. . . . . . . . . . . . . . . . . . . . 239
4.1. Diseño mediante la descripción de las funciones lógicas. . . 281
4.2. Banco de pruebas del circuito que implementa las dos funciones lógicas.282
4.3. Diseño de un MUX 4:1 mediante una sentencia if. . . . . 286
4.4. Descripción del MUX 4:1 mediante sentencias if y case. 287
4.5. Banco de pruebas del MUX 4: l. . . . . . . . . . . . . . . 288
4.6. Descripción errónea de la architecture del MUX 4:1. . . 289
4.7. Diseño de un MUX 4:1 mediante una sentencia concurrente. 290
4.8. Diseño de un MUX 4:1 mediante dos sentencias concurrentes. 290

18
CÓDIGO VHDL

4.9. Descripción del comportamiento de un restador completo de un bit. 292


4.10. Diseño de las puertas lógicas XOR2, NOT1, AND2 y OR3. . . . 294
4.11. Descripción de la estructura de un restador completo de un bit. . . 295
4.12. Banco de pruebas del restador completo de un bit. . . . . . . . . . . 297
4.13. Banco de pruebas del restador completo de un bit usando un proce-
dimiento. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
4.14. Banco de pruebas del restador completo de un bit usando una función.300
4.15. Diseño de las puertas lógicas AND2, OR3 y XOR2 con retardo. 303
4.16. Package con los componentes del sumador y diseño del sumador. . . 304
4.17. Banco de pruebas del sumador completo . . . . . . . . . . . . . . . . . 305
4.18. U so de package para la definición de constantes, y diseño de la AL U
mediante una asignación concurrente y un bloque process. . . . . . . 307
4.19. Package en el cual se definen las constantes usadas en el banco de
pruebas de la AL U y comienzo de la definición del banco de pruebas
de la ALU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
4.20. Fragmento del banco de pruebas de la ALU: definición del procedure
check_ALU. . . . . . . . . . . . . . . . . . . . . . . . . . . . 310
4.21. Fragmento de la definición del banco de pruebas de la ALU. 311
4.22. Parte final de la definición del banco de pruebas de la ALU. 312
4.23. Diseño de un codificador 4:2 con prioridad. . . . . . . . . . . 321
4.24. Parte inicial del banco de pruebas de un codificador 4:2 con prioridad. 322
4.25. Parte final del banco de pruebas de un codificador 4:2 con prioridad .. 323
4.26. Diseño del circuito comparador de 4 bit para X<5. 324
4.27. Banco de pruebas del circuito comparador de 4 bit para X<5. . . . . 325
4.28. Decodificador BCD a 7 segmentos descrito empleando una sentencia
case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
4.29. Banco de pruebas del decodificador BCD . . . . . . . . . . . . . . . . . 327
4.30. Decodificador BCD descrito empleando una sentencia if. . . . . . . . 328
4.31. Decodificador BCD descrito empleando una sentencia de asignación
concurrente condicional. . . . . . . . . . . . . . . . . . . . . . . . . 329
4.32. Decodificador BCD descrito empleando una sentencia with select. 330
4.33. Diseño del sumador de N bits. . . . . . . . . . . . . . . . 331
4.34. Parte inicial del banco de pruebas del sumador de 4 bits. 332
4.35. Parte final del banco de pruebas del sumador de 4 bits. . 333
4.36. Diseño del circuito desplazador. . . . . . . . . . . . . . . 334
4.37. Primera parte del banco de pruebas del circuito desplazador. 335
4.38. Segunda parte del banco de pruebas del circuito desplazador. 336
4.39. Diseño del circuito comparador de igualdad de dos números de 1 bit
y del circuito comparador de igualdad de dos números de N bits. 337

19
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4.40. Banco de pruebas del circuito comparador de igualdad de 4 bits . . . . 338


4.41. Diseño de la ALU cuyo circuito se muestra en la Figura 4.12 . . . . . . 340
4.42. Package en el cual se definen las constantes usadas en el banco
de pruebas de la ALU cuyo circuito se muestra en la Figura 4.12
y comienzo de la definición del banco de pruebas de la ALU. . . . . . 341
4.43. Fragmento del banco de pruebas de la ALU cuyo circuito se muestra
en la Figura 4.12: primera parte de la definición del procedure
check_AL U. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
4.44. Fragmento de la definición del banco de pruebas de la AL U cuyo
circuito se muestra en la Figura 4.12. . . . . . . . . . . . . . . 343
4.45. Parte final de la definición del banco de pruebas de la ALU cuyo
circuito se muestra en la Figura 4.12. . . . . . . . . . . . . . . 344
4.46. Diseño de una puerta NOT de 1 entrada y de una puerta AND de 4
entradas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
4.47. Diseño del decodificador 3 a 8. . . . . . . . . . . . . . . . . . . . 348
4.48. Fragmento inicial del banco de pruebas del decodificador 3 a 8. . 348
4.49. Fragmento final del banco de pruebas del decodificador 3 a 8. . . 349
4.50. Diseño del conversor de código binario a código Gray, empleando un
bloque process con una sentencia case. . . . . . . . . . . . . . . . . 350
4.51. Diseño del conversor de código binario a código Gray, empleando una
asignación concurrente de selección (with- select) . . . . . . . . . . . 351
4.52. Diseño del conversor de código binario a código Gray, describiendo la
estructura del circuito al nivel de puertas lógicas. . . . . . . . . 351
4.53. Banco de pruebas del conversor de código binario a código Gray. 352
5.1. Diseño de un registro de 4 bits con reset síncrono. . . . . . . 358
5.2. Banco de pruebas de un registro de 4 bits con reset síncrono. 359
5.3. Diseño de un registro multifunción de 4 bits. . . . . . . . . . 362
5.4. Banco de pruebas de un registro multifunción de 4 bits. . . . 365
5.5. Continuación del banco de pruebas de un registro multifunción de 4
bits. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
5.6. Parte final del banco de pruebas de un registro multifunción de 4 bits. 367
5.7. Diseño de un registro de desplazamiento de 32 bits. . . . . . 369
5.8. Banco de pruebas del registro de desplazamiento de 32 bits. . 370
5.9. Banco de pruebas del registro con acceso a fichero. . . 373
5.10. Diseño de un registro triestado. . . . . . . . . . . . . . 377
5.11. Diseño estructural del register file. . . . . . . . . . . . . 379
5.12. Banco de pruebas del register file, con acceso a fichero. 381
5.13. Continuación del banco de pruebas del register file. . . 382
5.14. Diseño del register file mediante la descripción del comportamiento. 385

20
CÓDIGO VHDL

5.15. Memoria de sólo lectura. . . . . . . . . . . . . . . . . . . 387


5.16. Memoria de lectura y escritura. . . . . . . . . . . . . . . 388
5.17. Bus bidireccional (continúa en el Código VHDL 5.18). . . 390
5.18. Bus bidireccional (continuación del Código VHDL 5.17). . 391
5.19. Diseño de un registro de desplazamiento de 4 bits. . . . . . 397
5.20. Otro diseño de un registro de desplazamiento de 4 bits. . . 398
5.21. Diseño erróneo de un registro de desplazamiento de 4 bits. . . 398
5.22. Banco de pruebas de un registro de desplazamiento de 4 bits con
entrada y salida serie. . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
5.23. Diseño de un registro de desplazamiento de N bits con entrada y
salida serie. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 400
5.24. Diseño del registro serie-a-paralelo y paralelo-a-serie de 4 bits. . . . . 401
5.25. Parte inicial del banco de pruebas para el registro serie-a-paralelo y
paralelo-a-serie de 4 bits. . . . . . . . . . . . . . . . . . . . . . . . . . 402
5.26. Parte final del banco de pruebas para el registro serie-a-paralelo y
paralelo-a-serie de 4 bits. . . . . . . . . . . . . . . . . . . . . . . . . . 403
5.27. Diseño del circuito ALU y registro, mostrado en la Figura 5.15. . .. 405
5.28. Package en el cual se definen las constantes y comienzo del banco de
pruebas de ALU+registro. . . . . . . . . . . . . . . . . . . . . . . . . 406
5.29. Fragmento del banco de pruebas de ALU+registro: procedure che-
ck_ALU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
5.30. Fragmento de la definición del banco de pruebas de ALU+registro ... 408
5.31. Parte final de la definición del banco de pruebas de ALU+registro ... 409
5.32. Diseño de la ROM. . . . . . . . 410
5.33. Banco de pruebas de la ROM. . 411
5.34. Diseño de la RAM. . . . . . . . 412
5.35. Banco de pruebas de la RAM. . 413
6.1. Diseño de un fiip-fiop JK con reset asíncrono. . 427
6.2. Comienzo del banco de pruebas de un fiip-fiop JK .. . 428
6.3. Continuación del banco de pruebas de un fiip-fiop JK .. . 429
6.4. Definición del package con la codificación de los estados y parte
inicial del diseño de la máquina de Moore de la Figura 6. 7. . . . . . 432
6.5. Continuación del diseño de la máquina de Moore de la Figura 6. 7. . . 433
6.6. Banco de pruebas de la máquina de Moore de la Figura 6. 7. . . . . . 435
6.7. Continuación del banco de pruebas de la máquina de Moore de la
Figura 6. 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
6.8. Diseño estructural de la máquina de Moore. . . . . . . . . . . . . . . 438
6.9. Package con la codificación de los estados y diseño de la máquina de
Mealy de la Figura 6.11. . . . . . . . . . . . . . . . . . . . . . . . . . 441

21
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

6.10. Continuación del diseño de la máquina de Mealy de la Figura 6.11. . 442


6.11. Diseño de la máquina de Mealy de la Figura 6.11. La salida se obtiene
de un circuito combinacional y se hace pasar por un flip-flop D. El
bloque process para la obtención del próximo estado es igual al
mostrado en el Código VHDL 6.10 . . . . . . . . . . . . . . . . . . . 443
6.12. Banco de pruebas que introduce algunos vectores de test en la má-
quina de Mealy de la Figura 6.11. . . . . . . . . . . . . . . . . 444
6.13. Banco de pruebas de la máquina de Mealy de la Figura 6.11. . 446
6.14. Parte final del banco de pruebas de la máquina de Mealy. . 447
6.15. Diseño de una FSM segura. . 450
6.16. Diseño de un latch D. . . . . . . 463
6.17. Banco de pruebas dellatch D. . 464
6.18. Diseño de un flip-flop RS. . 465
6.19. Parte inicial del banco de pruebas de un flip-flop RS. . 466
6.20. Parte final del banco de pruebas de un flip-flop RS. . . 467
6.21. Diseño de un flip-flop D con señales enable, set y clear. . 468
6.22. Banco de pruebas de un flip-flop D. . . . . . . . . . . . . 469
6.23. Package en el cual se definen las constantes del diseño del contador
ascendente módulo 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
6.24. Diseño de un contador ascendente módulo 4. . . . . . . . . . . . . . . 471
6.25. Parte inicial del banco de pruebas del contador ascendente módulo 4. 472
6.26. Parte final del banco de pruebas del contador ascendente módulo 4. . 473
6.27. Diseño estructural del contador ascendente módulo 4. . 476
6.28. Diseño del generador de señal. . . . . . . . . . . . . 477
6.29. Banco de pruebas del circuito generador de señal. . 478
6.30. Diseño del divisor de frecuencias por 3. . . . . . . . 480
6.31. Banco de pruebas del divisor de frecuencias por 3. . 481
6.32. Fragmento inicial del diseño del circuito especificado en el Ejercicio 6.9.483
6.33. Fragmento final del diseño del circuito especificado en el Ejercicio 6.9. 484
6.34. Banco de pruebas del diseño del circuito especificado en el Ejercicio
6.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
6.35. Diseño del detector de una secuencia 3 unos o más consecutivos . . . . 486
6.36. Diseño del banco de pruebas del detector de una secuencia 3 unos o
más consecutivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
6.37. Continuación del diseño del banco de pruebas del detector de una
secuencia 3 unos o más consecutivos. . . . . . . . 488
6.38. Diseño del contador BCD. . . . . . . . . . . . . . . . . . . . . . . . 490
6.39. Diseño del banco de pruebas del contador BCD. . . . . . . . . . . . 491
6.40. Continuación del diseño del banco de pruebas del contador BCD. . 492

22
CÓDIGO VHDL

6.41. Diseño del detector de la secuencia "1011". . . . . . . . . . . . . 494


6.42. Continuación del diseño del detector de la secuencia "1011". . . . 495
6.43. Diseño del banco de pruebas del detector de la secuencia "1011". 496
6.44. Continuación del diseño del banco de pruebas del detector de la
secuencia "1011". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
6.45. Diseño del contador binario ascendente y descendente de 4 bits. . .. 498
6.46. Diseño del banco de pruebas del contador binario ascendente y des-
cendente de 4 bits. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 499
6.47. Continuación del diseño del banco de pruebas del contador binario
ascendente y descendente de 4 bits. . . . . . . . . . . . . . . . . . . . 500
6.48. Package con la definición de las constantes y parte inicial del diseño
del controlador de dos semáforos. . . . . . . . . . . . . 501
6.49. Parte final del diseño del controlador de dos semáforos. 502
6.50. Parte inicial del banco de pruebas del controlador. .. . 503
6.51. Parte final del banco de pruebas del controlador . . . . . 504
6.52. Package con la definición de las constantes y parte inicial del diseño
del controlador del microondas. . . . . . . . . . . . . . . 506
6.53. Continuación del diseño del controlador del microondas. . . . 507
6.54. Parte final del diseño del controlador del microondas. . . . . 508
6.55. Banco de pruebas del diseño del controlador del microondas. 510
6.56. Continuación del banco de pruebas del controlador del microondas. 511
6.57. Parte final del banco de pruebas del controlador de microondas. 512
7.1. Codificación en VHDL de un algoritmo RT. . . . . . . . . . . . . . 527
7.2. Dos diseños de un circuito detector de la secuencia 0111 1110. . . . 529
7.3. Package con la definición de las constantes del circuito de la máquina
expendedora. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534
7.4. Entity y comienzo de la architecture del circuito de control de la
máquina expendedora. . . . . . . . . . . . . . . . . . . . . . . . . . . 535
7.5. Continuación del diseño del circuito de control de la máquina expen-
dedora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
7.6. Banco de pruebas del circuito de control de la máquina expendedora. 538
7. 7. Continuación del banco de pruebas del circuito de la máquina expen-
dedora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
7.8. Diseño del circuito que calcula el máximo común divisor de dos números.547
7.9. Banco de pruebas del circuito que calcula el máximo común divisor
de dos números . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 548
7.10. Diseño del circuito que calcula la media de 4 números de 4 bits. . .. 550
7.11. Banco de pruebas del diseño del circuito que calcula la media de 4
números de 4 bits. 551

23
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

7.12. Package con la definición de constantes y diseño del conversor de


código BCD a binario. . . . . . . . . . . . . . . . . . . . . . . . . 553
7.13. Parte inicial del banco de pruebas del conversor de código BCD a
binario. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554
7.14. Parte final del banco de pruebas del conversor de código BCD a binario.555
7.15. Package con la definición de las constantes globales y entity del
circuito exponenciador. . . . . . . . . . . . . . . . . . . . . 556
7.16. Diseño del circuito exponenciador. . . . . . . . . . . . . . . . 557
7.17. Principio del banco de pruebas del circuito exponenciador. . 558
7.18. Parte final del banco de pruebas del circuito exponenciador. 559

24
PREFACIO

ORGANIZACIÓN DE LA UNIDAD DIDÁCTICA

La presente Unidad Didáctica está estructurada en siete temas y dos apéndices,


y está acompañada de un CD-ROM.

El Tema 1 tiene carácter introductorio. En él se describen conceptos básicos,


tales como el ciclo de diseño del hardware digital y el papel que en él desempeñan los
lenguajes para la descripción del hardware, las diferentes representaciones y niveles
de abstracción en la descripción de los circuitos digitales, conceptos básicos del test
de los circuitos digitales, de las tecnologías empleadas para la implementación de
dichos circuitos, etc.

Asimismo, en el Tema 1 se desarrolla un ejemplo completo de diseño de un


sistema digital sencillo, mediante diferentes representaciones y niveles de abstracción,
empleando el lenguaje para la descripción del hardware que se explica en esta Unidad
Didáctica: VHDL'93. Finalmente, se sugiere al alumno que instale en su propio
ordenador algún simulador de VHDL'93, proporcionándole guía en la instalación
y manejo de dos simuladores que en su versión de estudiante están disponibles
gratuitamente: VeriBest y ModelSim. A ello están dedicados los Apéndices A y B,
respectivamente.

En el Tema 2 se explica e ilustra mediante ejemplos el empleo de un pequeño


subconjunto de las estructuras y capacidades del lenguaje VHDL'93: aquel que puede
ser usado para crear diseños sintetizables. Esto es, código VHDL'93 a partir del cual
las herramientas de CAD puedan generar automáticamente circuitos hardware que
funcionen. Asimismo, se describen algunas capacidades de VHDL'93 que resultan
útiles para la programación de los bancos de pruebas.

En el Tema 3 se explican los conceptos básicos de la simulación del código


VHDL. El Tema 4 está dedicado al diseño para síntesis de circuitos digitales
combinacionales y a la programación de bancos de pruebas para testear estos diseños.

25
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

En los Temas 5 y 6 se explica el diseño y prueba de circuitos secuenciales. El


Tema 5 está dedicado a los registros y memorias, y el Tema 6 a las máquinas de
estado finito. Se estudia el diseño de dos tipos de máquinas: de Mealy y de Moore.

Finalmente, el Tema 7 está dedicado al diseño de circuitos empleando la metodo-


logía de transferencia entre registros, cuya aplicación resulta idónea en aquellos casos
en los cuales el comportamiento del circuito viene descrito mediante un algoritmo.
Todo ello se realiza empleando VHDL'93.

La Unidad Didáctica está acompañada de un CD-ROM, en el cual se encuentra


el código VHDL de todos los diseños y bancos de pruebas explicados en los temas,
así como el código VHDL que forma parte de los enunciados de los ejercicios de
autocomprobación y de sus soluciones. Igualmente, en el CD se encuentra la versión
de estudiante del entorno de simulación VeriBest.

CÓMO UTILIZAR EL LIBRO

Es recomendable seguir el orden siguiente en el estudio de los temas. En primer


lugar, debería estudiarse el Tema 1, ya que los conceptos expuestos en este tema
sirven de base para la comprensión de los siguientes.

Al finalizar el estudio del Tema 1, el alumno debería tener instalado en su propio


ordenador algún entorno de simulación de VHDL'93 y debería saber emplearlo para
editar, simular y depurar código VHDL, así como para visualizar los resultados de la
simulación. En los Apéndices A y B se dan algunas instrucciones para la instalación
y el manejo de dos simuladores: VeriBest y ModelSim. Los ficheros de instalación de
VeriBest se encuentran en el CD distribuido junto con esta Unidad Didáctica.

El código VHDL descrito en las Secciones 1.9.1 y 1.9.2, consistente en el diseño de


un buffer triestado y su banco de pruebas, puede ser usado para realizar las primeras
pruebas y aprender el manejo del entorno de simulación escogido.

A continuación, debería estudiarse el Tema 2, en el cual se explican los fundamen-


tos básicos de VHDL y se muestran múltiples ejemplos de diseños de circuitos, cuya
finalidad es ilustrar el empleo de diferentes recursos del lenguaje VHDL'93. Puesto
que se muestran los diseños de los circuitos, pero no los bancos de pruebas que
ejercitan sus entradas, los ejemplos de este tema no están listos para ser simulados,
y por ello este tema puede estudiarse sin necesidad de emplear el ordenador. En
los ejercicios del Tema 2 sí se propone la programación de algún pequeño diseño y
banco de pruebas, con lo cual sí es conveniente disponer de ordenador para realizar
algunos de los ejercicios del Tema 2.

26
PREFACIO

Por regla general, los ejemplos mostrados en los Temas 3 a 7 están completamente
desarrollados. Es decir, cada diseño está acompañado de su banco de pruebas. Es
muy recomendable que el alumno realice las simulaciones de estos diseños por sí
mismo, familiarizándose de esta forma con el manejo del entorno de simulación y
con la interpretación de los resultados de las simulaciones.

Como actividad complementaria se sugiere al alumno que introduzca variaciones


en los diseños y en los bancos de pruebas propuestos en la parte teórica de los temas,
realizando por sí mismo las simulaciones y la interpretación de los resultados.

Al final de cada tema se plantean ejercicios de autocomprobación y se explican


sus soluciones. La forma en que se deberían trabajar los ejercicios es la siguiente. En
primer lugar, el alumno debería estudiar la parte de teoría del tema. A continuación,
debería intentar resolver por sí mismo los ejercicios de ese tema, sin consultar para
ello la parte de teoría. Una vez el alumno ha desarrollado su solución al ejercicio,
debería compararla con la solución propuesta en la Unidad Didáctica.

OBJETIVOS DOCENTES

Como objetivos docentes fundamentales, con esta Unidad Didáctica se pretende


que el alumno adquiera las capacidades siguientes:

l. Discutir las diferentes etapas del ciclo de diseño de circuitos digitales y el uso
de los lenguajes para la descripción del hardware (HDL) en cada una de ellas.

2. Discutir qué características fundamentales deben tener los HDL para poder
describir circuitos digitales y qué características fundamentales deben tener
los entornos de simulación que soportan este tipo de lenguajes.

3. Aplicar el lenguaje VHDL al diseño de circuitos digitales combinacionales y


secuenciales empleando los tipos de datos, operadores y otras capacidades de
VHDL que deben ser usados para crear código sintetizable.

4. Aplicar el lenguaje VHDL a la programación de bancos de prueba para testear


los circuitos diseñados.

Al comienzo de cada tema se indican los objetivos docentes que deben alcan-
zarse una vez completado su estudio y realizados los ejercicios prácticos. Un buen
procedimiento de autoevaluación consiste en repasar los objetivos docentes una vez
completado el estudio del tema, analizando en cada caso si se ha alcanzado o no el
objetivo.

27
TEMA 1

FUNDAMENTOS DEL DISENO DEL


HARDWARE DIGITAL

1.1. Introducción
1.2. Lenguajes para la descripción de hardware
1.3. Ciclo de diseño de los circuitos digitales
1.4. Tecnologías de circuitos integrados
1.5. Propiedades de los circuitos digitales
1.6. Test de los circuitos
l. 7. Representaciones y niveles de abstracción
1.8. Conceptos básicos a través de un ejemplo
1.9. Dos simuladores de VHDL'93: VeriBest y ModelSim
1.10. Lecturas recomendadas
1.11. Ejercicios de autocomprobación
1.12. Soluciones de los ejercicios
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

OBJETIVOS DOCENTES

Una vez estudiado el contenido del tema y realizados los ejercicios prácticos,
debería saber:

- Discutir la finalidad de los lenguajes para la descripción del hardware (HDL)


y algunas de las principales ventajas que presenta su uso.

- Discutir el ciclo de diseño del hardware digital y el papel que desempeñan en


el ciclo de diseño los HDL.

- Discutir y comparar las características de las siguientes tecnologías de fabrica-


ción de circuitos integrados: full-custom ASIC, standard cell ASIC, gate array
ASIC, dispositivos programables en campo (FPGA, CPLD, PROM, PAL y
PLA), y componentes estándar de pequeño y medio tamaño.

- Discutir las siguientes propiedades de los circuitos digitales: el retardo de


los dispositivos, su ejecución concurrente, la marginalidad en el diseño y la
fortaleza de las señales.

- Discutir el propósito y los fundamentos del test en diseño y manufactura, así


como los conceptos: modelo de fallos, cobertura del test y calidad del test.

- Discutir la utilidad y composición de los bancos de pruebas.

- Discutir y comparar los niveles de abstracción y representación de los sistemas


digitales.

- Instalar en su propio ordenador y realizar las operaciones básicas de manejo


de algún entorno de simulación de VHDL'93 de su elección. Estas operaciones
básicas incluyen al menos la edición de modelos VHDL, su depurado usando
el debugger, su simulación y la visualización de los resultados.

31
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

1.1. INTRODUCCIÓN

Los sistemas digitales se han ido haciendo más y más complejos durante las pasa-
das décadas. Este incremento en la complejidad responde, a grandes rasgos, a la Ley
de Moore, según la cual el avance tecnológico posibilita que cada aproximadamente
18 meses se doble el número de transistores que es posible alojar en un circuito
integrado.

De esta forma, en la década de 1970 un circuito integrado típico contenía decenas


de miles de transistores. En la década de 1980, la capacidad aumentó a cientos de
miles de transistores, y en la década de 1990 fue del orden de decenas de millones.
En la década de 2000, la capacidad de los circuitos integrados es del orden de miles
de millones de transistores.

Cuando se fabricaba un circuito integrado en la década de 1970, se documentaba


su funcionamiento empleando una combinación de esquemáticos (representación grá-
fica de los componentes del circuito), diagramas de transición de estados y lenguaje
natural (por ejemplo, inglés). Esta documentación podía consistir en varios cientos
de páginas. Los ingenieros, que compraban el circuito integrado para usarlo en sus
propios diseños, tenían que leer esta documentación para entender el funcionamiento
del circuito integrado. Como puede imaginarse, leer cientos de páginas no era tarea
fácil. Además, en ocasiones la documentación contenía errores o ambigüedades. La
consecuencia de ello era que frecuentemente los ingenieros tenían problemas para
emplear los circuitos integrados en el desarrollo de sus propios sistemas.

Debido a esta situación, el Departamento de Defensa de EE.UU. buscó un proce-


dimiento mediante el cual los fabricantes de circuitos integrados pudieran especificar
de forma precisa el funcionamiento de los circuitos. Con esta motivación, el Departa-
mento de Defensa de EE.UU. inició el desarrollo de un lenguaje para la descripción
del hardware, para lo cual estableció un grupo de trabajo compuesto por expertos
de varias disciplinas, pertenecientes a diferentes compañías.

Un lenguaje para la descripción del hardware o HDL (siglas que provienen del in-
glés: Hardware Description Language) es un lenguaje, legible tanto por las máquinas
como por los seres humanos, ideado para describir tanto el comportamiento como
la estructura del hardware. El HDL permite describir de forma precisa y rigurosa
el funcionamiento del circuito digital, el cual puede ser simulado en un ordenador
con el fin de reproducir exactamente el funcionamiento del circuito. La simulación
por ordenador permite obtener el valor de las señales de salida del circuito para una
determinada secuencia de señales de entrada.

33
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

El HDL que el Departamento de Defensa de EE.UU. creó en los años 80 se llamó


VHDL. Las siglas VHDL provienen de VHSIC Hardware Description L.anguage.
VHSIC es un acrónimo de Very High Speed Integrated Circuit, que fue el nombre
del proyecto llevado a cabo por el Departamento de Defensa de EE.UU.

La sintaxis de VHDL es muy similar a la del lenguaje de programación ADA.


En 1987, el Institute of Electrical and Electronics Engineers (IEEE) adoptó VHDL
como el estándar número 1076. El establecimiento de un estándar del lenguaje tiene
una ventaja fundamental: las compañías desarrolladoras de software de simulación
tienen una definición claramente establecida del lenguaje al que deben dar soporte.

1.2. LENGUAJES PARA LA DESCRIPCIÓN DE HARDWARE

En la actualidad, la casi totalidad de los diseñadores de circuitos digitales de


cierta complejidad usan para realizar sus diseños lenguajes para la descripción del
hardware. El empleo de HDL presenta ventajas respecto al empleo de descripciones
basadas en esquemáticos. Algunas de ellas son las siguientes:

l. Puesto que una descripción HDL es simplemente un fichero de texto, es mucho


más portable que un diseño esquemático, que debe ser visualizado y editado
empleando la herramienta gráfica específica del entorno de CAD ( Computer-
Aided Design- Diseño asistido por ordenador) con el que se ha creado.

2. Una descripción esquemática únicamente describe el diseño de manera estruc-


tural, mostrando los módulos y la conexión entre ellos. Por el contrario, la
descripción del circuito usando un HDL puede realizarse bien mostrando la
estructura, o bien describiendo el comportamiento. Es decir, los HDL permiten
describir el comportamiento que se desea que tenga el circuito, sin hacer nin-
guna referencia a su estructura. Las herramientas de síntesis permiten generar
automáticamente la estructura del circuito lógico a partir de la descripción de
su comportamiento.

3. El mismo HDL que se ha usado para la descripción del circuito, puede em-
plearse para describir los vectores de test y los resultados esperados del test.
Los vectores de test son los valores de las señales que se aplicarán a los pirres
de entrada del circuito con la finalidad de comprobar si el funcionamiento del
circuito es correcto. Así pues, pueden realizarse los programas de test (vectores
de test e instantes en los cuales son aplicados) del circuito a medida que se
diseña el propio circuito, pudiéndose con ello ir realizando diferentes pruebas

34
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

a medida que se avanza en el diseño. Como ventajas añadidas, la descripción


de los programas de test usando HDL es altamente portable y repetible.

1.2.1. Usos de un programa HDL

Resumiendo lo anteriormente explicado, los programas escritos en HDL pueden


tener las tres aplicaciones siguientes:

- Documentación formal. Un programa HDL puede ser usado como una especi-
ficación formal de un sistema digital. Se trata de un tipo de documentación
explícita y precisa acerca del sistema, que es intercambiable entre diferentes
diseñadores y usuarios.

- Entrada a un simulador. La simulación por ordenador del circuito permite


estudiar y comprobar su operación, sin necesidad de tener que construir físi-
camente el circuito. La entrada al simulador es el programa HDL que describe
el circuito, así como la descripción, también en el HDL, de los vectores de
test que deben aplicarse al circuito. Durante la ejecución de la simulación, el
simulador interpreta el código HDL y genera las respuestas del circuito.

- Entrada a una herramienta de síntesis. El flujo de diseño del hardware digi-


tal se basa en un proceso de refinamiento, que convierte gradualmente una
descripción de alto nivel del sistema a una descripción estructural de bajo
nivel. Algunos de estos pasos de refinamiento pueden ser realizados por las
herramientas software de síntesis.
Las herramientas software de síntesis aceptan como entrada la descripción
HDL del circuito y componen el correspondiente circuito empleando para ello
los componentes proporcionados en una librería. La salida de la herramienta de
síntesis es un nuevo programa HDL con la descripción estructural del circuito
sintetizado.

1.2.2. HDL más ampliamente usados

En la actualidad, los HDL más ampliamente usados son Verilog HDL y VHDL.
Ambos son lenguajes estándar de IEEE para el modelado y simulación de hardware.

- Verilog se creó, a principios de los años 80, como un lenguaje propiedad de


la compañía Philip Moorby, compañía que años más tarde fue adquirida por

35
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Cadence Design Systems. Posteriormente, Verilog se hizo de dominio público


y se promovió como un estándar de IEEE en el año 1995, denominado IEEE
1364.

- Como se ha explicado anteriormente, VHDL fue desarrollado en 1983 por


el Departamento de Defensa de los EE.UU. con la finalidad de servir como
lenguaje estándar para la descripción de hardware. En el año 1987 se convirtió
en un estándar de IEEE (IEEE 1067-1987). Posteriormente, se incorporaron
mejoras al lenguaje que dieron lugar a dos actualizaciones del estándar: la
primera en 1993 (IEEE 1076-1993) y la segunda en 2001 (IEEE 1076-2001).

A principios del año 2000 se desarrolló otro HDL denominado SystemC, el cual
consiste en un conjunto de librerías en C++. SystemC se convirtió en el estándar
1666 de IEEE en el año 2005.

1.3. CICLO DE DISENO DE LOS CIRCUITOS DIGITALES

El empleo de HDL es práctica habitual en las diferentes fases del ciclo de diseño
de circuitos digitales. En la Figura 1.1 se muestran las actividades que típicamente
se realizan durante el ciclo de diseño e implementación de los circuitos digitales.

En primer lugar, el diseñador debe establecer la especificación del diseño. Di-


cha especificación consiste en establecer qué se espera que haga el circuito y qué
restricciones deben satisfacerse (frecuencia de reloj, retardos, tamaño, etc.).

A continuación, el diseñador debe crear un diseño de alto nivel del circuito, para
lo cual puede emplear un lenguaje para la descripción de hardware (HDL), por
ejemplo VHDL o Verilog. Seguidamente, debe desarrollar un conjunto de programas
de test (usando también VHDL o Verilog) y, si es posible, usar estos programas
para testear el diseño de alto nivel, usando para ello una herramienta de simulación
(verificación funcional). En función de los resultados de la simulación de los tests,
puede ser preciso modificar el diseño de alto nivel, repitiéndose los pasos anteriores
tantas veces como sea preciso.

Una vez el diseño de alto nivel funciona adecuadamente, debe traducirse al nivel
de puertas lógicas o de transistores. Este proceso se denomina síntesis. Síntesis es
la generación automática del diseño del circuito a partir de la descripción de su
comportamiento. El resultado obtenido de la síntesis, denominado netlist, es una
descripción de todas las conexiones y componentes que deben componer el circuito.

36
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

Especificación del Diseño

Diseño de Alto Nivel

Programas de Test

Simulación: Verificación Funcional

Implementación (FPGA, ASIC, etc.)

Testeo del Prototipo

Figura 1.1: Ciclo de diseño del hardware digital.

La descripción al nivel de puertas o transistores, obtenida a partir de una des-


cripción en HDL, depende de la forma en que se ha programado el modelo en HDL
y de la herramienta de síntesis empleada. Las herramientas de síntesis proporcionan
numerosas opciones que permiten al diseñador especificar cómo debe realizarse la
síntesis. En particular, permiten especificar el nivel de esfuerzo a emplear por la
herramienta en la optimización automática del circuito, tanto en lo que respecta
a la reducción del área del circuito como en lo que respecta a sus prestaciones.
Asimismo, las herramientas de síntesis permiten especificar qué módulos del circuito
no deben ser optimizados.

El diseño a nivel de puertas o transistores debe ser vuelto a testear mediante


simulación (verificación de tiempos), usando, si es posible, el mismo conjunto de
tests que se realizaron sobre el diseño de alto nivel. El objetivo es estudiar si el
diseño se comporta como debe y si satisface todas las restricciones que se impusieron

37
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

en la fase de especificación. Si se detecta un problema a este nivel, debe volverse al


correspondiente paso del ciclo de diseño.

Una vez el diseño ha superado estos tests, puede implementarse en la plata-


forma hardware seleccionada: PLD (Programmable Logic Device), FPGA (Field-
Programmable Cate Array), ASIC (Application-Specific Integrated Circuit), etc. Se
emplean herramientas software para fabricar (en el caso de los ASIC) o programar
(en el caso de los FPG A) el circuito integrado a partir de la netlist.

Una vez implementado, el circuito integrado puede ser testeado con ayuda de un
generador de patrones (para generar los vectores de test), y un analizador lógico u
osciloscopio (para medir las salidas).

En este texto únicamente se explican las primeras fases del ciclo de diseño, en las
cuales se establece la especificación funcional del circuito, se realiza el diseño de alto
nivel del circuito, se elabora el programa de test, y se simula el banco de pruebas
con el fin de realizar una verificación funcional del circuito. La especificación de las
restricciones que debe satisfacer el circuito, así como las fases de síntesis, verificación
de tiempos, implementación y testeo del prototipo, quedan fuera del alcance de este
texto.

1.4. TECNOLOGÍAS DE CIRCUITOS INTEGRADOS

La implementación hardware del circuito digital puede realizarse empleando


circuitos integrados de diferentes tecnologías. Una característica fundamental que
diferencia cada tecnología de circuitos integrados es la manera de adaptar el circuito
a una determinada aplicación.

En algunas tecnologías, la estructura del circuito integrado está completamente


predefinida y el usuario debe particularizarlo para su aplicación "programándolo".
Es decir, definiendo un patrón de conexiones en la estructura del circuito integrado,
bien descargando dicha estructura en la memoria interna del circuito integrado o
mediante el fundido selectivo de los fusibles internos del circuito integrado.

En el otro extremo, las tecnologías ASIC (Application Specific Integrated Circuit)


requieren del diseño de máscaras de fotolitografía propias para cada uno de los pasos
del proceso de fabricación del circuito integrado.

Así pues, las tecnologías non-ASIC permiten particularizar el circuito en campo,


mientras que los circuitos de las tecnologías ASIC deben ser particularizados a su
aplicación en la fábrica de circuitos integrados.

38
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

1.4.1. Clasificación de las tecnologías

Es posible clasificar las tecnologías de circuitos integrados digitales de la manera


mostrada a continuación. Obsérvese que se ha conservado la terminología en lengua
inglesa en aquellos casos en que es ésta la usada habitualmente.

- Full-custom ASIC

- Standard-cell ASIC

- Gate array ASIC

- Dispositivos complejos programables en campo (FPGA y CPLD)

- Dispositivos sencillos programables en campo (PROM, PAL y PLA)

- Componentes estándar de pequeño y medio tamaño

A continuación, se describen algunas de las características más relevantes de cada


una de estas tecnologías.

Full-custom ASIC

En la tecnología full custom todos los aspectos del circuito integrado son diseña-
dos específicamente para una determinada aplicación, especificándose las caracterís-
ticas de cada uno de los dispositivos electrónicos (transistores, diodos, capacitares,
etc.) que componen el circuito. En consecuencia, el circuito resultante estará com-
pletamente optimizado y tendrá el mejor comportamiento posible.

Sin embargo, realizar el diseño al nivel de los dispositivos electrónicos es complejo


y sólo resulta práctico hacerlo para circuitos con un número de dispositivos relati-
vamente bajo. No resulta práctico usar este procedimiento para diseñar sistemas
completos, los cuales en la actualidad pueden constar de decenas e incluso cientos
de millones de transistores.

La aplicación fundamental de la tecnología full custom es el diseño de pequeños


circuitos digitales básicos, denominados "celdas estánda'f', que posteriormente serán
usados de manera modular para componer circuitos de mayor tamaño. Un tipo
importante de este tipo de módulo son los circuitos básicos a partir de los cuales,
por repetición, se construyen celdas estándar. Dos ejemplos son el circuito que
implementa un bit de memoria y el circuito que realiza la suma de dos números

39
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

de un bit, que son usados de manera repetitiva para el diseño de una memoria y un
sumador de dos números den bits, respectivamente.

Standard-cell ASIC

En la tecnología standard cell el circuito integrado es construido conectando entre


sí celdas estándar predefinidas, que ya han sido previamente diseñadas y testeadas.
Esta tecnología permite trabajar al nivel de puertas lógicas, en lugar de al nivel de
transistores, lo cual simplifica bastante el proceso de diseño.

Los fabricantes de dispositivos normalmente proporcionan librerías de celdas


estándar que implementan los bloques constitutivos básicos, tales como puertas
lógicas, componentes combinacionales simples (and-or-inverter, MUX 2:1, sumador
completo de 1 bit, etc.), elementos básicos de memoria (latch-D, flip-flop D, etc.),
memorias RAM, etc.

El circuito se construye conectando estas celdas estándar. El tipo de celdas


empleadas y la forma de conectarlas depende de la aplicación. Así pues, cada diseño
de circuito integrado de esta tecnología requiere de un juego específico de máscaras
de fotolitografía, con lo cual debe ser construido específicamente en la fábrica de
circuitos integrados.

Gate array ASIC

En la tecnología gate array el circuito es construido a partir de un array prede-


finido de "celdas base". Al contrario que en la tecnología standard cell, el circuito
integrado de la tecnología gate array consiste en la repetición unidimensional o
bidimensional de un único circuito sencillo, llamado celda base, que es similar a
una puerta lógica.

Asimismo, los fabricantes de gate array ASICs proporcionan librerías de com-


ponentes prediseñados, denominados "macro celdas", que son arrays de celdas base
conectadas entre sí para formar bloques lógicos con funcionalidades básicas. Las
macro celdas facilitan el diseño, que puede realizarse conectando entre sí macro
celdas.

Puesto que el diseño estructural de las celdas base y su posición en el circuito


integrado están predefinidos, es posible prefabricar el array de celdas base. La

40
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

particularización del circuito se realiza especificando cómo deben ser conectadas


entre sí las celdas base.

Así pues, los primeros niveles de fabricación de los circuitos integrados de la


tecnología gate array, que están dedicados a la fabricación de los transistores de las
celdas base, son comunes a todas las aplicaciones y por ello pueden ser fabricados
independientemente de la aplicación. Sólo las máscaras de fotolitografía de los niveles
de metal, que definen las conexiones entre las celdas base, deben ser diseñadas espe-
cíficamente para la aplicación. Al reducirse el número de máscaras de fotolitografía
que deben ser fabricadas específicamente para la aplicación en concreto, el proceso
de fabricación se simplifica considerablemente.

Dispositivos complejos programables en campo

La tecnología non-ASIC más versátil es el circuito integrado complejo programable


en campo, que consiste en un array de celdas lógicas genéricas y en la interconexión
genérica entre ellas. Aunque las celdas lógicas y su interconexión están prefabrica-
das, el circuito integrado dispone de fusibles que permiten "programar" el circuito
integrado, adaptándolo a su aplicación.

Este proceso de programación del circuito integrado, consistente en fundir algu-


nos de sus fusibles, puede realizarse empleando instrumental relativamente barato y
sencillo de usar. Puesto que la particularización del circuito integrado se realiza "en
campo", esta tecnología se denomina "programable en campo" (field programmable),
en oposición a las tecnologías ASIC, en las cuales el circuito integrado debe ser
particularizado en la fábrica en la que es construido.

Las celdas lógicas de los dispositivos programables en campo son bastante más
complejas que las celdas base de los gate array ASICs. De acuerdo a la estructura
circuital de sus celdas lógicas, los dispositivos complejos programables en campo
pueden clasificarse en dos tipos: CPLD ( Complex Programmable Logic Device) y
FPGA (Field Programmable Gate Array).

Dispositivos sencillos programables en campo

Los dispositivos sencillos programables en campo son, como su nombre indica,


dispositivos programables con una estructura interna más sencilla que CPLDs y
FPG As. Históricamente, este tipo de circuitos integrados se han llamado PLDs

41
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

( Programmable Logic Devices). Están compuestos por dos arrays, uno de puertas
AND y otro de puertas OR. Pueden programarse las interconexiones en uno de
estos arrays o en ambos, con el fin de adaptar el circuito a su aplicación.

- En los dispositivos PROM (Programmable Read Only Memory) puede progra-


marse el array OR.

- En los dispositivos PAL (Programmable Array Logic) puede programarse el


array AND.

- En los dispositivos PLA (Programmable Logic Array) pueden programarse


ambos arrays.

En la actualidad, los circuitos integrados de este tipo son usados raramente,


empleándose generalmente FPGAs.

Circuitos estándar de pequeña y media integración

Antes de la popularización de los dispositivos programables en campo, la única


alternativa que existía a los circuitos integrados ASIC era utilizar circuitos integrados
prefabricados SSI/MSI (Small-/Medium-Scaled Integrated circuits). Un ejemplo es
la serie 7400 de la familia TTL (Transistor- Transistor Logic), que contiene más
de 100 circuitos diferentes, que iban desde puertas NAND simples hasta unidades
aritméticas de 4 bits.

Los circuitos se diseñaban seleccionando cuáles de esos circuitos integrados debían


usarse y fabricando una placa impresa específica para la aplicación, con las pistas
para la conexión entre los pines de los circuitos integrados, y en la cual se soldaban los
circuitos integrados. En este tipo de implementación, la mayor parte de los recursos
(potencia consumida, área y coste de fabricación) es consumida por el encapsulado
y el routing, y no por el silicio, que es donde se realiza la computación. Dado que
los dispositivos programables tienen mejores capacidades y son más baratos, hoy en
día no se diseñan circuitos complejos usando tecnología SSI/MSI.

1.4.2. Comparación entre tecnologías

Una vez se ha decidido desarrollar hardware para una aplicación, debe escogerse
qué tecnología emplear. En esta sección se compararán las tres tecnologías FPGA,

42
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

gate array y standard cell, empleando para ello cuatro criterios: área, velocidad,
potencia consumida y coste. Cada tecnología tiene sus puntos fuertes y débiles, de
modo que para cada aplicación debe decidirse qué tecnología es más adecuada.

Área

El área del circuito integrado (o equivalentemente, su tamaño) depende de la


arquitectura del circuito y de la tecnología. Los circuitos integrados pequeños requie-
ren menos recursos, precisan de programas de test más sencillos y tienen un mejor
rendimiento en fabricación, entendiendo dicho rendimiento como el porcentaje de
chips buenos que se obtienen por oblea.

Frecuentemente, una misma funcionalidad puede conseguirse empleando diferen-


tes arquitecturas, con diferentes áreas y velocidades. Por ejemplo, existen diferentes
circuitos que realizan la suma de dos números den bits, algunos de ellos son sencillos
(ocupan poco área) y lentos, mientras que otros son complejos (ocupan mayor área)
y rápidos. Una vez se ha determinado la arquitectura del circuito, el área del circuito
integrado depende de la tecnología.

En la tecnología standard cell, las celdas estándar y sus interconexiones son


particularizadas para la aplicación en concreto, con lo cual no hay desperdicio de
área de silicio. El chip resultante está completamente optimizado y el área es mínima.

En la tecnología gate array, el circuito debe ser construido a partir de celdas base
cuya posición en el circuito está predefinida. Dado que la funcionalidad y posición
de las celdas base no son específicas a la aplicación, el aprovechamiento del silicio
no es óptimo. En consecuencia, normalmente un circuito integrado de la tecnología
gate arra y necesita mayor área (aproximadamente entre un 20% y un 100% más)
que ese mismo circuito desarrollado en la tecnología standard cell.

En la tecnología FPGA, una parte considerable del área del circuito integrado
está dedicada a posibilitar que el circuito pueda ser programado en campo. Más
aun, la funcionalidad de las celdas lógicas y las interconexiones están preestableci-
das, siendo frecuente que cierto porcentaje de la capacidad no sea utilizado en la
aplicación en concreto a la que se destina el FPGA. Por todo ello, puede estimarse
que un circuito implementado en la tecnología FPGA tiene entre 2 y 5 veces mayor
área que ese mismo circuito implementado en una tecnología ASIC.

43
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Velocidad

La velocidad de un circuito digital es el tiempo necesario para que dicho circuito


realice su función. Este tiempo se estima considerando el mayor retardo en la
propagación que puede producirse en cada etapa del circuito. Normalmente, cuanto
más rápido sea un circuito, mejor. Sin embargo, para poder realizar las operaciones
más rápidamente, es necesario emplear circuitos con arquitecturas más complejas,
que ocupan mayor área.

Si se usan arquitecturas idénticas, normalmente un circuito integrado con mayor


área es más lento, debido a sus mayores capacidades parásitas.

Dado que en la tecnología standard celllas interconexiones y el área pueden ser


optimizadas, esta tecnología es la que permite menores retardos de propagación y,
consiguientemente, mayor velocidad. En el otro extremo, la tecnología FPGA es la
que tiene retardos de propagación mayores.

Al igual que sucedía con el área, la diferencia que existe respecto a la velocidad
entre las tecnologías ASIC standard cell y gate array es considerablemente menor
que entre estas tecnologías ASIC y la tecnología FPGA.

Potencia consumida

La potencia consumida es la energía que consume el circuito integrado por unidad


de tiempo. En algunas aplicaciones, tales como los equipos portátiles alimentados
con pilas, tiene una gran importancia que los circuitos integrados consuman poca
potencia.

El consumo de potencia está relacionado con el número de transistores que


contenga el circuito integrado, con lo cual un criterio que puede imponerse al realizar
la síntesis automática de un diseño es minimizar el consumo de potencia.

Respecto a las tres tecnologías que estamos comparando, la tecnología standard


cell consume la menor cantidad de potencia, mientras que la tecnología FPGA es la
que consume mayor cantidad de potencia de las tres.

Por todo lo dicho hasta el momento, se deduce que la tecnología standard cell es
la mejor elección desde el punto de vista técnico, ya que un chip construido en esa
tecnología es tan pequeño, rápido y consume tan poca potencia como sea posible.

44
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

Coste

El coste es un factor importante, y en ocasiones decisivo, a la hora de seleccionar


la tecnología en la que implementar un circuito. Pueden considerarse las tres contri-
buciones al coste siguientes: el coste de producción, el coste de desarrollo y el coste
del tiempo de llegada al mercado.

El coste de producción ( eprod) son los euros que cuesta producir una unidad
del circuito integrado. Incluye dos conceptos: el coste de ingeniería (eing) y el coste
de fabricación (efab).

eing
eprod = efab + . . (1.1)
Unidades producidas

El coste de ingeniería (eing) se produce una única vez durante el proceso de


producción del circuito integrado, con independencia del número de unidades que
vayan a fabricarse. En este concepto se incluye el desarrollo de las máscaras de
fotolitografía, el desarrollo de los tests, y la fabricación y test de los prototipos.
La repercusión de este coste en cada unidad del circuito depende del número de
unidades producidas, siendo la repercusión menor cuanto mayor sea el número de
unidades fabricadas.

El coste de fabricación (efab) es la suma del coste que conlleva fabricar el


dispositivo, encapsularlo y testearlo. El coste de fabricación de un circuito integrado
ASIC es menor que el coste de un circuito desarrollado en la tecnología FPGA.
Igualmente, el coste de fabricación de un circuito standard cell es menor que el de
un circuito gate array. Esto es debido a que el circuito de la tecnología standard
cell está más optimizado que el circuito sintetizado en la tecnología gate array: tiene
menor área, con lo cual se obtienen más circuitos integrados por oblea y además, al
ser menor el área del circuito integrado, el porcentaje de circuitos integrados buenos
por oblea es mayor.

En la Figura 1.2 se muestra el coste por unidad para las tecnologías standard
cell, gate array y FPGA. A medida que el número de unidades fabricadas aumenta,
en primer lugar gate array, y a continuación standard cell, se hacen rentables. Los
puntos de intersección entre las curvas indican el volumen de producción a partir del
cual cada una de estas dos tecnologías resulta rentable. Obsérvese que el coste de
producción de la tecnología FPGA es constante, debido a que su coste de ingeniería
es nulo. Es decir, para la tecnología FPGA se verifica que: eprod = efab·

45
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Coste de (1) Número de unidades a partir del cual gate


producción array tiene menor coste que FPGA
'' (2) Número de unidades a partir del cual standard
(Cprod) ''
cell tiene menor coste que gate array
''
'

--------------- Gate array


Standard cell

(1) (2)
Unidades producidas

Figura 1.2: Comparación del coste de producción por unidad de circuito integrado.

La segunda contribución al coste es el coste de desarrollo. El proceso de


transformar una idea en un circuito integrado conlleva unos costes, entre los cuales
se incluyen los ordenadores y el software, y las horas de ingeniería. Aunque el
procedimiento de síntesis es similar para todas las tecnologías, el desarrollo de ASICs
es más complejo y requiere mayor esfuerzo, con lo cual el coste de ingeniería de un
circuito integrado ASIC es mucho mayor que el de ese mismo circuito implementado
en la tecnología FPGA. Por este mismo motivo, el coste de desarrollo de un circuito
standard cell es considerablemente mayor que el coste de desarrollo de ese mismo
circuito en la tecnología gate array.

La tercera contribución al coste del circuito integrado es el coste del tiempo


de llegada al mercado, si bien más que un coste es en realidad la pérdida de los
beneficios económicos que se obtendrían si el circuito se encontrara ya vendiéndose
en el mercado. En algunas aplicaciones, tales como los periféricos de los PCs, el
ciclo de vida de un producto es muy corto, del orden de 12 a 18 meses. Así pues, es
muy importante introducir el producto en el mercado cuanto antes. La tecnología
standard cell es la que tiene un tiempo mayor de validación, de desarrollo de los
tests y de puesta en producción, variando este tiempo entre unos meses y un año.
El tiempo de la tecnología gate array puede variar entre unas cuantas semanas y
unos meses. En el caso de la tecnología FPGA, la particularización del circuito a la
aplicación se realiza programando un circuito prefabricado, lo cual puede hacerse en
minutos.

46
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

1.5. PROPIEDADES DE LOS CIRCUITOS DIGITALES

Los circuitos digitales reales tienen algunas características importantes que afec-
tan a la manera en que deben ser modelados y diseñados. Estas características
son debidas tanto a los transistores que componen las puertas lógicas como a las
conexiones entre ellos. Entre las más importantes están las siguientes.

1.5.1. Retardo de los dispositivos

Un dispositivo lógico real tiene la propiedad de que un glitch en un puerto de


entrada, con una duración inferior al retardo de propagación del dispositivo, no tiene
efecto sobre la salida del dispositivo. Se denomina glitch a un cambio temporal (un
pico de subida o bajada) e inesperado en el voltaje.

Por ejemplo, si una puerta NAND tiene un retardo de propagación de 1 ns,


entonces un glitch de 0.5 ns (un O ó 1 temporal, de duración 0.5 ns) en una de sus
entradas no produce ningún cambio en su salida.

Este tipo de comportamiento del retardo se denomina retardo inercial y es el


modelo del retardo usado por defecto para todos los dispositivos en VHDL.

El retardo inercial es adecuado para modelar los retardos a través de dispositivos


tales como transistores y puertas lógicas. Un cambio en la entrada de un dispositivo
se ha de mantener estable durante cierto tiempo para que este cambio se propague
a su salida. Las puertas lógicas actúan así como filtros paso baja. El retardo inercial
es debido a la capacidad del dispositivo, la carga que conduce, sus características
intrínsecas, número y tipo de los elementos conectados al dispositivo, etc.

Otro tipo alternativo de modelo del retardo, en el cual todos los glitches a la
entrada se manifiestan en la salida, se denomina retardo de transporte o retardo puro.
El retardo de transporte es adecuado para modelar retardos a través de dispositivos
con poca inercia, tales como las líneas de metal construidas en el chip para conectar
los dispositivos. Los retardos puros pueden considerarse como desplazamientos en
el tiempo de la señal, ya que la señal en sí misma no se modifica. Al describir el
retardo de los circuitos, VHDL permite diferenciar entre ambos tipos de retardo.

Para ilustrar la diferencia entre ambos tipos de retardo, consideremos en primer


lugar un buffer cuya señal de entrada es x y cuya señal de salida es y1. El buffer
tiene un retardo inercial de 100 ns. Su comportamiento puede describirse en VHDL
de la forma siguiente:

47
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Messages

+x O
+v1 u
+v2 u

111111111 llllllllllllllllllllttlllllllltllllllllllllllllllllllllllllllllllllllllllllllllllllllllllltlllllll

450 ns 1s 100 ns 200 ns 300 ns 400 ns 500 ns


l5o nsJ
.i._ kl J
1 O ns to 542 ns 1 Now: 450 ns Delta : O

Figura 1.3: Retardo inercial y de transporte.

y1 <= x after 100 ns;

donde el símbolo <= representa la asignación del valor de la señal de la derecha (x) a
la señal de la izquierda (y1), una vez transcurrido el retardo indicado tras la palabra
reservada after. Supongamos que la señal digital x varía de la forma indicada en la
tabla siguiente:

Tiempo (ns) o 100 200 250


X '0' '1' '0' '1'

La señal y1 evoluciona según se muestra en la Figura 1.3. Durante los primeros


100 ns, el valor de la señal de salida y1 es indefinido, puesto que no ha sido ini-
cializado: vale 'U' (que proviene del inglés "Uninitialized"). Obsérvese que el buffer
no responde ante cambios en la señal de entrada cuya duración sea menor que el
retardo inercial. En concreto, el buffer no responde al cambio en la señal x que se
produce en el instante 200 ns.

Consideremos ahora una línea de metal que introduce un retardo de transporte


en la señal de 100 ns. Llamando x a la señal de entrada e y2 a la señal de salida,
el comportamiento de la línea de metal puede ser descrito en VHDL de la manera
indicada a continuación, donde la palabra reservada transport indica que el retardo
es de transporte:

y2 <= transport x after 100 ns;

Si la señal x varía de la forma indicada en la tabla anterior, la evolución de


la señal y2 es la mostrada en la Figura 1.3. Observe que la señal y2 es la señal x
desplazada 100 ns.

En resumen, las señales y1 e y2 sólo se diferencian en que la señal y1 no cambia


su valor en el instante 300 ns, como consecuencia del cambio de valor en x en el

48
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

instante 200 ns. Esto sucede porque el cambio en la señal x se mantiene durante un
tiempo inferior al valor del retardo inercial (100 ns).

Una observación final respecto al modelado del retardo. Obsérvese nuevamente la


Figura 1.1, en la cual se representa el ciclo de diseño del hardware digital. Cuando
se realizan los pasos "Diseño de alto nivel", "Programas de test" y "Simulación:
Verificación funcional", se sabe que todos los bloques circuitales del diseño van a
tener retardos. Sin embargo, en este punto del ciclo de diseño se desconoce el valor de
dichos retardos. Hasta que no se realice la síntesis, y por tanto quede especificada la
implementación hardware del circuito, no podrá estimarse el retardo de cada bloque
circuital.

Esta Unidad Didáctica se centra únicamente las primeras fases del ciclo de diseño.
Esto es, en la realización en VHDL del diseño de alto nivel, la programación en VHDL
de los programas de test y la simulación para la verificación funcional. Dado que en
estas fases iniciales del diseño no se conocen los retardos de los bloques circuitales
que componen el diseño, ya que todavía no se ha tomado la decisión acerca de cómo
van a implementarse en hardware, es práctica común no especificar el valor estimado
de los retardos en el diseño de alto nivel de los circuitos. En su lugar, suele asignarse
a cada uno de los bloques circuitales un retardo por defecto, denominado retardo 6.
Como se explicará ampliamente más adelante, esta forma de modelar el retardo es
suficiente para realizar la verificación funcional de los circuitos.

En un paso posterior, una vez realizada la síntesis, se incluirán los valores esti-
mados de los retardos en el diseño y se comprobará si se satisfacen las restricciones
referentes al tiempo de respuesta, que se impusieron en la especificación del diseño.
El paso en el cual se realiza la simulación del circuito, teniendo en cuenta los valores
estimados del retardo, es el señalado en la Figura 1.1 como "Simulación: Verificación
de tiempos".

1.5.2. 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 simularlo.
La metodología aplicada para ello por el simulador es la simulación de eventos
discretos.

49
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

1.5.3. 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 fabrica-
dos en diferentes obleas, e incluso existen variaciones entre los chips fabricados en
posiciones distantes dentro de una misma oblea.

Por este motivo, no es buena idea diseñar un circuito cuyo funcionamiento


dependa de que los retardos tomen un determinado valor o que su magnitud sea
mínima. Este tipo de circuitos puede funcionar correctamente cuando son simulados,
ya que las señales simuladas llegan a los módulos en un determinado orden, que viene
determinado por los valores de los retardos contenidos en el modelo. Sin embargo, si
el orden de llegada de los cambios en las señales depende del valor de los retardos,
y los retardos simulados no se corresponden con los existentes en el hardware físico,
entonces ese diseño producirá chips que no funcionen , o que funcionen sólo una parte
del tiempo.

1.5.4. Fortaleza de las señales

En un circuito digital típico, la transferencia de un valor lógico desde un pin


de salida de un módulo, a varios pines de entrada de otros módulos, precisa de la
transferencia de carga eléctrica hacia los pines de entrada (en el caso de '1' lógico)
o hacia el pin de salida (en el caso de 'O' lógico). El pin de salida debe tener la
capacidad de hacer de "fuente" y de "sumidero" de toda la corriente necesaria.

Desde el punto de vista práctico, esto implica que la salida de un módulo puede
ser conectada como máximo a un determinado número de entradas de otros módulos.
En aquellos casos en que la señal deba conectarse a un número de módulos superior a
este número máximo, entonces debe emplearse un árbol de buffers. En la Figura 1.4
se muestra un árbol de buffers que lleva una señal (out) a 16 módulos (in_O, ... ,
in_15), de tal forma que la salida de los buffers se conecta únicamente a 4 entradas.

El uso del árbol de buffers tiene un beneficio añadido: igualar los retardos de las
señales de entrada a todos los módulos, ya que el árbol de buffers está diseñado de
modo que la longitud de las líneas de todas sus ramas sea la misma. Este tipo de
árbol de buffers se emplea para llevar la señal de reloj a los flip-flops en los circuitos
secuenciales síncronos, en los cuales es importante que la señal de reloj llegue a todos
los flip- flops aproximadamente en el mismo instante.

50
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

in_O in_1 in_2 in_3

in_4

in_5
¡······················¡
>--+------1
in_6
: ...................... ;

>-~---------------~~~
f'""'''""'' ""'"¡ in_?

>-~--------------r-~
f"""'"""""""'¡ in_8
...................... ;
:

in_9

in_10

in_11

in_15 in_14 in_13 in_12

Figura 1.4: Árbol de buffers para llevar una señal a 16 módulos.

1.6. TEST DE LOS CIRCUITOS

El test juega un papel muy importante en el diseño de circuitos integrados. No


sólo se emplea para verificar el correcto funcionamiento del circuito ya completa-
mente diseñado, sino que también es una ayuda esencial para el diseñador durante
la fase de diseño del circuito.

Finalmente, el test se emplea en manufactura, para determinar qué chips han


resultado defectuosos o tienen limitadas prestaciones. Por ejemplo, puede emplearse
para separar los chips que funcionan correctamente a alta velocidad, de los que sólo
funcionan a baja velocidad (cada tipo es vendido a diferente precio). Si el diseño
se ha realizado correctamente, los chips defectuosos en los test de manufactura
se deben a problemas en los procesos de fabricación o de encapsulado. El test

51
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

realizado en manufactura tiene un impacto directo sobre el rendimiento (porcentaje


de chips fabricados que no son defectuosos), el cual tiene un impacto directo sobre
los beneficios de la compañía fabricante de los chips.

Esencialmente, el test consiste en fijar valores en todas las entradas del circuito
y observar qué valores se obtienen en sus salidas. A cada asignación de valores a
todas las entradas del circuito se le llama un vector de test. El programa de test
consiste en un conjunto de vectores de test, que se aplican sobre el dispositivo en
una determinada secuencia.

1.6.1. Test en manufactura

Un objetivo fundamental del test en manufactura es detectar problemas en el pro-


ceso de fabricación. Las causas de mal funcionamiento de los chips más comúnmente
observadas en la práctica son:

- Abiertos. Conexiones entre los dispositivos que se encuentran abiertas debido


a algún problema, por ejemplo, debido a la rotura de la línea de metal que
establece la conexión.

- Cortos. Conexiones que se han establecido entre diferentes dispositivos, cuan-


do no deberían haberse producido.

- Acopios. Valores lógicos en una parte del circuito que inadvertidamente cam-
bian el valor lógico en otra parte del circuito.

Modelar estos diferentes tipos de defectos en el circuito es extremadamente difícil.


Por ello, se han desarrollado diferentes modelos simplificados de fallos.

Uno de estos modelos de fallo es considerar que el defecto de fabricación hace que
una de las conexiones internas del circuito permanezca siempre a 1, o que permanezca
siempre a O.

En un circuito típico, este tipo de fallos da lugar a un número muy elevado de


patrones de fallo. Un patrón de fallo es una determinada selección de conexiones que
se encuentran permanentemente a 1 y de conexiones que se encuentran permanen-
temente a O.

Se da la circunstancia de que varios patrones de fallo pueden desembocar en el


mismo comportamiento del circuito. Por ejemplo, si cualquiera de las entradas de

52
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

una puerta NAND se encuentra siempre a O, el circuito se comporta de la misma


manera que si la salida del circuito se encontrara siempre a l.

Incluso tomando en consideración que existen patrones de fallo que dan lugar a
un comportamiento equivalente (defectuoso) del circuito, el número de patrones de
fallo esencialmente distintos es extremadamente grande.

Por ello, se ha desarrollado un modelo simplificado a partir del anterior. Consiste


en suponer que en el circuito hay una única conexión que se encuentra permanente-
mente a 1, o permanentemente a O. Aunque este modelo de fallos pudiera considerarse ·
muy restrictivo, ha demostrado ser eficaz.

Una vez se adopta un determinado modelo de fallos, el siguiente paso es crear


un conjunto de vectores de test que permita detectar ese tipo de fallos. Para que
se produzca la detección del fallo, es preciso que la salida del circuito, en caso de
estarse produciendo el fallo, sea diferente de la salida de un circuito que funcione
correctamente. En este caso, se dice que el fallo se encuentra cubierto por el vector
de test. Por supuesto, habrá otros tipos de fallos que darán lugar, para ese vector
de test, a las mismas salidas que un circuito que funcione correctamente. Se dice
entonces que el vector de test no cubre esos otros fallos.

Según se van usando más y más vectores de test, el porcentaje de fallos potenciales
(para un determinado modelo de fallo) que son cubiertos se aproxima al lOO%. Dado
un conjunto de vectores de test, la cobertura de fallos de ese conjunto de vectores
de test (dado un modelo específico de fallos) corresponde con el porcentaje de fallos
cubiertos.

El test de los circuitos secuenciales es más complicado, ya que las salidas del
circuito dependen no sólo de las entradas, sino también de su estado. Por tanto,
en este tipo de circuitos es preciso poder fijar los valores de todos los fiip-fiops a
voluntad. Esto puede hacerse de las dos maneras siguientes:

l. Mediante una secuencia de inicialización (secuencia de valores de las entradas


del circuito), se lleva el circuito al estado deseado. A continuación, se aplica el
vector de test para probar el circuito en ese estado.
Mediante este procedimiento, un único test consiste en una secuencia de ini-
cialización, seguida de otro vector de test. Este procedimiento conduce a usar
un gran número de vectores de test, muchos de los cuales son simplemente
secuencias de inicialización. Además, en algunos casos puede no ser posible
fijar todos los fiip-fiops a los valores deseados.

53
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2. El segundo método consiste en usar en el diseño sean fiip-fiops, 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 sean
flip-flops pueden construirse insertando multiplexores en la entrada D de los
fli p-flops.

En el test en manufactura, la calidad de un conjunto de vectores de test (denomi-


nado programa de test) se mide por medio de la cobertura de fallos del programa de
test (supuesto un determinado modelo de fallo) y del tiempo necesario para aplicar
todos los vectores de test al circuito, que es directamente proporcional al número de
vectores de test.

Cuanto mayor sea la cobertura de fallos, menor será el número de chips defectuo-
sos que superarán con éxito el proceso de inspección. Cuanto menor sea el número
de vectores de test, menor será el tiempo necesario para ejecutar el programa de
test, con lo cual podrán testearse mayor número de chips por unidad de tiempo.

1.6.2. 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, usando pro-
gramas 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.

54
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

1.6.3. Programas de test funcional

Un método para testear la funcionalidad de un circuito es probar todos los


posibles vectores de entrada. Sin embargo, en algunos circuitos esto no es posible,
bien porque el número de posibles vectores es muy grande, o bien porque algunas
combinaciones de valores de las entradas no son válidas para ese determinado circui-
to. Además , algunas funciones requieren de una determinada secuencia de vectores
de entrada.

En conclusión, el programa de test es algo que depende del circuito. Sin embargo,
en general se sigue el criterio de probar todos los posibles vectores de entrada, siempre
que esto sea posible.

Si el número de posibles vectores de entrada es muy grande (se tardaría meses


o años en pro bar los todos), existen varios métodos heurísticos que pueden aplicarse
para reducir el número de vectores de entrada.

l. Puede emplearse el conocimiento sobre el funcionamiento de circuito para


descartar aquellos vectores de entrada que no tienen ninguna función en el
circuito, o que nunca ocurrirán en la práctica.

2. El circuito puede dividirse en varios subcircuitos, que son testeados exhausti-


vamente (usando todas las combinaciones de los vectores de entrada para cada
sub circuito). A continuación, el circuito completo puede testaerse usando un
conjunto no exhaustivo de vectores de entrada, simplemente para comprobar
que los subcircuitos han sido integrados adecuadamente.

3. Se escoge un conjunto representativo de vectores de entrada, con el fin de ejerci-


tar el circuito bajo condiciones normales de funcionamiento y bajo condiciones
extremas.

Al testear un circuito, es deseable poder comparar de manera automática las


salidas del circuito con las correspondientes salidas que se obtendrían si el circuito
funcionara correctamente. Esto puede hacerse de varias maneras.

l. Una forma es almacenar en un fichero las salidas de un circuito que funcione


correctamente, y compararlas con las salidas obtenidas.

2. Otro procedimiento consiste en calcular la salida esperada del circuito usando


un método diferente al empleado en el test, y comparar los resultados.

55
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Circuito banco de pruebas

Entradas Salidas Subcircuito


Subcircuito al UUT delUUT
de comprobación
generador de
los vectores de test
UUT de los resultados
del test

Figura 1.5: Diagrama de bloques del modelo de un banco de pruebas.

Cuando no es posible aplicar un método de cálculo alternativo al del test, puede


comprobarse si los resultados obtenidos del test son "razonables". Por ejemplo,
si un circuito calcula la media de un conjunto de números, puede comprobarse
que el resultado obtenido sea mayor o igual que el menor de los números del
conjunto, y menor o igual que el mayor de los números del conjunto.

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

Una alternativa mucho más ventajosa consiste en codificar el programa de test


usando un HDL. Es decir, implementar el programa de test en otro módulo de código
HDL, que es denominado banco de pruebas.

El banco de pruebas contendrá el circuito que está siendo probado (denominado


abreviadamente UUT, del inglés "Unit Under Tesf') como un subcircuito. Todas las
entradas al UUT serán generadas dentro del banco de pruebas, y todas las salidas
del circuito serán comprobadas dentro del banco de pruebas.

En resumen, el banco de pruebas debe incluir (véase el diagrama de bloques en


la Figura 1.5):

- Un subcircuito generador de los vectores de test.

- El circuito que está siendo probado (UUT).

- Un subcircuito de comprobación de los resultados obtenidos del test.

56
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

Como módulo de código en HDL, el banco de pruebas es un módulo sin entradas


ni salidas externas. Puesto que el banco de pruebas normalmente no va a ser sinte-
tizado en un circuito físico, puede emplearse cualquier instrucción disponible en el
HDL para generar los vectores de test y analizar las salidas del UUT, pudiéndose
llegar a crear programas extremadamente complejos.

Finalmente, recalcar que cuando se diseña un circuito digital, es conveniente dise-


ñar también su banco de pruebas. Si el circuito se diseña jerárquicamente, entonces
cada subcircuito debe ser testeado separadamente antes de ser combinado con otros
subcircuitos para integrar un circuito de nivel jerárquico superior. Asimismo, deberá
desarrollarse un banco de pruebas para este circuito de nivel superior.

1.7. REPRESENTACIONES Y NIVELES DE ABSTRACCIÓN

En esta sección se describen dos aspectos ortogonales entre sí en el diseño del


hardware digital: la representación del sistema y el nivel de abstracción.

l. 7 .l. Representación del sistema

Cada una de las tareas del proceso de desarrollo y producción del hardware
digital, requiere el conocimiento de un tipo específico de información acerca del
sistema, que va desde la especificación del sistema hasta el layout de los componentes
físicos.

El mismo sistema es descrito de diferentes formas y es examinado desde diferentes


perspectivas. Estas perspectivas se denominan las representaciones o visiones del
sistema. Pueden diferenciarse tres:

- Representación del comportamiento

- Representación de la estructura

- Representación física

Representación del comportamiento

La representación del comportamiento describe la funcionalidad del sistema. En


esta visión del sistema, éste es considerado como una caja negra, ignorándose su

57
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

implementación interna, y enfocándose en la relación entre las señales de entrada


y de salida, definiendo qué señales de salida deben obtenerse cuando se aplica un
determinado conjunto de señales de entrada.

La descripción del comportamiento del sistema raras veces es única, ya que


normalmente hay diferentes maneras de especificar unas mismas características de
entrada-salida.

Representación de la estructura

La representación estructural describe la implementación interna del sistema,


especificando de qué componentes se compone y cómo están conectados estos com-
ponentes entre sí. Corresponde con una representación esquemática o diagrama del
sistema.

Normalmente se emplea el término "nef' para describir un conjunto de cables


o líneas conductoras que están conectados a un mismo nodo, y se usa el término
"netlisf' (lista de nets) para referirse a la descripción esquemática del sistema.

Representación física

La representación física describe las características físicas del sistema, especifi-


cando las dimensiones de los componentes electrónicos, su posición en el circuito
integrado y el camino físico del cableado de conexión entre los componentes. Añade,
por tanto, información adicional a la visión estructural del mismo. Se trata, de hecho,
de la especificación final para la fabricación del sistema.

l. 7.2. Niveles de abstracción

Cuando el número de transistores que componen un circuito integrado se hace


del orden de cientos de millones, es imposible para un ser humano, e incluso para
un ordenador, procesar esa cantidad de información directamente. El método que
posibilita diseñar sistemas tan complejos consiste en describir el sistema mediante
diferentes abstracciones.

Una abstracción es un modelo simplificado del sistema, el cual muestra sólo unas
determinadas características relevantes del sistema e ignora todos los demás detalles.

58
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

La finalidad de una abstracción es reducir la cantidad de datos a un volumen que


resulte manejable. De este modo, en una abstracción sólo se muestra la información
que es crítica para ese nivel en la representación del sistema.

Una abstracción de alto nivel está enfocada y muestra únicamente los datos más
vitales. Por otra parte, una abstracción de bajo nivel es más detallada y tiene en
cuenta información que es ignorada en abstracciones de nivel superior. Por ello, la
abstracción de bajo nivel es, a la vez que más compleja, también más precisa en sus
predicciones acerca del comportamiento del circuito real.

En el proceso de desarrollo de hardware, normalmente se comienza con una


abstracción de alto nivel, la cual permite centrarse en las características más vitales.
A medida que se va conociendo mejor el sistema, van incluyéndose más detalles y se
desarrollan abstracciones de más bajo nivel.

En el desarrollo de sistemas digitales suelen considerarse los cuatro niveles de


abstracción siguientes:

- Nivel de transistor

- Nivel de puertas lógicas

- Nivel de transferencia entre registros (RTL)

- Nivel de procesador

La división entre estos niveles se basa en el tamaño de sus bloques constitutivos


básicos, que son los transistores, las puertas lógicas, los módulos funcionales y los
procesadores, respectivamente.

El nivel de abstracción y la representación (descrita en la Sección l. 7.1) son dos


dimensiones independientes del sistema. Cada nivel de abstracción tiene sus propias
representaciones. Es posible combinar en un gráfico "Y" los niveles de abstracción y
las representaciones de un sistema. En la Figura 1.6 se muestra dicho gráfico, en el
cual cada uno de los tres brazos muestra una representación o visión del sistema, y
el nivel de abstracción aumenta al progresar desde el centro hacia los extremos. Las
siguientes subsecciones están dedicadas a cada uno de los niveles de abstracción.

59
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Representación del Representación de la


comportamiento estructura

Procesador, memoria, interfaz I/0


Operaciones de transferencia entre registros

Ecuaciones diferenciales y algebraicas

Layout de los transistores, resistencias, condensadores

Layout de las celdas

Floor plan de los módulos

Representad ón
flsica

Figura 1.6: Niveles de abstracción y representación del sistema.

Nivel de transistor

El nivel de abstracción más bajo es el nivel de transistor. En este nivel, los


bloques básicos constitutivos de la visión estructural del circuito son los dispositivos
electrónicos, tales como los transistores, resistencias y capacitares.

La descripción del comportamiento se realiza normalmente mediante ecuaciones


diferenciales y algebraicas, que son simuladas usando entornos de simulación de
sistemas analógicos, como por ejemplo Spice. Al nivel de transistor, el circuito digital
es tratado como un sistema analógico, en el cual las señales son de tiempo continuo,
pudiendo tomar cualquier valor en un rango continuo.

La visión física del circuito al nivel de transistor consiste en el layout de los


componentes y sus conexiones. Define las máscaras fotolitográficas que deben usarse
en los diferentes niveles del proceso de fabricación y es, por tanto, el resultado final
del proceso de diseño.

Nivel de puertas lógicas

El siguiente nivel de abstracción es el nivel de puertas lógicas. Los bloques


constitutivos básicos son puertas lógicas, tales como puertas AND, OR, XOR, MUX

60
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

2:1 de un bit, elementos básicos de memoria, tales como latch y flip-flop. En lugar
de considerar que las señales tienen valores continuos, se considera únicamente si la
señal está por encima o por debajo de un valor umbral, lo cual es interpretado como
'1' lógico y 'O' lógico, respectivamente.

Puesto que se realiza la simplificación de considerar que las señales tienen única-
mente dos valores, el comportamiento es descrito mediante ecuaciones booleanas. Es
decir, la abstracción esencialmente convierte un sistema continuo, que era descrito
mediante ecuaciones diferenciales y algebraicas, en un sistema discreto, descrito
mediante ecuaciones booleanas.

En este nivel se simplifica también el modelado de la respuesta temporal. Se define


el retardo en la propagación como el intervalo de tiempo que precisa un sistema para
proporcionar una señal de salida estable.

La representación física en este nivel consiste en la situación espacial de las


puertas o celdas, y el camino ( routing) que sigue el conexionado entre ellas.

En el nivel inferior de abstracción, se hablaba del área de silicio necesaria para


construir el circuito. En este nivel, se cuenta el número de puertas lógicas que com-
ponen el circuito (denominado gate count), de modo que la medida es independiente
de la tecnología. Se usa el área de la puerta NAND de dos entradas como unidad
básica de medida, ya que este normalmente es el circuito lógico más sencillo desde
el punto de vista físico. Así pues, en lugar de emplear el área física para expresar el
tamaño a la complejidad del circuito, se emplea el número equivalente de puertas
NAND en una determinada tecnología en particular.

Nivel de transferencia entre registros (RTL}

En el nivel de transferencia entre registros (RTL: Register Transfer Level), los


bloques constitutivos básicos son módulos construidos a partir de puertas. Estos
módulos incluyen unidades funcionales (sumadores, comparadores, etc.), componen-
tes de almacenamiento (registros, etc.) y componentes de enrutamiento de los datos
(multiplexores, etc.) Este nivel podría llamarse abstracción al "nivel de módulos",
sin embargo en diseño digital se emplea normalmente el término "transferencia entre
registros" y nosotros seguiremos esta terminología.

El término "transferencia entre registros" se emplea en dos contextos. Origi-


nalmente, el término "transferencia entre registros" se usaba para referirse a una
metodología de diseño en la cual la operación del sistema se describía indicando
cómo los datos son manipulados y transferidos entre registros de almacenamiento.

61
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Dado que la mayoría de los componentes usados en la metodología de transferencia


entre registros son módulos de tamaño intermedio, el término "transferencia entre
registros" se adoptó también para designar la abstracción al nivel de módulos.

En este texto distinguiremos entre ambos usos del término. Hablaremos de "nivel
de transferencia entre registros" (RTL: Register Transfer Level) para referirnos a la
abstracción al nivel de módulos y llamaremos "metodología de transferencia entre
registros" a la metodología específica de diseño.

La representación de los datos al nivel de transferencia entre registros es más


abstracta. Frecuentemente las señales se agrupan entre sí y son interpretadas como
un tipo especial de dato, tal como un número entero o el estado de un sistema.
La representación del comportamiento a este nivel usa expresiones generales para
especificar las operaciones funcionales y el camino de los datos, y emplea una má-
quina de estado finito para describir el sistema diseñado mediante la metodología
de transferencia entre registros.

Una característica importante de la descripción al nivel de transferencia entre


registros es el uso de una señal de reloj común en los elementos almacenadores. La
señal de reloj tiene la función de sincronización, haciendo que se almacenen los datos
en los componentes almacenadores en instantes específicos de tiempo, determinados
por el flanco de subida de la señal de reloj. En un sistema bien diseñado, el periodo
de la señal de reloj es lo suficientemente largo como para permitir que todas las
señales se estabilicen dentro del periodo. Puesto que las señales son muestreadas
sólo en los instantes de flanco de subida de la señal de reloj, las diferencias en los
retardos de propagación y los glitches no tienen efecto sobre la operación del sistema.
Esto permite considerar el tiempo en términos de número de ciclos de la señal de
reloj, en lugar de tener que considerar todos los retardos en la propagación.

El layout físico en esta abstracción se denomina fioor plan. Se emplea para en-
contrar el camino más lento entre los elementos de almacenamiento y así determinar
el periodo de la señal de reloj.

Nivel de procesador

El nivel de procesador es el mayor nivel de abstracción. Los bloques constitutivos


básicos en este nivel, llamados frecuentemente intellectual properties (IPs), incluyen
procesadores, módulos de memoria, etc.

La descripción del comportamiento del circuito es similar a un programa codi-


ficado en un lenguaje de programación convencional, tal como C. Las señales son

62
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

agrupadas e interpretadas como varios tipos de datos. El tiempo se mide en términos


de pasos de computación, los cuales están compuestos de un conjunto de operaciones
que se realizan entre dos instantes sucesivos de sincronización.

El layout físico al nivel de procesador se denomina también floor plan. En este


caso, los componentes usados en el fl.oor plan son mucho mayores que los usados en
el nivel de transferencia entre registros.

l. 7. 3. VHD L en el ft ujo de desarrollo

Como se ha explicado anteriormente, un sistema digital puede ser descrito de


acuerdo a diferentes niveles de abstracción, y de acuerdo a diferentes representa-
ciones o visiones. A medida que progresa el proceso de diseño, el nivel y la visión
van cambiando, tanto para los diseñadores humanos como para las herramientas
software.

Los lenguajes para la descripción del hardware (HDL) constituyen un marco


para el intercambio de información entre diseñadores y entre herramientas software.
Permiten modelar y describir el circuito de manera precisa, de acuerdo a la repre-
sentación del comportamiento y de acuerdo a la representación de la estructura, en
cada uno de los cuatro niveles de abstracción: transistor, puertas lógicas, RTL y
procesador.

Las herramientas de síntesis transforman automáticamente una descripción en


VHDL del comportamiento del circuito al nivel de transferencia entre registros en
una descripción en VHDL de la estructura del circuito al nivel de puertas lógicas
(netlist al nivel de puertas). Asimismo, puede programarse en VHDL el banco de
pruebas para testear la descripción RTL del comportamiento y puede emplearse ese
mismo banco de pruebas para testear la descripción estructural al nivel de puertas.

Puede emplearse una herramienta software para, a partir de la netlist al nivel


de puertas en VHDL, generar automáticamente el layout del circuito, que no está
expresado en VHDL.

1.8. CONCEPTOS BÁSICOS A TRAVÉS DE UN EJEMPLO

En esta sección se muestra un ejemplo sencillo que ilustra los conceptos básicos
de modelado empleando VHDL, así como las diferencias semánticas entre VHDL y
los lenguajes de programación tradicionales. Con este ejemplo se pretende dar una

63
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

visión general de VHDL. Los detalles acerca de la sintaxis y las construcciones del
lenguaje VHDL se explicarán en el Tema 2.

Tal como se explicó en la Sección l. 7, un sistema digital puede ser descrito en


cuatro niveles de abstracción (transistor, puertas lógicas, RTL y procesador) y desde
tres visiones o representaciones diferentes (comportamiento, estructura y física).

El lenguaje VHDL permite realizar descripciones del comportamiento y la es-


tructura de los circuitos digitales al nivel de puertas lógicas, RTL y procesador. Es
decir, permite:

- Describir el comportamiento del circuito mediante funciones lógicas, operacio-


nes de transferencia entre registros y algoritmos.

- Describir la estructura del circuito mediante la instanciación y conexión de


unidades de diseño de diferente complejidad, desde puertas lógicas hasta IPs.

En esta sección se mostrarán diferentes diseños de un circuito muy sencillo: un


detector de paridad. Se trata de un circuito con tres entradas, agrupadas en un bus,
y una salida. La salida toma el valor '1' cuando hay un número par de entradas con
valor '1 '. Se supone que el cero es un número par. Por ello, la salida vale '1' bien
cuando ninguna de las entradas vale '1 ', o bien cuando dos de las entradas valen '1 '.

Se realizarán tres descripciones del comportamiento del circuito, una al nivel


de funciones lógicas y dos descripciones abstractas diferentes. Por tratarse de un
circuito muy sencillo, sólo se realizará una descripción estructural, empleando para
ello los bloques constitutivos digitales más sencillos: las puertas lógicas.

1.8.1. Comportamiento al nivel de funciones lógicas

En la Tabla 1.1 se muestra la tabla de la verdad del circuito, que tiene tres
entradas (a 2 , a 1 , a0 ) y un salida (par). Obsérvese que la salida tiene el valor '1'
cuando la palabra de tres bits de entrada tiene un número par de bits '1'. Al realizar
el diseño, se considera que el cero es un número par.

A partir de la tabla de la verdad, puede obtenerse la función lógica que describe


la salida del circuito:

(1.2)

64
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

Tabla 1.1: Tabla de la verdad de un detector de paridad.

a2 al ao par
o o o 1
o o 1 o
o 1 o o
o 1 1 1
1 o o o
1 o 1 1
1 1 o 1
1 1 1 o

El código VHDL que describe el circuito, en base a su comportamiento al nivel


de función lógica, consta de dos unidades de diseño: entity y architecture.

- La unidad de diseño entity especifica los puertos de entrada y salida del


circuito. El circuito tiene un puerto de salida (par) y un puerto de entrada
(a), que es un vector de tres componentes: a(2), a(1) y a(O). La declaración de
la entity es mostrada en el Código VHDL 1.1.
La señal par es del tipo std_logic. Una señal del tipo std_logic usa un
sistema lógico con nueve valores. Además de 'O' y '1', usados para los valores
binarios, hay otros valores que sirven para representar valores intermedios y
desconocidos. Los más comúnmente usados son: 'U' (cuando a la señal no se
le ha asignado todavía un valor), 'X' (cuando el valor de la señal no puede ser
determinado, por ejemplo debido a que es generada por dos puertas lógicas,
y una trata de poner el valor de la señal a 'O' y la otra a '1 ') y 'Z' (alta
impedancia).
Los conjuntos de líneas de señal pueden ser usados como un único elemen-
to (denominado bus) en un circuito lógico digital. El tipo std_logic_vector
representa un vector de señales del tipo std_logic.

- La unidad de diseño architecture especifica la operación interna y la organi-


zación del circuito. Se muestra en el Código VHDL 1.2.

Las palabras reservadas (por ejemplo, enti ty, is, port, in, out, end) y los
nombres definidos por el usuario (por ejemplo, not1, xor2, and2, xO, x1, y) pueden
escribirse en VHDL 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 en ti ty, ENTITY y EnTi Ty, así como también es
equivalente escribir detectorPar y DETECTORPAR.

65
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Detector de número par de entradas '1'


-- entity
-- fichero: detector Par. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity detectorPar is
port ( par : out std_logic;
a : in std_logic_vector(2 downto o) );
end entity detectorPar;

Código VHDL 1.1: Entity del circuito detector de paridad.

-- Detector de número par de entradas '1'


-- architecture comportamiento func logica
-- fichero: comp_funcLog. vhd
library IEEE;
use IEEE. std_logic_1164. all;

architecture comp_funcLog of detectorPar is


signal p1, p2, p3, p4 : std_logic;
begin
par <= ( p1 or p2 ) or ( p3 or p4 ) after 20 ns;
p1 <= ( not a(2) ) and ( not a(1) ) and ( not a(O) ) after 15 ns;
p2 <= ( not a(2) ) and a(1) and a(O) after 12 ns;
p3 <= a(2) and ( not a(1) ) and a(O) after 12 ns;
p4 <= a(2) and a(1) and ( not a(O) ) after 12 ns;
end architecture comp_funcLog;

Código VHDL 1.2: /A rchitecture del detector de paridad describiendo el comportamiento


mediante la función lógica.

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 carácter del nombre.

Los comentarios comienzan con doble guión (--) y se extienden hasta el final de
la línea. Está permitido escribir comentarios en cualquier parte del código VHDL.
Cuando se desea comentar varias líneas seguidas de código, es preciso anteponer
el doble guión a cada una de ellas. VHDL'93 no ofrece la sintaxis para comentar
simultáneamente varias líneas de código. En la práctica esto no supone ninguna
limitación, ya que las herramientas de CAD que soportan VHDL suelen proporcionar
opciones de edición para comentar y descomentar cómodamente varias líneas de
texto. Es decir, es la herramienta de CAD quien antepone el doble guión o lo borra
de las líneas de código que el usuario ha seleccionado.

66
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

La primera línea de la architecture muestra el nombre del cuerpo, comp_funcLog,


y la correspondiente entity, detectorPar. La siguiente línea es la declaración de las
señales:

signal p1, p2, p3, p4 : std_logic;

Las señales p1, p2, p3 y p4 pueden ser interpretadas como conexiones entre las
partes internas. La declaración es visible sólo dentro de la architecture.

La descripción de la architecture está comprendida entre begin y end archi-


tecture. Está compuesta por cinco asignaciones concurrentes a señales:

par <= ( p1 or p2 ) or ( p3 or p4 ) after 20 ns;


p1 <= ( not a(2) ) and ( not a(1) ) and ( not a(O) ) after 15 ns;
p2 <= ( not a(2) ) and a(1) and a(O) after 12 ns;
p3 <= a(2) and ( not a(1) ) and a(O) after 12 ns;
p4 <= a(2) and a(1) and ( not a(O) after 12 ns;

Una asignación concurrente puede ser interpretada como un bloque del circuito.
La señal de la izquierda de la asignación es la salida del bloque. Todas las señales
que intervienen en la parte derecha de la asignación son las entradas al bloque.
El resultado está disponible tras un cierto retardo, que se especifica mediante la
cláusula after.

Por ejemplo, la sentencia de asignación concurrente

par <= ( p1 or p2 ) or ( p3 or p4 ) after 20 ns;

puede ser interpretada como un bloque circuital con entradas p1, p2, p3 y p4, y salida
par. El bloque realiza la operación OR de las cuatro entradas, y la operación tarda
20 ns en realizarse. Las otras cuatro asignaciones pueden ser interpretadas de forma
análoga.

Esta architecture contiene cinco asignaciones concurrentes, que son interpreta-


das como cinco bloques circuitales. Las asignaciones concurrentes están conectadas
a través de las señales que tienen en común. Cuando una señal aparece en la parte
izquierda de una asignación y en la parte derecha de otra, esto significa que hay
una conexión entre el bloque circuital representado por la primera asignación y el
bloque circuital representado por la segunda. En la Figura l. 7 se muestra el diagrama
conceptual de esta architecture.

Obsérvese que, puesto que cada sentencia de asignación concurrente representa


una parte del circuito y su interconexión, el orden en que se escriben las sentencias
de asignación concurrente es indiferente. Por ejemplo, podría escribirse el código de
la forma siguiente:

67
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

a(2) (not a (2)) and p1


a (1) (not a (1)) and -
a (O) (not a (O))

~~ (not a (2)) and p2


a (1) and
a (O)
~ (p1 or p2) or par
1---
..___ (p3 or p4)
a(2) and
(not a (1)) and
_Jr=
a (O)

'----
a(2) and
p4
- a (1) and -
(not a (O))

Figura l. 7: Diagrama conceptual de la architecture comp_funcLog.

p2 <= ( not a(2) ) and a(i) and a(O) after i2 ns;


p3 <= a(2) and ( not a(i) ) and a(O) after i2 ns;
par <= ( pi or p2 ) or ( p3 or p4 ) after 20 ns;
pi <= ( not a(2) ) and ( not a(i) ) and ( not a(O) ) after i5 ns;
p4 <= a(2) and a(i) and ( not a(O) ) after i2 ns;

Al contrario de lo que sucede con las sentencias en un lenguaje de programación,


las sentencias concurrentes de asignación a señal son independientes entre sí, y
pueden activarse en paralelo.

Si alguna de las señales de entrada cambia de valor en el instante t, la sentencia


concurrente es activada en dicho instante t. Es decir:

l. Se evalúa la expresión de la parte derecha de la asignación, usando para ello


el valor que tienen las señales de entrada en dicho instante t.

2. Se planifica asignar a la señal de salida (la situada en la parte izquierda de la


asignación) el valor calculado, de manera que el nuevo valor se asignará a la
señal una vez haya transcurrido el retardo de propagación especificado en la
sentencia de asignación.

Como se explicó anteriormente, cuando se realiza el diseño de alto nivel frecuen-


temente se desconoce el valor del retardo de los bloques circuitales, ya que todavía no
se ha realizado la síntesis. Es decir, no se ha especificado cómo va a implementarse en
hardware el bloque circuital. Por este motivo, en el diseño de alto nivel de los circuitos
no suele indicarse explícitamente el valor del retardo, omitiéndose la cláusula after
en las sentencias de asignación a señal. Por ejemplo, puede escribirse:

68
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

-- Detector de núm ero par de entradas '1 '


-- archit ecture comportamiento fun c log xor
-- fi chero: comp_funcLog_xor. vhd
library IEEE;
use IEEE. std_logic_1164. all;
architecture comp_funcLog_xor of detectorPar is
signa! impar : std_logic;
begin
par <= not impar;
impar <= a(2) xor a(1) xor a(O);
end architecture comp_funcLog_xor;

Código VHDL 1.3: Architecture del detector de paridad describiendo el comportamiento


mediante la función lógica xor.

par<= e pi or p2) ore p3 or p4 );

En este caso, la semántica de VHDL especifica que hay un cierto retardo o


o
implícito asociado a la operación. El retardo es un retardo infinitesimal, que es
mayor que cero, pero menor que cualquier número físico. La sentencia anterior debe
ser interpretada como:

par <= e pi or p2 ) or e p3 or p4 ) after 5;

Así pues, con independencia de que se especifique la cláusula after, siempre hay
un retardo de propagación asociado a una sentencia concurrente.

La tabla de la verdad es sólo un método de describir el comportamiento del


circuito. Una alternativa es usar la operación or-exclusiva (XOR). La operación or-
exclusiva puede ser usada para detectar si hay un número par de entradas con valor
'1 ', ya que la operación a EB b vale '1' cuando sólo una de las entradas vale '1 '. Por
ello, el circuito puede ser descrito mediante la función lógica siguiente:

(1.3)

El cuerpo de la architecture basado en esta función lógica se muestra en el


Código VHDL 1.3.

Nuevamente, las dos sentencias concurrentes de asignación representan dos partes


del circuito. En la Figura 1.8 se muestra el diagrama conceptual del circuito. Puesto
que no se especifica el valor del retardo, se supone que cada uno de los dos bloques
circuitales tiene un retardo o.

69
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

a(2)
impar par
a (1) a ( 2) xor a ( 1) xor a (O) 1--------1 not impar
a (O)

Figura 1.8: Diagrama conceptual de la architecture comp_funcLog_xor.

a( O)

:~ :
___ : : : : : :
::~·::::::::::::::::::::::::::::::::::::¡
: : : ~==
: . :
· ~
. ¡
x ·R ·
..·....· · ·
...o ··.·.·.·.·.·.~.·
· D · . · ~ = .
a(2)
........................................ unitl
........................................

Figura 1.9: Diagrama estructural (esquemático) al nivel de puertas.

1.8.2. Descripción de la estructura

En la visión estructural, el circuito está compuesto de componentes (esto es,


bloques circuitales) conectados entre sí. La descripción especifica el tipo de cada
componente y su conexión. Para ello, en el cuerpo de la architecture, el componente
primero debe ser declarado, y a continuación instanciado y conectado.

En la Figura l. 9 se muestra el diagrama estructural del circuito que detecta un


número par de entradas con valor '1 '. El circuito está compuesto de dos puertas
XOR y un inversor. Esta descripción corresponde con la función lógica mostrada en
la Ec. (1.3). En el Código VHDL 1.4 se define la puerta inversora y la puerta XOR
de dos entradas.

Una vez definidas las puertas lógicas, puede describirse el circuito de la manera
mostrada en el Código VHDL 1.4. Obsérvese que la descripción de los componentes
(en este caso las puertas XOR y NOT) puede codificarse en ficheros diferentes y
compilarse separadamente del fichero en el cual se define el circuito. Esto permite
crear librerías de componentes y facilita la reutilización del código.

Dentro de la architecture, en primer lugar se declaran los componentes. Por


ejemplo, la declaración de la puerta XOR es la siguiente.

component xor2 is
port ( yO out std_logic;
xO, x1 in std_logic );
end component xor2;

70
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

-- Inversor de 1 entrada: not1


-- fichero: notl. vhd
library IEEE; use IEEE. std_logic_1164. all;
entity not1 is
port ( yO : out std_logic;
xO : in std_logic ) ;
end entity not1;
architecture not 1 of not 1 is
begin
yO <= not xO;
end architecture not 1;

-- OR exclusiva de 2 entradas: xor2


-- fichero: xor2. vhd
library IEEE; use IEEE. std_logic_1164.all;
entity xor2 is
port ( yO : out std_logic;
xO, x1 : in std_logic );
end entity xor2;
architecture xor2 of xor2 is
begin
yO <= xO xor x1;
end architecture xor2;

-- Detector de número par de entmdas '1'


-- architecture estructura puertas xor-not
-- fichero: estruc_xor_not. vhd
library IEEE;
use IEEE. std_logic_1164. all;
architecture estruc_xor _not of detectorPar is
component xor2 is
port ( yO : out std_logic;
xO, x1 : in std_logic );
end component xor2;
component not 1 is
port ( yO : out std_logic;
xO : in std_logic ) ;
end component not 1;
signal s 1, s2 : std_logic;
begin
unit1 : xor2 port map ( xO => a(O), x1 = > a(1), yO = > s1 );
unit2 : xor2 port map ( xO = > s1, x1 = > a(2), yO = > s2 );
unit3 : not1 port map ( xO => s2, yO = > par );
end architecture estruc_xor _not;

Código VHDL 1.4: Puerta inversora. Puerta XOR con dos entradas. Architecture del detector
de paridad describiendo la estructura del circuito.

71
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

La información contenida dentro de la declaración es similar a la declaración de


la entity del componente, en la cual se especifican sus puertos de entrada y salida.

Aparte de la declaración de los componentes, en la architecture se declaran


también dos señales internas:

signa! s1, s2 : std_logic;

El cuerpo de la architecture consiste en tres sentencias, en cada una de las


cuales se instancia y conecta un componente. La primera es:

unit1 : xor2 port map ( xO => a(O), x1 => a(1), yO=> s1 );

Hay tres elementos en esta sentencia. El primero es la etiqueta uni t 1, que sirve
para designar este componente. El segundo es la clase del componente: xor2. La
tercera es port map ( ... ), que define la correspondencia entre las señales formales
(puertos definidos en la entity del componente) y las señales actuales (las señales
usadas en el cuerpo de la architecture).

En este ejemplo, port map ( ... ) indica que xO, x1, yO están conectadas a
a(O), a(1), s1 respectivamente. El código es esencialmente la descripción textual del
esquemático mostrado en la Figura 1.9. Las tres instanciaciones de los componentes
describen el circuito completo. Las conexiones se realizan implícitamente, usando el
mismo nombre de la señal.

La instanciación de un componente es un tipo de sentencia concurrente y puede


mezclarse en el cuerpo de una architecture con otros tipos de sentencias concurren-
tes, tales como las sentencias de asignación concurrente a señal o como los bloques
process, que explicaremos a continuación.

1.8.3. Descripción abstracta del comportamiento

En un diseño grande, la implementación puede ser muy compleja. Por este motivo,
el diseño se realiza en diferentes pasos, progresando desde una descripción inicial
abstracta del funcionamiento del circuito, independiente de la plataforma hardware
que vaya a usarse para implementar el circuito, hasta llegar a la descripción detallada
al nivel hardware.

El lenguaje VHDL facilita al diseñador realizar una descripción abstracta del


comportamiento del circuito. Uno de los recursos que proporciona para ello el lengua-
je son los bloques process. Un bloque process es una construcción que encapsula
un fragmento de código VHDL secuencial, y dentro de la cual pueden declararse y

72
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

usarse variables, que son locales al bloque process. La característica distintiva del
código secuencial es que es ejecutado en el mismo orden en el cual ha sido escrito.
La sintaxis básica del bloque process es la siguiente (en la Sección 2. 7 se ofrece una
descripción más completa):

process ( lista_de_sensibilidad )
Declaración de variables locales
begin
Código_secuencial
end process;

En el bloque process puede especificarse una lista de señales, denominada lista de


sensibilidad, que defina las condiciones para la ejecución del bloque: cuando cambia
el valor de alguna de las señales incluidas en esta lista, entonces se ejecuta el cuerpo
del bloque process.

A continuación, se muestran dos ejemplos de descripción abstracta del compor-


tamiento del circuito detector de un número par de entradas '1'.

El primer ejemplo, mostrado en el Código VHDL 1.5, corresponde conceptual-


mente con el diagrama mostrado en la Figura 1.10. La architecture comp_red_xor
contiene un bloque process, que utiliza una variable y un bucle for. Al contrario de
lo que sucede con las señales y las asignaciones a señales, la variable y el bucle no
tienen una correspondencia directa con el hardware. El bloque process se trata como
una unidad indivisible, cuyo comportamiento es especificado mediante sentencias
secuenciales.

El segundo ejemplo usa únicamente un bloque process, en el cual se describe el


algoritmo que realiza la operación que se desea que realice el circuito. Se muestra
en el Código VHDL 1.6. En primer lugar, el algoritmo suma el número de '1' en las
entradas, calcula el resto de la división entre 2, y finalmente usa una sentencia if
para generar el resultado en función del valor del resto de la división. Puesto que
la architecture contiene únicamente un bloque process, el diagrama conceptual
contiene un único bloque, tal como se muestra en la Figura 1.11. El código es muy
fácilmente comprensible y sencillo de programar, y no contiene ninguna información
acerca de cómo debe ser convertido en hardware.

73
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- D etector de número par de entradas '1 '


-- aTchitecture comportamiento Ted xor
-- fichero: comp_recLxor. vhd
library IEEE;
use IEEE. std_logic_1164. all;
architecture comp_red_xor of detectorPar is
signal impar : std_logic;
begin
par <= not impar;
process (a)
variable tmp : std_logic;
begin
tmp := '0';
for i in 2 downto O loop
tmp := tmp xor a(i);
end loop;
impar <= tmp;
end process;
end architecture comp_red_xor;

Código VHDL 1.5: Architecture del detector de paridad descrita mediante una red XOR.

procesa (a)
variable tmp : std_logic;
a(2) begin
tmp . - 1 o 1 i impar par
a (1) for i in 2 downto o loop
not impar
a (O) tmp . - tmp xor a(i);
end loop;
impar <= tmp;
end procese;

Figura 1.10: Diagrama conceptual de la architecture comp_recLxor.

74
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

-- Detector de número par de entradas '1 '


-- architect7LTe comportamiento algoTitmo
-- fic hem: comp_alg. vhd
library IEEE;
use IEEE . std_logic_1164. all;
architecture comp_alg of detectorPar is
begin
process (a)
variable suma, r : integer;
begin
suma :=O;
for i in 2 downto O loop
if a( i) = ' 1 ' then
suma := suma + 1;
end if;
end loop;
r := suma mod 2;
if (r = o) then
par < = '1';
el se
par < = '0';
end if;
end process;
end architecture comp_alg;

Código VHDL 1.6: Architecture del det ect or de paridad descrita mediante un algoritmo.

procesa (a)
variable suma, r : integer;
begin
suma . - o i
for i in 2 downto o loop
if a (i) = 111 then
a(2) suma . - suma + 1;
end if; par
a ( 1) end loop;
a(O) r . - suma mod 2·,
if (r = O) then
pa r <= 111 i
el se
pa r <= 1 o 1 i
end if;
end procesa;

Figura 1.11: Diagrama concept ual de la architecture comp_alg.

75
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

1.8.4. Banco de pruebas

Uno de los usos principales de un programa en VHDL es la simulación, que se usa


para estudiar la operación del circuito y para verificar que el diseño se ha realizado
correctamente. Realizar una simulación es similar a realizar un experimento con el
circuito real, en el cual se conectan las entradas del circuito a un generador de señales
y se observan las salidas del circuito empleando un analizador lógico.

Simular una descripción VHDL es como realizar un experimento virtual, en el


cual el circuito físico es reemplazado por la correspondiente descripción VHDL. Se
pueden programar unas rutinas en VHDL que generen los vectores de test y otras
que comparen las respuestas obtenidas de aplicar los vectores de test al circuito, con
las respuestas que deberían obtenerse del circuito.

El Código VHDL 1.7 es un banco de pruebas para el circuito detector de un


número par de entradas '1'. El banco de pruebas consta de una entity y una
architecture. Puesto que el banco de pruebas está autocontenido, la entity no
tiene ningún puerto. La architecture consta de tres sentencias concurrentes: la
instanciación del componente a testear y dos bloques process. Un bloque process
se usa para generar los vectores de test y el otro se usa para comprobar que las
salidas del circuito son correctas.

El bloque process llamado vecLtest es el generador de estímulos: produce todas


las combinaciones de valores de la entrada al circuito, desde "000" hasta "111". Cada
una de las combinaciones de las entradas se mantiene durante 200 ns. Obsérvese que
las comillas simples (' ') se usan para los bits individuales, mientras que las comillas
dobles (" ") se usan para los vectores.

El segundo bloque process, llamado verif, espera a que se produzca un cambio


en las señales de entrada, a continuación espera 100 ns más, con el fin de permitir
que se estabilicen las señales de salida del circuito, y entonces comprueba el valor
obtenido de las salidas con el valor correcto conocido. Si ambos valores no coinciden,
muestra un mensaje indicando el error.

En este punto no es importante entender los detalles de la definición de los bloques


process, tan sólo importa entender el concepto. En la Figura 1.12 se muestra un
esquema conceptual del banco de pruebas.

76
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

-- Banco de pruebas del detector de número par de entradas '1 '


-- fichero: bp_detectorPar.vhd
library IEEE; use IEEE . std_logic_1164. all;

entity bp_detectorPar is
end entity bp_detectorPar;

ar-r.;hitecture bp_arch of bp_detectorPar is


component detectorPar is
port ( par out std_logic;
a in std_logic_vector(2 downto o) );
end component detectorPar;
signal test_in : std_logic_vector(2 downto O);
signal test_out : std_logic;
begin
-- Instancia del circuito que va a ser testeado
UUT : detectorPar port map ( par => test_out, a => test _in );
-- Vectores de test
vect_test: process
begin
test_in <= "000"; wait for 200 ns;
test_in <= "001"; wait for 200 ns;
test_in <= "010"; wait for 200 ns;
test_in <= "011"; wait for 200 ns;
test_in <= "100"; wait for 200 ns;
test_in <= "101"; wait for 200 ns;
test_in <= "110"; wait for 200 ns;
test_in <= "111"; wait for 200 ns;
end process vect_ test;
-- Verificación de las salidas
verif : process
variable error _status : boolean;
begin
wait on test_in; wait for 100 ns;
if ( ( test_in = "000" and test_out = '1 ') or
( test_in "001" and test out '0') or
( test_in "010" and test_out '0') or
( test_in "011" and test out '1 ') or
( test_in "100" and test out '0') or
( test_in "101" and test_out '1 ') or
( test_in = "110" and test out '1 ') or
( test_in "111" and test_out = 'o') )
then
error_status := false;
el se
error _status := true;
end if;
assert not error _status report "Test fallado. 11 severity note;
end process verif;
end architecture bp_arch;

Código VHDL l. 7: Banco de pruebas del detector de paridad.

77
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

vect_ test: procesa verif : procesa


begin variable error_sta tu s : boolean;
test_in <= "000"; begin
wait for 200 ns; wai t on test in;
test_in <= " 00 1" ;
wait for 200 ns;
UUT wait for 10 0-ns;
if ( ( test_in = "000" and te st_out = '1' )
test_in <= "010"; ( test_in = "001" and test_out = ' O' )
wait for 200 ns ;
( test_in = " 010" and test_out = 'O' )
test_in < = 11 01 1" ; test in test out ( test_i n = "011" and test_out = '1')
wait for 200 ns; f - - - - . - - - - - - l A [ 2 .. OJ par f-----~ ( test_in = "lOO" and test_out = ' O' )
test_in <= 11 100"; ( test_in = "1 01 " and test_out = '1 ' )
wait for 200 ns;
( test_in = "110" and t est_out = '1' )
te st_in <= 11 1 01 11 ; ( test_i n = "111" and test_out = 'O' ) )
wait for 200 ns; then
test_in <= "110 11 ; error_status : = falsa ;
wait for 200 ns; el se
test in <= "111 11 ; error_ stat u s : = true ;
wait- for 200 ns; end if;
end procesa vect_test; assert not error_status
report "Test fa lla do."
severity note ;
end procesa verif;

Figura 1.12: Diagrama conceptual del banco de pruebas.

1.8.5. Configuración

El lenguaje VHDL separa de manera intencionada la declaración de la entity


y la architecture en dos . unidades de diseño independientes. Esto facilita asociar
múltiples architecture con una determinada entity.

Por ejemplo, la entity detectorPar de esta sección tiene media docena de archi-
tecture. A la hora de realizar la simulación y la síntesis, debemos especificar qué
architecture asociar con la entity. Esto puede hacerse definiendo una configura-
tion, como la mostrada en el Código VHDL 1.8 para nuestro circuito ejemplo. Si no
se ha definido una configuration, el entorno de simulación escogerá por defecto la
última architecture que ha sido compilada.

-- Detector de número par de entradas '1'


-- Configuration
--fichero: conf_detectorPar.vhd
configuration conf_detectorPar of bp_detectorPar is
for bp_arch
for uut: detectorPar
use entity work. detectorPar( comp_alg);
end for;
end for;
end configuration conf _detectorPar;

Código VHDL 1.8: Configuration para la simulación del banco de pruebas del detector de
paridad.

78
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

1.9. DOS SIMULADORES DE VHDL'93: VERIBEST Y MODELSIM

En este texto se proponen diferentes casos de diseño de circuitos digitales usando


el lenguaje VHDL, que el alumno debe simular en su propio ordenador empleando
algún simulador de VHDL'93. En los Apéndices A y B se proporcionan algunas
indicaciones básicas para la instalación y manejo de dos simuladores de VHDL'93:
VeriBest VHDL y ModelSim PE 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 M odelSim.

La única ventaja de VeriBest es que funciona para casi todas las versiones anti-
guas 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 decir, si el alumno dispone de
un ordenador relativamente moderno, es preferible emplear M odelSim en lugar de
VeriBest VHDL.

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 JI Web
Edition, que puede descargarse gratuitamente del sitio web de la compañía Altera
Corporation.

1.9.1. Diseño de un buffer triestado

En los Apéndices A y B se emplea el modelo de un buffer triestado para ilustrar


las explicaciones acerca del manejo del simulador. A continuación, se describe el
modelo VHDL del buffer triestado y de su banco de pruebas.

El buffer triestado se emplea comúnmente para conectar varios dispositivos a


un mismo bus. Tal como se muestra en la Figura 1.13, el buffer triestado tiene dos
entradas (d y E) y una salida (y). Dependiendo del valor de la entrada E, la salida
puede tomar el valor de la entrada o el valor Z (alta impedancia). Cuando el buffer
se encuentra en el estado de alta impedancia, se comporta como un circuito abierto.

79
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

b)

Figura 1.13: Buffer triestado: a) símbolo lógico; b) tabla de la verdad.

-- Modelo del buffer triestado


-- buffer Triestado. vhd
library IEEE;
use IEEE. std_logic_1164.all;

entity Buffer_TriEstado is port


( y : out std_logic;
E : in std_logic;
d : in std_logic ) ;
end entity Buffer_TriEstado ;

architecture Behavioral of Buffer_TriEstado is


begin
process (E, d)
begin
if (E = ' 1 ') then
y<= d;
else
y<= 'Z';
end if;
end process;
end architecture Behavioral;

Código VHDL 1.9: Buffer triestado.

El Código VHDL 1.9 describe el comportamiento de un buffer triestado. Obsér-


vese que el diseño consta de tres partes. En primer lugar, se indica qué librerías van
a usarse en la definición del modelo. A continuación, se define la interfaz del circuito
(módulo entity). Finalmente, se define el comportamiento del circuito (módulo
architecture). Todo ello será explicado con detalle en el tema siguiente.

1.9.2. Diseño del banco de pruebas

Una vez descrito el circuito, el siguiente paso es programar su banco de pruebas.


El banco de pruebas mostrado en el Código VHDL 1.10 genera las 22 posibles
combinaciones de entrada al buffer.

80
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

-- Banco de pruebas
-- bp_bufferTriestado. vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity bp_Buffer_TriEstado is
end entity bp_Buffer_TriEstado;
architecture bp_Buffer_TriEstado of bp_Buffer_TriEstado is
signa} y : std_logic; -- Conectar salida UUT
signa} d, E : std_logic; -- Conectar entradas UUT
component Buffer_ TriEstado is port
( y : out std_logic;
E, d : in std_logic ) ;
end component Buffer_TriEstado;
begin
-- Instanciar y conectar UUT
uut : component Buffer_TriEstado port map
( y => y, E => E, d => d );
gen_ ve e_ test : process
begin
E <= '0'; d <= '0';
wait for 10 ns;
d <= '1';
wait for 10 ns;
E<= '1';
wait for 10 ns;
d <= '0';
wait for 10 ns;
report "Final de la simulación";
wait;
end process gen_ ve e_ test;
end architecture bp_Buffer_TriEstado;

Código VHDL 1.10: Banco de pruebas del buffer triestado.

Messages

+ /bp buffer triestado/y z 1


+ /bp_buffer _triestado/d o 1 1
+ /bp_buffer _triestado/e o 1

1 1 1 1 1 ~ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
~~i¡') Now 40 ns 12 ns 16 ns 20 ns 24 ns 28 ns 32 ns
IS 4nsg8ns 36 ns 40 ns
~#'O Cursor 1 6 ns 6 ns
[[1 www 1 1 I/
1 O ns to 43 ns 1 Now: 40 ns Delta: 1

Figura 1.14: Simulación del banco de pruebas del buffer triestado.

La definición del banco de pruebas contiene las mismas tres partes que la descrip-
ción del circuito: en primer lugar se indica qué librerías van a usarse, a continuación
se define la interfaz del circuito (módulo entity) y finalmente se define su compor-
tamiento (módulo architecture).

81
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

La interfaz del banco de pruebas no contiene ningún puerto. En la architecture


se instancia el circuito que va a ser probado (UUT) y se definen las señales y, E
y d, que son conectadas a los puertos del UUT. En el bloque process llamado
gen_vec_test, se define la secuencia de vectores de test que son aplicados al UUT.

En la Figura 1.14 se muestra el resultado obtenido de simular el banco de pruebas.


La salida del buffer toma el valor de alta impedancia (Z) desde el instante O ns hasta
el instante 20 ns. Esto de debido a que durante ese tiempo se asigna E = 'O' (en la
figura aparece e en lugar de E, debido a que VHDL no diferencia entre mayúsculas
y minúsculas). Desde ese instante, hasta el final de la simulación (40 ns), la salida
del circuito (y) toma el mismo valor que la entrada d.

En los siguientes temas de esta Uni dad Didáctica se explicará con detalle la
forma en que debe realizarse el diseño de los circuitos y de sus bancos de pruebas.
La finalidad de este ejemplo del buffer triestado es simplemente proporcionar código
VHDL sencillo con el cual aprender el manejo del simulador de VHDL.

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.

1.10. LECTURAS RECOMENDADAS

El Capítulo 1 de (Chu 2006) proporciona información adicional acerca de los


niveles de abstracción en la representación de los sistemas digitales, y acerca del ciclo
de diseño del hardware digital y el papel de los HDL. Acerca de las características
de los lenguajes para la descripción del hardware, se recomienda la consulta del
Capítulo 2 de (Chu 2006). El Capítulo 2 de (Lee 2006) es una buena referencia
acerca del diseño de lógica digital usando lenguajes para la descripción del hardware.
En (Armstrong & Gray 2000) puede encontrarse información adicional acerca de las
diferentes tecnologías de circuitos integrados y acerca de la integración de VHD L en
la metodología de diseño.

82
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

1.11. EJERCICIOS DE AUTOCOMPROBACIÓN

Ejercicio 1.1

Discuta razonadamente por qué una descripción HDL es más portable que un
diseño esquemático.

Ejercicio l. 2

Discuta razonadamente la veracidad o falsedad de la siguiente afirmación:

"Empleando cualquier herramienta de síntesis se genera, a partir de una descrip-


ción HDL, una única descripción al nivel de puertas lógicas o transistores."

Ejercicio 1.3

Suponga que quiere implementar una única unidad de un circuito integrado con
un coste de producción mínimo. Indique razonadamente cuál de las tres tecnologías
siguientes conllevará un coste de producción menor: FPGA, gate array y standard
cell.

Ejercicio 1.4

Señale cuál de las siguientes cuatro afirmaciones es falsa:

A. La implementación hardware de un circuito digital empleando un circuito


integrado de la tecnología FPGA consume menor cantidad de potencia que
si se emplea un circuito integrado de las tecnologías standard cell o gate array.

B. La tecnología standard cell permite construir circuitos integrados con menores


retardos de propagación que las tecnologías FPGA y gate array.

C. El área del circuito integrado depende de la arquitectura del circuito y de la


tecnología.

D. La contribución del coste de ingeniería al coste de producción de un circuito


integrado depende del número de unidades producidas.

83
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 1.5

Señale al menos tres de las causas de mal funcionamiento de los chips más
comúnmente observadas en la práctica.

Ejercicio 1.6

Dada una puerta AND de dos entradas (A y B) y una salida (z), se pide obtener
el mínimo número de vectores de test que detectan los 6 patrones de fallos siguientes:

- La entrada A se encuentra permanentemente a O (A/0).

- La entrada B se encuentra permanentemente a O (B/0).

- La salida z se encuentra permanentemente a O ( z /O).

- La entrada A se encuentra permanentemente a 1 (A/1).

- La entrada B se encuentra permanentemente a 1 (B/1).

- La salida z se encuentra permanentemente a 1 ( z /1).

Para designar el fallo de que una señal x se encuentra permanentemente al valor


v se ha usado la notación x/v. Indique también cuántos vectores de test habría que
usar para probar exhaustivamente el funcionamiento del circuito.

Ejercicio l. 7

Dado el circuito mostrado en la Figura 1.15, indique un vector de test que


permita detectar que el nodo E (nodo de entrada a la puerta ancL2) se encuentra
permanentemente a l.

84
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

y
...........................

Figura 1.15: Circuito a testear, correspondiente al Ejercicio l. 7.

Ejercicio 1.8

Se ha diseñado usando VHDL un circuito para controlar la alarma de seguridad


de un coche. La alarma de seguridad del coche se enciende siempre que, estando la
llave del coche puesta en el contacto, la puerta del coche está abierta o el cinturón
de seguridad del conductor no está abrochado. El circuito tiene las señales de salida
y de entrada siguientes:

- Warning: se pone a 1 para encender la alarma.

- Igni tion: se pone a 1 si la llave del coche está puesta en el contacto.

- Door: se pone a 1 si la puerta está cerrada.

- Sbelt: se pone a 1 si el cinturón del conductor está abrochado.

Indique razonadamente qué tipo de representación y nivel de abstracciones tienen


las dos descripciones del circuito de control de alarma de un coche mostradas en el
Código VHDL 1.11 y 1.12.

85
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

---Circuito de control de la alarma de un coche. Fichero: buzzer 1. vhd


library IEEE;
use IEEE. std_logic_1164. all;
entity buzzer is
port ( Warning : out std_logic;
Door, Ignition, Sbelt : in std_logic);
end entity buzzer;
architecture buzzer1 of buzzer is
begin
Warning <= (not Door and Ignition) or (not SBelt and Ignition);

end architecture buzzer1;

Código VHDL 1.11: Diseño del circuito de control de la alarma de seguridad de un coche.

---Circuito de control de la alarma de un coche. Fichero: buzzer2. vhd


library IEEE;
use IEEE. std_logic_1164. all;
entity BUZZER is
port ( Warning : out std_logic;
Door, Ignition, Sbelt : in std_logic);
end entity BUZZER;
architecture buzzer2 of buzzer is
signal Door _not, Sbel t_not, B1, B2: std_logic;
component AND2
port ( yO : out std_logic;
xO, x 1 : in std_logic);
end component;
component OR2
port ( yO : out std_logic;
xO, x1 : in std_logic);
end component;
component NOT1
port ( yO : out std_logic;
xO : in std_logic);
end component;
begin
UO : NOT1 port map (Door _not, Door);
U1 : NOT1 port map (Sbelt_not, Sbelt);
U2 : AND2 port map (B1, Ignition, Door_not);
U3 : AND2 port map (B2, Ignition, Sbelt_not);
U4 : OR2 port map (Warning, B1, B2);

end architecture buzzer2;

Código VHDL 1.12: Diseño alternativo del circuito de control de la alarma de seguridad de un
coche.

86
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

1.12. SOLUCIONES DE LOS EJERCICIOS

Solución al Ejercicio 1.1

Una descripción HDL es más portable que un diseño esquemático ya que la


descripción HDL es simplemente un fichero de texto y no tiene que ser, como en el
caso de los diseños esquemáticos, visualizado y editado empleando la herramienta
gráfica específica del entorno de CAD con el que se ha creado.

Solución al Ejercicio 1.2

La anterior afirmación es falsa, ya que la descripción obtenida como salida de


la herramienta de síntesis depende no sólo de la descripción HDL de entrada, sino
también de la herramienta de síntesis empleada y de las especificaciones introducidas
en la herramienta. En particular, las herramientas de síntesis permiten especificar
el nivel de esfuerzo a emplear por la herramienta en la optimización automática del
circuito, tanto en lo que respecta a la reducción del área del circuito, como en lo
que respecta a sus prestaciones. Asimismo, las herramientas de síntesis permiten
especificar qué módulos del circuito no deben ser optimizados.

Solución al Ejercicio 1.3

El coste de producción (Cprod) depende del coste de fabricación (C¡ab), del coste
de ingeniería (Cing) y del número de unidades producidas, como se muestra en la
Ecuación 1.1.

Al producir una única unidad, el Cprod resultante es la suma de C¡ab y Cing·

La tecnología FPGA no tiene Cing, pero tiene un valor de C¡ab mayor que el que
tienen las otras dos tecnologías.

El valor de la suma C fab + Cing tanto de la tecnología standard cell como de la


tecnología gate array es mayor que el valor de C¡ab de la tecnología FPGA, que es
igual al valor de su Cprod·

Como resultado, para producir una única unidad la tecnología FPGA es la que
tiene un Cprod menor.

Por tanto, se elegirá el empleo de la tecnología FPGA.

87
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 1.4

La opción A es falsa, ya que la tecnología FPG A es la que consume mayor


cantidad de potencia de las tres.

Solución al Ejercicio 1.5

Abiertos, cortos y acopios.

Solución al Ejercicio 1.6

En la Tabla 1.2 se muestra para cada combinación de entrada cuál es la salida


correcta del circuito y cuál es la salida debida a cada patrón de fallo.

Tabla 1.2: Salidas de la puerta AND de 2 entradas para varios patrones de fallos.

Entradas Salida AjO B/0 z /0 A/1 B/1 z /1


A B correcta z z z z z z z
00 o o o o o o 1
o1 o o o o 1 o 1
1o o o o o o 1 1
11 1 o o o 1 1 1

Un vector de test que detecta un determinado patrón de fallo es una combinación


de valores de las señales de entrada, que hace que difiera la salida incorrecta de la
salida correcta.

Obsérvese que para los patrones de fallo A/0, B /0 y z /0 la salida incorrecta sólo
difiere de la salida correcta cuando las señales A y B del circuito tienen valor 1
(vector de test "11"). Este vector de test no nos va a permitir saber cuál de los tres
fallos se está produciendo.

- El patrón de fallo A/1 sólo se detecta con el vector de test "01".

- El patrón de fallo B /1 sólo se detecta con el vector de test "10".

- El patrón de fallo z /1 se puede detectar con los vectores de test "00", "O 1" y
"10'. Obsérvese que cualquier vector de test que detecte los patrones de fallos
A/1 o B /1, detecta también este patrón de fallo.

88
FUNDAMENTOS DEL DISEÑO DEL HARDWARE DIGITAL

Por tanto, el mínimo número de vectores de test para detectar los 6 patrones de
fallo es tres. Los tres vectores de test son los siguientes: "11", "01" y "10".

Para probar exhaustivamente el circuito, habría que testear el circuito para


cualquier valor de las señales de entrada. Puesto que existen dos señales de entrada,
que pueden tomar dos valores (O ó 1), el número de vectores de test para testear
exhaustivamente el circuito es 22 = 4.

Solución al Ejercicio l. 7

Para que pueda ser observado el valor en el nodo E, se pone la señal D a l. De


este modo, el valor de la señal de salida de la puerta ancL2 (y) es igual al valor en
el nodo E.

Para que el nodo E pueda ser controlado por las señales A o B, se pone el valor
e
de la señal a O. En consecuencia, el valor del nodo E es el resultado de realizar la
operación AND lógica de las señales A y B.

Si se ponen A o B a O, el valor correcto de la salida del circuito (y) es O. Pero, a


causa del fallo, la salida y va a tener valor l.

Por tanto, el vector de test que pone A a O, B a O, e a Oy D a 1 nos permite


detectar el fallo.

Obsérvese que no es necesario que las señales A y B tengan valor O simultánea-


mente, ya que el que una de estas dos señales tenga valor Oes suficiente para detectar
el fallo.

Solución al Ejercicio 1.8

El Código VHDL 1.11 es una representación del comportamiento del circuito,


expresada mediante funciones lógicas.

El Código VHDL 1.12 es una representación estructural del circuito al nivel de


puertas lógicas.

89
TEMA 2

CONCEPTOS BÁSICOS DE VHDL

2.1. Introducción
2.2. Unidades de diseño
2.3. Entity
2.4. Architecture
2.5. Asignaciones concurrentes
2.6. Sentencia generate
2.7. Bloque process
2.8. Código secuencial
2.9. Descripción de la estructura
2.10. Parametrización
2 .11. Señales, variables y constantes
2.12. Tipos de datos y operadores
2.13. Atributos
2.14. Librerías
2.15. Assert
2.16. Subprogramas
2.17. Paquetes
2.18. Lecturas recomendadas
2.19. Ejercicios de autocomprobación
2.20. Soluciones de los ejercicios
CONCEPTOS BÁSICOS DE VHDL

OBJETIVOS DOCENTES

Una vez estudiado el contenido del tema y realizados los ejercicios prácticos,
debería saber:

- Discutir la finalidad de las unidades de diseño de VHDL entity, architecture,


package y configuration.

- Describir la interfaz de los circuitos digitales mediante unidades de diseño


entity. Discutir las características y !'as diferencias entre los modos in, out e
inout de los puertos.

- Discutir la sintaxis y la finalidad de las sentencias concurrentes simple, condi-


cional y de selección. Dibujar el diagrama conceptual del hardware a que da
lugar la síntesis de estas sentencias y el correspondiente circuito al nivel de
puertas lógicas.

- Discutir la sintaxis y la finalidad de la sentencia generate.

- Discutir la sintaxis y la finalidad de los bloques process y de las sentencias


secuenciales de asignación a señal, a variable, if, case y del bucle for. En
casos sencillos, dibujar el diagrama conceptual del hardware a que da lugar
la síntesis del bloques process, y el correspondiente circuito compuesto de
puertas lógicas y biestables.

- Discutir cómo se realiza el modelado del retardo en VHDL.

- Definir en VHD L la estructura de un circuito mediante instanciación y cone-


xión de otros circuitos. Asimismo, discutir la utilidad de la parametrización en
la descripción de un circuito.

- Discutir las principales características de las señales, variables y constantes en


VHDL. Discutir la diferencia entre señales y variables en lo que respecta al
retardo en la asignación de los nuevos valores.

- Discutir cuáles son los tipos predefinidos de VHDL y sus operadores básicos.
Asimismo, discutir las finalidad, los operadores básicos y las funciones de
conversión de los tipos de dato std_logic, std_logic_vector, unsigned y
signed. Finalmente, discutir las características de los tipos de dato time y
string, así como de los tipos enumerados.

- Discutir qué son los atributos en VHDL y la finalidad de algunos de ellos.

93
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

- Discutir qué finalidad tienen las librerías en VHDL y conocer las librerías más
comúnmente usadas.

- Discutir la utilidad de los procedimientos y funciones de VHDL.

- Discutir la finalidad de las sentencias assert y report.

94
CONCEPTOS BÁSICOS DE VHDL

2.1. INTRODUCCIÓN

VHDL es un lenguaje complejo, con numerosas capacidades y librerías de fun-


ciones. De hecho, aunque es un lenguaje para describir hardware, posee muchas
de las capacidades de los lenguajes de programación (tales como C o Fortran),
incluyendo estructuras record, funciones, procedimientos y soporte a bloques de
código compilados separadamente.

Pese a lo anterior, para la mayor parte de las aplicaciones de VHDL al modelado


y simulación de circuitos digitales, es suficiente con emplear un pequeño subconjunto
de las estructuras y capacidades proporcionadas por el lenguaje. En particular,
se ha definido un subconjunto del lenguaje VHDL, denominado VHDL 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 codificación


de alto nivel, en este tema se introducen los conceptos básicos para el modelado
y simulación de circuitos digitales empleando VHDL. En las explicaciones sobre
los fundamentos del lenguaje VHDL proporcionadas en el resto del tema, no se
pretende revisar de manera sistemática todas las posibilidades que ofrece la sintaxis
de VHDL, que son muchas. El objetivo es ir introduciendo paulatinamente los
conceptos básicos, cuya utilidad para el diseño de circuitos se demostrará en los
sucesivos temas.

2.2. UNIDADES DE DISENO

Se denomina entidad de diseño al bloque constitutivo básico para la descripción


del hardware en VHDL. Consta al menos de las dos unidades de diseño siguientes:

- Entity: representa la definición de la interfaz entre el diseño y el entorno en el


cual se usa. Esta definición incluye los puertos de conexión (señales de entrada
y/ o salida) del circuito y sus constantes generic, así como declaraciones y
sentencias que forman parte del diseño.

- Architecture: permite definir el comportamiento y la estructura de la entidad


de diseño. Es decir, cómo los puertos de salida de la entidad de diseño se
relacionan con sus puertos de entrada.

95
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

library IEEE;
use IEEE. std_logic_1164. all;
entity detectorPar is
port ( par : out std_logic;
a : in std_logic_vector( 2 downto O) ) ;
end entity detectorPar;
architecture comp_funcLog of detectorPar is
signal p1, p2, p3, p4 : std_logic;
begin
par < = ( p 1 or p2 ) or ( p3 or p4 ) ;
pi <= ( not a(2) ) and ( not a(1) ) and ( not a(O) );
p2 <= ( not a(2) ) and a(1) and a(O);
p3 <= a(2) and ( not a(1) ) and a(O);
p4 <= a(2) and a(1) and ( not a(O) );
end architecture comp_funcLog;

Código VHDL 2.1: Circuito detector de paridad.

Un fichero con código VHDL puede contener varias unidades de diseño, pero una
unidad de diseño no puede ser dividida en dos o más ficheros.

El diseño del circuito descrito en la Sección 1.8, que es mostrado nuevamente


en el Código VHDL 2.1, puede servir para ilustrar cuál es el esqueleto básico
de una entidad de diseño de VHDL, la cual está compuesta por una entity y
una architecture. Obsérvese que en las sentencias concurrentes de asignación a
señal hay implícitamente un retardo 5. En las Secciones 2.3 y 2.4 se explican los
fundamentos de la definición de la entity y la architecture.

Un tercer tipo de unidad de diseño de VHDL es el package, el cual se emplea


normalmente para agrupar una colección de tipos de datos, subprogramas y compo-
nentes, que están de alguna forma relacionados entre sí y que van a ser usados por
otros programas VHDL.

Finalmente, otro tipo de unidad de diseño. de VHDL es la configuration, que


permite relacionar en tiempo de compilación la entity con la architecture.

El hecho de que la entity y la architecture se definan por separado, y que


puedan ser compiladas separadamente, facilita la definición de varias architecture
para una misma entity. En la Sección 1.8 se describió un ejemplo de ello. Otro
ejemplo diferente sería el caso en el cual se definieran varias architecture de
una misma entidad de diseño, correspondientes a diferentes versiones del circuito:
velocidad baja, media y alta.

Si no se define la configuration, en la cual se especifica explícitamente la


architecture que corresponde con la entity, entonces el entorno de simulación
asocia a la entity aquella de sus architecture que ha sido compilada en último

96
CONCEPTOS BÁSICOS DE VHDL

lugar. La descripción de la sintaxis y uso de la unidad de diseño configuration está


fuera del propósito de este texto.

2.3. ENTITY

La entity especifica la interfaz del diseño, definiendo la parte de él que es visible


desde "el mundo exterior".

En el Tema 1 se mostraron algunos ejemplos de declaración de entity. Así, en


el Código VHDL l. 7, que describe un banco de pruebas para el circuito detector de
paridad, se encuentra la declaración

entity bp_detectorPar is
end entity bp_detectorPar;

que sólo contiene el nombre asignado a la entity, bp_detectorPar, y las siguientes


palabras reservadas del lenguaje: entity, is y end. En la entity se declara la lista
de señales que componen la interfaz del circuito. A estas señales de la interfaz se las
denomina puertos. Dado que la interfaz del banco de pruebas no contiene ninguna
señal, en su entity no se declara ningún puerto.

También se vieron ejemplos en el Tema 1 de declaración de la entity de algunos


circuitos, como pueden ser puertas lógicas y el circuito detector de paridad. En estos
casos, la declaración de la entity comprende la declaración de los puertos. Otros
ejemplos se muestran en la Figura 2.1, donde se declaran las interfaces de las puertas
lógicas NOT, XOR y AND. A continuación, se explica con detalle la declaración de
los puertos, la cual se realiza en la cláusula port.

........................................ ....................... ,............


...
xO ~ yO
L. . ~~. ..! :~ P~.?.. .! yo :~ [...!. ... . ?. . ...! yO

entity not is entity xor2 is entity and2 is


port ( yO : out std_logic; port ( yO : out std_logic; port ( yO : out std_logic;
xO : in std_logic ) ; xO, x1 : in std_logic ); xO, x1 : in std_logic ) ;
end entity not; end entity xor2; end entity and2;

Figura 2.1: Interfaces de las puertas NOT, XOR y AND.

97
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.3.1. Cláusula port

Las señales de la interfaz, a las que se denomina puertos, se declaran mediante


la cláusula opcional port, en la cual se indica el nombre de los puertos, su modo y
su tipo. La sintaxis es:
entity nombre_enti ty is
port (
nombres_puertos modo tipo_dato;
nombres_puertos modo tipo_dato;

nombres_puertos modo tipo_dato


) ;
end entity nombre_entity;

Los puertos declarados en la entity son visibles desde la propia entity y desde
las architecture asociadas a la entity.

El modo del puerto indica la dirección de la señal:

- Las palabras reservadas in y out indican que la señal fluye hacia el circuito
o desde el circuito, respectivamente. Describen el hecho de que el puerto
correspondiente es una entrada o una salida del circuito.

- La palabra reservada inout indica que la señal fluye en ambas direcciones, es


decir, que se trata de un puerto bidireccional.

En este texto se aplica el convenio de declarar primero los puertos de salida y a


continuación los de entrada, si bien este convenio no es universalmente aceptado.

Como ejemplo de uso del modo inout, en la Figura 2.2 se ilustra el funciona-
miento de un puerto I/0 bidireccional con doble buffer. Como las señales de control
de los buffers triestado están conectadas a señales enable complementarias, cuando
uno de los buffers está habilitado, el otro tiene la salida a alta impedancia.

dir ---~:>-----1

- bi

sig_in

-
Figura 2.2: Puerto I/0 bidireccional con doble buffer triestado.

98
CONCEPTOS BÁSICOS DE VHDL

El modo del puerto bi es inout. El comportamiento del puerto I/0 puede


describirse de la forma siguiente:

bi <= sig_out when dir='1' else 'Z';


sig_in <= bi when dir='O' else 'Z';

Al describir los circuitos debe tenerse en cuenta que un puerto cuyo modo es out
no puede ser usado como una señal de entrada. Por ejemplo, consideremos el circuito
mostrado en la Figura 2.3. Podría pensarse en describir el circuito de la Figura 2.3
mediante el Código VHD L 2. 2.

a ¡...............................¡
X
..............................................
·8••••:
b
. ::::::::•! i. . Q ••moO
G; m::
......... . .... ..........
1..... : ........... .:. ... 1
y
::::::::::::::::::::::::::;:::::::::::::::::::

Figura 2.3: Circuito usado para explicar el modo de los puertos.

library IEEE;
use IEEE. std_logic_1164. all;
entity modoPuertos is
port ( x, y : out std_logic;
a, b : in std_logic ) ;
end entity modoPuertos;
architecture arch_incorrecta of modoPuertos is
begin
x <=a and b;
y <= not x; --MAL, pToduce eTTOT de compilación
end architecture arch_incorrecta;

Código VHDL 2.2: Código incorrecto, que produce un error de compilación.

Sin embargo, puesto que en dicho código se usa la señal x para calcular la señal
y, el compilador de VHDL considera que la señal x fluye hacia el circuito (véase
la Figura 2.4a). Esto contradice el hecho de que el modo de la señal x es out. La
consecuencia de ello es que se produce un error de compilación.

Una posible solución sería cambiar el modo del puerto x a inout. Sin embargo,
ésta no es una buena solución, ya que de hecho no se trata de un puerto bidireccional.

Una alternativa mucho mejor es definir una señal interna para representar el
resultado intermedio (véase la Figura 2.4b), tal como se muestra en el Código
VHDL 2.3.

99
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

a ,. . . . .. . . . . . . . .. . .
~:: ¡! o
b ;, - '
d .-. é;,.•
Interpretación del compilador de
VHDL sobre el flujo de la señal

: - ··~· · .•.
x
- -~
a
: 8····::·:.:.:: .:.-J
b
¡

¡o
¡

a) b)

Figura 2.4: a) La asignación y <= x hace que el compilador interprete que la señal x fluye hacia
el circuito; b) Definición de la señal ab.

library IEEE;
use IEEE. std_logic_1164. all;
entity modoPuertos is
port ( x, y : out std_logic;
a, b : in st<lJogic ) ;
end entity modoPuertos;
architecture arch_correcta of modoPuertos is
signa} ab : std_logic;
begin
ab <=a and b;
x <= ab;
y <= not ab;
end architecture arch_correcta;

Código VHDL 2.3: Descripción correcta del circuito mostrado en la Figura 2.3.

2.3.2. Cláusula generic

Otra cláusula opcional que puede declararse en la entity es la cláusula generic.


La cláusula se usa para declarar aquellas constantes cuyo valor necesite ser modifi-
cado a fin de adaptar el diseño a sus diferentes aplicaciones. A estas constantes se
las denomina constantes generic.

Las constantes generic son visibles desde la propia entity en que son declaradas y
desde las architecture asociadas a la entity. Ejemplos típicos de constantes generic
son el valor de determinados retardos, el número de bits de un bus de señales, etc.
Un ejemplo sencillo de declaración de entity incluyendo una cláusula generic es el
siguiente:

entity and2 is
generic ( Tpd: time);
port ( yO : out std_logic;
xO, x1 : in std_logic );
end entity and2;

100
CONCEPTOS BÁSICOS DE VHDL

Esta entity incluye una constante generic, Tpd, del tipo predefinido time.
El valor de esta constante generic puede ser usado en el cuerpo de cualquier
architecture asociada a esta entity. En la Sección 2.10 se volverá sobre este tema.

2.3.3. Declaraciones

En la entity pueden declararse subprogramas, atributos, tipos de datos, cons-


tantes, señales, etc. Estas declaraciones son visibles desde la propia entity y las
architecture asociadas.

Por ejemplo, en la entity de un banco de pruebas puede declararse una constante


que represente el número de bits del circuito a testear y otra que represente el retardo
usado en el test.

entity bp is
constant WORD SZ integer := 16;
constant DELAY time 10 ns;
end entity bp;

2.3.4. Sentencias

En la entity pueden incluirse sentencias assert, llamadas concurrentes a proce-


dimientos y bloques process. En ninguno de los casos deben producirse asignaciones
a señal.

El propósito de estas sentencias puede ser realizar comprobaciones sobre algunas


de las características de la entity. Por ejemplo, si se incluye una sentencia assert
en la entity, el mensaje se mostraría (si procede) al comienzo de la simulación, para
cada una de las architecture que tenga esa entity.

2.3.5. Resumen de la sintaxis de la entity

Resumiendo lo anterior, la declaración de la entity tiene la sintaxis mostrada


a continuación. La declaración comienza por la palabra reservada entity, seguida
del nombre asignado a la entity y de la palabra reservada is. A continuación, se
escriben las cláusulas generic y port, y las declaraciones. Finalmente, se escriben las
sentencias. La palabra reservada begin separa la parte declarativa de las sentencias,

101
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

en caso de que la entity contenga alguna sentencia. La declaración termina con las
palabras reservadas end entity seguidas del nombre asignado a la entity.
entity nombre_enti ty is
cláusula generic
cláusula port
declaraciones
begin
sentencias
end entity nombre_enti ty;

Por ejemplo, a continuación se muestra la entity de un registro de desplazamiento


de longitud N bits:

entity shiftReg is
generic (N : integer );
port ( SO out std_logic;
RSTn, clk, SI : in std_logic );
signal T: std_logic_vector( N downto O);
begin
assert (N>3) and (N<33)
report "N fuera del rango 4 a 32";
end entity shiftReg;

En la entity pueden declararse señales, como es el caso de la señal T del código


anterior. Aunque este tipo de declaraciones es legal, en general no se considera una
buena práctica de diseño. Es preferible declarar las señales que no pertenecen a la
interfaz del diseño en las architecture, no en la entity.

2.4. ARCHITECTURE

La architecture permite definir el comportamiento y la estructura de la entidad


de diseño. Esta definición puede realizarse mediante:

- Una descripción estructural, en la cual el componente es descrito mediante la


instanciación y conexión de otros componentes de más bajo nivel.

- Una descripción de su comportamiento, en la que se describe el comportamien-


to que debe tener el componente.

- Una descripción mixta de la estructura y del comportamiento, que incluya la


instanciación y conexión de componentes de más bajo nivel, y código descri-
biendo el comportamiento.

102
CONCEPTOS BÁSICOS DE VHDL

..-..................................,- ..-...................................-.

xo EG yO
:~ PI.. 2. ...lyo :~ l. ..!. . . . 2. . . .l yO

architecture not of not is architecture xor2 of xor2 is architecture and2 of and2 is


begin begin begin
yO <= not xO; yO <= xO xor x1; yO <= xO and x1;
end architecture not; end architecture xor2; end architecture and2;

Figura 2.5: Architecture de las puertas NOT, XOR y AND.

Por ejemplo, en la Figura 2.5 se muestran las architecture que describen el


comportamiento de las puertas lógicas NOT, XOR y AND. Las correspondientes
entity son las definidas en la Figura 2.1.

En los ejemplos mostrados en las Figuras 2.1 y 2.5 se ha dado el mismo nombre
a la entity y a la architecture de cada entidad de diseño. En general, se les puede
dar nombres diferentes. De hecho, como ya hemos visto, en VHDL pueden definirse
varias architecture para una misma entity. De este modo, es justamente a la hora
de realizar la simulación o la síntesis cuando se asocia una architecture en concreto
a la entity.

A grandes rasgos, la definición de la unidad de diseño architecture tiene la


sintaxis siguiente:
architecture nombre_archi tecture of nombre_enti ty is
Declaración de señales locales y constantes locales
Declaración de los componentes
Declaración de los subprogramas (procedimientos y funciones)
begin
Instanciación de los componentes
Asignaciones concurrentes a señales y bloques process
end architecture nombre_architecture;

El área de texto previa a la palabra reservada begin es la parte declarativa. Es


donde se declaran las señales y constantes (todas ellas locales a la definición de la
architecture), los componentes que van a ser instanciados en la architecture y
los subprogramas. Entre las palabras reservadas begin y end se define la estructura
y el comportamiento de la entidad de diseño. Para ello, pueden emplearse sentencias
concurrentes de asignación a señal, bloques process, y la instanciación y conexión
de componentes. En las Secciones 2.5, 2.7 y 2.9 se explicará detalladamente cada uno
de estos recursos que proporciona VHDL para la descripción del comportamiento y
la estructura.

103
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.5. ASIGNACIONES CONCURRENTES

Las asignaciones a señales directamente contenidas entre las palabras reservadas


begin y end de la architecture se denominan asignaciones concurrentes, debido a
que todas ellas se ejecutan de forma concurrente. Es decir, el orden de ejecución de
las sentencias concurrentes no está determinado por el orden en que se han escrito.

VHDL tiene dos tipos de asignaciones concurrentes a señal: la asignación con-


currente condicional y la asignación concurrente de selección. Las asignaciones
concurrentes simples (por ejemplo, e <= u and v;) pueden considerarse un caso
particular de asignación condicional, en la cual no hay expresión condicional. A
continuación, analizaremos cada uno de estos tres tipos de asignación concurrente a
señal.

2.5.1. Asignaciones concurrentes simples

Las asignaciones concurrentes simples tienen la sintaxis siguiente:

señal <= forma_de_onda;

donde la cláusula forma_de_onda consiste en la especificación de la expresión para


el cálculo del nuevo valor de la señal y la especificación del tiempo que transcurre
(retardo) entre el cálculo de dicho valor y su asignación a la señal.

La ejecución de una sentencia de asignación concurrente simple se produce en


el instante en que cambia el valor de alguna de las señales que aparecen en la
expresión escrita a la derecha del símbolo<=. Por ejemplo, la sentencia de asignación
concurrente

yO <= not xO;

es ejecutada cada vez que se produce un cambio en el valor de la señal xO. En


la terminología de VHDL, se dice que esta sentencia, de la cual se calcula yO, es
"sensible" a la señal xO.

En la sentencia

yO <= not xO;

no se especifica el retardo entre el instante en que se calcula el nuevo valor de la


señal yO y el instante en el cual este nuevo valor se asigna a la señal yO. Cuando
no se especifica el retardo, VHDL considera que existe un retardo infinitesimal 6.
Es decir, la expresión not xO se evalúa en el instante en que cambia el valor de xO,

104
CONCEPTOS BÁSICOS DE VHDL

calculándose el nuevo valor de yO. Este nuevo valor se asigna a la señal transcurrido
un tiempo 5.

Análogamente, la sentencia de asignación concurrente

e <= u and v;

es ejecutada cada vez que se produce un cambio en el valor de la señal u o en el


valor de la señal v. Se dice que la sentencia de asignación es "sensible" a las señales
u y v. La asignación del nuevo valor a e se produce transcurrido un retardo 5.

La asignación concurrente

y <= x1 + x2 after 10 ns;

indica que en el instante en que x1 o x2 cambien, debe evaluarse la expresión x1 +x2,


y el resultado debe asignarse a la señal y transcurridos 10 ns de retardo inercial.
Puede emplearse la cláusula transport para indicar que el retardo en la asignación
del nuevo valor a la señal es un retardo de transporte:

y <= transport x1 + x2 after 10 ns;

La información temporal de la cláusula forma_de_onda normalmente corresponde


al retardo en la propagación de las señales que se produce internamente en los
componentes físicos usados para realizar el cálculo del nuevo valor de la señal.
Sin embargo, dado que los retardos dependen de los componentes, la tecnología,
el cableado ( routing) entre componentes, etc., es imposible sintetizar un circuito con
un determinado valor del retardo. Por ello, en el código VHDL usado para síntesis
no se especifica el retardo de los componentes, usándose en su lugar el retardo 5. En
este caso, la sintaxis es:

señal <= expr_nuevo_valor_señal;

donde se omite la cláusula after e implícitamente se entiende que la asignación del


nuevo valor a la señal se produce tras un retardo 5.

La implementación conceptual de las asignaciones concurrentes simples es sen-


cilla. La asignación puede ser traducida mediante un bloque circuital, cuya salida
es la señal situada en el lado izquierdo de la asignación y cuyas entradas son las
señales situadas en el lado derecho de la asignación. Cada operador que interviene
en la asignación es reemplazado por un bloque circuital, cuyas entradas y salidas
son conectadas adecuadamente.

Por ejemplo, en la Figura 2.6 se muestra la implementación conceptual de las


tres sentencias de asignación concurrente siguientes:

105
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

a
b
e

xl ---1
x2 ---1 y
x3 ---1
x4 ---1

Figura 2.6: Diagrama conceptual de tres asignaciones concurrentes simples.

y <= '1';
y <= a + b + e - 1;
y<= ( x1 and x2) or ( x3 and x4 );

Es posible definir asignaciones en las cuales una misma señal aparece en el


lado izquierdo y derecho de la sentencia de asignación, si bien es una práctica
desaconsejable. Cuando una señal aparece como entrada (en el lado derecho) y salida
(en la parte izquierda) de la sentencia de asignación, se forma un lazo cerrado de
realimentación, que da lugar a la creación de un estado interno o a comportamiento
oscilatorio. Por ejemplo, en la sentencia

y<= (y and (noten) ) or ( x anden);

la señal y es la salida, pero también aparece en la expresión del lado derecho. La


señal y toma el valor de x cuando la señal en vale '1 ', y mantiene su valor anterior
cuando en vale 'O'. Obsérvese que la salida (y) depende de las entradas (en, x) y del
estado interno (el valor anterior de y), con lo cual el circuito no es combinacional,
ya que en un circuito combinacional la salida es función únicamente de las entradas.

Si se modifica la asignación anterior de la forma siguiente

y<= ( ( not y) and (noten) ) or ( x anden);

la señal de salida y oscila entre los valores 'O' y '1' mientras la señal en vale 'O'.

Cuando una asignación concurrente contiene un lazo cerrado, el valor de la señal


de salida es sensible al retardo interno en la propagación y puede oscilar. Este tipo
de circuito confunde a las herramientas de síntesis, y complica la verificación y el test
del circuito. Es una mala práctica de diseño y debe evitarse por completo cuando se
diseña para síntesis.

106
CONCEPTOS BÁSICOS DE VHDL

2. 5. 2. Asignaciones concurrentes condicionales

Básicamente, la sintaxis de una asignación concurrente condicional a una señal


es la siguiente:
señal <= expr_nuevo_valor_señal_1 vvhen expr_booleana_1 else
expr_nuevo_valor_señal_2 vvhen expr_booleana_2 else
expr_nuevo_valor_señal_3 vvhen expr_booleana_3 else

expr_nuevo_valor_señal_n;

donde when y else son palabras reservadas, y expr_booleana_1, expr_booleana_2,


. .. , son expresiones lógicas que al ser evaluadas devuelven el valor true o false.

Estas expresiones lógicas son evaluadas por orden, primero expr_booleana_1 ,


luego expr _booleana_2 y así sucesivamente, hasta que una de ellas vale true, en
cuyo caso se calcula el nuevo valor de la señal de la correspondiente expresión. Si
expr_booleana_1, ... , expr_booleana_i-1 valen false y expr_booleana_i vale true, en-
tonces el nuevo valor de la señal es el obtenido de evaluar expr _nuevo_ valor _señal_i.

Si todas las expresiones booleanas valen false, el nuevo valor de la señal se calcula
evaluando expr _nuevo_ valor _señal_n. En cualquier caso, el nuevo valor calculado
se asigna a la señal una vez ha transcurrido un retardo, que por defecto vale 5.

Como ejemplo de uso de la asignación concurrente condicional a señal, el Código


VHDL 2.4 describe un multiplexor de 4 entradas, cada una de las cuales tiene 8 bits.
El Código VHDL 2.5 describe un decodificador binario, que tiene una entrada de
n = 2 bits y una salida de 2n = 4 bits.

-- MUX 4:1 de 8 bits


-- fi chero: mux_4 x L 8bits_archCondicional. vhd
library IEEE;
use IEEE. std_logie_1164. all;
entity mux4 is
port ( x : out std_logic_vector(7 downto O);
a, b, e, d : in std_logic_vector(7 downto O);
S : in std_logic_vector( 1 downto O) ) ;
end entity mux4;
architecture areh_eond of mux4 is
begin
x <= a when (s="OO") else
b when (s="01") else
e when (s="10") else

'
end architecture areh_eond;

Código VHDL 2.4: Multiplexor de 4 entradas de 8 bits.

107
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Decodifi cador bin ario 2 a 4


-- fi chem: decodificador2x4_archCond-icional. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity decodificador4 is
port ( X : OUt std_logic_vector(3 downto 0);
s : in std_logic_vector( 1 downto O) ) ;
end entity decodificador4;

architecture arch_decodificador4 of decodificador4 is


begin
x < = "0001" when (s="OO") else
"0010" when (s="01") else
"0100" when (s="10") else
"1000";
end architecture arch_decodificador4;

Código VHDL 2.5: Decodificador binario de 2 entradas.

-- Codifi cador de prioridad 4 a 2


-- fi chem: codificador.Prioridad4 a2_archCondicional. vhd
library IEEE;
use IEEE. std_logic_1164.all;

entity codificadorPrioridad4a2 is
port ( codigo : out std_logic_vector(1 downto O);
activo : out std_logic;
X : in std_logic_vector(3 downto 0) );
end entity codificadorPrioridad4a2;

architecture codPrior4a2 of codificadorPrioridad4a2 is


begin
codigo < = "11" when ( x(3) = '1') else
"10" when ( x(2) = '1') else
"01" when ( x(1) = '1') else
"00" ;
activo <= x(3) or x(2) or x(1) or x(O);
end architecture codPrior4a2;

Código VHDL 2.6: Codificador 4 a 2 con prioridad.

El Código VHDL 2.6 describe un codificador 4 a 2 con prioridad. Este circuito


genera el código binario (señal eo digo, de 2 bits) de la entrada de mayor prioridad
cuyo valor es '1'. La entrada x (3) tiene mayor prioridad que x (2), la cual tiene
mayor prioridad que x(1) y ésta tiene mayor prioridad que x(O). La salida activo
vale '1' cuando al menos una de las entradas vale '1'. En caso contrario, vale 'O'.

Conceptualmente, la implementación hardware de una sentencia concurrente


condicional debe hacerse teniendo en cuenta que las expresiones lógicas son evaluadas
en orden hasta que una de ellas vale true, y entonces el valor de la correspondiente
expresión es el nuevo valor de la señal. En la síntesis hardware de una sentencia
concurrente condicional

108
CONCEPTOS BÁSICOS DE VHDL

señal <= expr_nuevo_valor_señal_1 vvhen expr_booleana_1 else


expr_nuevo_valor_señal_2 vvhen expr_booleana_2 else

expr_nuevo_valor_señal_n;

se emplean los circuitos necesarios para obtener cada uno de los nuevos valores de
la señal (expr_nuevo_valor_señal_1, ... , expr_nuevo_valor_señal_n), los circuitos
necesarios para obtener cada una de las expresiones booleanas (expr_booleana_1,
... , expr_booleana_n-1), y el circuito que implementa la red de prioridad.

La red de prioridad puede implementarse mediante la conexión de multiplexores


de dos entradas (MUX 2:1). Para entender cómo se construye la red de prioridad,
consideremos primero una sentencia condicional con una única cláusula when:
señal <= expr_nuevo_valor_señal_1 vvhen expr_booleana_1 else
expr_nuevo_valor_señal_2;

En este caso, la red de prioridad consiste en un único multiplexor, tal como se


muestra en la Figura 2.7. Se conecta a la entrada '1' del MUX 2:1 la salida del
circuito que implementa expr _nuevo_ valor _señal_! y se conecta a la entrada 'O' la
salida del circuito que implementa expr _nuevo_ valor _señal_2. La salida del circuito
que implementa la expresión booleana se conecta a la entrada de selección del MUX.

expr_nuevo_valor_señal_l señal
expr_nuevo_valor_señal_2

expr_booleana_1

Figura 2. 7: Diagrama conceptual de la síntesis de una sentencia concurrente condicional con una
única cláusula when.

La generalización al caso de más de una cláusula when es inmediata. Por ejemplo,


en la Figura 2.8 se muestra la red de prioridad que implementa una sentencia
concurrente con tres cláusulas when:
señal <= expr_nuevo_valor_señal_1 vvhen expr_booleana_1 else
expr_nuevo_valor_señal_2 vvhen expr_booleana_2 else
expr_nuevo_valor_señal_3 vvhen expr_booleana_3 else
expr_nuevo_valor_señal_4;

El proceso de síntesis se realiza de manera análoga para cualquier número de


cláusulas when. Dado que cada cláusula when introduce una etapa adicional en la
red de multiplexores, el número de etapas de la red de prioridad crece al aumentar

109
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

expr_nuevo_valor_señal_l
------------------------~ señal

expr_nuevo_valor_señal_2

expr_nuevo_valor_señal_3

expr_nuevo_valor_señal_4

expr_booleana_3
expr_booleana_2 -------------------.J
expr_booleana_1

Figura 2.8: Diagrama conceptual de la síntesis de una sentencia concurrente condicional con tres
cláusulas when.

el número de cláusulas when. Esto debe ser tenido en cuenta a la hora de diseñar
para síntesis.

2.5.3. Asignaciones concurrentes de selección

Básicamente, una sentencia concurrente de selección tiene la sintaxis mostrada


a continuación, donde, si no se indica el retardo, se asume implícitamente que la
asignación a la señal debe realizarse transcurrido un retardo 5.
with expresión_selección select
señal <= expr_nuevo_valor_señal_1 when valor_selección_1,
expr_nuevo_valor_señal_2 when valor_selección_2,

expr_nuevo_valor_señal_n when valor_selección_n;

El resultado de evaluar expresión_selección debe ser o bien un número entero


o bien un vector unidimensional. En cualquier caso, el resultado obtenido de evaluar
la expresión de selección tiene un número finito de posibles valores. Por ejemplo,
una señal del tipo bit_vector(1 downto O) puede tomar 22 posibles valores: "00",
"01", "10" y "11".

110
CONCEPTOS BÁSICOS DE VHDL

El valor que se asigna a la señal depende del valor de la expresión de selección.


Cada una de las selecciones valor _selección_1, ... , valor _selección_n debe ser
uno o varios de los posibles valores de expresión_selección, pero satisfaciendo dos
condiciones:

l. Deben ser mutuamente excluyentes. Es decir, un mismo valor no puede apa-


recer en más de una de las selecciones.

2. Deben incluir todos los posibles valores de expresión_selección. Puede em-


plearse la palabra reservada others como último valor de selección (esto es,
valor _selección_n) para representar todos los valores que no han sido usados
hasta el momento.

En otras palabras: cada uno de los posibles valores de expresión_selección debe


aparecer en una y sólo en una de las selecciones.

A continuación se muestran tres ejemplos. El Código VHDL 2. 7 muestra la


descripción de un multiplexor de 4 entradas de 8 bits mediante una sentencia de
asignación concurrente de selección. El Código VHDL 2.8 describe un decodificador
binario de 2 entradas.

Finalmente, el Código VHDL 2.9 muestra el diseño de un codificador 4 a 2 con


prioridad. Recuérdese que se asigna el valor "11" a la señal codigo si x (3) =' 1'. Esto
corresponde a ocho valores de la señal de entrada x: "1000", "1001", ... , "1111".
Obsérvese que se emplea el símbolo 1 para especificar múltiples valores.

-- MUX 4:1 de 8 bits


-- fich ero: mux_4 x L 8bits_archSelec. vhd
library IEEE;
use IEEE. std_logie_1164. all;

entity mux4 is
port ( x : out std_logic_vector(7 downto O);
a, b, e, d : in std_logic_vector(7 downto O);
S : in std_logic_vector(1 downto o) );
end entity mux4;
architecture areh_selee of mux4 is
begin
with s select
x <= a when "00",
b when "01",
e when "10",
d when others;
end architecture areh_selee;

Código VHDL 2. 7: Multiplexor de 4 entradas de 8 bits.

111
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- D ecodificador binario 2 a 4
-- fichero: decodificador2x4_archSelec. vhd
library IEEE;
use IEEE . std_logic_1164.all;

entity decodificador4 is
port ( x : out std_logic_vector(3 downto O);
s : in std_logic_vector ( 1 downto O) ) ;
end entity decodificador4;
architecture arch_decSelec of decodificador4 is
begin
with s select
x <= "0001" when "00",
"0010" when "01",
"0100" when "10",
"1000" when others;
end architecture arch_decSelec;

Código Y~DL_ 2_.8: Decodificador binario de 2 entradas.

-- Codificador de prioridad 4 a 2
-- fichero: codificadorPrioridad4 a2_archSelec. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity codificadorPrioridad4a2 is
port ( codigo : out std_logic_vector( 1 downto O);
activo : out std_logic;
X : in std_logic_vector(3 downto 0) );
end entity codificadorPrioridad4a2;

architecture codPrior4a2_selec of codificadorPrioridad4a2 is


begin
with x select
codigo <= "11" when "1000" 1 "1001" 1 "1010" 1"1011" 1
"1100" 1 "1101" 1 "1110" 1 "1111",
"10" when "0100" 1 "0101" 1 "0110" 1 "0111",
"01" when "0010" 1 "0011",
"00" when others;
activo <= x(3) or x(2) or x(1) or x(O);
end architecture codPrior4a2_selec;

Código VHDL 2.9: Codificador 4 a 2 con prioridad.

Conceptualmente, la implementación hardware de una asignación concurren-


te de selección puede realizarse empleando un multiplexor, que utiliza la señal
expresión_selección para seleccionar cuál de las expresiones del nuevo valor de
la señal debe usarse para evaluar la señal. Cada uno de los posibles valores de la
señal expresión_selección corresponde con un puerto de entrada del multiplexor.

En la Figura 2.9 se muestra el diagrama conceptual de la síntesis de una sentencia


concurrente de selección, en la cual la expresión de selección puede tomar n diferentes
valores y la señal a evaluar tiene m bits.

112
CONCEPTOS BÁSICOS DE VHDL

expr_nuevo_valor_señal_n
m
señal
m
expr_nuevo_valor_señal_2
m
expr_nuevo_valor_señal_l
m

expresión_selección

Figura 2.9: Diagrama conceptual de la síntesis de una sentencia concurrente de selección.

expr_nuevo_valor_señal_3
1---~ c3
señal
'----~ c2

expr_nuevo_valor_señal_2 -------IC}

expr_nuevo_valor_señal_l

expresión_selección

Figura 2.10: Ejemplo de diagrama conceptual de la implementación de una sentencia concurrente


de selección con tres when y en la cual la expresión de selección puede tomar cinco posibles valores.

Por ejemplo, en la Figura 2.10 se muestra el diagrama conceptual de la imple-


mentación de la siguiente sentencia concurrente de selección:

with expresión_selección select


señal <= expr_nuevo_valor_señal_1 when cO,
expr_nuevo_valor_señal_2 when c1,
expr_nuevo_valor_señal_3 when others;

donde se supone que la expresión de selección puede tomar cinco posibles valores:
cO, c1, c2, c3 y c4.

Todas las sentencias concurrentes de selección tienen un diagrama conceptual


similar. La diferencia está en el número de valores que puede tomar la expresión de
selección, el cual determina el tamaño del multiplexor.

113
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.5.4. Sensibilidad de las sentencias concurrentes

Como se explicó anteriormente, una asignac1on concurrente es ejecutada cada


vez que cambia el valor de alguna de las señales a las que es sensible.

Una asignación concurrente simple es sensible a todas las señales que intervienen
en la expresión para el cálculo del nuevo valor de la señal.

Una sentencia concurrente condicional es sensible a todas las señales que inter-
vienen en las expresiones para el cálculo del nuevo valor de la señal y también a
todas las señales que intervienen en las expresiones booleanas.

Una sentencia concurrente de selección es sensible a todas las señales que In-
tervienen en la expresión de selección y a todas las señales que intervienen en las
expresiones para el cálculo del nuevo valor de la señal.

A modo de ejemplo, obsérvese el código siguiente, donde se indica en los comen-


tarios a qué señales es sensible cada sentencia.

arehiteeture eoneS of eoneS is

begin

Sensible a: in1, eodigo, in2, in3(2)


a1 <= not in1 when eodigo = "00000000" el se
in1 when eodigo(7) = '1' and in2 '0' else
in3(2);

Sensible a: in2, souree, in1


a2 <= in2 after 10 ns when souree "1111" el se
in1 after 200 ns when souree "0000" el se
not in2 after 15 ns,
'1' after 20 ns,
'0' after 100 ns,
in2 after 200 ns;

Sensible a: in1, in2, in3(1)


a3 <= ( in1 and in2 ) or in3(1);

Sensible a: eodigo, in1, in2


with eodigo seleet
a4 <= in1 or in2 after 30 ns when "00000001",
in1 and in2 after 30 ns when "00000010",
in1 nand in2 after 40 ns when "00000011",
in1 nor in2 after 40 ns when "00000100",
in1 xor in2 after 40 ns when "00000101",
in1 when others;

end arehiteeture eoneS;

114
CONCEPTOS BÁSICOS DE VHDL

2.6. SENTENCIA GENERATE

Las sentencia generate facilita la ejecución iterativa o condicional de una porción


de código concurrente. Veremos dos formas de esta sentencia: la forma iterativa y la
forma condicional.

2.6.1. Sentencia generate iterativa

Básicamente, la sentencia generate iterativa tiene la sintaxis mostrada a conti-


nuación, donde for, in, generate, begin y end son palabras reservadas.

etiqueta: for índice in rango_bucle generate


Declaración de señales locales y constantes locales
begin
Sentencias_ concurrentes
end generate etiqueta;

El bucle generate repite las sentencias concurrentes del cuerpo del bucle un
número fijo de iteraciones, que está determinado por el rango de valores rango_bucle.
Para que la sentencia sea sintetizable, es necesario que los límites del rango sean
estáticos.

El índice del bucle (índice) especifica el valor del rango de valores que co-
rresponde con la iteración actual, con lo cual va tomando los sucesivos valores
de rango_bucle. El índice del bucle (índice) no necesita ser declarado, ya que
automáticamente pertenece al mismo tipo de dato que rango_bucle.

Si no se realiza la declaración de señales y constantes locales, puede omitirse la


palabra reservada begin. Por ejemplo:

signal z std_logic_vector( 7 downto O);


signal x std_logic_vector( 7 downto O);
signal y std_logic_vector(15 downto O);
E1: for i in x'range generate
z(i) <= x(i) AND y(i+8);
end generate E1;

El rango de índices del vector x, (7 downto O), se obtiene invocando el atributo


range del vector, de la forma x'range. Los atributos se explicarán en la Sección 2.13.

115
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.6.2. Sentencia generate condicional

La sentencia generate condicional tiene básicamente la sintaxis mostrada a


continuación. Las sentencias concurrentes se ejecutan sólo si expresión_booleana
vale true. Si no se realiza la declaración de señales y constantes locales, puede omitirse
la palabra reservada begin.

etiqueta: if expresión_ booleana generate


Declaración de señales locales y constantes locales
begin
Sentencias_ concurrentes
end generate etiqueta;

Es posible anidar sentencias generate. Por ejemplo, una sentencia generate


condicional puede anidarse dentro de una sentencia iterativa:

etiqueta!: for índice in rango_bucle generate

etiqueta2: if expresión_ booleana generate

end generate etiqueta2;

end generate etiqueta!;

2.7. BLOQUE PROCESS

Para describir la operación de un determinado circuito, puede ser preciso emplear


una secuencia de sentencias que se ejecuten justamente en el orden en que han sido
escritas. Para ello, se emplea el bloque process, cuya sintaxis es básicamente la
mostrada a continuación, donde process, begin y end son palabras reservadas.

etiqueta: process ( lista_de_sensibilidad )


Declaración de variables locales
Declaración de subprogramas (funciones y procedimientos)
begin
Código_secuencial
end process etiqueta;

La etiqueta con la que se inicia y finaliza la declaración es opcional. Su finalidad es


documentar el código, para lo cual es recomendable emplear etiquetas que describan
la finalidad del bloque.

116
CONCEPTOS BÁSICOS DE VHDL

La lista de sensibilidad es también opcional. Como veremos más adelante, pro-


porciona un mecanismo para definir la condición de ejecución del bloque: el bloque
process se ejecuta cada vez que cambia el valor de una de las señales de su lista de
sensibilidad.

En un bloque process no pueden declararse señales. Sin embargo, todas las


señales declaradas en la architecture, y todas las señales y puertos declarados en la
entity, son visibles desde dentro del bloque process. Por ejemplo, pueden intervenir
en la parte derecha e izquierda de las asignaciones secuenciales, respetando siempre
las limitaciones de lectura y escritura que impone el modo de los puertos (no se
pueden leer puertos con modo out, ni escribir puertos con modo in).

La declaración de variables es opcional y se realiza antes de la palabra reservada


begin. La sintaxis es:

variable nombre_variable tipo rango := valor_inicial;

La declaración comienza con la palabra reservada variable. A continuación se


escribe el nombre de la variable y su tipo. Si se trata de una variable vectorial, se
declara su rango. A continuación, puede asignarse valor inicial a la variable. El rango
y el valor inicial son opcionales .. El valor inicial no es sintetizable, sólo se tiene en
cuenta para la simulación.

Las variables declaradas dentro del bloque process son visibles sólo dentro del
bloque. El valor de una variable no puede pasarse directamente fuera del bloque
process. Cuando es necesario emplear el valor de una variable fuera del bloque
process, éste debe ser asignado a una señal. Las señales y las variables serán
estudiadas con detalle en la Sección 2.11.

Las sentencias contenidas dentro de un bloque process son ejecutadas secuen-


cialmente, es decir, en el mismo orden en que están escritas. Por ello, las sentencias de
asignación a variables y a señales contenidas dentro del bloque process se denominan
sentencias secuenciales.

Por otra parte, los bloques process se ejecuta concurrentemente unos respecto a
los otros. El bloque process en su conjunto se considera una sentencia concurrente
de alto nivel dentro de la definición de la architecture, al igual que las sentencias
concurrentes descritas en la Sección 2.5.

Las sentencias interiores a un bloque process se ejecutan repetidamente y con-


secutivamente, desde la primera sentencia del bloque hasta la última sentencia del
bloque, una y otra vez, en un bucle infinito. Para evitar que las sentencias de un

117
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

bloque process se ejecuten en un bucle infinito (consumiendo los recursos de la CPU


y dejando la simulación "colgada"), es preciso indicar en .qué punto debe suspenderse
su ejecución y en qué situaciones debe reanudarse su ejecución. Esto puede hacerse
de una de las dos maneras siguientes: mediante el uso de sentencias wait o mediante
una lista de sensibilidad.

2. 7.1. Sentencias wait

Pueden incluirse sentencias wait en el código secuencial del bloque process. Al


llegar a una sentencia wait, se suspende la ejecución de las sentencias del bloque. La
ejecución queda suspendida hasta que ocurre cierto evento o hasta que transcurre
cierto tiempo. Esto no afecta a la ejecución de los demás bloques process y las
sentencias concurrentes de asignación a señal.

Una vez satisfecha la condición fijada en la sentencia wait, se reanuda la ejecución


del bloque process, ejecutándose una tras otra las sentencias del mismo hasta que
se alcanza nuevamente una sentencia wait, en la cual la ejecución del bloque queda
suspendida. Una vez satisfecha la condición de esta sentencia wait, se reanuda la
ejecución del código del bloque, ejecutándose las sentencias siguientes hasta que se
alcanza una sentencia wait, y así sucesivamente. Cuando finaliza la ejecución de
la última sentencia del bloque process, comienza inmediatamente a ejecutarse de
nuevo la primera sentencia del código del bloque.

A continuación se explican algunas de las formas de la sentencia wait más


comúnmente empleadas en la práctica.

Wait on

La sintaxis de la sentencia es:

wait on señal1 , señal2, ... , señalN;

Se suspende la ejecución del código secuencial hasta que cambia el valor de una
o varias de las señales señal1, señal2, ... , señalN.

118
CONCEPTOS BÁSICOS DE VHDL

Wait until

La sintaxis de la sentencia es:

wait until expresión_booleana;

Se suspende la ejecución hasta que se evalúe la expresión booleana y ésta valga


true. El simulador evalúa la expresión booleana únicamente cuando cambia el valor
de alguna de las señales que intervienen en la expresión booleana.

Si la expresión booleana contiene señales y variables, y en cierto instante cambia


el valor de alguna de las variables, pero no cambia el valor de ninguna de las señales,
entonces la expresión booleana no es evaluada en ese instante.

Supongamos que clk es una señal de tipo std_logic, enable es una señal de tipo
boolean y ves una variable de tipo integer. Entonces, la condición booleana de la
sentencia

wait until clk='1' and enable and v<30;

sólo es evaluada en los instantes en que se produzca un cambio en el valor de alguna


de las dos señales. Si sólo cambia el valor de v, la sentencia no es evaluada, con lo
cual la ejecución del bloque sigue suspendida.

Por ejemplo, las condiciones de las sentencias

wait until v<30; wait until true;

nunca serían evaluadas, ya que no contienen ninguna señal. La ejecución del bloque
process quedaría suspendida indefinidamente en esas sentencias.

Es posible especificar explícitamente la lista de sensibilidad de la sentencia wait


until:

wait on señal1, señal2, ... , señalN


until expresión_ booleana;

Cuando cambia el valor de alguna de las señales señal1 , ... , señal N, entonces
se comprueba la expresión booleana. Si vale true, se reanuda la ejecución de las
sentencias del bloque process.

119
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Wait for

La sintaxis de la sentencia es:

wait for expresión_ temporal;

Se suspende la ejecución hasta que transcurra determinado intervalo de tiempo,


que es calculado evaluando la expresión temporal.

Un caso particular es cuando la expresión temporal es O ns. Cuando en el instante


t se ejecuta la sentencia
wait for O ns;

la ejecución del código secuencial queda suspendida durante un tiempo 6, reanun-


dándose en t + 6. De esta manera, se permite que se asignen a las señales los valores
calculados en el instante t.

La sentencia wait for puede combinarse con las otras dos formas de la sentencia
wait. Por ejemplo, la sentencia

wait until clk='1' and enable and v<30


for 50 ns;

hace que la ejecución del código secuencial se suspenda hasta que una de las dos
siguientes condiciones se satisfaga:

l. Cambia el valor de alguna de las señales ( clk, enable) y además se satisface


la condición clk=' 1' and enable and v<30.

2. Han transcurrido 50 ns desde que se ejecutó la sentencia wait y, por tanto, la


ejecución ha estado suspendida en la sentencia durante 50 ns.

2. 7.2. Lista de sensibilidad

Puede definirse la lista de señales a las cuales el bloque process es sensible. Esta
lista se escribe, entre paréntesis, a continuación de la palabra reservada process.
En este caso, el bloque process es ejecutado sólo en el instante en que una o varias
de estas señales a las que es sensible cambia de valor. En la lista de sensibilidad
sólo pueden incluirse señales que puedan ser leídas. Es decir, no pueden incluirse los
puertos de salida.

120
CONCEPTOS BÁSICOS DE VHDL

-- Biestable D con reset asíncrono activado en LOW


-- fichem: biestableD_resetAsincmno. vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity flipflop_D is port
( q, q_n : out std_logic;
d, clk, reset_n : in std_logic);
end entity flipflop_D;
architecture flipflop_D of flipflop_D is
begin
process (reset_n, clk) is -- Proceso activo cuando cambia
begin -- el valor de reseLn o de clk
if reset_n = 'O' then -- Comprueba reset asíncmno
q <= '0';
q_n <= '1';
elsif rising_edge( clk) then -- En el flanco de subida del reloj
q <= d;
q_n <= not d;
end if;
end process;
end architecture flipflop_D;

Código VHDL 2.10: Biestable D con reset asíncrono activado al nivel LOW.

Por ejemplo, el Código VHDL 2.10 muestra un método estándar de modelar un


flip-flop D disparado por el flanco de subida del reloj (clk) y con una entrada reset
asíncrona (reset_n) activada en LOW. Esto significa que cuando la entrada de reset
pasa de valer '1' a valer 'O', entonces se inicializa el biestable: q <- 'O', q_n <- '1'.
En este texto se emplearán indistintamente los términos "biestable" y "fiip-flap".

El bloque process de la descripción del biestable es sensible a dos señales:


reset_n y clk. Esto implica que el bloque process sólo se ejecuta cuando se produce
un cambio en el valor de la señal de reset o en el valor de la señal de reloj.
La ejecución del bloque process consiste en la ejecución secuencial de todas las
sentencias contenidas dentro de él. En este diseño, el bloque process sólo contiene
una sentencia: la sentencia if.

No se permite emplear sentencias wait y lista de sensibilidad en un mismo


bloque process. Debe optarse por uno de estos dos procedimientos para controlar
la ejecución del bloque process.

A todos los efectos, la lista de sensibilidad es equivalente a una sentencia wait


del tipo

wait on señal1, señal2, ... , señalN;

121
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

situada como última sentencia del código secuencial, donde las señales que aparecen
en la sentencia wait son las de la lista de sensibilidad. Por ejemplo, los dos bloques
process siguientes son equivalentes:

procA: process (a1, a2) procB: process


begin begin
a1 <= '0'; a1 <= '0';
a2 <= '1' after 2 ns; a2 <= '1' after 2 ns;
wait on a1, a2;
end process procA; end process procB;

En el instante inicial de la simulación, las sentencias del bloque process son


ejecutadas por orden hasta que la ejecución del bloque queda suspendida, bien por
una sentencia wait, o bien por esta sentencia wait "implícita" que, como hemos
explicado, representa la lista de sensibilidad. La resolución del modelo en el instante
inicial de la simulación se explicará detalladamente en la Sección 3.5.

2.8. CÓDIGO SECUENCIAL

Es importante no confundir las sentencias secuenciales con los circuitos secuen-


ciales. Las sentencias secuenciales son las sentencias de VHDL que están incluidas
dentro de los bloques process y los subprogramas, mientras que los circuitos se-
cuenciales son circuitos con estados internos. Los bloques process y las sentencias
secuenciales que contienen pueden emplearse para describir tanto circuitos combi-
nacionales como secuenciales.

A continuación, se describirá el uso de las asignaciones secuenciales a variables y


a señales, las sentencias if y case, y el bucle for.

2.8.1. Asignación secuencial a una señal

La sintaxis de una asignación secuencial a una señal es idéntica a la de las


asignaciones concurrentes simples:

señal <= expr_nuevo_valor_señal;

donde implícitamente se entiende que la asignación del nuevo valor de la señal se


produce tras un retardo b. Como consecuencia del retardo b, si el bloque process
tiene lista de sensibilidad (por tanto no tiene sentencias wait), entonces se asigna a

122
CONCEPTOS BÁSICOS DE VHDL

las señales su nuevo valor una vez ha finalizado la ejecución de todas las sentencias
del bloque.

Dentro de un bloque process pueden realizarse varias asignaciones secuenciales


a una misma señal. Si todas las asignaciones a la señal tienen un retardo b, entonces
sólo la última de ellas tiene efecto. Dado que el valor de la señal no es actualizado
hasta que se completa la ejecución del bloque, la señal nunca adquiere valores
"intermedios". Por ejemplo, el fragmento de código:

x1, x2, x3, x4, y: std_logic;

process (x1, x2, x3, x4)


begin
y <= x1 and x3;
y <= x1 or x2;
y <= x3 and x4;
end process;

es equivalente a:

x1, x2, x3, x4, y: std_logic;

process (x1, x2, x3, x4)


begin
y <= x3 and x4;
end process;

Obsérvese que el resultado hubiera sido muy diferente si estas asignaciones a


señal, en lugar de estar incluidas dentro de un bloque process, hubieran estado
fuera del bloque. Es decir, hubieran sido asignaciones concurrentes a señal:

x1, x2, x3, x4, y: std_logic;

-- Asignaciones concurrentes de asignación


y <= x1 and x3;
y <= x1 or x2;
y <= x3 and x4;

Aunque este código es sintácticamente correcto, el diseño es incorrecto, ya que


hay riesgo de que se produzca un conflicto en los valores asignados a la señal y. En
simulación, la señal y tomará el valor 'X' (desconocido) si dos de las tres puertas
lógicas tienen un valor de la salida diferente (es decir, si se intenta asignar valores
diferentes a la señal y).

123
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.8.2. Asignación secuencial a una variable

Dentro de un bloque process pueden declararse variables. La sintaxis de una


asignación secuencial a una variable es básicamente la siguiente:

variable := expr_nuevo_valor_variable;

o
No se produce retardo en las asignaciones a variables. Es decir, se asigna el
nuevo valor a la variable en el mismo instante en que se evalúa la expresión. Por
ejemplo, consideremos el siguiente fragmento de código:

signal x1, x2, y : std_logic;


process (x1, x2)
variable aux : std_logic;
begin
aux '0';
aux aux or x1;
aux aux or x2;
y <= aux;
end process;

La variable aux asume su valor inmediatamente en cada sentencia secuencial.


Una vez ejecutadas las tres sentencias secuenciales de asignación a la variable aux,
el valor de dicha variable es igual a x1 or x2. Este valor de la variable aux se usa
para calcular el nuevo valor de la señal y. Este nuevo valor se asigna a la señal y
transcurrido un retardo o.

Obsérvese que las variables son locales al bloque process y por ello tienen que
ser declaradas dentro del bloque.

2.8.3. Sentencia if

Básicamente, la sintaxis de una sentencia if es la mostrada a continuación. Las


ramas elsif son opcionales: puede no haber ninguna, una o varias. La rama else
también es opcional, pero a lo sumo puede haber una.

if expresión_booleana_1 then
sentencias_secuenciales
elsif expresión_booleana_2 then
sentencias_secuenciales

el se
sentencias secuenciales
end if;

124
CONCEPTOS BÁSICOS DE VHDL

Las expresiones booleanas son evaluadas secuencialmente. Cuando una de las


expresiones vale true, se ejecutan las sentencias secuenciales de la rama correspon-
diente, ignorándose las sentencias de las demás ramas. Si ninguna de las expresiones
vale true y existe rama else, entonces se evalúan las sentencias de la rama else.

Obsérvese que cada una de las ramas de la sentencia if puede consistir en varias
sentencias secuenciales, entre las cuales pueden encontrarse otras sentencias if.

Con el fin de ilustrar el uso de la sentencia if, a continuación se muestran tres


ejemplos. El Código VHDL 2.11 describe un multiplexor de 4 entradas de 8 bits,
empleando para ello un bloque process con una sentencia if. El Código VHDL 2.12
muestra la descripción de un decodificador binario basada en el uso de una sentencia
if. Finalmente, el Código VHDL 2.13 muestra la descripción del codificador con
prioridad.

-- MUX 4:1 de 8 bits


-- fichero: mux_4xL8bits_archProcesslf. vhd
library IEEE;
use IEEE. std_logie_1164. all;

entity mux4 is
port ( x : out std_logic_vector(7 downto O);
a, b, e, d : in std_logic_vector(7 downto O);
S : in std_logic_vector ( 1 downto O) ) ;
end entity mux4;

architecture areh_proeif of mux4 is


begin
process ( a, b, e, d, s )
begin
if (s = 11 00 11 ) then
x <=a;
elsif (s = 11
01 11 ) then
X<= b;
elsif ( s 11
=1O11 ) then
x <=e;
else
X<= d;
end if;
end process;
end architecture areh_proeif;

Código VHDL 2.11: Multiplexor de 4 entradas de 8 bits.

125
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Decodificador binario 2 a 4
-- fichero: decodificador2x4_archProcessif. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity decodificador4 is
port ( x : out std_logic_vector(3 downto O);
s : in std_logic_vector ( 1 downto O) ) ;
end entity decodificador4;

architecture arch_decProcif of decodificador4 is


begin
process ( s )
begin
if ( s = 11 00 11 ) then
X <=
11
0001 11 ;
elsif ( s = 11 01 11 ) then
X <=
11
0010 11 ;
elsif ( s = 11 10 11 ) then
X <=
11
0100 11 ;
el se
X <=
11
1000 11 ;
end if;
end process;
end architecture arch_decProcif;

Código VHDL 2.12: Decodificador binario de 2 entradas.

-- Codificador de prioridad 4 a 2
-- fichero: codificadorPrioridad4a2_archProciJ. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity codificadorPrioridad4a2 is
port ( codigo out std_logic_vector(1 downto O);
activo out std_logic;
x : in std_logic_vector ( 3 downto O) ) ;
end entity codificadorPrioridad4a2;

architecture codPrior4a2_procif of codificadorPrioridad4a2 is


begin
process ( x )
begin
if ( x(3) = '1 ') then
codigo <= 11 11 11 ;
elsif ( x(2) = '1') then
codigo <= 11 10 11 ;
elsif ( x(1) = '1') then
codigo <= 11 01 11 ;
else
codigo <= 11 00 11 ;
end if;
activo <= x(3) or x(2) or x(1) or x(O);
end process;
end architecture codPrior4a2_procif;

Código VHDL 2.13: Codificador 4 a 2 con prioridad.

126
CONCEPTOS BÁSICOS DE VHDL

Una cuestión que debe tenerse en cuenta es que cuando se asigna valor a una señal
en alguna de las ramas de una sentencia if, pero no en todas las ramas, entonces
se está introduciendo "memoria" en el circuito. Es decir, la síntesis de ese código
VHDL dará lugar a un circuito secuencial. Esta situación se produce siempre que
no existe la rama else, ya que en este caso no hay sentencias de asignación a las
señales en caso de que todas las expresiones booleanas valgan false. Así pues, si se
desea sintetizar un circuito combinacional, debe incluirse la rama else.

Por ejemplo, supongamos que se programa el siguiente bloque process con el fin
de describir un circuito comparador con dos entradas (a y b) y tres salidas (mayor,
menor e igual), cuyo valor es '1' cuando se satisface la condición a>b, a<b o a=b,
respectivamente.

process ( a, b ) Diseño incorrecto!!


begin
if ( a > b ) then
mayor <= ' 1 ' ;
elsif ( a < b ) then
menor <= ' 1 ' ;
el se
igual <= ' 1 ' ;
end if;
end process;

La semántica de VHD L especifica que si no se asigna valor a una señal, entonces


ésta mantiene su anterior valor. Cuando se satisface a>b, se ejecuta la primera rama
de la sentencia if, con lo cual se asigna a mayor el valor '1'. Como no se asigna
valor a las señales menor e igual, éstas mantienen su anterior valor. Se produce una
situación análoga en las otras dos ramas, ya que en cada caso sólo se asigna valor a
una de las tres salidas. Esto implica que la síntesis de esta código dará lugar a tres
elementos de memoria.

El código correcto del comparador sería el mostrado a continuación, en el cual


se asigna valor a las tres salidas en todas las ramas, y que por tanto es sintetizado
como un circuito combinacional:

process ( a, b )
begin
if a > b ) then
mayor <= ' 1' ;
menor <= '0';
igual <= '0';
elsif ( a < b ) then
mayor <= '0';
menor<= '1';

127
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

igual <= '0';


el se
mayor <= '0';
menor <= '0';
igual <= '1';
end if;
end process;

Una forma de hacer el código más compacto y fácilmente legible es asignar un


valor por defecto a cada señal al principio del bloque process:

process e a, b )
begin
mayor <= '0';
menor <= '0';
igual <= '0';
if e a > b ) then
mayor <= ' 1 ' ;
elsif e a < b ) then
menor <= ' 1 ' ;
el se
igual <= ' 1 ' ;
end if;
end process;

Recuérdese que si se realizan varias asignaciones con retardo 6 a una misma señal
en un bloque process con lista de sensibilidad, sólo tiene efecto la última asignación
a la señal. En el código anterior, si se realiza una asignación a la señal en la rama de
la sentencia if, entonces esa es la asignación que tiene efecto. Si no se asigna valor a
la señal en la sentencia if, entonces tiene efecto la asignación del valor por defecto
(valor '0'). En cualquier caso, se asigna valor a las tres señales.

En los diseños de los circuitos es una buena práctica asignar valores por defecto
a las señales al comienzo del bloque process, cubriendo de esta forma los valores
no asignados en las ramas de la sentencia if.

2.8.4. Sentencia case

Básicamente, la sintaxis de una sentencia case es la mostrada a continuación.


La sentencia emplea el valor de expresión_case para seleccionar un conjunto de
sentencias secuenciales. Al igual que sucede en la sentencia concurrente select,
expresión_case debe ser o bien de tipo entero, o bien ser un vector unidimensional.

128
CONCEPTOS BÁSICOS DE VHDL

case expresión_case is
when valor_1 =>
sentencias_secuenciales
when valor _2 =>
sentencias_secuenciales

when valor _n =>


sentencias_secuenciales
end case;

Cada término valor _i debe ser un valor o conjunto de valores que puede tomar
expresión_case. Los valores valor_1, ... , valor_n deben ser exclusivos entre sí y
deben cubrir completamente el conjunto de valores posibles de expresión_case.
Puede emplearse others en la última selección para cubrir todos los valores no
considerados.

El Código VHDL 2.14, 2.15 y 2.16 describe el multiplexor, el decodificador y el


codificador, respectivamente, usando sentencias case.

-- MUX 4:1 de 8 bits


-- ficheTO: rnux_4xL8bits_aTchPTOcessCase. vhd
library IEEE;
use IEEE. std_logie_1164. all;

entity mux4 is
port ( x : out std_logic_vector(? downto O);
a, b, e, d : in std_logic_vector(7 downto O);
s : in std_logic_vector ( 1 downto O) ) ;
end entity mux4;
architecture areh_proeCase of mux4 is
begin
process ( a, b, e, d, s )
begin
case s is
when "00" =>
x <=a;
when "01" =>
X<= b;
when "10" =>
x <=e;
w hen others = >
X<= d;
end case;
end process;
end architecture areh_proeCase;

Código VHDL 2.14: Multiplexor de 4 entradas de 8 bits.

129
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- D ecodificador binario 2 a 4
-- fi chero: decod~ficador2x4_ archProcess Case . vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity decodificador4 is
port ( x : out std_logic_vector(3 downto O);
s : in std_logic_vector ( 1 downto O) ) ;
end entity decodificador4;

architecture arch_decProcCase of decodificador4 is


begin
process ( s )
begin
case s is
when "00" = >
X <=
11
0001";
when "01" = >
X <=
11
0010";
when "10" = >
X <=
11
0100";
w hen others = >
X <=
11
1000";
end case;
end process;
end architecture arch_decProcCase;

Código VHDL 2.15: Decodificador binario de 2 entradas.

-- Codificador de prioridad 4 a 2
-- fi chero: codificadorPrioridad4 a2_archProcCase. vhd
library IEEE;
use IEEE . std_logic_1164. all;

entity codificadorPrioridad4a2 is
port ( codigo out std_logic_vector( 1 downto O);
activo out std_logic;
X : in std_logic_vector(3 downto 0) );
end entity codificadorPrioridad4a2; ·

architecture codPrior4a2_procCase of codificadorPrioridad4a2 is


begin
process ( x )
begin
case x is
when "1000" 1 "1001" 1 "1010" 1 "1011"
"1100 11 1 "1101 11 1 "1110 11 1 "1111 11 =>
codigo <= "11";
when "0100" 1 "0101" 1 "0110" 1 "0111" =>
codigo <= "10";
when "0010" 1 "0011" =>
codigo <= "01";
when others =>
codigo <= "00";
end case;
activo <= x(3) or x(2) or x(1) or x(O);
end process;
end architecture codPrior4a2_procCase;

Código VHDL 2.16: Codificador 4 a 2 con prioridad.

130
CONCEPTOS BÁSICOS DE VHDL

La sentencia secuencial case es similar a la sentencia select de asignación con-


currente. Si cada rama when de la sentencia case consiste en una única asignación
a una señal, entonces ambas sentencias son equivalentes. Es decir, la sentencia de
asignación concurrente de selección mostrada a continuación en la parte izquierda
puede ser escrita de la forma mostrada en la parte de la derecha.

with expresión_selección select case expresión_selección is


señal <= expr_nuevo_valor_señal_1 when valor_selección_1 =>
when valor_selección_1, señal <= expr_nuevo_valor_señal_1;
expr_nuevo_valor_señal_2 when valor_selección_2 =>
when valor_selección_2, señal <= expr_nuevo_valor_señal_2;

expr_nuevo_valor_señal_n when valor_selección_n =>


when valor_selección_n; señal <= expr_nuevo_valor_señal_n;
end case;

La equivalencia entre estas dos sentencias se limita a este caso sencillo. La


sentencia case es mucho más flexible y general, dado que cada una de sus ramas
puede consistir en varias sentencias secuenciales.

Al contrario de lo que sucede con la sentencia if, los valores de selección de la


sentencia case deben cubrir todos los posibles valores de expresión_selección. Si
no se hace así, el código VHDL es incorrecto y la herramienta CAD de simulación
debería mostrar un error.

Por otra parte, si se asigna valor a alguna señal en unas ramas de la sentencia case
y no en otras, se está introduciendo "memoria" en el circuito, ya que la semántica
de VHDL especifica que si no se asigna valor a una señal, entonces ésta conserva su
valor anterior.

Por ejemplo, el siguiente código pretende describir un decodificador con prioridad,


con una señal de entrada (a) de tres bits y tres señales de salida (alto , medio y
bajo) de un bit. La entrada a(2) tiene la máxima prioridad, a continuación a(1) y
finalmente a(O). Si a(2) =' 1', entonces la señal alto se pone a '1'. Si a(2) ='O' y
a(1)=' 1', entonces la señal medio se pone al valor '1'. Finalmente, si a(2)=a(1)='0'
y a(O)=' 1', entonces bajo se pone a '1'.

process ( a ) -- Diseño incorrecto!!


begin
case a is
when "100" 1 "101" 1 "110" 1 "111" =>
alto <= '1';
when "010" 1 "011" =>
medio<= '1';

131
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

when others =>


bajo <= '1';
end case;
end process;

Por ejemplo, si a= 11 111 11 , entonces se ejecuta la primera rama de la sentencia case,


asignándose a alto el valor '1'. Puesto que no se asigna valor a las señales de salida
medio y bajo, éstas mantienen su valor. Se produce una situación similar en las otras
dos ramas de la sentencia case, y por tanto el diseño de este circuito contiene tres
elementos de memoria. Para evitar la síntesis de estos tres elementos de memoria, es
preciso asignar valor a todas las señales sea cual sea la rama de la sentencia when.

process ( a ) Diseño correcto!!


begin
alto <= '0';
medio <= '0';
bajo <= '0';
case a is
when "100 11 1 11 101 11 1 11 110 11 1 11 111 11 =>
alto <= '1';
when 11 010 11 1 11 011 11 =>
medio <= '1' ;
when others =>
bajo <= '1';
end case;
end process;

2.8.5. Bucle for

VHDL proporciona varios tipos de bucle, tales como los bucles for y while, así
como sentencias para el control de la ejecución del bucle, como la sentencia exit,
que hace que no se ejecuten las restantes iteraciones del bucle, o la sentencia next,
que hace que no se ejecuten las restantes sentencias de la iteración actual. De todas
estas sentencias, sólo un conjunto muy restringido puede ser usado para síntesis.

En esta sección nos limitaremos a presentar la sentencia for simple, que se emplea
para representar de manera abreviada la repetición de un conjunto de sentencias.
La sintaxis de esta sentencia es básicamente la siguiente:

for índice in rango_bucle loop


sentencias_secuenciales
end loop;

132
CONCEPTOS BÁSICOS DE VHDL

El bucle for anterior repite las sentencias secuenciales del cuerpo del bucle un
número fijo de iteraciones, que está determinado por el rango de valores rango_bucle.
El índice del bucle (índice) especifica el valor del rango de valores que corresponde
con la iteración actual, con lo cual va tomando los sucesivos valores de rango_bucle.
El índice del bucle (índice) no necesita ser declarado, ya que automáticamente
pertenece al mismo tipo de dato que rango_bucle.

Para que el bucle for pueda ser sintetizado, es preciso que rango_bucle quede
fijado en el momento de la síntesis, no pudiendo cambiar en función del valor de las
señales de entrada.

Los dos ejemplos siguientes pretenden ilustrar el uso de la sentencia for. El primer
ejemplo, mostrado en el Código VHDL 2.17, es un circuito que realiza bit a bit la
operación XOR de dos señales, cada una de las cuales tiene 4 bits. El rango del bucle
es (WIDTH-1) downto O. Se ha definido la constante WIDTH para hacer el código más
fácilmente legible y sencillo de modificar en el futuro. El índice del bucle es i: es
local al bucle y no necesita ser declarado. El índice toma el valor 3 en la primera
iteración del bucle, el valor 2 en la segunda iteración y así sucesivamente, hasta que
en la última iteración adquiere el valor O.

-- XOR bit a bit de dos señales de 4 bits


-- Fichero: xor_2señales_4bits_b'UcleFor. vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity xor _2señales_ 4bi ts is
port ( y : out std_logic_vector(3 downto O);
a, b : in std_logic_vector(3 downto o) );
end entity xor _2señales_ 4bi ts;
architecture xor _2señales_ 4bi ts_bucleFor of xor _2señales_ 4bi ts is
constant WIDTH : integer : = 4;
begin
process ( a , b )
begin
-- Este código es sólo para il'Ustrar el 'USO de la
-- sentencia for. La misma operación p'Uede realizarse
-- mediante 'Una única sentencia:
y<=axorb;
for i in ( WIDTH - 1 ) downto O loop
y(i) <= a(i) xor b(i);
end loop;
end process;
end architecture xor_2señales_4bits_bucleFor;

Código VHDL 2.17: XOR bit a bit de dos señales de 4 bits.

133
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- X OR de los bits de una señal de 4 bits


-- Fichero: xor_1 señaL4bits_bucleFor. vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity xor_1señal_4bits is
port ( y : out std_logic;
a : in std_logic_vector(3 downto o) );
end entity xor_1señal_4bits;
architecture xor_1señal_4bits_bucleFor of xor_1señal_4bits is
constant WIDTH : integer := 4;
signal tmp : std_logic_vector( WIDTH-1 downto O );
begin
process ( a , tmp )
begin
tmp(O) <= a(O);
for i in 1 to (WIDTH- 1) loop
tmp(i) <= a(i) xor tmp(i-1);
end loop;
end process;
y <= tmp(WIDTH-1);
end architecture xor_1señal_4bits_bucleFor;

Código VHDL 2.18: XOR de los bits de una señal de 4 bits.

El segundo ejemplo, mostrado en el Código VHDL 2.18, es un circuito que realiza


la operación XOR sobre los bits de una señal de 4 bits. Por ejemplo, consideremos
la señal a de 4 bits. La operación xor de los cuatro bits de la señal es: a(3) EB a(2) EB
a(1) EB a(O).
La forma básica de realizar en hardware un bucle for es convirtiendo el bucle
en una secuencia plana de sentencias, que no contenga ningún bucle. Así pues, se
replica el hardware correspondiente al cuerpo del bucle en cada iteración. Para ello,
es necesario que en el momento de la síntesis el rango debe ser conocido y constante.
Por ejemplo, el código plano correspondiente al bucle for del Código VHDL 2.17 es
el siguiente:

y(3) <= a(3) xor b(3);


y(2) <= a(2) xor b(2);
y(1) <= a(1) xor b(1);
y(O) <= a(O) xor b(O);

Similarmente, el código plano correspondiente al bucle for del Código VHDL 2.18
es el mostrado a continuación:

tmp(1) <= a(1) xor tmp(O);


tmp(2) <= a(2) xor tmp(1);
tmp(3) <= a(3) xor tmp(2);

134
CONCEPTOS BÁSICOS DE VHDL

Puede considerarse que el bucle for es una forma abreviada de escribir sentencias
repetitivas. El rango del bucle puede emplearse para especificar el número de réplicas
que debe realizarse del hardware, lo cual facilita la parametrización de los diseños,
por ejemplo, permitiendo ajustar el número de bits del circuito.

2.9. DESCRIPCIÓN DE LA ESTRUCTURA

VHDL permite diseñar circuitos de forma modular y jerárquica. Es decir, es


posible describir un circuito mediante instanciación y conexión de otros circuitos
que han sido previamente definidos, y a su vez usar este nuevo circuito para des-
cribir, mediante su conexión con otros circuitos, otro circuito de un nivel jerárquico
superior, y así sucesivamente.

Para describir un circuito mediante la instanciación y conexión de circuitos pre-


viamente definidos, primero es necesario declarar los componentes. A continuación,
deben instanciarse tantos componentes como requiera el diseño y debe especificarse
cómo deben conectarse. Los pasos a seguir son los siguientes:

l. Declarar los componentes. Un componente (component) representa la pareja


entity 1 architecture que define un determinado circuito (aquel que va a
instanciarse). La declaración del componente es muy similar a la declaración
de la entity del circuito que va a ser usado como componente. La sintaxis para
declarar un componente es:

component nombre_componente is
cláusula_generic;
cláusula_port;
end component nombre_ componente;

La declaración comienza con la palabra reservada component, seguida de un


identificador, que es el nombre asignado al componente. La palabra reservada
is es opcional. La declaración termina con las palabras reservadas end com-
ponent, seguidas opcionalmente del nombre del componente. En el cuerpo
de la declaración deben escribirse las cláusulas generic y port que aparecen
en la declaración de la entity del circuito que está siendo declarado como
componente, en caso de que las haya.
Si el nombre que se asigna al componente, nombre_componente, es igual al
nombre de la entity del circuito que está siendo declarado como componente y
además existe una única architecture para esa entity, entonces la declaración
del componente especifica de manera unívoca una entity 1 architecture. En

135
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

este caso, no es necesario definir una configuration en la cual se especifique


qué architecture está asociada a esa entity. Este será el caso de los ejemplos
desarrollados en esta Uni dad Didáctica.
Por el contrario, si hay varias architecture asociadas a la entity, entonces
aparte de la declaración del componente debe definirse una configuration,
en la cual se especifique qué architecture de las asociadas a la entity debe
emplearse en el componente.

2. Instanciar los componentes e indicar su conexión. La sintaxis para ello es:

nombre instancia cornponent nombre_componente


port rnap ( asociación_puertos_señales );

La etiqueta nombre_instancia es el nombre de la instancia del componente,


mientras que nombre_componente es el nombre del componente. La palabra
reservada component es opcional. Las palabras reservadas port map están
seguidas por una lista, escrita entre paréntesis, que relaciona los puertos de la
instancia del componente con las señales del circuito compuesto.
La conexión entre instancias de componentes se indica asociando a los puertos
a conectar una misma señal del modelo compuesto.
La asociación entre los puertos de las instancias de los componentes y las
señales del circuito compuesto puede realizarse de dos maneras:

- Asociación posicional, es decir, mediante la posición en que el puerto se


declara en la cláusula port de la entity del componente.
- Asociación nominal o explícita, en la cual se especifica el nombre del
puerto asociado a la señal, de la forma: puerto => señal.

A continuación, se muestran dos ejemplos de diseño mediante descripción es-


tructural. El primer ejemplo es la descripción estructural al nivel de puertas de un
multiplexor de dos señales de un bit. En la Figura 2.11 se muestra el diagrama y la
implementación al nivel de puertas del circuito. Cuando la señal de control sO vale
'O', la señal iO se transmite a la salida d, mientras que cuando sO vale '1' es la señal
i 1 la que se transmite a la salida.

Como puede observarse en la Figura 2.11b, 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.

136
CONCEPTOS BÁSICOS DE VHDL

MUX2:1

iO
d
il
sO

a) b)

Figura 2.11: Multiplexor de 2 señales de 1 bit: a) diagrama; b) implementación.

-- MUX 2: 1 de 1 bit
-- fich ero: mux2_1 b'it. vhd
library IEEE; use IEEE.std_logic_1164.all;
entity Mux2_1bit is
port ( d :out std_logic;
iO, i1 : in std_logic;
sO : in std_logic ) ;
end entity Mux2_1 bit;

architecture Mux2_1 bit of Mux2 1bit is


component not1 is
port ( yO : out std_logic;
xO : in std_logic ) ;
end component not1;
component or2 is
port ( yO : out std_logic;
xO, x1 : in std_logic );
end component or2;
component and2 is
port ( yO : out std_logic;
xO, x1 : in std_logic );
end component and2;
signa} n1, n2, n3 : std_logic;
begin
Inv_1 : not1 port map ( xO => sO, yO => n1);
And2_1 : and2 port map ( xO => iO, x1 => n1, yO => n2);
And2_2 : and2 port map ( xO => i1, x1 => sO, yO => n3);
Or2_1 : or2 port map ( xO => n2, x1 => n3, yO => d);
end architecture Mux2_1 bit;

Código VHDL 2.19: Descripción estructural al nivel de puertas lógicas de un multiplexor de dos
señales de un bit.

137
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

í------------------------------------1
1 1
1
1 MUX2:1 1
1

~ iO
1
1
1 d3
d
hl...:~ i 1
sO

MUX2:1
a2 iO d2
b2: d
il
sO

MUX2:1
al iO dl
bl : d
il
sO

MUX2:1
aO iO dO
1
d ..... ~
bO 1
il 1
1
1
1
sO 1
1
: -Á :
L------------------ ------- -----~-----1
sO

Figura 2.12: Multiplexor de 2 señales de 4 bit diseñado mediante la conexión de 4 multiplexores


de 2 señales de 1 bit.

-- MUX 2:1 de 4 bit. Fichero: mux2_4bit.vhd


library IEEE; use IEEE. std_logic_1164. all;
entity Mux2_ 4bi t is
port ( dO, d1, d2, d3 : out std_logic;
aO, a1, a2, a3 : in std_logic;
bO, b1, b2, b3 : in std_logic;
sO : in std_logic ) ;
end entity Mux2_ 4bi t;
architecture Mux2_ 4bi t of Mux2_ 4bi t is
component Mux2_1bi t is
port ( d : out std_logic;
iO, i1 : in std_logic;
sO : in std_logic ) ;
end component Mux2_1 bit;
begin
Mux2_0 : Mux2_1bi t port map ( d = > dO, iO = > ao, i1 = > bO , sO = > sO );
Mux2_1 : Mux2_1bi t port map ( d = > d1, iO = > a1, i1 = > b1 , sO = > sO );
Mux2_2 : Mux2_1bi t port map ( d = > d2, iO = > a2, i1 = > b2 , sO = > sO );
Mux2_3 : Mux2_1bi t port map ( d = > d3, iO = > a3, i1 => b3 , sO = > sO );
end architecture Mux2_ 4bi t;

Código VHDL 2.20: Descripción estructural de un multiplexor de 2 señales de 4 bit.

138
CONCEPTOS BÁSICOS DE VHDL

El Código VHDL 2.19 describe la estructura del circuito multiplexor. 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 dichos puertos.

Como segundo ejemplo para ilustrar la descripción estructural de los circuitos,


a continuación se emplearán multiplexores de 2 señales de 1 bit para componer un
multiplexor de 2 señales de 4 bits. En la Figura 2.12 se muestra la representación
esquemática del circuito. El Código VHDL 2.20 describe este circuito.

2.9.1. Diseños con estructura regular

Como se explicó en la Sección 2.6, la sentencia generate facilita la ejecución


iterativa o condicional de una porción de código concurrente.

La sentencia generate puede emplearse para describir circuitos con estructura


regular. Por ejemplo, el Código VHDL 2.21 describe el array de 8 puertas AND
de dos entradas mostrado en la Figura 2.13. Obsérvese que en el cuerpo del bucle
generate se definen instancias de puertas AND, cuyas entradas y salidas se conectan
a los componentes de las señales y, iO e i1. En particular, las entradas de la instancia
I -ésima de la puerta AND se conecta a las señales i oC I) e i 1 CI) y su salida se conecta
a la señal y(I).

El uso de la sentencia generate condicional resulta particularmente útil para


realizar las conexiones de los elementos extremos de una estructura repetitiva. Para
ilustrar el uso de la sentencia generate condicional, el Código VHDL 2.22 descri-
be un detector de paridad de 8 bits, cuyo circuito se muestra en la Figura 2.14,
empleando puertas XOR de dos entradas. Obsérvese que en el cuerpo de la archi-
tecture existe un bucle generate en cuyo interior hay dos sentencias generate
condicionales.

La primera sentencia generate condicional, que tiene la etiqueta inicial, se


ejecuta sólo cuando el índice I del bucle es igual a O. En el cuerpo de este generate
condicional está la instanciación de la puerta xor _O.

La segunda sentencia generate condicional, que tiene la etiqueta intermedio, se


ejecuta cuando el índice I del bucle es distinto de O. En el cuerpo de esta sentencia
están las instanciaciones del resto de puertas XOR de dos entradas. Las asociaciones
de los puertos de entrada y salida dependen del índice I del bucle.

139
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

y(5) y(7)

iO(O) i1(0) i0(1) i1(1) i0(2) i1(2) i0(3) i1(3) i0(4) i1(4) i0(5) i1(5) i0(6) i1(6) i0(7) i1(7)

Figura 2.13: Array de 8 puertas AND.

-- Array puertas AND usando sentencia GENERATE


-- Fichero: arrayAND_generate. vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity arrayAND is
port ( y : out stdJogic_vector(7 downto O);
i1, iO : in std_logic_vector(7 downto O));
end entity arrayAND;
architecture arrayAND of arrayAND is
component and2 is
port ( yO : out std_logic;
xO, x1 : in std_logic );
end component and2;
begin
gen_array: for I in 7 downto O generate
begin
and_array: and2
port map (y(I), i1(I), iO(I));
end generate gen_array;
end architecture arrayAND;

Código VHDL 2.21: Array de 8 puertas AND.

140
CONCEPTOS BÁSICOS DE VHDL

parity_IN(O)

parity_IN(7)

Figura 2.14: Detector de paridad compuesto por puertas XOR.

-- Detector de paridad usando sentencia GENERATE condicional


-- Fichero: detectorParidad_generate.vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity paridad is
port ( pari ty : out std_logic;
parity_IN : in std_logic_vector(? downto O));
end entity paridad;
architecture paridad of paridad is
signal temp: std_logic_vector(6 downto O);

component xor2 is
port ( yO : out std_logic;
xO, x1 : in std_logic );
end component xor2;

begin

parity <= temp(6);


gen_array: for I in O to 6 generate
inicial: if I = O generate
xor_O: xor2
port map (temp(O), parity_IN(O), parity_IN(1));
end generate inicial;

intermedio: if I /= O generate
resto_xor: xor2
port map (temp(I), temp(I-1), parity_IN(I+1));
end generate intermedio;
end generate gen_array;

end architecture paridad;

Código VHDL 2.22: Detector de paridad de 8 bits.

141
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.10. PARAMETRIZACIÓN

La parametrización es una propiedad fundamental en la reutilización del código,


ya que permite adaptar un mismo fragmento de código a diferentes usos.

En la Sección 2.3.2 se explicó cómo pueden declararse constantes generic al


declarar una entity. El valor de estas constantes generic puede ser usado en la
architecture asociada a la entity. Esto permite parametrizar tanto la descripción
del comportamiento como la descripción de la estructura.

A continuación, se muestran ejemplos sencillos que ilustran el uso de las cons-


tantes generic. Por otra parte, el caso práctico descrito en la Sección 5.6 ilustra el
empleo de constantes generic tanto para la parametrización del comportamiento
como de la estructura.

2.10.1. Parametrización del comportamiento

En la Sección 2.3.2 se mostró la siguiente entity de una puerta AND:

entity and2 is
generic ( Tpd: time);
port ( yO out std_logic;
xO, xl : in std_logic );
end entity and2;

La constante generic Tpd especifica el retardo de propagación del módulo. Su


valor es usado en la sentencia que define el comportamiento de la puerta:

architecture and2D of and2 is


begin
yO <= xO and xl after Tpd;
end architecture and2D;

2.10.2. Parametrización de la estructura

Cuando se instancia un componente, puede asignarse valor a sus constantes ge-


neric. Esto permite adaptar la instancia del componente a la aplicación en concreto
a la que vaya a destinarse al formar parte del circuito de nivel jerárquico superior.

142
CONCEPTOSBÁffiCOSDEVHDL

La sintaxis para asignar valor a las constantes generic, al instanciar el compo-


nente, es mostrada a continuación. La palabra reservada component es opcional.

nombre instancia cornponent nombre_componente


generic rnap e valores_constantes_generic )
port rnap e asociación_puertos_señales );

Por ejemplo, podría asignarse el valor 3 ns a la constante generic Tpd, al instan-


ciar un componente and2 llamado puertaAND1, de la forma siguiente:

puertaAND1 : component and2


generic map eTpd => 3ns)
port map e yO=> sig_out, xO =>sigO, x1 => sig1);

Podrían asignarse valores diferentes de la constante generic a otras instancias


de la clase and2.

2.11. SENALES, VARIABLES Y CONSTANTES

En VHDL se emplean variables, señales y constantes para describir la operación


del circuito.

- Las señales corresponden con las señales lógicas reales existentes en el circuito.
Se emplean señales para representar datos a los que deba asignarse valor fuera
de los bloques secuenciales (process, function y procedure), y datos que
necesitan ser transferidos desde un puerto de entrada o a un puerto de salida.
Los puertos sólo pueden ser señales.

- Las variables pueden o no corresponder con señales físicas reales. Dos ejemplos
típicos de uso de las variables son los siguientes:

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.
Puesto que una señal de salida (un puerto cuyo modo es 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.

143
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

- Las constantes corresponden a magnitudes cuyo valor no cambia durante la


simulación (típicamente retardos, número de líneas de buses, número de bits
de palabras, etc.) .

Constantes y señales pueden ser declaradas en un package, entity o architectu-


re (en la parte dedicada a las declaraciones), mientras que las variables sólo pueden
ser declaradas y únicamente son visibles dentro de bloques de código secuencial
(process, function y procedure). Las señales no pueden ser declaradas dentro de
bloques de código secuencial.

Básicamente, la sintaxis para la declaración de señales, variables y constantes


es la mostrada a continuación, donde signal, variable y constant son palabras
reservadas:

signal nombre señal tipo_dato valor_inicial;


variable nombre_ variable tipo_dato valor_inicial;
constant nombre constante tipo_dato expresión;

En las declaraciones debe especificarse el nombre de la variable, señal o constante


que se está declarando y su tipo de dato. En la declaración de variables y señales
es posible asignarles valor inicial, si bien esta asignación no es sintetizable. La
inicialización se explicará con detalle más adelante. Al declarar una constante debe
asignársele valor.

Respecto a la asignación de valor a las variables, señales y constantes, cabe


realizar las distinciones siguientes:

- Para asignar valor a una variable se emplea : =. La sintaxis es:


nombre_variable := expresión;

Sólo puede asignarse valor a las variables en sentencias incluidas dentro de los
bloques de código secuencial. La asignación a la variable del nuevo valor se
realiza inmediatamente. Es decir, sin ningún retardo.

- Para asignar valor a una señal se emplea <=. La sintaxis es:


nombre_señal <= forma_de_onda;

Las sentencias de asignación a señal pueden ser tanto asignaciones concurren-


tes, como asignaciones secuenciales (aquellas situadas dentro de los bloques
de código secuencial). En ambos casos, salvo que se indique explícitamente el
retardo, se asigna a la señal el nuevo valor una vez transcurrido un retardo 6.

144
CONCEPTOSBÁffiCOSDEVHDL

Debe tenerse en cuenta que las señales definidas en el port de una entity
tienen una dirección, lo cual condiciona su uso: no puede leerse el valor de una
señal de salida (out), ni asignarse un valor a una señal de entrada (in).
Las señales declaradas en la definición de la architecture puede ser usadas
tanto en la parte derecha como en la izquierda de las asignaciones.

- Como .se ha explicado anteriormente, la asignación de valor a las constantes se


realiza al declararlas. Se les asigna el valor obtenido de evaluar expresión:

constant nombre_constante : tipo_dato := expresión;

Las sentencias de definición de constantes pueden situarse en las unidades de


diseño entity y architecture, antes de la palabra reservada begin. También
pueden definirse constantes dentro de la definición de un package.

El empleo de constantes facilita la comprensión del código. Considérense las dos


formas siguientes de definir el circuito detector de un número par de entradas '1 '.

architecture comp_red_xor of architecture comp_red_xor of ...


signal impar : std_logic; signal impar : std_logic;
constant BUS_WIDTH: integer := 3;
begin begin

tmp := O; tmp := O;
for i in 2 downto O loop for i in (BUS_WIDTH-1) downto O loop
tmp := tmp xor a(i); tmp := tmp xor a(i);
end loop; end loop;

El diseño mostrado en la parte derecha es claramente más sencillo de entender


debido al uso de la constante BUS_WIDTH, que representa el número de líneas del bus
de señales de entrada.

2.12. TIPOS DE DATOS Y OPERADORES

En VHDL, cada objeto es de un cierto tipo de dato. Un tipo de dato en VHDL


está definido por los dos conjuntos siguientes: el conjunto de valores que puede tomar
el objeto y el conjunto de operaciones que pueden realizarse sobre los objetos de ese
tipo de dato.

145
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Se dice que VHDL es un lenguaje "fuertemente tipado". Esto significa que a un


objeto sólo puede asignársele un valor de su tipo y que sólo pueden realizarse sobre
el objeto las operaciones definidas para su tipo de dato. Para asignar a un objeto
un valor de un tipo diferente, previamente debe convertirse el valor al tipo de dato
del objeto, usando para ello una función de conversión del tipo.

La motivación que hay detrás de hacer que un lenguaje sea fuertemente tipado
es facilitar la detección de errores de programación. Por ejemplo, si se asigna un
valor booleano a una señal del tipo integer, entonces el entorno de simulación puede
detectar el error en la fase de análisis. La desventaja de este tipo de lenguajes es que
precisan de la definición de funciones para la conversión entre tipos de datos, cuyo
uso en ocasiones dificulta la programación y la comprensión del código.

En VHDL se emplean tipos de datos para modelar las señales, variables y cons-
tantes. Estos tipos de datos pueden ser los estándar de VHDL o bien tipos definidos
por el programador. Los tipos de datos más comúnmente usados para las señales
son los tipos estándar std_logic, std_logic_vector, signed y unsigned.

El programador puede definir sus propios tipos de datos, bien como un subconjun-
to de los tipos de datos estándar, o bien puede definir sus propios tipos enumerados.
En teoría, cualquier tipo de dato con un número finito de valores puede hacerse
corresponder con un conjunto de representaciones binarias, y por tanto puede ser
realizado en hardware.

2.12.1. Tipos predefinidos en VHDL

Hay cerca de una docena de tipos de datos predefinidos en VHDL estándar IEEE
1076. De ellos, sólo algunos son relevantes desde el punto de vista de la síntesis:

integer VHDL no define el rango exacto de valores del tipo integer, pero
especifica que el rango mínimo debe ser desde -(2 31 - 1) hasta
231 - 1, que corresponde con 32 bits. Dos tipos de datos relacionados
(formalmente denominados subtipos) son natural y positive. El
primero incluye el cero y los números positivos, mientras que el
segundo incluye sólo los números positivos.
boolean Puede tomar dos valores: false, true.
bit Puede tomar dos valores: 'O' , ' 1 ' .
bit_vector Vector unidimensional de elementos del tipo bit.

146
CONCEPTOS BÁSICOS DE VHDL

Los literales de vectores de bits se escriben entre comillas dobles y opcionalmente


precedidos por una letra que indica la base en la cual están expresados: B (binario),
o (octal) y X (hexadecimal).
Si no se especifica la base, el vector se interpreta como binario. Un guión bajo
insertado entre dígitos adyacentes no altera el valor: es ignorado por el compilador
del código VHDL, pero hace que las cadenas sean más fácilmente legibles para el
programador.

La longitud del literal cadena de bits es el número de valores del tipo bit en la
secuencia representada. Por ejemplo, los cuatro literales

X"F_FF" 0"7777" 8"1111_1111_1111" "1111_1111 1111"

representan el mismo valor de 12 bits.

Operadores

En VHDL hay definidos cerca de 30 operadores. En un lenguaje fuertemente


tipado, la definición del tipo de dato incluye las operaciones que pueden realizarse
sobre los objetos de ese tipo. Es importante saber qué tipos de dato pueden usarse
con cada operador.

En la Tabla 2.1 se muestran algunos de los operadores definidos en VHDL'93 y


los tipos de dato a los que puede aplicarse cada operador.

Durante la síntesis, los operadores que se emplean en el código VHDL deben ser
implementados mediante componentes físicos. La complejidad del hardware asociado
a cada operador varía significativamente. Los operadores de desplazamiento (sil, srl,
sla, sra, rol, ror) y el operador xnor no están definidos en VHDL'87 y no están
incluidos en el estándar de síntesis IEEE 1076.6 RTL, que define el subconjunto de
VHD L a emplear para síntesis.

En la Tabla 2.2 se indica la precedencia de los operadores, los cuales han si-
do clasificados en siete grupos. Los operadores del mismo grupo tienen la misma
precedencia. Por ejemplo, en la expresión siguiente:

a + b > e or a < d

en primer lugar se realizará la operación +, a continuación se realizarán las opera-


ciones > y <, y finalmente se realizará la operación or.

147
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Tabla 2.1: VHDL'93- Operadores y tipos de dato a los que se aplican.

Operador Significado Tipo del Tipo del Tipo del


operando a operando b resultado
a ** b Exponenciación integer integer integer
abs a Valor absoluto integer integer
not a NOT lógico boolean, bit, boolean,bit,
bit_vector bit_vector
a * b Multiplicación integer integer integer
a 1 b División
a mod b Módulo
a rem b Resto
+ a Identidad integer integer
- a Negación
a + b Suma integer integer integer
a - b Resta
a &b Concatenación vector, elemen- vector, elemen- vector
to to
a sll b Desplaz. lógico izqda bit_vector integer bit_vector
a srl b Desplaz. lógico dcha
a sla b Desplaz. aritmético izqda
a sra b Desplaz. aritmético dcha
a rol b Rotación lógica izqda
a ror b Rotación lógica dcha
a = b Comprueba igualdad cualquiera mismo que a boolean
a /= b Comprueba desigualdad
a < b Menor que escalar, vector mismo que a boolean
a <= b Menor o igual que
a > b Mayor que
a >= b Mayor o igual que
a and b AND lógica boolean,bit, mismo que a mismo que a
bit_vector
a or b OR lógica
a nand b NAND lógica
a nor b NOR lógica
a xor b OR exclusiva lógica
a xnor b NOR exclusiva lógica

Tabla 2.2: Precedencia de los operadores.

Precedencia Operadores
Mayor
** abs not
* 1 mod rem
+ (identidad y negación)
& + (suma y resta)
sll srl sla sra rol ror
/= < <= > >=
Menor and or nand nor xor xnor

148
CONCEPTOS BÁSICOS DE VHDL

Si una expresión consta de varios operadores con la misma precedencia, entonces


comienza a evaluarse el operador situado más a la izquierda en la expresión y se
progresa avanzado hacia la derecha. Por ejemplo, en la expresión

a + b + e + d

primero se calcula la suma de a y b, el resultado se suma con e y finalmente se realiza


la suma con d.

Es importante tener en cuenta que, al contrario de lo que sucede en álgebra


booleana, los operadores and y or tienen la misma precedencia en VHD L y, por
tanto, deben usarse paréntesis para indicar el orden en que deben realizarse las
operaciones lógicas, como por ejemplo en:

ea and b ) or ee and d )

En general, es una buena práctica emplear paréntesis para representar de manera


explícita el orden en que deben realizarse las operaciones, incluso en aquellos casos
en que esto no sea necesario. Por ejemplo, la expresión

a + b > e or a < d

puede ser igualmente escrita de la forma siguiente:

e e a + b ) > e ) or e a < d )

Ambas expresiones son equivalentes, pero la segunda es más descriptiva y por ello
más sencilla de interpretar. En definitiva, es código más fácilmente comprensible.

2.12.2. Tipos del paquete IEEE.std_logic_ll64

El propósito original del tipo de dato bit era representar los dos valores binarios
usados en el álgebra booleana y la lógica digital. Obsérvese que la información se
comunica dentro de un sistema digital usando señales de valor binario (O ó 1). En
los sistemas de lógica positiva, cuando el voltaje de la señal tiene un valor "alto",
representa un 1 lógico, y cuando toma un valor "bajo" representa un O lógico.

En los circuitos alimentados por fuentes de tensión de 5 voltios, suele interpretarse


que los voltajes en el rango entre O voltios y 1.5 voltios corresponden a un 'O',
mientras que los voltajes en el rango entre 3.5 voltios y 5 voltios corresponden a
'1' lógico (véase la Figura 2.15). La señal sólo debería tomar valores intermedios
cuando pasa de ' O' a ' 1 ' , o viceversa.

149
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

5V
Ilógico
3.5V

1.5 V
} Valor lógico
indefinido

O lógico
ov
Figura 2.15: Rangos típicos de voltaje para O y 1 lógicos en tecnologías CMOS de 5 voltios.

Aunque todas las señales son interpretadas en los sistemas digitales como O y 1
lógicos, no siempre es posible modelar y simular los sistemas digitales usando sólo
señales O lógico y 1lógico. En un sistema real la señal puede tener otros valores. Por
ejemplo, puede valer "alta impedancia" a la salida de un buffer triestado. Asimismo,
puede tomar un valor intermedio entre los valores O y 1 lógicos, debido a que la
señal es generada por dos drivers, uno que intenta ponerla a O lógico y el otro que
intenta ponerla a 1 lógico. Por otra parte, el valor de algunas señales puede no ser
conocido en determinado intervalo de tiempo de la simulación, por ejemplo porque
esas señales todavía no hayan sido inicializadas, es decir, no se les haya asignado
valor.

Con el fin de reflejar mejor las propiedades del hardware digital, en el estándar
IEEE 1164 se introdujeron nuevos tipos de datos, que extendían los tipos bit y
bit_vector.

Estos nuevos tipos de datos fueron definidos en el paquete IEEE. std_logic_1164.


Entre estos nuevos tipos, sin duda los más ampliamente usados son std_logic y
std_logic_vector. El tipo std_logic es más versátil que bit, ya que aparte de los
valores 'O' y ' 1 ' , puede tomar otros siete valores.

Para poder usar en los diseños estos tipos de dato, es necesario especificar que se
desea usar el paquete IEEE. std_logic_1164. Esto se hace escribiendo las siguientes
sentencias al comienzo del código, donde library y use son palabras reservadas:

library IEEE;
use IEEE.std_logic_1164.all;

En los diseños y bancos de prueba mostrados en este texto, se empleará el tipo


de dato std_logic para representar las señales binarias y el tipo std_logic_vector
para representar los vectores de señales binarias.

150
CONCEPTOS BÁSICOS DE VHDL

std.Jogic

El tipo de dato std_logic pueden tomar nueve valores. Además de los valores
'O' y ' 1 ' , 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:

'U' El valor de la señal está sin inicializar. Es decir, aún no se ha asignado valor a
la señal.

'X' No puede determinarse el valor de la señal, quizá debido a que se intenta


asignar simultáneamente a la señal varios valores diferentes entre sí. Esto puede
suceder si varias sentencias concurrentes asignan valor a una misma señal.
Desde el punto de vista estructural, esta situación se produce si una puerta
lógica intenta poner a 'O' la señal, mientras otra puerta lógica intenta ponerla
a '1 '.

'Z' Alta impedancia. El valor indica que la señal ha quedado desconectada. Los
buffers triestado proporcionan una salida con este valor (véase la Sección l. 9.1).

Los restantes posibles valores de una señal del tipo std_logic son: 'W' (descono-
cida débil), 'L' (cero débil), 'H' (uno débil) y'-' (don't care, que puede traducirse
como "no importa").

Los valores 'L' (cero débil) y 'H' (uno débil) indican que la señal es obtenida de
circuitos de lógica cableada, en los cuales la corriente es débil. En la actualidad estos
valores raramente se usan, ya que no suelen emplearse circuitos de lógica cableada.

El valor '-' ( don't ca re) se usa para facilitar el diseño lógico. Puede usarse como
valor de entrada, con el fin de hacer más compacta y fácil de entender la tabla de la
verdad. Por ejemplo, la tabla de la verdad del codificador 4 a 2 con prioridad diseñado
en el Código VHDL 2.6, 2.9, 2.13 y 2.16 puede expresarse de manera compacta y
descriptiva usando don't care:

X codigo activo
1 - - - 1 1 1
o1 1 o 1
oo 1 o1 1
oo o 1 oo 1
oo o o oo o

151
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Cuando don't care se usa como valor de salida, indica que el valor exacto ('O' ó
'1 ') no es importante. Esto ocurre cuando algunas de las combinaciones de entrada
no son usadas. Al indicar que la salida es don't care, se deja libertad al algoritmo de
síntesis para que asigne a la salida aquel valor que permita reducir la complejidad
del circuito.

Algunos comentarios respecto a la interpretación que hacen las herramientas de


síntesis de los valores del tipo std_logic:

- Los valores 'O' y 'L' son interpretados como O lógico.

- Los valores '1' y 'H' son interpretados como 1 lógico.

- El valor 'z' es interpretado como alta impedancia.

- Los valores '-'y 'X' son interpretados como don't care. Así, en algunos diseños
mostrados en el Tema 6 se usará 'X' como don't ca re.

- Algunas herramientas de síntesis no aceptan los valores 'U' y 'W' . Por el


contrario, otras interpretan 'W' como don't ca re.

std_logic_ vector

En general, un vector es una colección de elementos del mismo tipo de da-


to. Cada elemento del vector es identificado mediante un índice. El tipo de dato
std_logic_vector es un vector de elementos del tipo std_logic.

El siguiente ejemplo ilustra el uso de std_logic_vector. Supongamos una señal


de 8 bits llamada a. Su declaración es:

signal a: std_logic_vector ( 7 downto O);

La declaración indica que la señal tiene 8 bits, que están indexados desde 7 hasta
O. El bits más significativo, es decir, el situado más a la izquierda, tiene el índice 7.
El bit menos significativo, es decir, el situado más a la derecha, tiene el índice O.

Es posible acceder a uno de los bits usando su índice. Por ejemplo: a(2), a(7).
También, es posible acceder a una conjunto de bits especificando su rango. Por
ejemplo: a(7 downto 2), a(2 downto O).

Otra forma de std_logic_vector es usando un rango ascendente, como en:

signal a: std_logic_vector (Oto 7 );

152
CONCEPTOS BÁSICOS DE VHDL

En este caso, el bit más significativo (situado más a la izquierda) tiene el índice
O, lo cual puede inducir a error si el bus o vector es interpretado como un número
binario. Por ello, no usaremos esa forma en este libro.

Operadores

La definición de un tipo de dato incluye no sólo el conjunto de valores que puede


tomar, sino que también incluye el conjunto de operaciones que pueden realizarse
sobre los datos de ese tipo. En VHDL pueden emplearse funciones con el mismo
nombre para operados de distinto tipo. Es decir, pueden definirse varias funciones
con el mismo nombre, cada una para un tipo diferente de dato. Esto se denomina
sobrecarga de los operadores.
En el paquete IEEE. std_logic_1164 se han sobrecargado todos los operadores
lógicos (and, or, nand, nor, xor, xnor) para std_logic y std_logic_vector. Obsér-
vese que en el paquete IEEE. std_logic_1164 no se han sobrecargado las operaciones
aritméticas y por tanto estas operaciones no pueden aplicarse a estos tipos de datos.

Conversión de tipos

En el paquete IEEE. std_logic_1164 se han definido las funciones para la con-


versión entre los tipos bit y std_logic, así como entre los tipos bit_vector y
std_logic_vector. En la Tabla 2.3 se muestran estas funciones.

Tabla 2.3: Funciones del paquete IEEE.stcLlogic_ll64.

Conversión de: a: Función


std_logic bit to_bit(arg)
bit std_logic to_stdulogic(arg)
std_logic_vector bit_vector to_bitvector(arg)
bit_vector std_logic_vector to_stdlogicvector(arg)

A continuación, se muestran algunos ejemplos de conversión entre tipos. Para


ello, se emplearán las señales siguientes:

signal si, s2, s3 std_logic_vector ( 7 downto O);


signal b1, b2 bit vector ( 7 downto O);

Por ejemplo, pueden realizarse las siguientes asignaciones entre estas señales:

153
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

s1 <= to_stdlogicvector( b1 );
b2 <= to_bitvector( s1 and s2 );
s3 <= to_stdlogicvector( b1 ) or s2;

o equivalentemente, la última sentencia de asignación puede escribirse:

s3 <= to_stdlogicvector( b1 or to_bitvector( s2) );

2.12.3. Operadores sobre bit_vector y std_logic_vector

Algunas operaciones, tales como la concatenación, las operaciones relacionales


y la agregación, están definidas sobre los tipos bit_vector y std_logic_vector. A
continuación, veremos cómo pueden realizarse estas operaciones.

Operadores relacionales

Los operadores relacionales (=, /=, <, <=, >, >=) pueden ser empleados para
comparar dos datos de tipo vector. Los dos operandos deben tener el mismo tipo de
elementos, pero sus longitudes pueden ser diferentes.

Cuando se aplica el operador, los dos vectores son comparados elemento a elemen-
to. La comparación comienza por el elemento situado más a la izquierda y continúa
hasta que puede establecerse cuál es el resultado. Si se alcanza el final de un vector
antes que el final del otro, entonces se considera que el primer vector (el de menor
longitud) es menor que el segundo, y por tanto, se considera que los dos vectores no
son iguales.

Por ejemplo, cada una de las siguientes operaciones devuelve el valor true:
11
o11 = o11
11 11 11
'
11
o11 11
> 11
o1o
11
'
11
o11 11
>11 0001 o11 '
11
o11 o
11
> 11
o11 11

Los vectores de diferente longitud pueden generar en ocasiones resultados ines-


perados (o dicho de otra manera, errores sutiles difíciles de localizar). Por ejemplo,
supongamos que las señales s1 y s2 tienen diferente longitud y escribimos:

if ( s1 = s2 ) then

el se

Debido a que las señales s1 y s2 tienen diferente longitud, la comparación de


igualdad siempre tiene el resultado false, con lo cual nunca se ejecutará la rama then.

154
CONCEPTOS BÁSICOS DE VHDL

Este tipo de error es bastante difícil de depurar, ya que el código es sintácticamente


correcto.

Operador concatenación

El operador de concatenación, &, permite concatenar elementos, segmentos de


vectores y vectores completos, para formar vectores de mayor longitud. Por ejemplo,
la siguiente sentencia desplaza los elementos del vector a dos posiciones hacia la
derecha e insertar dos bits 'O' por la izquierda:

y<= "00" & a( 7 downto 2 );

La siguiente sentencia rota los elementos del vector hacia la derecha dos posicio-
nes:

y<= a( 1 downto O) & a( 7 downto 2 );

Agregación de vectores

La agregación no es un operador, sino una construcción que permite asignar valor


a vectores. La forma más sencilla de expresar una agregación es usar una colección de
valores escritos entre comillas dobles. Por ejemplo, pueden realizarse las asignaciones
siguientes:

x1 <= "101111"; Representación binaria del decimal 47


x2 <= 0"57"; Representación octal del decimal 47
x3 <= H"2F"; Representación hexadecimal del decimal 47

Otra posibilidad es especificar la lista de valores, cada uno en su correspondien-


te posición. Este tipo de agregación se denomina agregación mediante asociación
posicional. La asignación

y<= "10101010";

es equivalente a:
y <= e, 1 , , , o, , , 1 , , , o, , , 1, , , o, , , 1, , , o, ) ;
También, puede emplearse la forma

índice => valor

155
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

para especificar de manera explícita el valor para cada índice. Esta forma de agrega-
ción se denomina asociación mediante nombre. La sentencia anterior puede escribirse
de la forma siguiente:

y <= ( 7 => ' 1 ' ' 6 => 'o' ' 5 => ' 1 ' ' 4 => 'o' '
3 => ' 1 ' ' 2 => 'o' ' 1 => ' 1' ' o => 'o' ) ;

o equivalentemente, con las asociaciones en un orden cualquiera:

y <= ( 7 => ' 1 ' ' 3 => ' 1 ' ' 5 => ' 1 ' ' 1 => ' 1 ' '
6 => 'o' ' 2 => 'o' ' 4 => 'o' ' o => 'o' ) ;

Esta asignación indica que el valor asignado al componente con índice 7 (es
decir, y(7)) es '1', que el valor asignado el componente con índice 6 es '0', y así
sucesivamente.

También, es posible combinar los índices, como por ejemplo en:

y <= ( 7 5 3 1 => '1''


6 4 2 o => 'o' ) ;

o bien, emplear la palabra reservada others para referirse a todos los índices que
no han sido nombrados. Por ejemplo:

y<= ( 7 1 5 1 3 1 1 => '1',


others => '0' );

También puede emplearse la palabra reservada others para asignar el mismo


valor a todos los componentes de un vector, como por ejemplo en:

y<= ( others => '0' );

Este tipo de sentencia tiene la ventaja de que es independiente del número de


componentes que tenga la señal, con lo cual sigue siendo válida si se modifica la
longitud del vector.

2.12.4. Tipos del paquete IEEE.numeric_std

Como hemos visto anteriormente, no pueden realizarse operaciones aritméticas


sobre los datos de los tipos bit_vector y std_logic_vee-tor. 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 operaciones lógicas.

156
CONCEPTOS BÁSICOS DE VHDL

Sí pueden realizarse operaciones aritméticas sobre los datos del tipo integer. Por
ejemplo, para realizar la suma de las señales a y b, puede emplearse el tipo integer:

signal a, b, suma : integer;

suma <= a + b;

Sin embargo, es complicado traducir esta sentencia a hardware, ya que el código


no indica el rango (número de bits) de las señales a y b. Aunque esta cuestión es
irrelevante para simulación, es muy importante para síntesis. Por ejemplo, hay una
gran diferencia, en lo que respecta a la complejidad del circuito, entre un circuito
sumador de dos números de 32 bits y un circuito sumador de dos números de 8 bits.

Una alternativa mucho más adecuada desde el punto de vista de la síntesis es


usar un vector de ceros y unos, e interpretarlo como un número binario con signo
o sin signo. De esta manera, quedan definidas de manera precisa la anchura de
los operandos y el tamaño del circuito sumador, con lo cual se obtiene un mejor
control sobre el hardware resultante de la síntesis. El paquete IEEE. numeric_std fue
desarrollado con este propósito.

unsigned y signed

Los tipos unsigned y signed están definidos en el paquete IEEE. numeric_std.


Son vectores de elementos del tipo std_logic:

- Para el tipo de dato unsigned, el vector se interpreta como un número


binario sin signo, donde el elemento situado más a la izquierda es el bit más
significativo del número binario.

- Para el tipo de dato signed, se interpreta el vector como un número binario


con signo, en el formato de complemento a 2. El elemento situado más a la
izquierda es el bit más significativo del número binario, que representa el signo
del número.

Obsérvese que los tres tipos de dato std_logic_vector, unsigned y signed están
definidos como vectores de elementos del tipo std_logic. Puesto que VHDL es un
lenguaje fuertemente tipado, estos tres tipos son considerados como tipos de datos
independientes, lo cual por otra parte es razonable ya que los tres tipos de dato son
interpretados de manera diferente.

157
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Por ejemplo, consideremos el vector de 4 bits "1100". Representa el número 12 si


es interpretado como un dato unsigned. Representa el número -4 si es interpretado
como del tipo signed. Finalmente, representa 4 bits independientes entre sí (por
ejemplo, cuatro señales de status) si es interpretado como del tipo std_logic_vector.

Puesto que los tipos de dato unsigned y signed son vectores, sus declaraciones
son similares a las del tipo std_logic_vector. Por ejemplo:

signal a: signed ( 15 downto O);

Para poder usar los tipos de dato unsigned y signed, debe incluirse la sentencia
especificando que va a usarse el paquete IEEE. numerie_std. Asimismo, puesto que
el paquete IEEE. numeric_std emplea el tipo de dato std_logic, debe indicarse que
va a usarse el paquete IEEE. std_logic_1164. Es decir, las primeras sentencias del
diseño deben ser:

library IEEE;
use IEEE.std_logie_1164.all;
use IEEE.numerie_std.all;

Operadores

Puesto que la finalidad del paquete IEEE. numerie_std es facilitar la realización


de operaciones aritméticas, en este paquete se sobrecargan todos los operadores
aritméticos: abs, *, 1, mod, rem, + y -. Por ejemplo, las siguientes sentencias son
válidas:

signal a, b, e, d unsigned ( 7 downto O);

a <= b + e;
d <= b + 1;
e <= ( 5 + a + b ) - e;

La definición de los operadores suma y resta sigue el modelo de un sumador


físico. Es decir, cuando se produce rebosamiento, el resultado de la suma es como
un contador que puede dar tantas vueltas como sea preciso.

Los operadores relacionales (=, !=, <, <=, >, >=) han sido sobrecargados. Los
operadores relacionales aplicados a datos del tipo unsigned o signed no comparan
los componentes del vector elemento a elemento, sino que interpretan los vectores
como números binarios.

158
CONCEPTOS BÁSICOS DE VHDL

Por ejemplo, consideremos la expresión:


11
011 11 > 11
1000 11

Si el tipo de dato de los dos operandos es std_logic_vector, entonces la expresión


vale false, puesto que el primer elemento de 11 001 11 (que es un 'O') es menor que el
primer elemento de 11 1000 11 (que es un '1 ').

Si el tipo de dato de los dos operandos es unsigned, entonces los operandos son
interpretados como 3 y 8 respectivamente. La expresión vale nuevamente false.

Sin embargo, si el tipo de los operandos es signed, entonces estos son interpre-
tados como 3 y -8, con lo cual la expresión vale true.

Funciones

Se definen algunas funciones nuevas en el paquete IEEE. numeric_std, entre las


cuales están las siguientes:

- shift_left (a, b), shift_right (a, b), rotate_left (a, b), rotate_right (a, b):
se emplean para realizar las operaciones de desplazamiento y rotación. El
operando a es de tipo unsigned o signed, mientras que bes de tipo natural.
El resultado es del mismo tipo que el operando a.
Se trata de nuevas funciones, no de los operadores de VHDL sobrecargados.
Esta distinción es importante, ya que las herramientas de síntesis soportan
estas funciones de desplazamiento del paquete IEEE. numeric_std, mientras que
no soportan los operadores de desplazamiento de VHDL.

- resize (a, b): se emplea para modificar el tamaño (es decir, el número de bits)
del operando a, que debe ser del tipo unsigned y signed. El operando b es
de tipo natural y representa el nuevo número de bits del dato. El resultado
es del mismo tipo que el operando a.

- std_match(a, b): se emplea para comparar vectores que tienen el valor'-' (don't
care). El operando a debe ser del tipo unsigned, signed std_logic_vector o
std_logic. El operando b debe ser del mismo tipo que a. El resultado es del
tipo boolean.

Veamos a continuación un ejemplo de uso de la función std_match. Se empleará


para definir la señal codigo del codificador 4 a 2 con prioridad diseñado en el Código
VHDL 2.6, 2.9, 2.13 y 2.16. Recuérdese que la tabla de la verdad del circuito es:

159
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

X codigo activo
1 - - -
1 1 1
o1 1 o 1
oo 1 o1 1
oo o 1 oo 1
oo o o oo o

Cabría pensar que la señal codigo puede definirse de la forma siguiente

-- Código correcto pero diseño incorrecto!


codigo <= "11" when x "1---" else
"10" when x "01--" else
"01" when x "001-" else
"00";

El código es sintácticamente correcto. Sin embargo, en el circuito cada bit de


la señal de entrada tendrá un valor ('O' , ' 1 ' , 'Z' , etc), pero nunca valdrá '-' .
Por tanto, las expresiones x=" 1---", x="01--" y x="001-" siempre valdrán false. Por
ejemplo, si el valor de la señal x es "1110", ninguna de las expresiones booleanas es
verdadera, con lo cual se asignará "00" a la señal codigo.

La función std_match permite comparar vectores con bits don't care. En este
caso, la señal codigo podría definirse de la forma siguiente:

-- Diseño correcto
use IEEE.numeric_std.all;

codigo <= "11" when std_match(x, "1---") el se


"10" when std_match(x, "01--") el se
"01" when std_match(x, "001-") el se
"00";

Conversión entre tipos

Hay tres funciones de conversión entre tipos en el paquete IEEE. numeric_std.


Estas son: to_unsigned, to_signed y to_integer. En la Tabla 2.4 se indica qué
función debe emplearse para realizar la conversión entre tipos.

La función to_integer tiene como parámetro un objeto del tipo unsigned o


signed y devuelve un objeto del tipo integer.

160
CONCEPTOS BÁSICOS DE VHDL

Tabla 2.4: Conversión de tipos.

Conversión de: a: Función


std_logic_vector, signed unsigned unsigned(arg)
std_logic_vector, unsig- signed signed(arg)
ned
unsigned, signed std_logic_vector std_logic_vector(arg)
unsigned, signed integer to_integer(arg)
integer, natural unsigned to_unsigned(arg,size)
integer signed to_signed(arg,size)
integer std_logic_vector integer ---+ unsigned/signed ---+
std_logic_vector
std_logic_vector integer std_logic_vector ---+
unsigned/ signed ---+ integer

Las funciones to_unsigned y to_signed convierten un integer en un objeto del


tipo unsigned y signed, respectivamente, con el número de bits especificado. Estas
funciones tienen dos parámetros. El primero es el número del tipo integer que se
desea convertir. El segundo es el número deseado de bits del nuevo tipo de dato.

Los tipos std_logic_vector, unsigned y signed están definidos como un vector


de elementos std_logic. Se trata de tipos de datos muy próximos entre sí, que pueden
convertirse entre sí escribiendo el objeto original entre paréntesis, delante del cual
debe escribirse el nuevo tipo de dato. Este tipo de conversión se denomina casting.
Por ejemplo:

signal u1, u2 unsigned ( 7 downto o ) ;


signal x1, x2 std_logic_vector ( 7 downto o ) ;

u1 <= unsigned( x1 ) ;
x2 <= std_logic_vector( u2 );

El tipo std_logic_vector no es interpretado como un número. Por ello, este tipo


no puede ser convertido directamente a integer o viceversa (véanse las dos últimas
filas de la Tabla 2.4).

A continuación, se muestran algunos ejemplos de asignaciones que pretenden


ilustrar el empleo de señales de distintos tipos de dato. Supóngase que las señales
han sido declaradas de la forma siguiente:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

161
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

signal si, s2, s3, s4, s5, s6 std_logic_vector ( 3 downto O);


signal u1, u2, u3, u4, u5, u6, u7 unsigned ( 3 downto O);
signal sg signed ( 3 downto O);

Las siguientes asignaciones a las señales u3 y u4 son válidas, puesto que el


operador + está sobrecargado para los tipos unsigned y natural:

u3 <= u2 + u1; Bien, ambos operandos unsigned


u4 <= u2 + 1; Bien, operandos unsigned y natural

Por otra parte, las dos asignaciones siguientes producen error:

u5 <= sg; Error


u4 <= 5; Error

Para poder realizar las asignaciones anteriores, es necesario realizar la conversión


entre los tipos:

u5 <= unsigned( sg ); Bien, casting


u4 <= to_unsigned( 5,4 ); Bien, función de conversión

Las operaciones aritméticas no están sobrecargadas para la mezcla entre los tipos
signed y unsigned, por lo tanto, la sentencia siguiente produce error:

u7 <= sg + u1; -- Error, operandos signed y unsigned

Para poder realizar la asignación, es necesario convertir el dato del tipo signed
a unsigned:

u7 <= unsigned( sg ) + u1; -- Bien, casting

La conversión anterior, del tipo signed a unsigned, implica cambiar la inter-


pretación que se hace del vector. Por ejemplo, 1111 es -1 para el tipo signed,
11 11

mientras que es 15 para el tipo unsigned.

Las siguientes dos asignaciones a señales del tipo std_logic_vector son incorrec-
tas:

s3 <= u3; Error


s4 <= 5; Error

Es necesario usar casting y funciones de conversión de tipo para resolver el


problema:

162
CONCEPTOS BÁSICOS DE VHDL

s3 <= std_logic_vector( u3 ); Bien, casting


s4 <= std_logic_vector ( to_unsigned(5,4) ); Bien, func. conversión

No es posible realizar operaciones aritméticas sobre objetos del tipo std_logic_vector.


Así pues, las siguientes sentencias no son válidas:

s5 <= s2 + si; Error, operador + indefinido


s6 <= s2 + 1; Error, operador + indefinido

Para solucionar el problema, es preciso convertir los operandos al tipo unsig-


ned o signed, realizar la suma, y a continuación convertir el resultado al tipo
std_logic_vector.

s5 <= std_logic_vector( unsigned(s2) + unsigned(s1) ); Bien


s6 <= std_logic_vector( unsigned(s2) + 1 ); Bien

2.12.5. Tipos 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 programación, un
string se define simplemente como un vector de caracteres.

2.12.6. Tipos definidos por el usuario

VHDL permite al usuario definir sus propios tipos de datos. A continuación se


explican tres categorías de tipos de datos definidos por el usuario: enteros, tipos
enumerados y tipos vectoriales.

163
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Tipos enteros definidos por el usuario

Puede definirse un tipo de datos especificando un determinado rango de valores


de los números enteros. Por ejemplo:

type miEntero is range -32 to 32;


type palabraMemoria is range O to 1024;

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 (suma,
resta, salto y parar), entonces es posible definir un nuevo tipo (type), llamado, por
ejemplo, opcode_ type, de la manera siguiente:

type opcode_type is (SUMA, RESTA, SALTO, PARAR);

y declarar opcode del tipo opcode_ type.

Este tipo de construcción hace el código VHDL más sencillo de entender. Sin
embargo, esta forma de realizar el modelo no permite especificar explícitamente el
código binario correspondiente a cada uno de los códigos de operación.

U na forma alternativa de programar el ejemplo anterior es definir SUMA, RESTA,


SALTO y PARAR como constantes (constant) de dos bits, y definir opcode como una
señal que sea un vector de dos bits.

Tipos vectoriales definidos por el usuario

Como se ha explicado anteriormente, existen tipos vectoriales predefinidos en


VHDL, y también hay otros tipos vectoriales que están definidos en los paquetes
IEEE. std_logic_1164e IEEE.numeric_std. Estos son: bit_vector, std_logic_vector,
signed y unsigned. El primero es un vector de componentes del tipo bit, mientras
que los tres últimos son vectores de componentes del tipo std_logic. En todos los
casos, se trata de vectores lD, es decir, unidimensionales.

164
CONCEPTOS BÁSICOS DE VHDL

VHDL permite al usuario definir sus propios tipos vectoriales. Por ejemplo,
vectores lD en los cuales los componentes sean a su vez de tipo vectorial lD, por
ejemplo std_logic_vector. Estos vectores unidimensionales, cuyos componentes son
a su vez vectores unidimensionales, se denominan vectores lD x lD.

Pueden definirse tipos vectoriales 2D (es decir, bidimensionales) con componen-


tes, por ejemplo, del tipo std_logic. También pueden definirse tipos vectoriales con
dimensión mayor que dos, si bien generalmente no son sintetizables.

En general, puede declararse un nuevo tipo vectorial empleando la sintaxis mos-


trada a continuación:

type nombre_ tipo is array especificacion_dimension of tipo_dato;

La declaración de señales, variables y constantes de los tipos vectoriales definidos


por el usuario se realiza de la misma manera que con los demás tipos.

Supongamos que se quiere definir un nuevo tipo vectorial lD x lD, que sea un
vector de 4 componentes, donde cada uno de los componentes sea a su vez un vector
de 8 componentes del tipo std_logic. El nuevo tipo, al que se asigna el nombre
regFile_ type, puede declararse de la forma siguiente:

type regFile_type is array (Oto 3) of std_logic_vector(7 downto O);

Puede declararse una constante y una señal de este tipo, a las cuales se asignan
los nombres data y reg_f ile respectivamente, y asignar valor a la constante, de la
forma mostrada a continuación:

constant data : regFile_type


( ( '0', '0', '1', '1', '0', '0', '0', '0' ) ,
( '1' ' '0'' '1', '0'' '1'' '0'' '1'' '1' ) '
( '0'' '1'' '0'' '1'' 'o'' 'o'' '1'' '0' ) '
( '1'' '0'' '1'' '0'' '0'' '1'' '0'' '0' ) ) ;
signal reg_file : regFile_type;

Para referirse a los elementos de los objetos de tipo vectoriallD x lD, se emplean
dos pares de paréntesis. Por ejemplo, reg_file (2) (3).

En el Código VHDL 5.14 se muestra un diseño en el cual se define un tipo


vectorial lD x lD similar al del ejemplo anterior y se declara una señal de ese tipo.

El siguiente ejemplo muestra la declaración de un tipo vectorial bidimensional,


llamado matriz2D, y de una constante y una señal de ese tipo. Obsérvese que la
forma de asignar valor a las constantes de un tipo vectorial lD x lD y de un tipo

165
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2D es la misma. La sintaxis para inicializar las señales y variables es la misma que


la empleada en los ejemplos para asignar valor a las constantes.

type matriz2D is array (O to 3, 7 downto O) of std_logic;


constant data : matriz2D
( ( '0'' '0'' '1'' '1'' '0'' '0'' '0'' '0' ) '
( '1'' '0'' '1'' '0'' '1'' '0'' '1'' '1' ) '
( '0'' '1'' '0'' '1'' '0'' 'o'' '1'' '0' ) '
( '1'' '0'' '1'' '0'' '0'' '1'' 'o'' '0' ) ) ;
signal mem_data : matriz2D;

Para referirse a los elementos de los objetos de tipo vectorial 2D, se emplea un
único par de paréntesis. Por ejemplo, mem_data (2, 3).

2.13. ATRIBUTOS

Puede considerarse que los atributos son propiedades de los tipos de datos. No
todos los atributos de los tipos estándar de datos son soportados para síntesis. En
la Tabla 2.5 se muestran algunos de los atributos que son soportados por la mayoría
de las herramientas de síntesis. Por otra parte, VHDL permite al usuario definir sus
propios atributos.

Por ejemplo, dada la señal

signal d : std_logic_vector( 7 downto O);

los valores de sus atributos son:

d' low=Ü d' high=7 d'left=7 d'right=Ü


d'length=8 d'range=(7 downto O) d' reverse_range=(O to 7)

Asimismo, existen atributos que resultan útiles para programar bancos de prueba
y que, por tanto, no necesitan ser sintetizados. Un atributo particularmente útil es

<tipo>'image(señal)

el cual 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 describir la mayor parte de los diseños
de circuitos digitales y bancos de pruebas. Se irán introduciendo estos atributos en
los casos de estudio explicados en los siguientes temas.

166
CONCEPTOS BÁSICOS DE VHDL

Tabla 2.5: Algunos atributos soportados por la mayoría de las herramientas de síntesis. La
nomenclatura empleada en la tabla se explica a continuación. < tipo > : tipo de dato. < vectorlD > :
tipo vectorial lD. <señal> : señal.

Atributo Significado
<tipo>' Indica que el argumento es del tipo <tipo>.
Por ejemplo, unsigned' ( "00") establece que
"00" se usa como unsigned, en lugar de como
bit_vector o std_logic_vector.
<vector1D>'range Rango de índices de un vector lD
<vector1D>'reverse_range Rango de índices del vector lD, en orden inverso
<vector1D>'length Número de componentes del vector lD
<vector1D>'low Índice más pequeño del vector
<vector1D>'high Índice más grande del vector
<vector1D>'left Índice del componente más a la izquierda
<vector1D>'right Índice del componente más a la derecha
<señal>'stable true mientras no hay cambios en <señal>
<señal>'event true sólo cuando hay un cambio en <señal>

Por ejemplo, en VHDL'87 se emplea

clk'event and ( clk = '1' )

para detectar el flanco de subida de la señal de reloj. Sin embargo, puesto que este
predicado es también cierto cuando la señal el k cambia del valor 'U' (no inicializado)
o del valor 'X' (desconocido forzado) a ' 1' , en VHD L'93 se usa

rising_edge(clk)

para detectar el flanco de subida de la señal clk. Asimismo, se usa

falling_edge(clk)

para detectar el flanco de bajada de la señal clk.

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

167
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

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:

IEEE. std_logic_1164 Incluye la definición de los tipos de datos std_logic y


std_logic_vector, y de las operaciones en las que intervie-
nen estos tipos de datos.
IEEE. numeric_std Incluye la definición de los tipos de datos unsigned y
signed, y de las operaciones más comunes realizadas sobre
estos tipos de datos.
IEEE.math_real Incluye la definición de las operaciones en las que intervienen
números reales (tipo real). Estos son números reales en
coma flotante de 64 bits según el estándar de IEEE.

Así pues, es frecuente incluir, antes de la definición de la entidad de diseño, las


tres sentencias siguientes:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

La primera sentencia indica que va a emplearse la librería de IEEE. Las otras


dos indican que los paquetes IEEE.stcLlogic_ll64 y IEEE.numeric_std deben estar
listos para su uso en el código VHDL que sigue a continuación. Por supuesto, si en
el código no se usan los tipos de datos unsigned y signed, entonces puede omitirse
la tercera sentencia.

168
CONCEPTOS BÁSICOS DE VHDL

Las herramientas de simulación y síntesis con VHDL suelen incluir otras librerías,
que pueden ser examinadas desde la propia herramienta.

Existen librerías y paquetes que son cargados por defecto, con lo cual no necesitan
ser incluidas. Las más notables son las dos siguientes:

work Librería por defecto donde se compilan todos los tipos, las
funciones, entity, architecture, package, etc. definidos
por el usuario.
std Contiene la mayoría de las definiciones y construcciones
estándar soportadas por VHDL.

2.15. 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 al simularlo, siendo ignorada por
las herramientas de síntesis. Su sintaxis es mostrada a continuación, donde assert,
report y severity son palabras reservadas:

assert condición_ booleana report mensaj e_a_mostrar


severity ni vel_severi ty;

Mientras la condición booleana vale true, la sentencia no realiza ninguna acción.


Cuando la condición se hace false, la sentencia muestra el texto mensaj e_a_mostrar
en la consola.

La cláusula severity se usa para indicar qué gravedad tiene la violación de la


condición booleana. Posibles valores de ni vel_severi ty son:

note No es un error.
warning Aviso.
error Error.
failure Error grave que provoca que termine la simulación.

169
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.16. SUBPROGRAMAS

Los subprogramas permiten definir fragmentos de código secuencial, contribu-


yendo a hacer el código VHDL más legible, portable y compacto. Hay dos tipos de
subprogramas: las funciones y los procedimientos.

Lo subprogramas (funciones y procedimientos) pueden ser definidos dentro de


paquetes (package), de modo que sean fácilmente reutilizados en diferentes proyec-
tos, o en el propio código principal del diseño. En este último caso, los subprogramas
deben ser definidos dentro de la sección de declaración de la entity, architecture
o de los bloques process.

2.16.1. Funciones

Una función es una rutina que devuelve un valor. La definición de la función se


especifica, mediante un fragmento de código secuencial, cómo se calcula el valor de
retorno a partir de los valores de los parámetros formal es de la función.

La función puede ser invocada desde sentencias concurrentes y secuenciales. Al


realizar la llamada o invocación a la función, se especifican los parámetros actuales,
que son asociados a los parámetros formales usados en la definición de la función.

En la definición de la función pueden emplearse las sentencias propias del có-


digo secuencial (if, case, for, assert, etc.), salvo la sentencia wait, que no puede
emplearse en la definición de la función. Por otra parte, dentro de una función no
pueden declararse señales o instanciarse componentes. Se emplea la sentencia return
para especificar qué valor devuelve la función. La declaración de la función sigue la
sintaxis siguiente:

function nombre_función lista_param_formales return tipo_dato is


declaracion de variables locales y constantes locales
begin
sentencias secuenciales
end function nombre_función;

donde lista_param_formales especifica los parámetros formales de entrada a la


función, que pueden ser constantes y señales, pero no variables. La función puede
tener un número cualquiera de parámetros formales (inclusive ninguno). La lista
de parámetros formales se escribe entre paréntesis. La sintaxis para declarar un
parámetro formal es

170
CONCEPTOS BÁSICOS DE VHDL

constant nombre_constante : tipo_dato;

si se trata de una constante, donde la palabra reservada constant es opcional, o


bien

signal nombre_señal : tipo_dato;

si se trata de una señal. El tipo del parámetro formal puede ser cualquiera de los
tipos sintetizables, boolean, std_logic, integer, etc.

Cuando se declaran parámetros formales vectoriales o enteros, no debe especi-


ficarse su rango. Por ejemplo, no hay que especificar el range en el caso de los
parámetros integer, ni to / downto para los parámetros std_logic_vector. Esto
facilita la reutilización de la función en diferentes contextos.

La función devuelve un único valor, cuyo tipo debe especificarse al declarar la


función. Por ejemplo, la siguiente función

function f ( c1, c2 integer;


signal s std_logic_vector) return boolean is

end function f;

recibe tres parámetros formales: las constant c1 y c2, de tipo integer, y la signal
s, de tipo std_logic_vector. Obsérvese que no se especifica el rango de valores de
los parámetros enteros, ni tampoco el rango del índice del parámetro vectorial. El
valor que devuelve la función es de tipo boolean.

Para ilustrar las explicaciones anteriores, en el Código VHDL 2.23 se muestra


la declaración de una función que acepta un vector del tipo std_logic_vector y
devuelve el número entero que equivale al vector, interpretando éste como un número
binario sin signo.

171
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Función para conversión de str:Llogic_vector a integer


-- Fichero: conv!nteger. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity conv _int is


port ( y : out integer range O to 15;
a : in std_logic_vector(3 downto o) );
end entity conv _int;
architecture conv _int of conv _int is

function conv_integer (signal vector : std_logic_vector)


return integer is
variable resultado, pot : integer range O to 2**vector' length-1;
begin
pot := 1;
if ( vector(vector'low)='1') then
resultado := 1;
el se
resultado := O;
end if;
for i in (vector'low+1) to (vector'high) loop
pot := pot*2;
if (vector(i)='1') then
resultado := resultado + pot;
end if;
end loop;
return resultado;
end function conv _integer;

begin
y < = conv _integer(a);
end architecture conv _int;

Código VHDL 2.23: La función conv_integer convierte un parámetro del tipo std_logic_vector
a un entero.

2.16.2. Procedimientos

El procedimiento es más versátil que la función, ya que puede devolver más


de un valor. Los procedimientos pueden declararse en la parte declarativa de las
architecture y de los bloques process, y también, como se explicará más adelante,
dentro de paquetes (package). La sintaxis para la declaración de un procedimiento
es la siguiente:

procedure nombre_procedimiento lista_param_formales is


declaracion de variables locales y constantes locales
begin
sentencias secuenciales
end procedure nombre_procedimiento;

172
CONCEPTOS BÁSICOS DE VHDL

En este caso, en la lista de parámetros formales no sólo se especifican los paráme-


tros formales de entrada, sino también los parámetros formales de salida. Es decir,
aquellos que son calculados en el procedimiento.

Un procedimiento puede tener un número cualquiera de parámetros formales,


cada uno de los cuales debe tener un modo: in, out o inout. Los parámetros formales
de un procedimiento pueden ser constantes, variables y señales. La sintaxis para
declarar cada parámetro formal en la lista de parámetros, según se trate de una
constante, una señal o una variable, es la siguiente:

constant nombre constante modo tipo_dato;


signal nombre señal modo tipo_dato;
variable nombre variable modo tipo_dato;

El modo del parámetro formal condiciona su uso en el procedimiento:

- Puede modificarse en el procedimiento el valor de los parámetros formales


declarados como out o inout, pero no el valor de los parámetros formales
declarados como in.

- Puede leerse en el procedimiento el valor de los parámetros formales declarados


como in o inout, pero no puede leerse dentro del procedimiento el valor de
los parámetros formales declarados como out.

- Si no se especifica la dirección de un parámetro formal del procedimiento, se


asume por defecto que es in.

- Un parámetro formal out o inout es por defecto una variable, a menos que se
indique explícitamente que es una señal.

- Se considera que un parámetro in es una constante dentro del bloque del


procedimiento. No obstante, si el parámetro in es una señal, entonces los
cambios que se produzcan en la señal fuera del procedimiento se producirán
igualmente en el valor de la señal dentro del procedimiento.

Por ejemplo, el procedimiento declarado a continuación

procedure proc ( a in std_logic;


signal b, e in std_logic;
signal x out std_logic_vector(7 downto O);
signal y in out integer range O to 99 ) is

end procedure proc;

173
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

tiene tres entradas: la constante de tipo std_logic a, y las señales del tipo std_logic b
y c. Se ha omitido la palabra reservada constant para el primer parámetro formal de
entrada, ya que por defecto se sobreentiende que es una constante. El procedimiento
tiene dos parámetros formales de salida: las señales x e y. Esta última tiene el modo
inout.

La invocación del procedimiento es una sentencia por sí misma, que puede formar
parte de código concurrente o secuencial.

- Cuando el procedimiento es invocado fuera de un bloque de código secuencial,


entonces la invocación es una sentencia concurrente. Esta sentencia concurrente
es equivalente a un bloque process que contuviera la llamada al procedimiento,
seguida de una sentencia wait on cuya lista de sensibilidad contuviera todos
los parámetros del procedimiento que son señales con modo in e in out. Los
procedimientos invocados en sentencias concurrentes no pueden tener paráme-
tros formales variable.

- ·Cuando el procedimiento es invocado en un fragmento de código secuencial, por


ejemplo, dentro de un bloque process, entonces no existe un wait implícito
al final del procedimiento. Esto significa que, una vez ejecutada la última
sentencia del procedimiento, se ejecuta la sentencia secuencial siguiente a la
de invocación del procedimiento.

Los parámetros actuales de la invocación al procedimiento se hacen corresponden


con los parámetros formales del procedimiento, bien por asociación posicional o bien
mediante la sintaxis

param_formal => param_actual

Al igual que se indicó en el caso de las funciones, cuando se declaran parámetros


formales vectoriales o enteros, no debe especificarse su rango. Su rango será el
de los parámetros actuales con los cuales se asocian al realizar la invocación al
procedimiento.

En el Código VHDL 2.24 se muestra la definición de un proc~dimiento que,


dados dos números enteros, los devuelve ordenados. Los parámetros actuales de la
invocación al procedimiento (d1_in, d2_in, min_out, max_out) se hacen corresponder
con los parámetros formales de la declaración del procedimiento (in1, in2, min, max)
mediante asociación posicional.

174
CONCEPTOS BÁSICOS DE VHDL

-- Procedimiento para cálculo del mínimo y el máximo


-- Fichero: minMax.vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity minMax is
generic ( 1 imite : integer : = 255 ) ;
port ( min_out, max_out : out integer range O to limite;
ena : in std_logic;
d1_in, d2_in : in integer range O to limite );
end entity minMax;
architecture minMax of minMax is
procedure ordena ( signal in1, in2 : in integer range O to limite;
signal min, max : out integer range O to limite ) is
begin
if (in1>in2) then
max <= in1;
min <= in2;
else
max <= in2;
min <= in1;
end if;
end procedure ordena;

begin
process (e na)
begin
if (e na= ' 1 ' ) then
ordena(d1_in, d2_in, min_out, max_out);
end if;
end process;
end architecture minMax;

Código VHDL 2.24: Procedimiento que devuelve dos parámetros de entrada ordenados.

2.16.3. Diferencias entre funciones y procedimientos

Una función tiene cero o más parámetros formales de entrada, y devuelve un


único valor. Los parámetros de entrada sólo pueden ser constant (por defecto)
o signal. No se permiten parámetros variable. Los parámetros formales de
las funciones siempre tienen el modo in, por ello no debe especificar su modo.

Un procedimiento puede tener cualquier número de parámetros in, out e


inout, los cuales pueden ser constant, signal y variable (sólo cuando se
llama al procedimiento desde código secuencial). Los parámetros de entrada
(modo in) se consideran por defecto constant, mientras que los de salida
(modos out e inout) se consideran por defecto variable.

175
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

- U na función es invocada como parte de una sentencia, mientras que la invo-


cación a un procedimiento es una sentencia en sí misma.

- En los procedimientos puede usarse la sentencia wait, en las funciones no. En


todo caso, la sentencia wait no es sintetizable.

- La declaración ·de funciones y procedimientos puede realizarse o bien dentro


de packages, con lo cual se facilita su reutilización desde diferentes diseños, o
bien en el código principal del diseño (en la parte declarativa de la entity, de
la architecture o de un bloque process).

El caso práctico descrito en la Sección 4.5 ilustra el empleo de procedimientos y


funciones.

2.17. PAQUETES

Como se ha explicado anteriormente, los fragmentos de código secuencial pueden


encapsularse en subprogramas, es decir, en funciones y procedimientos. Cuando los
subprogramas deban ser usados desde varios diseños, la reutilización se facilita si
los subprogramas son definidos dentro de paquetes (package), que a su vez son
compilados dentro de una librería (por defecto en la librería work). Además de
subprogramas, en un paquete pueden declararse también componentes, tipos de
datos y constantes.

La sintaxis para la declaración y definición de un paquete consta de dos partes:


la declaración del paquete (package) y el cuerpo del paquete (package body). El
nombre asignado a ambas partes (nombre_paquete) debe ser el mismo.

package nombre_paquete is
declaraciones
end package nombre_paquete;

package body nombre_paquete is


descripción de funciones y procedimientos
end package body nombre_paquete;

l. La primera parte, es decir, la declaración del paquete (package), es obligatoria


y contiene todas las declaraciones de componentes, tipos y subprogramas.

2. La segunda parte, esto es, el cuerpo del paquete (package body), es necesaria
sólo cuando se han declarado subprogramas (procedimientos o funciones) en

176
CONCEPTOS BÁSICOS DE VHDL

la primera parte. En este caso, en la segunda parte se incluye la descripción


del cuerpo de los subprogramas.

Por ejemplo, a continuación se muestra la declaración de un paquete, que contiene


la declaración de un tipo de dato y una constante. En este caso, la parte package
body no es necesaria.

library IEEE;
use IEEE.std_logic_1164.all;

package ejemplo! is
type estado is (st1, st2, st3, st4);
constant datoinicial : std_logic_vector(7 downto O) "11111111";
end package ejemplo!;

Si este package se compila en la librería work, para poder usar en un diseño el


tipo de dato y la constante que se declaran en este package, es necesario incluir en
el diseño la sentencia:

use work.ejemplo1.all;

A continuación, se muestra otro ejemplo. La función conv _integer, definida en


Código VHDL 2.23, que convierte un parámetro del tipo std_logic_vector a un
entero, puede declararse dentro de un package, como se muestra en el Código
VHDL 2.25 y ser usada como se muestra en Código VHDL 2.26.

177
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Package en el cual se define una función


-- Fichero: pack1 .vhd
library IEEE;
use IEEE. std_logic_1164. all;

package pack1 is
function conv_integer (signal vector : std_logic_vector)
return integer;
end package pack1;

package body pack1 is


function conv _integer ( signal vector : std_logic_vector)
return integer is
variable resultado, pot : integer range O to 2**vector' length-1;
begin
pot := 1;
if ( vector( vector' low)=' 1 ') then
resultado := 1;
el se
resultado := O;
end if;
for i in (vector'low+1) to (vector'high) loop
pot := pot*2;
if (vector(i)=' 1 ') then
resultado := resultado + pot;
end if;
end loop;
return resultado;
end function conv _integer;

end package body pack1;

Código VHDL 2.25: Definición de una función en un package.

-- Conversión de strLlogic_vector a integer usando


-- una función definida en un package
--Fichero: conv!ntegerPackl.vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work. pack1. all;
entity conv_int1 is
port ( y : out integer range O to 15;
a : in std_logic_vector ( 3 downto O) ) ;
end entity conv_int1;
architecture conv _int 1 of conv _int 1 is
begin
y <= conv_integer(a);
end architecture conv_int1;

Código VHDL 2.26: Uso de una función definida en un package.

178
CONCEPTOS BÁSICOS DE VHDL

2.18. LECTURAS RECOMENDADAS

Existe gran cantidad de bibliografía en la cual se describen las capacidades y uso


de VHDL'93. Una buena referencia en castellano es (Pardo & Boluda 2004). En los
Capítulos 3, 4 y 5 de (Chu 2006) se describen aquellas capacidades fundamentales
de VHDL que son relevantes para síntesis. Los Capítulos 1 a 8 de (Perry 2002)
constituyen una exposición paso a paso, muy didáctica, de los conceptos básicos de
VHDL. Los Capítulos 3 y 4 de (Pedroni 2004) contiene muchos ejemplos de definición
de nuevos tipos, conversión entre tipos, operaciones y atributos. El Capítulo 3 de
(Chang 1997) contiene una buena discusión sobre el concepto de señal, las asigna-
ciones concurrentes y secuenciales, y el retardo <5. El Capítulo 9 de (Cohen 1995) es
una buena referencia sobre la unidad de diseño configuration. En particular, sobre
cómo especificar en la configuration qué architecture se asocia a la entity de un
componente (recuérdese que esto es necesario sólo cuando hay varias architecture
asociadas a la entity).

179
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2.19. EJERCICIOS DE AUTOCOMPROBACIÓN

Ejercicio 2.1

Escriba el código VHDL que describe el comportamiento del circuito de la Figu-


ra 2.16, usando para ello sentencias de asignación concurrente y operadores lógicos.

x OR2_1
e=:>-·-·-- : r····························· ¡

:~:;;~_ xory
OR2_2
,. ............................ NOT
z 1 xoryorz
>D--!--_..r·~· ::::::: ·:~·
..~. ~. -=.~-. ..
-r-
1 - - - - - - - - . . - , '
>--i--------+---1

: .............................. ;
: ......................;

Figura 2.16: Circuito correspondiente a los Ejercicios 2.1 y 2.2.

A continuación, programe el código de un banco de pruebas tal que testee todas


las posibles entradas al circuito y simúlelo. Compruebe el correcto funcionamiento
del circuito observando visualmente sus señales de salida.

Ejercicio 2.2

Realice nuevamente el diseño del circuito mostrado en la Figura 2.16, pero esta
vez describa la estructura del circuito, usando como componentes dos puertas OR
de dos entradas y una puerta inversora.

Simule este diseño empleando el banco de pruebas que programó al resolver el


Ejercicio 2.1. Compruebe el correcto funcionamiento del circuito observando visual-
mente sus señales de salida.

Ejercicio 2.3

Dado el Código VHDL 2.27, indique cuál es el valor de las señales x1, x2, x3, x4,
x5, x6, x7 y x8 una vez se han realizado las operaciones de asignación.

180
CONCEPTOS BÁSICOS DE VHDL

library IEEE;
use IEEE. std_logic_1164. all;

entity codigo is
end entity codigo;
architecture codigo of codigo is

signal a : std_logic : = ' 1 ' ;


signal b : std_logic_vector ( 3 downto o) := 11 1100 11
signal e : std_logic_vector ( 3 downto O) : = 11 00 1O11
signal d : bit_vector( 3 downto o) := 11 1100 11 ;
signal x1: std_logic_vector( 4 downto O);
signal x2: std_logic_vector(7 downto O);
signal x3: std_logic_vector(3 downto O);
signal x4: std_logic;
signal x5: bit_vector(3 downto O);
signal x6: bit_vector(3 downto O);
signal x7: std_logic_vector ( 7 downto O);
signal x8: std_logic_vector (O to 7);

begin

x1 <=a & e;
x2 <=e & b;
x3 <= b xor e;
x4 <= a and b(3);
x5 <= d sll 2;
x6 <= d rol 2;
x7 <= (5=> '0', others=>'1');
x8 <= (5=> '0', others=>'1');
end architecture codigo;

Código VHDL 2.27: Diseño correspondiente al Ejercicio 2.3.

Ejercicio 2.4

VHDL permite al usuario definir nuevos tipos de datos. En particular, la defi-


nición de nuevos tipos de datos enteros, enumerados y compuestos puede realizarse
siguiendo la sintaxis indicada a continuación.

Tipo de dato entero:


type identificador is range rango_del_tipo;

Tipo de dato enumerado:


type identificador is (nombre1, nombre2, ... , nombreN);

Tipo de datos compuesto:


type identificador is array indice_elementos of tipo_elementos

181
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

El objetivo de este ejercicio es obtener el valor de diferentes atributos para los


cuatro tipos de datos siguientes:

type tipo1 is range O to 10;


type tipo2 is range 21 downto 11;
type tipo3 is (s1, s2, s3, s4);
type tipo4 is array (1 to 4, 5 downto O) of bit;

Para estos cuatro tipos de datos, indique el valor de los atributos señalados en
la tabla siguiente:

Atributo Valor Atributo Valor


tipol 'left tipol 'right
tipol'high tipol'low
tipo2'left tipo2'right
tipo2'high tipo2'low
tipo3'left tipo3'right
tipo3'high tipo3'low
tipo4'left(l) tipo4'right(2)
tipo4'high(l) tipo4'low(2)
tipo4'range(l) ti po4 'reverse_r ange (2)
tipo4'length(l) tipo4'length(2)

Ejercicio 2.5

Escriba el código VHDL que describe el comportamiento del circuito de la Fi-


gura 2.17 usando sentencias de asignación concurrente y operadores lógicos. Tenga
en cuenta que cada inversor tiene un retardo de 1 ns. Este circuito, denominado
"one-sho-f', tiene como salida un pulso de corta duración cuando la señal de entrada
pasa de valer 'O' a valer '1' .

..... ~... . . . . . . . . . . . . . . . !"""~'~'~'~""''"'"! y


.........................................

.~>--- ~-r=-no-t1 ~.~


. · ? ~ ~ m~
,

l .........................~.

--not2_l_
'·....·.·.-
. ........ . .-....·.·.·.·...[.·'
~~
.. m ........ ..... m,
·.·.r.---i-g:u
.............-----;-
.......... -+----ll

.... :_ ____..·___,
·.·.·. ·.·.t>o.·.·.
·.·..... ·.·.·.·.·.....__,
.

l.. . . . . . . . . . J ~
1ns 1ns 1ns
Figura 2.17: Circuito "one-shof', correspondiente al Ejercicio 2.5.

182
CONCEPTOS BÁSICOS DE VHDL

A continuación, programe el código de un banco de pruebas que testee todas las


posibles entradas al circuito y simúlelo. Compruebe el correcto funcionamiento del
circuito, observando visualmente sus señales de salida.

Ejercicio 2.6

Diseñe un decodificador 2:4 con entrada enable, como el mostrado en la Figu-


ra 2.18. La architecture debe describir el comportamiento del circuito, empleando
para ello una única sentencia if dentro de un bloque process.

en il io d3 d2 dl do
do ---+
o o o o o
---+ io
---+ il dl ---+ o o o o o
d2 ---+ o 1 o o 1 o
en o o 1 o o
d3 ---+
o o o
t

Figura 2.18: Decodificador 2:4 con entrada enable.

A continuación, programe un banco de pruebas para el decodificador, que testee


todas las posibles entradas al circuito, y simúlelo. Compruebe el correcto funciona-
miento del circuito observando visualmente sus señales de salida.

Ejercicio 2. 7

Considere el siguiente fragmento de código VHDL:

signal xO, x1, y std_logic;

y <= '0' when xO x1 else


'1';

Dibuje el diagrama conceptual de esta sentencia de asignación y, a continuación,


el correspondiente diagrama al nivel de puertas lógicas.

183
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 2.8

Dibuje el diagrama conceptual correspondiente al fragmento de código VHDL


mostrado a continuación. A continuación, dibuje el diagrama al nivel de puertas
lógicas.

signal x std_logic_vector (2 downto 1);


signal y std_logic_vector (1 downto O);

y <= "10" when x(2) '1' else


"01" when x(1) '1' else
"00";

Ejercicio 2.9

Dibuje el diagrama conceptual correspondiente al fragmento de código VHDL


mostrado a continuación.

signal a, b, r unsigned (7 downto O);


signal x, y unsigned (3 downto O);

r <= a+b when x+y>1 el se


a-b-1 when x>y and y!=O el se
a+1;

Ejercicio 2.10

Dibuje el diagrama conceptual correspondiente al fragmento de código VHDL


mostrado a continuación.

signal s : std_logic_vector (1 downto O);

with s select
x <=(a and b) when "11'',

184
CONCEPTOS BÁSICOS DE VHDL

(a or b) when "01" 1 "10",


'0' when others;

Ejercicio 2.11

Convierta la siguiente sentencia de asignación concurrente de selección a una


sentencia de asignación concurrente condicional.

with sel select


sig <= valor_expr_O when cO,
valor_expr_1 when c1 1 c3 1 c5,
valor_expr_2 when c2 1 c4,
valor_expr_n when others;

Ejercicio 2.12

Convierta la siguiente sentencia de asignac1on concurrente condicional a una


sentencia de asignación concurrente de selección, definiendo para ello las señales
auxiliares que necesite.

sig <= valor_expr_O when bool_expr_O el se


valor_expr_1 when bool _expr_1 el se
valor_expr_2 when bool_expr_2 el se
valor_expr_n;

Ejercicio 2.13

Dibuje el diagrama conceptual correspondiente a la sentencia if siguiente:

if boolean_expr then
a <= valor_expr_a_1;
b <= valor_expr_b_1;
el se
a <= valor_expr_a_2;
b <= valor_expr_b_2;
end if;

185
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 2.14

Dibuje el diagrama conceptual correspondiente a las sentencias if anidadas si-


guientes:

if boolean_expr_1 then
if boolean_expr_2 then
a <= valor_expr_a_1;
el se
a <= valor_expr_a_2;
end if;
el se
if boolean_expr_3 then
a <= valor_expr_a_3;
el se
a <= valor_expr_a_4;
end if;
end if;

Ejercicio 2.15

Dibuje el diagrama conceptual correspondiente a la sentencia case siguiente,


suponiendo que expr_case tiene cinco posibles valores: cO, c1, c2, c3 y c4.

case expr_case is
when cO =>
a <= valor_expr_a_O;
b <= valor_expr_b_O;
when c1 =>
a<= valor_expr_a_1;
b <= valor_expr_b_1;
when others =>
a <= valor_expr_a_n;
b <= valor_expr_b_n;
end case;
CONCEPTOS BÁSICOS DE VHDL

2.20. SOLUCIONES DE LOS EJERCICIOS

Solución al Ejercicio 2.1

El diseño del circuito mostrado en la Figura 2.16, realizado usando sentencias


de asignación concurrente y operadores lógicos, y el código del banco de pruebas, se
muestran en el Código VHDL 2.28.

El banco de pruebas mostrado en el Código VHDL 2.28 consta de una entity y


una architecture. Como el banco de pruebas no tiene entradas ni salidas, la entity
del banco de pruebas no tiene ningún puerto.

La architecture del banco de pruebas consta de dos sentencias concurrentes: la


instanciación del componente a testear y un bloques process.

Al bloque process se le ha asignado el nombre gen_ ve e_ test. En este bloque se


generan los vectores de test y se introducen como entradas de la UUT. La sentencia
wait se emplea para esperar durante un número determinado de unidades de tiempo.
En el código del banco de pruebas, se emplea

wait for 100 ns;

para esperar hasta que el UUT pueda producir las salidas correspondientes a las
entradas aplicadas. La sentencia wait situada al final del bloque process, 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".
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Library IEEE;
use IEEE. std_logic_1164. all;

entity puerta_nor3 is
port( f : out std_logic;
x, y, z : in stdJogic);
end entity puerta_nor3;
architecture fluj o_de_datos of puerta_nor3 is
signal xory, xoryorz: std_logic;
begin
xory < = x or y; -- Tres asignaciones concurrentes
xoryorz < = xory or z;
f <= not xoryorz;
end architecture fluj o_de_datos;

-- Banco de pruebas
library IEEE;
use IEEE. std_logic_1164. all;

entity bp_puerta_nor3 is
end entity bp_puerta_nor3;

architecture bp_puerta_nor3 of bp_puerta_nor3 is


signal f : std_logic; -- Conectar salida UUT
signal x, y, z : std_logic; -- Con ectar entradas UUT
component puerta_nor3 is
port ( f : out std_logic;
x, y, z : in std_logic);
end component puerta_nor3;
begin
-- Instanciar y con ectar UUT
uut : component puerta_nor3 port map
( f = > f, x = > x, y = > y, z = > z);
gen_ ve e_ test : process
begin
x < = '0'; y < = '0'; z < = '0'; wait for 100 ns;
x < ='O'; y < = 'O';z < = '1';waitfor 100 ns;
x < ='O'; y < = '1';z < = 'O';waitfor 100 ns;
x < ='O'; y < = '1';z < = '1';waitfor 100 ns;
x < = '1'; y < = '0'; z < = '0'; wait for 100 ns;
x < = '1'; y < = '0'; z < = '1'; wait for 100 ns;
x < = '1'; y < = '1'; z < = '0'; wait for 100 ns;
X < = '1'; y < = '1'; Z < = '1';
wait; -- Final de la simulación
end process gen_ ve e_ test;
end architecture bp_puerta_nor3;

Código VHDL 2 .28: Diseño y banco de pruebas correspondientes al Ejercicio 2.1.

188
CONCEPTOS BÁSICOS DE VHDL

Solución al Ejercicio 2.2

El diseño del circuito mostrado en la Figura 2.16, realizado describiendo su


estructura de puertas lógicas, se muestra en Código VHDL 2.29. Para facilitar la
interpretación del código, el circuito de la Figura 2.16 se muestra de nuevo en la
Figura 2.19.

x OR2_1

··~·~·~~~······ xory
OR2_2
NOT
xoryorz r······················:
...
z
:
.. ~:.~.·.-:::.~-
....-t-
_j - - - - - - - - - t - - : > ' : .......... ............;
... J

Figura 2.19: Circuito correspondiente a los Ejercicios 2.1 y 2.2.

library IEEE;
use IEEE. std_logic_1164. all;
entity puerta_nor3 is
port( f : out std_logic;
x, y, z : in std_logic);
end entity puerta_nor3;
architecture estructura of puerta_nor3 is
component or2 is
port ( y : out std_logic;
x1, x2 : in std_logic);
end component or2;
component not 1 is
port ( y : out std_logic;
x : in std_logic);
end component not1;
signal xory, xoryorz: std_logic;
begin
or2_1 : or2 port map ( y => xory, x1 = > x, x2 = > y);
or2_2 : or2 port map ( y = > xoryorz, x1 = > xory, x2 = > z);
Inv_1 : not1 port map ( y => f, x = > xoryorz);
end architecture estructura;

Código VHDL 2.29: Diseño correspondiente al Ejercicio 2.2.

189
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 2.3

En la tabla mostrada a continuación se indican los valores de las señales x1, x2,
x3, x4, x5, x6, x7 y x8.

Señal Valor
x1 10010
x2 00101100
x3 1110
x4 1
x5 0000
x6 0011
x7 11011111
x8 11111011

Obsérvese que, aunque se ha realizado la misma operación de asignación sobre


las señales x7 y x8, el valor de estas dos señales es distinto. Ello es debido a cómo
se ha especificado el rango de estas dos señales.

El rango de la señal x7 se ha especificado del siguiente modo: (7 downto 0). El


primer número del rango (7) indica el índice del bit más significativo del vector (el
situado más a la izquierda) y el segundo número del rango (O) indica el índice del
bit menos significativo del vector (el situado más a la derecha).

Por otro lado, el rango de la señal x8 se ha especificado del siguiente modo: (O


to 7). El primer número del rango (O) indica el índice del bit más significativo del
vector (el situado más a la izquierda), y el segundo número del rango (7) indica el
índice del bit menos significativo del vector (el situado más a la derecha).

190
CONCEPTOS BÁSICOS DE VHDL

Solución al Ejercicio 2.4

En la siguiente tabla se muestran los valores de los atributos.

Atributo Valor Atributo Valor


tipo1 'left o tipo1 'right 10
tipo1'high 10 tipo1'low o
tipo2'left 21 tipo2'right 11
tipo2'high 21 tipo2'low 11
tipo3'left s1 tipo3'right s4
tipo3'high s4 tipo3'low s1
tipo4'left(1) 1 tipo4'right(2) o
tipo4'high(1) 4 tipo4'low(2) o
tipo4'range(1) 1 to 4 tipo4'reverse_range(2) Oto 5
tipo4'length(1) 4 tipo4'length(2) 6

Solución al Ejercicio 2.5

El diseño del circuito "one-shof', realizado usando sentencias de asignación con-


currente y operadores lógicos, y el banco de pruebas se muestran respectivamente
en el Código VHDL 2.30 y 2.31 .

library IEEE;
use IEEE. std_logic_1164. all;
entity oneShot is
port ( y : out std_logic;
x : in std_logic);
end oneShot;
architecture oneShot of oneShot is
signal x1, x2, x3 : std_logic;
begin
x1 <= not x after 1ns; --Salida p'uer-ta notl
x2 <= not x1 after 1ns; --Salida puer-ta not2
x3 <= not x2 after 1ns; --Salida pueda not3
y <= x and x3;
end architecture oneShot;

Código VHDL 2.30: Diseño del circuito "one-shof'.

191
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas
library IEEE;
use IEEE. std_logic_1164. all;
entity bp_oneShot is
end entity bp_oneShot;
architecture bp_oneShot of bp_oneShot is
signal y : std_logic; -- Conectar salida UUT
signal x : std_logic; -- Conectar entradas UUT
component oneShot is
port (y : out std_logic;
x : in std_logic ) ;
end component oneShot;
begin
-- Instanciar y conectar UUT
uut : component oneShot port map
( y => y, x = > x);
x <= ' O' ,
' 1 ' after 5 ns,
'O' after 20 ns, '1' after 30 ns,
'O' after 35 ns;
end architecture bp_oneShot;

Código VHDL 2.31: Banco de pruebas del circuito "one-shof'.

Solución al Ejercicio 2.6

El diseño del decodificador y su banco de pruebas se muestran respectivamente


en el Código VHDL 2.32 y 2.33.

Obsérvese que en el código del banco de pruebas, la variable temp 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. La variable temp se ha declarado de
tipo unsigned. 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 (O) indica el índice del bit menos significativo del
vector. Se ha empleado las función de conversión de tipo TO_UNSIGNED, que está
definida en el package IEEE.numeric_std, para convertir el índice del bucle i en
una variable de tipo unsigned de 3 bits de longitud.

192
CONCEPTOS BÁSICOS DE VHDL

-- Decodificador 2:4 con entmda enable


library IEEE;
use IEEE. std_logic_ii64. all;
entity Dcd2x4 is
port ( d3, d2, di, dO : out std_logic;
ii, iO : in std_logic;
en : in std_logic ) ;
end entity Dcd2x4;
architecture Dcd2x4 of Dcd2x4 is
begin
process (en, ii, iO) is
begin
if ( en = ' O ' ) then
d3 <= '0'; d2 <= '0'; di <= '0'; dO <= '0';
elsif ( ii = '0' and iO = '0' ) then
d3 < = 'o' ; d2 < = 'o' ; di <= '0'; dO <= 'i';
elsif ( i i = ' O' and i O = ' i ' ) then
d3 < = 'o' ; d2 < = 'o' ; di <= 'i'; dO <= '0';
elsif ( i i = 'i ' and i O = ' O' ) then
d3 < = 'o' ; d2 < = ' i ' ; di <= '0'; dO <= '0';
elsif ( i i = ' i ' and i O = ' i ' ) then
d3 < = ' i ' ; d2 < = 'o' ; di <= '0'; dO <= '0';
end if;
end process;
end architecture Dcd2x4;

Código VHDL 2.32: Diseño de un decodificador 2:4 con entrada enable.

193
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del decodificador 4:2


library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity bp_Dcd2x4 is
constant DELA Y : time := 10 ns; -- Retardo usado en el test
end entity bp_Dcd2x4;

architecture bp_Dcd2x4 of bp_Dcd2x4 is


signal d3, d2, d1, dO : std_logic;
signal i1, iO, en : std_logic;

component Dcd2x4 is
port ( d3, d2, d1, dO : out std_logic;
i1, iO : in std_logic;
en : in std_logic ) ;
end component Dcd2x4;

begin
UUT : component Dcd2x4 port map
(d3, d2, d1, dO, i1, iO, en);

vec_ test : process is


variable temp : unsigned (2 downto O);
begin
report "Comienza la simulación";
-- Generar todos los posibles valores de entrada
for i in O to 7 loop
temp := TO_UNSIGNED(i,3);
en <= std_logic(temp(2));
i1 <= std_logic(temp(1));
iO <= std_logic(temp(O));
wait for DELAY;
end loop;

report "Simulación finalizada";


wait; -- Final de la simulación
end process vec_test;
end architecture bp_Dcd2x4;

Código VHDL 2.33: Banco de pruebas de un decodificador 2:4 con entrada enable.

194
CONCEPTOS BÁSICOS DE VHDL

Solución al Ejercicio 2. 7

El fragmento de código VHDL

signal xO, x1, y std_logic;

y <= '0' when xO x1 else


'1';

describe un circuito comparador de 1 bit. El diagrama conceptual correspondiente


a este fragmento de código se muestra en la Figura 2.20a .

. . .0. . . ....... . . .... .... .¡


o
1 . . J ... . . . . ... .... . . . . . .¡
xO
xl

a) b)

Figura 2.20: Comparador de 1 bit: a) diagrama conceptual; y b) diagrama al nivel de puertas


lógicas.

Obsérvese que los valores booleanos true y false, resultado de la comparación


xO = x1, se hacen corresponder en el circuito físico con los valores 1 y O lógico,
respectivamente. La función lógica que describe el comparador x 0 = x 1 puede
obtenerse a partir de la tabla de la verdad del circuito:

xo Xl XQ = X1
o o 1
o 1 o
1 o o
1 1 1

La función lógica del comparador es: x 0 ' ·x 1'+xo·x 1 , o equivalentemente: (x 0 EBx 1 )'.
Conectando la salida de este circ~ito comparador (puerta XNOR) a la entrada de
selección del MUX 2:1, se obtiene el circuito mostrado en la Figura 2.20b.

195
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 2.8

En la Figura 2.21 se muestra el diagrama conceptual correspondiente al fragmento


de código VHDL dado en el enunciado del ejercicio. En la Figura 2.22 se muestra la
implementación al nivel de puertas lógicas.

signal x std_logic_vector (2 downto 1);


signal y std_logic_vector (1 downto O);

y <= "10" when x(2) '1' else


"01" when x(1) '1' else
"00";

10
o
o
01
o
00

x(1)

x(2)
o
x(1)

x(2)

a) b)

Figura 2.21: Diagrama conceptual: a) empleando buses; y b) bit a bit .


.................................
. ...1................................¡ ''
: ''
:
........................... ......... ,.,j

. . .0. ................... ...........¡


........................................i

. . .0. . . . . . . . . . . . . . . . . ;

........................................\
. . . t . . ............. .. . . . .i

. . .0................ ........ ......;

. . xC2.L. . .. . . . . . . i

Figura 2.22: Diagrama al nivel de puertas lógicas.

196
CONCEPTOS BÁSICOS DE VHDL

Solución al Ejercicio 2.9

En la Figura 2.23 se muestra el diagrama conceptual correspondiente al fragmento


de código VHDL dado en el enunciado:

signal a, b, r unsigned (7 downto O);


signal x, y unsigned (3 downto O);

r <= a+b when x+y>1 el se


a-b-1 when x>y and y!=O el se
a+1;

a
b

o
x+y>l

Figura 2.23: Diagrama conceptual.

Reemplazando cada bloque aritmético y lógico por su equivalente al nivel de


puertas lógicas, se obtiene la descripción del circuito completo al nivel de puertas
lógicas.

197
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 2.10

En la Figura 2.24 se muestra el diagrama conceptual correspondiente al fragmento


de código VHDL dado en el enunciado:

signal s : std_logic_vector (1 downto O);

with s select
x <= (a and b) when "11",
(a or b) when "01" 1 "10",
'0' when others;

Figura 2.24: Diagrama conceptual.

Solución al Ejercicio 2.11

La sentencia de asignación concurrente de selección dada en el enunciado:

with sel select


sig <= valor_expr_O when cü,
valor_expr_1 when c1 1 c3 1 c5,
valor_expr_2 when c2 1 c4,
valor_expr_n when others;

es equivalente a la siguiente sentencia de asignación concurrente condicional:

sig <= valor_expr_O when (sel=cü) el se


valor_expr_ 1 when (sel=c1) or (sel=c3) or (sel=c5) el se
valor_expr_2 when (sel=c2) or (sel=c4) el se
valor_expr_n;

198
CONCEPTOS BÁSICOS DE VHDL

Solución al Ejercicio 2.12

La sentencia de asignación concurrente condicional dada en el enunciado

sig <= valor_expr_O when bool_expr_O else


valor_expr_1 when bool_expr_1 else
valor_expr_2 when bool_expr_2 else
valor_expr_n;

es equivalente a las siguientes sentencias concurrentes:

sel(2) <= '1' when bool_expr_O el se '0';


sel(1) <= '1' when bool_expr_ 1 el se '0';
sel(O) <= '1' when bool_expr_2 el se '0';
with sel select
sig <= valor_expr_O when "100" 1 "101" "110" 1 "111",
valor_expr_1 when "010" 1 "011",
valor_expr_2 when "001",
valor_expr_n when others;

Solución al Ejercicio 2.13

En la Figura 2.25 se muestra la sentencia if dada en el enunciado, así como su


diagrama conceptual.

valor_expr_a_l
a
if boolean_expr then
a<= valor_expr_a_l; valor_expr_a_2
b <= valor_expr_b_l;
else
valor_expr_b_1 ----+---t
a<= valor_expr_a_2;
b <= valor_expr_b_2;
end if; valor_expr_b_ 2 ----+---t

boolean_expr - - - o - - - . . . . ¡

Figura 2.25: Sentencia if y su diagrama conceptual.

199
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 2.14

En la Figura 2. 26 se muestra la sentencia if y su diagrama conceptual.

if boolean_expr_1 then
if boolean_expr_2 then valor_expr_a_1
a<= valor_expr_a_1;
else valor_expr_a_2
a<= valor_expr_a_2;
end if; boolean_expr_2
el se valor_ expr_a_3
ifboolean_expr_3 then
a<= valor_expr_a_3;
el se valor_expr_a_4
a<= valor_expr_a_4; boolean_expr_3
end if;
end if; boolean_expr_1

Figura 2.26: Sentencias if anidadas y su diagrama conceptual.

Solución al Ejercicio 2.15

En la Figura 2.27 se muestra la sentencia case y su diagrama conceptual.

valor_expr_a_n ______,____--;

case expr_case is
when cO =>
valor_expr_a_1 - - - - - ;
a<= valor_expr_a_O;
b <= valor_expr_b_O; valor_expr_a_O - - - - - ;
when el=>
a<= valor_expr_a_l;
b <= valor_expr_b_l;
when others =>
valor_expr_b_n -+--ti,___--;
a<= valor_expr_a_n;
b <= valor_expr_b_n;
end case;
valor_expr_b_1 - + - - - - ;
valor_expr_b_O - + - - - - ;

expr_case

Figura 2.27: Sentencias case y su diagrama conceptual.

200
TEMA 3

SIMULACIÓN DEL CÓDIGO VHDL

3.1. Introducción
3.2. Procesamiento del código VHDL
3.3. Orden de compilación
3.4. Drivers
3.5. Inicialización
3.6. Atributos de las señales
3. 7. El retardo delta
3.8. Gestión de la cola de transacciones del driver
3.9. Ejemplo: simulación de un circuito sencillo
3.10. Lecturas recomendadas
3.11. Ejercicios de autocomprobación
3.12. Soluciones de los ejercicios
SIMULACIÓN DEL CÓDIGO VHDL

OBJETIVOS DOCENTES

Una vez estudiado el contenido del tema y realizados los ejercicios prácticos,
debería saber:

- Discutir las etapas análisis, elaboración y ejecución, de que consta el procesa-


miento y simulación del código VHD L realizado por las herramientas de CAD.

- Discutir el orden en el cual debe compilarse el código VHDL, atendiendo a las


relaciones existentes entre las diferentes unidades de diseño.

- Discutir los conceptos driver y función de resolución.

- Discutir en qué consiste la inicialización y cómo se realiza.

- Discutir qué son los atributos de las señales y los conceptos evento, señal activa,
transacción y señal implícita.

- Discutir cómo se realiza la simulación de las asignaciones con retardo 5, y cómo


se combina la simulación de asignaciones con retardo explícito y asignaciones
con retardo 5.

- Discutir cómo se gestionan las colas de transacciones de los drivers.

Realizar manualmente, paso a paso, la simulación de diseños sencillos, In-


dicando cómo se realiza la inicialización, cómo va avanzando el reloj de la
simulación, qué eventos se producen y cómo se gestionan las colas de transac-
ciones planificadas. Saber comprobar el resultado de las simulaciones realizadas
manualmente, usando para ello algún simulador de VHDL.

203
SIMULACIÓN DEL CÓDIGO VHDL

3.1. INTRODUCCIÓN

Para poder diseñar hardware de manera eficaz usando VHDL, es indispensable


comprender cómo las herramientas de CAD simulan el código VHDL. Los conceptos
explicados en el Tema 2 sirven de base para ello. En concreto, se explicó la diferencia
entre una variable y una señal, y en qué situaciones debe emplearse una u otra. En
la Tabla 3.1 se muestra un resumen de ello.

También se explicó que en VHDL hay dos tipos de código: el código concurrente
y el código secuencial. Las sentencias concurrentes son la asignación condicional
(when-else), la asignación de selección (with-select-when) y la sentencia ge-
nerate. Las sentencias secuenciales son las incluidas dentro de bloques process,
function o procedure. Sentencias secuenciales son if, wait, case y for. Aun
cuando dentro de estos bloques la ejecución es secuencial, el bloque en su conjunto
es concurrente con el resto de bloques y sentencias concurrentes.

La ejecución de una sentencia de asignación concurrente se produce en el instante


en el cual cambia el valor de alguna de las señales a las cuales la sentencia es sensible.
El nuevo valor es asignado transcurrido un retardo, que por defecto es 5. Existen dos
formas alternativas de controlar la ejecución de un bloque process: mediante lista
de sensibilidad y mediante sentencias wait. Debe optarse por una de ellas, ya que
en un mismo bloque process no puede haber sentencias wait y lista de sensibilidad.

En este tema profundizaremos en el estudio de cómo es simulado el código VHDL.


Para ello, se introducirán conceptos nuevos, tales como el de driver, función de
resolución y señal implícita.

Tabla 3.1: Comparación entre signal y variable.

signal variable
Asignación <=
Qué representa Interconexiones en el circuito Información local
Visibilidad Puede ser global (visible desde Local (visible sólo desde el co-
todo el código) rrespondiente bloque process,
function o procedure)
Comportamiento El nuevo valor es asignado El nuevo valor es asignado in-
transcurrido un retardo, que mediatamente
por defecto vale 5.
Uso En package, entity y archi- Sólo en código secuencial. Es
tecture. En una entity, los decir, dentro de process, fun-
puertos son por defecto señales ction o proced ure

205
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

3.2. PROCESAMIENTO DEL CÓDIGO VHDL

Normalmente, el código VHDL es procesado por la herramienta de CAD siguien-


do las etapas consecutivas siguientes:

l. Análisis. Durante la etapa de análisis, el entorno de simulación comprueba la


sintaxis y semántica del código VHD L. El análisis se realiza sobre cada una
de las unidades de diseño. Si no hay errores, el entorno de simulación traduce
el código VHDL que describe la unidad de diseño a un formato propio y lo
almacena en la correspondiente librería.
Cuando existen dependencias entre las unidades de diseño, ·la compilación
de las mismas debe realizarse siguiendo un determinado orden. Las reglas
referentes al orden de compilación, así como las reglas de recompilación cuando
se hacen cambios en una de las unidades de diseño, serán explicadas en la
Sección 3.3.

2. Elaboración. En un diseño complejo, normalmente el sistema es descrito de


manera modular y jerárquica. Durante la etapa de elaboración el entorno de
simulación comienza por la unidad de diseño de nivel jerárquico superior y
enlaza la declaración de la entity del sistema con la definición de su archi-
tecture. En la architecture, va reemplazando cada componente instanciado
por su definición. Este proceso se repite recursivamente, descendiendo por los
niveles jerárquicos del diseño, hasta que se obtiene una descripción "plana" del
sistema, en la cual se ha deshecho la jerarquía y composición.

3. Ejecución. Durante la etapa de ejecución, la descripción plana del sistema,


obtenida de la elaboración, sirve como entrada al software de simulación o de
síntesis.
Al comienzo de la simulación se resuelve el problema de la inicialización. Se
denomina inicialización al cálculo del valor inicial (es decir, en el instante
de tiempo cero) de las señales explícitas (aquellas señales declaradas en las
entity y en las architecture) y de las señales implícitas. En la Sección 3.6 se
introducirá el concepto de señal implícita.
En la inicialización, los bloques process son ejecutados hasta que son suspen-
didos. Si el bloque process tiene sentencias wait, se ejecuta el bloque hasta
que queda suspendido en la primera sentencia wait. Si el bloque process
tiene lista de sensibilidad, se ejecuta una vez el código completo del bloque,
quedando suspendido tras la ejecución de la última sentencia del bloque.

206
SIMULACIÓN DEL CÓDIGO VHDL

3.3. ORDEN DE COMPILACIÓN

Cuando existen dependencias entre las unidades de diseño, debe seguirse un orden
en su compilación. Si una unidad de diseño usa un paquete, entonces la declaración
del paquete (package) debe compilarse primero. El cuerpo del paquete (package
body) puede compilarse posteriormente. Si en la declaración del paquete se hace
referencia a otros paquetes, entonces las declaraciones de estos deben compilarse
pnmero.

Si en una architecture se declaran componentes, entonces las entity de los


componentes deben compilarse primero. La architecture de los componentes puede
compilarse posteriormente.

Resumiendo lo anterior, el orden de compilación de las unidades de diseño puede


ser el siguiente:

l. Declaraciones de los paquetes (package), teniendo en cuenta las interdepen-


dencias entre los paquetes. Por ejemplo, si un paquete paqueteA necesita decla-
raciones de un paquete paqueteE, entonces paqueteE debe compilarse primero.

2. Las entity que hacen uso de los paquetes anteriores.

3. Las architecture. El orden en la compilación de las architecture puede ser


cualquiera, ya que cuando en una architecture se instancian componentes
(por ejemplo, en los bancos de prueba y en las descripciones estructurales),
esta architecture puede ser compilada sin necesidad de haber compilado
previamente las architecture de los componentes que utiliza.

4. Las unidades de diseño configuration.

5. El cuerpo de los paquetes (package body). Los cuerpos de los paquetes


pueden ser compilados en cualquier orden una vez han sido compiladas sus
declaraciones, no tienen forzosamente que compilarse al final. De hecho, nor-
malmente los cuerpos de los paquetes son compilados a continuación de sus
declaraciones.

Las dependencias entre las unidades de diseño puede obligar a recompilar varias
unidades de diseño si se modifica el código de una de ellas. A continuación, se
explican algunas reglas para la recompilación, en caso de que se modifique el código
de una unidad de diseño:

207
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

l. Si la declaración de un package cambia, entonces no sólo debe recompilarse


el cuerpo de ese paquete (package body), además deben recompilarse todos
los paquetes (la declaración y el cuerpo), las entity, las architecture y las
configuration que hacen uso del package cuya declaración se ha modificado.

2. Si el cuerpo de un paquete (package body) cambia, entonces sólo es preciso


recompilar el cuerpo del paquete.

3. Si se modifica una entity, entonces todas las architecture que usan esa
entity, incluyendo aquellas en las cuales se declaran o instancian componentes
de esa entity, deben ser recompiladas. Las declaraciones de configuration
deben ser también recompiladas.

4. Si una architecture cambia, entonces sólo es preciso recompilar dicha archi-


tecture.

5. Si cambia una configuration, sólo es preciso recompilar dicha configuration.

Las herramientas de CAD permiten al usuario especificar el orden de compilación


de las unidades de diseño. Por otra parte, algunas herramientas de CAD analizan
automáticamente las dependencias en el diseño VHDL y determinan qué unidades es
necesario recompilar antes de ejecutar la simulación. Esto supone una ayuda valiosa
para el mantenimiento del código en diseños de grandes dimensiones.

3.4. DRIVERS

El concepto de driver es empleado por el simulador de VHDL a fin de realizar la


simulación del código. Los drivers no son definidos explícitamente por el diseñador en
el código VHDL del diseño, sino que son creados automáticamente por el simulador
en la fase de elaboración del código.

Cada señal tiene asociado uno o varios drivers. El valor de la señal viene deter-
minado en todo momento por el valor de sus drivers. En el caso más sencillo, en que
la señal tiene un único driver, el valor de la señal coincide en todo momento con el
valor de su driver.

Cada driver de una señal está asociado a una o varias asignaciones a dicha señal.
Cada señal tiene un driver asociado a cada asignación concurrente a la señal y un
driver asociado a cada bloque process en el cual hay asignaciones a la señal. Las
reglas que se siguen para establecer dicha asociación son las siguientes:

208
SIMULACIÓN DEL CÓDIGO VHDL

- Se asocia un driver para la señal por cada asignación concurrente en la cual se


asigne valor a la señal.

- Si dentro de un bloque process se asigna valor a una señal mediante una


única asignación secuencial, entonces se asocia a dicha asignación secuencial
un driver para la señal.

- Si dentro de un bloque process se asigna valor a una misma señal en varias


asignaciones secuenciales, entonces se asocia a todas ellas un único driver para
la señal.

- Si se asigna valor a una misma señal en cierto número de bloques process,


entonces se asocia un driver para la señal por cada uno de estos bloques
process.

Cada driver contiene una cola. En ella van almacenándose las transacciones
futuras planificadas para la señal, debidas a la ejecución de las asignaciones asociadas
al driver. Cada una de estas transacciones planificadas consta de: el nuevo valor que
debe asignarse a la señal y el instante de tiempo en que debe asignarse dicho valor.

Así pues, cuando el simulador ejecuta una sentencia concurrente o secuencial


de asignación a una señal, el simulador calcula el nuevo valor de la señal y tam-
bién calcula el instante de tiempo en que debe asignarse el nuevo valor a la señal
(recuérdese que todas las asignaciones a señal tienen un retardo, que por defecto
vale 6). Esta información, que define una transacción planificada para un instante
futuro, se incluye en la cola de transacciones del driver asociado a la sentencia de
asignación. En la Sección 3.8 se explicará con detalle qué reglas aplica el simulador
para gestionar la cola de un driver.

Al ir avanzando la simulación, el valor del driver va cambiando de acuerdo a las


transacciones planificadas en su cola. Las transacciones van siendo eliminadas de la
cola a medida que se van asignando al driver los valores planificados.

El valor de la señal en cada instante se calcula a partir del valor de sus drivers
en ese instante. Si hay varios drivers asociados a una misma señal y todos ellos
proporcionan un mismo valor, entonces no se produce conflicto. Sin embargo, si los
drivers asociados a una señal proporcionan diferentes valores, entonces para decidir
qué valor asignar debe recurrirse a la función de resolución del tipo de dato de la
señal. Si el tipo de dato no tiene función de resolución, se produce un error. Este es
el caso, por ejemplo, de los tipos boolean e integer.

Una función de resolución es una función que examina los valores de los drivers
de la señal y resuelve el conflicto, devolviendo un valor. La función de resolución

209
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

3.5.1. Ejemplo: señal con un driver

Obsérvese el código siguiente:

architecture drivers2 of drivers2 is


signal a: std_logic 'Z';
begin
bloque! : process
begin
a<= '1';
wait;
end process bloque!;
end architecture drivers2;

Al declarar la señal a, se le asigna el valor inicial 'Z'. Por ello, en el instante t = O


el driver de la señal a (y consecuentemente la propia señal) vale 'z' . A continuación,
también en el instante t =O, se ejecuta el bloque process:

l. Como resultado de ejecutar la asignación a <= ' 1 ' , se planifica asignar a la


señal el valor ' 1 ' en el instante t = 5. Esta transacción se añade a la cola
de transacciones del driver. La cola de transacciones del driver en el instante
t =O es:
tiempo a
5 '1'

2. Se ejecuta la sentencia wait, que hace que se suspenda indefinidamente la


ejecución del bloque process.

El reloj de la simulación avanza al instante t = 5, ya que es el instante más


próximo en el cual se encuentra planificada una transacción. En el instante t = 5,
se asigna al driver de la señal a el valor ' 1 ' y se elimina esta transacción de la cola
del driver. La señal tiene un único driver. Por ello, el valor de la señal coincide con
el valor del driver en todo momento.

Dado que no hay ninguna otra transacción planificada y que el bloque process
está suspendido indefinidamente, finaliza la simulación. El resultado de la simulación,
representado mediante la lista de eventos en la señal a, se muestra en la tabla
siguiente. En la columna de la izquierda se indica el instante en el cual se asigna un
nuevo valor a la señal. En la columna de la derecha se indica cuál es ese nuevo valor.

tiempo a
o 'Z'
5 '1'

212
SIMULACIÓN DEL CÓDIGO VHDL

3.5.2. Ejemplo: señal con dos drivers

A continuación se muestra otro ejemplo, en el cual la señal a tiene dos drivers.

architecture drivers! of drivers! is


signal a : std_logic := 'Z';
begin

bloque! : process
begin
wait for 10 ns;
a <= '1';
wait for 20 ns;
a <= '0';
end process bloque!;

bloque2 : process
begin
wait for 20 ns;
a <= '1';
wait for 20 ns;
a <= '0';
end process bloque2;

end architecture drivers!;

El código contiene dos bloques process, a los que se ha llamado bloque! y


bloque2. Cada uno de estos bloques contiene dos asignaciones a una misma señal.
La señal es del tipo std_logic y se llama a. Al declarar la señal, se le asigna el valor
inicial 'z'.

El simulador crea dos drivers para la señal. Un driver se asocia a las asignaciones
a la señal que se producen dentro del bloque process llamado bloque! y el otro
driver se asocia a las asignaciones a la señal realizadas dentro del bloque process
llamado bloque2.

Cada driver tiene su propia cola de transacciones planificadas, en la cual se alma-


cenan las transacciones debidas a las asignaciones asociadas al driver. Los cambios
en el valor de cada driver están determinados por las transacciones planificadas en
su propia cola. En todo momento, el valor de la señal se calcula a partir de los valores
de los dos drivers, empleando la función de resolución cuando sea necesario.

En el instante t = O, el valor de los dos drivers y de la señal es igual a 'z'. En


t = O, se ejecutan ambos bloques process, quedando la ejecución suspendida en
ambos casos en la primera sentencia del bloque.

213
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Simulando el código durante 100 ns, se obtiene que el driver asociado al bloque
process bloque1 evoluciona de la forma siguiente:

tiempo driver1_a
o 'Z'
10 ns +o '1'
30 ns +o '0'
40 ns +o '1'
60 ns +o '0'
70 ns +o '1'
90 ns +o '0'
100 ns +O '1'

El driver asociado al bloque process bloque2 evoluciona de la forma siguiente:

tiempo driver2_a
o 'Z'
20 ns +o '1'
40 ns +o '0'
60 ns +o '1'
80 ns +o '0'
100 ns +o '1'

El valor de la señal se calcula de los valores de los dos drivers, aplicando la


función de resolución en caso de conflicto. Uniendo ambas tablas, de manera que
se muestre el valor de ambos drivers en los instantes en que uno de ellos cambia de
valor, se obtiene:

tiempo driver1_a driver2_a a


o 'Z' 'Z' 'Z'
10 ns +o '1' 'Z' '1'
20 ns +o '1' '1' '1'
30 ns +o '0' '1' 'X'
40 ns +o '1' '0' 'X'
60 ns +o '0' '1' 'X'
70 ns +o '1' '1' '1'
80 ns +o '1' '0' 'X'
90 ns +o '0' '0' '0'
100 ns +o '1' '1' '1'

214
SIMULACIÓN DEL CÓDIGO VHDL

Indicando en la tabla únicamente aquellos instantes de tiempo en los cuales se


produce cambio en el valor de la señal, se obtiene:

tiempo a
o 'Z'
10 ns +6 '1'
30 ns +6 'X'
70 ns +6 '1'
80 ns +6 'X'
90 ns +6 '0'
100 ns +6 '1'

Supongamos ahora que la señal del ejemplo anterior, a, no es inicializada al


declararla. Es decir, en lugar de

signal a: std_logic 'Z';

se escribe

signal a : std_logic;

Dado que no se inicializa la señal al declararla, el simulador asume que en t = O


los dos drivers y la señal tienen el valor por defecto del tipo std_logic, que es 'U'.
En la siguiente tabla se muestra la evolución de los drivers y de la señal:

tiempo driver1_a driver2_a a


o 'U' 'U' 'U'
10 ns +6 '1' 'U' 'U'
20 ns +6 '1' '1' '1'
30 ns +6 '0' '1' 'X'
40 ns +6 '1' '0' 'X'
60 ns +6 '0' '1' 'X'
70 ns +6 '1' '1' '1'
80 ns +6 '1' '0' 'X'
90 ns +6 '0' '0' '0'
100 ns +6 '1' '1' '1'

La evolución de la señal, indicando sólo aquellos instantes de tiempo en los cuales


cambia su valor, se muestra en la tabla siguiente:

215
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

tiempo a
o 'U'
20 ns +5 '1'
30 ns +5 'X'
70 ns +5 '1'
80 ns +5 'X'
90 ns +5 '0'
100 ns +5 '1'

Un comentario final acerca de la inicialización. Debe tenerse en cuenta que la


inicialización de las señales al declararlas es ignorada por las herramientas de síntesis.
Por este motivo, cuando se desee reflejar en el diseño del circuito una operación de
inicialización, debe hacerse mediante la correspondiente señal de reset, no asignando
valores iniciales a las señales. En los temas siguientes se muestran ejemplos de esta
técnica de diseño. Por otra parte, en la descripción de los bancos de prueba sí es
práctica común inicializar las señales al declararlas, ya que los bancos de prueba no
van a ser sintetizados.

3.6. ATRIBUTOS DE LAS SENALES

Los atributos de las señales proporcionan información acerca de los instantes en


los cuales se producen cambios en el valor de la señal y también acerca del valor en sí
de la señal. Estos atributos se emplean frecuentemente para sincronizar la ejecución
de sentencias concurrentes.

Los siguientes conceptos están relacionados con las señales y sus atributos: evento,
señal activa, transacción y señal implícita. A continuación se explica su significado.

- Un evento es un cambio en el valor de la señal, que ocurre cuando se asigna a


la señal un nuevo valor, diferente del que tenía anteriormente.

- Se dice que una señal está activa cuando su valor es actualizado, con indepen-
dencia de que el nuevo valor sea el mismo que el valor actual o sea diferente.
Por ejemplo, si en determinado instante el valor de la señal es '1' y se le asigna
el valor ' 1 ' , en ese instante la señal está activa, pese a que su valor no cambie.

- Se llama transacción a asignar valor a una señal, ya sea este valor igual o
diferente al valor que tiene la señal previamente a dicha asignación. En el
instante en que se produce la transacción, la señal está activa. Cuando el valor

216
SIMULACIÓN DEL CÓDIGO VHDL

asignado es diferente que el valor previo, se dice además que se ha producido


un evento.

- Se denomina señal implícita a una señal que no está declarada en el códi-


go VHDL, pero que se deduce del empleo de los atributos 'stable, 'quiet,
'delayed y 'transaction. Cada vez que uno de estos atributos es usado en
un diseño, el simulador genera automáticamente una señal implícita. VHDL
impone una restricción al uso de las señales implícitas: no pueden ser leídas
desde dentro de un subprograma.

Los atributos de las señales pueden clasificarse en dos tipos: aquellos que repre-
sentan una señal implícita y aquellos que equivalen a la llamada a una función. Los
atributos se muestran en la Tabla 3.3.

217
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Tabla 3.3: Atributos de las señales.

s'event Función booleana que devuelve true cuando se produce un evento


en la señal. El resto del tiempo devuelve false. Ejemplos:
if clk'event then ...
En el preciso instante en que clk cambia de valor, entonces ...
wait until clk'event and clk='1';
Suspende el proceso hasta que el valor de clk pasa a ser '1'
s'active Función booleana que devuelve true en el instante en el cual se
produce una transacción a la señal. El resto del tiempo devuelve
false. Ejemplos:
if dato' active then ...
En el preciso instante en que se asigna valor a dato, entonces ...
wait until dato'active;
Suspende el proceso hasta que se asigna valor a dato
s 'transaction Crea una señal implícita de tipo bit, cuyo valor va cambiando 'O',
'1', 'O', ... cada vez que se produce una transacción a la señal s.
Ejemplo:
wait on dato'transaction;
Se suspende el proceso hasta que se asigna valor a dato
s 'delayed(T) Crea una señal implícita del mismo tipo que s, cuyo valor es igual
al valor de s retrasado T. Si se omite T, el retardo por defecto
es O, con lo cual es el valor de la señal en el instante 5 anterior.
Por ejemplo, s 'delayed ( 4 ns) en el instante 10 ns es el valor que
tenía s en el instante 6 ns.
s 'stable (T) Crea una señal implícita de tipo booleano, cuyo valor es true si no
se ha producido un evento en la señal s durante las anteriores T
unidades de tiempo. En caso contrario, vale false. Ejemplo:
if dato'stable(100 ns) then ...
Si no se ha producido ningún evento en la señal dato durante los
últimos 100 ns, entonces ...
s 'quiet (T) Crea una señal implícita de tipo booleano, cuyo valor es true si
no se ha producido ninguna transacción a la señal s durante las
anteriores T unidades de tiempo. En caso contrario, vale false.
Ejemplo:
if dato'quiet(100 ns) then . . .
Si no se ha producido ninguna transacción a la señal dato durante
los últimos 100 ns, entonces ...
s' last_event Función que devuelve un valor del tipo time: el tiempo transcu-
rrido desde que se produjo el último evento en la señal s. Si no ha
habido evento previo, devuelve el valor máximo del tipo de dato
time (time'high).
s 'last_acti ve Función que devuelve un valor del tipo time: el tiempo transcu-
rrido desde que se produjo la última transacción a la señal s. Si no
ha habido ninguna transacción previa, devuelve el valor máximo
del tipo de dato time (time'high).
s' last_ value Función que devuelve un valor del mismo tipo que s: el valor de
la señal previo a la última transacción a la señal.

218
SIMULACIÓN DEL CÓDIGO VHDL

3.7. EL RETARDO DELTA

Uno de los requisitos que debe satisfacer la simulación del código concurrente es
el siguiente: el resultado de la simulación debe ser independiente del orden en que
se ejecuten en un determinado instante las sentencias concurrentes.

Para satisfacer este requisito, una vez se han evaluado todas las sentencias
concurrentes activas en el instante t y se han calculado los nuevos valores de las
señales, estos nuevos valores se asignan a las señales en el instante t + 6 (supuesto
que no se indique en el código explícitamente el retardo).

El tiempo 6 es una cantidad infinitesimal de tiempo, que representa un tiempo


mayor que cero, pero que se considera cero cuando se suma a una cantidad de tiempo
no infinitesimal.

Por ejemplo, supongamos que en el instante t = 15 ns +46 se evalúa la asignación

s <= '1' after 3 ns;

El valor '1' se debe asignar a la señal s transcurridos 3 ns. Es decir, en el instante


t = 15 ns + 46 + 3 ns. Sin embargo, al sumar múltiplos de 6 con valores del tiempo
no infinitesimales, se supone que los múltiplos de 6 valen cero. Por ello, el valor '1'
se asigna a la señal en el instante t = 18 ns. Es decir, al realizar la suma se considera
que 46 vale cero.

A continuación se muestra un ejemplo:

architecture drivers3 of drivers3 is


signal a1 std_logic '0';
signal a2 : std_logic '0';
begin

bloque! : process
begin
wait for 100 ns;
a2 <= '1';
a1 <= '1';
end process bloque!;

bloque2 : process
begin
a1 <= not a1 after 1 ns;
wait on a2;
end process bloque2;

end architecture drivers3;

219
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

En el código mostrado anteriormente se declaran dos señales, que son inicializadas


al valor 'O'. El código contiene dos bloques process. En el primero (bloque!) se
realizan asignaciones con retardo <5 a las señales a1 y a2. En el segundo bloque
process (bloque2) se realiza una asignación a la señal a1 con un retardo de 1 ns.
En consecuencia, el simulador asocia:

- Dos drivers a la señal a1, uno por cada bloque process. En las explicaciones
siguientes llamaremos dri ver1_a1 y dri ver2_a1 a los drivers de la señal a1
asociados a los bloques process bloque! y bloque2, respectivamente.

- Un driver a la señal a2. Llamaremos driver_a2 al driver de la señal a2.

En el instante t = O, los drivers y las señales tienen valor 'O', debido a que ese
es el valor con el que las señales han sido inicializadas al declararlas.

En t =O se ejecutan los dos bloques process:

l. La ejecución del bloque process bloque! queda suspendida en su primera


sentencia (wai t f or 100 ns).

2. Se ejecuta la primera sentencia (a1 <= not a1 after 1 ns) de bloque2. Se


planifica asignar a dri ver2_a1 el valor '1' en el instante t = 1 ns.
3. Se suspende la ejecución de bloque2 en la sentencia wai t on a2.

En t = 1 ns, se asigna el valor '1' a dri ver2_a1. El otro driver de la señal,


dri ver1_a1, mantiene el valor 'O', que se le asignó en la inicialización. El simulador
emplea la función de resolución para resolver el conflicto, asignándose a la señal a1
el valor 'X' en el instante t = 1 ns.

En el instante t = 100 ns finaliza la ejecución de la sentencia wait de bloque!,


reanudándose la ejecución de dicho bloque. Se ejecutan las dos asignaciones a las
señales y la ejecución del bloque queda de nuevo suspendida en la sentencia wait. Co-
mo resultado de la ejecución de las dos asignaciones, se planifica asignar a dri ver1_a1
y a driver_a2 el valor '1' en el instante t = 100 ns +<5.

En el instante t = 100 ns +<5 se asigna el valor '1' a dri ver1_a1. Los dos drivers
de la señal a1 valen ' 1 ' , con lo cual la señal adquiere el valor ' 1 ' en el instante
t = 100 ns +<5.
Asimismo, en el instante t = 100 ns +<5 se asigna el valor '1' a driver _a2. La
señal a2 tiene un único driver, con lo cual en todo momento el valor de la señal y del

220
SIMULACIÓN DEL CÓDIGO VHDL

driver coinciden. Así pues, la señal a2 adquiere el valor '1' en el instante t = 100
ns +5.

El cambio en el valor de a2 hace que en el instante 100 ns + 5 finalice la


ejecución de la sentencia wait de bloque2. Por tanto, en ese mismo instante se
ejecuta la primera sentencia de bloque2 ( a1 <= not a1 after 1 ns) y a continuación
nuevamente la sentencia wait, quedando la ejecución de bloque2 suspendida una vez
más.

Como resultado de la ejecución de la sentencia a1 <= not a1 after 1 ns, se


planifica asignar a dri ver2_a1 el valor 'O' en el instante 100 ns + 5 + 1 ns. Dado
que los múltiplos de 5 se consideran cero al ser sumados con valores no infinitesimales
del tiempo, el nuevo valor se asignará al driver en t = 101 ns.

La siguiente tabla muestra el resultado de la ejecución del código anterior hasta


el instante t = 101 ns.

tiempo driver1_a1 driver2_a1 a1 a2


o '0' '0' '0' '0'
1 ns '0' '1' 'X' '0'
100 ns +5 '1' '1' '1' '1'
101 ns '1' '0' 'X' '1'

3.8. GESTIÓN DE LA COLA DE TRANSACCIONES DEL DRIVER

Cada driver contiene una cola, en la cual van almacenándose las transacciones
planificadas para la señal. Cuando se ejecuta una sentencia de asignación a la
señal, las transacciones calculadas en dicha sentencia son añadidas a la cola del
driver asociado a dicha asignación. Una vez añadidas las nuevas transacciones,
se aplican unas reglas para decidir si las transacciones que estaban anteriormente
almacenadas en la cola deben ser eliminadas o no. Estas reglas dependen de si las
nuevas transacciones deben producirse con un retardo inercial o de transporte.

Supongamos que en el instante t se añaden a la cola un conjunto de transacciones,


que están planificadas para los instantes futuros t 1 , t 2 , . . . Se aplican las siguientes
reglas para decidir si las transacciones que estaban almacenadas en la cola del driver
deben eliminarse o conservarse:

Regla 1 Se eliminan de la cola todas las transacciones planificadas para instantes


de tiempo iguales o posteriores a t 1 .

221
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Regla 2 Si las nuevas transacciones tiene retardo inercial (para retardo de trans-
porte este paso no se realiza), se van inspeccionando las transacciones que se
encontraban en la cola del driver, progresando hacia atrás en el tiempo, desde
el instante t 1 hacia el cero:

Regla 2.1 Si la transacción que está siendo inspeccionada asigna a la señal


el mismo valor que la nueva transacción planificada para t 1 , entonces la
transacción inspeccionada se mantiene en la cola.
Regla 2.2 Si la transacción inspeccionada asigna a la señal un valor diferente
del que asigna la nueva transacción planificada para t 1 , entonces se eli-
mina de la cola la transacción que está siendo inspeccionada y todas las
transacciones planificadas para instantes anteriores a ésta.

3.8.1. Ejemplo: simulación de formas de onda con retardo inercial

En la siguiente architecture se define una señal, si, a la que se asigna valor en


dos sentencias contenidas dentro de un bloque process. El retardo en la asignación
del valor a la señal es retardo inercial en ambas sentencias. Se asocia un único driver
a estas dos sentencias.

architecture delayi of delayi is


signal si : natural;
begin
process
begin
si <= 3 after 3 ns,
i after 6 ns,
2 after i5 ns,
7 after 22 ns,
30 after 24 ns,
70 after 80 ns;
si <= 2 after 20 ns,
30 after 25 ns,
6 after 60 ns;
wait;
end process;
end architecture delayi;

Como no se especifica el valor inicial de la señal, se le asigna en la inicialización


el valor por defecto para el tipo natural, que es cero. Asimismo, también en t =O ,
se ejecuta el bloque process.

Al ejecutar la primera sentencia, se planifican las siguientes transacciones, que


se almacenan en la cola del driver de la señal:

222
SIMULACIÓN DEL CÓDIGO VHDL

tiempo si
3 ns 3
6 ns 1
15 ns 2
22 ns 7
24 ns 30
80 ns 70

Al ejecutar la segunda sentencia, se añaden las nuevas transacciones a la cola.


Las nuevas transacciones se han señalado anteponiendo (n).

tiempo si
3 ns 3
6 ns 1
15 ns 2
(n) 20 ns 2
22 ns 7
24 ns 30
(n) 25 ns 30
(n) 60 ns 6
80 ns 70

A continuación, para decidir qué transacciones "antiguas" deben eliminarse de la


cola, se aplican las reglas descritas anteriormente:

l. La primera transacción nueva está planificada para el instante 20 ns. Las


transacciones antiguas planificadas para instantes posteriores son eliminadas
de la cola (aplicación de la Regla 1). Las transacciones eliminadas de la cola
se señalan con (x).

tiempo si
3 ns 3
6 ns 1
15 ns 2
(n) 20 ns 2
(x) 22 ns 7
(x) 24 ns 30
(n) 25 ns 30
(n) 60 ns 6
(x) 80 ns 70

223
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2. Se van inspeccionando las transacciones antiguas planificadas para instantes


anteriores a 20 ns. La transacción planificada para el instante 15 ns tiene el
mismo valor que la transacción nueva, por ello se conserva (aplicación de la
Regla 2.1). Las transacciones planificadas para los instantes 3 ns y 6 ns, dado
que tienen valor diferente, son eliminadas de la cola (aplicación de la Regla
2.2).

tiempo s1
(x) 3 ns 3
(x) 6 ns 1
15 ns 2
(n) 20 ns 2
(x) 22 ns 7
(x) 24 ns 30
(n) 25 ns 30
(n) 60 ns 6
(x) 80 ns 70

El contenido de la cola es la unión de las transacciones antiguas no eliminadas y


las transacciones nuevas. Esto es:

tiempo s1
15 ns 2
(n) 20 ns 2
(n) 25 ns 30
(n) 60 ns 6

Dado que la siguiente sentencia del bloque process es wait, se suspende su


ejecución indefinidamente.

Finalizada la ejecución del código en t = O (es decir, la inicialización), el simula-


dor va avanzando el reloj de la simulación a fin de ir realizando los sucesivos eventos
(cambios en el valor de la señal). Simulando el diseño, se observa que la señal toma
los valores siguientes:

tiempo s1
O ns o
15 ns 2
25 ns 30
60 ns 6

224
SIMULACIÓN DEL CÓDIGO VHDL

3.8.2. Ejemplo: simulación de formas de onda con retardo de transporte

Supongamos ahora que las asignaciones a la señal tuvieran retardo de transporte.


Obsérvese que, al tener ambas asignaciones retardo de transporte, sólo es aplicable
la Regla l. La architecture en este caso sería:

architecture delay2 of delay2 is


signal s2 : natural;
begin
process
begin
s2 <= transport 3 after 3 ns,
1 after 6 ns,
2 after 15 ns,
7 after 22 ns,
30 after 24 ns,
70 after 80 ns;
s2 <= transport 2 after 20 ns,
30 after 25 ns,
6 after 60 ns;
wait;
end process;
end architecture delay2;

En t = O, se asigna el valor inicial por defecto a la señal y se ejecuta el bloque


process. Resultado de ejecutar la primera sentencia, se añaden las transacciones a la
cola del driver. Al ejecutar la segunda sentencia, se añaden las nuevas transacciones
a la cola. Las nuevas transacciones se han señalado anteponiendo (n).

tiempo s2
3 ns 3
6 ns 1
15 ns 2
(n) 20 ns 2
22 ns 7
24 ns 30
(n) 25 ns 30
(n) 60 ns 6
80 ns 70

Se eliminan de la cola todas las transacciones antiguas posteriores a la primera


transacción nueva (aplicación de la Regla 1). Las transacciones eliminadas se señalan
con (x).

225
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

tiempo s2
3 ns 3
6 ns 1
15 ns 2
(n) 20 ns 2
(x) 22 ns 7
(x) 24 ns 30
(n) 25 ns 30
(n) 60 ns 6
(x) 80 ns 70

Al ejecutar la sentencia wait se suspende la ejecución del bloque process. El


reloj de la simulación va avanzando a los instantes futuros en los cuales se produce
evento en la señal. Simulando el diseño, se observa que la señal toma los valores
siguientes:

tiempo s2
O ns o
3 ns 3
6 ns 1
15 ns 2
25 ns 30
60 ns 6

3.9. EJEMPLO: SIMULACIÓN DE UN CIRCUITO SENCILLO

El circuito mostrado en la Figura 3.2, así como las formas de onda de las señales
x1 y x2, son descritas por el código VHDL mostrado a continuación:

library IEEE;
use IEEE.std_logic_1164.all;
entity delay3 is
end entity delay3;

architecture delay3 of delay3 is


signal x1, x2, s, y : std_logic;
begin
s <= x1 nand x2 after 1 ns;
y <= s or x2 after 2 ns;
x1 <= '1';
x2 <= '1', '0' after 5 ns;
end architecture delay3;

226
SIMULACIÓN DEL CÓDIGO VHDL

xl
retardo = 1 ns

:·:·~.: ~~¡
:~
....
2·:·:: : : : : ·: : :.:·: : : : : : _..: :..
: :.x·:·::::.:· :.::::.:.::::.:.::::::·:.::¡··.

t !.....~.~~ ~J ::::::::::::::::::::6:
............................... ¡ retardo = 2 ns

Figura 3.2: Circuito ejemplo.

Al declarar las señales no se especifica su valor inicial. Por ello, las cuatro señales
tienen en t = O el valor por defecto para std_logic, es decir, valen 'U'. En t = O,
se ejecutan las sentencias de asignación a las cuatro señales. A continuación, se
muestra el resultado de la inicialización y el contenido de las colas de transacciones
planificadas para cada señal:

tiempo x1 x2 S y
o 'U' 'U' 'U' 'U'

tiempo x1 tiempo x2 tiempo S tiempo y


5 '1' 5 '1' 1 ns 'U' 2 ns 'U'
5 ns '0'

El reloj de la simulación avanza hasta el instante t = 5, ya que es el instante en


el cual está planificado el evento más próximo al tiempo actual. En t = 5 se asigna
el valor '1' a las señales x1 y x2.

El cambio en el valor de las señales x1 y x2 hace que se evalúen las asignaciones


a las señales s e y. Se calcula el nuevo valor de dichas señales y se introduce en la
cola. El valor calculado para y es el resultado de la operación ( 'U' or ' 1 ' ) , que es
igual a '1'. Los instantes en que deben asignarse los valores se calculan teniendo en
cuenta que 5 + 1 ns es igual a 1 ns y que 5 + 2 ns es igual a 2 ns. El resultado de la
simulación y el contenido de las colas de transacciones planificadas para cada señal
se muestran a continuación:

tiempo x1 x2 S y
o 'U' 'U' 'U' 'U'
5 '1' '1' 'U' 'U'

tiempo x1 tiempo x2 tiempo S tiempo y


5 ns '0' 1 ns '0' 2 ns '1'

227
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

El siguiente evento está planificado para el instante 1 ns, por tanto, el reloj
de la simulación avanza hasta t = 1 ns. En t = 1 ns, se asigna a la señal s el
valor 'O'. El cambio en el valor de la señal s hace que se ejecute la asignación
y <= s or x2 after 2 ns;, calculándose un nuevo valor para y, que se introduce
en la cola de la señal. El resultado de la simulación y el contenido de las colas de
transacciones planificadas para cada señal se muestran a continuación:

tiempo x1 x2 S y
o 'U' 'U' 'U' 'U'
ó '1' '1' 'U' 'U'
1 ns '1' '1' '0' 'U'

tiempo x1 tiempo x2 tiempo S tiempo y


5 ns '0' 2 ns '1'
3 ns '1'

El siguiente evento está planificado para el instante t = 2 ns, con lo cual el reloj
de la simulación salta hasta ese instante, en el cual se asigna el valor a la señal y. El
resultado de la simulación y el contenido de las colas de transacciones planificadas
para cada señal se muestran a continuación:

tiempo x1 x2 S y
o 'U' 'U' 'U' 'U'
ó '1' '1' 'U' 'U'
1 ns '1' '1' '0' 'U'
2 ns '1' '1' '0' '1'

tiempo x1 tiempo x2 tiempo S tiempo y


5 ns '0' 3 ns '1'

Dado que la señal y vale ' 1 ' , la transacción planificada para t = 3 ns no es un


evento. El reloj de la simulación salta hasta el siguiente evento, que se produce en
el instante t = 5 ns, en el cual se asigna el valor 'O' a la señal x2. El cambio en el
valor de x2 produce que se evalúen las sentencias s <= x1 nand x2 after 1 ns; y
y <= s or x2 after 2 ns;. Los valores calculados para s e y son '1' y 'o', respec-
tivamente. El resultado de la simulación y el contenido de las colas de transacciones
planificadas para cada señal se muestran a continuación:

228
SIMULACIÓN DEL CÓDIGO VHDL

tiempo x1 x2 S y
o 'U' 'U' 'U' 'U'
5 '1' '1' 'U' 'U'
1 ns '1' '1' '0' 'U'
2 ns '1' '1' '0' '1'
5 ns '1' '0' '0' '1'

tiempo x1 tiempo x2 tiempo S tiempo y


6 ns '1' 7 ns '0'

El siguiente evento se produce en el instante t = 6 ns, con lo cual el reloj de


la simulación salta hasta t = 6 ns. En ese instante, se asigna a la señal s el valor
'1'. El cambio en s hace que se evalúe la asignación y <= s or x2 after 2 ns;,
obteniéndose que se planifica asignar a la señal y el valor '1' en el instante t = 8 ns.
Al añadir este nuevo valor en la cola de la señal, se elimina el valor planificado para
t = 7 ns, ya que esa transacción pone la señal a un valor diferente (aplicación de la
Regla 2.2). El resultado de la simulación y el contenido de las colas de transacciones
planificadas para cada señal se muestran a continuación:

tiempo x1 x2 S y
o 'U' 'U' 'U' 'U'
5 '1' '1' 'U' 'U'
1 ns '1' '1' '0' 'U'
2 ns '1' '1' '0' '1'
5 ns '1' '0' '0' '1'
6 ns '1' '0' '1' '1'

tiempo x1 tiempo x2 tiempo S tiempo y


8 ns '1'

La transacción planificada para t = 8 ns no modifica el valor de la señal, con lo


cual no es preciso ejecutarla. Dado que no quedan más transacciones pendientes en
las colas, finaliza la simulación. El resultado de la misma se muestra a continuación
(véase también la Figura 3.3):

229
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

tiempo x1 x2 S y
o 'U' 'U' 'U' 'U'
8 '1' '1' 'U' 'U'
1 ns '1' '1' '0' 'U'
2 ns '1' '1' '0' '1'
5 ns '1' '0' '0' '1'
6 ns '1' '0' '1' '1'

Messages

+x 1 1 ::S
+x2 1
+s
+ v
u
u
j
1
1 1 1 1 1 1 1 1
~!m@ Now 8 ns hs 2 ns 4 ns 6 ns 8 ns
t]¡./'0 O nsJ
liJ li.GJ ~ih 1 1/
1 Onsto8ns 1 Now: 8 ns Delta: 1 //.

Figura 3.3: Señales x 1 , x 2 , y y s del circuito ejemplo.

3.10. LECTURAS RECOMENDADAS

La mayor parte de los textos sobre VHDL, incluyendo (Chang 1997, Chu 2006,
Vahid & Lysecky 2007, Pedroni 2004, Lee 2006, Ashenden 2002, Armstrong & Gray
2000, Heinkel 2000), abordan con mayor o menor profundidad la simulación del
código. Sin embargo, es raro encontrar una descripción tan detallada acerca de los
drivers y la simulación del retardo como la que se ofrece en los Capítulos 4 y 5 de
(Cohen 1995).

230
SIMULACIÓN DEL CÓDIGO VHDL

3.11. EJERCICIOS DE AUTOCOMPROBACIÓN

Ejercicio 3.1

Dado el Código VHDL 3.1, dibuje el cronograma de la evolución de las señales


y1, y2, y3, y4.

library IEEE;
use IEEE . std_logic_1164. all;
entity codigo is
end entity codigo;
architecture codigo of codigo is
signal y1, y2, y3, y4 : std_logic;
begin
y1 <= '0',
'1' after 100 ns;
y1 <= '0',
'1' after 50 ns;
y2 <= '0',
'1' after 100 ns,
'O' after 200 ns,
'1' after 250 ns;
y3 <= y2 after 100 ns;
y4 <= transport y2 after 100 ns;
end architecture codigo;

Código VHDL 3.1: Código correspondiente al Ejercicio 3.1.

Ejercicio 3.2

Consideremos el circuito mostrado en la Figura 3.4. Las puertas AND2 y OR2


tienen un retardo inercial de 10 ns y 20 ns, respectivamente. El Código VHDL 3.2
describe el circuito y las señales de entrada. Explique detalladamente cómo se realiza
la simulación del código y dibuje el cronograma de las señales.

xl
.........................................

x2
.........................................
:. ............... . ?..~. ! ........ ............ ................... . ..
... ~~..............................¡

Figura 3.4: Circuito cuyo comportamiento se desea analizar.

231
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

library IEEE;
use IEEE. std_logic_1164 . all;
entity delay4 is
end entity delay4;
architecture delay4 of delay4 is
signal x1, x2, x3, s, y : std_logic;
begin
s <= x1 and x2 after 10 ns;
y <= s or x3 after 20 ns;
x1 <= '1',
'O' after 15 ns,
'1 'after 20 ns,
'O' after 30 ns,
'1 'after 70 ns,
'O' after 80 ns;
x2 <= '1';
x3 <= '0',
'1 'after 70 ns,
'O' after 80 ns;
end architecture delay4;

Código VHDL 3.2: Código correspondiente al Ejercicio 3.2.

Ejercicio 3.3

Tomando como base el diseño mostrado en el Código VHDL 3.3 y el banco de


pruebas mostrado en el Código VHDL 3.4, indique cuál es la evolución de las señales
X1, X2, X3 , sig_s1, Y1.

library IEEE;
use IEEE. std_logic_1164. all;
entity codigo1 is
port( X1, X2, X3: in std_logic;
Y1 :out std_logic);
end entity codigo 1;
architecture behv of codigo1 is
signal sig_s1: std_logic;
begin
Proc1: process (X1, X2, X3)
begin
sig_s1 <= X1;
Y1 <= sig_s1 xor X3;
sig_s1 <= X2;
end process;
end architecture behv;

Código VHDL 3.3: Diseño del Ejercicio 3.3.

232
SIMULACIÓN DEL CÓDIGO VHDL

-- Banco de pruebas
library IEEE;
use IEEE. std_logic_1164. all;
entity bp_codigo1 is
end entity bp_codigo1;
architecture bp_codigo1 of bp_codigo1 is
signal Y1 : std_logic; -- Conectar salida UUT
signal X1 , X2, X3 : std_logic; -- Conectar entradas UUT
component codigo1 is
port ( Y1 : out std_logic;
X1 , X2, X3 : in std_logic );
end component codigo1 ;
begin
-- Instanciar y conectar UUT
uut : component codigo 1 port map
( Y1 = > Y1 , X1 = > X1 , X2 = > X2, X3 => X3 );
gen_vec_ test : process
begin
X1 <= '0'; X2 <= '0' ; X3 <= '1' ; wait for 100 ns;
X1 <= '0'; X2 <= '1 ' ; X3 <= '1' ; wait for 100 ns;
X1 <= '1'; X2 <= '0' ; X3 <= '0' ; wait for 100 ns;
X1 <= '1'; X2 <= '1' ; X3 <= '0' ; wait for 100 ns ;
X1 <= '0'; X2 <= '1'; X3 <= '0'; wait for 100 ns;
X1 <= '1'; X2 <= '0' ; X3 <= '1 ' ;
wait ;
end process gen_vec_test ;
end a r chitecture bp_codigo1;

Código VHDL 3.4: Banco de pruebas del Ejercicio 3.3.

233
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 3.4

Tomando como base el diseño mostrado en el Código VHDL 3.5 y el banco de


pruebas mostrado en Código VHDL 3.6, explique detalladamente la evolución de las
señales y dibuje su cronograma.

library IEEE;
use IEEE. std_logic_1164. all;
entity codigo2 is
port( X1, X2, X3 : in std_logic;
Y2 : out std_logic);
end entity codigo2;
architecture behv of codigo2 is
begin
proc2: process (X1, X2, X3)
variable var _s 1 : std_logic;
begin
var_s1 := X1;
Y2 <= var_s1 xor X3;
var_s1 := X2;
end process proc2;
end architecture behv;

Código VHDL 3.5: Diseño del Ejercicio 3.4.

234
SIMULACIÓN DEL CÓDIGO VHDL

-- Banco de pruebas
library IEEE;
use IEEE. std_logic_1164. all;
entity bp_codigo2 is
end entity bp_codigo2;
architecture bp_codigo2 of bp_codigo2 is
signal Y2 : std_logic; -- Conectar salida UUT
signal X1, X2, X3 : std_logic; -- Conectar entradas UUT
component codigo2 is
port ( Y2 : out std_logic;
X1, X2, X3 : in std_logic);
end component codigo2;
begin
-- Instanciar y conectar UUT
uut : component codigo2 port map
( Y2 => Y2, X1 => X1, X2 => X2, X3 => X3 );
gen_vec_ test : process
begin
X1 <= '0'; X2 <= '0'; X3 <= ' 1'; wait for 100 ns;
X1 <= '0'; X2 <= '1'; X3 <= ' 1'; wait for 100 ns;
X1 <= '1'; X2 <= '0'; X3 <= 'O'; wait for 100 ns;
X1 <= '1'; X2 <= '1 '; X3 <= 'O'; wait for 100 ns;
X1 <= '0'; X2 <= '1 '; X3 <= '0'; wait for 100 ns;
X1 <= '1'; X2 <= '0'; X3 <= '1 ';
wait;
end process gen_vec_test;
end architecture bp_codigo2;
------------------------

Código VHDL 3.6: Banco de pruebas del Ejercicio 3.4.

235
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 3.5

Dado el diseño mostrado en el Código VHDL 3.7 y el banco de pruebas mostrado


en el Código VHDL 3.8, indique cuál es el valor de las señales a, b, e, d, s1, s2, s3
en los instantes de tiempo O, <5, 2<5, 3<5, 4<5.

library IEEE;
use IEEE. std_logic_1164. all;
entity deltas is
port( d : out std_logic;
a, b, e : in std_logic);
end deltas;
architecture arquitectura of deltas is
signal s 1, s2, s3 : std_logic;
begin
p1 : process (a, b)
begin
s1 <= a and b;
end process p1;
p2 : process(b, e)
begin
s2 <= b ore;
end process p2;
p3 : process (s1, s2)
begin
s3 <= s1 xor s2;
end process p3;
p4 : process (s3)
begin
d <= not s3;
end process p4;
end architecture arquitectura;

Código VHDL 3. 7: Diseño correspondiente al Ejercicio 3.5.

236
SIMULACIÓN DEL CÓDIGO VHDL

-- Banco de pruebas
library IEEE;
use IEEE. std_logie_1164. all;
entity bp_del tas is
end entity bp_del tas;
architecture bp_del tas of bp_del tas is
signal d : std_logic; -- Conectar salida UUT
signal a, b, e : std_logic; -- Conectar entradas UUT
component deltas is
port ( d : out std_logic;
a, b, e : in std_logic ) ;
end component deltas;
begin
-- Instanciar y conectar UUT
uut : component deltas port map
( d=>d, a => a, b => b, e => e);
gen_ ve e_ test : process
begin
a<= '1';
b<= '1';
e<= '0';
wait;
end process. gen_vee_test;
end architecture bp_del tas;

Código VHDL 3.8: Banco de pruebas correspondiente al Ejercicio 3.5.

Ejercicio 3.6

El Código VHDL 3.9 describe una puerta NAND con un retardo inercial de 2 ns
y su banco de pruebas. Dibuje y explique la evolución de las señales in1, in2, s1,
s2, s3 y s4 durante los primeros 50 ns. A continuación, simule el banco de pruebas
y compare los resultados obtenidos con los que usted ha predicho.

237
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

--Puerta NAND con retardo inercial. Fichero: retardo_nand2.vhd


library IEEE; use IEEE. std_logic_1164. all;
entity nand2 is port
( yO : out std_logic;
xO, x1 : in std_logic);
end entity nand2;
architecture nand2 of nand2 is
begin
yO <= xO nand x1 after 2 ns; -- Retardo inercial de 2 ns
end architecture nand2;

-- Banco de pruebas de diferentes retardos. Fichero: bp_retardo_nand2.vhd


library IEEE; use IEEE.std_logic_1164.all;

entity retardo_bp is
end entity retardo_bp;

architecture retardo_bp of retardo_bp is


signal s1, s2, s3, s4 std_logic;
signal in1, in2 : std_logic;
component nand2 is port
( yO : out std_logic;
xO, x1 : in std_logic);
end component nand2;
begin
-- Instancia la UUT
gO : component nand2 port map (s1, in1, in2);
s2 <= in1 nand in2 after 2 ns; -- Misma forma de onda que s1
process is
variable var1, var2 : std_logic;
begin
for i in O to 4 loop -- Itera 5 veces
var1 := in1 nand in2;
var2 := var1; -- var2 debe ser igual a vaT1
s3 <= in1 nand in2;
s4 <= s3; -- s4 debe 8er igual al valor antiguo de 83
wait for 10 ns; -- Repetir para O, 1O, 20, 30 y 40 n8
end loop;
wait; -- D etiene este bloque proces8
end process;
-- Genera lo8 vectores de te8t
in1 <= '1';
in2 <= '0', -- in2 comienza a O
' 1 ' after 1O ns, ' O' after 11 ns, -- Pul8o de 1 n8 en el in8tante 1O n8
'1' after 20 ns, 'O' after 22 ns, -- Pulso de 2 ns en el instante 20 ns
'1' after 26 ns, 'O' after 29 ns; -- Pulso en el instante 26 ns
end architecture retardo_bp;

Código VHDL 3.9: Puerta NAND con retardo inercial y su banco de pruebas.

238
SIMULACIÓN DEL CÓDIGO VHDL

Ejercicio 3. 7

Dado el Código VHDL 3.10, indique los valores que toman las señales YO y
Y1 en los instantes de tiempo en que existen eventos en estas señales. Explique
razonadamente la evolución de cada una de las señales. A continuación, simule el
código VHDL y compare los resultados obtenidos con los que usted ha predicho.

library IEEE;
use IEEE. std_logic_1164. all;
entity codigoP is
end entity codigoP;
architecture codigoP of codigoP is
signa} YO: std_logic := '1';
signa} Y1: std_logic;
begin
Y1 <= YO after 10 ns;
process
begin
YO <= transport 'O' after 10 ns;
YO <= transport '1' after 20 ns;
YO <= transport '1' after 15 ns;
YO <= transport 'O' after 30 ns;
wait;
end process;
end architecture codigoP;

Código VHDL 3.10: Diseño del Ejercicio 3.7.

239
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

3.12. SOLUCIONES DE LOS EJERCICIOS

Solución al Ejercicio 3.1

En la Figura 3.5 se muestra el cronograma de las señales. En la tabla situada


debajo de la figura, se indica detalladamente la evolución de las señales .

• y1 X 11

.y2 o 11

.y3 u
.y4 u

1111111111111 d lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
~Q@ow 400 ns lS 50 ns 1 100 ns 150 ns 200 ns 250 ns 300 ns 350 ns 400 ns
~,0 l?§JJ.:J
Figura 3.5: Cronograma de las señales Yl, Y2, y3, Y4·

tiempo y1 y2 y3 y4
o 'U' 'U' 'U' 'U'
8 o o 'U' 'U'
50 ns 'X' o 'U' 'U'
100 ns 1 1 o o
200 ns 1 o 1 1
250 ns 1 1 1 1
300 ns 1 1 1 o
350 ns 1 1 1 1

Ninguna de las señales es inicializada al ser declarada. Por ello, su valor en t = O


es 'u'. En t = O se ejecutan las cuatro sentencias concurrentes. Dos sentencias
concurrentes asignan valor a la señal y1. Mientras las dos sentencias asignan el
mismo valor a la señal, no se produce conflicto. En caso de conflicto, se emplea la
función de resolución para resolverlo. Así, la señal y1 toma el valor 'X' entre los
instante 50 ns y 100 ns, debido a que durante ese intervalo de tiempo se asignan
simultáneamente dos valores diferentes a y1.

La señal y4 es la señal y2 desplazada 100 ns. Las señales y3 e y4 sólo se diferencian


en que la señal y3 no cambia su valor en el instante 300 ns como consecuencia del
cambio de valor en y2 en el instante 200 ns. Esto sucede porque el cambio en la señal
y2 se mantiene un tiempo inferior al tiempo de retardo inercial (100 ns).

240
SIMULACIÓN DEL CÓDIGO VHDL

Solución al Ejercicio 3.2

Al declarar las señales no se especifica su valor inicial. Por ello, las cinco señales
tienen en t =O el valor por defecto para std_logic, es decir, valen 'U'. En t =O, se
ejecutan las sentencias de asignación a las cinco señales. A continuación, se muestra el
resultado de la inicialización y el contenido de las colas de transacciones planificadas
para cada señal:

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


5 '1' 5 '1' 5 '0' 10 ns 'U' 20 ns 'U'
15 ns '0' 70 ns '1'
20 ns '1' 80 ns '0'
30 ns '0'
70 ns '1'
80 ns '0'

El reloj de la simulación salta al instante t = 5, en el cual se asigna el valor


planificado a las señales x1, x2, x3. El evento en esas señales hace que se ejecuten
las sentencias de asignación a las señales s, y. Los nuevos valores calculados para
esas señales son '1' y 'U', respectivamente, y se planifica asignar esos valores
en los instantes 10 y 20 ns, respectivamente. El resultado de la simulación y las
transacciones planificadas son las siguientes:

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
5 '1' '1' '0' 'U' 'U'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


15 ns '0' 70 ns '1' 10 ns '1' 20 ns 'U'
20 ns '1' 80 ns '0'
30 ns '0'
70 ns '1'
80 ns '0'

El reloj de la simulación salta hasta el instante t = 10 ns, en el cual se asigna a la


señal s el valor planificado. El evento en esta señal hace que se ejecute la sentencia de

241
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

asignación a y. El valor calculado se asignará a y en el instante 30 ns. Al introducir


este nuevo valor en la cola, se elimina la transición que estaba planificada para el
instante 20 ns (aplicación Regla 2.2). El resultado de la simulación y la cola de
transacciones son:

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
6 '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


15 ns '0' 70 ns '1' 30 ns '1'
20 ns '1' 80 ns '0'
30 ns '0'
70 ns '1'
80 ns '0'

El reloj de la simulación salta al instante t = 15 ns, en el cual se asigna a la señal


x1 el valor 'O' . El evento en x1 hace que se ejecute la sentencia de asignación a la
señal s. El valor calculado se asignará a la señal s en el instante 25 ns.

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
6 '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'
15 ns '0' '1' '0' '1' 'U'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


20 ns '1' 70 ns '1' 25 ns '0' 30 ns '1'
30 ns '0' 80 ns '0'
70 ns '1'
80 ns '0'

El reloj de la simulación avanza hasta t = 20 ns. Se asigna a x1 su nuevo valor.


El evento en la señal x1 hace que se ejecute la sentencia de asignación a la señal s,
calculándose un valor que se asignará a la señal en el instante 30 ns. La transacción
sobre s que estaba planificada para el instante 25 ns se elimina de la lista (aplicación
Regla 2.2).

242
SIMULACIÓN DEL CÓDIGO VHDL

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
o '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'
15 ns '0' '1' '0' '1' 'U'
20 ns '1' '1' '0' '1' 'U'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


30 ns '0' 70 ns '1' 30 ns '1' 30 ns '1'
70 ns '1' 80 ns '0'
80 ns '0'

El reloj de la simulación avanza hasta el instante t = 30 ns. Se asigna el nuevo


valor a las señales x1, y. Dado que el nuevo valor para s es igual al actual, no se
produce la transacción sobre la señal, eliminándose aquella de la cola. El evento en
x1 hace que se ejecute la sentencia de asignación a s. El nuevo valor se asignará a
la señal en el instante 40 ns.

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
o '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'
15 ns '0' '1' '0' '1' 'U'
20 ns '1' '1' '0' '1' 'U'
30 ns '0' '1' '0' '1' '1'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


70 ns '1' 70 ns '1' 40 ns '0'
80 ns '0' 80 ns '0'

El reloj de la simulación salta al instante t = 40 ns. Se asigna a la señal s su


nuevo valor. Este evento hace que se ejecute la sentencia de asignación a y. El valor
calculado se asignará a la señal y en el instante 60 ns.

243
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
o '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'
15 ns '0' '1' '0' '1' 'U'
20 ns '1' '1' '0' '1' 'U'
30 ns '0' '1' '0' '1' '1'
40 ns '0' '1' '0' '0' '1'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


70 ns '1' 70 ns '1' 60 ns '0'
80 ns '0' 80 ns '0'

El reloj de la simulación salta hasta el instante t = 60 ns, en el cual se asigna el


nuevo valor a la señal y.

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
o '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'
15 ns '0' '1' '0' '1' 'U'
20 ns '1' '1' '0' '1' 'U'
30 ns '0' '1' '0' '1' '1'
40 ns '0' '1' '0' '0' '1'
60 ns '0' '1' '0' '0' '0'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


70 ns '1' 70 ns '1'
80 ns '0' 80 ns '0'

El reloj de la simulación salta hasta el instante t = 70 ns, en el cual se asignan


los nuevos valores a x1, x3. Estos eventos provocan la ejecución de las sentencias de
asignación a s y y. Los valores calculados se asignarán a las señales en el instante
80 y 90 ns, respectivamente.

244
SIMULACIÓN DEL CÓDIGO VHDL

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
5 '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'
15 ns '0' '1' '0' '1' 'U'
20 ns '1' '1' '0' '1' 'U'
30 ns '0' '1' '0' '1' '1'
40 ns '0' '1' '0' '0' '1'
60 ns '0' '1' '0' '0' '0'
70 ns '1' '1' '1' '0' '0'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


80 ns '0' 80 ns '0' 80 ns '1' 90 ns '1'

El reloj de la simulación avanza hasta el instante t = 80 ns. Se asignan los nuevos


valores a las señales x1, x3, s. Estos eventos hacen que se ejecuten las sentencias de
asignación a s y a y. Se planifica asignar los valores calculados en los instantes 90
y 100 ns, respectivamente. Dado que el valor planificado para el instante 100 ns
que acaba de añadirse a la cola asociada a y tiene el mismo valor que el que había
anteriormente planificado para el instante 90 ns, éste último no es eliminado de la
cola (aplicación Regla 2.1).

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
5 '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'
15 ns '0' '1' '0' '1' 'U'
20 ns '1' '1' '0' '1' 'U'
30 ns '0' '1' '0' '1' '1'
40 ns '0' '1' '0' '0' '1'
60 ns '0' '1' '0' '0' '0'
70 ns '1' '1' '1' '0' '0'
80 ns '0' '1' '0' '1' '0'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


90 ns '0' 90 ns '1'
100 ns '1'

245
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

El reloj de la simulación avanza hasta el instante t = 90 ns. Se asignan los nuevos


valores a las señales s, y. El evento en s hace que se ejecute la sentencia de asignación
a y. El nuevo valor calculado para y es 'O' . Ese valor se asignará a la señal y en el
instante 110 ns. Al añadir ese valor a la cola de la señal se elimina la transacción
planificada para el instante 100 ns (aplicación Regla 2.2).

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
c5 '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'
15 ns '0' '1' '0' '1' 'U'
20 ns '1' '1' '0' '1' 'U'
30 ns '0' '1' '0' '1' '1'
40 ns '0' '1' '0' 'o' '1'
60 ns '0' '1' '0' 'o' '0'
70 ns '1' '1' '1' 'o' '0'
80 ns '0' '1' '0' '1' '0'
90 ns '0' '1' '0' 'o' '1'

tiempo x1 tiempo x2 tiempo x3 tiempo S tiempo y


110 ns '0'

El reloj de la simulación avanza hasta t = 110 y se le asigna a la señal y el nuevo


valor. El resultado de la simulación se muestra a continuación (véase también la
Figura 3.6).

tiempo x1 x2 x3 S y
o 'U' 'U' 'U' 'U' 'U'
c5 '1' '1' '0' 'U' 'U'
10 ns '1' '1' '0' '1' 'U'
15 ns '0' '1' '0' '1' 'U'
20 ns '1' '1' '0' '1' 'U'
30 ns '0' '1' '0' '1' '1'
40 ns '0' '1' '0' '0' '1'
60 ns '0' '1' '0' '0' '0'
70 ns '1' '1' '1' '0' '0'
80 ns '0' '1' '0' '1' '0'
90 ns '0' '1' '0' '0' '1'
110 ns '0' '1' '0' '0' '0'

246
SIMULACIÓN DEL CÓDIGO VHDL

+ x1 1 L
- 1---

+ x2 1
1---
+ x3 o
-
.y
+ s u
u
-
¡---

l
l!
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Clil0' Now l40 ns :l s 20 ns 40 ns 60 ns 80 ns 100 ns 12(
~,0 i!Óns]
Figura 3.6: Cronograma de las señales.

Solución al Ejercicio 3.3

Ninguna de las señales es inicializada al ser declarada. Por ello, su valor en el


instante t = O es 'u'. En t = O se ejecutan los bloques process del banco de pruebas
y del componente:

Se ejecutan las tres primeras sentencias del bloque process del banco de
pruebas y la ejecución queda suspendida en la sentencia wait. Los nuevos
valores se asignarán a las señales x1, x2 y x3 en el instante t = 6.

- Se ejecutan las tres sentencias del bloque process del componente. Obsérvese
que la primera y la tercera sentencia son asignaciones a una misma señal:
sig_s1. Cuando en el instante t se ejecuta la primera sentencia, se planifica
una transacción para la señal sig_s1 para el instante t + 6. Cuando en ese
mismo instante t se ejecuta la tercera sentencia, se planifica otra transacción
para la señal sig_s1 para el instante t + 6, anulándose la transacción que
se planificó para esa señal como resultado de ejecutar la primera sentencia
(aplicación Regla 1). El resultado es que la primera sentencia de asignación no
tiene ningún efecto. Es decir, al ejecutar el bloque process en el instante t, se
planifica asignar en el instante en t + 6 a la señal sig_s1 el valor que tenga la
señal X2 en el instante t. En este caso t vale cero, pero la discusión anterior es
válida para cualquier instante t.

A continuación se muestra el resultado de la simulación en t = O y la cola de


transacciones planificadas para cada señal.

247
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

tiempo x1 x2 x3 Y1 sig_s1
o 'U' 'U' 'U' 'U' 'U'

tiempo x1 tiempo x2 tiempo x3 tiempo Y1 tiempo sig_s1


6 '0' 6 '0' 6 '1' 6 'U' 6 'U'

El reloj de la simulación avanza hasta el instante t = 6. Se asignan los nuevos


valores a las señales x1, x2, x3. Los nuevos valores planificados para Y1, sig_s1 no
cambian el valor de las señales, con lo cual no se asignan los nuevos valores.

Los eventos en las señales x1, x2, x3 hacen que se ejecute el bloque process del
componente, calculándose nuevos valores para las señales Y1, sig_s1. El nuevo valor
de sig_s1 es igual al valor de x2, que es 'O'. El nuevo valor de Y1 es el resultado
de la operación XOR de los valores actuales de sig_s1 y X3, es decir, 'U' XOR '1',
que es 'U' . Estos nuevos valores se asignarán a las señales en el instante t = 26. El
resultado de la simulación y las colas de transacciones planificadas son:

tiempo x1 x2 x3 Y1 sig_s1
o 'U' 'U' 'U' 'U' 'U'
6 '0' '0' '1' 'U' 'U'

tiempo x1 tiempo x2 tiempo x3 tiempo Y1 tiempo sig_s1


26 'U' 26 '0'

El reloj de la simulación avanza hasta el instante t = 26, en el cual se asignan


los nuevos valores a las señales Y1, sig_s1. El resultado de la simulación y las colas
de transacciones planificadas son:

tiempo x1 x2 x3 Y1 sig_s1
o 'U' 'U' 'U' 'U' 'U'
6 '0' '0' '1' 'U' 'U'
26 '0' '0' '1' 'U' '0'

tiempo x1 tiempo x2 tiempo x3 tiempo Y1 tiempo sig_s1

El reloj de la simulación avanza hasta el instante t = 100 ns, ya que en ese instante
se reanuda la ejecución del bloque process del banco de pruebas. Se ejecutan las

248
SIMULACIÓN DEL CÓDIGO VHDL

tres sentencias de asignación a las señales x1, x2, x3, y se suspende la ejecución
del bloque al ejecutarse la sentencia wait. Los nuevos valores se planifican para
el instante t = 100 + 6. El resultado de la simulación y las colas de transacciones
planificadas son:

tiempo x1 x2 x3 Y1 sig_s1
o 'U' 'U' 'U' 'U' 'U'
6 '0' '0' '1' 'U' 'U'
26 '0' '0' '1' 'U' '0'

tiempo x1 tiempo x2 tiempo x3 tiempo Y1 tiempo sig_s1


100 ns+6 '0' 100 ns+6 '1' 100 ns+6 '1'

Obsérvese que en la tabla que muestra el resultado de la simulación no se ha


añadido una fila correspondiente al instante t = 100 ns. Esto es debido a que en el
instante t = 100 ns todas las señales tienen el mismo valor que en el instante t = 26.

El reloj de la simulación avanza al instante t = 100 ns +6. Se asigna el nuevo


valor a la señal x2. Obsérvese que los nuevos valores de las señales x 1, x3 no hacen
que cambie el valor de las mismas, por ello no se realizan las asignaciones.

El evento en la señal x2 hace que se ejecute el bloque process del componente.


Se ejecutan las sentencias del bloque, calculándose los nuevos valores de las señales
Y1, sig_s1 , que se planifican para el instante t = 100 ns +25.

tiempo x1 x2 x3 Y1 sig_s1
o 'U' 'U' 'U' 'U' 'U'
6 '0' '0' '1' 'U' 'U'
26 '0' '0' '1' 'U' '0'
100 ns+6 '0' '1' '1' 'U' '0'

tiempo x1 tiempo x2 tiempo x3 tiempo Y1 tiempo sig_s1


100 ns+26 '1' 100 ns+26 '1'

El reloj de la simulación avanza hasta el instante t = 100 ns +26, en el cual se


asignan los nuevos valores a las señales Y1, sig_s 1. El resultado de la simulación
hasta este instante y las colas de transacciones planificadas para cada señal son:

249
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

tiempo x1 x2 x3 Y1 sig_s1
o 'U' 'U' 'U' 'U' 'U'
5 '0' '0' '1' 'U' 'U'
25 '0' '0' '1' 'U' '0'
100 ns+5 '0' '1' '1' 'U' '0'
100 ns+25 '0' '1' '1' '1' '1'

tiempo x1 tiempo x2 tiempo x3 tiempo Y1 tiempo sig_s1

El reloj de la simulación avanza hasta el instante t = 200 ns, en el cual se reanuda


la ejecución del bloque process del banco de pruebas. Se ejecutan las sentencias que
calculan los nuevos valores de x1, x2, x3. Estos nuevos valores de asignan en t = 200
ns + 5. Estos eventos hacen que se ejecute el bloque process del componente,
asignándose en t = 200 ns + 25 los nuevos valores a las señales Y1, sig_s1, y
así sucesivamente. El resultado completo de la simulación se muestra en la tabla
siguiente y el cronograma de las señales en la Figura 3.7.

tiempo x1 x2 x3 Y1 sig_s1
o 'U' 'U' 'U' 'U' 'U'
5 '0' '0' '1' 'U' 'U'
25 '0' '0' '1' 'U' '0'
100 ns+5 '0' '1' '1' 'U' 'o'
100 ns+25 '0' '1' '1' '1' '1'
200 ns+5 '1' '0' '0' '1' '1'
200 ns+25 '1' '0' '0' '1' 'o'
300 ns+5 '1' '1' '0' '1' '0'
300 ns+25 '1' '1' '0' '0' '1'
400 ns+5 '0' '1' '0' '0' '1'
400 ns+25 '0' '1' '0' '1' '1'
500 ns+5 '1' '0' '1' '1' '1'
500 ns+25 '1' '0' '1' '0' '0'

250
SIMULACIÓN DEL CÓDIGO VHDL

+ jbp_codigo1/uut¡)(1 o
+ ¡bp_codigo1/uut,(.l(2 o
+ ¡bp_codigo1/uut¡)(3 1
+ jbp_codigo1/uutjY1 u
+ jbp_codigo1/uutjsig_sl o

d d d 11

1
11111111 lllllllttlttllllltllttllllll lllllllltlttlllllltlttllllll llllllltllttllllltllttllllll llllllltllttlllllltlttll
Now 600 ns S 100 ns 200 ns 300 ns 400ns 500 ns 600 ns
Cursor 1 O ns O nsl

Figura 3. 7: Cronograma de las señales.

Solución al Ejercicio 3.4

Ninguna de las señales es inicializada al ser declarada. Por ello, su valor en el


instante t = O es 'U'. En t = O se ejecutan los bloques process del banco de pruebas
y del componente:

Se ejecutan las tres primeras sentencias del bloque process del banco de
pruebas y la ejecución queda suspendida en la sentencia wait. Los nuevos
valores se asignarán a las señales X1, X2, X3 en el instante t = fJ.

Se ejecutan las tres sentencias del bloque process del componente. Cuando
se ejecuta el bloque process en el instante t, en primer lugar se asigna a la
variable var_s1 el valor que tiene la señal X1 en el instante t. A continuación,
se calcula el nuevo valor de la señal Y2, que es el resultado de la operación
XOR entre el valor de la variable var_s1 y el valor de la señal X3. Dado que el
valor de la variable var_s1 es igual al valor de la señal X1, el nuevo valor de la
señal Y2 es el resultado de la operación XOR entre los valores que tienen las
señales X1 y X3 en el instante t. El nuevo valor se asignará a la señal Y2 en el
instante t + fJ. La tercera sentencia asigna un nuevo valor a la variable var _s 1.
Este nuevo valor de var_s1 no influye en la señal Y2.

A continuación, se muestra el resultado de la simulación en t = O y la cola de


transacciones planificadas para cada señal.

tiempo X1 X2 X3 Y2
o 'U' 'U' 'U' 'U'

tiempo X1 tiempo X2 tiempo X3 tiempo Y2


fJ '0' fJ '0' fJ '1' fJ 'U'

251
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

El reloj de la simulación avanza hasta el instante t = 5. Se asignan los nuevos


valores a las señales X1, X2, X3. El nuevo valor planificado para Y2 no cambia el valor
de la señal, con lo cual no se asigna el nuevo valor.

Los eventos en las señales X1, X2, X3 hacen que se ejecute el bloque process del
componente. El nuevo valor de la señal Y2 es el resultado de la operación XOR entre
el valor de X1 y el de X3. Se planifica la transacción para el instante t = 25.

tiempo X1 X2 X3 Y2
o 'U' 'U' 'U' 'U'
5 '0' '0' '1' 'U'

tiempo X1 tiempo X2 tiempo X3 tiempo Y2


25 '1'

El reloj de la simulación avanza hasta el instante t = 25, en el cual se asigna


el nuevo valor a la señal Y2. El resultado de la simulación y las transacciones
planificadas se muestran a continuación:

tiempo X1 X2 X3 Y2
o 'U' 'U' 'U' 'U'
5 '0' '0' '1' 'U'
25 '0' '0' '1' '1'

1 tiempo 1 X1 11 tiempo 1 X211 tiempo 1 X311 tiempo 1 Y21

El reloj de la simulación avanza hasta el instante t = 100 ns, en el cual se


reanuda la ejecución del bloque process del banco de pruebas. Se ejecutan las tres
sentencias de dicho bloque process y se suspende de nuevo la ejecución al alcanzarse
la sentencia wait. Se planifica asignar los nuevos valores de las señales X1, X2 y X3
en el instante t = 100 ns + 5.

tiempo X1 X2 X3 Y2
o 'U' 'U' 'U' 'U'
5 '0' '0' '1' 'U'
25 '0' '0' '1' '1'

252
SIMULACIÓN DEL CÓDIGO VHDL

tiempo X1 tiempo X2 tiempo X3 tiempo Y2


100 ns +o '0' 100 ns +O '1' 100 ns +o '1'

El reloj de la simulación avanza hasta el instante t = 100 ns + o, en el cual se


asigna el nuevo valor a la señal X2. El valor de las otras dos señales no cambia. El
evento hace que se ejecute el bloque process del componente. Se calcula el nuevo
valor de la señal Y2 y se planifica asignar dicho valor a la señal.

tiempo X1 X2 X3 Y2
o 'U' 'U' 'U' 'U'
o '0' '0' '1' 'U'
20 '0' '0' '1' '1'
100 ns +o '0' '1' '1' '1'

tiempo X1 tiempo X2 tiempo X3 tiempo Y2


100 ns + 2o '1'

El reloj de la simulación avanza hasta el instante t = 100 ns + 20. Dado que el


nuevo valor de la señal Y2 es igual al actual, no se produce la transacción.

El reloj de la simulación avanza hasta el instante t = 200 ns, en el cual se reanuda


la ejecución del bloque process del banco de pruebas. Se calculan los nuevos valores
de las señales X1, X2, X3, que se asignarán en el instante t = 200 ns + o. En ese
instante, se ejecutará el bloque process del componente, calculándose el nuevo valor
de la señal Y2, el cual se asignará a la señal en el instante t = 200 ns + 20, en caso
de ser el nuevo valor diferente del valor que ya tuviera la señal. Así sucesivamente.

A continuación se muestra el resultado de la simulación y en la Figura 3.8 el


cronograma de las señales.

tiempo X1 X2 X3 Y2
o 'U' 'U' 'U' 'U'
o '0' '0' '1' 'U'
20 '0' '0' '1' '1'
100 ns +o '0' '1' '1' '1'
200 ns +o '1' '0' '0' '1'
300 ns +o '1' '1' '0' '1'
400 ns +o '0' '1' '0' '1'
400 ns + 20 '0' '1' '0' '0'
500 ns +o '1' '0' '1' '0'

253
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

¡... Msgs

+ ¡bp_codigo2/X1 1
+ ¡bp_codigo2/X2 o
+ ¡bp_codigo2/X3 1
+ ¡bp_codigo2/Y2 o
1 1 1 1 1 1
1~:1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1- 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
iO Now 700 ns s 100 ns 200 ns 300 ns 400 ns 500 ns 600
;o Cursor 1 O ns llo nsJ
Figura 3.8: Cronograma de las señales.

Solución al Ejercicio 3.5

Dado que ninguna de las señales ha sido inicializada al ser declarada, todas las
señales valen 'U' en t = O. En t = O se ejecutan todos los bloques process. Se
planifica asignar los nuevos valores a las señales en el instante t = o. El resultado de
la simulación en t = O y las transacciones planificadas son las siguientes:

tiempo a b e s1 s2 s3 d
o 'U' 'U' 'U' 'U' 'U' 'U' 'U'

t a t b t e t s1 t s2 t s3 t d
o '1' o '1' o '0' o 'U' o 'U' o 'U' o 'U'

El reloj de la simulación avanza hasta el instante t = en el cual se asignan o,


los nuevos valores a las señales a, b, c. Los nuevos valores de las demás señales son
iguales a los valores que ya tienen, con lo cual esas transacciones no se producen. Los
eventos en a, b, e hacen que se ejecuten los bloques process p1, p2, calculándose
nuevos valores para las señales s1, s2, los cuales se asignarán a las señales en el
instante 2o.

tiempo a b e s1 s2 s3 d
o 'U' 'U' 'U' 'U' 'U' 'U' 'U'
o '1' '1' '0' 'U' 'U' 'U' 'U'

El reloj de la simulación avanza hasta el instante t = 2o, en el cual se asignan


los nuevos valores a las señales s1, s2. Los eventos en estas señales hacen que se

254
SIMULACIÓN DEL CÓDIGO VHDL

ejecute el bloque process p3. El nuevo valor calculado para la señal s3 se asignará
a la misma en el instante t = 35.

tiempo a b e si s2 s3 d
o 'U' 'U' 'U' 'U' 'U' 'U' 'U'
5 'i' 'i' '0' 'U' 'U' 'U' 'U'
25 'i' 'i' '0' 'i' 'i' 'U' 'U'

1 2
03
1 t 1 a 11 t 1 b 11 t 1 e 11 t 1 s 11 t 1 s 11
3; 1 ," ' 11 t 1 d 1

El reloj de la simulación avanza hasta el instante t = 35, en el cual se asigna


el nuevo valor a la señal s3. El evento en esta señal hace que se ejecute el bloque
process p4. El nuevo valor calculado para la señal d se asignará a la señal en el
instante 45.

tiempo a b e si s2 s3 d
o 'U' 'U' 'U' 'U' 'U' 'U' 'U'
5 'i' 'i' '0' 'U' 'U' 'U' 'U'
25 'i' 'i' '0' 'i' 'i' 'U' 'U'
35 'i' 'i' '0' 'i' 'i' '0' 'U'

'~'
1 2 3
1 t 1 a 11 t 1 b 11 t 1 e 11 t 1 s 11 t 1 s 11 t 1 s 11 4; 1 1

El reloj de la simulación avanza hasta el instante t = 45, en el cual se asigna


el nuevo valor a la señal d. Este evento no hace que se planifique ninguna otra
transacción, finalizando la simulación. El resultado de la simulación es el siguiente:

tiempo a b e si s2 s3 d
o 'U' 'U' 'U' 'U' 'U' 'U' 'U'
5 'i' 'i' '0' 'U' 'U' 'U' 'U'
25 'i' 'i' '0' 'i' 'i' 'U' 'U'
35 'i' 'i' '0' 'i' 'i' '0' 'U'
45 'i' 'i' '0' 'i' 'i' '0' 'i'

El Código VHDL 3.8 muestra el banco de pruebas que hay que simular para
obtener la evolución temporal de las señales. Una vez activada la simulación del
banco de pruebas usando el simulador ModelSim, para poder obtener los valores de
las señales en los instantes de tiempo O, 5, 25, 35 y 45 hay que seguir los siguientes
pasos:

255
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

l. Añadir la ventana "List". Para ello seleccionamos la opción "List" del menú
"View". La ventana "List" muestra, en modo texto, los valores de las señales en
el tiempo en un formato tabular. La opción "List preferences ... " del menú "List"
nos permite configurar las propiedades de dicha ventana. Para poder obtener
el valor de las señales teniendo en cuenta los retardos 6 hay que configurar las
opciones de la ventana "List", tal como se muestra en la Figura 3.9.

2. Añadir a la ventana "List" las señales del diseño. Para ello, hay que seleccionar
las señales de la ventana "Objects" (véase la Figura 3.10).

3. Realizar la simulación del banco de pruebas. En la Figura 3.10 se muestran


los valores obtenidos tras realizar la simulación. Los valores de las señales se
muestran en una tabla que tiene 5 filas, una fila por cada instante de tiempo, y
7 columnas, una columna por cada señal. Las columnas de izquierda a derecha
se corresponden respectivamente con las señales d, a, b, e, s_1, s_2 y s_3. Las
filas, de arriba a abajo, se corresponden con los instantes de tiempo O, 8, 28,
36 y 48.

256
SIMULACIÓN DEL CÓDIGO VHDL

lli ~" ...


'l&l
'•

[TI] IY\oof y Display Propi{rtfes (list)

Window Properties Triggers J _ilij

~Deltas:
G: Expand Deltas C Collapse Deltas O No Deltas
1

,..---Trigger On:

M Signa! Change Strobe Period: lo ns

rJ Strobe First Strobe at: lo ns

- Trigger Gating:

[J Use Gating Expression Use Expression Builder 1

Expression: 1

On Duration: lo ns

OK 1 Cancel 1 8J:tply 1

Figura 3.9: Propiedades de la ventana "List" del simulador ModelSim.

Name
ns.,.. /bp_deltas/uut/ ct.,.. /bp_deltas/uut/s2.,..
+a delta.,.. /bp_deltas/uut/ a.,.. /bp_deltas/uut/s3.,..
+b /bp_deltas/uut/b.,..
+e /bp_deltas/uut/c.,..
+d /bp_deltas/uut/s1.,..
+s i O +O u u u u u ~ u +----o
+ s2 o +1 u 1 1 o u u u +----o
+s3 o +2 u 1 1 o 1 1 u +---- 28
o +3 u 1 1 o 1 1 o +---- 38
View Declaration
Vie1N r.1emory Contents
o +4 1 1 1 o 1 1 o +---- 48
View Messages

Copy
Find ...

Insert Breakpoint
Add to Wave
Selected Signals
Add to Log Signals in Region
Add to Dataflow
Toggle Coverage

Figura 3.10: Ventana "List" del simulador ModelSim.

257
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 3.6

Ninguna de las señales ha sido inicializada al ser declarada, por ello valen 'u' en
t = O. Asimismo, en t = O se ejecutan las sentencias concurrentes, calculándose el
nuevo valor de las señales s1, s2, in1, in2, y se ejecuta el bloque process. Se ejecuta
la primera iteración del bucle for que hay dentro del bloque process, quedando la
ejecución suspendida en la sentencia wait. Con ello, se calcula el nuevo valor de
las señales s3, s4. Se planifica asignar los nuevos valores a las señales en el instante
t = 6. El resultado de la simulación en t = O y las transacciones planificadas son las
siguientes:

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'

t in1 t in2 t s1 t s2 t s3 t s4
6 '1' 6 '0' 6 'U' 6 'U' 6 'U' 6 'U'
10 ns '1'
11 ns '0'
20 ns '1'
22 ns '0'
26 ns '1'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 6, en el cual se asignan los


nuevos valores a las señales in1, in2. Los nuevos valores de las demás señales son
iguales a los valores que ya tienen las señales, con lo cual esas transacciones no se
producen.

Los eventos en in1, in2 hacen que se ejecuten las sentencias concurrentes para el
cálculo de los nuevos valores de s1, s2. Dado que estas sentencias tienen un retardo
inercial de 2 ns, los nuevos valores se asignarán a s1, s2 en el instante t = 2 ns.

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
6 '1' '0' 'U' 'U' 'U' 'U'

258
SIMULACIÓN DEL CÓDIGO VHDL

t in1 t in2 t s1 t s2 t s3 t s4
10 ns '1' 2 ns '1' 2 ns '1'
11 ns '0'
20 ns '1'
22 ns '0'
26 ns '1'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 2 ns, en el cual se asignan


los nuevos valores a las señales s 1, s2.

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'

t in1 t in2 t s1 t s2 t s3 t s4
10 ns '1'
11 ns '0'
20 ns '1'
22 ns '0'
26 ns '1'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 10 ns, en el cual se asigna un


nuevo valor a la señal in2 y se reanuda la ejecución del bloque process. Se ejecutan
las cuatro primeras sentencias que hay dentro del cuerpo del bucle for y se suspende
la ejecución del bloque al llegar a la sentencia wait. Los nuevos valores calculados
para las señales s3, s4 se asignarán en el instante t = 10 ns + 5. Asimismo, el evento
en la señal in2 hace que se ejecuten las sentencias que calculan el nuevo valor para
las señales s1, s2. Estos nuevos valores se asignarán a las señales s1, s2 en el instante
t = 12 ns.

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'
10 ns '1' '1' '1' '1' 'U' 'U'

259
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

t in1 t in2 t s1 t s2 t s3 t s4
11 ns '0' 12 ns '0' 12 ns '0' 10 ns +5 '0' 10 ns +5 'U'
20 ns '1'
22 ns '0'
26 ns '1'
29 ns '0'

El reloj de la simulación avanza hasta el instante 10 ns + 5, en el cual se asigna el


nuevo valor a la señal s3. Como el nuevo valor de s4 es igual al actual, no se asigna
el nuevo valor a esa señal.

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'
10 ns '1' '1' '1' '1' 'U' 'U'
10 ns + 5 '1' '1' '1' '1' '0' 'U'

t in1 t in2 t s1 t s2 t s3 t s4
11 ns '0' 12 ns '0' 12 ns '0'
20 ns '1'
22 ns '0'
26 ns '1'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 11 ns, en el cual se asigna el


nuevo valor a la señal in2. El evento en in2 hace que se ejecuten las sentencias para
el cálculo del nuevo valor de las señales s1, s2. El nuevo valor calculado para estas
señales es '1', el cual será asignado con un retardo de 2 ns, es decir, en el instante
13 ns. Al añadir a la cola estas nuevas transacciones, se eliminan las que estaban
planificadas para el instante 12 ns (aplicación Regla 2.2).

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'
10 ns '1' '1' '1' '1' 'U' 'U'
10 ns + 5 '1' '1' '1' '1' '0' 'U'
11 ns '1' '0' '1' '1' '0' 'U'

260
SIMULACIÓN DEL CÓDIGO VHDL

t in1 t in2 t s1 t s2 t s3 t s4
20 ns '1' 13 ns '1' 13 ns '1'
22 ns '0'
26 ns '1'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 13 ns, en el cual está


planificado asignar los nuevos valores a las señales s1 , s2. Sin embargo, dado que los
nuevos valores son iguales a los actuales, no se produce la transacción.

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
c5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'
10 ns '1' '1' '1' '1' 'U' 'U'
10 ns + c5 '1' '1' '1' '1' '0' 'U'
11 ns '1' '0' '1' '1' '0' 'U'

t in1 t in2 t s1 t s2 t s3 t s4
20 ns '1'
22 ns '0'
26 ns '1'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 20 ns, en el cual se asigna


el nuevo valor a la señal in2 y se reanuda la ejecución del bloque process, que se
suspende de nuevo al llegar a la sentencia wait. Los nuevos valores calculados para
las señales s3, s4 se asignarán en el instante t = 20 ns + 6.

Asimismo, el evento en in2 hace que se ejecuten las sentencias que calculan el
nuevo valor de las señales s1, s2. Los nuevos valores se asignaran a estas señales en
el instante t = 22 ns.

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
c5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'
10 ns '1' '1' '1' '1' 'U' 'U'
10 ns + c5 '1' '1' '1' '1' '0' 'U'
11 ns '1' '0' '1' '1' '0' 'U'
20 ns '1' '1' '1' '1' '0' 'U'

261
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

t ini t in2 t si t s2 t s3 t s4
22 ns '0' 22 ns '0' 22 ns '0' 20 ns +o '0' 20 ns +o '0'
26 ns 'i'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 20 ns + o, en el cual se


asigna el nuevo valor a la señal s4. No se produce transacción en la señal s3 ya que
el valor nuevo y el actual son iguales.

tiempo ini in2 si s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
o 'i' '0' 'U' 'U' 'U' 'U'
2 ns 'i' '0' 'i' 'i' 'U' 'U'
10 ns 'i' 'i' 'i' 'i' 'U' 'U'
10 ns +o 'i' 'i' 'i' 'i' '0' 'U'
11 ns 'i' '0' 'i' 'i' '0' 'U'
20 ns 'i' 'i' 'i' 'i' '0' 'U'
20 ns +o 'i' 'i' 'i' 'i' '0' '0'

t ini t in2 t si t s2 t s3 t s4
22 ns '0' 22 ns '0' 22 ns '0'
26 ns 'i'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 22 ns, en el cual se asignan


los nuevos valores a las señales in2, si, s2. El evento en in2 hace que se ejecuten las
sentencias que calculan los nuevos valores de las señales si, s2. Estos nuevos valores
se asignarán a las señales en el instante t = 24 ns.

tiempo ini in2 si s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
o 'i' '0' 'U' 'U' 'U' 'U'
2 ns 'i' '0' 'i' 'i' 'U' 'U'
10 ns 'i' 'i' 'i' 'i' 'U' 'U'
10 ns +o 'i' 'i' 'i' 'i' '0' 'U'
11 ns 'i' '0' 'i' 'i' '0' 'U'
20 ns 'i' 'i' 'i' 'i' '0' 'U'
20 ns +o 'i' 'i' 'i' 'i' '0' '0'
22 ns 'i' '0' '0' '0' '0' '0'

262
SIMULACIÓN DEL CÓDIGO VHDL

t in1 t in2 t s1 t s2 t s3 t s4
26 ns '1' 24 ns '1' 24 ns '1'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 24 ns, en el cual se asignan


los nuevos valores a las señales s1, s2.

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'
10 ns '1' '1' '1' '1' 'U' 'U'
10 ns + 5 '1' '1' '1' '1' '0' 'U'
11 ns '1' '0' '1' '1' '0' 'U'
20 ns '1' '1' '1' '1' '0' 'U'
20 ns + 5 '1' '1' '1' '1' '0' '0'
22 ns '1' '0' '0' '0' 'o' '0'
24 ns '1' '0' '1' '1' '0' '0'

t in1 t in2 t s1 t s2 t s3 t s4
26 ns '1'
29 ns '0'

El reloj de la simulación avanza hasta el instante t = 26 ns, en el cual se asigna


el nuevo valor a la señal in2. El evento en la señal in2 hace que se ejecuten las
sentencias que calculan los nuevos valores de las señales s1, s2. Estos nuevos valores
se asignarán a las señales s1, s2 en el instante t = 28 ns.

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'
10 ns '1' '1' '1' '1' 'U' 'U'
10 ns + 5 '1' '1' '1' '1' '0' 'U'
11 ns '1' '0' '1' '1' '0' 'U'
20 ns '1' '1' '1' '1' '0' 'U'
20 ns + 5 '1' '1' '1' '1' '0' '0'
22 ns '1' '0' '0' '0' '0' '0'
24 ns '1' '0' '1' '1' '0' '0'
26 ns '1' '1' '1' '1' '0' '0'

263
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

t ini t in2 t si t s2 t s3 t s4
29 ns '0' 28 ns '0' 28 ns '0'

El reloj de la simulación avanza hasta el instante t = 28 ns, en el cual se asignan


los nuevos valores a las señales si, s2.

tiempo ini in2 si s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
8 'i' '0' 'U' 'U' 'U' 'U'
2 ns 'i' '0' 'i' 'i' 'U' 'U'
10 ns 'i' 'i' 'i' 'i' 'U' 'U'
10 ns + 8 'i' 'i' 'i' 'i' '0' 'U'
11 ns 'i' '0' 'i' 'i' '0' 'U'
20 ns 'i' 'i' 'i' 'i' '0' 'U'
20 ns + 8 'i' 'i' 'i' 'i' '0' '0'
22 ns 'i' '0' '0' '0' '0' '0'
24 ns 'i' '0' 'i' 'i' '0' '0'
26 ns 'i' 'i' 'i' 'i' '0' '0'
28 ns 'i' 'i' '0' '0' '0' '0'

n: ~~~
81 82 83 84
1 t 1 ini 11 29 1 11 t 1 11 t 1 11 t 1 11 t 1 1

El reloj de la simulación avanza hasta el instante t = 29 ns, en el cual se asigna


el nuevo valor a la señal in2. El evento en in2 hace que se ejecuten las sentencias
que calculan los nuevos valores de si, s2. Estos nuevos valores se asignarán en el
instante t = 31 ns.

264
SIMULACIÓN DEL CÓDIGO VHDL

tiempo ini in2 si s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
t5 'i' '0' 'U' 'U' 'U' 'U'
2 ns 'i' '0' 'i' 'i' 'U' 'U'
10 ns 'i' 'i' 'i' 'i' 'u' 'U'
10 ns + t5 'i' 'i' 'i' 'i' '0' 'U'
11 ns 'i' '0' 'i' 'i' '0' 'U'
20 ns 'i' 'i' 'i' 'i' '0' 'U'
20 ns + t5 'i' 'i' 'i' 'i' '0' '0'
22 ns 'i' '0' '0' '0' '0' '0'
24 ns 'i' '0' 'i' 'i' '0' '0'
26 ns 'i' 'i' 'i' 'i' 'o' '0'
28 ns 'i' 'i' '0' '0' '0' '0'
29 ns 'i' '0' '0' '0' '0' '0'

t ini t in2 t si t s2 t s3 t s4
31 ns 'i' 31 ns 'i'

El reloj de la simulación avanza hasta el instante t = 30 ns, dado que en ese


instante se reanuda la ejecución del bloque process. Se calculan los nuevos valores
de las señales s3, s4, y se suspende la ejecución del bloque al llegar a la sentencia
wait. Los nuevos valores de s3, s4 se asignarán a las señales en el instante t = 30
ns + 6.

tiempo ini in2 si s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
t5 'i' '0' 'U' 'U' 'U' 'U'
2 ns 'i' '0' 'i' 'i' 'U' 'U'
10 ns 'i' 'i' 'i' 'i' 'U' 'U'
10 ns + t5 'i' 'i' 'i' 'i' '0' 'U'
11 ns 'i' '0' 'i' 'i' '0' 'U'
20 ns 'i' 'i' 'i' 'i' '0' 'U'
20 ns + t5 'i' 'i' 'i' 'i' '0' '0'
22 ns 'i' '0' '0' '0' '0' '0'
24 ns 'i' '0' 'i' 'i' '0' '0'
26 ns 'i' 'i' 'i' 'i' '0' '0'
28 ns 'i' 'i' '0' '0' '0' '0'
29 ns 'i' '0' '0' '0' '0' '0'

265
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

t ini t in2 t si t s2 t s3 t s4
31 ns 'i' 31 ns 'i' 30 ns +o 'i' 30 ns + o 'o'

El reloj de la simulación avanza hasta el instante t = 30 ns + o, en el cual se


asignan el nuevo valor a la señal s3. El nuevo valor de s4 es igual al actual, por ello
no se asigna el nuevo valor a esa señal.

tiempo ini in2 si s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
o 'i' '0' 'U' 'U' 'U' 'U'
2 ns 'i' '0' 'i' 'i' 'U' 'U'
10 ns 'i' 'i' 'i' 'i' 'U' 'U'
10 ns + o 'i' 'i' 'i' 'i' '0' 'U'
11 ns 'i' '0' 'i' 'i' '0' 'U'
20 ns 'i' 'i' 'i' ./ i' '0' 'U'
20 ns + o 'i' 'i' 'i' 'i' '0' '0'
22 ns 'i' '0' '0' '0' '0' '0'
24 ns 'i' '0' 'i' 'i' '0' '0'
26 ns 'i' 'i' 'i' 'i' '0' '0'
28 ns 'i' 'i' '0' '0' '0' '0'
29 ns 'i' '0' '0' '0' '0' '0'
30 ns + o 'i' '0' '0' '0' 'i' '0'

t ini t in2 t si t s2 t s3 t s4
31 ns 'i' 31 ns 'i'

El reloj de la simulación avanza hasta el instante t = 31 ns, en el cual se asignan


los nuevos valores a las señales si, s2.

266
SIMULACIÓN DEL CÓDIGO VHDL

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'
10 ns '1' '1' '1' '1' 'U' 'U'
10 ns + 5 '1' '1' '1' '1' '0' 'U'
11 ns '1' '0' '1' '1' '0' 'U'
20 ns '1' '1' '1' '1' '0' 'U'
20 ns + 5 '1' '1' '1' '1' '0' '0'
22 ns '1' '0' '0' '0' '0' '0'
24 ns '1' '0' '1' '1' '0' '0'
26 ns '1' '1' '1' '1' '0' '0'
28 ns '1' '1' '0' '0' '0' '0'
29 ns '1' '0' '0' '0' '0' '0'
30 ns + 5 '1' '0' '0' '0' '1' '0'
31 ns '1' '0' '1' '1' '1' '0'

1t 1in1 11 t 1in211 t 1si 1 t 1s211 t 1s311 t 1s41

El reloj de la simulación avanza hasta el instante t = 40 ns, en el cual se reanuda


la ejecución del bloque process. Los nuevos valores calculados para las señales s3,
s4 se asignarán en el instante t = 40 ns + 5.

tiempo in1 in2 s1 s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
5 '1' '0' 'U' 'U' 'U' 'U'
2 ns '1' '0' '1' '1' 'U' 'U'
10 ns '1' '1' '1' '1' 'U' 'U'
10 ns + 5 '1' '1' '1' '1' '0' 'U'
11 ns '1' '0' '1' '1' '0' 'U'
20 ns '1' '1' '1' '1' '0' 'U'
20 ns + 5 '1' '1' '1' '1' '0' '0'
22 ns '1' '0' '0' '0' '0' '0'
24 ns '1' '0' '1' '1' '0' '0'
26 ns '1' '1' '1' '1' '0' '0'
28 ns '1' '1' '0' '0' '0' '0'
29 ns '1' '0' '0' '0' '0' '0'
30 ns + 5 '1' '0' '0' '0' '1' '0'
31 ns '1' '0' '1' '1' '1' '0'

267
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

t ini t in2 t si t s2 t s3 t s4
40 ns +5 'i' 40 ns +o 'i'

El reloj de la simulación avanza hasta el instante t = 40 ns + o, en el cual se


asigna el nuevo valor a las señal s4. El nuevo valor de la señal s4 es igual al actual,
con lo cual no se asigna el nuevo valor. En la tabla siguiente se muestra el resultado
de la simulación. El cronograma está representado en la Figura 3.11.

tiempo ini in2 si s2 s3 s4


o 'U' 'U' 'U' 'U' 'U' 'U'
o 'i' '0' 'U' 'U' 'U' 'U'
2 ns 'i' '0' 'i' 'i' 'U' 'U'
10 ns 'i' 'i' 'i' 'i' 'U' 'U'
10 ns +o 'i' 'i' 'i' 'i' '0' 'U'
11 ns 'i' '0' 'i' 'i' '0' 'U'
20 ns 'i' 'i' 'i' 'i' '0' 'U'
20 ns +o 'i' 'i' 'i' 'i' '0' '0'
22 ns 'i' '0' '0' '0' '0' '0'
24 ns 'i' '0' 'i' 'i' '0' '0'
26 ns 'i' 'i' 'i' 'i' '0' '0'
28 ns 'i' 'i' '0' '0' '0' '0'
29 ns 'i' '0' '0' '0' '0' '0'
30 ns +O 'i' '0' '0' '0' 'i' '0'
31 ns 'i' '0' 'i' 'i' 'i' '0'
40 ns +o 'i' '0' 'i' 'i' 'i' 'i'

+ /retardo_bp/s1 u
+ /retardo_bp/s2
+ /retardo_bp/s3
u
u
f---l
f-----1 tF=CJ J

+ / retardo_bp/s4 u
+ /retardo_bp/in1 1
+ /retardo bp/in2 o
1
Now 50 ns 1 ' ' ' '
1
' ' ' ' 101 ' ' ' ' 1
' ' ' ' 1
20
' ' ' ' 1
' ' ' ' 301 ' ' ' ' 1
' ' ' ' 401 ' ' ' 1
' ' ' ' 501
...
Cursor 1 Ons
.... ....
~

Figura 3.11: Formas de onda obtenidas al simular el banco de pruebas.

268
SIMULACIÓN DEL CÓDIGO VHDL

Solución al Ejercicio 3. 7

Al declarar las señales se especifica que el valor inicial de YO es ' 1 ' , pero no se
especifica el valor inicial de Y1. Por ello, la señal YO tiene en t = O el valor ' 1',
mientras que la señal Y1 tiene el valor por defecto para std_logic, que es 'U' .

Asimismo, en t =O se ejecutan la sentencia de asignación a la señal Y1 y el bloque


process:

- Al ejecutar la sentencia de asignación a Y1, se calcula el nuevo valor para Y1,


que es igual al valor que tiene YO en t = O. Es decir, ' 1 ' . Este nuevo valor se
asignará a la señal transcurridos 10 ns. Esto es, en el instante t = 10 ns.

- Las sentencias del bloque process se ejecutan secuencialmente, una tras otra,
hasta que se ejecuta la sentencia wait, que hace que la ejecución del bloque
process quede suspendida. La ejecución de cada sentencia de asignación a YO
hace que se actualice la cola de transacciones del driver. Por tratarse de asig-
naciones con retardo de transporte, en cada caso se actualiza la cola aplicando
únicamente la Regla l. Obsérvese que al añadir la transacción correspondiente
a la sentencia
YO <= transport '1' after 15 ns;

se elimina de la cola la transacción correspondiente a la sentencia


YO <= transport '1' after 20 ns;

ya que la transacción descrita por esta última asignación está planificada para
un tiempo posterior a 15 ns (aplicación de la Regla 1).

A continuación, se muestra el resultado de la inicialización y el contenido en t = O


de las colas de transacciones planificadas.

tiempo YO Y1
o '1' 'U'

tiempo YO tiempo Y1
10 ns '0' 10 ns '1'
15 ns '1'
30 ns '0'

El reloj de la simulación avanza hasta el instante t = 10 ns, ya que es el instante


en el cual está planificado el evento más próximo al tiempo actual. En t = 10 ns se
asigna el valor 'o' a la señal YO y el valor ' 1 ' a la señal Y1.

269
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

El evento en la señal YO activa la sentencia concurrente de asignación a la señal Y1.


Como resultado de la ejecución de dicha sentencia, se añade a la cola del driver de Y1
una nueva transacción: asignar el valor 'o' en el instante t = 20 ns. A continuación,
se muestra el resultado de la simulación hasta este instante y el contenido de la cola
de transacciones planificadas para cada señal:

tiempo YO Y1
o '1' 'U'
10 ns '0' '1'

tiempo YO tiempo Y1
15 ns '1' 20 ns '0'
30 ns '0'

El siguiente evento está planificado para el instante 15 ns. Por tanto, el reloj de
la simulación avanza hasta t = 15 ns, instante en el cual se asigna a la señal YO el
valor '1 '.

El cambio en el valor de la señal YO hace que se ejecute la sentencia de asignación


a la señal Y1, esto es,

Y1 <= YO after 10 ns;

calculándose el nuevo valor para Y1, que es ' 1'. Este nuevo valor se asignará a la
señal en el instante t = 25 ns. Al introducir esta nueva transacción en la cola de
transacciones del driver, se elimina de la cola la transacción que estaba planificada
para el instante t = 20 ns (aplicación de la Regla 2.2). El resultado de la simulación
hasta el instante t = 15 ns y el contenido de las colas de transacciones se muestran
a continuación.

tiempo YO Y1
o '1' 'U'
10 ns '0' '1'
15 ns '1' '1'

tiempo YO tiempo Y1
30 ns '0' 25 ns '1'

No se genera ningún evento en el instante t = 25 ns, aunque existe una transac-


ción planificada para la señal Y1 en dicho instante, ya que el valor planificado para la

270
SIMULACIÓN DEL CÓDIGO VHDL

señal y el valor actual son iguales. Por tanto, el reloj de la simulación avanza hasta
t = 30 ns, instante en el cual está planificado el evento más próximo.

En t = 30 ns, se asigna a la señal YO el valor 'o'. El cambio en el valor de la


señal YO hace que se ejecute la asignación concurrente a la señal Y1. El nuevo valor
de la señal Y1 es 'o' y se asignará a la señal en el instante t = 40 ns. El resultado
de la simulación hasta este instante y el contenido de las colas de transacciones
planificadas se muestran a continuación.

tiempo YO Y1
o '1' 'U'
10 ns '0' '1'
15 ns '1' '1'
30 ns '0' '1'

tiempo YO tiempo Y1
40 ns '0'

El siguiente evento está planificado para el instante 40 ns. Por tanto, el reloj de
la simulación avanza hasta t = 40 ns , instante en el cual se asigna a la señal Y1 el
valor 'o' . Como no existen más eventos planificados, la simulación termina en este
instante.

La tabla siguiente muestra los valores que toman las señales YO e Y1 en los
instantes de tiempo en que existe un evento en alguna de estas señales.

tiempo YO Y1
o '1' 'U'
10 ns '0' '1'
15 ns '1' '1'
30 ns '0' '1'
40 ns '0' '0'

271
TEMA 4

DISEÑO DE LÓGICA COMBINACIONAL

4.1. Introducción
4.2. Diseño para síntesis de lógica combinacional
4.3. Funciones lógicas
4.4. Multiplexor de 4 entradas
4.5. Restador completo de 1 bit
4.6. Sumador completo de 1 bit
4. 7. Unidad aritmético lógica
4.8. Lecturas recomendadas
4.9. Ejercicios de autocomprobación
4.10. Soluciones de los ejercicios
DISEÑO DE LÓGICA COMBINACIONAL

OBJETIVOS DOCENTES

Una vez estudiado el contenido del tema y realizados los ejercicios prácticos,
debería saber:

- Discutir qué características debe reunir un diseño para que el circuito resul-
tante de su síntesis sea combinacional.

- Diseñar circuitos lógicos combinacionales empleando VHDL, tales como fun-


ciones lógicas, multiplexores, sumadores y restadores binarios, y ALUs, descri-
biendo el comportamiento y/ o la estructura del circuito.

- Describir un mismo circuito combinacional usando diferentes representacio-


nes (comportamental, estructural o mixta) y empleando diferentes tipos de
sentencias, tanto concurrentes como secuenciales.

- Programar y simular bancos de prueba para circuitos combinacionales, yana-


lizar los resultados de la simulación.

275
DISEÑO DE LÓGICA COMBINACIONAL

4.1. INTRODUCCIÓN

Los conocimientos sobre el lenguaje VHDL adquiridos en el Tema 2 son aplicados


en este tema al diseño para síntesis de sistemas digitales combinacionales y a la
programación de bancos de prueba para dichos diseños circuitales.

Se abordará el diseño de algunos de los sistemas digitales combinacionales más


comúnmente usados: un circuito multiplexor, un sumador binario, un restador bina-
rio y una unidad aritmético lógica. Al hacerlo, se propondrán diseños alternativos
para un mismo sistema digital, empleando en unos casos sentencias concurrentes, en
otros sentencias secuenciales y en otros realizando una descripción de la estructura.
Con ello, se pretende mostrar las diferentes posibilidades para la descripción de los
circuitos digitales que ofrece VHDL.

4.2. DISEÑO PARA SÍNTESIS DE LÓGICA COMBINACIONAL

Cuando el objetivo de la descripción del circuito mediante VHDL es la síntesis de


un circuito combinacional, debe tenerse presente que la característica fundamental
de un bloque lógico combinacional es que su comportamiento y sus salidas dependen
únicamente del valor actual de las entradas. No dependen del valor pasado de las
entradas, ni tampoco del estado. Así pues, el código VHDL que describe un circuito
combinacional no debe tener "memoria", ni tampoco debe describir dependencia
respecto al estado.

Por otra parte, al realizar el diseño debe evitarse incluir retardos temporales
en la descripción VHDL del circuito, ya que los retardos del circuito real serán
dependientes del hardware en particular que se emplee para implementar el circuito.

Existen varios métodos para describir circuitos combinacionales en VHDL. De


hecho, el mismo tipo de circuito puede ser descrito empleando diferentes sentencias
VHDL. Por ejemplo, un multiplexor 2:1 puede definirse indicando su estructura
(conexión de las correspondientes puertas lógicas) o describiendo su comportamiento,
mediante una sentencia concurrente de asignación a una señal, tal como:

out <= in1 when (sel='1') else inO;

A continuación, se describe un método para la descripción de circuitos combi-


nacionales que es sencillo de entender, aplicable de manera general y ampliamente
usado.

277
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4.2.1. Empleo de sentencias concurrentes

Los circuitos lógicos combinacionales pueden ser descritos empleando sentencias


concurrentes de asignación a señales. Este tipo de sentencias modelan de manera
correcta el comportamiento de los dispositivos combinacionales, que están activos
durante todo el tiempo de manera concurrente.

En la parte izquierda de una sentencia de asignación concurrente debe aparecer,


o bien una señal local de la architecture, o bien una señal de la interfaz
(definida en la entity) del tipo out o inout.

En la parte derecha de la asignación concurrente pueden aparecer señales


locales de la architecture y también señales de la interfaz, del tipo in o
inout.

Las herramientas de síntesis pueden sintetizar las puertas lógicas simples a partir
de las operaciones lógicas primitivas de VHDL. A continuación, se muestran dos
ejemplos:
Puerta NAND nand_out <= iO nand i1;
Puerta OR-exclusiva xor_out <= iO xor i1;

También, pueden sintetizarse arrays de puertas lógicas a partir de este mismo tipo
de sentencias. Por ejemplo, la siguiente sentencia describe un array de inversores:
Array de inversores inv_vec <= not iO_vec;
donde inv_vec e iO_vec son std_logic_vector.

El que la herramienta de síntesis cree una única puerta lógica o un array de


puertas lógicas, depende del tipo de señales usadas en la sentencia de asignación
concurrente. Por ejemplo, las siguientes sentencias dan lugar a un buffer triestado y
a un array de buffers triestado, respectivamente.
Buffer triestado tri_out <= iO when (sel='1') else 'Z';
Array de buffers triestado tri_vec <= iO_vec when (sel='1')
else (others => 'Z');
donde tri_ ve e e iO_ ve e son std_logic_vector.

Es posible sintetizar multiplexores y decodificadores que están descritos mediante


sentencias concurrentes condicionales. Por ejemplo:
Decodificador 2:4 dec vec <= 11 0001 11 when (sel_vec 110011)
else 11 0010 11 when (sel_vec 110111)
else 11 0100 11 when (sel_vec 111011)
else 11 1000 11 ;

278
DISEÑO DE LÓGICA COMBINACIONAL

Igualmente, pueden emplearse sentencias concurrentes de selección. Por ejemplo:


Multiplexor 4:1 with sel_vec select
mux41 - out <= iO when "00",
i1 when "01",
i2 when "10",
i3 when others;
Como se explicó en la Sección 2.5, es aconsejable usar sentencias concurrentes
de selección para describir multiplexores y decodificadores, ya que el empleo de
sentencias concurrentes condicionales puede dar lugar a la síntesis de circuitos in-
necesariamente complejos. Esto es debido a que las condiciones de las sentencias
condicionales no tienen forzosamente que ser excluyentes entre sí, cosa que sí sucede
siempre con las condiciones de las sentencias concurrentes de selección.

Es posible también realizar una descripción del circuito basada únicamente en la


operación que se desea que realice. Por ejemplo:
Multiplexor 4:1 mux41_out <= iO_vec( TO_INTEGER(unsigned(sel_vec)) );
donde iO_ ve e y sel_ ve e son std_logic_vector.

donde se emplean las funciones de conversión de tipo TO_INTEG ER y unsigned,


que están definidas en el package IEEE.numeric_std.

Finalmente, los circuitos que realizan operaciones aritméticas pueden ser des-
critos aplicando las correspondientes operaciones aritméticas a los tipos de datos
adecuados. Por ejemplo, los operandos std_logic_vector deben ser convertidos a
unsigned antes de emplear los operandos suma o multiplicación. Por ejemplo:
Sumador add_uvec <= unsigned(iO_vec) + i1_uvec;
donde i1_uvec y add_uvec son unsigned.
Multiplicador mult_uvec <= unsigned(iO_vec) * i1_uvec;
donde i1_uvec y mult_uvec son unsigned.

Este tipo de descripción da lugar a la síntesis de circuitos aritméticos estándar:


dependiendo de la opción seleccionada en la síntesis, las unidades aritméticas sinte-
tizadas 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 (si se escoge la opción "optimizar la velocidad").

Para crear tipos específicos de unidades aritméticas, tales como tipos especiales
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.

279
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4.2.2. Empleo de bloques process

Aunque las sentencias concurrentes de asignación a señal son útiles para crear
estructuras combinacionales simples, es necesario disponer de otro método para crear
circuitos más complejos. En concreto, cierto número de cláusulas de VHDL (tales
como if, case y for) sólo pueden ser usadas dentro de bloques process.

Los bloques process pueden ser usados para describir lógica combinacional. Para
que el circuito resultante de la síntesis sea combinacional, deben respetarse las reglas
siguientes:

l. Todas las entradas del circuito deben estar incluidas en la lista de sensibilidad
del bloque process.

2. Ninguna otra señal debe estar incluida en la lista de sensibilidad.

3. Ninguna de las sentencias internas al bloque process debe ser sensible al flanco
de subida o de bajada de ninguna señal.

A continuación, se muestran varios ejemplos sencillos de diseño de circuitos


combinacionales, empleando tanto sentencias concurrentes como bloques process.

4.3. FUNCIONES LÓGICAS

En esta sección se describe el modelado de dos funciones lógicas y de su banco


de pruebas. Las dos funciones lógicas (F y G), que dependen de 3 variables (a, b y
e), son las siguientes:
F a and b or not e
G a and b or not b and e

4.3.1. Diseño del circuito

El Código VHDL 4.1 describe las funciones lógicas. Obsérvese que el orden en
el cual deben realizarse las operaciones booleanas debe indicarse explícitamente
mediante paréntesis en el código VHDL (en caso contrario se obtiene error). Es
decir, las funciones lógicas deben escribirse de la forma siguiente:

F ( a and b ) or not e
G ( a and b ) or ( not b and e )

280
DISEÑO DE LÓGICA COMBINACIONAL

-- Funcion es lógicas:
F = ab + e'
G = ab + b'c
Fichero: fun cLog_F_G.vhd
library IEEE; use IEEE.std_logie_1164.all;
entity funeLog_F _G is port
( F, G : out std_logic;
a, b, e : in std_logic );
end entity funeLog_F _G;
architecture funeLog_F _G of funeLog_F _G is
begin
F <= (a and b) or not e;
G <= (a and b) or (not b and e);
end arch1tecture funeLog_F _G;

Código VHDL 4.1: Diseño mediante la descripción de las funciones lógicas.

La interfaz externa del circuito que implementa las funciones lógicas es descrita
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, e). 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.

4.3.2. Programación del banco de pruebas

Una vez modelado el circuito, puede programarse su banco de pruebas tal como
se muestra en el Código VHDL 4.2. Puesto que el banco de pruebas no va a ser
sintetizado, puede emplearse para su programación cualquier instrucción VHDL dis-
ponible (incluso aquellas que darían lugar a circuitos no sintetizables). Instrucciones
útiles de este tipo son wait, assert y report, que permiten controlar el progreso de
la simulación, comprobar y mostrar sus resultados.

En este caso, la finalidad del banco de pruebas es únicamente generar las 23


posibles entradas al circuito. Normalmente, los propios programas de test contienen
los algoritmos necesarios para determinar si las salidas del circuito son las esperadas
y muestran los correspondientes mensajes en aquellos casos en que no lo sean. Por

281
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas
-- Fichero: bp_funcLog_F_G. vhd
library IEEE;
use IEEE. std_logie_1164. all;
use IEEE.numerie_std . all;

entity bp_funeLog_F _G is
end entlty bp_funeLog_F _G;

architecture bp_funeLog_F _G of bp_funeLog_F _G is

signal yO, y1 : std_logic; -- Conectar salidas UUT


signal xO, x1, x2 : std_logic; -- Conectar entradas UUT

component funeLog_F _G is port


( F, G : out stdJogic;
a, b, e : in std_logic);
end component funeLog_F _G;

begin

-- Instanciar y conectar UUT


uut : component funeLog_F _G port map
( F = > yO, G = > y 1,
a => xO, b => x1, e = > x2 );
gen_ ve e_ test : process
variable test_in : unsigned (2 downto O); -- Vector de test
begin
test_in := B"OOO";
for eount in O to 7 loop
x2 <= test_in(2);
x1 <= test_in(1);
xO <= test_in(O);
wait for 10 ns;
test_in := test_in + 1;
end loop;
wait;
end process gen_vee_test;

end architecture bp_funeLog_F _G;

Código VHDL 4.2: Banco de pruebas del circuito que implementa las dos funciones lógicas.

282
DISEÑO DE LÓGICA COMBINACIONAL

simplicidad, en este caso esta labor la asume el diseñador. Es decir, observando las
señales de salida del circuito y comparando con la tabla de la verdad de las funciones
lógicas, el diseñador determina si el funcionamiento del circuito es el esperado.

Como programa VHDL, el banco de pruebas es un tipo especial de pareja entity-


architecture, que no tiene ni entradas ni salidas externas. Por este motivo, la entity
del banco de pruebas no contiene ningún puerto.

Internamente, el banco de pruebas tiene conexiones al UUT. Se han definido


señales internas al banco de pruebas para todas las conexiones al UUT:

signal yO, y1 std_logic; Conectar salidas UUT


signal xO, x1, x2 std_logic; Conectar entradas UUT

La conexión del UUT en el banco de pruebas se realiza instanciando el UUT


como un subcircuito dentro del banco de pruebas. En este caso, la conexión se
realiza nombrando explícitamente los puertos:

uut : component funcLog_F_G port map


( F => yO, G => y1,
a=> xO, b => x1, e=> x2 );

Obsérvese que la señal y su puerto asociado son incluidos en la lista de parámetros


de la forma siguiente: puerto => señal

La architecture del banco de pruebas contiene un proceso (bloque process) en


el cual se generan los vectores de test y se introducen como entradas del UUT. El
bloque process se emplea para encapsular una secuencia de sentencias que serán
ejecutadas secuencialmente. En el código del banco de pruebas, el bloque process
tiene la estructura siguiente:

gen_vec_test : process
variable
begin

end process gen_vec_test;

donde las variables se declaran antes de la palabra reservada begin, y las sentencias a
ejecutar secuencialmente se escriben a continuación de la palabra begin. Obsérvese
que VHDL permite opcionalmente asignar un nombre a los bloques process. En
este caso, se ha asignado al bloque el nombre gen_ ve e_ test.

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

283
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

pueda ser incrementado (con el fin de generar todas las posibles combinaciones de
vectores de test) empleando un bucle for. 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
(O) indica el índice del bit menos significativo del vector.

La sentencia wait for se emplea para esperar durante un número determinado


de unidades de tiempo. En el código del banco de pruebas, se emplea

wait for 10 ns;

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 del bloque process, no tiene
ninguna indicación acerca del tiempo que hay que esperar. Este tipo de sentencia
wait se emplea para suspender indefinidamente la ejecución del bloque process, 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 4.1.

+ /bp_funclog_f_g/_yO 1 1 1
+ /bp_funclog_f_g/_y1 1 1
1 1 1
+ /bp_funclog_f_g/xO 1 1 1 1 1 1 l 1
+·/bp_funclog_f_g/x1 1 1 1 1
+ /bp_funclog_f_g/x2 1 1

~11111111
2

4
~ü ~~~
6
~ü ~~
8
111 1 1 1 1 1 1 1 1 1 1 1 1 1 1 111 1 1 1 1 1 1 1 1111111 11 11111 1111111 1 1111111 ~ü 11
Now 80 ns
Cursor 1 Ons llQflil
El wW~I hl l .,.....
1 O ns to 84 ns 1 Now: 80 ns Delta: 1

Figura 4.1: Formas de onda obtenidas de simular el Código VHDL 4.2.

284
DISEÑO DE LÓGICA COMBINACIONAL

4.4. MULTIPLEXOR DE 4 ENTRADAS

En la Figura 4.2 se muestra un multiplexor de 4 entradas (i3, i2, i1, iO), dos
entradas de selección (si, so) y una salida (d). En esta sección se describen diferentes
maneras de modelar el multiplexor, así como bancos de pruebas que permiten simular
tests sobre los modelos del circuito.

Figura 4.2: Multiplexor de 4 entradas.

4.4.1. Diseño usando sentencias secuenciales

El Código VHDL 4.3 describe el MUX 4:1, empleando para ello una sentencia
if incluida en un bloque process. Asimismo, el Código VHDL 4.4 describe el com-
portamiento del multiplexor mediante sentencias if y case incluidas en un bloque
process. Obsérvese que en ambos diseños el bloque process es sensible a las señales
i3, i2, i1, iO, s1, sO. Esto significa que las sentencias del bloque se ejecutarán cada
vez que alguna de estas señales cambie de valor.

El Código VHDL 4.5 es un banco de pruebas que aplica algunos vectores de test
al multiplexor. Se trata únicamente de un pequeño ejemplo, no es un programa de
test exhaustivo para este circuito. En la Figura 4.3a se muestran las formas de onda
obtenidas al simular el banco de pruebas.

Un error que a veces se comete consiste en olvidar incluir en la lista alguna de las
variables a las que es sensible el bloque process. La consecuencia de este error es que
el bloque process no se ejecutará cuando cambie el valor de la variable no incluida
en la lista, con lo cual el modelo simulado no reproducirá correctamente el circuito
real. Por ejemplo, supongamos que en el modelo del multiplexor no se incluyen las
entradas i3, i2, i1, iO en la lista de variables a las que es sensible el bloque process.
Es decir, supongamos que por error la architecture del multiplexor se define tal
como se muestra en el Código VHDL 4.6.

285
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- MUX 4x1
-- Fichero: mux_4xLprocess_if. vhd
library IEEE; use IEEE. std_logic_1164. all;
entity mux_ 4x1 is port
( d : out std_logic;
i3, i2, i1, iO : in std_logic;
s 1, sO : in std_logic ) ;
end entity mux_4x1;
architecture mux_ 4x1 of mux_ 4x1 is
begin
process (i3, i2, i1, iO, s1, sO)
begin
if (s1='0' and s0='0') then
d <= iO;
elsif (s1=' O' and sO=' 1 ') then
d <= i1;
elsif (s1=' 1' and sO=' O') then
d <= i2;
el se
d <= i3;
end if;
end process;
end architecture mux_4x1;

Código VHDL 4.3: Diseño de un MUX 4:1 mediante una sentencia if.

Este modelo no reproduce adecuadamente el comportamiento de un multiplexor,


como puede observarse en la Figura 4.3b. Obsérvese que es este caso la salida d no
reproduce el cambio en el valor de la entrada iO que se produce en el instante 5 ns.
En el instante 5 ns la entrada iO pasa de valer 'O' a valer '1 ', mientras que el valor
de la salida d no cambia: sigue siendo 'O'. Esto es debido a que el cambio en el valor
de iO no dispara la ejecución del bloque process, con lo cual el valor de la salida
no se actualiza al nuevo valor de la entrada iO.

4.4.2. Diseño usando sentencias concurrentes

El Código VHDL 4. 7 describe el circuito multiplexor usando una sentencia con-


currente, en la cual se asigna valor a la señal d en función del valor que tomen las
entradas al circuito.

El Código VHDL 4.8 ilustra el empleo de señales del tipo integer. Este diseño
es una variación del anterior, describiéndose en este caso el comportamiento del
circuito mediante dos sentencias concurrentes. En la primera, se asigna valor a la
señal integer sel en función del valor de las entradas de selección. En la segunda,
se asigna valor a la salida del circuito en función de las entradas de datos y del valor
de la señal entera. En la Figura 4.4 se muestra el resultado de la simulación.

286
DISEÑO DE LÓGICA COMBINACIONAL

-- MUX 4x1
-- Fichero: mux_4xLprocess_if_case. vhd
library IEEE; use IEEE. std_logic_1164. all;
entity mux_ 4x1 is port
( d : out std_logic;
i3, i2, i1, iO : in stcLlogic;
s1, sO : in std_logic );
end entity mux_4x1;

architecture mux_4x1 of mux 4x1 is


begin
process (i3, i2, i1, iO, s1, sO)
variable sel : integer;
begin
if (s1='0'and s0='0') then
sel := O;
elsif (s1= 'O' and sO=' 1') then
sel := 1;
elsif (s1='1'and sO='O') then
sel := 2;
el se
sel := 3;
end if;
case sel is
when O =>
d <= iO;
when 1 =>
d <= i1;
when 2 =>
d <= i2;
when others =>
d <= i3;
end case;
end process;
end architecture mux_4x1;

Código VHDL 4.4: Descripción del MUX 4:1 mediante sentencias if y case.

287
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas
-- Fichero: bp_mux_4x1. vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity bp_mux_ 4x1 is
end entity bp_mux_4x1;
architecture bp_mux_ 4x1 of bp_mux_ 4x1 is
signal d : std_logic; -- Conectar salida UUT
signal iO, i1, i2, i3,
sO, s1 : std_logic; -- Conectar entmdas UUT

component mux_4x1 is port


( d : out std_logic;
i3, i2, i1, iO : in std_logic;
s 1, sO : in std_logic ) ;
end component mux_4x1;
begin
-- Instanciar y conectar UUT
uut : component mux_ 4x1 port map
( d = > d,
iO = > iO, i1 = > i1, i2 = > i2, i3 = > i3,
sO = > sO, s1 = > s1 );

gen_ ve e_ test : process


begin
iO < = '0'; i1 < = '0'; i2 <= '1'; i3 < = '0';
sO < = '0'; s1 < = '0';
wait for 5 ns;
iO < = '1';
wait for 5 ns;
sO < = '1';
wait for 10 ns;
sO<= '0'; s1 < = '1';
wait for 10 ns;
sO < = '1';
wait;
end process gen_vec_test;
end architecture bp_mux_4x1;

Código VHDL 4.5: Banco de pruebas del MUX 4:1.

288
DISEÑO DE LÓGICA COMBINACIONAL

+ /bp_mux_4x1/d o 1 L 1 1

+ /bp_mux_4x1 /i0 1 1
+ /bp_mux_4x1/i1 o
+ /bp_mux_4x1/i2 1
+ /bp_mux_4x1 /i3 o
+ /bp_mux_4x1/s0 1 1 1 1

+ /bp_mux_4x1/s1 1 1

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Now 60 ns ) 10 20 30 40
a)
+ /bp_mux_4x1/d o 1 1

+ /bp_mux_4x1/i0 1 11 1

+ /bp_mux_4x1/i1 o 11

+ /bp_mux_4x1/i2 1 11

+ /bp_mux_4x1/i3 o 11

+ /bp_mux_4x1/s0 1 11 1 1 1

+ /bp_mux_4x1/s1 1 11 1

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Now 60 ns ) 10 20 30 40

b)

Figura 4 .3: Formas de onda obtenidas de simular el banco de pruebas: a) modelo del multiplexor
correct o; b) modelo del mult iplexor erróneo.

-- MUX 4x 1
-- ERROR al definir la sensibilidad del bloque process
-- Fich ero : mux_4x Lprocess_if"_in sen sible_i3i2i1iO. vhd
architecture mux_4x1 of mux_4x1 is
begin
process (s1 , sO) -- Error: no se incluyen i3,i2, i1,i0
begin
if (s1='0'and s0='0') then
d <= iO;
elsif (s1=' O' and sO=' 1 ') t hen
d <= i1;
elsif (s1=' 1 'and sO=' O') then
d <= i2 ;
el se
d <= i3 ;
end if;
end process;
end architectur e mux_4x1;

Código VHDL 4. 6 : Descripción errónea de la a r chitecture del MUX 4: 1.

289
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- MUX 4x1
-- Fichero: mnx_4xLconcnrrente1. vhd
library IEEE; use IEEE.std_logic_ii64.all;
entity mux_ 4xi is port
( d : out std_logic;
i3, i2, ii, iO : in std_logic;
si, sO : in std_logic );
end entity mux_4xi;

architecture mux_4xi concurrente of mux_4xi is


begin
d <= iO when (si='O' and s0='0') else
ii when (si=' O' and sO=' i ') else
i2 when (si=' i' and sO=' O') else
i3;
end architecture mux_4xi_concurrente;

Código VHDL 4. 7: Diseño de un MUX 4:1 mediante una sentencia concurrente.

-- MUX 4x1
-- Fichero: mnx_4xLconcurrente. vhd
library IEEE; use IEEE. std_logic_ii64.all;
entity mux_ 4xi is port
( d : out std_logic;
i3, i2, ii, iO : in std_logic;
si, sO : in std_logic ) ;
end entity mux_4xi;
architecture mux_4xi_concurrente of mux 4xi is
signal sel : integer;
begin
sel <=O when (si='O' and s0='0') else
i w hen (si= ' O' and sO= ' i ' ) else
2 when (si='i' and s0='0') else
3;
d <= iO when sel = O else
i i when sel = i else
i2 when sel = 2 else
i3;
end architecture mux_4xi_concurrente;

Código VHDL 4.8: Diseño de un MUX 4:1 mediante dos sentencias concurrentes.

+ /bp_mux_ 4x1/uutld o 11 1 1 1 1
+ /bp_mux_4x1/uutli0 1 11 1
+ /bp_mux_4x1/uutli1 o 11
+ /bp_mux_ 4x1/uut/i2 1 1'
+ /bp_mux_ 4x1/uut/i3 o 11
+ /bp_mux_ 4x1/uut/s0 1 11 1 1 1

+ /bp_mux_4x1/uutls1 1 11 1

+ /bp_mux_4x1/uut/sel 3 o 1 2 3
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Now 45 ns ) 10 20 30 40

Figura 4.4: Formas de onda obtenidas de simular el banco de pruebas, empleando la descripción
del comportamiento del multiplexor.

290
DISEÑO DE LÓGICA COMBINACIONAL

4.5. RESTADOR COMPLETO DE 1 BIT

En esta sección se describe el diseño de un circuito restador completo de 1


bit y de su banco de pruebas. VHDL permite describir la architecture de un
circuito mediante su comportamiento y también mediante su estructura, es decir,
indicando cómo están conectados los subcircuitos que lo componen. En primer
lugar , se realizará una descripción del circuito basada en su comportamiento. A
continuación, se hará una descripción basada en su estructura.

4.5.1. Descripción del comportamiento

A continuación, se muestra la tabla de la verdad del circuito restador de 1 bit.


Este circuito calcula el resultado (res) y el acarreo (acarreo) obtenidos de realizar la
resta (a- b) de dos bits (a,b).

a b res acarreo
o o o o
o 1 1 1
1 o 1 o
1 1 o o

Un circuito restador completo de 1 bit tiene una entrada adicional: el acarreo


de entrada. Conectando varios de estos circuitos, puede obtenerse un restador de
números de varios bits.

El Código VHDL 4.9 describe un restador completo de 1 bit. Obsérvese que la


architecture describe el funcionamiento del circuito, sin entrar en detalles acerca
de su implementación.

La interfaz del restador completo es descrita en la entity llamada rest_completo.


En ella se definen los dos puertos de salida (res, acarreo_out), seguidos de los tres
puertos de entrada (a, b, acarreo_in).

Los puertos de entrada y de salida se definen del tipo std_logic, con el fin de
facilitar el uso del restador como subcircuito en otros circuitos: se emplean señales
del tipo std_logic y std_logic_vector para modelar las señales transmitidas por el
cableado de los circuitos físicos.

En la architecture, se define una señal del tipo unsigned de 2 bits, llamada


resul t, con el fin de almacenar el resultado de la operación de sustracción. Al

291
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- R estador completo de 1 bít


-- Fíchero: restadorCompletol bítComport. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity rest_completo is port


( res, acarreo_out : out std_logic;
a, b, acarreo_in : in std_logic);
end entity rest_completo;
architecture rest_completo_comport of rest_completo is
signal result : unsigned ( 1 downto O );
begin
result <= ('0' & a)- ('0' & b)- ('0' & acarreo_in);
acarreo_out <= result(1);
res <= result(O);
end architecture rest_completo_comport;

Código VHDL 4.9: Descripción del comportamiento de un restador completo de un bit.

declararla, se indica que la señal tiene 2 bits, especificando para ello su rango:
( 1 downto O ) . Si no se especifica el rango, las señales del tipo unsigned tienen
por defecto 32 bits. El tipo de la señal debe ser unsigned, a fin de permitir el uso
del operador resta.

Las señales de entrada, de 1 bit, deben ser extendidas a 2 bits (concatenando un


O), de modo que el resultado de la resta pueda ser almacenado en una señal de 2
bits del tipo unsigned.

Finalmente, el resultado de la resta se asigna a res y acarreo_out. Obsérvese


que es posible realizar las asignaciones:

acarreo_out <= result(1);


res <= result(O);

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.

292
DISEÑO DE LÓGICA COMBINACIONAL

4.5 .2. Descripción de la estructura

En la Figura 4.5 se muestra un circuito restador completo de 1 bit. Para su


definición, se emplean puertas OR-exclusiva de 2 entradas (xor2) , AND de dos
entradas (and2), OR de tres entradas (or3) e inversor (not1) .

.----+r--;
··. . ... . . . . . . . . . 1 d

.------+---+¡ _-.--~...... ....g}_j


¡-·····························¡ acarreo out
. ~g~] ;.- . . . . . .... . . . ..... . . . ...... ..

a
.............................................
res
b
............................................. -~ ...
;:.·.·.-.·.·.·.-.·.·.-.·.-.-.....................

acarreo m
.............................................

Figura 4.5: Diagrama de un circuito restador completo de 1 bit.

Obsérvese que, a fin de facilitar la descripción del modelo, se han etiquetado las
señales internas (not_a, e, d, e, f) y las puertas lógicas (gO, ... , g6). La definición de
cada una de estas puertas lógicas se muestra en el Código VHDL 4.10.

Para componer el circuito restador usando las puertas lógicas anteriores , es


necesario instanciar los componentes necesarios y conectarlos. Para ello, es preciso
escribir la entity de cada uno de los componentes, instanciar los componentes y
describir la conexión entre ellos. El Código VHDL 4.11 describe la estructura del
circuito restador completo.

En el modelo anterior, se realiza la conexión entre los componentes mediante


asociación posicional. Es posible también usar asignación implícita. Por ejemplo:

g2 : component not1 port map (yO=> not_a, xO =>a);

293
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Puerta OR exclusiva de 2 entradas. Fi chero: xor2. vhd


library IEEE; use IEEE. std_logic_1164. all;
entity xor2 is port
( yO : out std_logic;
xO, x1 : in std_logic );
end entity xor2;

architecture xor2 of xor2 is


begin
yO <= xO xor x1;
end architecture xor2;

-- Inversor de 1 entrada. Fichero: notl. vhd


library IEEE; use IEEE. std_logic_1164. all;
entity not 1 is port
( yO : out std_logic;
xO : in std_logic ) ;
end entity not1;
architecture not 1 of not 1 is
begin
yO <= not xO;
end architecture not 1;

-- Puerta AND de 2 entradas. Fi chero: and2.vhd


library IEEE; use IEEE. std_logic_1164. all;
entity and2 is port
( yO : out std_logic;
xO, x 1 : in std_logic ) ;
end entity and2;
architecture and2 of and2 is
begin
yO <= xO and x1;
end architecture and2;

-- Puerta OR de 3 entradas. Fichero: or3.vhd


library IEEE; use IEEE.std_logic_1164.all;
entity or3 is port
( yO : out std_logic;
xO, x1, x2 : in std_logic );
end entity or3;
architecture or3 of or3 is
begin
yO <= xO or x1 or x2;
end architecture or3;

Código VHDL 4.10: Diseño de las puertas lógicas XOR2, NOTl , AND2 y OR3.

294
DISEÑO DE LÓGICA COMBINACIONAL

-- R estador completo de 1 bit


-- Fichero: restadorCompletol bitEstruc. vhd
library IEEE;
use IEEE. std_logie_1164. all;
entity rest_eompleto is port
( res, aearreo_out : out std_logic;
a, b, aearreo_in : in std_logic);
end entity rest_eompleto;
architecture rest_eompleto_estrue of rest_eompleto is
signal not_a, e, d, e, f : std_logic;
-- Declaración de las clases de los componentes
component xor2 is port
( yO : out std_logic;
xO, x 1 : in std_logic ) ;
end component xor2;
component not 1 is port
( yO : out std_logic;
xO : in std_logic ) ;
end component not 1;
component and2 is port
( yO : out std_logic;
xO, x 1 : in std_logic ) ;
end component and2;
component or3 is port
( yO : out std_logic;
xO, x1, x2 : in std_logic );
end component or3;
begin
-- Instanciación y conexión de los componentes
gO : component xor2 port map (e, a, b );
g1 : component xor2 port map (res, e, aearreo_in);
-- g2 : component notl port map {noLa, a);
g2 : component not1 port map (yO => not_a, xO = > a);
g3 : component and2 port map (d, not_a, aearreo_in);
g4 : component and2 port map (e, not_a, b);
g5 : component and2 port map (f, b, aearreo_in);
g6 : component or3 port map (aearreo_out, d, e, f);

end architecture rest_eompleto_estrue;

Código VHDL 4.11: Descripción de la estructura de un restador completo de un bit.

295
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4.5.3. Programación del banco de pruebas

En este caso, en el código del banco de pruebas se comprueban las salidas


obtenidas del UUT con las salidas esperadas. Es decir, el propio banco de pruebas
comprueba si el comportamiento del circuito es correcto y en caso de que no lo sea
generará el correspondiente mensaje. Se usará la descripción estructural del restador
para modelar el UUT y su descripción del comportamiento para obtener las salidas
"correctas", que se compararán con las salidas del UUT.

El Código VHDL 4.12 es el banco de pruebas. La architecture del banco de


pruebas contiene un bloque process en el cual se generan los vectores de test, se
introducen como entradas del UUT y se comprueban las salidas del UUT.

El banco de pruebas no tiene ni entradas ni salidas externas. Por ese motivo, la


entity del banco de pruebas no contiene ningún puerto (port):

entity bp_rest_completo is
end entity bp_rest_completo;

La conexión del UUT en el banco de pruebas se realiza instanciando el restador


binario como un subcircuito dentro del banco de pruebas. Aunque la conexión
se realiza mediante asociación posicional, podría haberse realizado la asociación
nombrando explícitamente los puertos:

uut : component rest_completo port map


(res => res, acarreo_out => acarreo_out,
a=> a, b => b, acarreo_in => acarreo_in);

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 entra-
das 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 salidas
"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:

esperado := ('0' & a)- ('0' & b)- ('0' & acarreo_in);

296
DISEÑO DE LÓGICA COMBINACIONAL

-- Banco de pruebas del restador completo de 1 bit. Fichero: restadorCompletolbiLbp.vhd


library IEEE; use IEEE. std_logic_1164.all; use IEEE.numeric_std.all;

entity bp_rest_completo is -- El banco de pruebas no tiene


end entity bp_rest_completo; --. ni entradas ni salidas
architecture bp_rest_completo of bp_rest_completo is
signal res, acarreo_out : std_logic; -- Para conectar el UUT
signal a, b, acarreo_in : std_logic; -- Para conectar el UUT

component rest_completo is port


( res, acarreo_out : out std_logic;
a, b, acarreo_in : in std_logic);
end component rest_completo;

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 O); -- Vector de test
variable esperado : unsigned (1 downto O); -- Salida esperada
variable num_errores : integer := O; -- Numero de errores
begin
test_in := B"OOO";
for count in O to 7 loop
a <= test_in(2);
b <= test_in(1);
acarreo_in <= test_in(O);
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( O)) &
") /= 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;
end process gen_vec_test;
end architecture bp_rest_completo;

Código VHDL 4.12: Banco de pruebas del restador completo de un bit.

297
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

UJ wave · default .±J.~J29


+ /bp_rest_completo/res 1 1 l r l 1 1 .3
+ /bp_rest_completo/acarreo_out

j
1 1 1 1
+ /bp_rest_completo/a 1
+ /bp_rest_completo/b 1
+ /bp_rest_completo/acarreo_in 1 l r l 1 1 1

GJ ...!.J..!.J ...!... h.l ·----


1 t!{í r~stadorCompl~to1bit_bp.vhd 1 UJ wave 1 .iliJ

VSIM 10> run


t:l "' Note: Test completo. Hay Oerrores.
t:l Time: 80 ns lteration: O lnstance: /bp_rest_completo

VSIM 11 >

Figura 4.6: Formas de onda y mensaje en la consola obtenidos al simular el banco de pruebas.

El comando report se usa para escribir texto en la consola. El argumento


del comando (esto es, el texto a escribir) debe ser del tipo string. Por ejemplo,
cadenas de caracteres concatenadas mediante el operador &. Por ello, todo lo que
se desee mostrar deben ser convertido previamente al tipo string. Por ejemplo,
std_logic' image (res) se usa para convertir el valor de res, que es del tipo std_logic,
a un dato del tipo string.

Asimismo, now es una función predefinida que devuelve el tiempo simulado


como un dato del tipo time. Puede usarse time'image(now) para obtener una
representación del tipo string del tiempo actual de la simulación.

Como resultado de la simulación del banco de pruebas, se obtienen las formas de


onda y el mensaje en la consola mostrados en la Figura 4.6.

Frecuentemente, en un banco de pruebas es preciso comparar el valor esperado


de una señal con el valor obtenido de la simulación del circuito. Si ambos valores no
coinciden, entonces se muestra un mensaje de error y se incrementa el contador del
número de errores. El Código VHDL 4.13 es el banco de pruebas para el circuito
restador completo de 1 bit, programado empleando un procedimiento que realiza
la comparación entre el valor esperado y el actual, y que, en su caso, muestra los
correspondientes mensajes de error.

El código anterior del banco de pruebas puede modificarse con el fin de emplear
una función en lugar de un procedimiento. El Código VHDL 4.14 es una posible
forma de hacerlo. Obsérvese que se ha sustituido la cláusula if, que compara el valor
esperado con el valor actual, por una sentencia assert. El motivo es únicamente
ilustrar el uso de la sentencia assert.

298
DISEÑO DE LÓGICA COMBINACIONAL

-- Banco de pruebas del restador completo de 1 bit empleando un procedimiento


-- Fichero: restadorCompletoi biL bp_procedure.vhd
library IEEE; use IEEE. std_logic_1164. all; use IEEE. numeric_std. all;

entity bp_rest_completo is -- El banco de pruebas no tiene


end entity bp_rest_completo; -- ni entradas ni salidas

architecture bp_rest_completo_procedure of bp_rest_completo is


signal res, acarreo_out : std_logic; -- Para conectar el UUT
signal a, b, acarreo_in : std_logic; -- Para conectar el UUT
procedure error _check( esperado, actual : in unsigned;
num_errores : inout integer ) is
begin
if (esperado / = actual) then -- Comprueba resultado y report del error
report "ERROR : Esperado (" &
std_logic' image (esperado ( 1)) & std_logic' image (esperado (O)) &
") /= actual (" &
std_logic' image (actual ( 1)) & std_logic' image (actual (O)) &
") en el instante" & time' image(now);
num_errores := num_errores + 1;
end if;
end procedure error _check;
component rest_completo is port
( res, acarreo_out : out std_logic;
a, b, acarreo_in : in std_logic);
end component rest_completo;

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 O); -- Vector de test
variable esperado : unsigned (1 downto O); --Salida esperada
variable num_errores : integer := O; -- Numero de errores
begin
test_in := B"OOO";
for count in O to 7 loop
a <= test_in(2);
b <= test_in(1);
acarreo_in <= test_in(O);
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;

Código VHDL 4.13: Banco de pruebas del restador completo de un bit usando un procedimiento.

299
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del restador completo de 1 bit empleando una funcion


-- Fichero: restadorCompletol biLbp_funcion. vhd
library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all;

entity bp_rest_completo is -- El banco de pruebas no tiene


end entity bp_rest_completo; -- ni entradas ni salidas
architecture bp_rest_completo_funcion of bp_rest_completo is
signal res, acarreo_out : std_logic; -- Para conectar el UUT
signal a, b, acarreo_in : std_logic; -- Para conectar el UUT

function error _check( esperado, actual : unsigned;


tnow : time ) return integer is
begin
assert ( esperado = actual ) -- Comprobacion usando assert y report del error
repdrt 11 ERROR : Esperado ( 11 &
std_logic' image (esperado ( 1)) & std_logic' image (esperado (O)) &
11
) /= actual ( 11 &
std_logic' image (actual ( 1)) & std_logic' image (actual (O)) &
11
) en el instante 11 & time'image(tnow)
severity error; -- Opcion severity
if ( esperado / = actual ) then
return 1; -- Indica error
el se
return O; -- Indica que no hay error
end if;
end function error _check;

component rest_completo is port


( res, acarreo_out : out std_logic;
a, b, acarreo_in : in std_logic);
end component rest_completo;

begin
uut : component rest_completo port map (res, acarreo_out, a, b, acarreo_in);
gen_ vec_ test : process
variable test_in : unsigned (2 downto O); -- Vector de test
variable esperado : unsigned (1 downto O); --Salida esperada
variable num_errores : integer := O; -- Numero de errores
begin
test_in := B11 000 11 ;
for count in O to 7 loop
a <= test_in(2); b <= test_in(1); acarreo in <= test_in(O);
wait for 10 ns;
esperado := ('0' & a)- ('0' & b)- ('0' & acarreo_in);
num_errores := num_errores -t-
error_check( esperado, acarreo_out & res, now );
test_in := test_in -t- 1;
end loop;
report 11 Test completo. Hay 11 & integer'image(num_errores) & 11 errores. 11 ;
wait;
end process gen_vec_test;
end architecture bp_rest_completo_funcion;

Código VHDL 4.14: Banco de pruebas del restador completo de un bit usando una función.

300
DISEÑO DE LÓGICA COMBINACIONAL

4.6. SUMADOR COMPLETO DE 1 BIT

Un sumador completo es un circuito con tres bits de entrada (xi, Yi, ci) y dos
bits de salida: el bit suma (si) y el bit acarreo (Ci+ 1 ). El funcionamiento del circuito
está descrito por la tabla de la verdad siguiente:

Ci Xi Yi Ci+l Si
o o o o o
o o 1 o 1
o 1 o o 1
o 1 1 1 o
1 o o o 1
1 o 1 1 o
1 1 o 1 o
1 1 1 1 1

Simplificando las funciones lógicas mediante mapas de Karnaugh, se llega a las


expresiones mostradas a continuación. En la Figura 4. 7 se muestra el circuito.

Ci+l XiYi + XiCi + YiCi


Si Xi EB Yi EB Ci


............................................

.·.·.·.·. ·.)!L.·.·.·.·.·:.-.·.·.·.·.·.·.·.·.·.·.·.·:.·.·.·.·.·.:

"''''•c;•••oo•••••oooooooooooo•••oo•'

..........................................

¡A:N52.....................¡
-----+-:....,. ¡ n2
i.~.~º~-1... ..........1
l---+¡A-t·No2""""""""'""1n .....__...,.¡o_
...R-'1.·3"""""""""""'1
3 .............................................

i.~NQL?. ............1 i.QR~-~ ...............1


¡A:N52.....................¡
1------+-:-+ ¡ n4
i.~NR~-~ ............1

Figura 4. 7: Sumador completo.

301
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4.6.1. Diseño del circuito

El Código VHDL 4.15 describe las puertas lógicas necesarias para componer el
circuito sumador de la Figura 4.7. Las puertas lógicas AND, OR y XOR se modelan
con un retardo de 10 ns.

En este caso, en lugar de declarar los componentes en la architecture del


sumador, se han definido los componentes en un package, tal como se muestra
en el Código VHDL 4.16.

4.6.2. Banco de pruebas

Para comprobar el correcto funcionamiento de este circuito, se puede emplear un


banco de pruebas muy similar al que se diseñó para el restador de 1 bit.

En el banco de pruebas se compara el resultado obtenido de la descripción


de la estructura del sumador, con el resultado obtenido de la descripción de su
comportamiento. Se muestra un mensaje si ambos resultados no coinciden y se lleva
la cuenta del número de errores, mostrando al final de la simulación un mensaje con
el número total de errores. El banco de pruebas es el Código VHDL 4.17.

En la Figura 4.8 se muestra el resultado de la simulación del banco de pruebas.


Obsérvese que, debido al retardo de las puertas lógicas, desde el instante inicial hasta
el instante 20 ns las salidas del sumador toman el valor 'U' (indefinido). Asimismo,
los cambios en las señales de entrada tardan 20 ns en propagarse a las señales de
salida.

+ /bp_sum_completo/c_in 1 1
+ /bp_sum_completo/ x 1 1 1
+ /bp_sum_completo/y
1
1 1 1 1 1 1 1
+ /bp_sum_completo/c_out
1
1 ----., 1 1 1
+ /bp_sum_completo/s 1 ----., 1 1 1

11111111111111111111111111111111111111111111111111111111111111111111 d 111111111111111111111
Now 450 ns ) 100 200 300 400
.... . ....

Figura 4.8: Simulación del banco de pruebas del sumador completo .

.. .... _,

/~ . \,.: . ,. . . :
'
DISEÑO DE LÓGICA COMBINACIONAL

-- A ND de 2 entradas con retardo


-- Fi chero : and2_retardo. vhd
library IEEE; use IEEE.std_logic_1164.all;

entity and2 is
generic ( DELAY : time := 10 ns );
port ( yO : out std_logic;
xO, x 1 : in std_logic ) ;
end entity and2;
architecture and2 of and2 is
begin
yO <= ( xO and x1 ) after DELAY;
end architecture and2;

-- OR de 3 entradas con retardo


-- Fichero: or3_retardo. vhd
library IEEE; use IEEE. std_logic_1164. all;

entity or3 is
generic ( DELAY : time := 10 ns );
port ( yO : out std_logic;
xO, x1, x2 : in std_logic );
end entity or3;
architecture or3 of or3 is
begin
yO <= ( xO or x1 or x2 ) after DELAY;
end architecture or3;

-- OR exclusiva de 2 entradas con retardo


-- Fichero: xor2_retardo .vhd
library IEEE; use IEEE. std_logic_1164. all;

entity xor2 is
generic ( DELAY : time := 10 ns );
port ( yO : out std_logic;
xO, x1 : in std_logic );
end entity xor2;
architecture xor2 of xor2 is
begin
yO <= ( xO xor x1 ) after DELAY;
end architecture xor2;

Código VHDL 4.15: Diseño de las puertas lógicas AND2, OR3 y XOR2 con retardo.

BERGARA
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Package en el qv,e se defin en los componentes


-- Fichero: pv,ertasLogicas_package. vhd
library IEEE;
use IEEE. std_logic_1164. all;
package puertasLogicas_package is
component xor2 is
generic ( DELAY : time := 10 ns );
port ( yO : out std_logic;
xO, x 1 : in std_logic ) ;
end component xor2;
component and2 is
generic ( DELAY : time := 10 ns );
port ( yO : out std_logic;
xO, x 1 : in std_logic ) ;
end component and2;
component or3 is
generic ( DELAY : time := 10 ns );
port ( yO : out std_logic;
xO, x1, x2 : in std_logic );
end component or3;
end package puertasLogicas_package;

-- Sumador completo de 1 bit


-- Fich ero: snmadorCompletol bitEstrnc. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work. puertasLogicas_package. all;
entity sum_completo is port
( s, C_out : out std_logic;
x, y, C_in : in std_logic);
end entity sum_completo;
architecture sum_completo_estruc of sum_completo is
signal n1, n2, n3, n4: std_logic;
begin
-- Instanciación y conexión de los componentes
XOR2_1 : component xor2 port map
(xO => x, x1 =>y, yO => n1 );
XOR2_2 : component xor2 port map
(xO => C_in, x1 => n1, yO=> S );
AND2_1 : component and2 port map
(xO => x, x1 =>y, yO => n2 );
AND2_2 : component and2 port map
(xO => x, x1 => C_in, yO => n3 );
AND2_3 : component and2 port map
(xO => y, x1 => C_in, yO => n4 );
OR3_1 : component or3 port map
(xO => n2, x1 => n3, x2 => n4, yO => C_out );
end architecture sum_completo_estruc;

Código VHDL 4.16: Package con los componentes del sumador y diseño del sumador.

304 .
DISEÑO DE LÓGICA COMBINACIONAL

-- Banco de pruebas del sumador completo de 1 bit


-- Fichero: sumadorCompletol biLbp. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE.numeric_std.all;

entity bp_sum_completo is -- El banco de pntebas no tiene


end entity bp_sum_completo; -- ni entradas ni salidas
architecture bp_sum_completo of bp_sum_completo is
signal s, C_out,
x, y, C_in : std_logic; -- Para conectar el UUT

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 O); -- Vector de test
variable esperado : unsigned (1 downto O); --Salida esperada
variable num_errores : integer := O; -- Numero de errores
begin
test_in := B"OOO";
for count in O to 7 looi_>
C_in <= test_in(2);
x <= test_in(1);
y <= test_in(O);
wait for 50 ns;
esperado := ('0' & x) + ('0' & y)+ ('0' & C_in);
if (esperado / = ( C_out & s ) ) then -- Comprueba resultado
report "ERROR : Esperado ( 11 & -- Report del error
std_logic' image( esperado( 1)) &
std_logic ' image (esperado (O)) &
") /= actual (" &
std_logic' image(C_out) &
std_logic ' image ( s) &
11
) en el instante
11
&
time' image(now);
num_errores := num_errores + 1;
end if;
test_in := test_in + 1;
end loop;
report "Test completo. Hay 11 & integer'image(mim_errores) & 11 errores.";
wait;
end process gen_vec_test;
end architecture bp_sum_completo;

Código VHDL 4.17: Banco de pruebas del sumador completo.

305
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4.7. UNIDAD ARITMÉTICO LÓGICA

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.

En esta sección se realizará el diseño de una AL U que realiza operaciones entre


dos operandos, A y B, en función del valor de la señal de entrada de selección de
función, mode, que tiene 3 bits (véase la Tabla 4.1).

Tabla 4.1: Tabla de operaciones de la AL U.

mo de Operación Descripción
000 A* 2 Multiplicar por 2 (equivale a desplazamiento a la izqda)
oo1 A+B Suma
o1 o A-B Resta
o1 1 -A Complemento a dos
1 oo A and B AND lógico
1 o1 A or B OR lógico
11o A xor B XOR lógico
111 notA Complemento de todos los bits

4.7.1. Diseño de la ALU

Este circuito puede ser descrito mediante una asignación concurrente a una señal,
o bien mediante varias asignaciones incluidas dentro de un bloque process, tal
como se muestra en el Código VHDL 4.18. Ambos diseños dan lugar a circuitos
combinacionales equivalentes.

Recuérdese que, en general, un circuito combinacional puede ser descrito me-


diante 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. En este caso, el bloque process es sensible a tres señales: los dos operandos
y la señal de selección de la operación.

En estos diseños se empleará un package para definir tanto la constante que


determina el tamaño de palabra de los operandos, como la constante que determina
el tamaño de la palabra de selección de la operación. Obsérvese que para poder usar
este package se incluye en ambos diseños la sentencia:

use work.ALU_CONSTANTS.all;

306
DISEÑO DE LÓGICA COMBINACIONAL

-- Definición de constantes globales de la ALU. Fichero: ALU_CONS TANTS.vhd


package ALU_ eONSTANTS 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_eONSTANTS;

-- AL U diseñada mediante una sentencia concurrente. Fichero: AL U_concurrente. vhd


library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
use work. ALU_eONSTANTS . all;

entity ALU is
port ( e : out std_logic_vector (WIDTH-1 downto O);
A, B :in std_logic_vector (WIDTH-1 downto O);
mode : in std_logic_vector (SEL_BITS-1 downto O) );
end entity ALU;
architecture ALU_concurrente of ALU is
begin
e <= std_logic_vector (signed(A)+signed(A)) when (mode= 11 000 11 )
else std_logic_vector (signed(A)+signed(B)) when (mode= 11 001 11 )
else std_logic_vector (signed(A)-signed(B)) when (mode= 11 010 11 )
else std_logic_vector (-signed(A)) when (mode= 11 011 11 )
else A and B when (mode= 11 100 11 )
else A or B when (mode= 11 101 11 )
else A xor B when (mode= 11 110 11 )
else not A;
end architecture ALU_concurrente;

-- AL U diseñada mediante un bloque process. Fichero : AL U_bloqueProcess.vhd


library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
use work . ALU_eONSTANTS. all;
architecture ALU_bloqueProcess of ALU is
begin
process (A, B, mode) is
begin
case mode is
when 11 000 11 = > e < = std_logic_vector(signed(A)+signed(A));
when 11 001 11 = > e < = std_logic_vector(signed(A)+signed(B) ) ;
when 11 010 11 = > e < = std_logic_vector(signed(A)-signed(B)) ;
when 11 011 11 = > e < = std_logic_vector(-signed(A));
when 11 100 11 = > e < = A and B;
when 11 101 11 = > e < =A or B;
when 11 110 11 = > e < =A xor B;
when others = > e < =notA;
end case;
end process ;
end architecture ALU_bloqueProcess;

Código VHDL 4 .18: Uso de package para la definición de const antes, y diseño de la ALU
mediante una asignación concurrente y un bloque process.

307
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4.7.2. Programación del banco de pruebas

Como hemos visto en otros ejemplos, el banco de pruebas está típicamente


formado por las tres partes siguientes: el dispositivo que va a ser probado (UUT),
el código para la generación de los vectores de test y el código para comprobar los
resultados del test.

Aún en el caso de una ALU sencilla como esta, examinar que la ALU realiza
correctamente las operaciones para todos los posibles valores de los operadores
consumiría bastante tiempo. En la práctica esta técnica sería inviable, por lo cual
debe seleccionarse un conjunto de vectores de test, por ejemplo, atendiendo a los
criterios siguientes:

- Se escogen valores de los operandos entorno al cero. Por ejemplo: -2, -1, O,
1 y 2.

- Se escogen valores de los operandos en el límite inferior de su rango. Por ejem-


plo, si MIN_NEG_DATA representa el valor mínimo que puede tomar el operando,
entonces se escogen los valores MIN_NEG_DATA, ... , MIN_NEG_DATA+4 para cada
uno de los operandos.

- Se escogen valores de los operandos en el límite superior de su rango. Si


MAX_POS_DATA representa el valor máximo que puede tomar el operando, en-
tonces se escogen los valores MAX_POS_DATA-4, ... , MAX_POS_DATA para cada uno
de los operandos.

- Finalmente, se escogen algunos valores "al azar", más o menos distribuidos


uniformemente en el rango de los operandos.

El Código VHDL 4.19 contiene un package en el cual de definen las constantes


globales del banco de pruebas, cuyo valor es calculado a partir de las constantes
globales de la ALU. El Código VHDL 4.19- 4.22 es el banco de pruebas.

308
DISEÑO DE LÓGICA COMBINACIONAL

-- Definición de constantes globales del banco de pruebas de la AL U


--Fichero: TB_ALU_CONSTANTS.vhd
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 pr'uebas para la AL U


-- Fichero: TB_ALU.vhd
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
end entity TB_ALU;

architecture TB_ALU of TB ALU is

signal A,B,C : std_logic_vector (WIDTH-1 downto O);


signal mode : std_logic_vector (SEL_BITS-1 downto O);

component ALU is
port ( C : out std_logic_vector (WIDTH-1 downto O);
A, B : in std_logic_vector (WIDTH-1 downto O);
mode : in std_logic_vector (SEL_BITS-1 downto O) );
end component ALU;

Código VHDL 4.19: Package en el cual se definen las constantes usadas en el banco de pruebas
de la AL U y comienzo de la definición del banco de pruebas de la AL U.

309
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

---------------- Continua banco de pruebas para la AL U (fichero TB_AL U. vhd) -------------

-- Procedure que calcula C ( expectecL C) y lo compara con el


-- valor de C que se pasa como argumento ( actuaLC)
-- Si ambos valores no co'i nciden, se muestra un mensaje y se
-- incrementa el contador de errores (error_count)
procedure check_ALU
( i, j, k : in integer;
actual_C : in std_logic_vector (WIDTH-1 downto O);
error _count : inout integer ) is
variable expected_C : integer;
begin
case k is
when O => expected_C := i *2;
when 1 => expected_C := i+j;
when 2 => expected_C := i-j;
when 3 => expected_C := -i;
when 4 => expected_C := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED( i,WIDTH)) and
std_logic_vector(TO_SIGNED(j ,WIDTH)) ) );
when 5 => expected_C := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED( i,WIDTH)) or
std_logic_vector(TO_SIGNED(j ,WIDTH)) ));
when 6 => expected_C := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED( i,WIDTH)) xor
std_logic_vector(TO_SIGNED(j ,WIDTH)) ));
when others => expected_C := TO_INTEGER(signed(
not std_logic_vector(TO_SIGNED(i,WIDTH)) ));
end case;
expected_C := TO_INTEGER(TO_SIGNED( expected_C,WIDTH) );
-- Trunca el resultado a WIDTH bits
assert( expected_C = TO_INTEGER(signed(actual_C)) )
report 11 ERROR. Ops: 11 & integer' image ( i) & 11 , 11 & integer' image (j) &
11
, Operacion:
11
& integer' image(k) &
11
, resultado esperado:
11
&
integer' image( expected_C) &
11
, resultado actual:
11
&
integer'image(TO_INTEGER(signed(actual_C))) &
11
en el instante 11 &
time ' image ( now);
if (expected_C /= TO_INTEGER(signed(actual_C))) then
error_count := error_count + 1;
end if;
end procedure check_ALU;
-- Fin de la definición del procedure

Código VHDL 4.20: Fragmento del banco de pruebas de la ALU: definición del procedure
check_ALU.

310
DISEÑO DE LÓGICA COMBINACIONAL

---------------- Continua banco de pruebas para la AL U (fichero TB_AL U. vhd) ------------ -

begin
UUT : component ALU port map (e, A, B, mo de);

-- bloque process para generar los vectores de test y


-- comprobar el resultado
main : process is
variable error_count : integer := O;
begin

report "Comienza la simulación";

-- Vectores de test: operandos con valor próximo a cero


for i in -2 to 2 loop
for j in -2 to 2 loop
for k in O to SEL_MAX loop
A <= std_logic_vector(TO_SIGNED( i,WIDTH) );
b <= std_logic_vector(TO_SIGNED(j ,WIDTH) );
mode <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait for DELAY;
check_ALU(i, j, k, e, error_count);
end loop;
end loop;
end loop;

-- Vectores de test: operandos con valor próximo al mínimo


for i in MIN_NEG_DATA to MIN_NEG_DATA+4 loop
for j in MIN_NEG_DATA to MIN_NEG_DATA+4 loop
for k in O to SEL_MAX loop
A <= std_logic_vector(TO_SIGNED( i,WIDTH) );
b <= std_logic_vector(TO_SIGNED(j ,WIDTH) );
mode <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait for DELAY;
check_ALU(i, j, k, e, error_count);
end loop;
end loop;
end loop;

-- Vectores de test: operandos con valor próximo al máximo


for i in MAX_POS_DATA-4 to MAX_POS_DATA loop
for j in MAX_POS_DATA-4 to MAX_POS_DATA loop
for k in O to SEL_MAX loop
A <= std_logic_vector(TO_SIGNED(i,WIDTH));
b <= std_logic_vector(TO_SIGNED(j ,WIDTH) );
mode <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait for DELAY;
che ck_ALU ( i, j, k, e, error_ count);
end loop;
end loop;
end loop;

Código VHDL 4.21: Fragmento de la definición del banco de pruebas de la ALU.

311
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

---------------- Continua banco de pruebas para la AL U (fichero TB_AL U. vhd) -------------


-- Vectores de test: operandos con valores al azar
for i in O to 9 loop
for j in O to 9 loop
for k in O to SEL_MAX loop
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, e, error_count);
end loop;
end loop;
end loop;

wait for DELAY;

-- Informe mostrando el resultado del test


if (error_count=O) then
report "Finaliza la simulación sin errores";
el se
report "Finaliza la simulación:" & integer'image(error_count) & "errores";
end if;

wait; -- Termina la simulación


end process main;

end architecture TB_ALU;

Código VHDL 4.22: Parte final de la definición del banco de pruebas de la ALU.

312
DISEÑO DE LÓGICA COMBINACIONAL

4.8. LECTURAS RECOMENDADAS

El Capítulo 2 de (Vahid & Lysecky 2007) es una introducción didáctica al diseño


de lógica combinacional. El Capítulo 6 de (Chu 2006) es una excelente referencia
acerca de la síntesis del código VHDL. En el Capítulo 7 de este mismo texto se
dan recomendaciones y guías valiosas acerca del diseño con VHDL para síntesis
de circuitos combinacionales eficientes. En los Capítulos 9 y 10 de (Perry 2002) se
discute el diseño para síntesis usando VHDL.

Es importante saber qué estructura circuital se puede obtener a partir de una


descripción VHDL. Los libros (Chang 1997) y (Sjoholm & Lindh 1997) contienen
ejemplos donde se muestra el código de un diseño y el circuito sintetizado al cual da
lugar. Además, el Capítulo 8 de (Chang 1997) contiene una guía general de cómo se
ha de describir en VHDL un circuito para síntesis.

Los Capítulos 2, 3 y 4 de (Hwang 2005) contienen varios ejemplos de circuitos


combinacionales típicos, algunos de ellos descritos en VHDL. Estos tres Capítulos
recogen conceptos fundamentales del diseño de circuitos digitales combinacionales,
como el álgebra de Boole, los mapas de Karnaugh, etc ...

313
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4.9. EJERCICIOS DE AUTOCOMPROBACIÓN

Ejercicio 4.1

Diseñe en VHDL un codificador 4:2 con prioridad. Este circuito tiene cuatro
entradas de 1 bit (i3, i2, i1, iO) y dos salidas: la señal valida, de 1 bit, que vale '1'
cuando al menos una de las entradas vale '1', y la señal codificada, de 2 bits, cuyo
valor corresponde con la entrada de mayor prioridad cuyo valor es '1 '. La entrada
i3 tiene mayor prioridad que i2, ésta mayor que i1 y finalmente la entrada iO es la
de menor prioridad.

A continuación, programe un banco de pruebas que testee todas las posibles


entradas al circuito y simúlelo.

Ejercicio 4.2

Diseñe un circuito comparador, que devuelva '1' si el valor del número de 4


bits (x3 x2 x1 xo) de entrada es menor que 5. Emplee únicamente asignaciones
concurrentes y operadores lógicos. Una vez diseñado el circuito, programe un banco
de pruebas para testearlo.

Recomendación: obtenga las funciones lógicas que describen el comportamiento


del circuito a partir de su tabla de verdad.

Ejercicio 4.3

Diseñe un decodificador de código decimal binario de 4 bits (BCD) a 7 segmentos


capaz de alimentar un display numérico de LEDs. La entrada de 4 bits (i 1 , i 2 , i 3 e i 4 )
codifica la representación binaria de un dígito decimal. Los 7 bits de salida (a, b, e,
d, e, f y g) toman el valor 'O' ó '1' de modo que el display de LEDs muestre el dígito
correspondiente. El esquemático del display, con los nombres correspondiente a cada
segmento, se muestra en la Figura 4.9. La operación del decodificador se especifica
en la Tabla 4.2.

Escriba en VHDL el código del decodificador BCD utilizando un único bloque


process y una sentencia case. Las señales de entrada y de salida del decodificador
han de ser del tipo std_logic.

314
DISEÑO DE LÓGICA COMBINACIONAL

f b

Figura 4.9: Display de 7 segmentos.

Tabla 4.2: Tabla de la verdad del circuito decodificador

Z3 Z2 Zl zo a b e d e f g
o o o o 1 1 1 1 1o 1
o o o 1 o 1 1 o o o o
o o 1 o 1 1 o 1 1 o 1
o o 1 1 1 1 1 1 o o 1
o 1 o o o 1 1 o o 1 1
o 1 o 1 1 o 1 1 o 1 1
o 1 1 o 1 o 1 1 1 1 1
o 1 1 1 1 1 1 o o o o
1 o o o 1 1 1 1 1 1 1
1 o o 1 1 1 1 o o 1 1

A continuación, programe un banco de pruebas para el decodificador, que testee


todas las posibles entradas al circuito, y simúlelo. Compruebe el correcto funciona-
miento del circuito observando visualmente sus señales de salida.

Ejercicio 4.4

Escriba en VHDL el código del decodificador BCD descrito en el Ejercicio 4.3


usando esta vez un único bloque process y una sentencia if. Las señales de entrada
y de salida del decodificador han de ser del tipo std_logic.

A continuación, compruebe el correcto funcionamiento del circuito usando el


banco de pruebas programado en el Ejercicio 4.3.

315
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 4.5

Escriba en VHDL el código del decodificador BCD descrito en el Ejercicio 4.3


usando esta vez una asignación concurrente condicional. Las señales de entrada y de
salida del decodificador han de ser del tipo std_logic.

A continuación, compruebe el correcto funcionamiento del circuito usando el


banco de pruebas programado en el Ejercicio 4.3.

Ejercicio 4.6

Escriba en VHDL el código del decodificador BCD descrito en el Ejercicio 4.3


usando esta vez únicamente la sentencia select y asignaciones concurrentes. Las
señales de entrada y de salida del decodificador han de ser del tipo std_logic.

A continuación, compruebe el correcto funcionamiento del circuito usando el


banco de pruebas programado en el Ejercicio 4.3.

Ejercicio 4. 7

La Figura 4.10 representa un esquema de un sumador binario paralelo de 4 bits


con propagación del arrastre compuesto por 4 sumadores completos de 1 bit. Progra-
me en VHDL un sumador de N bits, donde N es una contante de tipo generic, usando
el sumador completo de 1 bit desarrollado en la Sección 4.6. Emplee sentencias
generate para realizar la instanciación y conexión de los N sumadores completos de
1 bit.

x3 Y3 x2 Y2 xl yl Xo Yo

X¡ y¡ X¡ Y; X¡ Y; X¡ y¡

eout c3 c2 el ein
ci+l SBC C¡ ci+I SBC C¡ ci+l SBC C¡ ci+l SBC C¡

S¡ S¡ S¡ S¡

s3 s2 SI So

Figura 4.10: Sumador binario paralelo de 4 bits con propagación del arrastre.

316
DISEÑO DE LÓGICA COMBINACIONAL

A continuación, programe un banco de pruebas para el sumador de 4 bits (N = 4).


El banco de pruebas debe testear todas las posibles entradas al circuito y mostrar
al final de la simulación un mensaje con el número total de errores producidos.

Ejercicio 4.8

Diseñe un circuito desplazador de 4 bits de entrada que realice las operacio-


nes que se muestran en la Tabla 4.3, usando únicamente sentencias de asignación
concurrentes. Programe un banco de pruebas y simúlelo.

Tabla 4.3: Operaciones del circuito desplazador

op Operación
00 Desplaza a la izquierda rellenando con 'O'
o1 Desplaza a la derecha rellenando con 'O'
1o Rota a la izquierda
11 Rota a la derecha

Ejercicio 4. 9

Diseñe un circuito que compare si dos números de N bits tienen igual valor.
Construya el circuito de manera iterativa, tal como se muestra en la Figura 4.11.

Po
'1'
EQ EQ ••• EQ

Figura 4.11: Circuito que compara si dos números de N bits son iguales.

Diseñe inicialmente un comparador de 1 bit, que tenga las tres entradas siguien-
tes: los dos operandos de un bit (xi e Yi) y el resultado de la comparación de la
etapa anterior (Pi)· Pi es un bit cuyo valor es '1' sólo si todas las parejas de bits
comparadas hasta esa etapa son iguales. La salida del comparador de 1 bit, Pi+l ,
es el resultado de la comparación llevada acabo en esa etapa, teniendo en cuenta
el valor de las tres entradas. Finalmente, encadene N comparadores de 1 bit para
implementar el comparador de N bits, usando para ello la sentencia generate.

317
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 4.10

Diseñe la ALU cuyo circuito se muestra en la Figura 4.12 y que realiza las
operaciones descritas en la la Tabla 4.4. La salida de la AL U se selecciona mediante
el bit más significativo de la señal sel, mientras que la operación que realiza es
especificada por los otros tres bits de esta señal. Emplee en el diseño de la AL U
únicamente código concurrente. A continuación, programe un banco de pruebas que
testee el correcto funcionamiento de la AL U diseñada.

a(7:0) - -....--t

Unidad
Lógica
b(7:0) - .....-+o--1

y(7:0)

Unidad
aritmética
cin(O:O)---~
sel(3)

sei(3:0) _ _ _..__ _ _,.__ _ _ _ _ ____J

Figura 4.12: Estructura de la ALU.

Tabla 4.4: Tabla de operaciones de la ALU.

Unidad sel Operación Descripción


0000 a Deja pasar a
ooo 1 a+ 1 Incrementa a
oo1 o a- 1 Decrementa a
Unidad Aritmética
oo1 1 b Deja pasar b
o 1 oo b+1 Incrementa b
o1 o1 b-1 Decrementa b
o1 1 o a+b Suma a y b
o1 1 1 a+b+cin Suma a, b y cin
1 ooo nota Complemento de a
1 oo1 not b Complemento de b
1 o1 o a and b AND lógico
1 o1 1 a or b OR lógico
U ni dad Lógica
1 1 oo a nand b NAND lógico
1 1 o1 a nor b NOR lógico
111o a xor b XOR lógico
1111 a xnor b XNOR lógico

318
DISEÑO DE LÓGICA COMBINACIONAL

Ejercicio 4.11

Escriba en VHDL la entity y la architecture que describe el comportamiento


de una puerta NOT de 1 entrada. A continuación, escriba en VHDL la entity y la
architecture que describe el comportamiento de una puerta AND de 4 entradas.

Finalmente, escriba en VHDL la entity y la architecture que describe la


estructura al nivel de puertas lógicas de un circuito combinacional decodificador
3 a 8, con entrada enable. La architecture debe describir la estructura del circuito
combinacional, instanciando y conectando adecuadamente las puertas lógicas NOT
y AND cuyo diseño ha realizado anteriormente.

Programe en VHDL el banco de pruebas del circuito decodificador que ha diseña-


do. Explique detalladamente cómo el programa de test comprueba exhaustivamente
el valor del UUT para todos los posibles valores de la entrada. El banco de pruebas
debe comprobar que los valores obtenidos del UUT coinciden con los esperados,
mostrando el correspondiente mensaje en caso de que no coincidan. Al final del test,
debe mostrarse un mensaje indicando el número total de errores.

Ejercicio 4.12

A continuación de muestra la tabla de la verdad de un circuito conversor de


código binario de 3 bits a código Gray. Debajo se ha escrito la entity del circuito.

X y
000 000
001 001
010 011
011 010
100 110
101 111
110 101
111 100

entity codGray is
port ( y : out std_logic_vector(2 downto O);
x : in std_logic_vector(2 downto O) );
end entity codGray;

319
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Escriba en VHDL, de las tres formas indicadas a continuación, la architecture


que describe el comportamiento del circuito combinacional conversor de código
binario de 3 bits a código Gray.

- En primer lugar, emplee un bloque process con una sentencia case.

- En segundo lugar, emplee una asignación concurrente de selección (with -


select).

- Finalmente, describa la estructura del circuito, empleando para ello dos puertas
lógicas XOR de dos entradas. Tenga en cuenta que el bit en la posición i de
una palabra del código Gray es 1 si los bits en las posiciones i e i + 1 de la
correspondiente palabra binaria son diferentes. La entity de la puerta lógica
XOR se muestra a continuación.

entity xor2 is
port ( yO out std_logic;
xO, x1 in std_logic );
end entity xor2;

Asimismo, programe en VHDL un banco de pruebas que testee exhaustivamente


el circuito.

320
DISEÑO DE LÓGICA COMBINACIONAL

4.10. SOLUCIONES DE LOS EJERCICIOS

Solución al Ejercicio 4.1

El Código VHDL 4.23 es el diseño de un codificador 4:2 con prioridad. Obsérvese


que el bloque process es activado cuando cambia cualquiera de las entradas, ya
que el bloque es sensible a estas cuatro señales. Se emplean sentencias if-elsif para
inspeccionar de manera priorizada las entradas. El Código VHDL 4.24 y 4.25 es el
banco de pruebas para este diseño.

-- Codificador 4:2 con prioridad


-- Fich ero: codificador_4_2_prioridad. vhd
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 O);
i3, i2, i1, iO : in std_logic );
end entity codificador_ 4_2_prioridad;

architecture codificador_ 4_2_prioridad of codificador_ 4_2_prioridad is


begin
process (i3, i2, i1, iO) is --Activado cuando cambia alguna entrada
begin

if ( (i3='1') or (i2='1') or (i1='1') or (i0='1')) then


valida <= '1 '; -- Indica que la salida es válida
else
valida <= '0'; -- Salida no válida, puesto que no hay entrada
end if;

if ( i3=' 1 ' ) then codificada <= 11 11 11 ;


elsif ( i2=' 1 ') then codificada<= 11 10 11 ;
elsif ( i 1 = ' 1 ' ) then codificada<= 11 01 11 ;
el se codificada <= 11 00 11 ;
end if;

end process;
end architecture codificador_4_2_prioridad;

Código VHDL 4.23: Diseño de un codificador 4:2 con prioridad.

321
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del codificador 4:2 con prioridad


-- Fichero: bp_codificador_4_2. vhd
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;

architecture bp_codificador_4_2 of bp_codificador_4_2 is


-- Salidas UUT
signal valida : std_logic;
signal codificada : std_logic_vector ( 1 downto O);
-- Entradas UUT
signal i3, i2, i1, iO : std_logic;

component codificador_ 4_2_prioridad is


port ( valida : out std_logic;
codificada : out std_logic_vector(1 downto O);
i3, i2, i1, iO : in std_logic );
end component codificador_ 4_2_prioridad;

begin -- Cuerpo de la arquitectura


UUT : component codificador_4_2_prioridad port map
(valida, codificada, i3, i2, i1, iO);
main : process is
variable temp : unsigned (3 downto O); -- Usado en los cálculos
variable esperado_ valida : std_logic;
variable esperado_codificada : std_logic_vector(1 downto O);
variable error _count : integer := O;
begin
report "Comienza la simulación";
-- GeneraT todos los posibles valoTes de entrada
for i in O 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));
iO <= std_logic(temp(O) );
-- Calcular el valor esperado
if (i=O) 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;

Código VHDL 4.24: Parte inicial del banco de pruebas de un codificador 4:2 con prioridad.

322
DISEÑO DE LÓGICA COMBINACIONAL

-- Continua el banco de pruebas del codificador 4:2 con prioridad

wait for DELAY; -- Espera y compara con las salidas de UUT

if ( esperado_ valida / = valida ) then


report "ERROR en la salida valida. Valor esperado: " &
std_logic' image (esperado_ valida) &
", valor actual: " &
std_logic' image(valida) &
" en el instante: " &
time ' image ( now);
error count := error_count +1;
end if;

if ( esperado_codificada /= codificada ) then


report "ERROR en la salida codificada. Valor esperado: 11 &
std_logic' image ( esperado_codif icada( 1)) &
std_logic' image ( esperado_codif icada( O)) &
", valor actual: " &
std_logic' image (e o di f i cada ( 1)) &
std_logic' image( codificada( O)) &
" en el instante: " &
time ' image ( now);
error count := error_count + 1;
end if;

end loop; -- Final del b'ucle for de posibles valores de entrada

-- Informe del número total de errores


if (error_count =o) then
report "Simulación finalizada sin errores";
el se
report "ERROR: Hay " &
integer'image(error_count) &
"errores.";
end if;

wait; -- Final de la simulación

end process main;

end architecture bp_codificador_4_2;

Código VHDL 4.25: Parte final del banco de pruebas de un codificador 4:2 con prioridad.

323
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 4.2

La tabla de la verdad del circuito, y la función lógica obtenida a partir de dicha


tabla, son los siguientes:

x3 x2 x1 xO F = X<5
o o o o 1
o o o 1 1
o o 1 o 1
o o 1 1 1
o 1 o o 1
o 1 o 1 o
o 1 1 o o
o 1 1 1 o
1 - - - o
F (not x3 and not x2) or (not x3 and x2 and not x1 and not xO)

El diseño del circuito y su banco de pruebas se muestran en el Código VHDL 4.26


y 4.27, respectivamente.

-- Comparador F = X< 5:
F = x3'x2'+x3'x2x1 'xO'
-- Fichero: comparaXmenor5.vhd
library IEEE; use IEEE. std_logic_1164. all;
entity comparaXmenor5 is port
( F : out std_logic;
x : in std_logic_vector ( 3 downto O) ) ;
end entity comparaXmenor5;
architecture comparaXmenor5 of comparaXmenor5 is
begin
F <= (not x(3) and not x(2))
or (not x(3) and x(2) and not x(1) and not x(O));
end architecture comparaXmenor5;

Código VHDL 4.26: Diseño del circuito comparador de 4 bit para X<5.

324
DISEÑO DE LÓGICA COMBINACIONAL

-- Banco de pntebas comparador X< 5


-- Fichero: bp_comparaXmenor5. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity bp_comparaXmenor5 is
end entity bp_comparaXmenor5;

architecture bp_comparaXmenor5 of bp_comparaXmenor5 is


signal F : std_logic; -- Conectar salidas UUT
signal x : std_logic_vector(3 downto O); -- Conectar entradas UUT

component comparaXmenor5 is port


( F : out std_logic;
X : in std_logic_vector(3 downto 0));
end component comparaXmenor5;

begin
-- Instanciar y conectar UUT
uut : component comparaXmenor5 port map
( F => F, X => X );

gen_ ve e_ test : process


variable test_in : unsigned (3 downto O) := B11 0000 11 ; - - Vector de test
variable num_errores : integer := O; -- Num ero de errores
begin

for count in O to 15 loop


x(3) <= test_in(3);
x(2) <= test_in(2);
x(1) <= test_in(1);
x(O) <= test_in(O);
wait for 10 ns;
-- Comprueba resultado
if (F= 'O' and test_in<5) or (F=' 1' and test_in>=5) then
report 11 Error. Valor 11 & integer' image(to_integer(test_in) );
num_errores := num_errores + 1;
end if;
test_in := test_in + 1;
end loop;

report 11
Test completo. Hay &
integer'image(num_errores) &
11
errores. 11 ;
wait; --Final simulación
end process gen_vec_test;

end architecture bp_comparaXmenor5;

Código VHDL 4.27: Banco de pruebas del circuito comparador de 4 bit para X<5.

325
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 4.3

El diseño del decodificador BCD a 7 segmentos empleando una sentencia case


y su banco de pruebas se muestran en el Código VHDL 4.28 y 4.29. Obsérvese
que se han declarado en el bloque process dos variables, bcd y segs, del tipo
std_logic_vector. La variable bcd es el resultado de concatenar las cuatro señales
de entrada y la variable segs se usa para almacenar el estado de los segmentos del
display. Cada componente de la variable segs es asignado a una señal de salida.

-- D ecodificador BCD a 7 segmentos. Architecture con sentencia case


-- Fichero : bcdTo7SegCASE. vhd
library IEEE;
use IEEE. std_logie_1164. all;
entity BCDto7seg is
port( a, b, e, d, e, f, g : out std_logic;
i3, i2, i1, iO : in std_logic);
end BCDto7seg;
architecture BCDto7segCASE of BCDto7seg is
begin
process {i3, i2, i1, iO)
variable bed : std_logic_vector ( 3 downto O);
variable segs : std_logic_vector ( 6 downto O);
begin
bed := i3 & i2 & i1 & iO;
case bed is
when "0000" => segs .- "1111110";
when "0001" => segs .- "0110000";
when "0010" => segs .- "1101101";
when "0011" => segs .- "1111001";
when "0100" => segs .- "0110011";
when "0101" => segs .- "1011011";
when "0110" => segs .- "1011111";
when "0111" => segs .- "1110000";
when "1000" => segs := "1111111";
when "1001" => segs := "1110011";
when others => segs := "0000000";
end case;
a <= segs(6); b <= segs(5); e <= segs(4); d <= segs(3);
e <= segs(2); f <= segs(1); g <= segs(O);
end process;
end architecture BCDto7segCASE;

Código VHDL 4.28: Decodificador BCD a 7 segmentos descrito empleando una sentencia case.

326
DISEÑO DE LÓGICA COMBINACIONAL

-- Banco de pruebas del decodificador BCD a 7 segmentos


-- Fich ero: bp_bcdTo7Seg. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity bp_bcdTo7Seg is
constant DELAY : time := 10 ns; -- Retardo usado en el test
end entity bp_bcdTo7Seg;
architecture bp_bcdTo7Seg of bp_bcdTo7Seg is

signal segs : std_logic_vector(6 downto O);


signal bcd : stdJogic_vector(3 downto O);

component bcdTo7Seg is
port ( a, b, e, d, e, f, g : out std_logic;
i3, i2, i1, iO : in std_logic);
end component bcdTo7Seg;

begin
UUT : component bcdTo7Seg port map
(segs(6), segs(5), segs(4), segs(3), segs(2),
segs(1), segs(O), bcd(3), bcd(2), bcd(1), bcd(O));
ve e_ test : process is
variable valor : unsigned (3 downto O);
begin
report "Comienza la simulación";
-- Gen erar todos los posibles valores de entrada
for i in O to 9 loop
valor := TO_UNSIGNED(i,4);
bcd <= std_logic(valor(3)) & std_logic(valor(2))
& std_logic(valor(1)) & std_logic(valor(O));
wait for DELAY;
end loop;
report "Simulación finalizada";
wait; -- Final de la simulación
end process ve e_ test;

end architecture bp_bcdTo7Seg;

Código VHDL 4.29: Banco de pruebas del decodificador BCD.

327
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 4.4

El diseño del decodificador BCD a 7 segmentos empleando una sentencia if se


muestra en Código VHDL 4.30.

-- D ecodificador BCD a 7 segmentos. Architecture: sentencia if


-- Fichero: bcdTo7SegiF. vhd
library IEEE;
use IEEE. std_logie_1164. all;
entity BCDto7seg is
port( a, b, e, d, e, f, g : out std_logic;
i3, i2, i1, iO : in std_logic);
end BCDto7seg;
architecture BCDto7segiF of BCDto7seg is
begin
process (i3, i2, i1, iO)
variable bed : std_logic_vector ( 3 downto O);
variable segs : std_logic_vector ( 6 downto O);
begin
bed := i3 & i2 & i1 & iO;
if (bed = "0000") then segs := "1111110";
elsif (bed = "0001") then segs := "0110000";
elsif (bed = "0010") then segs := "1101101";
elsif (bed = "0011") then segs := "1111001";
elsif (bed = "0100") then segs := "0110011";
elsif (bed = "0101") then segs := "1011011";
elsif (bed = "0110") then segs := "1011111";
elsif (bed = "0111") then segs := "1110000";
elsif (bed = "1000") then segs := "1111111";
elsif (bed = "1001") then segs := "1110011";
else segs := "0000000";
end if;
a <= segs(6);
b <= segs(5);
e <= segs(4);
d <= segs(3);
e <= segs(2);
f <= segs(1);
g <= segs(O);
end process;
end architecture BCDto7segiF;

Código VHDL 4.30: Decodificador BCD descrito empleando una sentencia if.

328
DISEÑO DE LÓGICA COMBINACIONAL

Solución al Ejercicio 4.5

El diseño del decodificador BCD a 7 segmentos empleando una sentencia de


asignación concurrente condicional a una señal se muestra en Código VHDL 4.31.

-- Decodificador BCD a 1 segmentos. Architecture: sentencia concurrente condicional


-- Fichero: bcdTo1SegConc. vhd
library IEEE;
use IEEE. std_logie_1164. all;
entity BCDto7seg is
port( a, b, e, d, e, f, g : out std_logic;
i3, i2, i1, iO : in std_logic);
end BCDto7seg;
architecture BCDto7segCone of BCDto7seg is
signal bed : std_logic_vector ( 3 downto O);
signal segs : std_logic_vector ( 6 downto O);
begin
bed <= i3 & i2 & i1 & iO;
segs <= 11 1111110 11 when (bed = 11 0000 11 )
else 11 0110000 11 when (bed = 11 0001 11 )
else 11 1101101 11 when (bed = 11 0010 11 )
else 11 1111001 11 when (bed = 11 0011 11 )
else 11 0110011 11 when (bed = 11 0100 11 )
else 11 1011011 11 when (bed = 11 0101 11 )
else 11 1011111 11 when (bed = 11 0110 11 )
else 11 1110000 11 when (bed 11
0111 11 )
else 11 1111111 11 when (bed 11
1000 11 )
else 1110011 when (bed
11 11 11
1001 11 )
else 11 0000000 11 ;
a <=segs(6);
b <=segs(5);
e <=segs(4);
d <=segs(3);
e <=segs(2);
f <=segs(1);
g <=segs(O);
end architecture BCDto7segCone;

Código VHDL 4.31: Decodificador BCD descrito empleando una sentencia de asignación
concurrente condicional.

329
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 4.6

El diseño del decodificador BCD a 7 segmentos empleando una sentencia select


se muestra en Código VHDL 4.31.

-- Decodificador BCD a 7 segmentos. Architecture: sentencia select


-- Fichero: bcdTo7Seg WithSelect. vhd
library IEEE;
use IEEE . std_logie _1164 . all;

entity BCDto7seg is
port( a, b, e, d, e, f, g : out std_logic;
i3, i2, i1, iO : in std_logic);
end BCDto7seg;

architecture BCDto7segWi thSeleet of BCDto7seg is


signal bed : std_logic_vector ( 3 downto O);
signal segs : std_logic_vector ( 6 downto O);
begin
bed <= i3 & i2 & i1 & iO;
with bed select
segs <= 11 1111110 11 when 11 0000 11 ,
11
0110000 11 when 11 0001 11 ,
11
1101101 11 when 11 0010 11 ,
11
1111001 11 when 11 0011 11 ,
11
0110011 11 when 11 0100 11 ,
11
1011011 11 when 11 0101 11 ,
11
1O11111 11 w hen 11 O11 O11 ,
11
1110000 11 when 11 0111 11 ,
11
1111111 11 when 11 1000 11 ,
11
1110011 11 when 11 1001 11 ,
11
0000000 11 when others;
a <= segs(6);
b <= segs(5);
e <= segs(4);
d <= segs(3);
e <= segs(2);
f <= segs(1);
g <= segs(O);
end architecture BCDto7segWi thSeleet;

Código VHDL 4.32: Decodificador BCD descrito empleando una sentencia with select.

330
DISEÑO DE LÓGICA COMBINACIONAL

Solución al Ejercicio 4. 7

El diseño del sumador y su banco de pruebas se muestran en el Código VHDL 4.33,


4.34 y 4.35.

Obsérvese que en la architecture del sumador hay una sentencia generate


iterativa que tiene la etiqueta conexion. El cuerpo del bucle generate incluye la
sentencia que instancia y conecta los sumadores completos de 1 bit. Esta sentencia
se ejecuta N veces, desde que el índice del bucle, k, toma el valor N-1 hasta que toma
el valor O.

-- Sumador de 2 números de N bits


-- Fichero: sumador_Nbits_generate.vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity sumador_Nbits is

generic( N: integer :=4);


port ( s : out std_logic_vector(N- 1 downto O);
C_out : out std_logic;
x, y : in std_logic_vector(N-1 downto O);
C_in : in std_logic);

end entity sumador_Nbits;

architecture sumador_Nbits of sumador Nbits is

signal carryv: std_logic_vector(N downto O);


component sum_completo is
port ( s, C_out : out std_logic;
x, y, C_in : in std_logic);
end component sum_completo;

begin
carryv(O) <= C_in;
--Instanciación y conexión de componentes usando GENERATE
conexion: for k in N-1 downto O generate --GENERATE iterat'ivo
FullAdder: sum_completo
port map (s(k), Carryv(k+1), x(k), y(k),Carryv(k));
end generate conexion;

C_out <= carryv(4);


end architecture sumador_Nbits;

Código VHDL 4.33: Diseño del sumador de N bits.

331
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del sumador paralelo de 4 bits


-- Fichero: bp_sum._Nbits. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity bp_sum_Nbi ts is -- El banco de pn.Lebas no tiene


end entity bp_sum_Nbi ts; -- ni entradas ni salidas
architecture bp_sum_Nbi ts of bp_sum_Nbi ts is
-- Señales para conectar el UUT
signal C_out, C_in : std_logic_vector(O downto O);
signal x, y, s : std_logic_vector(3 downto O);

component sumador_Nbits is
generic (N: integer :=4);
port ( s : out std_logic_vector(N-1 downto O);
C_out : out std_logic;
x, y : in std_logic_vector(N-1 downto O);
C_in : in std_logic);
end component sumador _Nbi ts;

begin
-- Instanciar y conectar UUT
uut : component sumador_Nbits port map
( s => s, C_out => C_out(O),
x => x, y => y, C_in => C_in(O) );

Código VHDL 4.34: Parte inicial del banco de pruebas del sumador de 4 bits.

332
DISEÑO DE LÓGICA COMBINACIONAL

-- Continuación del banco de pruebas del s.umador paralelo de 4 bits


-- Fichero: bp_surn_Nbits.vhd

-- Crear vectores de test y comprobar salidas del UUT


gen_ vec_ test : process
variable sumaEsperada : unsigned (4 downto O); --Resultado suma
variable num_errores : integer := O; -- Num ero de errores
begin
for sumando_X in O to 2**4-1 loop
for sumando_Y in O to 2**4-1 loop
for acarreo_in in O to 1 loop
sumaEsperada := to_unsigned(acarreo_in,5) +
to_unsigned(sumando_x,5) +
to_unsigned( sumando_y ,5);
x <= std_logic_vector(to_unsigned(sumando_x,4));
y <= std_logic_vector(to_unsigned(sumando_y,4));
C_in <= std_logic_vector(to_unsigned(acarreo_in,1));
wait for 100 ns;
report time' image(now) &
" : 11 &
std_logic' image ( sumaEsperada( 4)) &
std_logic' image ( sumaEsperada( 3)) &
std_logic' image ( sumaEsperada( 2)) &
std_logic' image ( sumaEsperada( 1)) &
std_logic' image ( sumaEsperada( O)) &
"Suma calculada : " &
std_logic' image(C_out(O)) &
std_logic' image ( s ( 3)) &
std_logic' image ( s ( 2)) &
std_logic' image ( s ( 1)) &
std_logic' image ( s (O))

if (sumaEsperada /= unsigned( C_out & s )) then -- Comprueba resultado


num_errores := num_errores + 1;
report "ENTRA EN BUCLE" ;
end if;
end loop;
end loop;
end loop;
report "Test completo. Hay " &
integer' image(num_errores) &
"errores.";
wait;
end process gen_vec_test;
end architecture bp_sum_Nbi ts;

Código VHDL 4.35: Parte final del banco de pruebas del sumador de 4 bits.

333
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 4.8

El diseño del circuito desplazador y su banco de pruebas se muestran en el Código


VHDL 4.36, 4.37 y 4.38.

Las funciones shift_left, shift_right, rotate_left y rotate_right, empleadas en


el banco de pruebas, se encuentran en el paquete IEEE.numeric_std.

-- Desplazador de 4 bits
-- Fichero: desplazador. vhd
library IEEE;
use IEEE . std_logic_1164. all;

entity desplazador is
port( salida : out std_logic_vector(3 downto O);
op : in std_logic_vector(1 downto O);
entrada : in std_logic_vector(3 downto o));
end desplazador;
architecture desplazador of desplazador is
begin

salida <= entrada(2 downto o) & 'o' when (op = "00")


else '0' & entrada(3 downto 1) when (op = "01")
else entrada(2 downto O) & entrada(3) when (op = "10")
else entrada(O) & entrada(3 downto 1);
end architecture desplazador;

Código VHDL 4.36: Diseño del circuito desplazador.

334
DISEÑO DE LÓGICA COMBINACIONAL

-- Banco de pruebas de l desplazador. FicheTo: bp_desplazadoT. vhd


library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity bp_desplazador is
constant DELA Y : time := 10 ns; -- R etaTdo 'Usado en el test
end entity bp_desplazador;

architecture bp_desplazador of bp_desplazador is


signa! salida : std_logic_vector(3 downto O); --Salida UUT
signa! op : std_logic_vector(1 downto O) ; --Entmdas UUT
signa! entrada : std_logic_vector(3 downto O);

component desplazador is
port ( salida : out std_logic_vector(3 downto O);
op : in std_logic_vector ( 1 downto O);
entrada : in std_logic_vector(3 downto o));
end component desplazador ;

-- PmceduTe que calcula la salida ( expecterLs) y lo compaTa con el


-- valor de salida que se pasa como argumento ( actuaL s)
-- Si ambos valoTes no coinciden, se muestTa un mensaje y se
-- incTementa el contadoT de eTroTes (erToLcount)
procedure check_desp
( op : in integer;
data : in unsigned(3 downto O);
actual_s : in unsigned (3 downto O);
error _count: inout integer ) is
var iable expected_s : unsigned(3 downto O) ;
begin
case op is
when O = > expected_s := shift_left(data,1);
when 1 = > expected_s := shift_right(data,1);
when 2 = > expected_s := rotate_left(data,1) ;
when others = > expected_s := rotate_right(data,1);
end case;
assert( expected_s = actual_s)
report "ERROR. Entrada: " & integer' image(to_integer(data)) &
", Operacion: " & integer' image( op) &
" , resultado esperado: " &
integer'image(to_integer(expected_s)) &
",resultado actual:" &
integer' image(to_integer(actual_s)) &
" en el instante " &
time ' image ( now) ;

if ( expected_s / = actual _s) then


error _count := error _count + 1;
end if;
end procedure check_desp; -- Fin de la defin'i ción del procedure

Código VHDL 4.37: Primera parte del banco de pruebas del circuito desplazador.

335
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Continuación del banco de pruebas. Fichero: bp_desplazador. vhd


begin
UUT : component desplazador port map (salida, op, entrada);
vec_test : process is
variable temp : std_logic_vector (5 downto O);
variable error_count: integer := O;
begin
report 11 Comienza la simulación";
-- Generar todos los posibles valores de entrada
for i in O to 2**6-1 loop
temp := std_logic_vector(to_unsigned(i,6));
op <= temp(5 downto 4);
entrada <= temp(3 downto O);
wait for DELAY;
checlLdesp ( to_integer ( unsigned ( op)), unsigned (entrada), unsigned (salida) , error_count);
end loop;
-- Informe mostrando el resultado del test
if ( error_count=O) then
report 11 Finaliza la simulación: O errores 11 ;
el se
report "Finaliza la simulación: 11 & integer'image(error_count) & 11
errores";
end if;
wait; -- Termina la simulación
end process vec_test;
end architecture bp_desplazador;

Código VHDL 4.38: Segunda parte del banco de pruebas del circuito desplazador.

336
DISEÑO DE LÓGICA COMBINACIONAL

Solución al Ejercicio 4.9

El comparador de dos números de 1 bit satisface la siguiente función lógica:


Pi+l = (xi xnor Yi) and Pi· El diseño de este circuito, así como el diseño del circuito
comparador de N bits, se muestra en Código VHDL 4.39. El Código VHDL 4.40 es
el banco de pruebas del circuito comparador de dos números de N bits.

-- CompaTador de dos números de 1 bit. Fichero: comparadorEQ1bit.vhd


library IEEE;
use IEEE. std_logic_ii64. all;

entity comparadorEQibit is port


( pi : out std_logic;
pO, x, y : in std_logic);
end entity comparadorEQibit;
architecture comparadorEQ i bit of comparadorEQ i bit is
begin
pi <= (x xnor y) and pO;
end architecture comparadorEQibit;
-- CompaTadoT igualdad de 2 números de N bits. Fichero: compamdorEQNbits.vhd
library IEEE;
use IEEE. std_logic_ii64. all;

entity comparadorEQNbi ts is
generic (N: integer :=4);
port ( s : out std_logic;
x, y : in std_logic_vector(N-i downto O));
end entity comparadorEQNbi ts;
architecture comparadorEQNbi ts of comparadorEQNbi ts is
signal p: std_logic_vector(N downto O);

component comparadorEQibi t is
port ( pi : out std_logic;
pO, x, y : in std_logic);
end component comparadorEQibi t;
begin
p(O) <= 'i';
--Instanciación y conexión de componentes usando GENERATE
conexion: for k in N-i downto O generate --GENERATE iterativo
comparadorNbits: comparadorEQibit
port map (p(k+i), p(k), x(k), y(k));
end generate conexion;
s <= p(N);
end architecture comparadorEQNbi ts;

Código VHDL 4.39: Diseño del circuito comparador de igualdad de dos números de 1 bit y del
circuito comparador de igualdad de dos números de N bits.

337
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pr'll,ebas comparador de 'igualdad de N bits


library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity bp_comparadorEQNbi ts is
end entity bp_comparadorEQNbi ts;

architecture bp_comparadorEQNbi ts of bp_comparadorEQNbi ts is


signa} s : std_logic; -- Conectar salidas UUT
signa} x, y : std_logic_vector(3 downto O); -- Conectar entradas UUT

component comparadorEQNbi ts is
generic ( N: integer : =4);
port ( s : out std_logic;
x, y : in std_logic_vector(N-1 downto O));
end component comparadorEQNbi ts;

begin
-- Instanciar y conectar UUT
uut : component comparadorEQNbi ts port map
( S => s, X => x, y => y );
gen_ ve e_ test : process
variable num_errores : integer := O; -- Numero de errores
begin
for op_X in O to 2**4-1 loop
for op_Y in O to 2**4-1 loop
x <= std_logic_vector(to_unsigned( op_x,4) );
y <= std_logic_vector(to_unsigned( op_y,4) );
wait for 10 ns;
-- Comprueba resultado
if (x=y and s='O') or (x/=y and s='1') then
report 11 Error. Valores 11 &
integer'image(op_x) &
.. , 11 &
integer' image ( op _y);
num_errores := num_errores + 1;
end if;
end loop;
end loop;

report Test completo. Hay 11


11
&
integer'image(num_errores) &
11
errores. 11 ;
wait; --F'inal sirmLlación
end process gen_ ve e_ test;
end architecture bp_comparadorEQNbits;

Código VHDL 4.40: Banco de pruebas del circuito comparador de igualdad de 4 bits.

338
DISEÑO DE LÓGICA COMBINACIONAL

Solución al Ejercicio 4.10

El diseño de la ALU se muestra en el Código VHDL 4.41. Las constantes globales


de la AL U se han definido en un package. En el diseño de la AL U se han declarado
las señales ari th y logic que se usan para guardar el resultado de las unidades
aritmética y lógica, respectivamente. El multiplexor recibe ambas señales y selecciona
cuál de ellas es la salida. Esta selección se realiza en función del valor del bit más
significativo de la entrada de selección.

El banco de pruebas de la ALU se muestra en Código VHDL 4.42- 4.45. El Código


VHDL 4.42 contiene un package en el cual de definen las constantes globales del
banco de pruebas, cuyo valor es calculado a partir de las constantes globales de la
AL U. Se ha seleccionado un conjunto de vectores de test atendiendo a los criterios
siguientes:

- Se escogen valores de los operandos entorno al cero. Por ejemplo: -2, -1, O,
1 y 2.

- Se escogen valores de los operandos en el límite inferior de su rango. Por ejem-


plo, si MIN_NEG_DATA representa el valor mínimo que puede tomar el operando,
entonces se escogen los valores MIN_NEG_DATA, ... , MIN_NEG_DATA+4 para cada
uno de los operandos.

- Se escogen valores de los operandos en el límite supenor de su rango. Si


MAX_POS_DATA representa el valor máximo que puede tomar el operando, en-
tonces se escogen los valores MAX_POS_DATA-4, ... , MAX_POS_DATA para cada uno
de los operandos.

- Finalmente, se escogen algunos valores "al azar", más o menos distribuidos


uniformemente en el rango de los operandos.

339
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Definición de constantes globales de la ALU. Fichero: ALU_CONSTANTS.vhd


package ALU_CONSTANTS is
constant WIDTH integer := 8;
-- Núm. bits de los operandos
constant SEL_BITS integer := 4;
-- Núm. bits selección de operación
end package ALU_CONSTANTS;
-- Diser1o de la AL U. Fichero: AL U. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE.numeric_std.all;
use work. ALU_CONSTANTS. all;
entity ALU is
port ( y : out std_logic_vector (WIDTH-1 downto O);
a, b : in std_logic_vector (WIDTH-1 downto O);
e in : in std_logic_vector (O downto O);
sel : in std_logic_vector (SEL_BITS-1 downto O) );
end entity ALU;
architecture ALU_concurrente of ALU is
signal arith, logic: std_logic_vector(WIDTH-1 downto O);
begin
--Unidad Aritmética
with sel(SEL_BITS-2 downto O) select
arith <=a when "000",
std_logic_vector(signed(a)+1) when "001",
std_logic_vector(signed(a)-1) when "010",
b when "O 11",
std_logic_vector(signed(b)+1) when "100",
std_logic_vector(signed(b)-1) when "101",
std_logic_vector(signed(a)+signed(b)) when "110",
std_logic_vector(signed( a)+signed(b )+signed("OOO" & e in))
when others;
--Unidad Lógica
with sel(SEL_BITS-2 downto O) select
logic <= not a when "000",
not b when "001",
a and b when "010",
a or b when "011",
a nand b when "100",
a nor b when "101",
a xor b when "110",
a xnor b when others;
--Multiplexor
with sel(SEL_BITS-1) select
y <= arith when '0',
logic when others;
end architecture ALU_concurrente;

Código VHDL 4.41: Diseño de la ALU cuyo circuito se muestra en la Figura 4.12.

340
DISEÑO DE LÓGICA COMBINACIONAL

-- Definición de constantes globales del banco de pruebas de la AL U


--Fichero: bp_ALU_CONSTANTS.vhd
use work. ALU_CONSTANTS. all;
package bp_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 DELA Y : time : = 1O ns;
end package bp_ALU_CONSTANTS;
-- Banco de pruebas para la AL U
--Fichero: bp_ALU.vhd
library IEEE;
use IEEE. std_logie_1164. all;
use IEEE. numerie_std. all;
use work. bp_ALU_CONSTANTS. all;
use work.ALU_CONSTANTS.all;
entity bp_ALU is
end entity bp_ALU;

architecture bp_ALU of bp_ALU is


signal a, b, y : std_logic_vector (WIDTH-1 downto O);
signal e in : std_logic_vector (O downto O);
signal sel : std_logic_vector (SEL_BITS-1 downto O);

component ALU is
port ( y : out std_logic_vector(WIDTH-1 downto O);
a, b : in std_logic_vector (WIDTH-1 downto O);
e in : in std_logic_vector (O downto O);
sel : in std_logic_vector (SEL_BITS-1 downto O) );
end component ALU;

Código VHDL 4.42: Package en el cual se definen las constantes usadas en el banco de pruebas
de la ALU cuyo circuito se muestra en la Figura 4.12 y comienzo de la definición del banco de
pruebas de la ALU.

341
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

---------------- Continua banco de pruebas para la AL U {fichero bp_AL U. vhd) -------------

-- Procedure que calcula C ( expectecL C) y lo compara con el


-- valor de C que se pasa como argumento (actuaL C)
-- Si ambos valores no coinciden, se muestra 'Un mensaje y se
-- incrementa el contador de errores (error_count)
procedure check_ALU
( a, b, cin, sel : in integer;
actual_y : in std_logic_vector (WIDTH-1 downto O);
error _count : inout integer ) is
variable expected_y : integer;
begin
case sel is
when O => expected_y := a;
when 1 => expected_y := a+1;
when 2 => expected_y := a-1;
when 3 => expected_y := b;
when 4 => expected_y := b+1;
when 5 => expected_y := b-1;
when 6 => expected_y := a+b;
when 7 => expected_y := a+b+cin;
when 8 => expected_y := TO_INTEGER(signed(
not std_logic_vector(TO_SIGNED(a,WIDTH)) ));
when 9 => expected_y := TO_INTEGER(signed(
not std_logic_vector(TO_SIGNED(b, WIDTH)) ) ) ;
when 10 => expected_y := TO_INTEGER(signed(
std_logic_vector (TO _SI GNED (a, WIDTH)) and
std_logic_vector(TO_SIGNED(b,WIDTH)) ));
when 11 => expected_y := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED( a,WIDTH)) or
std_logic_vector(TO_SIGNED(b,WIDTH)) ) );
when 12 => expected_y := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED( a,WIDTH)) nand
std_logic_vector(TO_SIGNED(b,WIDTH)) ));
when 13 => expected_y := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED( a,WIDTH)) nor
std_logic_vector(TO_SIGNED(b,WIDTH)) ) );
when 14 => expected_y := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED( a,WIDTH)) xor
std_logic_vector(TO_SIGNED(b,WIDTH)) ) );
when others => expected_y := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED( a,WIDTH)) xnor
std_logic_vector(TO_SIGNED(b,WIDTH)) ));
end case;

Código VHDL 4.43: Fragmento del banco de pruebas de la ALU cuyo circuito se muestra en la
Figura 4.12: primera parte de la definición del procedure check_ALU.

342
DISEÑO DE LÓGICA COMBINACIONAL

---------------- Continua banco de pruebas para la AL U (fichero bp_AL U. vhd) -------------

expected_y := TO_INTEGER(TO_SIGNED( expected_y,WIDTH) );


-- Trunca el resultado a WIDTH bits
assert( expected_y = TO_INTEGER(SIGNED(actual_y)) )
report "ERROR. Operandos: " & integer' image(a) &
"," & integer'image(b) & "," & integer'image(cin) &
", Operacion: " & integer' image(sel) &
", resultado esperado:" & integer'image(expected_y) &
",resultado actual:" & integer'image(TO_INTEGER(signed(actual_y))) &
" en el instante " & time'image(now);
if ( expected_y / = TO_INTEGER( signed( actual_y))) then
error_count := error_count + 1;
end if;
end procedure check_ALU; -- Fin de la definición del procedure

begin
UUT : component ALU port map (y, a, b, cin, sel);
-- Bloque process para generar los vectores de test y comprobar el resultado
main : process is
variable error _count : integer := O;
begin
report "Comienza la simulación";
-- Vectores de test: operandos con valor- próx:imo a cer-o
for i in -2 to 2 loop
for j in -2 to 2 loop
for k in O to SEL_MAX loop
for 1 in O to 1 loop
a <= std_logic_vector(TO_SIGNED( i,WIDTH));
b <= std_logic_vector(TO_SIGNED(j,WIDTH));
sel <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
cin <= std_logic_vector(TO_SIGNED(l,1));
wait for DELAY;
check_ALU(i, j, 1, k, y, error_count);
end loop;
end loop;
end loop;
end loop;
-- Vectores de test: operandos con valor pr-óximo al mínimo
for i in MIN_NEG_DATA to MIN_NEG_DATA+4 loop
for j in MIN_NEG_DATA to MIN_NEG_DATA+4 loop
for k in O to SEL_MAX loop
for 1 in O to 1 loop
A <= std_logic_vector(TO_SIGNED(i,WIDTH) );
b <= std_logic_vector(TO_SIGNED(j ,WIDTH));
sel <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
cin <= std_logic_vector(TO_SIGNED(l,1) );
wait for DELAY;
check_ALU(i, j, 1, k, y, error_count);
end loop;
end loop;
end loop;
end loop;

Código VHDL 4.44: Fragmento de la definición del banco de pruebas de la ALU cuyo circuito
se muestra en la Figura 4.12.

343
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

---------------- Continua banco de pTuebas paTa la AL U (ficheTo bp_AL U. vhd) -------------

-- VectoTes de test: opeTandos con valoT pTóximo al máximo


for i in MAX_POS_DATA-4 to MAX_POS_DATA loop
for j in MAX_POS_DATA-4 to MAX_POS_DATA loop
for k in O to SEL_MAX loop
for 1 in O to 1 loop
a <= std_logic_vector(TO_SIGNED(i,WIDTH));
b <= std_logic_vector(TO_SIGNED(j ,WIDTH) );
sel <= std_logic_vector(TO_SIGNED(k,SEL_BITS) );
cin <= std_logic_vector(TO_SIGNED(l,1));
wait for DELAY;
check_ALU(i, j, 1, k, y, error_count);
end loop;
end loop;
end loop;
end loop;
-- VectoTes de test: opeTandos con valoTes "al azar
for i in O to 9 loop
for j in O to 9 loop
for k in O to SEL_MAX loop
for 1 in O to 1 loop
A <= std_logic_vector(TO_SIGNED( 41 *i-273,WIDTH));
b <= std_logic_vector(TO_SIGNED(89*j-384,WIDTH));
sel <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
cin <= std_logic_vector(TO_SIGNED(l,1) );
wait for DELAY;
check_ALU(41 *i-273, 89*j-384, 1, k, y, error_count);
end loop;
end loop;
end loop;
end loop;

wait for DELAY;

-- InjoTm e mostmndo el Tesultado del test


if (error_count=O) then
report "Finaliza la simulación sin errores";
else
report "Finaliza la simulación: " & integer' image(error_count)
& " errores";
end if;

wait; -- TeTmina la simulación


end process main;

end architecture bp_ALU;

Código VHDL 4.45: Parte final de la definición del banco de pruebas de la ALU cuyo circuito
se muestra en la Figura 4.12.

344
DISEÑO DE LÓGICA COMBINACIONAL

Solución al Ejercicio 4.11

Los diseños de la puerta NOT de 1 entrada y la puerta AND de 4 entradas se


muestran en el Código VHDL 4.46.

-- NOT de 1 entrada
library IEEE; use IEEE. std_logic_1164. all;

entity not 1 is
port ( y : out std_logic;
x : in std_logic ) ;
end entity not 1;
architecture not 1 of not 1 is
begin
y <= not x;
end architecture not1;

--AND de 4 entradas
library IEEE; use IEEE.std_logic_1164.all;
entity and4 is
port ( y : out std_logic;
xO, x1, x2, x3 : in std_logic ) ;
end entity and4;
architecture and4 of and4 is
begin
y <= xO and x1 and x2 and x3;
end architecture and4;

Código VHDL 4.46: Diseño de una puerta NOT de 1 entrada y de una puerta AND de 4
entradas.

345
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Nombrando las entradas y salidas del circuito tal como se muestra en la Fi-
gura 4.13a, la tabla de la verdad del circuito decodificador es la mostrada en la
Figura 4.13b.

E A¿ Al Ao y7 y6 Ys y4 y3 y2 yl Yo
o X X X o o o o o o o o
1 o o o o o o o o o o 1
1 o o 1 o o o o o o 1 o
1 o 1 o o o o o o 1 o o
1 o 1 1 o o o o 1 o o o
1 1 o o o o o 1 o o o o
1 1 o 1 o o 1 o o o o o
1 1 1 o o 1 o o o o o o
E
a) b) 1 1 1 1 1 o o o o o o o
Figura 4.13: Decodificador 3 a 8: a) circuito; y b) tabla de verdad.

El diagrama estructural al nivel de puertas lógicas del circuito decodificador y


su descripción en VHDL se muestran en la Figura 4.14 y en Código VHDL 4.47,
respectivamente.

Existen varias formas de realizar el diseño del banco de pruebas del circuito
decodificador 3 a 8 con entrada enable. En el Código VHDL 4.48 y 4.49 se muestra
una de ellas.

346
E:~r i~l A ,~~ i~l
2 1 0

1 11 ! ! 1 ( 111 ! 1 !1 : 111 1 1 1 i: ;
.···
. .~···w· ··.~····
........ ......··.··. .· .· .··. .· ..· · .··· ···. . .· .· .· .··. .· .· ..· · .· .········
.. . . . . . . . . .··. .
··. .· .···
. . .·· · · .··. .· .· .··. .· .· .· .··..· ..· · .···. . .· .· .· .· .· .··. .· .· .· .· ..·· .· .······
. .. .. . . . .· ·. ..
···. ·. .··. .· .· .· ..· · .· .··. .· .····
. .. .· .
· .· .··. .· .· .· ..· · .· ..···.

••• "!• i ':¡ •~J • • • ••• •••••••••••••• • ••••••••••••••••••••••.•• • • • • •••••••••• •• ••••••••••••• ••••••••••• • •••••••••:••
..........
; ~

: A.2::
n·ot_A.d ::1: :1: : 1: . : 1: • : • : : • : • :1 : : •• : • : • • • : • : : 1: • • • • : • • : : : : : : : : 1: : : : : : : : : : : : : : : 1 : : : : :·: : : : : : : :+:: ::::::::::::+.............; ............ i .
:A.f ::1::1: 1 ::::::: :1:;::
1
:::: :1; .... :::::1 ::::::::::::::1 .... .. .. .. 1., .. .. .. .. .... 1 1

. ... . ·ll<itj\1'
:::: :: : A.a:
. ·1·::· ·: 1·::· ·: :• •:::· • ·: ::• · 1·: 1·::• ·::· :::::
•· • •• :••::·¡·¡·
: : ·: ::
•· •:::::
•· ••·::••: ::•·¡·r
: ·::••:::
•••::••::•::· •::••¡•r•
: :::
•••: ::::
••· ••: :••¡•¡•
: : :::
•••: :::
••••::•::: : :::
•••¡•¡• •••: ::•••: ::::
••••¡•r •••••••••·11
• . • . . ' ' ' 1

:E :: : :: :: : : no(AO 1 : : : : 1: 1: 1. .. .. .. : 1: 1:;: : : : : : : : : : : : 1: 1: 1: : · : 1:1:1 :· .. ....


.. . .. . . 1 1.1 . . 11 1

__....
. . . . ... . . . . . ~
U1
•••• o ••• o ••• ••••••••• - •

• • • • o • • • ••• o •• o • • • • • t::rJ
. . . .. . .. . .. . . . .. . . .. . . . . . . .. . . Z•
o
tj
t::rJ
t"'
o,
0
Q
;¡:;..
o
o
~
tJ:j

Figura 4.14: Diagrama estructural al nivel de puertas lógicas del circuito decodificador 3 a 8.
z
;¡:;..
o
e,..;¡
oz
~ ;¡:;..
-..;¡ t"'
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Decodificador 3 a 8 bits
library IEEE;
use IEEE.std_logic_1164.all;

entity decodificador_3_a_8 is port


( Y7, Y6, Y5, Y4, Y3, Y2, Y1, YO : out std_logic;
E, AO, A1, A2 : in std_logic);
end entity decodificador_3_a_8;

architecture decodificador_3_a_8 of decodificador_3_a_8 is


signal not_A2, not_A1, not_AO : std_logic;
-- Declaración de las clases de los componentes
component not 1 is port
( y : out std_logic;
x : in std_logic ) ;
end component not 1;
component and4 is port
( y : out std_logic;
xO, x1, x2, x3 : in std_logic );
end component and4;
begin
-- Instanciación y conexión de los componentes
NOT_O : component not1 port map (not_AO, AO);
NOT_1 : component not1 port map (not_A1, A1);
NOT_2 : component not1 port map (not_A2, A2);
AND_7 : component and4 port map (Y7, E, A2, A1, AO);
AND_6 : component and4 port map (Y6, E, A2, A1, not_AO);
AND_5 : component and4 port map (Y5, E, A2, not_A1, AO);
AND_4 : component and4 port map (Y4, E, A2, not_A1, not_AO);
AND_3 : component and4 port map (Y3, E, not_A2, A1, AO);
AND_2 : component and4 port map (Y2, E, not_A2, A1, not_AO);
AND_1 : component and4 port map (Y1, E, not_A2, not_A1, AO);
AND_O : component and4 port map (YO, E, not_A2, not_A1, not_AO);
end architecture decodificador_3_a_8;

Código VHDL 4.47: Diseño del decodificador 3 a 8.

-- Banco de pruebas
-- decodificador_3_a_8
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity bp_decodificador_3_a_8 is
end entity bp_decodificador_3_a_8;

architecture bp_decodificador_3_a_8 of bp_decodificador_3_a_8 is


signal Y : std_logic_vector( 7 downto O); -- Conectar salidas UUT
signal E, AO, A1, A2 : std_logic; -- Conectar entradas UUT
component decodificador_3_a_8 is
port ( Y7 , Y6, Y5, Y4, Y3, Y2, Y1, YO : out std_logic;
E, AO, A1, A2 : in std_logic);
end component decodificador _3_a_8;

begin

Código VHDL 4.48: Fragmento inicial del banco de pruebas del decodificador 3 a 8.

348
DISEÑO DE LÓGICA COMBINACIONAL

-- InstanciaT y conectaT UUT


uut : component decodificador_3_a_8
port map( Y(7), Y(6), Y(5), Y(4), Y(3), Y(2), Y(1), Y(O), E, AO, A1, A2 );
gen_vec_test : process
variable test_in : unsigned (3 downto O); -- Vector de t est
variable esperado_ Y : std_logic_vector(7 downto O);
variable error _count : integer := O;
begin
test_in := B"OOOO";
report "Comienza la simulación";
for count in O to 15 loop
E <= test_in(3);
A2 <= test_in(2);
A1 < = test_in(1);
AO <= test_in(O);
if (count<8) then esperado_Y := "00000000";
elsif (count=8) then esperado_Y := "00000001";
elsif (count=9) then esperado_Y := "00000010";
elsif ( count=10) then esperado_ Y .- "00000100";
elsif (count=11) then esperado_Y .- "00001000";
elsif (count=12) then esperado_Y .- "00010000";
elsif ( count=13) then esperado_ Y .- "00100000";
elsif (count=14) then esperado_Y .- "01000000";
else esperado_Y := "10000000";
end if;

wait for 10 ns;


test_in := test_in + 1;
if ( esperado_ Y / = Y ) then
report "ERROR en la salida valida. Valor esperado: " &
std_logic' image( esperado_ Y(7)) &
std_logic' image( esperado_ Y( 6)) &
std_logic' image (esperado_ Y(5)) &
std_logic' image( esperado_ Y( 4)) &
std_logic' image( esperado_ Y(3)) &
std_logic' image( esperado_ Y(2)) &
std_logic' image( esperado_ Y( 1)) &
std_logic' image( esperado_ Y(O)) &
", valor actual: " &
std_logic' image(Y(7)) &
std_logic' image (Y ( 6)) &
std_logic' image(Y(5)) &
std_logic' image (Y ( 4)) &
std_logic' image (Y ( 3)) &
std_logic' image (Y ( 2)) &
std_logic' image (Y ( 1)) &
std_logic' image (Y (O)) &
" en el instante: " &
time' image ( now);
error count := error_count + 1;
end if;

end loop;
report "ERROR: Hay " &
integer'image(error_count) &
"errores.";
wait;
end process gen_vec_test;
end architecture bp_decodificador_3_a_8;

Código VHDL 4.49: Fragmento final del banco de pruebas del decodificador 3 a 8.

349
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 4.12

El diseño del conversor realizado de las tres maneras indicadas en el enunciado,


esto es, empleando un bloque process con una sentencia case, empleando una
asignación concurrente de selección (with - select) y describiendo la estructura
del circuito, compuesto empleando puertas lógicas XOR de dos entradas, se muestra
en el Código VHDL 4.50-4.52. El Código VHDL 4.53 es un posible banco de pruebas
para el circuito.

-- Codificador binario a código Gray


-- empleando un bloque pmcess con una sentencia case
library IEEE;
use IEEE. std_logic_1164. all;

architecture arch_codGrayCase of codGray is


begin
process ( x) is
begin
case x is
when ("000") = > y < = "000";
when ("001") = > y<="001";
when ("010") = > y < ="011";
when ("011") = > y < ="010";
when ("100") = > y<="110";
when ("101") = > y < ="111";
when ("110") = > y < ="101";
when ("111") = > y < ="100";
when others = > y < ="OOO";
end case;
end process;
end architecture arch_codGrayCase;

Código VHDL 4.50: Diseño del conversor de código binario a código Gray, empleando un bloque
process con una sentencia case.

350
DISEÑO DE LÓGICA COMBINACIONAL

-- Codificador binario a código Gray


-- asignacion concurrente de seleccion
library IEEE;
use IEEE. std_logic_1164. all;

architecture arch_codGraySelect of codGray is


begin
with x select
y <= 11 000 11 when ( 11 000 11 ) ,
11
001 11 when ( 11 001 11 ) ,
11
011 11 when ( 11 010 11 ) ,
11
010 11 when ( 11 011 11 ) ,
11
110 11 when ( 11 100 11 ) ,
11
111 11 when ( 11 101 11 ) ,
11
101 11 when ( 11 110 11 ) ,
11
100 11 when ( 11 111 11 ) ,
11
000 11 when others;
end architecture arch_codGraySelect;

Código VHDL 4.51: Diseño del conversor de código binario a código Gray, empleando una
asignación concurrente de selección (with - select).

-- Conversor binario a Gray


-- descripcion estructural usando
-- 2 puertas XOR de 2 entradas
library IEEE;
use IEEE. std_logic_1164 . all;
architecture arch_codGrayEst of codGray is
component xor2 is
port ( yO : out stdJogic;
xO, x1 : in std_logic);
end component xor2;
begin
y(2) <= x(2);
-- Instanciación y conexión de los componentes
xor2_1 : component xor2 port map
(yO => y(1), xO => x(2), x1 => x(1) );
xor2_2 : component xor2 port map
(yO = > y(O), xO => x(1), x1 => x(O) );
end architecture arch_codGrayEst;

Código VHDL 4.52: Diseño del conversor de código binario a código Gray, describiendo la
estructura del circuito al nivel de puertas lógicas.

351
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del conversor de código binario a Gray


library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity bp_codGray is
constant DELA Y : time := 10 ns; -- R etardo usado en el test
end entity bp_codGray;
architecture bp_codGray of bp_codGray is
signal x : std_logic_vector(2 downto O);
signal y : std_logic_vector ( 2 downto O);
component codGray is
port ( y : out std_logic_vector(2 downto O);
X : in std_}ogic_vector(2 downto 0));
end component codGray;
begin
UUT : component codGray port map
(y, x);
vec_ test : process is
variable temp : unsigned (2 downto O);
begin
report "Comienza la simulación";
-- Generar todos los posibles valores de entrada
for i in O to 7 loop
temp := TO_UNSIGNED(i,3);
x(2) <= std_logic(temp(2));
x(1) <= std_logic(temp(1));
x(O) <= std_logic(temp(O));
wait for DELAY;
end loop;
report "Simulación finalizada";
wait; -- Final de la simulación
end process vec_ test;
end architecture bp_codGray;

Código VHDL 4.53: Banco de pruebas del conversor de código binario a código Gray.

352
TEMA 5

REGISTROS Y MEMORIAS

5.1. Introducción
5.2. Registro de 4 bits
5.3. Registro multifunción
5.4. Registro de desplazamiento
5.5. Register file
5.6. Bus bidireccional y memorias
5.7. Lecturas recomendadas
5.8. Ejercicios de autocomprobación
5.9. Soluciones de los ejercicios
REGISTROS Y MEMORIAS

OBJETIVOS DOCENTES

Una vez estudiado el contenido del tema y realizados los ejercicios prácticos,
debería saber:

- Discutir la diferencia conceptual entre la operación de reset síncrono y asín-


crono. Describir ambas usando VHDL.

- Diseñar usando VHDL registros con las funcionalidades siguientes: reset, carga
serie y paralelo, lectura serie y paralelo, y desplazamiento de 1 bit hacia la
derecha e izquierda. Programar usando VHDL bancos de pruebas para los
registros que testeen las funcionalidades anteriores.

- Discutir las características de los registros siguientes: registro de desplazamien-


to, registro multifunción, register file y registro triestado.

- Realizar el diseño comportamental y estructural usando VHDL de un register


file.

- Programar bancos de pruebas que lean los vectores de test de fichero.

- Diseñar usando VHDL el acceso al bus de varios componentes mediante buffers


triestado.

- Diseñar en VHDL memorias RAM y ROM, y buses bidireccionales.

355
REGISTROS Y MEMORIAS

5.1. INTRODUCCIÓN

En el Tema 4 se estudió el diseño y test de hardware combinacional usando


VHDL. En este tema y en el siguiente se llevará a cabo un estudio similar, pero
enfocado en el diseño y test del hardware secuencial.

Los circuitos secuenciales almacenan bits, siendo los registros, las RAM y las
ROM los componentes básicos usados para ello.

Aparte de desempeñar la función de almacenamiento de bits, los registros permi-


ten realizar diferentes funciones, tales como desplazamientos, y soportan diferentes
opciones de carga y lectura de los datos, operaciones que pueden realizarse tanto en
serie, es decir, bit a bit, como en paralelo, es decir, simultáneamente sobre todos los
bits almacenados.

En este tema se aborda el diseño y test usando VHDL de varios tipos de registros
y memorias. Asimismo, se introduce una capacidad de VHDL no presentada hasta
el momento: el acceso a fichero. Esta capacidad resulta útil en la programación de
los bancos de pruebas.

5.2. REGISTRO DE 4 BITS

En la Figura 5.1 se muestra un registro de 4 bits. El registro tiene una entrada


de reloj, una entrada de reset síncrono (rst), cuatro entradas de datos (13 , 12 , 11 ,
10 ) y cuatro salidas de datos (Q 3 , Q2 , Q1 , Q0 ). Si la señal de reset vale '1' cuando
se produce el flanco de subida del reloj, entonces se almacena en el registro el valor
"0000". Si la señal de reset vale 'O' cuando se produce el flanco de subida de la señal
de reloj, entonces el registro se carga con los datos de entrada.

Figura 5.1: Registro de 4 bits.

357
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

5.2.1. Descripción del comportamiento

Una forma de diseñar el registro es mediante la descripción de su estructura,


usando 4 flip-flops. Otra posibilidad, es describirlo indicando cuál es su comporta-
miento, tal como se muestra en el Código VHDL 5.1.

-- Registro de 4 bits con reset síncrono


-- Fichero: Reg4. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity Reg4 is
port ( Q : out std_logic_vector(3 downto O);
I : in std_logic_vector ( 3 downto O);
clk, rst : in std_logic );
end entity Reg4;

architecture Reg4 of Reg4 is


begin
process ( clk)
begin
if rising_edge( clk) then
if(rst = '1') then
Q <= "0000";
else
Q <= I;
end if;
end if;
end process;
end architecture Reg4;

Código VHDL 5.1: Diseño de un registro de 4 bits con reset síncrono.

La architecture del registro tiene un bloque process que es sensible únicamente


a la señal de reloj. Al contrario de lo que sucede en los circuitos combinacionales, las
salidas del registro no se ven afectadas directamente por los cambios en los datos de
entrada (r). Por el contrario, los datos de entrada son cargados en el registro sólo
cuando se produce el flanco de subida de la señal de reloj.

Asimismo, obsérvese que el contenido del registro es puesto al valor 0000 11 11

cuando, al producirse el flanco de subida de la señal de reloj, la entrada de reset


tiene el valor '1'. Así pues, se trata de una entrada de reset síncrono.

5.2.2. Banco de pruebas

El Código VHDL 5.2 es un banco de pruebas sencillo para el registro. El programa


de test aplica los cuatro vectores de test siguientes: reset, carga 1111 carga 1010
11 11
,
11 11

y carga 0000
11 11

358
REGISTROS Y MEMORIAS

-- Banco de pruebas del registro de 4 bits. Fichero: bp_R eg4 .vhd


library IEEE; use IEEE. std_logic_1164. all;
entity bp_Reg4 is
end entity bp_Reg4;
architecture bp_Reg4 of bp_Reg4 is
constant PERIODO : time := 10 ns; -- Periodo reloj
signal Q : std_logic_vector(3 downto O); -- Salidas UUT
signal clk : std_logic := 'O'; -- Entradas UUT
signal I : std_logic_vector(3 downto O);
signal rst : std_logic;

component Reg4 is
port ( Q : out std_logic_vector(3 downto O);
I : in std_logic_vector(3 downto O);
clk, rst : in std_logic );
end component Reg4;
begin
uut : component Reg4 port map (Q, I, clk, rst);

clk <= not clk after (PERIOD0/2);

gen_ vec_ test : process is


begin
report "Comienza la simulación";
I <= "1111"; -- Reset
rst <= '1';
wait until rising_edge( clk);
wait for (PERIOD0/2);
I <= "1111"; -- Carga 1111
rst <= '0';
wait until rising_edge( clk);
wait for (PERIOD0/2);
I <= "1010"; --Carga 1010
rst <= '0';
wait until rising_edge( clk);
wait for (PERIOD0/2);
I <= "0000"; -- Carga 0000
rst <= '0';
wait until rising_edge( clk);
wait for (PERIOD0/2);
report "Finaliza la simulación";
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_Reg4;

Código VHDL 5.2: Banco de pruebas de un registro de 4 bits con reset síncrono.

359
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Tras aplicar cada uno de estos vectores de test, se ejecutan las dos sentencias
wait siguientes:

wait until rising_edge(clk);


wait for (PERIOD0/2);

La primera de ellas espera hasta que se produzca el siguiente flanco de subida


de la señal de reloj. La segunda espera durante la mitad del periodo de la señal de
reloj. En general, la sentencia

wait until condición;

espera hasta que la condición cambie de valer false a valer true. Si la condición
inicialmente vale true, entonces la sentencia wait espera hasta que la condición se
haga false y posteriormente vuelva a valer true.

El resultado del programa de test es inspeccionado visualmente, con el fin de


comprobar si el registro ha sido diseñado correctamente. En la Figura 5.2 se muestra
el resultado obtenido al simular el banco de pruebas durante 50 ns. Se comprueba
que el funcionamiento del registro es el esperado .

.
Messages
, l
8 + /bp_reg4/q 0000 uuuu ~000 ~1111 ~1010 ~000
+ /bp_reg4/clk o 1 1 1 1 1 1 1 L_
8 + /bp_reg4/i 0000 ¡1111 ~1010 ~000
+ /bp _reg4/rst o 1
1

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
>'«QO Now 50 ns lS 10 ns 20 ns 30 ns 40 ns

!il ..L~ ~ ~
:......... !h 1 1 /

1 O ns to 43 ns 1 Now: 50 ns Delta: 1

Figura 5.2: Simulación del banco de pruebas del registro de 4 bits.

5.3. REGISTRO MULTIFUNCIÓN

El registro descrito anteriormente tenía una única entrada de control: la entrada


de reset síncrono. Un registro más general tiene más entradas de control, tales como
carga paralelo ( Ld), desplazamiento hacia la derecha ( Shr) y hacia la izquierda
(Shl). Asimismo, tiene las entradas de datos correspondientes a los desplazamientos
(Shr_In, ShLin). En la Figura 5.3 se muestra este tipo de registro multifunción y su
tabla de operación.

360
REGISTROS Y MEMORIAS

rst Ld Shr Shl Operación

Q3 Q2 Q¡ Qo o o o o Mantiene valor
o o o Desplaz. Izq.
o o Desplaz. Drcha.
o Carga paralelo
Reset (carga "0000")

Figura 5.3: Registro multifunción.

5.3.1. Descripción del comportamiento

El Código VHDL 5.3 muestra la descripción del comportamiento del registro.


Se emplea una sentencia if para fijar las prioridades entre las diferentes entradas de
control: rst tiene la máxima prioridad, seguido de Ld, a continuación Shr y finalmente
Shl.

Los desplazamientos se describen empleando sentencias for. Por ejemplo, la


sentencia siguiente:

for index in O to 2 loop


R(index) <= R(index+1);
end loop;

es equivalente a escribir:

R(O) <= R(1);


R(1) <= R(2);
R(2) <= R(3);

Debe tenerse en cuenta que estas sentencias de asignación a señal producen un


cambio en el valor de la señal transcurrido un retardo o, empleándose el valor actual
de las señales para calcular los nuevos valores.

En el diseño del registro de 4 bits mostrado en la Sección 5.2, se empleó la señal Q


del puerto de salida para almacenar la palabra de 4 bits contenida en el registro. Sin
embargo, en el diseño del registro multifunción, se emplea la señal R para almacenar
la palabra de 4 bits. La razón para definir la señal R es que las operaciones de
desplazamiento requieren leer la palabra almacenada y un puerto de salida no puede
ser leído.

361
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- R eg'istro mnlt'ifunción de 4 bits


-- Fi chero: R eg4mf. vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity Reg4mf is
port ( Q : out std_logic_vector(3 downto O);
I : in std_logic_vector(3 downto O);
Shr_In, Shl_In : in std_logic;
Ld, Shr, Shl : in std_logic;
clk, rst : in std_logic );
end entity Reg4mf;

architecture Reg4mf of Reg4mf is


signal R : std_logic_vector(3 downto O);
begin

Q <= R;
process ( clk)
begin
if rising_edge( clk) then
if(rst = '1') then
R <= "0000";
elsif (Ld = '1') then
R <= I;
elsif (Shr = '1 ') then
R(3) <= Shr_In;
for index in O to 2 loop
R(index) <= R(index+1);
end loop;
elsif (Shl = '1 ') then
R(O) <= Shl_In;
for index in O to 2 loop
R(index+1) <= R(index);
end loop;
end if;
end if;
end process;
end architecture Reg4mf;

Código VHDL 5.3: Diseño de un registro multifunción de 4 bits.

362
REGISTROS Y MEMORIAS

Dado que en el puerto de salida del registro Q debe obtenerse en todo momento
el valor almacenado, R, es necesario copiar en todo momento el valor de la señal R
en la señal Q. Para ello, en el diseño se ha incluido la sentencia de asignación:

Q <= R;

que se ejecuta cada vez que cambia el valor de R, asignando transcurrido un tiempo
infinitesimal oeste nuevo valor a la señal Q.

Obsérvese que esta sentencia no ha sido incluida dentro de ningún bloque pro-
cess. Recuérdese que este tipo de sentencias de asignación a señal, que se encuentran
en la architecture fuera de los bloques process, se denominan sentencias concu-
rrentes de asignación a señal.

Puede considerarse que una sentencia concurrente de asignación a señal consti-


tuye por sí misma un bloque process, que se ejecuta concurrentemente con el resto
de bloques process. Por ejemplo, la sentencia de asignación concurrente

Q <= R;

es equivalente al bloque process siguiente:

process (R)
begin
Q <= R;
end process;

Cada vez que cambia el valor de la señal R, se ejecuta el bloque process, con lo
cual el valor de Q es actualizado al nuevo valor de R transcurrido un tiempo o(delta).

Una forma incorrecta de describir Q hubiera sido incluir la sentencia Q <= R;


dentro del bloque process, justo antes del segundo end if. Es decir:

process (clk) -- No describe el comportamiento del registro


begin
if rising_edge(clk) then
if (rst = '1') then
R <= ...
elsif (Ld = '1') then
R <= ...
elsif (Shr = '1') then
R <= ...
elsif (Shl = '1') then
R <=
end if;
Q <= R; Mal ! !
end if;
end process;

363
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Este código no reproduce adecuadamente el comportamiento del registro. Re-


cuérdese el funcionamiento de las asignaciones a señal dentro de un bloque process:
el nuevo valor de las señales se evalúa a partir del valor actual de las mismas y el
nuevo valor no se asigna hasta transcurrido un tiempo 5.

Así pues, la sentencia añadida al bloque process asignaría a la variable Q el


valor "antiguo" de R y no el nuevo valor que se ha asignado a R en el cuerpo de la
sentencia if-elsif-end if. El valor "antiguo" de R es el valor asignado a dicha señal
en la evaluación anterior del bloque process. Es decir, el valor de la señal R en la
transición anterior de la señal de reloj. En consecuencia, la señal Q iría retrasada
respecto a la señal R.

5.3.2. Banco de pruebas

El Código VHDL 5.4- 5.6 es un banco de pruebas parcial para el registro multifun-
ción, que prueba únicamente un grupo muy reducido de vectores de test. El banco
de pruebas correctamente diseñado debería comprobar el circuito de manera más
exhaustiva, testeando, por ejemplo, todas las posibles combinaciones de las entradas
de control.

En la Figura 5.4 se muestra el resultado obtenido de simular el banco de pruebas


del registro multifunción durante 120 ns.

Messages r V
[±) + fbp_reg4mf/q 0000 u.. . mooo U111 l!O!O 1.0101 1.0011 U001 1.0100 1.0000 1.0001 1.0010 1.0000
+ fbp_reg4mf/clk
GJ + fbp_reg4mf/i
o
1111
1
1111 l!010 1.0101 1.0011 U111 roooo

U111
+ fbp_reg4mf/rst 1 lr---J
+fbp_reg4mf/shr_in 1 lr---J 1 L___j
+fbp_reg4mf/shl_in 1 r---L____J L____j
+ fbp_reg4mf/ld 1 1 1
+fbp_reg4mf/shr 1 J
+ fbp_reg4mf/shl 1 1 1

.~1iii}@
11111111 .¡,,,,,,,,,,,, 1111111111111111 , , , , , , , , , , d t l l l l l l l l l l l l l l l l l ,,,,1111111111111111 d 11111111 , , , , , , , , , , , , , , , , , , , , , , , , 1
Now 120 ns 15 20 ns 40 ns 60 ns 80 ns 100 ns 120 ns
w i.J ~ L!:Jik l 1 /
1 Ons to 123 ns 1 Now: 120ns Delta: 1

Figura 5.4: Simulación del banco de pruebas del registro multifunción.

364
REGISTROS Y MEMORIAS

-- Banco de pruebas del registro multifunción


-- Fichero: bp_Reg4mf.vhd
library IEEE;
use IEEE.std_logic_1164.all;
entity bp_Reg4mf is
end entity bp_Reg4mf;
architecture bp_Reg4mf of bp_Reg4mf is
constant PERIODO : time .- 10 ns;
signal Q : std_logic_vector(3 downto O);
signal clk : std_logic := 'O';
signal I : std_logic_vector(3 downto O);
signal rst : std_logic;
signal Shr _In, Shl_In : std_logic;
signal Ld, Shr, Shl : std_logic;
component Reg4mf is
port ( Q : out std_logic_vector(3 downto O);
I : in std_logic_vector ( 3 downto O);
Shr _In, Shl_In : in std_logic;
Ld, Shr, Shl : in std_logic;
clk, rst : in std_logic );
end component Reg4mf;
begin
-- Instanciar y conectar UUT
uut : component Reg4mf port map
(Q, I, Shr_In, Shl_In, Ld, Shr, Shl, clk, rst);
clk <= not clk after (PERIOD0/2);
gen_ vec_ test : process is
variable numTest : integer := O;
begin
report "Comienza la simulación";

-- R eset
I <= "1111"; Shr_In <= '1'; Shl_In <= '1';
rst <= '1'; Ld <= '1'; Shr <= '1'; Shl <= '1';
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = "0000")
report "Error vector " & integer' image(numTest);

Código VHDL 5.4: Banco de pruebas de un registro multifunción de 4 bits.

365
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Continuación del banco de pr'uebas del registro multifunción


-- Fich ero : bp_Reg4 mfvhd

-- Carga 1111
I <= "1111"; Shr_In <= '0'; Shl_In <= '0';
rst < = 'O' ; Ld < = ' 1 ' ; Shr < = ' 1 ' ; Shl < = ' 1' ;
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = 11 111 !1')
report "Error vector 11 & integer' image(numTest);
-- Carga 101 O
I <= "1010"; Shr_In <= '0'; Shl_In <= '1';
rst <= '0'; Ld <= '1'; Shr <= '1'; Shl <= '1';
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = "1010" )
report "Error vector " & integer' image(numTest);
-- Carga 0101
I <= "010!1'; Shr_In <= '1'; Shl_In <= '1';
rst <= '0'; Ld <= '1'; Shr <= '1'; Shl <= '1';
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = "0101" )
report "Error vector 11 & integer' image(numTest);
-- Carga 0011
I <= "0011"; Shr_In <= '1'; Shl_In <= '1';
rst <= '0'; Ld <= '1'; Shr <= '1'; Shl <= '1';
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = "0011" )
report "Error vector 11 & integer' image(numTest);
-- D esplazamiento D erecha, Carga serie '1'
I <= "1111"; Shr_In <= '1'; Shl_In <= '1';
rst <= '0'; Ld <= '0'; Shr <= '1'; Shl <= '0';
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = "100!1' )
report "Error vector 11 & integer' image(numTest);

Código VHDL 5.5: Continuación del banco de pruebas de un registro multifunción de 4 bits.

366
REGISTROS Y MEMORIAS

-- Parte fina l del banco de pruebas de l registro m ultifunción


-- Fichero: bp_R eg4 mf.vhd

-- D esplazamiento D erecha, Carga serie 'O'


I <= 11 11 1111 11 ; Shr_In <= '0'; Shl_In <= '1';
rst <= '0'; Ld <= '0'; Shr <= '1'; Shl <= '0';
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = 11 0100 11 )
report 11 Error vector 11 & integer' image(numTest);
-- Carga 0000
I <= 11 0000 11 ; Shr_In <= '1'; Shl_In <= '1';
rst <= '0'; Ld <= '1'; Shr <= '1'; Shl <= '1';
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = 11 0000 11 )
report 11 Error vector 11 & integer' image(numTest);
-- D esplazamiento Izquierda, Carga serie '1 '
I <= 11 1111 11 ; Shr_In <= '1'; Shl_In <= '1';
rst <= '0'; Ld <= '0'; Shr <= '0'; Shl <= '1';
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = 11 0001 11 )
report 11 Error vector 11 & integer' image(numTest);
-- D esplazamiento Izquierda, Carga serie 'O'
I <= 11 111!1'; Shr_In <= '1 '; Shl_In <= '0';
rst <= '0'; Ld <= '0'; Shr <= '0'; Shl <= '1';
wait until rising_edge( clk) ;
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = 11 0010 11 )
report 11 Error vector 11 & integer' image(numTest) ;
-- R eset
I <= 11 1111 11 ; Shr_In <= '1'; Shl_In <= '1';
rst <= '1'; Ld <= '1'; Shr <= '1'; Shl <= '1';
wait until rising_edge( clk);
wait for (PERIOD0/2);
numTest := numTest + 1;
assert ( Q = 11 0000 11 )
report 11 Error vector 11 & integer' image(numTest);
report 11 Finaliza la simulación 11 ;
wait; -- Final del bloque process
end process gen_ vec_ test;
end architecture bp_Reg4mf;

Código VHDL 5.6: Parte final del banco de pruebas de un registro multifunción de 4 bits.

367
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

5.4. REGISTRO DE DESPLAZAMIENTO

El registro multifunción mostrado en la Figura 5.3 incluye, entre otras, las ope-
raciones de desplazamiento hacia la izquierda y la derecha. En aquellos casos en que
sólo se requiera la operación de desplazamiento y la entrada serie de bits, puede
emplearse un circuito más sencillo, tal como el registro de desplazamiento mostrado
en la Figura 5.5.

rst Shr Operación


Ql Qo o o Mantiene valor
o Desplaz. Drcha.
Reset (carga X"OOOOOOOO")

Figura 5.5: Registro de desplazamiento de 32 bits.

El registro de desplazamiento de 32 bits de la Figura 5.5 tiene una entrada de


control (Shr), una entrada de datos (Shr_in), una entrada de reset síncrono (rst) y
una salida paralelo de 32 bits ( Q). En la tabla mostrada en la parte derecha de la
Figura 5.5 se describe su operación. Si cuando se produce el flanco de subida del
reloj la entrada de control Shr vale '1 ', entonces el registro desplaza su contenido
una posición hacia la derecha y carga Shr_in en el bit situado más a la izquierda.

5.4.1. Descripción del comportamiento

El Código VHDL 5. 7 muestra el diseño del registro de desplazamiento, en el cual


se ha empleado un bucle for en la descripción del desplazamiento hacia la derecha.

El bucle for se expande. Así pues, es equivalente escribir el código mostrado en


la parte izquierda a escribir las 32 sentencias de asignación a señal, una para cada
bit del registro de desplazamiento, mostradas en la parte de la derecha:

R(31) <= Shr_in; R(31) <= Shr_in;


for index in O to 30 loop R(O) <= R(1);
R(index) <= R(index+1); R(1) <= R(2);
end loop;
R(30) <= R(31);

368
REGISTROS Y MEMORIAS

-- R egistro de desplazamiento de 32 bits


-- Fichero: R egDesp32. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity RegDesp32 is
port ( Q : out std_logic_vector(31 downto O);
Shr, Shr _in : in std_logic;
clk, rst : in std_logic ) ;
end entity RegDesp32;
architecture RegDesp32 of RegDesp32 is
signal R : std_logic_vector ( 31 downto O);
begin
process (el k)
begin
if rising_edge( clk) then
if (rst = '1 ') then
R <= X11 00000000 11 ;
elsif (Shr = '1 ') then
R(31) <= Shr_in;
for index in O to 30 loop
R(index) <= R(index+1);
end loop;
end if;
end if;
end process;
Q <= R;
end architecture RegDesp32;

Código VHDL 5. 7: Diseño de un registro de desplazamiento de 32 bits.

5.4.2. Banco de pruebas

El Código VHDL 5.8 muestra un banco de pruebas que aplica algunos vectores
de test al registro de desplazamiento. En primer lugar, el programa de test resetea
el circuito. A continuación, pone las señales Shr y Shr_in al valor '1' y espera
durante 16 ciclos de reloj. Con ello, se realizan 16 desplazamientos hacia la derecha,
introduciéndose 16 bits '1' por la parte izquierda del registro. El valor almacenado
resultante es X"FFFFOOOO". A continuación, el programa de test pone la señal Shr_in
al valor 'O' y espera durante otros 16 ciclos de reloj. El valor almacenado resultante
es X"OOOOFFFF". Finalmente, el programa de test pone la señal Shr al valor 'O' y
finaliza el bloque process en el que se aplican los vectores de test.

En la Figura 5.6 se muestran algunos fragmentos del resultado obtenido al simular


el banco de pruebas durante 350 ns.

369
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del registro de 32 bits. Fichero: bp_RegDesp32. vhd


library IEEE; use IEEE.std_logic_1164.all;

entity bp_RegDesp32 is
end entity bp_RegDesp32;

architecture bp_RegDesp32 of bp_RegDesp32 is


constant PERIODO : time : = 1O ns;
signal Q : std_logic_vector(31 downto O);
signal clk : std_logic := 'O';
signal Shr : std_logic;
signal Shr in : std_logic;
signal rst : std_logic;

component RegDesp32 is
port ( Q : out std_logic_vector(31 downto O);
Shr, Shr _in : in std_logic;
clk, rst : in std_logic ) ;
end component RegDesp32;

begin
uut : component RegDesp32 port map (Q, Shr, Shr_in, clk, rst);

clk < = not clk after (PERIDDD/2);


gen_ vec_ test : process is
begin
report "Comienza la simulación";

-- Reset
rst < = '1'; Shr < = '1'; Shr_in < = '1';
wait until rising_edge( clk); wait for (PERIODD/2);
-- Carga serie 16 bits '1 '
rst < = '0'; Shr < = '1'; Shr_in < = '1';
for index in O to 15 loop
wait until rising_edge( clk);
end loop;
wait for (PERIODD/2);
assert ( Q = X" FFFFOOOO 11 ) report "Fallado Q=FFFFOOOO";
-- Carga serie 16 bits 'O'
rst < = '0'; Shr <= '1'; Shr_in < = '0';
for index in O to 15 loop
wait until rising_edge( clk);
end loop;
wait for (PERIODD/2);"
assert ( Q = X"OOOOFFFF") report "Fallado Q=OOOOFFFF";

Shr < = '0';


report "Finaliza la simulación 11 ;
wait; -- Final del bloque process
end process gen_ vec_ test;
end architecture bp_RegDesp32;

Código VHDL 5.8: Banco de pruebas del registro de desplazamiento de 32 bits.

370
REGISTROS Y MEMORIAS

---· ·-·-···-·-·- --
Messages r
(±] + /bpJegdesp32/q 0000000000 XXXXXXXXXXXXXXX. .. IC 00000 000000000000000000000000 10000000000000000000000000000000 110000000000000000 ...
+ lbpJegdesp32/clk 1 1 1 L_
+ /bpJegdesp32/shr 1
+ /bpJegdesp32/shr _in 1
+ lbpJegdesp32/rst 1 1

1 1 1 1 1
Jil~s
1 1 1 1 1 1 1 1 1 1 1 1 1 1
Ni~@ Now 350 ns 4 ns 16 ns 20 ns 24 ns 28 ns
lS 12 ns
GJJ'~ Cursor 1 7 ns S

..:!.1 ...!.,_ill .!..,!f,J...J__J /"

1 O ns to 31 ns 1 Now: 350 ns Delta: 1


-
Messages
a:;. /bp_regdesp32/q 11111111111 l1111111111 1111100000000000000000 1111111 1111111110000000000000000 ro 1111111111111111 ooooooooooooooo
+ /bp_regdesp32/clk 1 _j 1 1 1 1 1
+ /bpJegdesp32/shr 1
+ /bpJegdesp32/shr _in 1
+ /bp_regdesp32/rst o

.W~© Now 350 ns


1 1
156 ns
1 1 1 1
160 ns
1 1 1
164 ns
1 1
~8ns
i 1 1 1 1
172 ns
1 1
176 ns
1 1
180 ns
1 1
184 ns
~.1'0 Cursor 1 167 ns S

..:!.1 ..t. ill .!.. t-~J __j_J ,/

1 154 ns to 185 ns 1 Now: 350 ns Delta: 1

Messages V
±; + /bp_regdesp32/q 0000000000 0000000000000111111111111111100 000000000000001111111111 1111110 !00000000000000001111111111111111
+ lbpJegdesp32/clk o 1
+ lbp_regdesp32/shr 1
+ /bpJegdesp32/shr jn O
+ lbpJegdesp32/rst o
1 1 1 1 1 1 1 1 1 1 1 1 ~ 1 1 1 1 1 1 1 1 1
a~~@ Now 350 ns 308 ns 312 ns 316 ns 320 ns ~ 324 ns 328 ns 332 ns 33E
f-.1,/'0 Cursor 1 322ns 322 ns

..:!.1 ..!..ill .!.. , J _LJ ./

1 305 ns to 336 ns 1 Now: 350 ns Delta : 1

Figura 5.6: Fragmentos del resultado de la simulación del banco de pruebas del registro de
desplazamiento de 32 bits.

5.4.3. Banco de pruebas con acceso a fichero

Cuando los diseños se hacen más complejos y el tamaño de palabra de las


entradas, salidas y señales internas se hace mayor, no resulta práctico especificar
el conjunto de vectores de test en términos de asignaciones a señal, sentencias wait
y sent encias assert.

Consideremos, por ejemplo, el banco de pruebas para el registro de desplaza-


miento de 32 bits. Cargar en el registro una palabra de 32 bits precisa 64 sentencias
VHDL: 32 sentencias que asignan valor a la señal de carga serie (Shr_in) y 32
sentencias wait. Así pues, un banco de pruebas que cargue en el registro 100 palabras
de 32 bits, constará al menos de 6.400 sentencias.

Una alternativa consiste en que el banco de pruebas lea de un fichero los vectores
de test. De esta forma, resulta relativamente sencillo incluir nuevos vectores de test,
y pueden emplearse diferentes ficheros para testear diferentes aspectos del diseño y

371
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

escenarios. Otra ventaja es que de esta forma pueden añadirse nuevos vectores de
test al fichero y realizar la simulación, sin necesidad de recompilar el código VHDL
del banco de pruebas.

El Código VHDL 5.9 muestra un banco de pruebas en el cual se van leyendo los
bits de carga serie ( Shr_in) de un fichero. Para ello, se usa el paquete std. textio. all,
en el cual se define el tipo file y los subprogramas (procedimientos y funciones)
asociados que permiten leer de ficheros: file_open(), file_close(), endfile(), read-
line() y read().

Obsérvese que dentro del bloque process del Código VHDL 5.9 se realiza la
declaración siguiente:

file fichVectores text;


variable inputLinea line;
variable inputBit bit;

La primera sentencia define un fichero del tipo "fichero de texto" y cuyo identifi-
cador es fichVectores. Un "fichero de texto" es un fichero que contiene un número
arbitrario de caracteres ASCII y, por tanto, puede ser editado empleando cualquier
editor de texto.

Las variables inputLinea e inputBi t, de los tipos line y bit respectivamen-


te, son empleadas en la lectura del fichero. El tipo line se define en el paquete
std. textio. all y representa una línea que puede ser leída o escrita El tipo bit es
uno de los tipos predefinidos que fueron descritos en la Sección 2.12. Puede tomar
únicamente los valores 'O' y '1'.

En primer lugar, el banco de pruebas abre el fichero usando una llamada al pro-
cedimiento file_open(). Este procedimiento tiene tres parámetros: el identificador
del fichero, el nombre del fichero y el modo de acceso. El modo de acceso puede
tomar tres valores: read_mode, write_mode y append_mode. La sentencia

file_open(fichVectores, "vectores.txt", read_mode);

abre en modo lectura el fichero llamado "vectores. txt", asociándole el identificador


fichVectores.

Antés de empezar a leer de fichero, el banco de pruebas resetea el registro.


A continuación, pone la señal de reset a 'O' y, dado que la señal de control del
desplazamiento (Shr) tiene el valor '1', comienzan a introducirse bits en el registro.
Los bits son leídos del fichero cuyo identificador es fichVectores. La lectura de los
bits se realiza mediante el bucle while siguiente:

372
REGISTROS Y MEMORIAS

-- Banco de pruebas del registro de 32 bits con acceso a fich ero


-- Fich ero: bp_RegDesp32fich. vhd
library IEEE; use IEEE.std_logic_1164.all; use std.textio.all;
entity bp_RegDesp32 is
end entity bp_RegDesp32;

architecture bp_RegDesp32fich of bp_RegDesp32 is


constant PERIODO : time := 10 ns;
signal Q : std_logic_vector(31 downto O);
signal clk : std_logic := 'O';
signal Shr : std_logic;
signal Shr in : std_logic;
signal rst : std_logic;
component RegDesp32 is
port ( Q : out std_logic_vector(31 downto O);
Shr, Shr _in : in std_logic;
clk, rst : in std_logic );
end component RegDesp32;
begin
uut : component RegDesp32 port map (Q, Shr, Shr_in, clk, rst);
clk <= not clk after (PERIOD0/2);
gen_ vec_ test : process is
file fichVectores : text;
variable inputLinea : line;
variable inputBi t : bit;
begin
report 11 Comienza la simulación 11 j
-- R eset
rst <= '1'; Shr <= '1'; Shr _in < = ' 1 ' ;
wait until rising_edge( clk); wait for (PERIOD0/2);
-- Carga de vectores de t est des de fichero
rst <= '0';
file_open(fichVectores, 11 vectores. txt 11 , read_mode );
while not endfile(fichVectores) loop
readline(fichVectores, inputLinea);
for i in inputLinea' range loop
read(inputLinea, inputBit);
if inputBi t = ' 1' then
Shr _in < = ' 1 ' ;
else
Shr _in < = 'O' ;
end if;
wait until rising_edge( clk);
end loop; -- bucle for
end loop; -- bucle while
file_close(fichVectores);

Shr <= '0';


wait until rising_edge( clk); report 11
Finaliza la simulación 11 ;
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_RegDesp32fich;

Código VHDL 5.9: Banco de pruebas del registro con acceso a fichero.

373
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

while not endfile(fichVectores) loop


readline(fichVectores, inputLinea);
for i in inputLinea'range loop
read(inputLinea, inputBit);
if inputBit = '1' then
Shr_in <= '1';
el se
Shr_in <= '0';
end if;
wait until rising_edge(clk);
end loop; bucle for
end loop; -- bucle while

La función endfile(fichVectores) devuelve el valor true cuando se alcanza el final


del fichero.

El procedimiento readline tiene dos parámetros, el primero del tipo file y el


segundo del tipo line. La sentencia

readline(fichVectores, inputLinea);

lee una línea del fichero fichVectores y la almacena en la variable inputLinea. Para
leer los caracteres individuales de la línea de entrada, es preciso usar el procedi-
miento read. Se usa un bucle for para acceder a los bits de inputLinea, donde
inputLinea' range especifica el número de caracteres de la línea.

Dentro del bucle for, se lee cada bit de inputLinea mediante la sentencia

read(inputLinea, inputBit);

El procedimiento read tiene dos parámetros. El primero es del tipo line y es


la línea de la cual se leen los caracteres. El segundo parámetro es una variable del
tipo bit, en la cual se guarda el caracter leído de la línea. El procedimiento read se
define también para otros tipos, tales como bit_vector y character, entre otros.

A continuación, el banco de pruebas escribe el bit leído del fichero en la señal


Shr_in. Sin embargo, puesto que los tipos bit y std_logic no son compatibles, se
emplea una sentencia if para asignar valor a Shr _in. Otra posibilidad hubiera sido
realizar la conversión de tipo:

Shr_in <= to _stdulogic(inputBit);

Una vez se ha asignado valor a Shr_in, se espera hasta el siguiente flanco de


subida del reloj antes de leer el siguiente bit de la línea de entrada.

Una vez se alcanza el final del fichero, finaliza el bucle while y se ejecuta la
sentencia de cierre del fichero. El procedimiento file_close tiene un único parámetro,
que es un identificador de fichero (del tipo file).

374
REGISTROS Y MEMORIAS

El fichero vectores. txt debe estar situado en el directorio espacio de trabajo del
entorno de simulación. Si el contenido del fichero es:

1111111111111111
0000000000000000

al ejecutar el banco de pruebas se obtendrá esencialmente el mismo resultado que


se obtuvo al ejecutar el banco de pruebas de la Sección 5.4.2.

5.5. -REGISTER FILE

Un register file es un módulo compuesto de varios registros, y de la lógica de


acceso a ellos para lectura y escritura. Por ejemplo, un register file de tamaño 4 x 32,
contiene 4 registros, cada uno de los cuales tiene 32 bits. En la Figura 5. 7 se muestra
el diseño estructural de un register file 4 x 32.

W data 32 32 R data

dl
Ío R addr
Í¡ Ío
Í¡

d2

en
W enable en
,.___--+----1 d R enable
3

rst ______.+----------+~
elk

Figura 5. 7: Register file con 4 registros de 32 bits.

En el register file mostrado en la Figura 5. 7, los registros tienen una entrada


de datos de 32 bits y una entrada de control para carga paralelo ( Ld). También
disponen de una entrada de reset síncrono ( rst). La entrada de reset del register file

375
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

está conectada a la entrada de reset de cada uno de los registros. Finalmente, el


register file tienen una salida de 32 bits.

Además de los cuatro registros de 32 bits, el register file está compuesto por
dos decodificadores 2:4 con entrada enable, uno para escritura (situado en la parte
izquierda) y otro para lectura (situado en la parte derecha), y por cuatro buffers
triestado. El funcionamiento del buffer triestado se explicó en la Sección 1.9.1.

En este caso, el propósito de los buffers triestado es permitir que las salidas de los
registros se conecten al bus R_data, evitando así tener que utilizar un multiplexor,
que es un circuito más grande y lento. Esta estructura de conexión al bus a través de
buffers triestado funciona correctamente cuando se garantiza que en todo momento
no hay más de un buffer que tenga una salida diferente de alta impedancia ( 'Z'). El
decodificador de lectura garantiza este comportamiento.

5.5.1. Registro triestado

Puede considerarse que el registro y su buffer triestado constituyen a su vez un


registro con una nueva entrada: OE ( Output Enable). En función del valor que se
asigne a la entrada OE, puede obtenerse en la salida del registro triestado, o bien el
valor almacenado (si OE='l'), o bien alta impedancia (si OE='O'). En la Figura 5.8
se muestra este registro con entrada output enable.

El Código VHDL 5.10 describe el registro triestado mostrado en la Figura 5.8.


La descripción consta de dos bloques process: regProc describe el comportamiento
de reset síncrono y almacenamiento, mientras que outputProc describe la lógica
combinacional del comportamiento como buffer triestado del registro.

1
OE
~·~---------+------~

o
Figura 5.8: Registro con entrada OE output enable.

Obsérvese que en el primer bloque process se ha incluido la sentencia

R <= (others => '0');

376
REGISTROS Y MEMORIAS

-- Registro de 32 bits con output enable


-- Fichero: Reg32_0E.vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity Reg32_DE is
port ( Q : out std_logic_vector(31 downto O);
I : in std_logic_vector(31 downto O);
Ld, DE : in std_logic;
el k, rst : in std_logic ) ;
end entity Reg32_DE;

architecture Reg32_DE of Reg32_DE is


signal R : std_logic_vector(31 downto O);
begin
regProc: process ( clk)
begin
if rising_edge( clk) then
if (rst = '1') then
R <= (others => '0');
elsif (Ld = '1 ') then
R <= I;
end if;
end if;
end process regProc;

outputProc: process (R, DE)


begin
if (DE=' 1 ') then
Q <= R;
else
Q <= (others => 'Z');
end if;
end process outputProc;
end architecture Reg32_DE;

Código VHDL 5.10: Diseño de un registro triestado.

que asigna el valor 'O' a cada uno de los 32 bits del vector R. Esta sentencia es
equivalente a:

R <= X"OOOOOOOO";

con la diferencia de que usando others no se especifica el número de bits del vector,
con lo cual pueden escribirse diseños más generales. Asimismo, others proporciona
una notación más compacta y legible. Por ejemplo, en el segundo bloque process
se ha escrito

Q <= (others => 'Z');

que es considerablemente más corto que

Q <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";

377
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

dado que en este caso no se hubiera podido usar la representación hexadecimal para
reducir el tamaño de la palabra. Una peculiaridad de others es que sólo puede usarse
en sentencias de asignación, no puede usarse como parte de una condición.

5.5.2. Descripción estructural del register file

El register file mostrado en la Figura 5. 7 está compuesto por dos decodificadores


2:4 con entrada enable, idénticos a los diseñados en temas anteriores. También, está
compuesto por cuatro registros triestado como los diseñados en la Sección 5.5.1.

Empleando estos componentes, puede realizarse la descripción estructural del


register file, tal como se muestra en el Código VHDL 5.11. Se han definido ocho
señales internas al register file, que corresponden con las salidas del decodificador
de escritura (W_d3, W_d2, W_d1, W_dO) y con las salidas del decodificador de lectura
(R_d3, R_d2, R_d1, R_dO).

5.5.3. Drivers y función de resolución

Obsérvese que en el bloque process outputProc, del registro Reg32_0E (véase el


Código VHDL 5.10), se escribe en el puerto de salida Q. En la descripción del register
file, este puerto de salida es mapeado con la señal R_data. Dado que cada instancia
del componente Reg32_0E da lugar a una instancia del bloque process outputProc,
la señal R_data es escrita en el register file desde cuatro bloques process.

Tal como se explicó en la Sección 3.4, el valor de una señal está determinado
en todo momento por el valor de sus drivers. Si un bloque process contiene una
sentencia de asignación a señal, entonces el bloque process tendrá un driver para
esa señal. En el caso del register file , la señal R_data tiene cuatro drivers.

Por la forma en que se ha realizado el diseño del register file, en cada instante
a lo sumo uno de los drivers escribe el valor 'O' ó '1' en la señal, mientras que los
demás drivers escriben el valor 'Z'. En consecuencia, en cada instante se escriben
cuatro valores en la señal, tres de los cuales son 'Z', y el cuarto es 'O', '1' ó 'Z'.

Como también se explicó en la Sección 3.4, el simulador dispone de un método


para decidir qué valor asignar a la señal cuando ésta tiene drivers con diferentes
valores. El método consiste en disponer de una función de resolución, cuya entrada
son los múltiples valores de los drivers y que devuelve sólo uno, que es el que se
asigna a la señal.

378
REGISTROS Y MEMORIAS

-- Register fil e 4x32.


-- Descripción estructural
-- Fichero: R egFile4x32_estruc. vhd
library IEEE;
use IEEE. std_logic_1164 . all;

entity RegFile4x32 is
port ( R_data : out std_logic_vector(31 downto O);
W_data : in std_logic_vector(31 downto O);
R_addr, W_addr : in std_logic_vector(1 downto O);
R_en, W_en : in std_logic;
clk, rst : in std_logic );
end entity RegFile4x32;

architecture RegFile4x32_estruc of RegFile4x32 is

component Dcd2x4 is
port ( d3, d2, d1, dO : out std_logic;
i1, iO : in std_logic;
en : in std_logic );
end component Dcd2x4;

component Reg32_0E is
port ( Q : out std_logic_vector(31 downto O);
I : in std_logic_vector(31 downto O);
Ld, DE : in std_logic;
clk, rst : in std_logic ) ;
end component Reg32_0E;

signal W_d3, W_d2, W_d1, W_dO : std_logic;


signal R_d3, R_d2, R_d1, R_dO : std_logic;

begin
R_Dcd : Dcd2x4 port map (R_d3, R_d2, R_d1, R_dO, R_addr(1), R_addr(O), R_en);
W_Dcd : Dcd2x4 port map (W_d3, W_d2, W_d1, W_dO, W_addr(1), W_addr(O), W_en);
RegO : Reg32_0E port map (R_data, W_data, W_dO, R_dO, clk, rst );
Reg1 : Reg32_0E port map (R_data, W_data, W_d1, R_d1, clk, rst );
Reg2 : Reg32_0E port map (R_data, W_data, W_d2, R_d2, clk, rst );
Reg3 : Reg32_0E port map (R_data, W_data, W_d3, R_d3, clk, rst );

end architecture RegFile4x32_estruc;

Código VHDL 5.11: Diseño estructural del register file.

379
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Cuando hay varios drivers para una misma señal, el simulador automáticamente
llama a la función de resolución asociada con el tipo de dato de la señal. En el
caso de la señal R_data, como es del tipo std_logic_vector, el simulador llama
a la función de resolución de ese tipo, que se encuentra definida en el paquete
IEEE. std_logic_1164. all (véase la Tabla 3.2). Esta función de resolución devuelve
'O' si uno de los drivers es 'O' y los demás 'Z'. Devuelve '1' si uno de los drivers es
'1' y los demás 'Z'. Sin embargo, si unos drivers valen 'O' y otros valen '1', entonces
la función de resolución devuelve 'X', cuyo significado es "valor desconocido".

5.5.4. Banco de pruebas del register file

El Código VHDL 5.12 y 5.13 es un banco de pruebas para el register file, que lee
los vectores de test de un fichero. Cada una de las líneas de este fichero (vectores. txt)
consta de una palabra de 39 bits, cuyo significado es mostrado en la Figura 5.9. En
la Figura 5.10 se muestra parte del resultado de la simulación.

1 bit 32 bits 2 bits 1 bit 2 bits 1 bit


+-++-------------------++----~~---+~----~---+

W data lw_addr 1 W_en 1 R_addr 1 R_en 1

Figura 5.9: Interpretación de cada línea del fichero vectores. txt.

Obsérvese que la línea leída del fichero es asignada a la variable aux, del tipo
std_logic_vector, que es definida dentro del bloque process gen_ ve e_ test. A con-
tinuación, descomponiendo esta palabra como se muestra en la Figura 5.9, se asigna
valor a los puertos de entrada del register file. Para ilustrar el funcionamiento del
banco de pruebas, se define un fichero de vectores de test (vectores. txt) muy sencillo,
cuyo contenido se muestra a continuación. La interpretación se indica en la Tabla 5.1.

111111111111111111111111111111111000000
011111111111111111111111111111111001000
010101010101010101010101010101010011000
011111111111111111111111111111111101000
001010101010101010101010101010101111000
000000000000000000000000000000000000001
000000000000000000000000000000000000011
000000000000000000000000000000000000101
000000000000000000000000000000000000111

380
REGISTROS Y MEMORIAS

-- Banco de pruebas del register fil e. Fich ero: bp_RegFile4x32. vhd


library IEEE;
use IEEE.std_logic_1164.all; use std.textio.all;

entity bp_regFile4x32 is
constant PERIODO : time := 10 ns;
end entity bp_regFile4x32;

architecture bp_regFile4x32 of bp_regFile4x32 is


signal R_data : std_logic_vector(31 downto O);
signal W_data : std_logic_vector(31 downto O);
signal R_addr, W_addr : std_logic_vector(1 downto O);
signal R_en, W_en : std_logic;
signal rst : std_logic;
signal clk : std_logic := 'O';

component RegFile4x32 is
port ( R_data : out std_logic_vector(31 downto O);
W_data : in std_logic_vector(31 downto O);
R_addr, W_addr : in std_logic_vector(1 downto O);
R_en, W_en : in std_logic;
clk, rst : in std_logic ) ;
end component RegFile4x32;

begin
uut : component RegFile4x32 port map
(R_data, W_data, R_addr, W_addr, R_en, W_en, clk, rst);

clk <= not clk after (PERIOD0/2);


gen_ vec_ test : process is
file fichVectores : text;
variable inputLinea : line;
variable inputBi t : bit;
constant numBi ts : integer := 38; -- Num bits menos 1
variable aux : std_logic_vector(numBits downto O);

begin
report "Comienza la simulación";
-- Carga de vectores de test desde fichero
file_open(fichVectores, "vectores. txt", read_mode );
while not endfile(fichVectores) loop

-- L ectura desde fichero


readline(fichVectores, inputLinea);
for i in numBits downto O loop
read(inputLinea, inputBit);
if inputBit = '1 'then
aux ( i) . - ' 1 ' ;
el se
aux ( i) : = ' O' ;
end if;
end loop; -- bucle for

Código VHDL 5.12: Banco de pruebas del register file, con acceso a fichero.

381
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Continuación del banco de pruebas del register file. Fichero: bp_RegFile4x32. vhd
-- Asigna valor a W_data) W_addr) W_en) R_addr, R_en
rst <= aux(38);
W_data <= aux(37 downto 6);
W_addr <= aux(5 downto 4);
W_en <= aux(3);
R_addr <= aux(2 downto 1);
R_en <= aux(O);
wait for PERIODO;
end loop; -- bucle while
file_close(fichVectores);
wait until rising_edge( clk);
report "Finaliza la simulación";
wait; -- Final del bloque process
end process gen_ ve e_ test;
end architecture bp_regFile4x32;

Código VHDL 5.13: Continuación del banco de pruebas del register file.

Tabla 5.1: Interpretación de los vectores de test.

rst W_data w_addr W_en ILaddr !Len


1 11111111111111111111111111111111 00 o 00 o Reset
o 11111111111111111111111111111111 00 1 00 o Escribe regO
o 10101010101010101010101010101010 01 1 00 o Escribe reg1
o 11111111111111111111111111111111 10 1 00 o Escribe reg2
o 01010101010101010101010101010101 11 1 00 o Escribe reg3
o 00000000000000000000000000000000 00 o 00 1 Lee regO
o 00000000000000000000000000000000 00 o 01 1 Lee reg1
o 00000000000000000000000000000000 00 o 10 1 Lee reg2
o 00000000000000000000000000000000 00 o 11 1 Lee reg3

382
REGISTROS Y ME~ORIAS

Messages

±l +/bp_regfile4x32/r_data ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ l;;;:=;;;;:;=:=;;:;:;:;:;:;:;:;:;:;:;:;:;:;:;:=;;;=================t====~;,:;;:d


C!) + /bp_regfile4x32/w_data 11111111111111111111111111111111 ~~1;;:_:11:=11=:1=:11:=11:=1:=11=:11:=11=:1=:11:=11:=1:=11=:11:=11:=1:=11=================i=====~1=01:::01:::0::j1.
C!) + /bp_regfile4x32/r _addr 00
::±J + /bp_regfile4x32/w_addr 00
+ /bp_regfile4x32/r _en O
+ /bp_regfile4x32/w_en
+ /bp_regfile4x32/rst
+ /bp_regfile4x32/clk L
;:±) + /bp_regfile4x32/uut/reg0/r 11111111111111111111111111111111 UUUUUUUUUUUUUUUUUUUU ... 1!10000000000000000000000000000000 1111111111111111111111111111111
::±J + /bp_regfile4x32/uut/reg1/r 00000000000000000000000000000000 UUWUUUUUUUUUUUUUUUU... 0000000000000000000000000000000
;:±) + /bp_regfile4x32/uut/reg2/r OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO UUUUUUUUUUUUUUUUUUUU. .. OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
+
W /bp_regfile4x32/uut/reg3/r 00000000000000000000000000000000 UUWUUUUUUUUUUUUUUUU.. . 000 OOOOOOOOOOOOOOOOOOOOOOOOOO

~c;l@ Now 100 ns 2 ns 4 ns


1
6 ns
1
8 ns
1
10ns
1
12 ns
1
14 ns
1 1 i 1
16 ns r::'---118ns
1 1
20 ns
2!J"@ Cursor2 17 ns 117 nsl
l.!,
1Onsto22ns 1 Now: 100 ns Delta: 1

m
.
W+
Messages

/bp_regfile4x32/r _data
/bp_regfile4x32/w_data
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
11111111111111111111111111111111 10101010101010101010101010 01010 1111111111111111111111111111111 !0101010.
W + /bp_regfile4x32/r _addr 00 00
W+ /bp_regfile4x32/w_addr 10 10 11
+ /bp_regfile4x32/r _en o
+ /bp_regfile4x32/w_en
+ /bp_regfile4x32/rst

m
..
m
+ /bp_regfile4x32/clk
/bp_regfile4x32/uut/reg0/r
/bp_regfile4x32/uut/reg1/r
11111111111111111111111111111111
1o 101 o 10101 o 10101 o 10101 o 1o 101 o 1o
11111111111111111111111111111111
00000000000000000000000 ... 10101010101010101010101010101010
[___

W + /bp_regfile4x32/uut/reg2/r 11111111111111111111111111111111 00000000000000000000000000000000 1111111111111111111111111111111


::±J + /bp_regfile4x32/uut/reg3/r 00000000000000000000000000000000 00000000000000000000000000000000

1 1 1 1 1 1 1
22 ns 24 ns 26 ns 28 ns JO ns 32ns 34 ns 40 ns

120 ns to 42 ns 1 Now: 100 ns Delta: 1


F'""-----·-----·--·- .--------- --·=--·-
==->==" ......,...................___ --
Messages

W + /bp regfile4x32/r data 11111111111111111111111111111111 11111111111111111111111111111111 10101 o 10101 o 10101 o 10101 o 101 o 101 o
w + /bp_regfile4x32/w_data oooooooooooooooooooooooooooooooo ~~0~10~10::1:::01:::01:=0:::10:=
.. ·=oo=oo=o=oo=oo=o=oo=oo=oo=o=oo=oo=o=oo=oo=oo=o=oo===F=====;~==============1
w + /bp_regfile4x32/r_addr 00 00 1!11
w + /bp_regfile4x32/w_addr 00 1~1:;:1= = = = ; ; ; : ; ; = = = = = = = = = = = F = = = = = = = = = = = = = = = = = = = 1
+ /bp_regfile4x32/r _en
+ /bp_regfile4x32/w_en
+ /bp_regfile4x32/rst
+ /bp_regfile4x32/clk
::±J + /bp_regfile4x32/uut/reg0/r 11111111111111111111111111111111 ~~1;;;11~1~11~11*11~1~11;;;11~11~1~11*11~1~11;;;11~11~1~11;=======!f=================:::j
8+ /bp_regfile4x32/uut/reg1/r 10101010101010101010101010101010 ~~1~01~0~10~10~10~10~1~01~01~0~10~10~10~1~01~01~0~10========!f=================:::j
@+ /bp_regfile4x32/uut/reg2/r 11111111111111111111111111111111 11111111111111111111111111111111
8 + /bp_regfile4x32/uut/reg3/r 01010101010101010101010101010101 1;0:;10;:10~1;;;01~01~0~10:;10;:10~1;;;01:;;=01~0~10:;10;:10~10~1=======!f=================:::j
l-----------------------------i--,l--,l---,l--l-1-·-¡--¡---¡-¡--~-~--¡---
~ -~-~-~---
~ --~ -~--T--1-
1
~~~ Curs:~: ~~ ~: 48 ns 50 ns 52 ns 54 ns 56 ns ~58 ns 60 ns 62 ns 64 ns 66 ns 68 ns

l.!,r-J
1 47 ns to 69 ns J Now: 100 ns Delta: 1

Figura 5.10: Algunas formas de onda resultantes de la ejecución del banco de pruebas del register
file. En la figura superior, puede observarse la operación de reset síncrono, que se produce en
el instante 5 ns. En el instante 15 ns se escribe en regO. En la figura central, se muestran las
operaciones de escritura en reg1 (25 ns) y en reg2 (35 ns). La escritura es una operación síncrona:
se produce en el flanco de subida de la señal de reloj. Finalmente, en la figura inferior se muestran
las operaciones de lectura de regO (50 ns) y reg1 (60 ns). Obsérvese que la operación de lectura
es asíncrona: se produce en el flanco de subida de la señal r_en, con independencia del valor de la
señal de reloj.

383
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

5.5.5. Descripción del comportamiento del register file

En el Código VHDL 5.14 se muestra otro diseño del register file, en el cual
se realiza una descripción de su comportamiento. Obsérvese que en este diseño se
declara un nuevo tipo de dato, llamado regfile_type, que es un array:

type regfile_type is
array (Oto 3) of std_logic_vector(31 downto O);

Un array es otra forma de declaración de tipo, en la cual el objeto está formado


por un conjunto de elementos, todos del mismo tipo y accesibles mediante un índice.
En la declaración anterior se indica que regf ile_ type consiste en consta de tres
elementos, numerados de O a 3, del tipo std_logic_vector y con 32 bits.

Por ejemplo, en la parte del código en la que se describe la operación de reset, se


accede a los elementos de la señal regfile, que es del tipo regfile_ type, mediante
su índice:

regfile(O) <= X"OOOOOOOO";


regfile(1) <= X"OOOOOOOO";
regfile(2) <= X"OOOOOOOO";
regfile(3) <= X"OOOOOOOO";

El diseño del register file consta de dos bloques process. En el bloque process
W_process se escribe en los registros, tanto en la operación de reset como en la
operación normal de escritura, en la cual la dirección del registro viene determinada
por el vector de dos bits W_addr. Obsérvese cómo se realiza la conversión del vector
de dos bits a un entero, que es usado como índice del array regfile:

regfile(conv_integer(W_addr)) <= W_data;

La función conv_integer, incluida en IEEE. std_logic_unsigned. all, realiza la


conversión de std_logic_vector a integer. Existen funciones con el mismo nombre
en los paquetes IEEE. std_logic_signed. all y IEEE. std_logic_ari th. all, que rea-
lizan las conversiones correspondientes. Así pues, la función conv_integer se usa
habitualmente para convertir un vector a un entero, con el fin de emplear el entero
como índice de un array.

Puede emplearse el banco de pruebas programado en la Sección 5.5.4 para com-


probar el funcionamiento de este diseño. En la Figura 5.11 se muestran las formas de
onda obtenidas en los primeros 27 ns de la simulación. En el instante 5 ns se produce
la operación de reset y, en los instantes 15 ns y 25 ns, se produce la escritura en regO
y reg 1 respectivamente.

384
REGISTROS Y MEMORIAS

-- R egister fi le 4x32.
-- Descripción del comportamiento
-- Fichero: R egFile4x32_comp. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. std_logic_unsigned. all;

entity RegFile4x32 is
port ( R_data : out st<Llogic_vector(31 downto O);
W_data : in std_logic_vector(31 downto O);
R_ addr, W_ addr : in std_logic_vector ( 1 downto O);
R_en, W_en : in std_logic;
clk, rst : in std_logic ) ;
end entity RegFile4x32;

architecture RegFile4x32_comp of RegFile4x32 is

type regfile_type is
array (O to 3) of std_logic_vector ( 31 downto O);
signal regfile : regfile_ type;

begin
W_process : process ( clk)
begin
if rising_edge( clk) then
if ( rst = ' 1 ') then
regfile(O) <= X"OOOOOOOO";
regfile(1) <= X"OOOOOOOO";
regfile(2) <= X"OOOOOOOO";
regfile(3) <= X"OOOOOOOO";
elsif ( W_en = '1 ') then
regfile( conv _integer(W_addr)) <= W_data;
end if;
end if;
end process W_process;

R_process: process (R_addr, R_en, regfile)


begin
if ( R_en = '1') then
R_data <= regf ile ( conv _integer(R_addr));
else
R_data <= (others = > 'Z');
end if;
end process R_process;

end architecture RegFile4x32_comp;

Código VHDL 5.14: Diseño del regist er file mediante la descripción del comportamiento.

385
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Messages r
8 + /bp_regfile4x32/r _data zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
8 + /bp_regfile4x32/w_data 10101010101010101010101010101010 11111111111111111111111111111111 10101010101010101010 ' ..
8 + /bp_regfile4x32/r _addr 00 o
lB+ /bp_regfile4x32/w_addr 01 o 1
+ lbp_regfile4x32/r_en o
+ lbp_regfile4x32/w_en 1
+ lbp_regfile4x32/rst o
+ /bp_regfile4x32/clk 1 1
i.::J + /bp_regfile4x32/uut/regfile {11111111111111111111111111111111}{ uuuuuuuuuuu .. . HOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO ... !{1111111111111111111111111111111 ... H11• ..
m+ <o) 11111111111111111111111111111111 uuuuuuuuuuuu. '' !00000000000000000000000000000000 11111111111111111111111111111111
w+ <1> 10101010101010101010101010101010 uuuuuuuuuuuu. '' !00000000000000000000000000000000 101 ..
@. (2) 00000000000000000000000000000000 UUUUUUUUUUUU ... lOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
@. (3) 00000000000000000000000000000000 uuuuuuuuuuuu' '' lO 0000000000000000000000000000000
,\X[ilf@ Now 100 ns 15
1 1
4 ns
1
ens
1 1 1
12ns
1 1
16 ns
1 1
20 ns
1
' 1 '
24ns ~
i
Gl!I'O Cursor 1 26 ns 26 ns
~~ ..!.,..!.L_1 l!. 1 /

1 Onsto27ns Now: 100 ns Delta: 1

Figura 5.11: Simulación del banco de pruebas, empleando el diseño del register file basado en su
comportamiento.

5.6. BUS BIDIRECCIONAL Y MEMORIAS

Se pretende describir usando VHDL el comportamiento de dos unidades de


memoria y un bus que conecta ambas. Para simplificar, se supone que las unidades de
memoria tienen capacidad para almacenar una única palabra de N bits. Una de las
memorias tiene capacidad de lectura y escritura. La otra sólo de lectura. Además de
las dos memorias, se modela un bus de N líneas que puede leer de ambas memorias y
escribir en la memoria que admite escritura. A continuación, se describe el modelado
mediante VHD L de este sistema.

5.6.1. Memoria de sólo lectura

Los puertos de la memoria son los siguientes:

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.

Vector de salida de N bits (data). Contiene el dato almacenado en memoria


(palabra de N bits) una vez ejecutada la operación de lectura. Está a alta
impedancia cuando la operación de lectura está deshabilitada (DE_n = '1 ').

El Código VHDL 5.15 describe la interfaz y el funcionamiento de esta memoria.


Se definen dos constantes generic: WORD_SIZE, que contiene el número de bits de la

386
REGISTROS Y MEMORIAS

-- Fuente de datos unidireccional (lectura)


-- Fich ero: fuente Unidireccional. vhd
library IEEE; use IEEE. std_logic_1164. all;

entity fuenteUnidireccional is
generic ( WORD_SIZE integer := 8; -- B its por palabm, por defecto 8
READ_DELAY : time := 10 ns); -- RetaTdo en la lectura, por def ecto 10 ns
port ( data : out std_logic_vector(WORD_SIZE-1 downto O); --Datos de salida
OE_n : in std_logic); -- Habilita lectura
end entity fuenteUnidireccional;
architecture fuenteUnidireccional of fuenteUnidireccional is
begin
rom : process (OE_n)
begin
if (OE_n = '0') then
data <= ( O => '1', others = > 'O') after READ_DELAY;
else
data <= (others => 'Z');
end if;
end process rom;
end architecture fuenteUnidireccional;

Código VHD L 5.15: Memoria de sólo lectura.

palabra (N) y READ_DELAY, que contiene el tiempo de retardo entre que se habilita
la señal de lectura hasta que el dato está disponible.

La sentencia

data<= (O=> '1', others => '0' ) after READ_DELAY;

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
'O' excepto el menos significativo, que debe valer '1' (es decir, data<= "OO ... 01" ;) 1 .
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

data<= (others => 'Z');

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).
1
El software de CAD VeriBest muestra un error de compilación en esta sentencia, debido a que
en VHDL 93-2002 la selección others puede usarse junto con otms elecciones sólo si el mngo de
la señal es localment e estático. Por el contrario, el software de CAD ModelSim no muestra error
de compilación, ya que se ha relajado esta restricción del lenguaj e.

387
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

5.6.2. Memoria de lectura y escritura

El Código VHDL 5.16 describe la memoria de lectura y escritura. Como puede


observarse en el código, los puertos de esta memoria son los indicados a continuación:

Señal de entrada de 1 bit (DE_n). Cuando esta señal se pone a 'O', 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.

Vector de entrada y salida de N bits (data).

-- Fuente de datos bidireccional (lectura y escritura)


-- Fichero: fuenteBidireccional. vhd
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 O); -- Señal bidireccional datos
OE_n : in std_logic; -- Habilita lectura
WE_n : in std_logic ) ; -- Habilita escritura
end entity fuenteBidireccional;

architecture fuenteBidireccional of fuenteBidireccional is


signal data_stored : std_logic_vector(WORD_SIZE-1 downto O);
-- Datos almacenados internamente
begin
ram : process (OE_n, WE_n, data)
begin
if ( OE_n = 'O' ) then
data <= data_stored after READ_DELAY;
elsif ( WE_n = ' O' ) then
data_stored <= data after WRITE_DELAY;
else
data <= (others => 'Z');
end if;
end process ram;
end architecture fuenteBidireccional;

Código VHDL 5.16: Memoria de lectura y escritura.

388
REGISTROS Y MEMORIAS

5.6.3. Bus bidireccional

A continuación, se muestra el código del bus de datos que se emplea para rea-
lizar varias operaciones de lectura y escritura sobre las memorias. Al instanciar las
memorias, se asignan nuevos valores al tamaño de la palabra, que pasa a ser 16 bits,
y a los retardos:

- Memoria de sólo lectura: retardo en la lectura de 20 ns.

- Memoria de lectura y escritura: retardo en la lectura de 30 ns y retardo en la


escritura de 40 ns.

Las operaciones que se realizan son las siguientes:

l. tiempo== O (instante inicial). Se asigna valor '1' a las señales OE1_n, OE2_n
y WE_n, es decir, inicialmente se encuentras deshabilitadas las operaciones de
lectura y escritura en las memorias. También, en el instante inicial, se asigna
el valor Ox0fc3 a la señal wri teData del banco de pruebas, cuya finalidad es
almacenar el valor que va a ser escrito en la memoria.

2. tiempo == 100 ns. Se habilita la operación de escritura, para ello se pone a


'O' la señal WE_n. A consecuencia de ello, en el instante tiempo = 140 ns se
escribe el valor Ox0fc3 en la memoria.

3. tiempo == 200 ns. Se deshabilita la operación de escritura, poniendo la señal


WE_n al valor '1 '. Se habilita la operación de lectura de la memoria de sólo
lectura, para lo cual se pone la señal OE2_n a 'O'. A consecuencia de ello, el
valor Ox0001 está disponible en el bus en el instante tiempo = 220 ns.

4. tiempo == 300 ns. Se deshabilita la lectura de la memoria de sólo lectura,


para lo cual se pone la señal OE2_n a '1'. Finalmente, se habilita la lectura de
la memoria de lectura y escritura, para lo cual se pone la señal OE1_n a 'O'.
A consecuencia de ello, en el instante tiempo = 330 ns el valor Ox0fc3 está
disponible en el bus.

El Código VHDL 5.17 y 5.18 describe las operaciones realizadas sobre las memo-
rias mediante el empleo del bus. En la Figura 5.12 se muestra el resultado obtenido
de la simulación.

389
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Conexión de la fuente de datos bidireccional y la fuente unidireccional mediante un bus


-- Fich ero : bus. vhd
library IEEE; use IEEE.std_logic_1164.all;

entity tb_bus is
constant WORD_SZ integer := 16; -- B'its por palabra
constant PERIOD time := 100 ns; -- Periodo ciclo reloj
end entity tb_bus;

architecture tb_bus of tb_bus is

signal data : std_logic_vector(WORD_SZ-1 downto O); -- Datos en el bus


signal OE1_n : std_logic; -- Habilita lectura memoria lectura/escrit'ura
signal OE2_n : std_logic; -- Habilita lectura memoria sólo lectura
signal WE_n : std_logic; -- Habilita escr'itura
signal wri teData : std_logic_vector(WORD_SZ-1 downto O); -- Datos a escribir

component fuenteBidireccional is
generic ( WORD_SIZE integer := 8; -- Bits por palabra
READ_DELAY time := 10 ns; -- Retardo en la lectura
WRITE_DELAY : time := 10 ns); --Retardo en la escritura
port ( data : inout std_logic_vector(WORD_SIZE-1 downto O);
-- Señal de datos bidireccional
OE_n : in std_logic; -- Habilita lectura
WE_n : in std_logic ); -- Habilita escr'itura
end component fuenteBidireccional;

component fuenteUnidireccional is
generic ( WORD_SIZE integer := 8; -- Bits por palabra
READ DELAY time := 10 ns); --- Retardo en la lectura

port ( data : out std_logic_vector(WORD_SIZE-1 downto O);


-- Señal de datos bidireccional
OE_n : in std_logic); -- Habilita lectura
end component fuenteUnidireccional;

begin
-- Instanciar las fuentes de datos, asignando valor a sus constantes generic
U1 : component fuenteBidireccional
generic map (WORD_SZ, 30 ns, 40 ns) -- Asigna valor constantes generic
port map (data, OE1_n, WE_n);

U2 : component fuenteUnidireccional
generic map (WORD_SZ, 20 ns ) -- Asigna valor constantes generic
port map (data, OE2_n);
------------- Continua ... ----------------------------------

Código VHDL 5.17: Bus bidireccional (continúa en el Código VHDL 5.18).

390
REGISTROS Y MEMORIAS

Continuacion ------ ----------------------------

data <= writeData when ( WE_n = '0') else ( others => 'Z');

vectoresTest : process is
begin
OE1_n <= '1 '; OE2_n <= '1'; WE_n <= '1'; -- D eshabilita señales
writeData <= B"0000_1111_1100_0011"; --Dato a escribir {= Ox0fc3)
wait for PERIOD;
WE_n <= '0'; -- Habilita escritura (se escribe Ox0fc3)
wait for PERIOD;
WE_n <= '1'; -- Deshabilita escritura
OE2_n <= '0'; -- Habilita lectura desde la fu ente unidireccional
-- El dato en el bus debe ser Ox0001
wait for PERIOD;
OE2_n <= '1'; -- D eshabilita lectura de la fu ente unidireccional
OE1_n <= '0'; -- Habilita lectura desde la fuente bidireccional
-- El dato en el bus debe ser Ox0fc3
wait for PERIOD;
wait;
end process vectoresTest;
end architecture tb_bus;

Código VHDL 5.18: Bus bidireccional (continuación del Código VHDL 5.17).

0+ /tb_bus/data 0000111111000011 0000111111000011 - 0000000000000001 --0000111111000011


+ /tb_bus/oe1_n o
+ /tb_bus/oe2_n 1
+ /tb_bus/we_n 1
0+ /tb_bus/writedata 0000111111000011 0000111111000011
0+ /tb_bus/u1/data_stored 0000111111000011 uuuuuuuuuuuuuuuu 0000111111000011

,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Now 500 ns ) 50 100 150 200 250 300 350 400
' ·-

Figura 5.12: Formas de onda obtenidas de simular el circuito.

5.7. LECTURAS RECOMENDADAS

Los Capítulos 8 y 9 de (Chu 2006) contienen varios ejemplos de diseño de registros


y memorias.

En el Capítulo 7 de (Pedroni 2004) se encuentra el Código VHDL de diferentes


registros, descritos de diferentes formas, y se discute el número de elementos de
memoria inferidos en cada descripción. Asimismo, se comentan algunos de los errores
de diseño más comunes.

En el Capítulo 9 de (Pedroni 2004) se describe el diseño de diferentes elementos


de memoria, tales como la memoria ROM y la RAM.

391
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

5.8. EJERCICIOS DE AUTOCOMPROBACIÓN

Ejercicio 5.1

Diseñe en VHD L un registro de desplazamiento de 4 bits con una entrada serie


(Serial_in) y una salida serie (Serial_out), como el mostrado en la Figura 5.13. El
registro realiza una operación de desplazamiento de 1 bit en cada flanco de subida
de la señal de reloj ( clk).

....------, Serial out

elk

Figura 5.13: Registro de desplazamiento de 4 bits con entrada y salida serie.

A continuación, programe un banco de pruebas y simúlelo. Inspeccionando visual-


mente las señales de entrada y salida, compruebe que el registro que acaba de diseñar
funciona correctamente. Si la solución es correcta, la señal de salida (Serial_ out)
debería estar retrasada 4 flancos de subida de la señal de reloj respecto a la señal de
entrada (Serial_in).

Ejercicio 5.2

Generalice el diseño del Ejercicio 5.1 al caso de un registro de desplazamiento


de N bits, con una entrada serie y una salida serie. Para ello, defina el número de
bits del registro (N) como una constante de tipo generic. Emplee una sentencia for
dentro de un bloque process para describir la operación de desplazamiento.

392
REGISTROS Y MEMORIAS

Ejercicio 5.3

Diseñe usando VHD L un registro de desplazamiento conversor serie-a-paralelo


y paralelo-a-serie de 4 bits, como el mostrado en la Figura 5.14. El circuito tiene
las siguientes entradas: señal de reloj, dos entradas de selección, una entrada serie,
cuatro entradas para carga en paralelo. Las salidas del circuito son la salida serie y
cuatro salidas en paralelo.

D3 D2 D¡ Do
Serial in
SHSel1
SHSel 0 Clock

º3 º2 Q¡ Qo

Figura 5.14: Registro de desplazamiento de 4 bits serie-a-paralelo y paralelo-a-serie.

Para llevar a cabo la conversión serie-a-paralelo, en primer lugar deben cargarse


los 4 bits en el registro a través de la entrada serie y a continuación realizarse la
lectura en paralelo.

Por otro lado, para la conversión paralelo-a-serie, se realiza primero una escritura
en paralelo y a continuación se realiza la lectura del contenido del registro bit a
bit a través de la salida serie. Para ello, es necesario realizar tres operaciones de
desplazamiento. En la Tabla 5.2 se muestran las operaciones del registro.

Tabla 5.2: Operaciones del registro.

SHSel1 Operación
o o Mantiene valor
o 1 Carga en paralelo
1 o Desplaza 1 bit a la derecha el contenido del
registro y asigna a Q3 el valor en SeriaLin

El diseño del registro en VHDL debe realizarse describiendo el comportamiento


del circuito, empleando para ello un único bloque process. A continuación, programe
un banco de pruebas en VHDL que testee el circuito diseñado. Compruebe el correcto
funcionamiento del circuito observando visualmente sus señales de salida.

393
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 5.4

Diseñe usando VHDL el circuito mostrado en la Figura 5.15, que está compuesto
por una unidad aritmético lógica (ALU) y un registro de desplazamiento. La salida de
la ALU es la entrada al registro de desplazamiento. El tamaño de los dos operandos
de entrada, A y B, es de 16 bits.

A B

Figura 5.15: Circuito compuesto de una ALU y un registro de desplazamiento.

La señal Sel, de 3 bits, determina la operación realizada por el circuito. El bit


menos significativo de Sel indica la operación que realiza el registro, según se muestra
en la Tabla 5.3. Los dos bits más significativos de Sel indican la operación que realiza
la ALU, según se muestra en la Tabla 5.4.

Realice el diseño del circuito usando dos bloques process, uno para describir
las operaciones de la AL U y otro para describir las operaciones del registro. A
continuación, programe un banco de pruebas para testear el circuito.

Tabla 5.3: Operaciones del registro.

Sel(O) Operación
o Desplazamiento a la derecha introduciendo un 'O' a la izquierda
1 Carga el nuevo valor

Tabla 5.4: Operaciones de la ALU.

Sel(2) Sel(1) Operación


o o suma
o 1 resta
1 o and
1 o or

394
REGISTROS Y MEMORIAS

Ejercicio 5.5

Diseñe una memoria de sólo lectura que contenga 8 palabras de 8 bits (ROM
8 x 8). Como se muestra en la Figura 5.16, la ROM contiene un conjunto de palabras
( words) almacenadas. La ROM tiene los siguientes valores (decimales) almacenados
en las direcciones O a 7: O, 2, 4, 8, 6, 32, 64 y 128.

ROM
word O

word 1
addr-~...~ ~-:~data
word 2

Figura 5.16: Representación esquemática de la ROM.

El funcionamiento de la ROM es el siguiente: se presenta en la salida data aquella


palabra seleccionada por la entrada de dirección addr.

Realice el diseño en VHDL de modo que el número de bits de cada palabra (bits)
y el número de palabras de la memoria (words) sean constantes de tipo generic.
Una vez realizado el diseño, programe y simule un banco de pruebas.

395
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 5. 6

Diseñe en VHD L una memoria de acceso aleatorio que contenga 16 palabras de


8 bits (RAM 16 x 8).

Tal como se muestra en la Figura 5.17, la RAM tiene una bus de entrada de
datos (data_in), un bus de salida de datos (data_out), un bus de direcciones (addr),
una entrada de reloj ( clk) y una entrada para habilitar la escritura (wr_ena).

RAM
word O
data_in--+
word 1
data_out
word 2

addr--+

clk wr_ena

Figura 5.17: Representación esquemática de la RAM.

La señal data_in se almacena en la posición indicada por addr cuando la señal


wr_ena está a '1' y la señal clk está en el flanco de subida.

Por otro lado, el bus de salida de datos debe mostrar continuamente los datos
seleccionados por addr.

Realice el diseño en VHDL de modo que el número de bits de cada palabra (bits)
y el número de palabras de la memoria (words) sean constantes de tipo generic.
Una vez realizado el diseño, programe y simule un banco de pruebas.

396
REGISTROS Y MEMORIAS

5.9. SOLUCIONES DE LOS EJERCICIOS

Solución al Ejercicio 5.1

En el Código VHDL 5.19 se muestra un posible diseño del registro de desplaza-


miento. Se usa 1 señal (Serial_ out) y 3 variables (RO, R1 y R2), todas ellas del tipo
std_logic, para almacenar los bits.

Obsérvese que se usan las variables antes de que se les asigne un valor y por ello
la síntesis dará lugar a flip-fiops que almacenan los valores de la anterior ejecución
del bloque process.

Asimismo, puesto que se asigna valor a la señal Serial_ out en el flanco de subida
de la señal de reloj, se generará al realizar la síntesis un fiip-flop que almacenará el
correspondiente bit.

-- R egistro de desplazamiento de 4 bits usando variables


-- Fichero: regDesp4Bits_variables
library IEEE;
use IEEE. std_logic_1164. all;
entity regDesp is
port (Serial_out : out std_logic;
Serial_in, clk : in std_logic);
end entity regDesp;
architecture regDesp of regDesp is
begin
process( clk)
variable RO, R1, R2: std_logic;
begin
if (rising_edge( clk)) then
Serial_out <= R2;
R2 := R1;
R1 :=RO;
RO := Serial_in;
end if;
end process;
end architecture regDesp;

Código VHDL 5.19: Diseño de un registro de desplazamiento de 4 bits.

El Código VHDL 5.20 es otra posible forma de realizar el diseño del registro. En
este caso, se usan 4 señales del tipo std_logic para almacenar los bits: Serial_out,
R2, R1 y RO. La asignación a una señal en el flanco de subida de la señal de reloj da
lugar a la síntesis de un fiip-flop. Por tanto , se sintetizarán 4 fiip-fiops.

Finalmente, el Código VHDL 5.21 es una forma errónea de realizar el diseño.


Se usan 3 variables, como en el Código VHDL 5.19. Sin embargo, en este caso las
asignaciones de los valores se realizan en el orden inverso, con lo cual el diseño

397
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- R egistro desplazamiento usando señales. Fichero : regDesp4Bits_signals.vhd


library IEEE;
use IEEE. std_logic_1164. all;

entity regDesp is
port(Serial_out : out std_logic;
Serial_in, clk : in std_logic);
end entity regDesp;

architecture regDesp of regDesp is


signal RO, R1, R2: std_logic;
begin
process ( clk)
begin
if ( rising_edge( clk) ) then
RO <= Serial_in;
R1 < =RO;
R2 <= R1;
Serial_out < = R2;
end if;
end process;
end architecture regDesp;

Código VHDL 5.20: Otro diseño de un registro de desplazamiento de 4 bits.

-- Diserio ERRONEO del registro. Fichero: regDesp4Bits_variablesMAL.vhd


library IEEE;
use IEEE. std_logic_1164. all;

entity regDesp is
port (Serial_out : out std_logic;
Serial_in, el k : in std_logic);
end entity regDesp;
architecture regDesp of regDesp is
begin
process (el k)
variable RO, R1, R2 : std_logic;
begin
if ( rising_edge( clk) ) then
RO := Serial_in;
R1 :=RO;
R2 := R1;
Serial_out <= R2;
end if;
end process;
end architecture regDesp;

Código VHDL 5.21: Diseño erróneo de un registro de desplazamiento de 4 bits.

no reproduce correctamente el comportamiento del registro de desplazamiento. La


síntesis de este diseño da lugar a un único fl.ip-fl.op.

El banco de pruebas para el registro de desplazamiento es el Código VHDL 5.22.


En este diseño se emplea la sentencia

falling_edge(clk)

398
REGISTROS Y MEMORIAS

para detectar el flanco de bajada de la señal de reloj. Simulándolo se comprueba


que los diseños del Código VHDL 5.19 y 5.20 reproducen correctamente el compor-
tamiento del registro.

-- Banco de pruebas del registro de 4 bits


-- Fichero: bp_regDesp4Bits. vhd
library IEEE;
use IEEE. std_logic_1164.all;

entity bp_regDesp is
end entity bp_regDesp;

architecture bp_regDesp of bp_regDesp is


constant PERIODO : time := 200 ns; -- Reloj
signal Serial_out : std_logic; -- Salidas UUT
signal clk : std_logic:=' O'; -- Entradas UUT
signal Serial_in : std_logic;

component regDesp is
port ( Serial_out : out std_logic;
clk : in std_logic·
Serial_in : in std_logic);
end component regDesp;

begin
-- Instanciar y conectar UUT
uut : component regDesp port map (Serial_out, clk, Serial_in);

clk < = not clk after (PERIOD0/2);


gen_ vec_ test : process is
begin
report "Comienza la simulación";
Serial_ in<=' O'; wait until falling_edge( clk); --200ns
Serial_ in< =' 1'; wait until falling_edge( clk); --400ns
Serial_ in< =' 1'; wait until falling_edge( clk); --600ns
Serial_ in< =' O'; wait until falling_edge( clk); --800ns
report "Finaliza la simulación";
wait; -- Final del bloque process
end process gen_ vec_ test;
end architecture bp_regDesp;

Código VHDL 5.22: Banco de pruebas de un registro de desplazamiento de 4 bits con entrada
y salida serie.

399
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 5.2

El Código VHDL 5.23 es el diseño de un registro de desplazamiento de N bits


con entrada y salida serie. El número de bits del registro (N) se configura asignando
valor a la constante generic N. Obsérvese que los N bits del registro se almacenan
en las señales Serial_ out, R(N-2), ... , R(O). Cada una de estas señales, a las cuales
se asigna valor en el flanco de subida de la señal de reloj, dará lugar al realizar la
síntesis del circuito a un fiip-fl.op.

-- Registro desplazamiento de N bits


-- Fichero: regDespNbits. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity regDesp is
generic (N: integer := 4);
port (Serial_out : out std_logic;
Serial_ in, clk : in std_logic);
end entity regDesp;
architecture regDesp of regDesp is
begin
process ( clk)
variable R: std_logic_vector(N-2 downto O);
begin
if (rising_edge( clk)) then
Serial_out <= R(N-2);
for index in N-3 downto O loop
R(index+1) := R(index);
end loop;
R(O) := Serial_in;
end if;
end process;
end architecture regDesp;

Código VHDL 5.23: Diseño de un registro de desplazamiento de N bits con entrada y salida
serie.

400
REGISTROS Y MEMORIAS

Solución al Ejercicio 5.3

El diseño del registro de desplazamiento paralelo-a-serie y serie-a-paralelo, y el


código del banco de pruebas se muestran respectivamente en Código VHDL 5.24 y
5.25-5.26.

-- Registro serie-a-paralelo y paralelo-a-serie de 4 bits


-- Fichero: registroSerieParalelo.vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity registroSerieParalelo is
port( Serial_out : out std_logic;
Q : out std_logic_vector(3 downto O);
Clock : in std_logic;
SHSel : in std_logic_vector( 1 downto O);
Serial in : in std_logic;
D : in std_logic_vector(3 downto O));
end entity registroSerieParalelo;
architecture registroSerieParalelo of registroSerieParalelo is
signal content: std_logic_vector(3 downto O);
begin
process(Clock)
begin
if(rising_edge(Clock)) then
case SHSel is
when "01" => -- carga paralelo
content <= D;
when "10" => -- desplazamiento derecha
--y Tellena a la izqda con bits
--entrada SeriaLin
content <= Serial_in & content(3 downto 1);
w hen others = >
null;
end case;
end if;
end process;

Q <= content;
Serial_out <= content(O); --Bit más a la derecha

end architecture registroSerieParalelo;

Código VHDL 5.24: Diseño del registro serie-a-paralelo y paralelo-a-serie de 4 bits.

401
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del registro serie-a-paralelo y paralelo-a-serie de 4 bits


-- Fichero: bp_registroSerieParalelo. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity bp_registroSerieParalelo is
end entity bp_registroSerieParalelo;

architecture bp_registroSerieParalelo of bp_registroSerieParalelo is


constant PERIODO : time := 200 ns; --Reloj
signal Serial_out : std_lo~ic; -- Salidas UUT
signal Q: std_logic_vector(3 downto O);
signal Clock: std_logic:= 'O'; -- Entradas UUT
signal SHSel: std_logic_vector(1 downto O);
signal Serial_in: std_logic;
signal D: ·std_logic_vector(3 downto O);

component registroSerieParalelo is
port ( Serial_out : out std_logic;
Q : out std_logic_vector(3 downto O);
Clock : in std_logic;
SHSel : in std_logic_vector(1 downto O);
Serial_in : in std_logic;
D : in std_logic_vector ( 3 downto O));
end component registroSerieParalelo;

begin
-- Instanciar y conectar UUT
uut : component registroSerieParalelo
port map (Serial_out, Q, Clock, SHSel, Serial_in, D);

Clock <= not Clock after (PERIOD0/2);


gen_ ve e_ test : process is
begin
report "Comienza la simulación";
-- Operacion Paralelo-Serie: realizamos una escritura en paralelo y
-- desp'ués vamos desplazando los bits que vamos leyendo de la salida serie

SHSel<="Oi"; Serial_in<='O'; D<="1010"; --Carga paralelo


wait until falling_edge(Clock); --200ns

SHSel<="10"; --Desplaza a la derecha


wait until falling_edge(Clock); --400ns

SHSel<="10"; --Desplaza a la derecha


wait until falling_edge(Clock); --600ns

SHSel<="10"; --Desplaza a la derecha


wait until falling_edge(Clock); --800ns

Código VHDL 5.25: Parte inicial del banco de pruebas para el registro serie-a-paralelo y paralelo-
a-serie de 4 bits.

402
REGISTROS Y MEMORIAS

-- Continuación del banco de pruebas del registro serie-a-paralelo y paralelo-a-serie


-- Fichem: bp_registmSerieParalelo. vhd

-- Operacion Serie-Paralelo: desplazamos los bits que van llegando por entrada serie y
-- después realizamos una lectura en paralelo
SHSel<= 11 01 11 ; Serial_in<=' O'; 0<= 11 0000 11 ;--Car:qa paralelo
wait until falling_edge(Clock); --1000ns
SHSel<= 11 10 11 ; Serial_in<=' 1'; --Desplaza a la derecha
wait until falling_edge(Clock); --1200ns
SHSel<= 11 10 11 ; Serial_in<='O';--Desplaza a la derecha
wait until falling_edge(Clock); --1400ns
SHSel<= 11 10 11 ; Serial_in<=' 1' ;--Desplaza a la derecha
wait until falling_edge(Clock); --1600ns
SHSel<= 11 10 11 ; Serial_in<='O';--Desplaza a la derecha y leemos
wait until falling_edge(Clock); --1800ns
report 11 Finaliza la simulación 11 ;
wait; -- Final del bloque pmcess
end process gen_ ve e_ test;
end architecture bp_registroSerieParalelo;

Código VHDL 5.26: Parte final del banco de pruebas para el registro serie-a-paralelo y paralelo-
a-serie de 4 bits.

403
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 5.4

El diseño del circuito mostrado en la Figura 5.15 es el Código VHDL 5.27. En


este diseño se ha declarado la señal alu_salida, que se usa para guardar el resultado
de la ALU. El registro recibe esta señal, cuyos bits carga o desplaza en función del
valor del bit menos significativo de la entrada de selección, es decir, en función del
valor de Sel (O).

El banco de pruebas de la ALU se muestra en Código VHDL 5.28-5.31. El Código


VHDL 5.28 contiene un package en el cual de definen las constantes globales del
banco de pruebas, cuyo valor es calculado a partir de las constantes globales del
circuito. Se ha seleccionado un conjunto de vectores de test atendiendo a los criterios
expuestos en la Sección 4. 7.2. Son los siguientes:

- Se escogen valores de los operandos entorno al cero. Por ejemplo: -2, -1, O,
1 y 2.

- Se escogen valores de los operandos en el límite inferior de su rango. Por ejem-


plo, si MIN_NEG_DATA representa el valor mínimo que puede tomar el operando,
entonces se escogen los valores MIN_NEG_DATA, ... , MIN_NEG_DATA+4 para cada
uno de los operandos.

Se escogen valores de los operandos en el límite supenor de su rango. Si


MAX_POS_DATA representa el valor máximo que puede tomar el operando, en-
tonces se escogen los valores MAX_POS_DATA-4, ... , MAX_POS_DATA para cada uno
de los operandos.

- Finalmente, se escogen algunos valores "al azar", más o menos distribuidos


uniformemente en el rango de los operandos.

404
REGISTROS Y MEMORIAS

-- Definición de constantes globales de la ALU+Reg. Fichero: ALUReg_CONSTANTS.vhd


package ALUReg_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 ALUReg_CONSTANTS;

-- ALU con registro. Fichero: ALUReg.vhd


library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
use work. ALUReg_CONSTANTS. all;

entity ALUReg is
port( Z : out std_logic_vector(WIDTH-1 downto O);
A, B : in std_logic_vector(WIDTH-1 downto O);
Sel : in std_logic_vector(SEL_BITS-1 downto O);
clk : in std_logic);
end ALUReg;
architecture ALUReg of ALUReg is
signal alu_salida : std_logic_vector(WIDTH-1 downto O);
begin
--ALU
alu: process (Sel, A, B)
begin
case Sel (SEL_BITS-1 downto 1) is
when "00" =>
alu_salida <= std_logic_vector(signed(A) + signed(B));
when "01" =>
alu_salida <= std_logic_vector (signed(A) - signed(B));
when "10" =>
alu_salida <= A and B;
when others =>
alu_salida <= A or B;
end case;
end process alu;
--Registro
reg:process(clk)
begin
if rising_edge( clk) then
if (Sel(O) = '1 ') then --Desplaza a la drcha introduciendo O
Z <= '0'& alu_salida(WIDTH-1 downto 1);
el se
Z <= alu_salida; --Carga el nuevo valor
end if;
end if;
end process reg;
end architecture ALUReg;

Código VHDL 5.27: Diseño del circuito ALU y registro, mostrado en la Figura 5.15.

405
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- D efin ición de constantes globales


-- del banco de pruebas de la AL U+ R egistro
--Fichero : bp_ALUReg_CONS TANTS .vhd
use work. ALUReg_CONSTANTS. all;
package bp_ALUReg_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);
end package bp_ALUReg_CONSTANTS;

-- Banco de pruebas para la AL U


-- Fichero: bp_ALUReg.vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
use work. ALUReg_CONSTANTS. all;
use work. bp _ALUReg_CONSTANTS. all;

entity bp_ALUReg is
constant PERIODO : time := 100 ns;
end entity bp_ALUReg;

architecture bp_ALUReg of bp_ALUReg is


signal A, B, Z : std_logic_vector (WIDTH-1 downto O);
signal Sel : std_logic_vector (SEL_BITS-1 downto O);
signal clk : std_logic:=' O';

component ALUReg is
port ( Z : out std_logic_vector(WIDTH-1 downto O);
A, B : in std_logic_vector(WIDTH-1 downto O);
Sel : in std_logic_vector(SEL_BITS-1 downto O);
el k : in std_logic);
end component ALUReg;

Código VHDL 5.28: Package en el cual se definen las constantes y comienzo del banco de
pruebas de ALU+registro.

406
REGISTROS Y MEMORIAS

---------------- Continua banco de pruebas de AL U+ R eg (fichero bp_AL UReg. vhd) -------------

-- Procedure que calcula Z ( expectecLZ) y lo compara con el


-- valor de Z que se pasa como argumento ( actuaLZ)
-- Si ambos valores no coinC'iden, se muestra 'Un mensaje y se
-- incrementa el contador de errores {error_count)
proced ure checLAL U
( i, j, k : in integer;
actuaLZ: in std_logic_vector (WIDTH-1 downto O);
error_count : inout integer ) is
variable var_Z : integer;
variable expected_Z : integer;
variable varAux: std_logic_vector(WIDTH-1 downto O);
begin
case k is
when O 11 => var_Z := i+j;
when 2 1 3 => var_Z := i-j;
when 4 1 5 => var_Z := TO_INTEGER(signed(
std_logic_vector(TO_SIGNED (i, WIDTH)) and
std_logic_vector (TO_SI G NED (j, WIDTH)) ) );
when others => var_Z := TO_INTEGER(signed(
std_logic_vector(TO_SIG NED ( i, WIDTH)) or
std_logic_vector(TO_SIGNED(j, WIDTH)) ));
end case;
case k is
when 1 1 31 51 7 =>
varAUX := std_logic_vector(TO_SIGNED(var_Z,WIDTH));
expected_Z := TO_INTEGER(signed('O'& varAUX(WIDTH-1 DOWNTO 1)));
when others => -- Trunca el resultado a WIDTH bits
expectecLZ := TO_INTEGER(TO_SIGNED(var_Z,WIDTH));
end case;
assert( expectecLZ = TO_INTEGER(signed(actuaLZ)) )
report "ERROR. Operandos: " & integer'image(i) &
", " & integer'image(j) &
", Operacion: " & integer'image(k) &
", resultado esperado: " &
integer'image~ expected_Z) &
", resultado actual: " &
integer'image(TO_INTEGER( signed( actuaLZ))) &
" en el instante " &
time'image( now);
if (expected_Z /= TO_INTEGER(signed(actuaLZ))) then
error_count : = error_count + 1;
end if;
end procedure checLALU;
-- Fin de la definición del procedv,Te

Código VHDL 5.29: Fragmento del banco de pruebas de ALU+registro: procedure checLALU.

407
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

---------------- Continuación banco de pruebas de AL U+ Reg (fichero bp_AL UReg. vhd) -------------

begin
UUT : component ALUReg port map (Z, A, B, Sel, clk);
clk <= not clk after (PERIODO /2);
-- Bloque process para generar los vectores de test y comprobar el resultado
main : process is
variable erroLcount : integer : = O;
begin
report 11 Comienza la simulación 11 ;
-- Vectores de test: operandos con valor prÓX'i mo a cero
for i in -2 to 2 loop
for j in -2 to 2 loop
for k in O to SEL_MAX loop
A <= std_logic_vector(TO_SIGNED(i,WIDTH));
b <= std_logic_vector(TO_SIGNED(j,WIDTH) );
Sel < = std_logic_vector (TO_SIG NED (k,SEL_BITS));
wai t until falling_edge ( clk);
check....ALU(i, j, k, Z, error_count);
end loop;
end loop;
end loop;
-- Vectores de test: operandos con valor próximo al mínimo
for i in MIN_NEG_DATA to MIN_NEG_DATA +4 loop
for j in MIN_NEG_DATA to MIN_NEG_DATA +4 loop
for k in O to SEL_MAX loop
A <= std_logic_vector(TO_SIGNED(i,WIDTH));
b <= std_logic_vector(TO_SIGNED(j,WIDTH));
Sel <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait until falling_edge(clk);
check....ALU(i, j, k, Z, error_count);
end loop;
end loop;
end loop;
-- Vectores de test: operandos con valor próximo al máximo
for i in MA)LPOS_DATA-4 to MA)LPOS_DATA loop
for j in MA)LPOS_DATA-4 to MA)LPOS_DATA loop
for k in O to SEL_MAX loo~
A <= std_logic_vector(TO_SIGNED(i,WIDTH));
b <= std_logic_vector(TO_SIGNED(j,WIDTH));
Sel <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wai t unt il falling_edge (el k) ;
check....ALU(i, j, k, Z, erroLcount);
end loop;
end loop;
end loop;

Código VHDL 5.30: Fragmento de la definición del banco de pruebas de ALU+registro.

408
REGISTROS Y MEMORIAS

---------------- Continua banco de pruebas de AL U+ R eg (fichero bp_AL UReg. vhd) -------------

-- Vectores de test: operandos con valores 11 al azar 11


for i in O to 9 loop
for j in O to 9 loop
for k in O to SEL_MAX looP-
A <= std_logic_vector(TO_SIGNED(41 *i-273,WIDTH));
b <= std_logic_vector(TO_SIGNED(89*j-384,WIDTH));
Sel <= std_logic_vector(TO_SIGNED(k,SEL_BITS));
wait until falling_edge( clk);
check_ALU(41 *i-273, 89*j-384, k, Z, error_count);
end loop;
end loop;
end loop;
wait for PERIODO;
-- Informe mostrando el resultado del test
if ( error_count=O) then
report 11 Finaliza la simulación sin errores 11 ;
el se
report 11 Finaliza la simulación: 11 & integer 'image ( error_count) & 11
errores 11 ;
end if;
wait; -- Termina la simulación
end process main;
end architecture bp_AL UReg;

Código VHDL 5.31: Parte final de la definición del banco de pruebas de ALU+registro.

409
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 5.5

El diseño de la memoria de sólo lectura (ROM 8 x 8) y el código del banco de


pruebas se muestran en Código VHDL 5.32 y 5.33.

Obsérvese que en el diseño de la ROM se ha definido un nuevo tipo, llamado


vector _arra y, que es un array que consta de 8 elementos, numerados de O a 7, del
tipo std_logic_vector y con 8 bits.

-- Memoria de sólo lectura (ROM 8x8)


--Fichero: ROM.vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity rom is
generic( bits : integer := 8; --Num. bits por palabra
words : integer := 8 ); --Num. palabras en memoria
port( data : out std_logic_vector(bits-1 downto O);
addr : in integer range O to words-1 ) ;
end rom;

architecture rom of rom is


type vector _arra y is array (O to words-1) of
std_logic_vector(bits-1 downto O);

constant memory: vector_array := ( "00000000",


"00000010"'
"00000100"'
"00001000"'
"00010000"'
"00100000"'
"01000000"
"10000000 11 ) ;
begin
data <= memory(addr);
end architecture rom;

Código VHDL 5.32: Diseño de la ROM.

410
REGISTROS Y MEMORIAS

-- Banco de pruebas de la ROM 8x8


-- Pichero: bp_ROM.vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity bp_ROM is
constant DELA Y :time .- 10 ns; -- Retardo usado en el test
end entity bp_RDM;

architecture bp_ROM of bp_ROM is


signal addr : integer range O to 7;
signal data : std_logic_vector(7 downto O);

component rom is
generic( bits : integer := 8; --Num. bits por palabra
words : integer := 8);--Num. palabras en mem.
port( data : out std_logic_vector(7 downto O);
addr : in integer range O to 7);
end component rom;
begin
UUT : component rom port map
(data, addr);

vec_ test : process is


begin
report "Comienza la simulación";
-- Generar todos los posibles valores de entrada
for i in O to 7 loop
addr <= i;
wait for DELAY;
end loop;
report "Simulación finalizada";
wait; -- Final de la simulación
end process vec_ test;
end architecture bp_ROM;

Código VHDL 5.33: Banco de pruebas de la ROM.

411
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 5.6

El diseño de la memoria acceso aleatorio (RAM) y su banco de pruebas son el


Código VHDL 5.34 y 5.35.

Obsérvese que en el diseño de la RAM se ha declarado un nuevo tipo, llamado


vector_array, que es un array que consta de 15 elementos, numerados de O a 14,
del tipo std_logic_vector y con 8 bits.

-- Memoria de acceso aleatorio (RAM) 16x8


-- Fichero: RA!VJ. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity ram is
generic( bits : integer := 8; --Num. bits por palabra
words : integer := 16);--Num. palabras en mem.
port( data_out : out std_logic_vector(bits-1 downto O);
wr _en a : in std_logic;
clk : in std_logic;
addr : in integer range O to words-1;
data_in : in std_logic_vector(bits-1 downto o));
end entity ram;
architecture ram of ram is
type vector _array is array (O to words-1) of
std_logic_vector(bi ts-1 downto O);

signal memory: vector _array;


begin
process( clk, wr _ena)
begin
if(wr_ena = '1') then
if rising_edge( clk) then
memory(addr) <= data_in;
end if;
end if;
end process;
data_out <= memory(addr);
end architecture ram;

Código VHDL 5.34: Diseño de la RAM.

412
REGISTROS Y MEMORIAS

-- Banco de pruebas de la RAM 16x8


-- Fichero: bp_RAM.vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity bp_RAM is
constant PERIODO :time .- 100 ns; -- R etardo usado en el test
end entity bp_RAM;
architecture bp_RAM of bp_RAM is
signal wr _ena : std_logic;
signal clk : std_logic := 'O';
signal addr : integer range O to 15;
signal data_in : std_logic_vector(7 downto O);
signal data_out : std_logic_vector(7 downto O);
component ram is
generic( bits : integer := 8; --Num. bits por palabra
words : integer := 16);--Num. palabras en mem.
port( data_out : out std_logic_vector(7 downto O);
wr _ena : in std_logic;
clk : in std_logic;
addr : in integer range O to 15;
data_in : in std_logic_vector(7 downto o));
end component ram;
begin
UUT : component ram port map
(data_out, wr_ena, clk, addr, data_in);

clk <= not clk after (PERIOD0/2);

gen_ vec_ test : process is


begin
report "Comienza la simulación";
wr _ena <= '1 '; --Habilitada la escritura
addr <= 3; data_ in <= "00000001"; wait until falling_edge( clk);
addr <= 4; data_ in <= "00000010"; wait until falling_edge( clk);
addr <= 5; data_in <= "00000100"; wait until falling_edge(clk);

wr _ena <= 'O'; --Deshabilitada la escritura


addr <= 3; data_ in <= "00001000"; wait until falling_edge( clk);
addr <= 4; data_in <= "00010010"; wait until falling_edge(clk);
addr <= 5; data_in <= "00010100"; wait until falling_edge(clk);

report "Finaliza la simulación";


wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_RAM;

Código VHDL 5.35: Banco de pruebas de la RAM.

413
TEMA 6

DISEÑO DE LÓGICA SECUENCIAL

6.1. Introducción
6.2. Diseño de máquinas de estado finito
6.3. Síntesis de lógica secuencial
6.4. Flip-flop JK
6.5. Máquinas de estado finito de Moore
6.6. Máquinas de estado finito de Mealy
6.7. Máquinas de estado finito seguras
6.8. Lecturas recomendadas
6.9. Ejercicios de autocomprobación
6.10. Soluciones de los ejercicios
DISEÑO DE LÓGICA SECUENCIAL

OBJETIVOS DOCENTES

Una vez estudiado el contenido del tema y realizados los ejercicios prácticos,
debería saber:

- Diseñar usando VHDL distintos tipos de flip-flop y sus bancos de prueba.


Diseñar usando VHDL el circuito latch. Discutir la diferencia entre un flip-flop
y un latch.

- Discutir buenas prácticas aplicables al diseño para síntesis de circuitos secuen-


ciales síncronos.

- Diseñar en VHD L máquinas de estado finito de Moore y de Me aly sintetizables,


realizando el diseño tanto en base a la descripción de su estructura al nivel de
puertas lógicas y flip-flops, como en base a su comportamient?.

- Diseñar y programar en VHDL bancos de pruebas de circuitos secuenciales


síncronos. Discutir diferencias conceptuales entre los bancos de pruebas para
circuitos secuenciales síncronos y para circuitos combinacionales.

- Discutir qué son las máquinas de estado finito seguras y realizar el diseño de
este tipo de máquinas usando VHDL.

417
DISEÑO DE LÓGICA SECUENCIAL

6.1. INTRODUCCIÓN

Algunos problemas de diseño pueden ser resueltos usando máquinas de estado


finito. Una máquina de estado finito consiste esencialmente en un conjunto de estados
(codificados usando flip-fiops) y transiciones entre estos estados, gobernadas por un
conjunto de bits de condición.

En este tema trataremos algunos aspectos del diseño de máquinas de estado


finito de Moore y de Mealy usando VHDL. Una máquina de estado finito de Moore
(o simplemente, "máquina de Moore") es una máquina de estado en la cual las salidas
del circuito dependen del estado actual y no del valor actual de las entradas. Por el
contrario, las salidas de una máquina de M ealy dependen del estado actual y también
del valor actual de las entradas.

Ambos tipos de máquina pueden ser diseñados de manera sistemática, usando el


método de diseño de máquinas de estado finito descrito en este tema.

6.2. DISEÑO DE MÁQUINAS DE ESTADO FINITO

Las máquinas de Moore y Mealy pueden ser diseñadas de manera sistemática


siguiendo los pasos descritos a continuación:

l. Dibujar el diagrama de estados del circuito.

2. Definir un conjunto de variables de estado y codificar los estados del diagrama


de estados usando estas variables de estado.

3. Escribir la tabla de transición del estado usando el diagrama dibujado en el


Paso 1 y la codificación de los estados del Paso 2.

4. Formular, a partir de la tabla de transición del estado del Paso 3, las funciones
lógicas simplificadas para el nuevo estado y las salidas.

5. Diseñar el circuito empleando un flip-flop por cada variable de estado, y lógica


combinacional para las funciones de transición del estado y de salida obtenidas
en el Paso 4. Obsérvese, que el diseño estructural de la máquina de estado
finito (FSM) puede representarse de manera genérica tal como se muestra en
la Figura 6.1.

419
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

¡------------------------------
1
1
1
salidas
entradas: Lógica
combinacional -

f estado actual

elk Registro de estado


1
1
1
1
1
1
1
f próximo estado
1
L------------------------------
Figura 6.1: Modelo de la implementación de una máquina de estado finito.

6.2.1. Circuito detector de secuencias

El método anterior puede aplicarse al diseño de un circuito que detecte la secuen-


cia 101. El circuito tiene una única entrada, por la que recibe bits en serie, y una
única salida, en la que genera un bit 1 cuando detecta la secuencia 101 en los bits de
entrada, y genera un O en caso contrario. Obsérvese que también deben detectarse
las secuencias cuando se encuentran solapadas, por ejemplo: 10101

El primer paso del diseño es dibujar el diagrama de estados del circuito, que
consiste en un conjunto de estados y (posiblemente) transiciones etiquetadas entre
los estados. En la Figura 6.2 se muestra el diagrama de transición para el circuito
detector de la secuencia 101.

Figura 6.2: Diagrama de estados del circuito detector de la secuencia 101.

Cada estado del diagrama "recuerda" una porción de la secuencia 101. Lastran-
siciones 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

420
DISEÑO DE LÓGICA SECUENCIAL

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.

El segundo paso del método de diseño consiste en codificar los estados. Puesto
que hay tres estados, son necesarias dos variables de estado: A y B. Obsérvese
la diferencia conceptual entre los estados de la máquina y las variables de estado
definidas para codificar dichos estados. Por simplicidad en la exposición, realizaremos
una codificación binaria de los estados:

Estado A B
So O O
s1 o 1
s2 1 o

En general, unas codificaciones de los estados conducen a circuitos más sencillos


que otras, aunque las diferencias típicamente no son muy grandes.

El tercer paso del método de diseño consiste en escribir la tabla de transición


de estados y salidas. Esto puede hacerse de manera sencilla a partir del diagrama de
transición de estados mostrado en la Figura 6.2 y de la tabla anterior de codificación
de los estados. La tabla de transición de estados y salidas es la siguiente:

Estado actual Entrada Próximo estado Salida


A B X NA NB y
So: 00 o So: 00 o
So: 00 1 S1: o1 o
S1: o1 o S2: 1o o
S1: o1 1 S1: o1 o
S2: 1o o So: 00 o
S2: 1o 1 S1: o1 1

El cuarto paso consiste en obtener las funciones lógicas simplificadas que re-
lacionan el próximo estado y la salida, con el estado actual y la entrada. Estas
funciones son las siguientes:

NA xB (6.1)
NB X (6.2)
y xA (6.3)

421
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Finalmente, el quinto paso consiste en sintetizar el circuito secuencial síncrono


que implemente las funciones lógicas anteriores. Si se usan flip-flops D, las entradas
al flip-flop corresponden con el nuevo estado (DA= N A, DB =N B), mientras que
las salidas del fli p-flop corresponden con el estado actual (QA = A, QB = B). En la
Figura 6.3 se muestra el circuito .

. - - - - - - - - - - - - - - - - - + r - -..............................
r l !.............................~........
: "~ ··· · ·······""'''''''''''''''''''' ''' ''' '

; ........................... ,..;

X
.........................................

elK
.........................................

Figura 6.3: Circuito detector de la secuencia 101.

6.3. SÍNTESIS DE LÓGICA SECUENCIAL

El comportamiento y la salida de un bloque de lógica secuencial depende del


valor actual de sus entradas y de sus variables de estado. El valor de las variables
de estado se almacena típicamente en elementos de memoria, ya sea en latches o en
flip-flops.

Se llama latches a aquellos circuitos cuyo estado cambia únicamente cuando su


entrada enable está a un determinado nivel ('O' ó '1'). A continuación, se muestra
parte de la architecture de un latch-D.

process (enable, D) is
begin
if (enable = '1') then
q <= D;
end if;
end process;

Asimismo, se llama flip-flops a aquellos circuitos cuyo estado cambia o bien en el


flanco de subida del reloj, o bien en el flanco de bajada del reloj. En la Sección 2.7
se describió el diseño de un flip-flop D.

422
DISEÑO DE LÓGICA SECUENCIAL

6.3.1. Sentencias condicionales incompletas

Obsérvese que el latch se define empleando una cláusula if-then sin else. Se
denomina sentencias condicionales incompletas a este tipo de sentencias. Este punto
es importante, ya que muestra que las sentencias condicionales incompletas (if, case,
etc. sin else) son sintetizadas mediante latches. Esto es debido a que la salida debe
mantener su valor si ninguna de las condiciones de la cláusula se satisface.

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

6.3.2. Sentencias condicionales completas

U na característica inherente a las sentencias if-elsif-else es que las condiciones


no tienen forzosamente que ser excluyentes entre sí. La herramienta se síntesis asume,
por tanto, que deben comprobarse las condiciones en un cierto orden de prioridad,
generando la lógica para ello. Esto da lugar a circuitería innecesaria en el caso en
que las condiciones sean excluyentes.

En aquellos casos en que las condiciones de la sentencia condicional completa sean


excluyentes entre sí, es preferible emplear sentencias case o with. Esto es debido
a que las sentencias case y with se sintetizan de manera natural en multiplexores
o estructuras equivalente a multiplexores, que son rápidas y ocupan relativamente
poco área.

6.3.3. Retardos

En la Sección 4.2 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 tec-
nologí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 wai t for x ns. Igual-
mente, no es posible sintetizar sentencias que empleen la cláusula after. Algunas

423
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

herramientas de síntesis ignoran estas sentencias, mientras que otras muestran men-
sajes 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.

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

La inicialización de una variable o señal implica una acción que se realiza úni-
camente una vez al comienzo de la simulación. Si es preciso realizar una acción al
comienzo de la simulación, entonces debe situarse en la secuencia de acciones que
se ejecutan cuando se activa la señal de reset. Estas acciones se definen típicamente
dentro de un bloque process sensible a la señal de reset.

6.3.5. Bloques process

La descripción de la architecture de los circuitos secuenciales se basa funda-


mentalmente en el empleo de bloques process. Las asignaciones a señales dentro de
los bloques process deben cumplir que:

- La señal en la parte izquierda de la asignación secuencial debe ser una señal


definida dentro del bloque process, o una señal out o inout de la interfaz del
circuito.

424
DISEÑO DE LÓGICA SECUENCIAL

- Las señales en la parte derecha de la asignación secuencial deben ser señales


definidas dentro del bloque process, o señales in o inout de la interfaz del
circuito.

- No se debe asignar valor a una determinada señal dentro de más de un bloque


process. Es decir, cada señal debe ser evaluada en un único bloque process.
Aunque VHDL no impide que se asigne valor a una misma señal en varios
bloques process, esta práctica da lugar a circuito difíciles de depurar y típi-
camente no es soportada por las herramientas de síntesis comerciales.

Para asignar valor a las salidas de los fiip-fiops 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 6 (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 controlar cuán-
do 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 o mediante el empleo de cláusulas wait dentro del cuerpo el
bloque process. En cada bloque process debe optarse por uno de los dos métodos,
ya que no es posible emplear simultáneamente una lista de sensibilidad y senten-
cias wait. Sin embargo, no es recomendable emplear este segundo método (uso de
sentencias wait dentro del bloque process), ya que puede dar lugar a circuitos no
sintetizables.

6.4. FLIP-FLOP JK

En esta sección se describe el diseño de un fiip-fiop JK con reset asíncrono


activado al nivel LOW. Este circuito puede encontrarse en dos estados: Q='O' y
Q='l'. La tabla de transición de estados, considerando únicamente las entradas J
y K, así como el estado actual (Qt) y el siguiente estado (Qt+I), es la mostrada a
continuación. Las transiciones de estado se producen en el flanco de subida de la
señal de reloj.

425
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

J K Nuevo estado
0- -0
o o

-- -------~GJ-~-~~GJ
Qt+l=Q,
o 1 Qt+l=O
1 o Qt+l =1
1 1 Q1+1=not Q,

Figura 6.4: 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 '-' es "don't care" (por ejemplo, "0-" representa "00" ó "01"). La
transición de reset se representa mediante una línea punteada.

Cuando la entrada de reset asíncrono pasa de valer '1' a valer 'O', el circuito pasa
al estado Q='O'. Se denomina reset asíncrono porque la transición al estado 'O' 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 asíncrono se representa mediante una
línea punteada en el diagrama situado en la parte derecha de la Figura 6.4.

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.

6.4.1. Diseño del flip-flop

El Código VHDL 6.1 es el diseño de un flip-flop JK con reset asíncrono activado


al nivel LOW. La architecture contiene un bloque process que es sensible a la
señal de reset y a la señal de reloj. En el cuerpo del bloque process se examina
primero la señal de reset, ya que en caso de estar activa esa señal (con valor 'O') la
máquina debe pasar al estado Q='O'.

6.4.2. Banco de pruebas

En el caso de los circuitos combinacionales, el objetivo del programa de test


es comprobar (cuando esto es posible) todas las posibles combinaciones de valores
de las entradas al circuito. En los circuitos secuenciales, el programa de test debe
recorrer (cuando esto es posible) todos los arcos del diagrama de estado, para cada
uno de los valores de las entradas que producen la transición.

En el caso del biestable JK, esto implica testear 8 transiciones. En la Figura 6.5
se indica el orden en que el programa de test recorrerá los arcos (número inscrito

426
DISEÑO DE LÓGICA SECUENCIAL

-- Biestable JK con reset asíncrono en nivel LOW


-- Fichero: fiipfiop_JK. vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity flipflop_JK is
port ( q, q_n : out std_logic;
clk, J, K, reset_n : in std_logic ) ;
end entity flipflop_JK;
architecture flipflop_JK of flipflop_JK is
signal q_interna : std_logic;
begin
q <= q_interna;
q_n <= not q_interna;
process (reset_n, clk) is
variable JK : std_logic_vector( 1 downto O);
begin
if (reset_n = 'O') then
q_interna <= '0';
elsif rising_edge( clk) then
JK := J & K;
case (JK) is
when 11 01 11 = > q_interna <= '0';
when 11 10 11 = > q_interna <= '1';
when 11 11 11 => q_interna <= not q_interna;
when others => null;
end case;
end if;
end process;
end architecture flipflop_JK;

Código VHDL 6.1: Diseño de un fl.ip-fl.op JK con reset asíncrono.

en una circunferencia), y qué valores de las entradas se aplicará en cada caso para
producir la transición. El Código VHDL 6.2 y 6.3 es el banco de pruebas.

En el banco de pruebas se ha definido un procedure, que comprueba que los


valores actuales de la salida del flip-flop coinciden con los esperados, mostrando el
correspondiente mensaje en caso de que no coincidan.

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 indefi-
nidamente. Por tanto, la simulación del banco de pruebas no finaliza por sí misma,
siendo preciso fijar su duración: 900 ns. La simulación del banco de pruebas se realiza
con cero errores. En la Figura 6.6 se muestra el resultado obtenido de la simulación.

427
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- B anco de pruebas del fiip-fiop JK


-- Fichero: bp_fiipfi opJK. vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity bp_flipflopJK is
end entity bp_flipflopJK;

architecture bp_flipflopJK of bp_flipflopJK is


constant PERIODO : time := 100 ns; -- Reloj
signal q, q_n : std_logic; -- Salidas UUT
signal clk : std_logic := 'O'; -- Entradas UUT
signal J, K, reset_n : std_logic;

component flipflop _JK is


port ( q, q_n : out std_logic;
clk, J, K, reset_n : in std_logic ) ;
end component flipflop_JK;

-- P rocedimiento para compro bar las salidas del fiip-fi op


procedure comprueba_salidas
( esperado_q std_logic;
actual_q, actual_q_n std_logic;
error_count : inout integer) is
begin
-- Com prueba q
if ( esperado_q /= actual_q ) then
report "ERROR: Estado esperado (" &
std_logic' image( esperado_q) &
"), estado actual (" &
std_logic' image(actual_q) &
11
) , instante:
11
&
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) &
11
) , instante: " &
time' image ( now);
error count := error_count + 1;
end if;
end procedure comprueba_salidas;

Código VHDL 6 .2: Comienzo del banco de pruebas de un flip-flop JK.

428
DISEÑO DE LÓGICA SECUENCIAL

-- Continuación del banco de pruebas del fiip-fiop JK


-- Fichero: bp_fiipfiopJK.vhd
begin
-- Instanciar y conectaT UUT
uut : component flipflop_JK port map
(q, q_n, clk, J , K, reset_n);

reset_n <= '1 ',


'O' after (PERIODO/ 4),
'1' after (PERIODO+PERIOD0/4);
clk <= not clk after (PERIOD0/2);
gen_ vec_ test : process is
variable error _count : integer := O; -- Núm. errores
begin
report "Comienza la simulación";

-- Vectores de test y comprobación del resultado


J <= '0'; K <= '0'; wait for PERIODO; -- 1
comprueba_salidas(' O' ,q,q_n,error _count);
J <= '0'; K<= '1'; wait for PERIODO; -- 2
comprueba_salidas(' 0' ,q,q_n,error _count );
J <= '1'; K<= '0'; wait for PERIODO; --3
comprueba_salidas(' 1' ,q,q_n,error_count);
J <= '0'; K <= '1'; wait for PERIODO; --4
comprueba_salidas( 'O' ,q,q_n,error _count );
J <= '1';K <= '1'; waitforPERIODO; --5
comprueba_salidas(' 1' ,q,q_n,error_count);
J <= '0'; K <= '0'; wait for PERIODO; -- 6
comprueba_salidas(' 1' ,q,q_n,error_count);
J <= '1'; K<= '0'; wait for PERIODO; -- 7
comprueba_salidas(' 1' ,q,q_n,error_count);
J <= '1';K <= '1'; waitforPERIODO; -- 8
comprueba_salidas( 'O' ,q,q_n,error _count );
J <= 'O'; K <= 'O'; -- D eja el fiip-fiop en el estado 'O'
-- Informe final
if (error_count =o) then
report "Simulación finalizada sin errores";
else
report "ERROR: Hay " &
integer' image (error_ count) &
" errores.";
end if;

wait; -- Final del bloque pTocess, pero como


-- la architecture tiene sentencias de
-- asignación concuTrente, esta sentencia
-- wait no finaliza la simulación
end process gen_vec_test;

end architecture bp_flipflopJK;

Código VHDL 6.3: Continuación del banco de pruebas de un fl.ip-fl.op JK.

429
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

CD oo ® oo

---~----~ ~+-----~-:-~ ~ 1_1-

~ ®10 ~
G) 11

Figura 6.5: Orden en que el programa de test recorre los arcos del diagrama de transiciones.

Messages , V
+ /bp_flipflopjk/q o ---, 1 1
+ /bp_flipflopjk/q_n 1 ---' 1 1 1 1
+ /bp_flipflopjk/clk o
+ /bp_flipflopjk/j o 1 1 1 1 1 1
+ tbp_flipflopjk/k o 1
+ /bp_flipflopjk/reset_n 1 'l 1

lllllllllllllllllllllllllllllltlllllllllllllllllllllllllllllltllllllllllllllllllllllllllll
,~¡;;¡}~ Now ~00 ns lS 200 ns 400 ns 600 ns 800 ns
iJ .!.J .!J.!.J r-. 1 1
1 Onsto935ns 1 Now: 900 ns Delta: 1

Figura 6.6: Resultado de la ejecución del banco de pruebas del flip-flop JK.

6.5. MÁQUINAS DE ESTADO FINITO DE MOORE

Hay varias maneras de escribir código VHDL para una máquina de Moore.
En primer lugar, puede escogerse describir el comportamiento o la estructura del
circuito. En la mayoría de los casos es preferible describir el comportamiento 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 6. 7 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 8 2 y O en los demás estados. Este código puede ser adaptado fácilmente
para la descripción de otras máquinas de Moore.

6.5.1. Diseño de la máquina

El Código VHDL 6.4 y 6.5 describe la máquina de Moore mostrada en la Fi-


gura 6.7. En primer lugar, se define un package con las constantes que serán
usadas en el circuito y en el banco de pruebas. Definir las constantes globales de

430
DISEÑO DE LÓGICA SECUENCIAL

Figura 6. 7: Máquina de estado finito de Moore.

esta manera facilita realizar cambios globales y también favorece la legibilidad del
código. Asimismo, en el diseño de la máquina puede observarse que:

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

- Se ha definido una señal interna a la architecture, llamada internal_state,


que almacena el estado actual en que se encuentra la máquina. Cabe pregun-
tarse por qué no se usa directamente la señal state, ya que ambas señales
representan lo mismo y, de hecho, la sentencia
state <= internal_state;

hace que ambas tengan el mismo valor. El motivo es que, por ser state
una señal de salida de la interfaz, no puede ser leída en el cuerpo de la
architecture. Puesto que internal_state es una señal interna, puede ser
leída y escrita.

La architecture contiene dos bloques process:

l. El primero, que es activado cuando hay un cambio en internal_state,


describe los cambios en la señal de salida, z.
2. El segundo, que es activado cuando cambia la señal de reset asíncrono
(res et _n) o la señal de reloj (e lk), describe los cambios en el estado de
la máquina, actualizando el valor de la señal internal_state .
Puesto que se comprueba antes el valor de reset_n, esta señal tiene
prioridad sobre la señal de reloj.
Se emplea la función estándar de VHDL rising_edge para representar
que las transiciones en el estado sólo se producen en el flanco de subida
de la señal de reloj.

431
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Paquete con la definición de las constantes globales


-- Fichero: STATE_CONSTANTS.vhd
library IEEE;
use IEEE. std_logic_1164. all;
package STATE_CONSTANTS is
constant STATE_BITS: integer := 2; -- Bits codifican estado
constant SO: std_logic_vector(1 downto O) .- "00"; --Estados
constant S1: std_logic_vector(1 downto O) .- "01";
constant S2: std_logic_vector(1 downto O) .- "10";
end package;

-- Máquina de Moore
-- Fichero : maquinaMooreSimple. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work.STATE_CONSTANTS.all;

-- Definición de la entity
entity maquinaMooreSimple is
port( z : out std_logic; -- Señal de salida
state : out std_logic_vector(STATE_BITS-1 downto O);
-- Estado actual de la máquina
reset_n : in std_logic; -- Señal reset activada en bajo
clk : in std_logic· -- Señal de reloj
x : in std_logic); -- Señal de entrada
end entity maquinaMooreSimple;
-- Definición de la architecture
architecture maquinaMooreSimple of maquinaMooreSimple is
signa! internal_state: std_logic_vector(STATE_BITS-1 downto O);

begin
state <= internal_state; -- Estado actual

-- Genera la salida
salida: process(internal_state) is
begin
case internal_state is
when SO => z <= '0';
when S1 => z <= '0';
when S2 => z <= '1 ';
when others => z <= 'X';
end case;
end process salida;

Código VHDL 6.4: Definición del package con la codificación de los estados y parte inicial del
diseño de la máquina de Moore de la Figura 6.7.

432
DISEÑO DE LÓGICA SECUENCIAL

-- Continuación del dis eño de la máquina de lVIoore


-- Fichero: maquinaMooreSimple. vhd
-- Genera el siguiente estado
proximo_estado: process(reset_n,clk) is
begin
if (reset_n = 'O') then -- Reset asíncrono
internal_state <= SO;
elsif rising_edge( clk) then -- En flanco subida del reloj
case internal_state is
when SO => -- Estado actual: SO
if ( x = ' 1 ' ) then
internal_state <= S1;
else
internal_state <= S2;
end if;
when S1 => -- Estado actual: Sl
if ( x = 'O' ) then
internal_state <= S2;
end if;
when S2 => -- Estado actual: S2
if (x = '0') then
internal_state <= SO;
end if;
when others => -- Por completitud
internal_state <= "XX";
end case;
end if;
end process proximo_estado;
end architecture maquinaMooreSimple;

Código VHDL 6.5: Continuación del diseño de la máquina de Moore de la Figura 6.7.

Se ha añadido una cláusula when others al final de las dos sentencias case,
con el fin de contemplar todos los casos posibles. Obsérvese que se asigna el
valor 'X' 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). Se volverá sobre este tema en la Sección 6.7, en la cual
se discutirá una forma más adecuada de describir el comportamiento de la
máquina en los estados ilegales.

6.5.2. Banco de pruebas

A continuación, se muestra el código VHDL de un banco de pruebas que puede


usarse para comprobar el funcionamiento de la máquina de estado finito. El programa
de test ejercita completamente la máquina: todos los arcos de las transiciones son
recorridos al menos una vez.

En la Figura 6.8 se indica el instante de tiempo en el cual se produce la transición


entre los estados. La constante Tes el periodo de la señal de reloj, que en el código
VHDL del banco de pruebas de denomina PERIODO y toma el valor 100 ns. La señal de

433
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

reloj, que inicialmente vale O, tiene un periodo (PERIODO) de T = 100 ns. Esto implica
que los flancos de subida de la señal de reloj se producen en los instantes: 0.5 · T = 50
ns, 1.5 · T = 150 ns, 2.5 · T = 250 ns, ... que son precisamente los instantes en que se
producen las sucesivas transiciones en el estado, según se muestra en la Figura 6.8.
Para generar la señal de reloj se emplea la siguiente sentencia concurrente:

clk <= not clk after ( PERIOD0/2 );

donde se asume que la señal de reloj ha sido inicializada al valor 'O'. Obsérvese que
de esta forma se crea una señal de reloj infinitamente larga, con lo cual la simulación
no finalizará automáticamente, sino que hay que definir el instante de finalización.

~ IT=PERIODO=lOOnsl

s~~T
_o:~~:!_,. @~
8 4.5 ri 3.5-r

Figura 6.8: Transiciones en el estado realizadas durante el test.

En el Código VHDL 6.6 y 6. 7 es el banco de pruebas para la máquina de Moore.


Obsérvese que se define un procedimiento para comparar el valor esperado del estado
y la salida de la máquina con los actuales. De esta forma, el código del banco de
pruebas es más sencillo de entender. En la Figura 6.9 se muestran las formas de
onda obtenidas al ejecutar el banco de pruebas. El test de ejecuta con cero errores.
----···¡¡;~=~~~~;~~~~;;S~~;¡;;;~~=~- ·;- - --- r==:i- ---------·--·-----·-- --- ···--·-·-··--·---· ···--·-·····----··--·-·-· .. -- -·--·-·-·--·-·--···--···-··--·------·----·---- ----·-·-·-·--·
+ /bp_maquinamooresimple/clk O •
+ /bp_maquinamooresimple/x 1
(±¡ + /bp_maquinamooresimple/state 10 .!,&LOO 10 00 01 10
+ /bp_maquinamooresimple/z •---, ,..------

1'~' ' '''''


1
'''''';~·~·~~ ' ''''' 1 ''''''~b~~~~~''''' ' '''''3~~ ~~~'''''''''''''~b'~ ~~~'''''' ''''''~o·~·~~''''''' ''''''~b'~ ~~~'''''''''''' ~o~·~~'''''''''''' '~O'~'~~''
1 1
Now 800 ns

_!..~ _!.. t-. 1 1 /


,
1-o -ns-to -82-6 n-s ----~ Now: 800 ns Delta: 1

Figura 6.9: Resultado de la ejecución del test.

434
DISEÑO DE LÓGICA SECUENCIAL

-- Banco de pTuebas paTa la máquina de MooTe. Fichero: bp_maquinaMooTeSimp le.vhd


library IEEE;
use IEEE. std_logic_1164. all;
use work. STATE_CONSTANTS. all;

entity bp_maquinaMooreSimple is
constant PERIODO : time := 100 ns; -- Periodo reloj
end entity bp_maquinaMooreSimple;

architecture bp_maquinaMooreSimple of bp_maquinaMooreSimple is


signal z : std_logic;
signal state : std_logic_vector(STATE_BITS-1 downto O);
signal reset_n : std_logic;
signal clk : std_logic := 'O'; -- Inicializada a 'O'
signal x : std_logic;

component maquinaMooreSimple is
port( z : out std_logic; -- Señal de salida
state : out std_logic_vector(STATE_BITS-1 downto O);
-- Estado actual de la máquina
reset_n : in std_logic; -- Señal reset activada en bajo
clk : in std_logic; -- Señal de reloj
x : in std_logic); -- Serial de entrada
end component maquinaMooreSimple;

-- Procedimiento para comprobar el resultado


procedure comprueba_state_z
( esperado_state std_logic_vector(STATE_BITS-1 downto O);
esperado_z std_logic;
actual_state std_logic_vector(STATE_BITS-1 downto O);
actual z : std_logic;
error _count : inout integer ) is
begin
-- Comprue ba el estado
assert ( esperado_state = actual_state )
report "ERROR : estado esperado (" &
std_logic' image( esperado_state(1)) & std_logic' image( esperado_state(O)) &
"), estado actual C' &
std_logic' image(actual_state(1)) & std_logic' image(actual_state(O)) &
") en el instante " & time' image(now);
if ( esperado_state 1= actual_state ) then
error_count := error_count + 1;
end if;
-- Comprueba la salida
if ( esperado_z 1= 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;

Código VHDL 6.6: Banco de pruebas de la máquina de Moore de la Figura 6.7.

435
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Continuación del banco de pruebas. Fichero: bp_maquinaMooreSimple.vhd


begin -- Cuerpo de la architecture
UUT : component maquinaMooreSimple port map ( z, state, reset_n, clk, x );

-- Genera un único pulso LOW en el instante PERIOD0/4: resetea la máquina


reset_n <= '1',
'0' after ( PERIOD0/4 ),
'1' after ( PERIODO +
PERIOD0/4 );

-- Genera señal clk, asumiendo que se inicializó a O. Flanco de subida en los instantes:
-- PERIOD0/2, PERIODO+PERIOD0/2, 2*PERIODO+PERIOD0/2, ...
clock : clk <= not clk after ( PERIOD0/2 );

-- main process: genera vectores de test y comprueba resultados


main : process is
variable error _count : integer := O; -- 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 SO
comprueba_state_z(SO, 'O', 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;
-- En el instante 3*PERIODO, el estado debería ser 82
comprueba_state_z(S2, '1', state, z, error _count );
x <= 'O'; wait for PERIODO;
-- En el instante 4 *PERIODO, el estado debería ser SO
comprueba_state_z(SO, 'O', state, z, error _count);
x <= '1'; wait for PERIODO;
-- En el instante 5*PERIODO, el estado debería ser S1
comprueba_state_z(S1, '0', state, z, error_count);
wait for PERIODO;
-- En el instante 6*PERIODO, el estado debería ser S1
comprueba_state_z(S1, '0', state, z, error_count);
x <= 'O'; wait for PERIODO;
-- En el instante 7*PERIODO, el estado debería ser 82
comprueba_state_z(S2, '1', state, z, error _count);
x <= '1 '; -- El estado final es S2
wait for PERIODO;
if (error_count = o) then
report "Simulación finalizada con O errores";
el se
report "ERROR: hay 11 & integer'image(error_count) & " errores.";
end if;
wait; -- Final de la ejecución del bloque process.
end process main;
end architecture bp_maquinaMooreSimple;

Código VHDL 6. 7: Continuación del banco de pruebas de la máquina de Moore de la Figura 6. 7.

436
DISEÑO DE LÓGICA SECUENCIAL

6.5.3. Modelado estructural

Ahora veremos cómo describir la máquina de estado finito de la Figura 6. 7


empleando código VHDL estructural. Usando código estructural se tiene mayor
control acerca de la lógica que se emplea en el diseño, con lo cual en algunos casos
pueden conseguirse circuitos más optimizados que los dados por las herramientas de
síntesis a partir de la descripción del comportamiento. Sin embargo, implica realizar
parte del diseño manualmente, con el consiguiente riesgo de cometer errores.

Para emplear código VHDL estructural, en primer lugar hay que decidir qué
componentes van a usarse en el diseño. Emplearemos puertas lógicas básicas (AND,
OR, inversor, NAND, NOR y XOR), así como flip-flops D. Recuérdese que en la
Sección 2.7 se describió el diseño de un flip-flop D. Para ello, deben obtenerse las
funciones lógicas para el cálculo de la salida y del siguiente estado. La tabla de
transición de estados y salidas para la máquina descrita en la Figura 6. 7 es:

Estado actual Entrada Próximo estado Salida


A B X NA NB z
So: 00 o S2: 1 o o
So: 00 1 S1: o1 o
S1: o1 o S2: 1o o
S1: o1 1 S1: o1 o
S2: 1o o So: oo 1
S2: 1o 1 S2: 1o 1

Las funciones lógicas simplificadas que relacionan el próximo estado (N A, N B)


y la salida (z), con el estado actual (A, B) y la entrada (x) son:

NA xA+xA (6.4)
NB xA (6.5)
z A (6.6)

El Código VHDL 6.8 describe estructuralmente estas funciones lógicas. Se trata


de una nueva architecture para la entity del circuito anteriormente definida.
Puede emplearse el banco de pruebas descrito en la Sección 6.5.2 para testear
esta descripción del circuito. Se obtienen los mismos resultados que se obtuvieron
cuando se hizo el test de la descripción del comportamiento (véase la Figura 6.9).
Los resultados del test se muestran en la Figura 6.10.

437
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Máquina de Moore, diseño estructural


-- Fichero: maquinaMooreSimple_estruc. vhd
library IEEE;
use IEEE. std_logic_1164. all;

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

-- Componente: fiip-fiop 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

-- Conexiones de los fiip-fiops


-- Las salidas q_n se dejan sin conectar
dff_A: component flipflop_D port map
( q => A, d => NA, clk => clk, reset_n => reset_n );
dff_B: component flipflop_D port map
( q => B, d => NB, clk => clk, reset_n => reset_n );

-- Funciones para el cálculo del nuevo estado '!/. la salida


NA <= ((not x) and (not A)) or (x andA);
NB <= x and (not A);
z <=A;
end architecture maquinaMooreSimple_estruc;

Código VHDL 6.8: Diseño estructural de la máquina de Moore.

+ /bp_maquinamooresimple/uut/reset_n 1
+ /bp_maquinamooresimple/uut/clk
+ /bp_maquinamooresimple/uut/x
+ /bp_maquinamooresimple/uut/dff_a/q 1
+ /bp_maquinamooresimple/uut/dff_b/q O
lf) + /bp_maquinamooresimple/uut/state 10 10 00 01
+ /bp_maquinamooresimple/uut/z 1
.---------,

200 ns 400 ns 600 ns 800 ns

1 Ons to 834 ns

Figura 6.10: Resultado de la ejecución del test.

438
DISEÑO DE LÓGICA SECUENCIAL

6.6. MÁQUINAS DE ESTADO FINITO DE MEALY

En las máquinas de Mealy, las salidas del circuito dependen del estado actual
y del valor actual de las entradas. Así pues, aunque la máquina permanezca en un
determinado estado, sus salidas pueden cambiar si cambian las entradas.

Como ejemplo de implementación de una máquina de Mealy, consideremos la


máquina para el reconocimiento de la secuencia de bits 0110 mostrada en la Fi-
gura 6.11. Obsérvese que se permite el solapamiento de secuencias (por ejemplo,
0110110).

0/0
~

1/0 0,
~~~~
----------~0 r 0/1 0/0 ®
~®~
Figura 6.11: Diagrama de una máquina de Mealy para el reconocimiento de la secuencia 0110.

La salida de la máquina es un '1' lógico cada vez que se detecta el patrón 0110
en la secuencia de bits de entrada, que se supone que está sincronizada con el reloj
de la máquina. El tiempo que transcurre entre la entrada del último 'O' del patrón
y la salida del '1' es igual al retardo de una puerta lógica. Para los demás bits de la
secuencia de entrada, la salida de la máquina es 'O'.

6.6.1. Diseño de la máquina

Además de la entrada serie de la secuencia de bits (x) y la entrada del reloj


( clk), la máquina tiene una entrada de reset síncrono activada en 'O' (reset_n).
Esto significa que si cuando se produce un flanco de subida de la señal del reloj, la
entrada reset_n vale 'O', entonces se resetea la máquina, es decir, pasa al estado SO.
La máquina tiene dos salidas: el estado actual de la máquina ( state) y la salida de
detección del patrón 0110 (z).

Las constantes globales, que son usadas tanto en el diseño del circuito como en
el banco de pruebas, son definidas en el package mostrado en el Código VHDL 6.9.
El Código VHDL 6.9 y 6.10 describe el comportamiento de la máquina.

439
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Obsérvese que se han definido dos bloques process: uno para generar la salida,
que es sensible al estado y a la entrada, y otro para generar el próximo estado y
resetear la máquina, que es sensible únicamente a la señal de reloj. Puesto que la
máquina tiene reset síncrono, este segundo bloque process no es sensible a la señal
de reset.

El bloque process usado para generar el próximo estado corresponde directa-


mente con el diagrama mostrado en la Figura 6.11. La señal de reset no se ha incluido
en la lista de señales a las que es sensible el bloque. Así pues, este bloque sólo es
activado cuando se produce un cambio en la señal de reloj. Es decir, la condición

if ( (reset_n = '0') and rising_edge(clk) )

sólo se comprueba cuando se produce un cambio en la señal de reloj. De esta forma,


se implementa un reset síncrono.

El bloque process usado para generar la señal de salida podría reemplazarse por
la siguiente sentencia concurrente:

z <= '1' when ( (internal_state = 83) and (x = '0') ) else '0';

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 'O' mientras la máquina permanezca en el
estado 53.

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:

ffD_salida: process (clk) is


begin
if ( rising_edge(clk) ) then
z_long <= z;
end if;
end process ffD_salida;

y haciendo que z_long sea la salida del circuito. La definición del circuito, modificada
de la forma descrita anteriormente, es mostrada en el Código VHDL 6.11.

Para mostrar el funcionamiento del circuito, puede diseñarse un pequeño banco


de pruebas que introduzca algunos vectores de test. El Código VHDL 6.12 es un
ejemplo de este tipo de banco de pruebas.

440
DISEÑO DE LÓGICA SECUENCIAL

-- Definición de las constantes globales


--Fichero: seq0110_CONST.vhd
library IEEE;
use IEEE. std_logic_1164. all;

package seq0110_CONST is
constant STATE_BITS : integer := 2; -- Nnm. bits del estado
constant SO : std_logic_vector(1 downto O) .- 11 00 11 ;
constant 81 : std_logic_vector(1 downto O) := 11 01 11 ;
constant 82 : std_logic_vector ( 1 downto O) : = 11 1O11 ;
constant 83 : std_logic_vector(1 downto O) := 11 11 11 ;
end package seq0110_CONST;

-- Máquina de M ealy detectora de la secuencia O11 O


-- Fichero: seq011 O. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work. seq0110_CONST. all;

entity seq0110 is
port ( z : out std_logic; -- Señal de salida
state : out std_logic_vector(STATE_BITS-1 downto O);
-- Estado actual
reset_n : in std_logic; -- Reset síncrono activado LOW
clk : in std_logic; -- Señal 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 O);
begin
state <= internal_state;

-- Cálculo de la salida
calculo_salida: process (internal_state, x) is
begin
if ( (internal_state = 83) and (x = '0')) then
z <= '1';
el se
z <= '0';
end if;
end process calculo_salida;

Código VHDL 6.9: Package con la codificación de los estados y diseño de la máquina de Mealy
de la Figura 6.11.

441
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Continuación del diseño de la máquina de M ealy detectora de la secuencia O11 O


-- Fi chero: seq0110.vhd

-- Cálculo del próximo estado


proximo_estado: process ( clk) is
begin
if ( (reset_n = 'O') and rising_edge( clk) ) then -- Reset síncrono
internal_state <= SO;
elsif rising_edge( clk) then -- Flanco de subida del reloj
case internal_state is
when SO =>
if ( x = ' O' ) then -- Primer bit del patrón
internal_state <= S1;
el se
internal_state <= SO;
end if;
when S1 =>
if ( x = ' 1 ' ) then -- Segundo bit del patrón
internal_state <= S2;
el se
internal_state <= S1;
end if;
when S2 =>
if ( x = ' 1 ' ) then -- Tercer bit del patrón
internal_state <= S3;
else
internal_state <= S1;
end if;
when others =>
if ( x = ' O' ) then -- Cuarto bit del patrón
internal_state <= S1;
else
internal_state <= SO;
end if;
end case;
end if;
end process proximo_estado;
end architecture seq0110;

Código VHDL 6.10: Continuación del diseño de la máquina de Mealy de la Figura 6.11.

442
DISEÑO DE LÓGICA SECUENCIAL

--Máquina de Mealy detectora de la secuencia 0110


-- Fichero: seq011 O_ffD. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work. seq0110_CONST. all;

entity seq0110 is
port ( z_long : out std_logic; -- Señal de salida
state : out std_logic_vector(STATE_BITS-1 downto O); --Estado actual
reset_n : in std_logic; -- Reset síncrono activarlo LOW
clk : in std_logic; -- Señal de reloj
x : in std_logic ) ; -- Bit de entrada
end entity seq0110;

architecture seq0110 of seq0110 is


signa} internal_state : std_logic_vector(STATE_BITS-1 downto O);
signa} z : std_logic; -- Señal de salida obtenida de circ. combinacional
begin
state <= internal_state;

-- Cálculo de la salida
z <= '1' when ( (internal_state = 83) and (x ' O' ) ) else ' O' ;
ffD_salida: process ( clk) is
begin
if ( rising_edge( clk) ) then
z_long <= z;
end if;
end process ffD_salida;

-- Cálc'ulo del prÓx'imo estado


proximo_estado: process ( clk) is
begin
end process proximo_estado;

end architecture seq0110;

Código VHDL 6.11: Diseño de la máquina de Mealy de la Figura 6.11. La salida se obtiene de
un circuito combinacional y se hace pasar por un flip-fl.op D. El bloque process para la obtención
del próximo estado es igual al mostrado en el Código VHDL 6.10

443
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas no riguroso de la máquina detectora de la secuencia 011 O


--Fichero : bpLseq0110.vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work. seq0110_CONST. all;

entity bp1_seq0110 is
constant PERIODO : time := 100 ns; -- Per-íodo reloj
end entity bp1_seq0110;

architecture bp1_seq0110 of bp1_seq0110 is


signal z_long : std_logic; -- Salida de la máquina
signal state : std_logic_vector(STATE_BITS-1 downto O); -- Estado actual
signal reset_n : std_logic; -- Reset síncrono activado LOW
signal clk : std_logic := 'O'; -- Señal de reloj
signal x : std_logic; -- Entrada a la máquina

component seq0110 is
port ( z_long : out std_logic;
state : out std_logic_vector(STATE_BITS-1 downto O);
reset_n : in std_logic;
clk : in std_logic;
x : in std_logic ) ;
end component seq0110;

begin
UUT: component seq0110 port map ( z_long, state, reset_n, clk, x );

-- Generar un pulso LO W en la entrada de r-eset


reset_n <= '1 ',
' O' after ( PERIODO/ 4 ) ,
'1 'after ( PERIODO + PERIOD0/4 );
-- Generar la señal de reloj, asumiendo que ha sido inicializada a 'O'
clk <= not clk after ( PERIOD0/2 );
-- GenemT algunos vectores de test
main : process is
begin
report "Comienza la simulación";
x <= 'O'; wait for 2*PERIODO;
x <= '1'; wait for PERIODO;
x <= '1'; wait for PERIODO;
x <= '0'; wait for PERIODO;
x <= '1 '; wait for PERIODO;
x <= '1'; wait for PERIODO;
x <= 'O'; wait for PERIODO;
x <= '1'; wait for PERIODO;
wait; -- Detiene este bloque process
end process main;
end architecture bp1_seq0110;

Código VHDL 6.12: Banco de pruebas que introduce algunos vectores de test en la máquina de
Mealy de la Figura 6.11.

444
DISEÑO DE LÓGICA SECUENCIAL

+Jbp1 _seq0 110/uut/z_long O


~~--------------~

8
+ /bp1_seq0110/uut/z
+ /bp1_seq0110/uut/state
O
00
~~~------------~' 1~--------~r 1~------------------
.illL____,OO 01 10 11 01 10 11 01 10 11 00
+ /bp1_seq01 10/uut/reset_n 1
+ /bp1_seq0110/uut/clk O
+ /bp1_seq01 10/uut/x

~~O Now 120005


1 ~ • • • • •• •• ¡, ,,' •• ~~~6~~'' •••,, ¡, • • ,, • ·~o6~~,, •,, ,, ¡, •• •, • ' 606~~ •, •• ••• r. ,, •, • ' S06~~ , , ,, , ,,,,.,, •• , 1~,0~~~ ·, •,, •• ¡, •• , ~~~ ~~ ·
1
1
,,

¿j :ilil '~ /
ro-,;-;t;!232;;-;---- ,Ñ~;;-¡;-2oQ-,;-;o~·¡·------·-·--·-----------·--·-----·--·----------·------·----·------

Figura 6.12: Resultado de la simulación del circuito detector del patrón 0110.

Ejecutando el banco de pruebas del Código VHDL 6.12 durante 1200 ns, se
obtienen las señales mostradas en la Figura 6.12. Obsérvese que la señal z vale '1'
mientras el circuito se encuentra en el estado 83 y la entrada vale 'O'. La señal z
está conectada a la entrada de un fl.ip-fl.op D, cuya salida es la señal z_long, que
mantiene su valor a '1' durante un ciclo completo de reloj.

6.6.2. Banco de pruebas

El banco de pruebas anterior da cierta información acerca del comportamiento


del circuito, pero no lo prueba de manera sistemática. El Código VHDL 6.13 y 6.14
es un banco de pruebas que testea sistemáticamente el circuito, pasando al menos
una vez por cada uno de los arcos de transición entre estados de la máquina. El
orden en el cual el banco de pruebas recorre los arcos de transición de la máquina es
mostrado en la Figura 6.13. El test se ejecuta durante 1500 ns, sin que se produzca
ningún error. En la Figura 6.14 se muestra la evolución de las señales.

Figura 6.13: Orden en que el programa de test recorre los arcos del diagrama de estado.

445
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas - Máquina detectora secuencia 011 O. Fichero: bp_seq011 O. vhd


library IEEE;
use IEEE. std_logic_1164. all;
use work. seq0110_CONST. all;

entity bp_seq0110 is
constant PERIODO : time := 100 ns; -- Periodo reloj
end entity bp_seq0110;

architecture bp_seq0110 of bp_seq0110 is


signal z_long : std_logic; -- Salida de la máquina
signal state : std_logic_vector(STATE_BITS-1 downto O); -- Estado actual
signal reset_n : std_logic; -- Reset síncrono activado LOW
signal clk : std_logic := 'O'; -- Señal de reloj
signal x : std_logic; -- Entrada a la máquina

component seq0110 is
port ( z_long : out std_logic;
state : out std_logic_vector(STATE_BITS-1 downto O);
reset_n : in std_logic;
clk : in std_logic;
x : in std_logic ) ;
end component seq0110;

-- Procedimiento para comprobar si se produce error


procedure comprueba_estado_salida
( esperado_state std_logic_vector(STATE_BITS-1 downto O);
esperado_z std_logic;
actual_state std_logic_vector(STATE_BITS-1 downto O);
actual z : std_logic;
error_count : inout integer) is
begin
-- Comprueba el estado
assert~ esperado_state = actual_state )
report "ERROR: Estado esperado (" &
std_logic' image( esperado_state( 1)) & std_logic' image( esperado_state(O)) &
"), estado actual (" &
std_logic' image(actual_state(1)) & std_logic' image(actual_state(O)) &
"), instante: 11 & time' image(now);
if ( esperado_state /= actual_state ) then
error_count := error_count + 1;
end if;
-- Comprueba salida
assert( esperado_z = actual_z )
report "ERROR: Salida esperada (" &
std_logic' image( esperado_z) &
"), salida actual (" &
std_logic' image ( actual_z) &
"), instante: 11 & time' image(now);
if ( esperado_z / = actual_z ) then
error_count := error_count + 1;
end if;
end procedure comprueba_estado_salida;

Código VHDL 6.13: Banco de pruebas de la máquina de Mealy de la Figura 6.11.

446
DISEÑO DE LÓGICA SECUENCIAL

-- Continuación del banco de pruebas. Fichero: bp_seqOiiO. vhd


begin
UUT: component seq0110 port map ( z_long, state, reset_n, clk, x );
reset_n <= '1',
'O' after ( PERIODO/ 4 ),
'1' after ( PERIODO+ PERIOD0/4 );
clk <= not clk after ( PERIOD0/2 );
-- Gener-ar vectores de test y comprobar- el res'ultado
main : process is
variable error_count : integer := O; -- Núm. errores
begin
report 11 Comienza la simulación 11 ;
x <= 'O'; wait for PERIODO; -- Comprueba reset, empieza en SO
comprueba_estado_salida(SO, 'O' ,state,z_long,error_count );
x <= '1 '; wait for PERIODO; -- Sigue en SO
comprueba_estado_salida(SO, 'O' ,state,z_long,error_count );
x <= 'O'; wait for PERIODO; -- Va a Si
comprueba_estado_salida(S1, 'O' ,state,z_long,error_count );
x <= 'O'; wait for PERIODO; -- Sigue en Si
comprueba_estado_salida(S1, 'O' ,state,z_long,error_count );
x <= '1'; wait for PERIODO; -- Va a S2
comprueba_estado_salida(S2, 'O' ,state,z_long,error _count );
x <= 'O'; wait for PERIODO; -- Va a Si
comprueba_estado_salida(S1, 'O' ,state,z_long,error _count );
x <= '1'; wait for PERIODO; -- Va a S2
comprueba_estado_salida(S2, 'O' ,state,z_long,error_count );
x <= '1'; wait for PERIODO; -- Va a S3
comprueba_estado_salida(S3, 'O' ,state,z_long,error _count );
x <= '1'; wait for PERIODO; -- Va a SO
comprueba_estado_salida(SO, 'O' ,state,z_long,error_count );
x <= 'O'; wait for PERIODO; -- Va a Si
comprueba_estado_salida(S1, 'O' ,state,z_long,error_count );
x <= '1'; wait for PERIODO; -- Va a S2
comprueba_estado_salida(S2, 'O' ,state,z_long,error_count );
x <= '1'; wait for PERIODO; -- Va a S3
comprueba_estado_salida(S3, 'O' ,state,z_long,error_count );
x <= '0'; wait for PERIOD0/4; -- Va a Si
comprueba_estado_salida(S3, '0' ,state,z_long,error_count); --Salida 'O' en S3
wait for 3*(PERIOD0/4);
comprueba_estado_salida(S1,' 1 ',state,z_long,error _count ); -- Salida 'i' en Si
wait for PERIODO; -- Sigue en Si
comprueba_estado_salida(S1, 'O' ,state,z_long,error_count );
wait for PERIODO; -- Tests finalizados
H(error_count =o) then
report 11 Simulación finalizada sin errores 11 ;
el se
report 11 ERROR: Hay 11 & integer'image(error_count) & 11 errores. 11 ;
end if;
wait; -- Detiene este bloque process
end process main;
end architecture bp_seq0110;

Código VHDL 6.14: Parte final del banco de pruebas de la máquina de Mealy.

447
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

+ /bp_seq0110/uut/z_long o ----,
+ /bp_seq0110/uut/z o
(±) + /bp_seq0110/uut/state 01 uu .00 01 10 01 10 11
+ /bp_seq0110/uut/reset_n 1 '1

1
+ tbp_seq0110/uut/clk o
+ /bp_seq0110/uut/x o 1 1 1 1 1

rrr r rrrrrlrrrrrrrrrlrrrrrrrrrlrrr1rrrrrlrrrrrrrrrlrrrrrrrrrlrrrrrrrrrlrrrrrrr1rlrrr
a'\~1$) Now 1400 ns lS 200 ns 400 ns 600 ns 800 ns

+ /bp_seq0110/uut/z_long

m. + /bp_seq0110/uut/z
+
/bp_seq0110/uut/state
tbp_seq0110/uut/reset_n
01

+ /bp_seq0110/uut/clk
+ /bp_seq0110/uut/x

1606 ns to 1442 ns

Figura 6.14: Resultado de la simulación del programa de test.

6.7. MÁQUINAS DE ESTADO FINITO SEGURAS

Una máquina de estado finito (FSM) segura es una FSM tal que en su definición
se ha considerado la posibilidad de que la máquina alcance un estado ilegal y, en tal
caso, se ha descrito cómo debe realizarse la transición a un estado legal.

En teoría, los estados ilegales son inalcanzables. Sin embargo, en la práctica la


máquina puede entrar en un estado ilegal debido a un error en el circuito. Por
ejemplo, ruido eléctrico elevado puede hacer que un bit cambie de 'O' a '1', o
viceversa. Si se alcanza un estado ilegal, el comportamiento de la FSM es indefinido
y por tanto el circuito o bien queda bloqueado en dicho estado, o bien comienza a
realizar transiciones entre estados ilegales.

Consideremos de nuevo la FSM de Moore que se diseñó en la Sección 6.5 y que


se muestra nuevamente en la Figura 6.15a. El estado 8 3 es un estado ilegal y, por
tanto, no ha sido considerado en el diseño. Si debido a un error en el circuito la
máquina entra en ese estado, queda atrapada en él.

En la Figura 6.15b se muestra la versión segura de esta FSM, en la cual se ha


incluido explícitamente en el diseño el estado ilegal 8 3 . En el diseño seguro, si la
máquina alcanza el estado 8 3 , entonces la salida es 'O' y el siguiente estado es 8 0 .
Obsérvese que resulta extraño tener un estado sin ninguna transición que conduzca
a él, pero recuérdese que este estado sólo puede alcanzarse debido a un error en el
circuito.

448
DISEÑO DE LÓGICA SECUENCIAL

1
~

@"Z¿
d o r;;0
----------· r:-::s!:;?~
~ o

a)

Figura 6.15: Definición insegura y segura de una maquina de estado finito: a) FSM insegura, ya
que si la máquina entra en el estado indefinido (83 ="11"), no puede salir de él; y b) FSM segura,
con transiciones explícitas desde los estados indefinidos a estados definidos.

En el diseño VHDL de una FSM segura, se emplea la opción others dentro


de la cláusula case con el fin de describir el comportamiento de la máquina~.en los
estados ilegales. Por ejemplo, en el caso de la máquina mostrada en la Figura 6.15, el
diseño mostrado en la Sección 6.5 debería modificarse según se muestra en el Código
VHDL 6.15 con el fin de hacerlo seguro.

Uno podría pensar que no es necesario incluir la opción others cuando el número
de estados es potencia de dos. Esto es así cuando se codifican los estados empleando el
mínimo número de bits. Sin embargo, recuérdese que también es posible codificar los
estados de modo que el registro de estado tenga un bit por cada estado del diagrama
de transiciones. Desde el punto de vista estructural, se emplearía un flip-flop D por
cada estado de la FSM. Este tipo de codificación, que se denomina one-hot encoding,
da lugar a numerosos estados ilegales. En este caso, el uso de others garantiza que
estos estados ilegales, en caso de producirse, tendrán una transición a un estado
legal.

449
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

architecture maquinaMooreSimple of maquinaMooreSimple is


signal internal_state: std_logic_vector(STATE_BITS-1 downto O);
begin
state <= internal_:state; -- Muestra el estado

-- Genera la salida
salida: process(internal_state) is
begin
case internal_state is
when SO => z <= '0';
when S1 => z <= '0';
when S2 => z <= '1';
when others => z <= 'O'; -- Salida en el estado ilegal

end case;
end process salida;

-- Genera el siguiente estado


proximo_estado: process(reset_n,clk) is
begin
if (reset_n = 'O') then -- Reset asíncrono
internal_state <= SO;
elsif rising_edge( clk) then -- En flanco subida del reloj
case internal_state is
when SO => -- Estado actual: SO
if ( x = ' 1 ' ) then
internal_state <= S1;
el se
internal_state <= S2;
end if;
when S1 => -- Estado actual: S 1
if (x = '0') then
internal_state <= S2;
end if;
when S2 => -- Estado actual: S2
if (x = '0') then
internal_state <=SO;
end if;
when others => -- Del estado ilegal va a SO
internal_state <= "00";
end case;
end if;
end process proximo_estado;

end architecture maquinaMooreSimple;

Código VHDL 6.15: Diseño de una FSM segura.

450
DISEÑO DE LÓGICA SECUENCIAL

6.8. LECTURAS RECOMENDADAS

El Capítulo 3 de (Vahid & Lysecky 2007) es una introducción didáctica al diseño


de lógica secuencial. El Capítulo 12 de (Pardo & Boluda 2004) contiene ejemplos
sencillos de diseño de circuitos secuenciales. Los Capítulos 8 y 9 de (Chu 2006)
contienen información útil y variedad de ejemplos acerca del diseño para síntesis
de circuitos secuenciales. El Capítulo 10 está dedicado por completo al diseño de
máquinas de estado finito con VHDL a partir de diagramas ASM. El Capítulo 8 de
(Pedroni 2004) es una buena referencia sobre las máquinas de estado finito y tiene
varios ejemplos interesantes descritos en VHDL.

451
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

6.9. EJERCICIOS DE AUTOCOMPROBACIÓN

Ejercicio 6.1

Diseñe usando VHDL un latch D con entrada enable activa a nivel alto y pro-
grame un banco de pruebas para comprobar su correcto funcionamiento. Emplee en
la descripción de la architecture una sentencia if.

Ejercicio 6.2

Diseñe usando VHDL un flip-flop RS disparado por el flanco de subida del reloj
y con reset asíncrono (reset_n) activado a nivel bajo. A continuación, programe un
banco de pruebas que testee de manera sistemática el funcionamiento del circuito.

Ejercicio 6.3

Diseñe usando VHDL un flip-flop D que es activado por el flanco de subida de la


señal de reloj. Además de la entrada de reloj, el fiip-fiop tiene otras cuatro señales
de entrada: D, Enable, Set y Clear. El flip-fiop tiene una única señal de salida, cuyo
valor coincide en todo momento con el valor del estado del circuito (Q).

Cuando la señal Set es puesta al valor '1', el estado del flip-fiop cambia inmedia-
tamente al valor '1 '. Por el contrario, cuando la señal Clear es puesta al valor '1 ',
el estado del flip-flop cambia inmediatamente al valor 'O'. Es decir, las señales Set y
Clear cambian de manera asíncrona el estado del fiip-flop.

Si la señal Enable vale '1 ', entonces en el flanco de subida de la señal de reloj se
asigna el valor de la entrada D al estado del fiip-fiop Q. Por el contrario, si la señal
Enable vale 'O', la carga del fiip-fiop desde la entrada D está deshabilitada.

Al realizar el diseño de este circuito, emplee una sentencia if. Una vez realizado
el diseño, programe y simule un banco de pruebas para testearlo.

Ejercicio 6.4

Realice el diseño usando VHDL de un contador síncrono ascendente módulo 4.


Es decir, la salida del circuito toma cíclicamente los valores '0', '1' , '2', '3'. Si la

452
DISEÑO DE LÓGICA SECUENCIAL

cuenta está habilitada, se obtiene un nuevo valor de la salida en cada flanco de


subida de la señal de reloj. El contador debe tener una entrada e activa a nivel alto
que permita habilitar y deshabilitar la cuenta, y una entrada reset asíncrona, que
pone la cuenta a 'O'. Describa el comportamiento del circuito en términos de una
máquina de Moore. Una vez realizado el diseño, programe un banco de pruebas que
permita testearlo.

Ejercicio 6.5

Diseñe nuevamente el contador síncrono ascendente módulo 4 descrito en el


Ejercicio 6.4 usando VHDL, pero esta vez describiendo su estructura. Emplee puertas
lógicas básicas (AND, OR y NOT) y fiip-fiops D con entrada reset asíncrona.

Ejercicio 6.6

Diseñe un generador de señales que obtenga la forma de onda mostrada en la


parte inferior de la Figura 6.16 a partir de una señal de reloj clk. Describa su
comportamiento como una máquina de estado finito. A continuación, programe un
banco de pruebas para comprobar su correcto funcionamiento.

+--------- 1 periodo

Figura 6.16: Forma de onda de entrada (reloj, en la parte superior) y de salida (en la parte
inferior de la figura) del generador de señales.

Ejercicio 6. 7

Escriba·en VHDL la architecture que describe el comportamiento de un divisor


de frecuencias por 3, con señal de reset asíncrona activa a nivel bajo. El código VHDL
de la entity del divisor de frecuencias se muestra a continuación.

453
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

entity divisor_frecuencia_3 is
port( clk3 : out std_logic;
clk, resetn: in std_logic );
end entity divisor_frecuencia_3;

La salida clk3 es una señal periódica con la misma forma de onda que la señal
clk, pero con un tercio de su frecuencia. Es decir, un periodo de la señal clk3 se
corresponde con tres periodos de la señal clk. Los cambios síncronos en la señal clk3
se producen en el flanco de la señal clk. La entrada resetn pone asíncronamente la
señal clk3 a O, manteniéndose dicho valor mientras el valor de resetn valga O.

Una vez realizado el diseño, programe y simule un banco de pruebas para tes-
tearlo.

Ejercicio 6.8

A continuación, se muestra el diseño de cuatro circuitos. La entity de todos ellos


es la siguiente.

entity ffd is
port( q out std_logic;
d, clk, rst in std_logic );
end entity ffd;

La architecture de cada uno de los circuitos se muestra a continuación (véase


Solución 1, 2, 3 y 4).

---- Solucion 1 ---- ---- Solucion 2 ----


architecture arch1 of ffd is architecture arch2 of ffd is
begin begin
process (clk, rst) process (clk)
begin begin
if (rst = '1') then if (rst = '1') then
q <= 'O'; q <= 'O';
elsif (rising_edge(clk)) then elsif (rising_edge(clk)) then
q <= d; q <= d;
end if; end if;
end process; end process;
end arch1; end arch2;

454
DISEÑO DE LÓGICA SECUENCIAL

---- Solucion 3 ---- ---- Solucion 4 ----


architecture arch3 of ffd is architecture arch4 of ffd is
begin begin
process (clk) process (clk, rst, d)
begin begin
if (rst = '1') then if (rst = '1') then
q <= 'O'; q <= 'O';
elsif (clk = '1') then elsif (clk = '1') then
q <= d; q <= d;
end if; end if;
end process; end process;
end arch3; end arch4;

Para cada circuito, explique detalladamente si tiene la funcionalidad de un flip-


flop D con señal de reset asíncrona.

Ejercicio 6.9

Escriba en VHDL la architecture que modela el comportamiento de un circuito


digital que, a partir de una señal del reloj clk, genera las tres señales mostradas en
la Figura 6.17.

En el diseño del circuito, implemente dos máquinas de estado, una que opere
exclusivamente en la transición positiva de la señal clk y otra que opere exclusiva-
mente en la transición negativa. Estas máquinas de estado generan las señales out 1
y out2. Obtenga la señal out3 mediante una AND lógica de las señales out1 y out2.

A continuación se muestra el código VHDL de la entity del circuito.

entity gen is
port( out1, out2, out3 out std_logic;
el k in std_logic );
end entity gen;

Programe asimismo un banco de pruebas para comprobar su correcto funciona-


miento.

455
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

el k
:Perio~o clk:
~:

1
1
outl 1 1

Periodo o~ t 1

1
1
1
out2 Periodo o1Jl. t 2
1

out3 1
1 Periodo o* t 3
:•
Figura 6.17: Señales generadas en el circuito correspondiente al Ejercicio 6.9.

Ejercicio 6.10

Diseñe un circuito secuencial síncrono capaz de detectar cuándo le llegan al


menos tres unos consecutivos por su entrada. La entity del circuito se muestra
a continuación. El circuito tiene una señal de reloj (clk), un entrada serie de un bit
(x), una señal de reset asíncrona activa en '1' (reset), una señal que indica el estado
en que se encuentra el circuito (state) y una señal de salida de un bit (Y). La señal
Y se pone a '1' si por la entrada X se han recibido tres o más unos consecutivos.
La señal reset pone el circuito en su estado inicial. Todos los cambios tienen lugar
en el flanco de subida de la señal de reloj. Escriba en VHDL la architecture que
describe el comportamiento del circuito en términos de una máquina de Moore.
Dibuje el diagrama de estados correspondiente al circuito que ha diseñado.

entity detector is
port( Y out std_logic;
state out std_logic_vector(1 downto O);
X in std_logic;
reset in std_logic;
clk in std_logic);
end entity detector;

456
DISEÑO DE LÓGICA SECUENCIAL

Programe asimismo el banco de pruebas del circuito secuencial que ha diseñado.


Explique detalladamente cómo el programa de test comprueba de manera sistemática
el funcionamiento del circuito. El banco de pruebas debe comprobar que los valores
obtenidos de la UUT coinciden con los esperados, mostrando el correspondiente
mensaje en caso de que no coincidan. Al final del test, debe mostrarse un mensaje
indicando el número total de errores.

Ejercicio 6.11

Realice el diseño usando VHDL de un contador síncrono BCD. Es decir, la salida


del circuito toma cíclicamente los valores "0000", "0001", "0010", "0011", "0100",
"0101", "0110", "0111", "1000" y "1001". Se obtiene un nuevo valor de la salida en
cada flanco de subida de la señal de reloj. El contador debe tener una entrada reset
asíncrona activa a nivel alto, que pone la cuenta a cero. Describa el comportamiento
del circuito en términos de una máquina de Moore.

La entity del circuito es:

entity contador is
port( count out std_logic_vector(3 downto O);
clk, reset in std_logic );
end entity contador;

Programe asimismo el banco de pruebas del circuito secuencial que ha diseñado.


Explique detalladamente cómo el programa de test comprueba de manera sistemática
el funcionamiento del circuito. El banco de pruebas debe comprobar que los valores
obtenidos de la UUT coinciden con los esperados, mostrando el correspondiente
mensaje en caso de que no coincidan. Al final del test, debe mostrarse un mensaje
indicando el número total de errores.

Ejercicio 6.12

Diseñe un circuito secuencial síncrono capaz de detectar cuando le llega la se-


cuencia "1011" por su entrada. La entity del circuito se muestra a continuación.
El circuito tiene una señal de reloj (clk), un entrada serie de un bit (x), una señal
de reset asíncrona activa en '1' (reset), una señal que indica el estado en que se
encuentra el circuito (state) y una señal de salida de un bit (Y). La señal Y se pone
a '1' si por la entrada X los últimos 4 bits que han llegado se corresponden con la
secuencia "1011". La máquina no vuelve al estado inicial tras haber reconocido la

457
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

secuencia, sino que detecta secuencias solapadas. La señal reset pone el circuito
en su estado inicial. Todos los cambios tienen lugar en el flanco de subida de la
señal de reloj. Escriba en VHDL la architecture que describe el comportamiento
del circuito en términos de una máquina de Moore. Dibuje el diagrama de estados
correspondiente al circuito que ha diseñado.

entity detector is
port( Y out std_logic;
state out std_logic_vector(2 downto O);
X in std_logic;
reset in std_logic;
clk in std_logic );
end entity detector;

Programe asimismo un banco de pruebas para el circuito secuencial. El programa


de test debe primero resetear el circuito y a continuación cargar en el circuito, a
través de la entrada (x) y por este orden, los siete bits siguientes: '1', '0', '1', '1', '0',
'1', '1 '. Si los valores de la señal de salida de la UUT no coinciden con lo esperado,
el programa de test debe mostrar el correspondiente mensaje.

Ejercicio 6.13

Diseñe usando VHDL un contador binario ascendente y descendente de 4 bits. La


entity del circuito se muestra a continuación. Las entradas al circuito son: señal de
reloj (Clock), señal de reset asíncrono activo a nivel alto (Clear), señal que habilita
la cuenta (Count) y señal para seleccionar si la cuenta es ascendente o descendente
(Down). El circuito tiene una señal de 4 bits de salida de datos (Q).

entity udcounter is
port ( Q out std_logic_vector(3 downto O);
Clock in std_logic;
Clear in std_logic;
Count in std_logic;
Down in std_logic );
end udcounter;

Mientras Clear vale 'O' y Count vale '1 ', en cada flanco de subida de la señal de
reloj el contador se incrementa o decrementa en uno. Se incrementa si Down vale 'O'
y se decrementa si Down vale '1 '.

Mientras Clear vale 'O' y Count vale 'O', el valor de la cuenta se mantiene
constante.

458
DISEÑO DE LÓGICA SECUENCIAL

El diseño debe realizarse describiendo el comportamiento del circuito, empleando


para ello un único bloque process. Utilice únicamente las librerías siguientes:

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

Programe en VHDL un banco de pruebas para el contador binario. Además,


dibuje el cronograma de evolución que han de seguir las señales de entrada y salida
de la UUT.

La señal de reloj (Clock) debe tener un periodo de 10 ns e inicialmente valer 'O'.

El programa de test debe primero resetear el contador. La señal (Clear) debe


valer '1' únicamente entre los instantes 2.5 y 7.5 ns. A continuación, el programa de
test debe incrementar el valor del contador hasta "0101". Después, ha de mantener el
valor "0101"durante un ciclo de reloj. Finalmente, debe decrementar la cuenta hasta
alcanzar el valor "000 1".

Si el valor de la señal de salida de la UUT no coincide con lo esperado, el programa


de test debe mostrar el correspondiente mensaje.

Ejercicio 6.14

Diseñe un circuito para el control de dos semáforos, semáforo 1 y 2, que regulan el


tráfico de un cruce. El controlador ha de tener las salidas mostradas en la Tabla 6.1.
Los estados del controlador y el tiempo que se ha de pasar en cada estado se muestran
en la Tabla 6.2. La señal de reloj tiene una frecuencia de 60Hz. El controlador tiene
una señal reset asíncrona que cuando está a '1' pone ambos semáforos en amarillo,
permaneciendo en ese estado mientras la señal está activa. El diagrama de estados
del controlador es el mostrado en la Figura 6.18.

Tabla 6.1: Salidas del circuito de control del cruce.

Señal Significado
r1 Pone el semáforo 1 en rojo
r2 Pone el semáforo 2 en rojo.
g1 Pone el semáforo 1 en verde.
g2 Pone el semáforo 2 en verde.
y1 Pone el semáforo 1 en amarillo.
y2 Pone el semáforo 2 en amarillo.

459
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Tabla 6.2: Estados del controlador y tiempos.

Estado Tiempo Salida


RG timeRG (30 s) r1 '1'' g2 '1'
RY timeRY (5 s) r1 '1'' y2 '1'
GR timeGR (45 s) g1 '1', r2 '1'
YR timeYR (5 s) y1 '1', r2 '1'
yy y1 '1'' y2 '1'

1
1
1
1

reseti
1

Figura 6.18: Diagrama de estados del circuito controlador de dos semáforos.

Una vez realizado el diseño del circuito controlador en VHDL, programe un banco
de pruebas para comprobar que funciona correctamente.

460
DISEÑO DE LÓGICA SECUENCIAL

Ejercicio 6.15

Diseñe usando VHDL el circuito de control de un microondas. Las entradas al


circuito se muestran en la Tabla 6.3 y las salidas en la Tabla 6.4. El sistema se
puede describir usando los estados descritos en la Tabla 6.5. El diagrama de estados
se muestra en la Figura 6.19.

Una vez realizado el diseño del circuito, programe un banco de pruebas que lo
testee.
Tabla 6.3: Entradas al circuito controlador de un microondas.

Entrada Significado
minuto Incrementa el contador de tiempo de cocc1on en 60 seg. En
cualquier momento se puede apretar este botón para aumentar
el periodo de cocción.
marcha Inicia la marcha del horno siempre que el tiempo de cocción sea
mayor que O.
stop_Reset Si el microondas se encuentra en estado de cocción, cuando esta
señal está a '1' se detiene la marcha del horno. Si se activa esta
señal cuando el horno no está en estado de cocción se resetea el
tiempo de cocción.
puerta Según su valor sea '1' ó 'O' indica si la puerta del microondas
está abierta o cerrada. Abrir la puerta en el periodo de cocción
interrumpe la cocción. Abrir la puerta cuando la alarma está
activada la desconecta.
clk Reloj de entrada con periodo de 125 ms.
reset Señal asíncrona para resetear el sistema.

Tabla 6.4: Salidas del circuito controlador de un microondas.

Salida Significado
segundos(9 ... 0) Indjr>an a una pantalla el número de segundos de cocción restantes.
La 1dificación es binaria, por lo que se pueden programar hasta
10"' seg.
calentar Cu do está a '1' el horno calienta.
luz e;,, :lo está a '1' enciende la luz interna del horno.
alarma io está a '1' suena la alarma. La alarma debe sonar cuando
E. .npo de cocción llegue a O después de que el horno ha estado
e ttando. La alarma se debe desconectar cuando se abre la
p 'ta del horno.
-------------------

461
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Tabla 6.5: Estados del circuito controlador de un microondas.

Estado Significado
PuertaAbierta Microondas parado con la puerta abierta. Las señales de salida tie-
nen los siguientes valores: calentar = O, luz = 1 y alarma = O
PuertaCerrada Microondas parado con la puerta cerrada. Las señales de salida tie-
nen los siguientes valores: calentar = O, luz = O y alarma = O
Coccion El microondas está cociendo. Las señales de salida tienen los
siguientes valores: calentar = 1, luz = 1 y alarma = O
AlarmaActivada La alarma se encuentra activa. Las señales de salida tienen los
siguientes valores: calentar = O, luz = O y alarma = 1.

reset ,

~ stop_Reset

uerta

stop_Reset Q t_alarma=O

Figura 6.19: Diagrama de estados del circuito controlador de microondas.

462
DISEÑO DE LÓGICA SECUENCIAL

6.10. SOLUCIONES DE LOS EJERCICIOS

Solución al Ejercicio 6.1

El Código VHDL 6.16 es el diseño de un latch D y el Código VHDL 6.17 es su


banco de pruebas.

-- Latch D
-- Fichero: latclL.D. vhd
Library IEEE;
use IEEE. std_logic_1164. all;
entity latch_D is port(
Q : out std_logic;
D, Enable: in std_logic);
end entity latch_D;
architecture latch_D of latch_D is
begin
process(D, Enable)
begin
if Enable = ' 1' then
Q <= D;
end if;
end process;
end architecture latch_D;

Código VHDL 6.16: Diseño de un latch D.

463
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas de un latch D. Fichero : bp_latclLD.vhd


library IEEE;
use IEEE. std_logic_1164. all;
entity bp_latch_D is
end entity bp_latch_D;
architecture bp_latch_D of bp_latch_D is
signal Q : std_logic; -- Salidas UUT
signal D, Enable : std_logic; -- Entradas UUT
component latch_D is
port ( Q : out std_logic;
D, Enable : in std_logic ) ;
end component latch_D;
-- Procedimiento para comprobar las salidas de la latch
procedure comprueba_salidas
( esperado_Q std_logic;
actual_Q : std_lo&ic;
error_count : inout integer) is
begin
if ( esperado_Q / = actual_Q ) then
report "ERROR: Estado esperado (" & std_logic' image( esperado_Q) &
"), estado actual (" & std_logic' image( actual_Q) &
"), instante: " & time' image(now);
error count := error_count + 1;
end if;
end procedure comprueba_salidas;
begin
uut : component latch_D port map (Q, D, Enable);
gen_ vec_ test : process is
variable error _count : integer := O; -- Núm. errores
begin
report "Comienza la simulación";
-- Vectores de test y comprobación del resultado
D <= '0'; Enable <= '0'; wait for 10ns; -- 10ns
Enable <= '1 '; wait for 5ns; -- 15ns
comprueba_salidas( 'O' ,Q,error_count );
D <= '1'; Enable <= '0'; wait for 10ns; -- 25ru;
Enable <= '1 '; wait for 5ns; -- 30ns
comprueba_salidas(' 1 ',Q,error_count);
Enable <= '0';
-- Informe final
if (error_ count = O) then
report "Simulación finalizada sin errores";
else
report "ERROR: Hay " & integer' image(error_count) & "errores.";
end if;
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_latch_D;

Código VHDL 6.17: Banco de pruebas dellatch D.


DISEÑO DE LÓGICA SECUENCIAL

Solución al Ejercicio 6.2

El diseño del fiip-fl.op RS y el código del banco de pruebas se muestran en Código


VHDL 6.18, 6.19 y 6.20. El diagrama de estados del fiip-fl.op se muestra en la
Figura 6.20. Los números inscritos en circunferencias indican el orden en el cual
el programa de test va recorriendo los arcos del diagrama.

___ ... --''


@reset__:~

Figura 6.20: Diagrama de estados del flip-flop RS.

--Flip-fiop RS. Fichero: fiipfiopRS.vhd


library IEEE;
use IEEE. std_logic_1164. all;

entity flipflopRS is
port ( q, notq : out std_logic;
el k, R, S, reset_n: in std_logic);
end entity flipflopRS;

architecture flipflopRS of flipflopRS is


signal q_interna: std_logic;
begin
q <= q_interna;
notq <= not q_interna;
process(reset_n, clk)
variable aux: std_logic;
begin
if (reset_n = 'O') then
aux := '0';
elsif (rising_edge( clk)) then
if (R='1' and S='O') then
aux := '0';
elsif (R= 'O' and S=' 1 ') then
aux:='1';
end if;
end if;
q_interna <= aux;
end process;
end architecture flipflopRS;

Código VHDL 6.18: Diseño de un fiip-fl.op RS.

BERGARA
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del flip-flop RS (fichero bp_flipflopRS. vhd)


library IEEE;
use IEEE. std_logic_1164. all;

entity bp_flipflopRS is
end entity bp_flipflopRS;

architecture bp_flipflopRS of bp_flipflopRS is


constant PERIODO : time := 100 ns; -- Reloj
signal q, notq : std_logic; -- Salidas UUT
signal clk : std_logic := 'O'; -- Entradas UUT
signal R, S, reset_n : std_logic;
component flipflopRS is
port ( q, notq : out std_logic;
clk, R, S, reset_n : in std_logic );
end component flipflopRS;

-- Procedimiento para compmbar las salidas del flip-flop


procedure comprueba_salidas
( esperado_q : std_logic;
actual_q, actual_q_n : std_logic;
error _count : inout integer) is
begin
-- Comprueba q
if ( esperado_q /= actual_q ) then
report "ERROR: Estado esperado (" & 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 flipflopRS port map (q, notq, clk, R, S, reset_n);

reset_n <= '1 ',


'O' after (PERIODO/ 4),
'1' after (PERIODO+PERIOD0/4);

clk <= not clk after (PERIOD0/2);

Código VHDL 6.19: Parte inicial del banco de pruebas de un fiip-fiop RS.

466
DISEÑO DE LÓGICA SECUENCIAL

-- Continuación de l banco de pruebas de l flip flap RS (fichero bp_flipflopRS. vhd)

gen_ ve e_ test : process is


variable error _count : integer := O; -- Num. errores
begin
report "Comienza la simulacion";

-- Vectores de test y comprobacion del resultado


S <= '0' ; R <= '0'; wait for PERIODO; -- 1
comprueba_salidas( 'O' ,q,notq,error _count ) ;
S <= '0'; R <= '1'; wait for PERIODO;-- 2
comprueba_salidas( 'O' ,q,notq,error _count );
S <= '1'; R <= '0'; wait for PERIODO;-- 3
comprueba_salidas(' 1' ,q,notq,error _count );
S <= '0'; R <= '0'; wait for PERIODO;-- 4
comprueba_salidas(' 1' ,q,notq,error_count);
S <= '1 ' ; R <= 'O ' ; wait for PERIODO ; -- 5
comprueba_salidas(' 1 ',q,notq,error_count);
S <= 'O'; R <= '1'; wait for PERIODO; -- 6
comprueba_salidas( 'O' ,q,notq,error_count);

-- Informe fina l
if (error_count = o) then
report "Simulación finalizada sin errores";
else
report "ERROR: Hay " & integer' image (error_ count) & 11
errores. 11
;

end if;
wait; -- Final del bloque process
end process gen_vec_test;

end architecture bp_flipflopRS;

Código VHDL 6.20: P arte final del banco de pruebas de un flip-flop RS .

467
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 6.3

El Código VHDL 6.21 y 6.22 es el diseño del fiip-flop D y su banco de pruebas.


El banco de pruebas no testea el fiip-fiop de manera exhaustiva, ya que sólo recorre
alguno de los arcos del diagrama de transición de estados, según se muestra en la
Figura 6.21. En cada arco de transición se muestran 4 bits. Los valores de izquierda
a derecha de estos 4 bits se corresponden, respectivamente, con los valores que han
de tomar las señales Set , Clear, Enable y D para que se produzca dicha transición.
El valor '-' ( don't care) indica que se produce la transición con independencia del
valor de ese bit de la señal.

1---
0)0011

Figura 6.21: Diagrama de transición de un flip-flop D y orden del test.

-- Flip fiop D con entradas Enable, set and clear. Fichero: FFD_Enable_SeLClear.vhd
library IEEE;
use IEEE. std_logic_1164. all;

entity FFD is
port(Q : out std_logic;
Clock, Enable, Set, Clear, D : in std_logic);
end entity FFD;
architecture FFD of FFD is
begin
process(Clock, Set, Clear)
begin
if Set = ' 1 ' then
Q <= '1';
elsif Clear = ' 1' then
Q<='O';
elsif (rising_edge(Clock)) then
if (Enable =' 1') then
Q <= D;
end if;
end if;
end process;
end architecture FFD;

Código VHDL 6.21: Diseño de un flip-flop D con señales enable, set y clear.

468
DISEÑO DE LÓGICA SECUENCIAL

-- Banco de pruebas del fiip-.fiop D. Fichero: bp_FFD_Enable.._SeLClear.vhd


library IEEE;
use IEEE. std_logic_1164. all;

entity bp_FFD is
end entity bp_FFD;

architecture bp_FFD of bp_FFD is


constant PERIODO :time := 100 ns; -- R eloj
signal Q : std_logic; -- Salidas UUT
signal Clock : std_logic := 'O'; -- Entradas UUT
signal Enable, Set, Clear, D : std_logic;

component FFD is
port ( Q : out std_logic;
Clock, Enable, Set, Clear, D : in std_logic );
end component FFD;
-- Procedimiento para comprobar las salidas del fiip-fiop
procedure comprueba_salidas
( esperado_q std_logic;
actual_q std_logic;
error_count : inout integer) is
begin
-- Comprueba q
if ( esperado_q /= actual_q ) then
report "ERROR: Estado esperado (" & std_logic'image(esperado_q) &
"),estado actual (" & st<Llogic'image(actual_q) &
"),instante:" & time'image(now);
error count := error_count + 1;
end if;
end procedure comprueba_salidas;
begin
uut : component FFD port map ( Q, Clock, Enable, Set, Clear, D );
Clock <= not Clock after (PERIOD0/2);
gen_vec_test : process is
variable error _count : integer := O; -- Núm. errores
begin
report "Comienza la simulación";
-- Vectores de test y comprobación del resultado
Set <= '1'; Clear <= '0'; Enable <= '0'; D<='1'; --1
wait for PERIODO; comprueba_salidas(' 1', Q, error_count);
Set <= '0'; Clear <= '0'; Enable <= '1'; D<='O'; --2
wait for PERIODO; comprueba_salidas('O', Q, error_count);
Set <= '0'; Clear <= '0'; Enable <= '0'; D<='1'; --3
wait for PERIODO; comprueba_salidas('O', Q, error_count);
Set <= '0'; Clear <= '0'; Enable <= '1'; D<='1'; --4
wait for PERIODO; comprueba_salidas(' 1 ', Q, error_count);
Set <= 'O'; Clear <= '1'; Enable <= '1'; D<=' 1 '; --5
wait for PERIODO; comprueba_salidas( 'O', Q, error _count );
report "Num. errores: Hay " & integer'image(error_count) & " errores.";
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_FFD;

Código VHDL 6.22: Banco de pruebas de un flip-flop D.

469
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 6.4

El Código VHD L 6. 23 es un package en el cual se han definido las constantes


empleadas en el diseño: el número de bits del estado y la codificación de los estados.
El diseño del contador módulo 4 es el Código VHDL 6.24. El banco de pruebas es
el Código VHDL 6.25 y 6.26. En el diagrama de transición de estados del circuito,
que se muestra en la Figura 6.22, se ha señalado el orden en el cual el programa de
test recorre los arcos.

Figura 6.22: Diagrama de transición de estados de un contador ascendente módulo 4. En el


diagrama se ha señalado el orden en el cual el programa de test recorre los arcos.

-- Paquete con la definición de las constantes globales


--Fichero: STATE_CONSTANTS.vhd
library IEEE;
use IEEE. std_logic_1164. all;
package STATE_CONSTANTS is
constant STATE_BITS: integer := 2; -- Bits codifican estado
constant SO: std_logic_vector(1 downto O) := 11 00 11 ; --Estados
constant S1: std_logic_vector ( 1 downto O) : = 11 O1 11 ;
constant S2: std_logic_vector(1 downto O) := 11 10 11 ;
constant S3: std_logic_vector ( 1 downto O) : = 11 11 11 ;
end package;

Código VHDL 6.23: Package en el cual se definen las constantes del diseño del contador
ascendente módulo 4.

470
DISEÑO DE LÓGICA SECUENCIAL

-- Contador- módulo 4 implementado corno máq'u,'i na de Moore


-- Fich ero: contador_Mod_4. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work.STATE_CONSTANTS.all;

entity contador _Mod_ 4 is


port(state : out std_logic_vector(STATE_BITS-1 downto O);
clock, reset, e : in std_logic);
end entity contador _Mod_ 4;

architecture contador _Mod_ 4 of contador _Mod_ 4 is


signal internal_state: std_logic_vector(STATE_BITS-1 downto O);
begin
state <= internal_state;
proximo_estado: process ( clock, reset) --Cálc,u,lo del próximo estado
begin
if (reset = '1') then
internal_state <= SO;
elsif (rising_edge( clock)) then
case internal_state is
when SO =>
if e = ' 1 ' then
internal_state <= S1;
else
internal_state <= SO;
end if;
when S1 =>
if e = ' 1 ' then
internal_state <= S2;
else
internal_state <= S1;
end if;
when S2 =>
if e = ' 1 ' then
internal_state <= S3;
else
internal_state <= S2;
end if;
when S3 =>
if e = ' 1 ' then
internal_state <= SO;
el se
internal_state <= S3;
end if;
when others=>
internal_state <= SO;
end case;
end if;
end process proximo_estado;

end architecture contador _Mod_ 4;

Código VHDL 6.24: Diseño de un contador ascendente módulo 4.

471
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pTuebas del contadoT ascendente sincmno mod·ulo 4


-- FicheTo: bp_contadoT_MorL4.vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work. STATE_CONSTANTS. all;

entity bp_contador _Mod_ 4 is


end entity bp_contador_Mod_4;

architecture bp_contador_Mod_4 of bp_contador_Mod_4 is


constant PERIODO : time := 100 ns; -- Reloj
signal q : std_logic_vector(STATE_BITS-1 downto 0);-- Salidas UUT
signal clk : std_logic := 'O'; -- EntTadas UUT
signal reset, e : std_logic;

component contador _Mod_ 4 is


port ( state : out std_logic_vector(STATE_BITS-1 downto O);
clock, reset, e : in std_logic );
end component contador _Mod_ 4;

-- Pmcedimiento paTa compTobaT las salidas


procedure comprueba_salidas
( esperado_q std_logic_vector(STATE_BITS-1 downto O);
actual_q std_logic_vector ( ST ATE_B ITS-1 downto O);
error_count : inout integer) is
begin
-- CompTueba q
if ( esperado_q / = actual_q ) then
report "ERROR: Estado esperado (" &
std_logic' image (esperado_ q ( 1)) &
std_logic' image( esperado_q(O)) &
"), estado actual (" &
std_logic' image( actual_q( 1)) &
std_logic' image(actual_q(O)) &
"), instante: " &
time' image(now);
error count := error_count + 1;
end if;
end procedure comprueba_salidas;

begin
-- InstanciaT y conectaT UUT
uut : component contador _Mod_ 4 port map (q, clk, reset, e);

reset <= '0', '1' after (PERIOD0/4),


'0' after (PERIODO+PERIOD0/4);

clk <= not clk after (PERIOD0/2);

Código VHDL 6.25: Parte inicial del banco de pruebas del contador ascendente módulo 4.

472
DISEÑO DE LÓGICA SECUENCIAL

-- Continuación del banco de pruebas del contadoT ascendente síncrono modulo 4


-- Fichero: bp_contador-_MorL4.vhd

gen_vec_test : process ~
variable error _count : integer := O; -- Núm. errores
begin
report 11 eomienza la simulación 11 ;

-- VectoTes de test y comprobación del resultado


e <= 'O'; wait for PERIODO; -- 1
comprueba_salidas(SO, q, error_count);
e <= '1'; wait for PERIODO; -- 2
comprueba_salidas(S1, q, error_count);
e <= 'O'; wait for PERIODO; -- 3
comprueba_salidas(S1,q, error_count);
e <= '1'; wait for PERIODO; -- 4
comprueba_salidas(S2, q, error_count);
e <= 'O'; wait for PERIODO; -- 5
comprueba_salidas(S2 ,q, error_count);
e <= '1'; wait for PERIODO; -- 6
comprueba_salidas(S3, q, error_count);
e <= 'O'; wait for PERIODO; -- 7
comprueba_salidas(S3, q, error_count);
e <= '1'; wait for PERIODO; -- 8
comprueba_salidas(SO, q, error_count);

-- Informe final
if (error_count =o) then
report 11 Simulación finalizada sin errores 11 ;
else
report 11 ERROR: Hay 11 &
integer'image(error_count ) &
11
errores. 11 ;
end if;
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_contador _Mod_ 4;

Código VHDL 6.26: Parte final del banco de pruebas del contador ascendente módulo 4.

473
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 6.5

La tabla de transición de estados y salidas del contador se muestran en la


Tabla 6.6. Las funciones lógicas simplificadas que relacionan el próximo estado (Dl,
DO) y la salida (State(l : 0)), con el estado actual (Ql, QO) y la entrada (e) son las
siguientes:

Dl e Ql + Ql QO +e Ql QO
DO e QO +e QO
State(l) Ql
State(O) Q

En el diseño del contador se han empleado puertas lógicas básicas (AND, ORe
inversor) y 2 fiip-fiops D (uno por cada variable de estado). Los fiip-flops D usados
son activos en el flanco de subida de la señal del reloj y tienen una entrada reset
asíncrona activa a nivel bajo.

Tabla 6.6: Tabla de transición de estados del contador ascendente módulo 4.

Estado actual Entrada Próximo estado Salida


Ql QO e DI DO State(l : O)
o o o o o o o
o o 1 o 1 o o
o 1 o o 1 o 1
o 1 1 1 o o 1
1 o o 1 o 1 o
1 o 1 1 1 1 o
1 1 o 1 1 1 1
1 1 1 o o 1 1

El Código VHDL 6.27 es el diseño correspondiente al circuito mostrado en la


Figura 6.23, que describe estructuralmente las anteriores funciones lógicas. Se ha
empleado en este diseño el package mostrado en Código VHDL 6.23.

Puede emplearse el banco de pruebas mostrado en Código VHDL 6.25-6.26 para


testear esta descripción del circuito.

474
DISEÑO DE LÓGICA SECUENCIAL

Q1
not_1
Q1_n : ·:······~-- ····+-¡- - - - - - - - - - - - ,
~ ............... . . .i
e QO
...r ,·¿··¡ QO_n : .......1-
...¡ ! - - - - - - - - - - - - ,

;~':l~cc-\ yand ~ñOC~


1
g ¡__< ¡ ~---1-f--f--+-i!-,----.,1\ ; -
t.........................J
and 2 or 1
;·······= .. .......; ;............ .......; state(1)
1-f---+--+--!-!"'-f"'"'"""""""'"! ~ y?r_1 ¡ D QH¡_Q_1_+--I-__..._...~:¡-:::-::::-: : - 1: ~c: : : : :=>: : : :
~.....Jyand_2 ~ ................... ! i~LRN i
and_3 L. ..~... .!
.
:-···=~ ····¡ yand_3 1

,--¡¡-t:::j~::t:::t:~. :r. . .-..,


...... ; r- _r··~. · ~·H···¡_a_o___.....,__....___+-'~-..!~_. .~._~.(r. 9--">
. L.
and_4 yor_2 ~+> ;. . . . . . . .
hd...
l CLAN

c_n '-----+--+J_,'LJ.iyan~=~ ()~"'f :..:::<:::... ,

'--c-lo_c_k-------t~---!""""iC~~~~ yan1~¡--- ¡
:::º:::::::::::::::: not_3
reset :·········.:··¡ reset_n
::::º:::::::::::::::: !. ... ~ ......... !
Figura 6.23: Contador módulo 4 compuesto por flip-flops D y puertas lógicas.

475
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

---Contador módulo 4 según estructura. Fichero: contador_MocL4_estruct.vhd


library IEEE;
use IEEE.std_logic_1164.all;
use work. STATE_CONSTANTS . all;

entity contador _Mod_ 4 is


port(state : out std_logic_vector(STATE_BITS-1 downto O);
clock, reset, e : in std_logic);
end entity contador _Mod_ 4;

architecture contador_Mod_4 of contador_Mod_4 is


signal Q1_n, QO_n, Q1, QO : std_logic;
signal reset_n, c_n : std_logic;
signal yand_1, yand_2, yand_3, yand_4, yand_5 : std_logic;
signal yor _1, yor _2 : std_logic;

component flipflop_D is port


( q : out std_logic;
d, clk, reset_n : in std_logic);
end component flipflop_D;
component and3 is port
( yO : out std_logic;
xO, x1, x2 : in std_logic );
end component and3;
component or3 is port
( yO : out std_logic;
xO, x1, x2 : in std_logic );
end component or3;
component and2 is port
( yO : out std_logic;
xO, x1 : in std_logic );
end component and2;
component or2 is port
( yO : out std_logic;
xO, x1 : in std_logic );
end component or2;
component not 1 is port
( yO : out std_logic;
xO : in std_logic ) ;
end component not1;

begin
state(1) <= Q1;
state(O) <= QO;
not_1: not1 port map (Q1_n, Q1);
not_2: not1 port map (QO_n, QO);
not_3: not1 port map (reset_n, reset);
not_4: not1 port map (c_n, e);
and_1: and2 port map (yand_1, c_n, Q1);
and_2: and2 port map (yand_2, Q1, QO_n);
and_3: and3 port map (yand_3, e, Q1_n, QO);
or_1: or3 port map (yor_1, yand_1, yand_2, yand_3);
and_ 4: and2 port map (yand_ 4, c_n, QO);
and_5 : and2 port map (yand_5, e, QO_n);
or_2: or2 port map (yor_2, yand_4, yand_5);
D1 flipflop_D port map (Q1, yor_1, clock, reset_n);
D2 flipflop_D port map (QO, yor_2, clock, reset_n);

end architecture contador _Mod_ 4;

Código VHDL 6.27: Diseño estructural del contador ascendente módulo 4.

476
DISEÑO DE LÓGICA SECUENCIAL

Solución al Ejercicio 6.6

El Código VHDL 6.28 es el diseño del generador de señal. Obsérvese que el valor
de la señal de salida wave se asigna en el flanco de subida de la señal de reloj.
Esto supone que al sintetizar el circuito se inferirá un flip-flop, cuya finalidad será
almacenar el valor de esta señal. No resultaría adecuado que la salida del generador
de señales fuera directamente la salida de un circuito combinacional, ya que no deben
producirse glitches en la salida de un generador de señales.

-- Paquete con la definición de las constantes globales. Fichero: STATE_CONST.vhd


library IEEE;
use IEEE. std_logic_1164. all;
package STATE_CONST is
constant STATE_BITS: integer := 3; -- Bits codifican estado
constant SO: std_logic_vector(2 downto o) := 11 000 11 ; --Estados
constant S1: std_logic_vector ( 2 downto O) : = 11 00 1 11 ;
constant S2: std_logic_vector(2 downto O) := 11 010 11 ;
constant S3: std_logic_vector ( 2 downto O) : = 11 O11 11 ;
constant S4: std_logic_vector(2 downto O) := 11 100 11 ;
constant S5: std_logic_vector(2 downto O) .- 11 101 11 ;
constant S6: std_logic_vector(2 downto O) .- 11 110 11 ;
constant S7: std_logic_vector ( 2 downto O) . - 11 111 11 ;
end package;

---Generador de señal implementado como máquina de estados. Fichero: generadorOnda. vhd


library IEEE;
use IEEE. std_logic_1164. all;
use work. STATE_CONST. all;

entity generador is
port(wave : out std_logic;
clk : in std_logic);
end entity generador;

architecture fsm of generador is


signal state : std_logic_vector(STATE_BITS-1 downto O);
begin
--Cálculo del próximo estado
proximo_estado: process (clk)
begin
if (rising_edge( clk)) then
case state is
when SO => state <= S1; wave <= 'O';
when S1 => state <= S2; wave <= '1';
when S2 => state <= S3; wave <= 'O';
when S3 = > state <= S4; wave <= '1';
when S4 = > state <= S5; wave <= '1';
when S5 => state <= S6; wave <= '1';
when S6 = > state <= S7; wave <= 'O';
when others = > state <= SO; wave <= 'O';
end case;
end if;
end process proximo_estado;
end architecture f sm;

Código VHDL 6.28: Diseño del generador de señal.

477
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

El banco de pruebas del generador de señal es el Código VHDL 6.29. Debe


comprobarse el correcto funcionamiento del circuito inspeccionando visualmente el
resultado de la simulación del banco de pruebas.

-- Banco de pruebas del generador de señal


-- Fichero: bp_gen eradorOnda. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work.STATE_CONST.all;

entity bp_generador is
end entity bp_generador;

architecture bp_generador of bp_generador is


constant PERIODO : time := 100 ns; -- Reloj
signal wave : std_logic; -- Salida UUT
signal clk : std_logic := 'O'; -- Entrada UUT

component generador is
port ( wave : out std_logic;
clk : in std_logic);
end component generador;

begin
-- Instanciar y conectar UUT
uut : component generador port map (wave, clk);

clk <= not clk after (PERIOD0/2);


end architecture bp_generador;

Código VHDL 6.29: Banco de pruebas del circuito generador de señal.

478
DISEÑO DE LÓGICA SECUENCIAL

Solución al Ejercicio 6. 7

Un posible diseño del divisor de frecuencias por 3 se muestra en el Código


VHDL 6.30. En este código existen dos bloques process, uno de ellos es sensible a
los flancos de subida de la señal de reloj y a la señal resetn, mientras que el otro
bloque es sensible a los flancos de bajada de la señal de reloj y a la señal resetn.

En el primero de estos bloques se genera una señal, llamada rise, y en el segundo


una señal denominada f al l. Estas dos señales tienen un sexto de la frecuencia de la
señal clk y un cierto desfase entre ambas, de modo que en el semiperiodo en que la
señal rise tiene valor '1' la señal fall tiene valor 'O' la mitad del tiempo y después
pasa a tener valor '1 '.

La señal clk3 se genera haciendo la operación lógica XNOR de las señales rise
y fall.

En el Código VHDL 6.31 se muestra un banco de pruebas para el circuito.


Simulando este banco de pruebas, se puede comprobar visualmente que la evolución
de las señales es la esperada.

479
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

--Divisor de frecuencias por 3


library IEEE;
use IEEE. STD_LOGIC_1164. ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE. STD_LOGIC_UNSIGNED. ALL;
entity di visor _frecuencia_3 is
port (
clk3 : out std_logic;
clk, resetn : in std_logic );
end divisor_frecuencia_3;
architecture di visor _frecuencia_3 of di visor frecuencia_3 is
signal rise,fall: std_logic;
begin
process( clk,resetn) --Calculo señal fall
variable r_cnt : integer range O to 2;-- Variable contadora
begin
if resetn = 'O' then
r_cnt := O;
rise <= '0';
elsif rising_edge( clk) then
if r_cnt = 2 then
r_cnt :=O;
rise <= not rise;
else
r _cnt := r _cnt + 1;
end if;
end if;
end process;
process( clk, resetn) --Calculo señal rise
variable f_cnt : integer range O to 2;-- Variable contadora
begin
if resetn = 'O' then
f_cnt := 2;
fall <= '1';
elsif falling_edge( clk) then
if f_cnt = 2 then
f_cnt := O;
fall <= not fall;
else
f_cnt := f_cnt + 1;
end if;
end if;
end process;
clk3 <= fall xnor rise;
end divisor_frecuencia_3;

Código VHDL 6.30: Diseño del divisor de frecuencias por 3.

480
DISEÑO DE LÓGICA SECUENCIAL

--Divisor de frecuencias por 3


library IEEE;
use IEEE. std_logic_1164 . all;
use IEEE. numeric_std. all;

entity di visor _frecuencia_3 is port(


clk3 : out std_logic;
clk, resetn : in std_logic );
end entity di visor _frecuencia_3;

architecture di visor _frecuencia_3 of di visor _frecuencia_3 is


signal countr: std_logic_vector (1 downto 0):= 11 00 11 ;
signal countf: std_logic_vector (1 downto 0):= 11 00 11 ;
begin
process(clk, resetn)
begin
if resetn = 'O' then
countr < = (others = > '0');
countf < = (others = > '0');
elsif (rising_edge(clk)) then
if countr < 11 10 11 then
countr < = std_logic_vector( unsigned( coun~r) + 1);
else
countr < = (others = > '0') ;
end if;
els if ( f all ing_ edge (e lk)) then
1f countf < 11 10 11 then
countf < = std_logic_vector(unsigned( countf) + 1);
else
countf < = (others = > '0');
end if;
end if;
end process;
clk3 < = countr(1) or countf(1);
end;

Código VHDL 6.31 : Banco de pruebas del divisor de frecuencias p or 3.

48 1
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 6.8

De todos los circuitos, el único que tiene la funcionalidad de un flip-flop D con


señal reset asíncrona es el circuito Solución l.

El circuito Solución 2 se corresponde con un flip-fl.op D con señal reset síncrona.


Para que dicho circuito se comportase como un fl.ip-fl.op D con señal reset asíncrona,
la lista sensible de su bloque process tendría que incluir la señal rst.

Los diseños Solución 3 y Solución 4 no describen el comportamiento de un fl.ip-


flop D, ya que el estado de estos dos circuitos no cambia ni en el flanco de subida,
ni en el flanco de bajada, de la señal de reloj. En particular, el circuito Solución 4
describe la funcionalidad de un latch D con señal de reset asíncrona.

482
DISEÑO DE LÓGICA SECUENCIAL

Solución al Ejercicio 6.9

Un posible diseño del circuito especificado se muestra en el Código VHDL 6.32-


6.33. En el Código VHDL 6.34 se muestra un banco de pruebas que permite inspec-
cionar visualmente que el correcto funcionamiento del circuito diseñado.

-- Circuito generador de señales


-- Pregunta 4
library IEEE; use IEEE.std_logic_1164.all;
entity gen is port(
out1, out2, out3 : out std_logic;
clk : in std_logic );
end entity gen;
architecture gen of gen is
type state is (one, two, three);
signal internal_state1: state;
signal internal_state2: state;
signal temp_out1, temp_out2: std_logic;
begin
------Maquina de estados 1
proximo_estado1:process(clk)
begin
if (rising_edge( clk)) then
case internal_state1 is
when one = >
internal_state1 < = two;
when two = >
internal_state1 < = three;
when three = >
internal_state1 < = one;
end case;
end if;
end process proximo_estado1;
salida1: process ( internal_state1)
begin
case internal_state1 is
when one = >
temp_out1 < = '1';
when two = >
temp_out1 < = '0';
when three = >
temp_out1 < = '1';
end case;
end process salida1;

Código VHDL 6.32: Fragmento inicial del diseño del circuito especificado en el Ejercicio 6.9.

483
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

--------Maquina de estados 2
proximo_estado2:process (clk)
begin
if (falling_edge( clk)) then
case internal_state2 is
when one =>
internal_state2 <= two;
when two =>
internal_state2 <= three;
when three =>
internal_state2 <= one;
end case;
end if;
end process proximo_estado2;
salida2:process (internal_state2)
begin
case internal_state2 is
when one =>
temp_out2 <= '1';
when two =>
temp_out2 <= '1';
when three =>
temp_out2 <= 'O';
end case;
end process salida2;
out1 <= temp_out1;
out2 <= temp_out2;
out3 <= temp_out 1 and temp_out2;
end gen;

Código VHDL 6.33: Fragmento final del diseño del circuito especificado en el Ejercicio 6.9.

--Banco de pruebas del circuito4


--generador de frecuencias
library IEEE;
use IEEE. std_logic_1164. all;

entity bp_circui to4 is


end entity bp_circui to4;

architecture bp_circui to4 of bp_circui to4 is


constant PERIODO : time := 100 ns; --Reloj
signal clk : std_logic .- 'O'; -- Entmdas UUT
signa} out1, out2, out3 : std_logic;

component gen is port(


out1, out2, out3 : out std_logic;
clk : in std_logic );
end component gen;

begin
-- Instanciar y conectar UUT
uut : component gen port map
( out1, out2, out3, clk);

clk <= not clk after (PERIOD0/2);


end architecture bp_circui to4;

Código VHDL 6.34: Banco de pruebas del diseño del circuito especificado en el Ejercicio 6.9.

484
DISEÑO DE LÓGICA SECUENCIAL

Solución al Ejercicio 6.10

En la Figura 6.24 se muestra el diagrama de estados del circuito implementado


como una máquina de Moore.

Figura 6.24: Diagrama de estados del circuito detector de una secuencia 3 unos o más consecutivos.

El código VHDL que describe el comportamiento del circuito en términos de una


máquina de Moore se muestra en el Código VHDL 6.35.

El banco de pruebas del detector de secuencias se muestra en el Código VHDL 6.36


y 6.37. Este banco de pruebas comprueba todas las transiciones de estados del
circuito en el orden indicado en la Figura 6.25.

Figura 6.25: Orden en que el programa de test recorre los arcos del circuito detector de una
secuencia 3 unos o más consecutivos.

485
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

---Detector de 3 o mas unos consecutivos

library IEEE;
use IEEE. std_logic_1164.all;

entity detector is
port ( Y : out std_logic;
state : out std_logic_vector(1 downto O);
X : in std_logic;
reset : in std_logic;
clk : in std_logic);
end entity detector;

architecture detector of detector is


signal internal_state: std_logic_vector(1 downto O);
begin
state < = internal_state;

--Cálculo salida
salida: process ( internal_state) is
begin
case internal_state is
when 11 00 11 = > Y <= '0';
when 11 01 11 =>Y <= '0';
when 11 10 11 = > Y < = '0';
when others = > Y <= '1 ';
end case;
end process salida;
--Calculo del proximo estado
proximo_estado: process (clk, reset)
begin
if (reset = '1 ') then --reset asíncrono
internal_state <= 11 00 11 ;
elsif (rising_edge( clk)) then
case internal_state is
when 11 00 11 = > -- Estado actual: 00
if X = ' 1 ' then
internal_state <= 11 01 11 ;
el se
internal_state < = 11 00 11 ;
end if;
when 11 01 11 = > --Estado actual: 01
if X = ' 1 ' then
internal_state < = 11 10 11 ;
el se
internal_state < = 11 00 11 ;
end if;
when 11 10 11 = > --Estado actual: 10
if X = ' 1 ' then
internal_state <= 11 11 11 ;
el se
internal_state < = 11 00 11 ;
end if;
when 11 11" = > -- Estado actual: 11
if X = ' 1 ' then
internal_state < = 11 11 11 ;
el se
internal_state < = 11 00 11 ;
end if;
when others= > -- Por completitud
internal_state < = 11 00 11 ;
end case;
end if;
end process proximo_estado;
end architecture detector;

Código VHDL 6.35: Diseño del detector de una secuencia 3 unos o más consecutivos.

486
DISEÑO DE LÓGICA SECUENCIAL

-- Banco de pruebas del detector de 3 unos consecutivos


library IEEE;
use IEEE. std_logic_1164. all;

entity bp_detector is
end entity bp_detector;

architecture bp_detector of bp_detector is


constant PERIODO : time := 100 ns; -- Reloj
signal state : std_logic_vector( 1 downto O);-- Salidas UUT
signal Y : std_logic;
signal clk : std_logic := 'O'; -- Entradas UUT
signal reset, X : std_logic;

component detector is
port ( Y : out std_logic;
state : out std_logic_vector( 1 downto O);
X : in std_logic;
reset : in stcLlogict
clk : in std_logic);
end component detector;

-- Procedimiento para comprobar las salidas


procedure comprueba_salidas
( esperado_state std_logic_vector(1 downto O);
actual_state std_logic_vector(1 downto O);
esperado_ Y stcLlogic;
actual_ Y std_logic;
error count inout integer) is
begin
-- Comprueba state
if ( esperado_state /= actual_state ) then
report "ERROR: Estado esperado (" &
std_logic' image( esperado_state(1)) &
std_logic' image( esperado_state(O)) &
"), estado actual (" &
std_logic' image ( actual_state ( 1)) &
std_logic' image ( actual_state (O)) &
"), instante: " &
time' image ( now);
error_count := error_count + 1;
end if; -- Comprueba Y
if ( esperado_Y /= actual_Y ) then
report "ERROR: Salida Y esperada (" &
std_logic' image( esperado_ Y) &
"), salida actual (" &
std_logic' image (actual_ Y) &
"), instante: " &
time ' image ( now);
error count := error_count + 1;
end if;
end procedure comprueba_salidas;

Código VHDL 6.36: Diseño del banco de pruebas del detector de una secuencia 3 unos o más
consecutivos.

487
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

begin
-- Instanciar y conectar UUT
uut : component detector port map
(Y, state, X, reset, clk);

reset <= 'O', '1' after (PERIOD0/4),


'0' after (PERIODO+PERIOD0/4);
clk <= not clk after (PERIOD0/2);
gen_ ve e_ test : process is
variable error_count : integer := O; --Núm. errores
begin
report 11 Comienza la simulación 11 ;
-- Vectores de t est y comprobación del resultado
X <= 'O'; wait for PERIODO; -- 1
comprueba_salidas( 11 00 11 , state, 'O', Y, error_count );
X <= '1 '; wait for PERIODO; -- 2
comprueba_salidas( 11 01 11 , state, '0', Y, error_count);
X <= '1 '; wait for PERIODO; -- 3
comprueba_salidas( 11 10 11 , state, 'O', Y, error_count );
X <= '1'; wait for PERIODO; -- 4
comprueba_salidas( 11 11 11 , state, '1', Y, error_count );
X <= '1'; wait for PERIODO; -- 5
comprueba_salidas( 11 11 11 ,state, '1', Y, error_count);
X <= 'O'; wait for PERIODO; -- 6
comprueba_salidas( 11 00 11 , state, 'O', Y, error _count );
X <= '1'; wait for PERIODO; -- 7
comprueba_salidas( 11 01 11 , state, 'O', Y, error_count );
X <= 'O'; wait for PERIODO; -- 8
comprueba_salidas( 11 00 11 , state, '0', Y, error_count);
X <= '1 '; wait for PERIODO; -- 9
comprueba_salidas( 11 01 11 , state, '0', Y, error_count);
X <= '1 '; wait for PERIODO; -- 10
comprueba_salidas( 11 10 11 , state, '0', Y, error_count);
X <= 'O'; wait for PERIODO; -- 11
comprueba_salidas( 11 00 11 , state, 'O', Y, error _count );
-- Inform e final
report 11 Hay 11 &
integer'image(error_count ) &
11
errores. 11 ;
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_detector;

Código VHDL 6.37: Continuación del diseño del banco de pruebas del detector de una secuencia
3 unos o más consecutivos.

488
DISEÑO DE LÓGICA SECUENCIAL

Solución al Ejercicio 6.11

El circuito diseñado tiene 10 estados, cada uno de ellos se corresponde con un


valor de la señal de salida count distinto.

El código VHDL que describe el comportamiento del circuito en términos de una


máquina de Moore se muestra en el Código VHDL 6.38.

El banco de pruebas comprueba que cuando la señal reset se activa el circuito


está en el estado inicial, que se corresponde con un valor de la señal de salida count
"0000". También comprueba que cada vez que se produce un flanco de subida de la
señal de reloj la señal de salida count cambia tomando consecutivamente los valores
"0000", "0001", "0010", "0011","0100", "0101", "0110", "0111", "1000", "1001" y "0000".

El banco de pruebas del contador BCD diseñado se muestra en el Código VHDL 6.39
y 6.40.

489
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

---Contador BCD implementado como máquina de Moore

library IEEE;
use IEEE. std_logic_1164. all;
entity contador is port(
count out std_logic_vector(3 downto O);
clk, reset : in std_logic);
end entity contador;
architecture contador of contador is
signal internal_state: std_logic_vector(3 downto O);
begin
count < = internal_state;

--Cálculo del próximo estado


proximo_estado: process ( clk, reset)
begin
if (reset = '1 ') then
internal_state <= "0000";
elsif (rising_edge( clk)) then
case internal_state is
when "0000" =>
internal_state <= "0001";
when "0001" =>
internal_state <= "0010";
when "0010" =>
internal_state <= "0011";
when "0011" =>
internal_state <= "0100";
when "0100" =>
internal_state <= "0101";
when "0101" =>
internal_state <= "0110";
when "0110" =>
internal_state < = "O 111";
when "0111" =>
internal_state < = "1000";
when "1000" =>
internal_state <= "1001";
when "1001"=>
internal_state <= "0000";
when others =>
internal_state <= "0000";
end case;
end if;
end process proximo_estado;
end architecture contador;

Código VHDL 6.38: Diseño del contador BCD.

490
DISEÑO DE LÓGICA SECUENCIAL

-- Banco de pruebas del contador


--BCD
library IEEE;
use IEEE. std_logic_1164. all;
entity bp_contador is
end entity bp_contador;
architecture bp_contador of bp_contador is
constant PERIODO : time := 100 ns; -- Reloj
signal q : std_logic_vector(3 downto 0);-- Salidas UUT
signal clk : std_logic := 'O'; -- Entradas UUT
signal reset : std_logic;

component contador is
port ( count : out std_logic_vector(3 downto O);
clk, reset : in std_logic );
end component contador;

-- Procedimiento pam compro bar las salidas


procedure comprueba_salidas
( esperado_q std_logic_vector( 3 downto O);
actual_q std_logic_vector(3 downto O);
error_count : in out integer) is
begin
-- Comprueba q
if ( esperado_q /= actual_q ) then
report "ERROR: Estado esperado (" &
std_logic' image( esperado_q(3)) &
std_logic' image( esperado_q(2)) &
std_logic' image( esperado_q( 1)) &
std_logic ' image (esperado_ q (O)) &
"), estado actual (" &
std_logic' image( actual_q(3)) &
std_logic' image(actual_q(2)) &
std_logic' image ( actual_q ( 1)) &
std_logic' image ( actual_q (O)) &
"), instante: 11 &
time' image ( now);
error count := error _count + 1;
end if;
end procedure comprueba_salidas;

Código VHDL 6.39: Diseño del banco de pruebas del contador BCD.

491
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

begin
-- Instanciar y conectar UUT
uut : component contador port map
(q, clk, reset);

reset <= '0', '1' after (PERIOD0/4),


'O' after (PERIODO+PERIOD0/4);
clk <= not clk after (PERIOD0/2);
gen_ ve e_ test : process is
variable error _count : integer := O; -- Núm. errores
begin
report 11 Comienza la simulación 11 ;
-- Vectores de test y comprobación del resultado
wait for PERIODO; -- 1
comprueba_salidas( 11 0000 11 , q, error_count);
wait for PERIODO; -- 2
comprueba_salidas( 11 0001 11 , q, error_count);
wait for PERIODO; -- 3
comprueba_salidas( 11 0010 11 , q, error_count );
wait for PERIODO; -- 4
comprueba_salidas( 11 0011 11 , q, error_count);
wait for PERIODO; -- 5
comprueba_salidas( 11 0100 11 ,q, error _count );
wait for PERIODO; -- 6
comprueba_salidas( 11 0101 11 , q, error_count);
wait for PERIODO; -- 7
comprueba_salidas( 11 0110 11 , q, error _count );
wait for PERIODO; -- 8
comprueba_salidas( 11 0111 11 , q, error_count);
wait for PERIODO; -- 9
comprueba_salidas( 11 1000 11 , q, error_count);
wait for PERIODO; -- 1O
comprueba_salidas( 11 1001 11 , q, error _count );
wait for PERIODO; -- 11
comprueba_salidas( 11 0000 11 , q, error _count );
-- Informe .final
if (error_count = o) then
report 11 Simulación finalizada sin errores 11 ;
el se
report 11 ERROR: Hay 11 &
integer' image( error _count ) &
11
errores. 11 ;
end if;
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_contador;

Código VHDL 6.40: Continuación del diseño del banco de pruebas del contador BCD.

492
DISEÑO DE LÓGICA SECUENCIAL

Solución al Ejercicio 6.12

El circuito diseñado tiene 5 estados: SO, S1, S2, S3 y S4. El circuito se encuentra
en el estado SO cuando no se ha detectado ningún bit de la secuencia. Está en
los estados S1, S2, S3 y S4 cuando se han detectado respectivamente el primero,
segundo, tercero y cuarto bit de la secuencia, respectivamente. En la Figura 6.26 se
muestra el diagrama de estados de dicho circuito.

reset

'O'

'O' '1'

Figura 6.26: Diagrama de estados del detector de la secuencia "1011 '.

El código VHDL que describe el comportamiento del circuito en términos de una


máquina de Moore se muestra en el Código VHDL 6.41- 6.42.

El banco de pruebas se muestra en el Código VHDL 6.43 y 6.44. Este banco


de pruebas comprueba que al resetear el circuito éste pasa al estado "0000", cuya
salida (Y) vale 'O'. Después, para cada carga del bit de entrada (x) comprueba
que el circuito pasa al estado que le corresponde y que la salida (Y) tiene el valor
correcto. Finalmente, el programa muestra un mensaje con el número total de errores
detectados.

493
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

--- DetectoT de la secuencia 1O11


library IEEE;
use IEEE. std_logic_1164. all;
entity detector is
port ( Y : out std_logic;
state : out std_logic_vector(2 downto O);
X : in std_logic;
reset : in std_logic;
clk : in std_logic);
end entity detector;
architecture detector of detector is
signal internal_state: std_logic_vector(2 downto O);
begin
state <= internal_state;

-- Cálcv,lo salida
salida: process (internal_state) ~
begin
case internal_state is
when "100" = > Y<= '1';
when others = > Y <= '0';
end case;
end process salida;

Código VHDL 6.41: Diseño del detector de la secuencia "1011".

494
DISEÑO DE LÓGICA SECUENCIAL

--Cálculo del próximo estado


proximo_estado: process ( clk, reset)
begin
if (reset = ' 1 ') then --reset asíncrono
internal_state <= 11 000 11 ;
elsif (rising_edge( clk)) then
case internal_state is
when 11 000 11 => -- Estado actual: SO
if X = ' 1 ' then
internal_state <= 11 001 11 ;
el se
internal_state <= 11 000 11 ;
end if;
when 11 001 11 = > --Estado actual: Si
if X = ' 1 ' then
internal_state <= 11 001 11 ;
el se
internal_state <= 11 010 11 ;
end if;
when 11 010 11 => --Estado actual: S2
if X = ' 1 ' then
internal_state <= 11 011 11 ;
else
internal_state <= 11 000 11 ;
end if;
when 11 01P => -- Estado actual: S3
if X = ' 1 ' then
internal_state <= 11 100 11 ;
el se
internal_state <= 11 010 11 ;
end if;
when 11 100 11 => --Estado actual: S4
if X = ' 1 ' then
internal_state <= 11 001 11 ;
el se
internal_state <= 11 010 11 ;
end if;
when others=> -- Por completitud
internal_state <= 11 000 11 ;
end case;
end if;
end process proximo_estado;
end architecture detector;

Código VHDL 6.42: Continuación del diseño del detector de la secuencia "1011".

495
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pT'uebas del detector de sec'U,encias


library IEEE;
use IEEE. std_logic_1164. all;

entity bp_detector is
end entity bp_detector;

architecture bp_detector of bp_detector is


constant PERIODO : time := 100 ns; --Reloj
signal state : std_logic_vector(2 downto 0);-- Salidas UUT
signal Y : std_logic;
signal clk : std_logic := 'O'; -- Entradas UUT
signal reset, X : std_logic;

component detector is
port ( Y : out std_logic;
state : out std_logic_vector(2 downto O);
X : in std_logic;
reset : in std_logic;
clk : in std_logic);
end component detector;

-- Procedimiento para comprobar las salidas


procedure comprueba_salidas
( esperado_state std_logic_vector(2 downto O);
actual_state std_logic_vector(2 downto O);
esperado_ Y std_logic;
actual Y std_logic;
error count inout integer) is
begin
-- Comprueba state
if ( esperado_state / = actual_state ) then
report "ERROR: Estado esperado (" &
std_logic' image( esperado_state(2)) &
std_logic' image( esperado_state( 1)) &
std_logic' image( esperado_state(O)) &
"), estado actual (" &
std_logic' image(actual_state(2)) &
std_logic' image ( actual_state ( 1)) &
std_logic' image ( actual_state (O)) &
"), instante: " &
time' image(now);
error count := error_count + 1;
end if; -- Comprueba Y
if ( esperado_Y /= actual_Y ) then
report "ERROR: Salida Y esperada (" &
std_logic' image (esperado_ Y) &
"), salida actual (" &
std_logic' image (actual_ Y) &
"), instante: " &
time ' image ( now);
error count := error_count + 1;
end if;
end procedure comprueba_salidas;

Código VHDL 6.43: Diseño del banco de pruebas del detector de la secuencia "1011".

496
DISEÑO DE LÓGICA SECUENCIAL

begin
-- lm;tanciar y conectaT UUT
uut : component detector port map
(Y, state, X, reset, clk);

reset <= '0', '1' after (PERIOD0/4),


'O' after (PERIOD0/2);
clk <= not clk after (PERIOD0/2);
gen_ vec_ test : process is
variable error _count : integer := O; -- Núm. eTT-ores
begin
report "Comienza la simulación";
-- Vectores de test y comprobación del resultado
wait for 3*PERIOD0/4;
comprueba_salidas("OOO", state, 'O', Y, error _count );
X <= '1'; wait for PERIODO; -- 1
comprueba_salidas("001", state, '0', Y, error_count);
X <= 'O'; wait for PERIODO; -- 2
comprueba_salidas("010", state, 'O', Y, error _count );
X <= '1'; wait for PERIODO; -- 8
comprueba_salidas("011", state, '0', Y, error_count);
X <= '1'; wait for PERIODO; -- 4
comprueba_salidas("100", state, '1 ', Y, error _count );
X <= 'O'; wait for PERIODO; -- 5
comprueba_salidas("010" ,state, '0', Y, error_count);
X <= '1'; wait for PERIODO; -- 6
comprueba_salidas("011", state, '0', Y, error_count);
X <= '1'; wait for PERIODO; -- 7
comprueba_salidas("100", state, '1', Y, error_count);
-- Inform e final
report 11 Hay 11 &
integer'image(error_count ) &
11
errores. 11 ;
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_detector;

Código VHDL 6.44: Continuación del diseño del banco de pruebas del detector de la secuencia
"1011".

497
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 6.13

El código VHDL que describe el comportamiento del circuito se muestra en el


Código VHDL 6.45. El banco de pruebas del dicho circuito se muestra en el Código
VHDL 6.46 y 6.47.

library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
entity udcounter is port (
Q: out std_logic_vector(3 downto O);
Clock: in std_logic;
Clear: in std_logic;
Count: in std_logic;
Down: in std_logic);
end udcounter;
architecture udcounter OF udcounter IS
begin
process {Clock, Clear)
variable value: INTEGER RANGE O TO 15;
begin
if (Clear = '1 ') then
value :=O;
elsif (rising_edge(Clock)) then
if (Count = '1 ') then
if (Down = '0') then
value := value + 1;
else
value := value - 1;
end if;
end if;
end if;
Q <= std_logic_vector(to_unsigned(value,4));
end process;
end udcounter;

Código VHDL 6.45: Diseño del contador binario ascendente y descendente de 4 bits.

498
DISEÑO DE LÓGICA SECUENCIAL

-- B aneo de pruebas del contador binario


-- ascendente y descendente de 4 bits
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;

entity bp_udcounter is
end entity bp_udcounter;

architecture bp_udcounter of bp_udcounter is


constant PERIODO : time := 10 ns; -- Reloj
signal Q : std_logic_vector(3 downto 0);-- Salidas UUT
signal Clock : std_logic := 'O'; -- Entradas UUT
signal Clear, Count, Down : std_logic;

component udcounter is
port ( Q : out std_logic_vector(3 downto O);
Clock, Clear, Count, Down : in std_logic ) ;
end component udcounter;

-- Pmcedimiento para compmbar las salidas


procedure comprueba_salidas
( esperado_q std_logic_vector ( 3 downto O);
actual_q std_logic_vector ( 3 downto O);
error_count : inout integer) is
begin
-- Comprueba q
if ( esperado_q /= actual_q ) then
report 11 ERROR: Estado esperado ( 11 &
std_logic' image( esperado_q(3)) &
std_logic' image( esperado_q(2)) &
std_logic' image( esperado_q( 1)) &
std_logic' image( esperado_q(O)) &
11
) , estado actual ( 11 &
std_logic' image( actual_q(3)) &
std_logic' image( actual_q(2)) &
std_logic' image ( actual_q ( 1)) &
std_logic' image( actual_q(O)) &
11
) , instante:
11
&
time' image(now);
error count := error _count + 1;
end if;
end procedure comprueba_salidas;

Código VHDL 6.46: Diseño del banco de pruebas del contador binario ascendente y descendente
de 4 bits.

499
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

begin
-- Inst an ciar y conectar UUT
uut : component udcounter port map
(Q, Clock, Clear, Count, Down);
Clear <= 'O', '1' after (PERIOD0/4),
'0' after (3*PERIOD0/4);
Clock <= not Clock after (PERIOD0/2);
gen_ vec_ test : process is
variable temp : unsigned (3 downto O);
variable error _count : integer := O; -- Núm. ermres
begin
report "Comienza la simulación";
-- Vectores de t est y compmbación del resultado
wait for PERIODO;
Count <= '1'; Down <='0';
for i in O to 4 loop
temp := TO_UNSIGNED(i,4);
comprueba_salidas( std_logic_vector(temp), Q, error_count);
wait for PERIODO;
end loop;
Count <= '0'; Down <= '1';
wait for PERIODO; -- 1
Count <= '1';
for i in 5 downto 1 loop
temp := TO_UNSIGNED(i,4);
comprueba_salidas( std_logic_vector(temp), Q, error_count);
wait for PERIODO;
end loop;
Count <= '0';
-- Inform e final
if (error_ count = O) then
report "Simulación finalizada sin errores";
else
report "ERROR: Hay " &
integer' image(error_count ) &
" errores. ";
end if;
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_udcounter;

Código VHDL 6.47: Continuación del diseño del banco de pruebas del contador binario
ascendente y descendente de 4 bits.

500
DISEÑO DE LÓGICA SECUENCIAL

Solución al Ejercicio 6.14

El Código VHDL 6.48 - 6.51 es el diseño del circuito controlador y su banco de


pruebas. Al diseñar el controlador, se ha declarado un tipo enumerado denominado
type_state, con el fin de definir los 5 posibles estados del controlador: (RG, RY, GR,
YR e YY).

Por otra parte, en el bloque process proximo_estado se ha declarado una señal


( internal_state) y una variable (count) auxiliares. La señal internal_state se usa
para almacenar el estado del controlador. La variable count se emplea para llevar la
cuenta de tiempo que el semáforo pasa en un determinado estado.

Cabe esperar que el hardware obtenido de la síntesis de este diseño tenga 15


flip-flops: 3 flip-flops para almacenar los bits de la señal internal_state (la má-
quina tiene 5 estados, así que se necesitan 3 bits para codificarlos) y 12 flip-flops
para el contador (se trata de un contador de 12 bits, ya que debe contar hasta
timeMAX = 2700).

-- Definición de las constantes globales. Fichero: ctrLsemaforo_CONSTANTS.vhd


library IEEE;
use IEEE. std_logic_1164.all;
package ctrl_semaforo_CONSTANTS is
constant PERIODO : time := 16667 us; --60 Hz
constant timeMAX : integer := 2700; --45s*60ciclos/s
constant timeRG : integer := 1800; --30s *60ciclos/s
constant timeRY : integer := 300; --5s*60ciclos/s
constant timeYR : integer := 300; --5s*60ciclos/s
constant timeGR : integer := 2700; --45*60ciclos/s
end package;

-- Controlador semáforos. Fichero: ctrLsemaforo. vhd


Library IEEE;
use IEEE. std_logic_1164. all;
use work.ctrl_semaforo_CONSTANTS.all;

entity ctrl_semaforo is
port(r1, r2, y1, y2, g1, g2 : out std_logic;
clk, reset : in std_logic);
end entity ctrl_semaforo;

architecture ctrl_semaforo of ctrl_semaforo is


type type_state is (RG, RY, GR, YR, YY);
signal internal_state: type_state;
begin

Código VHDL 6.48: Package con la definición de las constantes y parte inicial del diseño del
controlador de dos semáforos.

501
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Continuación diseño del controlador semáforos. Fichero: ctrLsemaforo. vhd


proximo_estado: process ( clk, reset)
variable count: integer range O to timeMAX;
begin
if (reset = '1 ') then
internal_state <= YY;
count :=O;
elsif (rising_edge( clk)) then
case internal_state is
when RG =>
if ( count = timeRG) then
internal_state <= RY; count := O;
end if;
when RY =>
if ( count = timeRY) then
internal_state <= GR; count := O;
end if;
when GR =>
if ( count = timeGR) then
internal_state <= YR; count := O;
end if;
when YR =>
if ( count = timeYR) then
internal_state <= RG; count := O;
end if;
when YY =>
internal state <= RY; count := O;
end case;
count := count + 1;
end if;
end process proximo_estado;

salidas: process(internal_state)
begin
case internal_state is
when RG =>
r1 <= '1 '; r2 <= '0'; y1 <= '0';
y2 <= '0'; g1 <= '0'; g2 <= '1';
when RY =>
r1 <= '1 '; r2 <= '0'; y1 <= '0';
y2 <= '1 '; g1 <= '0'; g2 <= '0';
when GR =>
r1 <= '0'; r2 <= '1'; y1 <= '0';
y2 <= '0'; g1 <= '1'; g2 <= '0';
when YR =>
r1 <= '0'; r2 <= '1'; y1 <= '1';
y2 <= '0'; g1 <= '0'; g2 <= '0';
when YY =>
r1 <= '0'; r2 <= '0'; y1 <= '1';
y2 <= '1'; g1 <= '0'; g2 <= '0';
end case;
end process salidas;
end architecture ctrl_semaforo;

Código VHDL 6.49: Parte final del diseño del controlador de dos semáforos.

502
DISEÑO DE LÓGICA SECUENCIAL

-- Banco de pruebas del controlador de do s semáforos. Fichero : bp_ctrLsemaforo. vhd


library IEEE;
use IEEE. std_logic_1164 . all;
use work.ctrl_semaforo_CONSTANTS.all;

entity bp_ctrl_semaforo is
end entity bp_ctrl_semaforo;

architecture bp_ctrl_semaforo of bp_ctrl_semaforo is


signal z : std_logic_vector(5 downto O); -- Salidas UUT
signal clk : std_logic .- 'O'; -- Entradas UUT
signal reset : std_logic;

component ctrl_semaforo is
port ( r1, r2, y1, y2, g1, g2 : out std_logic;
clk, reset : in std_logic ) ;
end component ctrl_semaforo;

-- Procedimiento para comprobar las salidas del fiip-fiop


procedure comprueba_salidas
( esperado_z : std_logic_vector(5 downto O);
actual_z : std_logic_vector(5 downto O);
error_count : inout integer) is
begin
if ( esperado_z /= actual_z ) then
report "ERROR: Estado esperado (" &
std_logic' image( esperado_z(5)) &
std_logic' image( esperado_z( 4)) &
std_logic' image( esperado_z(3)) &
std_logic' image( esperado_z(2)) &
std_logic' image( esperado_z( 1)) &
std_logic' image( esperado_z(O)) &
"), estado actual (" &
std_logic' image ( actual_z ( 5)) &
std_logic' image ( actual_z ( 4)) &
std_logic' image(actual_z(3)) &
std_logic' image ( actual_z ( 2)) &
std_logic' image ( actual_z ( 1)) &
std_logic' image ( actual_z (O)) &
"), instante: " &
time ' image ( now);
error count := error_count + 1;
end if;
end procedure comprueba_salidas;

Código VHDL 6.50: Parte inicial del banco de pruebas del controlador.

503
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Continuación del banco de prv,ebas del controlador sem~foros


-- Fichero: bp_ctrLsemaforo. vhd

begin
-- Instanciar y conectar UUT
uut: component ctrLsemaforo port map (z(5), z(4), z(3), z(2), z(1), z(O),clk, reset);
reset <= 'O',
'1' after (PERIOD0/4),
'O' after (PERIODO+PERIOD0/4);
clk <= not clk after (PERIODO /2);
gen_vec_test : process is
variable error_count : integer := O; -- Núm. errores
begin
report "Comienza la simulación";
-- Vectores de test y comprobación del resultado
wait for PERIODO; -- 1
comprueba_salidas ( "00 1100", z, error_count);
wait for PERIODO; -- 2
comprue ba_salidas (" 100100", z, error_count);
wait for timeRY*PERIODO; -- 3
comprueba_salidas("010010", z, error_count);
wait for timeGR *PERIODO; -- 4
comprueba_salidas("011000", z, error_count);
wait for timeYR*PERIODO; -- 5
comprueba_salidas(" 100001 ", z, error_count);
wait for timeRG*PERIODO; -- 6
comprueba_salidas(" 100100", z, error_count);
-- Informe final
if ( error_count = O) then
report "Simulación finalizada sin errores" ;
else
report "ERROR: Hay" &
integer'image( error_count) &
"errores.";
end if;
wait; -- Final del bloque process
end process gen_vec_test;
end architecture bp_ctrLsemaforo;

Código VHDL 6.51: Parte final del banco de pruebas del controlador.

504
DISEÑO DE LÓGICA SECUENCIAL

Solución al Ejercicio 6.15

El Código VHDL 6.52- 6.54 es el diseño del controlador del microondas. Se han de-
clarado las siguientes señales auxiliares: minutoAnterior, internalState, t_coccion,
t_alarma, reset_alarma y resetTimer. La señal internalState almacena el estado
actual. Las señales t_coccion y t_alarma se usan para llevar la cuenta del tiempo
restante para finalizar la cocción y para apagar la alarma, respectivamente. Las
señales reset_alarma y resetTimer son del tipo boolean y se usan para resetear el
tiempo de alarma y de cocción, respectivamente.

Se han definido tres bloques process. En el bloque process proximo_estado se


calcula el siguiente estado, que depende de las entradas y del estado anterior. En
el bloque process salidas se calculan las salidas del controlador, que dependen
únicamente del estado. Finalmente, en el bloque process contador se modifica el
valor del tiempo de cocción y de alarma. Las señales reset_alarma y resetTimer
comunican este bloque con el bloque process donde tiene lugar el cálculo del estado.
Esto se hace de la siguiente forma.

Cuando el controlador se encuentra en el estado coccion, se emplea el valor


de la variable t_coccion para determinar si debe producirse la transición al esta-
do alarmaActivada. Una vez en el estado alarmaActivada, se emplea el valor de
la variable t_alarma para determinar si debe producirse la transición al estado
puertaCerrada.

Asimismo, cuando estando el controlador en el estado puertaCerrada la señal


de entrada marcha adquiere el valor '1 ', entonces se emplea el valor de la variable
t_coccion para decidir si debe producirse la transición al estado coccion. Para
resetear el tiempo de alarma y de cocción se pone a true el valor de las señales
reset_alarma y resetTimer, respectivamente.

En el bloque process contador , se modifica el valor de las variables t_coccion


y t_alarma como se describe a continuación. El tiempo de cocción se incrementa
cuando el usuario pulsa el botón minuto. Esto se ha modelado como sigue: si la
señal minuto está a '1 ', la señal resetTimer está a false, y además la señal minuto
estaba a 'O' en la última transición de la señal de reloj, entonces se incrementa el
tiempo de cocción.

Si el controlador se encuentra en estado coccion y el tiempo de cocción (t_coccion)


es mayor que O, entonces se va decrementando el valor del tiempo de cocción en cada
flanco de subida de la señal de reloj. El tiempo de alarma se aumenta cada flanco
de subida de la señal de reloj si el controlador está en el estado alarmaActi vada.

505
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Definición de las constantes globales


--Fichero: microondas_CONST.vhd
library IEEE;
use IEEE. std_logic_1164. all;
package microondas_CONST is
constant PERIODO : time := 125 ms; -- R eloj
constant ALARMAT : integer := 24; -- 3 seg. a frecuencia reloj 125ms
constant SESENTASEC : integer := 480; -- 60 seg. a frecuencia reloj 125ms
constant UNSEC : integer := 8; -- 1 seg. a frecuencia reloj 125ms
constant TMAX : integer := 1023; --Máximo tiempo
type estadoMicro is
(puertaAbierta,puertaCerrada, coccion, alarmaActivada);
end package microondas_CONST;
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE. numeric_std. all;
use work. microondas_CONST. all;
entity microondas IS
port (segundos: out std_logic_vector(9 downto O);
calentar, luz, alarma: out std_logic;
reset, minuto, marcha, stop_Reset, puerta, clk: in std_logic);
end entity microondas;
architecture microondas of microondas IS
signal minutoAnterior: std_logic;
signal internal_state:estadoMicro;
signal t_coccion: integer range O to TMAX;
signal t_alarma: integer range O to ALARMAT;
signal reset_alarma: boolean;
signal resetTimer: boolean;
begin
proximo_estado: --Calcula el siguiente estado
process( clk, reset) is
begin
if (reset = '1 ') then
internal_state <= puertaCerrada;
reset_alarma <= true; resetTimer <= true;

Código VHDL 6.52: Package con la definición de las constantes y parte inicial del diseño del
controlador del microondas.

506
DISEÑO DE LÓGICA SECUENCIAL

Continuación de l diseño del controlador de microondas. Fichero : microondas.vhd


elsif rising_edge( clk) then
case internal_state is
when puertaAbierta = >
if puerta = 'O' then
internal_state < = puertaCerrada;
end if;
if stop_Reset = '1' then resetTimer < = true;
else resetTimer < = false ;
end if;
when puertaCerrada = >
if puerta = '1' then
internal_state < = puertaAbierta;
end if;
if t_coccion> O and marcha = '1' then
internal_state < = coccion;
end if;
if stop_Reset = '1' then resetTimer < = true ;
else resetTimer < = false;
end if;
when coccion = >
if puerta = '1' then
internal _state < = puertaAbierta;
end if;
if t_coccion=O then
internal_state < = alarmaActivada;
resetTimer < = true; reset_alarma < = false;
end if;
if stop_Reset = '1' then
internal_state < = puertaCerrada;
end if;
when alarmaActivada = >
if puerta = ' 1' then
internal_state < = puertaAbierta;
reset _alarma < = true ;
end if;
if t_alarma = (ALARMAT-1) then
reset_alarma < = true;
internal_state < = puertaCerrada;
end if;
if stop_Reset = '1' then
resetTimer < = true ;
el se
resetTimer < = false ;
end if;
end case;
end if;
end process proximo_estado;

Código VHDL 6.53: Continuación del diseño del controlador del microondas.

507
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Continuación del diseño del contmlador de microondas. Fichero: microondas. vhd

salidas: --Calcula las salidas


process(internal_state) is
begin
case internal_state is
when puertaAbierta = >
calentar < = '0'; luz < = '1'; alarma < = ' 0';
when puertaCerrada = >
calentar < = '0'; luz < = '0'; alarma < = '0';
when coccion = >
calentar < = '1'; luz < = '1'; alarma < = '0';
when alarmaActi vada = >
calentar < = '0'; luz < = '0'; alarma < = '1';
end case;
end process salidas;
--Convierte los segundos a stcLlogic_vector de lon9itud 10
segundos < = std_logic_vector( to_unsigned( tt_coccion+1) /unsec,10) );

contador: --Modifica valores Lcoccion y Lalarma


process( clk) is
begin
if reset _alarma then
t_alarma < =0;
elsif internal_state = alarmaActi vada and t_alarma < (ALARMAT) then
if ( rising_edge( clk) ) then
t_alarma < = t_alarma + 1;
end if;
end if;
if resetTimer then
t_coccion < = O;
elsif minuto = '1' and minutoAnterior = 'O' then
t_coccion < = t_coccion + (sesentasec- 1);
elsif internal_state = coccion and t_coccion > O then
if ( rising_edge( clk) ) then
t_coccion < = t_coccion - 1;
end if;
end if;
minutoAnterior < = minuto ;
end process contador;
end architecture microondas;

Código VHDL 6. 54: Parte final del diseño del controlador del microondas.

508
DISEÑO DE LÓGICA SECUENCIAL

El Código VHDL 6.54-6.57 es su banco de pruebas. En la Figura 6.27 se indica


el orden en que se realizan las transiciones entre los estados.

reset

stop_Reset
@

t_alarma=O

Figura 6.27: Transiciones en el estado realizadas durante el test del circuito controlador del
microondas.

509
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del controlador del microondas


-- Fich ero: bp_microondas. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
use work.microondas_CONST .all;
entity bp_microondas is
end entity bp_microondas;
architecture bp_microondas of bp_microondas is
signal calentar, luz, alarma : std_logic; -- Salidas UUT
signal segundos: std_logic_vector(9 downto O); -- Salidas UUT
signal clk : std_logic := 'O'; -- Entradas UUT
signal reset, minuto, marcha : std_logic; -- Entradas UUT
signal stop_Reset, puerta : std_logic; -- Entradas UUT

component microondas is
port( segundos : out std_logic_vector( 9 downto O);
calentar, luz, alarma : out std_logic;
reset, minuto, marcha : in std_logic;
stop_Reset, puerta, clk : in std_logic);
end component microondas;
procedure comprueba -- Procedimiento para comprobar las salidas
( esperado_segundos: integer;
esperado_luz, esperado_alarma, esperado_calentar : std_logic;
actual_segundos: std_logic_vector(9 downto O);
actual_luz, actual_alarma, actual_calentar std_logic;
error_count : inout integer) is
variable e_seg: integer range O to 1023;
begin
if ( esperado_luz /= actual_luz ) then -- Comprueba luz
report "ERROR: Luz esperada (" & std_logic' image(esperado_luz) &
"), luz actual (" & std_logic' image(actual_luz) &
"), instante: " & time' image(now);
error_count := error_count + 1;
end if;
if ( esperado_alarma / = actual_alarma) then -- Comprueba alarma
report "ERROR: Alarma esperada (" & std_logic' image( esperado_alarma) &
"), alarma actual (" & std_logic' image(actual_alarma) &
"), instante: " & time' image(now);
error count := error_count + 1;
end if;

Código VHDL 6.55: Banco de pruebas del diseño del controlador del microondas.

510
DISEÑO DE LÓGICA SECUENCIAL

-- Continuación del banco de pruebas del controlador del microondas


-- Fichero: bp_microondas. vhd

if ( esperado_calentar /= actual_calentar ) then -- Comprueba calentar


report "ERROR: Calentar esperado (" & std_logic'image(esperado_calentar) &
"), calentar actual (" &std_logic' image(actual_calentar) &
"), instante: " & time' image(now);
error_count := error_count + 1;
end if;
e_seg := to_integer((unsigned(actual_segundos)));
if ( esperado_segundos / = e_seg) then -- Comprueba segundos
report "ERROR: Segundos esperados (" & integer' image( esperado_segundos) &
"),segundos actual (" & integer'image(e_seg) &
"), instante: " & time' image(now);
error count := error_count + 1;
end if;
end procedure comprueba;
begin
-- Instanciar y conectar UUT
uut : component microondas port map (segundos,calentar,luz,alarma,reset,
minuto,marcha,stop.,...Reset,puerta,clk);
reset < = '0', '1' after (PERIOD0/4), '0' after (PERIODO+PERIOD0/4);
clk <= not clk after (PERIOD0/2);
gen_ vec_ test : process is
variable error _count : integer := O; -- Núm. errores
begin
report "Comienza la simulación";

-- Vectores de test y comprobación del resultado


minuto <= '0'; marcha <= '0'; stop_Reset <= '0'; puerta<= '0';
wait for 2*PERIODO;
comprueba( O,' O',' O',' O' ,segundos,luz,alarma,calentar,error _count);
minuto <= '1 '; marcha <= '1'; wait for PERIODO;
comprueba( 60, 'O',' O',' O' ,segundos,luz,alarma,calentar ,error _count);
minuto <= 'O'; wait for PERIODO; --1 coccion
comprueba(60,' 1', '0',' 1' ,segundos,luz,alarma,calentar,error_count);
minuto<=' 1'; wait for PERIODO;
minuto <= 'O'; marcha <= 'O'; wait for PERIODO;
comprueba(119,' 1',' O',' 1' ,segundos,luz,alarma,calentar,error_count );

Código VHDL 6.56: Continuación del banco de pruebas del controlador del microondas.

511
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Continuación del banco de pruebas del microondas. Fichero: bp_microondas. vhd

minuto <= '0'; marcha <= '0';


wait for 2*sesentasec*PERIODO; --2 alarmaActivada
comprueba( O,' O',' 1 ','O' ,segundos, luz, alarma, calentar, error _count );
puerta <= '1'; wait for PERIODO; -- 3 puertaAbierta
comprueba( O,' 1 ', '0', '0' ,segundos,luz,alarma,calentar,error_count);
minuto < = '1 '; wait for PERIODO;
comprueba(60,' 1', 'O',' O' ,segundos,luz,alarma,calentar,error _count );
minuto<=' O'; stop_Reset < = '1'; wait for 2*PERIODO; --4 puertaAbierta
comprueba( O,' 1 ', '0', '0' ,segundos,luz,alarma,calentar,error_count);
stop_Reset <= 'O'; puerta <= 'O'; wait for PERIODO; --5 puerta Cerrada
comprueba( O,' O',' O',' O' ,segundos,luz,alarma,calentar,error _count );
minuto <= '1'; marcha < =' 1'; wait for 2*PERIODO; --6 coccion
comprueba(60,' 1',' O',' 1' ,segundos,luz,alarma,calentar,error_count);
minuto<= '0'; puerta < = '1'; marcha < = '0';
wait for PERIODO; --7 puertaAbierta
comprueba( 59,' 1',' 0', '0' ,segundos,luz,alarma,calentar,error_count);
puerta <= 'O'; wait for PERIODO; --8 puertaCerrada
comprueba( 59,' O',' O',' O' ,segundos,luz,alarma,calentar ,error _count);
puerta <= '1 '; wait for PERIODO; --9 puertaAbierta
comprueba( 59,' 1', 'O',' O' ,segundos,luz,alarma,calentar,error_count );
puerta <= 'O'; wait for PERIODO; --1 O puertaCerrada
comprueba(59, '0', '0', 'O' ,segundos,luz,alarma,calentar,error_count);
marcha <= '1'; wait for PERIODO; --11 coccion
comprueba( 59,' 1', 'O',' 1' ,segundos,luz,alarma,calentar ,error _count);
stop_Reset <= '1'; puerta <= 'O'; wait for PERIODO; --12 puertaCerrada
comprueba( 59,' O',' O',' O' ,segundos,luz,alarma,calentar,error _count );
marcha < = '1'; stop_Reset <= 'O'; wait for PERIODO; --13 coccion
comprueba( 59,' 1',' 0',' 1' ,segundos,luz,alarma,calentar,error_count);
wait for (sesentasec)*PERIODO; --14 alarmaActivada
comprueba( O,' O',' 1', 'O' ,segundos,luz,alarma,calentar,error_count);
wait for (ALARMAT-10)*PERIODO;
comprueba( O,' O',' 1', 'O' ,segundos,luz,alarma,calentar,error_count);
minuto < = '1'; marcha<= '0'; wait for PERIODO;
comprueba(60,' 0',' 1', 'O' ,segundos,luz,alarma,calentar,error_count);
stop_Reset < = '1'; minuto < = 'O'; wait for 2*PERIODO; --15 alarmaActivada
comprueba( O, '0',' 1', '0' ,segundos,luz,alarma,calentar,error_count);
stop_Reset < = 'O'; wait for ?*PERIODO; --16 puerta Cerrada
comprueba( O,' O',' O',' O' ,segundos,luz,alarma,calentar,error _count );
minuto < = '1'; marcha <= 'O'; wait for PERIODO;
comprueba( 60, 'O',' O',' O' ,segundos,luz,alarma,calentar ,error _count);
stop_Reset < = '1 '; wait for 2*PERIODO; --17 puertaCerrada
comprueba( O,' O',' O',' O' ,segundos,luz,alarma,calentar,error _count );
minuto < = 'O'; stop_Reset < = 'O';

report "Finaliza la simulación con " & integer' image( error _count) &
"errores."; -- Informe final
wait; -- Final del bloque process
end process gen_ vec_ test;
end architecture bp_microondas;

Código VHDL 6.57: Parte final del banco de pruebas del controlador de microondas.

512
TEMA 7

METODOLOGÍA DE
TRANSFERENCIA ENTRE REGISTROS

7.1. Introducción
7.2. Operaciones de transferencia entre registros
7.3. Máquinas de estado finito con camino de datos
7.4. Descripción del programa RT usando VHDL
7.5. Circuito detector de secuencia
7.6. Control de una máquina expendedora
7. 7. Lecturas recomendadas
7.8. Ejercicios de autocomprobación
7.9. Soluciones de los ejercicios
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

OBJETIVOS DOCENTES

Una vez estudiado el contenido del tema y realizados los ejercicios prácticos,
debería saber:

- Discutir los conceptos siguientes: operaciones RT , notación RT, programa RT


y metodología RT.

- Discutir el ciclo de ejecución de una operación RT.

- Discutir los principios fundamentales de la programación RT.

- Dado un algoritmo , traducirlo a un programa RT.

- Describir usando VHDL programas RT sencillos y programar bancos de prue-


bas para testear estos diseños.

- Discutir los conceptos fundamentales de la síntesis de programas RT mediante


FSMD. En particular, discutir la estructura general de la FSMD, cómo se
realiza la síntesis del camino de datos y por qué la unidad de control puede
sintetizarse como una FSM.

515
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

7.1. INTRODUCCIÓN

El comportamiento de los sistemas se describe frecuentemente mediante algorit-


mos. Es decir, mediante una secuencia de acciones o pasos, que deben ejecutarse
para resolver un problema o realizar una tarea. Dos características básicas de los
algoritmos son, por una parte, el empleo de variables, que sirven para almacenar los
resultados intermedios de los cálculos, y por otra parte, la ejecución secuencial de
las acciones. Es decir, los pasos de un algoritmo se ejecutan uno tras otro, siguiendo
un orden bien establecido.

La metodología de transferencia entre registros (metodología RT) permite descri-


bir de manera algorítmica el comportamiento del hardware. En esta metodología, los
registros se emplean para almacenar los datos intermedios, desempeñando de esta
forma el mismo papel que juegan las variables en los algoritmos.

En la notación RT ( Register Transfer), todas las operaciones son descritas como la


transferencia de datos de uno o más registros, a otro registro. Durante la transferen-
cia de los datos, éstos pueden transformarse mediante operaciones combinacionales
aritméticas y lógicas, desplazamientos, etc.

Por lo general, la síntesis de este tipo de descripciones da lugar a circuitos secuen-


ciales, si bien en algunos casos sencillos puede dar lugar a circuitos combinacionales.
En este tema nos centraremos en el diseño de programas RT para síntesis de circuitos
secuenciales síncronos con camino de datos. En estos circuitos cabe distinguir dos
partes (véase la Figura 7.1):

El camino de los datos, que consiste en componentes, tanto combinacionales


como secuenciales, que almacenan, combinan y manipulan los datos. Entre los
componentes que típicamente forman parte del camino de datos se encuentran
los registros, los sumadores, los multiplexores, etc.

- La lógica de control, que consiste en la lógica necesaria para generar las señales
de control que controlan todos los componentes del camino de datos. Puede
tratarse de una FSM del tipo que se explicó en el Capítulo 6, con la lógica
combinacional necesaria para generar las señales de control correspondientes
a cada estado.

El camino de datos envía señales de status (que indican el estado de determinados


datos) a la lógica de control, que a su vez envía señales de control al camino de datos,
basadas en la señales de status recibidas y en el propio estado interno de la lógica
de control.

517
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Lógica de
control

Figura 7.1: Circuito secuencial síncrono con lógica de control y camino de datos.

Resumiendo lo anterior, llamamos a esta metodología de implementación meto-


dología de transferencia entre registros porque un algoritmo es transformado en una
secuencia de acciones que especifican cómo los datos son manipulados y transferidos
entre registros. Una implementación RT típica incluye un camino de datos y la lógica
de control. Este tipo de circuito, consistente en una máquina de estado finito (FSM)
a la que se ha añadido el camino de datos, se denomina FSMD (FSM con un camino
de Datos).

7.2. OPERACIONES DE TRANSFERENCIA ENTRE REGISTROS

En esta sección se describen los fundamentos de las operaciones de transferencia


entre registros, denominadas de manera abreviada operaciones RT.

7.2.1. Operación RT básica

La acción básica en la metodología RT es la operación de transferencia entre


registros, que puede representarse de la manera siguiente:

rdest f- f(rorigl, rorig2, · · ·, rorigN );

donde los registros situados en el lado de la derecha son los registros origen de los
datos (r origl, r orig2, ... , r origN), la funciÓn f representa la operaciÓn a realizar, y el
registro situado en el lado de la izquierda es el registro destino (r dest), en el cual se
almacena el resultado de la operación.

En resumen, esta notación significa que el nuevo valor de r dest se calcula evaluando
f ( r origl, r orig2, ... , r origN), y que el resultado Se almacena en r dest en el siguiente
flanco de subida de la señal de reloj. Obsérvese que la notación f - no existe en
VHDL. Se emplea únicamente para representar la operación RT.

518
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

Tabla 7.1: Algunas operaciones RT y sus correspondientes sentencias VHDL.

Sentencia VHD L Operación RT


X <= Y; Transfiere el contenido de Y a X
X <= O; Guarda en X el valor decimal O
X<= (others => '1'); Pone todos los bits de X al valor '1'
X <= 1; Guarda en X el valor decimal 1
X <= X slr 1; Desplaza el contenido de X un bit
hacia la derecha e introduce el valor
'O' en el bit más significativo (MSB)
X <= X ror 4; Desplaza el contenido de X cuatro
bits hacia la derecha de manera
circular
X<= M( 16#C2# ); Transfiere a X el contenido del ele-
mento C216 (elemento 194w) de M
X <= Y or Z; X+-- Y or Z (or bit a bit)
X <= Y and Z; X+-- Y and Z (and bit a bit)
X <= Y xor Z; X+-- Y xor Z (xor bit a bit)
X <= not Y; X +-- complemento a 1 de Y
X <= -Y; X +-- complemento a 2 de Y
X <= Y + Z; X+-Y+Z
X <= Y - Z; X+-Y-Z
X<= (e and Y) or ((note) and Z); X+-- (e and Y) or (e and Z)
X <= Y when e else Z; Equivalente a la anterior
if (e) then X <= Y; else X <= Z; Equivalente a la anterior

Asimismo, la única restricción que se impone a la función f es que debe poder


ser sintetizada mediante un circuito combinacional. Durante la transferencia de los
datos, éstos pueden transformarse mediante operaciones combinacionales aritméticas
y lógicas, desplazamientos, etc. En la Tabla 7.1 se muestran algunos ejemplos de
operaciones RTL y sus correspondientes sentencias VHDL.

La mayor diferencia entre una variable de un algoritmo y un registro es que en la


operación RT está implícito el papel de la señal de reloj. Las acciones que implica
la operación RT

rdest +--- f(rorigl, rorig2, · · ·, rorigN );

son las siguientes:

519
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

l. Se produce el flanco de subida de la señal de reloj. Transcurrido un cierto


retardo interno de propagación de los registros, los datos de salida de los
registros están disponibles.

2. Los datos son operados por el circuito combinacional que realiza la función
f y el resultado es ruteado a la entrada del registro r dest. Se asume que el
periodo de la señal de reloj es lo suficientemente grande como para acomodar
el retardo de propagación de los registros y del circuito combinacional.

3. En el siguiente flanco de subida de la señal de reloj, el resultado es almacenado


en el registro r dest.

7.2.2. Programa RT

Como punto de partida para el diseño de la FSMD, se describe su operación


como un algoritmo en notación RT. Este algoritmo se denomina programa RT.

Aquellas operaciones que pueden realizarse simultáneamente, pueden definirse en


un mismo paso del programa RT. Las operaciones que deben ejecutarse consecutiva-
mente, deben forzosamente definirse en pasos consecutivos. Los pasos del algoritmo
irán ejecutándose en el circuito secuencial en ciclos consecutivos de la señal de reloj.

Las operaciones que se realizan en un mismo paso del programa RT serán tra-
ducidas a sentencias VHDL que se ejecutarán concurrentemente. Así pues, varias
operaciones pueden realizarse en un mismo paso del programa RT si pueden ser
ejecutadas unas independientemente de las otras. Es decir, si no existe dependencia
entre los datos y los recursos involucrados en dichas operaciones.

Pueden incluirse diferentes tipos de operaciones en los pasos del programa RT,
tales como asignaciones a variables, operaciones aritméticas o lógicas, acciones con-
dicionales, llamadas a subrutinas y funciones, y bucles for y while.

Los bucles for y while pueden constituir un único paso del programa RT,
cuando las acciones del cuerpo del bucle puedan ejecutarse concurrentemente. Por
el contrario, si las operaciones del cuerpo del bucle deben ejecutarse en varios pasos
consecutivos, entonces el cuerpo del bucle se estructurará en varios pasos.

Es posible escribir varios programas RT que realicen el mismo algoritmo. Si se


escribe un programa RT que tenga un número menor de pasos, entonces el circuito
resultante será más eficiente.

520
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

Como ejemplo de construcción de un programa RT, consideremos el diseño de


un circuito que, dado un número de entrada (n), calcula su factorial (fact). Un
programa RT que describe la operación de este circuito es el siguiente.

Paso O. fact<15:0> <- 1;


fin <- O;
num <- 2;
Paso 1. if (num <= n) then begin
fact <- fact * num;
num <- num + 1 ;
go to Paso 1;
end 1* if *1
Paso 2. fin <- 1;

Al decidir qué operaciones se engloban en un mismo paso, debe tenerse en cuenta


que todas las sentencias RT de un mismo paso serán operaciones que el circuito
realizará concurrentemente.

Una implicación de este hecho es que si en un mismo paso del programa RT se


asigna valor a una variable y se usa esa variable, entonces se está usando el valor
antiguo de la variable y no el valor actualizado de la misma. Por ejemplo, supongamos
que el Paso 1 del programa RT anterior se sustituye por:

Paso 1. if (num <= n) then begin


num <- num + 1;
fact <- fact * num;
go to Paso 1;
end 1* if *1

La diferencia introducida en el Paso 1 es que ahora se ha escrito la sentencia que


calcula el nuevo valor de num antes que la sentencia que calcula el nuevo valor de
f act. Es decir, se ha intercambiado el orden de estas dos sentencias

num <- num + 1;


fact <- fact * num;

Sin embargo, ambas versiones del Paso 1 son equivalentes, ya que en la sentencia

fact <- fact * num;

se utiliza el valor antiguo de num. Esto es debido a que las sentencias de un paso se
ejecutan concurrentemente y por ello el orden en que están escritas es indiferente.

521
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

7.3. MÁQUINAS DE ESTADO FINITO CON CAMINO DE DATOS

En esta sección de describen algunos aspectos de la síntesis de los programas


RT. En particular, se describen los fundamentos de las máquinas de estado finito
con camino de datos (FSMD), que son circuitos secuenciales síncronos empleados
para sintetizar los programas RT. Como se ha indicado, las FSMD constan de dos
partes (véase la Figura 7.1): el camino de los datos y la lógica de control.

7.3.1. Múltiples operaciones RT y camino de datos

Un programa RT consiste en varios pasos y, en general, un determinado regis-


tro puede ser cargado con diferentes datos en diferentes pasos del algoritmo. Por
ejemplo, el registro r 1 puede ser cargado con el valor O en el paso de inicialización,
seguidamente puede sumarse su contenido al del registro r 2 en un paso de suma, y
finalmente puede incrementarse su contenido. Así pues, hay tres operaciones RT que
usan el registro r 1 como registro destino:

rl ~ rl + r2;
r1 ~ r1 + 1;

1-----~d q

.-------1:>
ft

Sefiales de control -____;>~,------J d q

clk - - - - - - - - - ó - - 0
f2

Figura 7.2: Tres operaciones RT cuyo destino es el registro r 1 .

Debido a que hay varias posibilidades, es necesario emplear un circuito multi-


plexor para enrutar el valor deseado hasta la entrada del registro r 1 . El diagrama
de bloques se muestra en la Figura 7.2. Se puede escoger la operación RT deseada
asignando el valor adecuado a la señal de selección del multiplexor.

522
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

7.3.2. Lógica de control mediante FSM

Como hemos indicado anteriormente, el camino de datos realiza todas las opera-
ciones RT del algoritmo. Ahora bien, es necesario disponer de un mecanismo para
especificar cuándo y qué operaciones RT deben realizarse. Esta es la finalidad de la
lógica de control.

La lógica de control (también llamada camino de control) se usa para determinar


el orden de las operaciones RT y para realizar selectivamente ciertas operaciones RT
dependiendo del valor de comandos externos o de señales de status. Típicamente, la
lógica de control se implementa mediante una máquina de estado finito (FSM). Los
motivos son principalmente los siguientes:

- La transición entre los estados de una FSM se produce en los instantes en que
se produce el flanco de subida de la señal de reloj. Puesto que el instante en
que se produce la ejecución de las operaciones RT está también dictado por la
señal de reloj, puede asociarse la operación RT a un estado de la FSM.

- En una FSM las transiciones entre los estados se producen siguiendo una
secuencia bien definida. Así pues, la FSM puede emplearse para definir la
secuencia en la cual deben ejecutarse la operaciones RT.

- En función del valor de sus señales de entrada, la FSM puede realizar unas u
otras transiciones entre estados, con lo cual la FSM permite realizar bifurca-
ciones en la secuencia de operaciones RT. Esto posibilita la implementación
de las sentencias if y de los bucles que pueda haber en el programa RT.

Puesto que se asocia la operación RT con un estado de la FSM, puede extenderse


la definición de la FSM indicando la operación RT que debe realizarse en cada estado.
Esta definición extendida de la FSM constituye la definición de la FSMD: en los arcos
de transición entre estados, o en los estados, además de especificar la salida de la
FSM se especifica qué operación RT debe realizarse.

7.3.3. Diagrama de bloques básico de la FSMD

En la Figura 7.3 se muestra el diagrama de bloques conceptual de la FSMD.


Puede observarse que se encuentra dividido en dos partes: el camino de datos y la
lógica de control.

523
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

CAMINO DE DATOS
~-------------------------~------------------------,

D atos de
entrada
l Conexionado
de
H Unidades ____.
Conexionado
de
____. d q
Registros
1
Datos d e
salida ..
-,

..,. enrutamiento funcionales enrutamiento


de datos
t>
------ _____________________________f ____________ _
Señal de status interna 1 Señal de control

Comandos
externos y
l..------.
Lócricapara

obtener el r--t
d Lógica para
q 1--o-~,obtener la
Señal de
status
externa
...
-----+--o-~ siguiente estado Registro ~ salida
de estado
~

LÓGICA DE CONTROL

Figura 7.3: Diagrama de bloques de una FSMD.

El camzno de datos puede realizar todas las operaciones RT necesarias. Está


compuesto de las tres partes siguientes:

- Registros de datos, en los que se almacenan los resultados intermedios de los


cálculos.

- Unidades funcionales, que realizan las funciones (!) especificadas en las ope-
raciones RT. Entre las unidades funcionales típicas se encuentran un sumador,
un restador, un circuito incrementador y uno decrementador, etc.

- El conexionado de enrutamiento, que conecta por una parte las salidas de los
registros con las entradas de las unidades funcionales, y por otra las resul-
tados obtenidos de las unidades funcionales con las entradas a los registros.
Normalmente el enrutamiento se realiza mediante multiplexores.

El camino de datos normalmente tiene las siguientes señales de entrada y salida:

- Los datos de entrada, que son los datos externos que debe procesar la FSMD.

- Los datos de salida, que son los resultados del programa que implementa la
FSMD.

524
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

- La señal de control, que especifica qué operación RT debe ejecutarse. Esta


señal es generada por la lógica de control.

- La señal de status interna es una señal generada por el camino de datos cuya
finalidad es informar a la lógica de control de que se ha satisfecho cierta
condición, por ejemplo, que el contenido de un registro es cero. Esta señal es
usada por la lógica de control para determinar la secuencia futura de acciones.

La lógica de control es una FSM y como tal contiene un registro de estado, la


lógica para el cálculo del siguiente estado y la lógica para el cálculo de la salida. La
lógica de control normalmente tiene las siguientes señales de entrada y salida:

- Los comandos externos, que son señales externas que señalan que deben rea-
lizarse determinadas acciones, por ejemplo, que comience la operación de la
FSMD.

- La señal de status interna, que proviene del camino de datos, y que es empleada
para determinar el siguiente estado.

- La señal de control, que es una señal de salida de la FSM cuya finalidad es


controlar la operación del camino de datos.

- La señal de status externa, que es una señal de salida de la FSM cuya finalidad
es indicar cuál es el estado de la operación de la máquina, por ejemplo, si se
encuentra libre u ocupada.

Además de estas señales, los registros del camino de datos y de la lógica de


control están conectados a la misma señal de reloj y opcionalmente a una señal de
reset asíncrono.

Obsérvese que el camino de datos tiene la forma de un circuito secuencial y que


la lógica de control es una FSM, y por tanto, es otro circuito secuencial. Por tanto,
puede considerarse que la FSMD es la combinación de dos circuitos secuenciales,
ambos sincronizados por la misma señal de reloj.

7.4. DESCRIPCIÓN DEL PROGRAMA RT USANDO VHDL

Aunque el programa RT puede ser escrito en formato libre y posteriormente


traducido a VHDL, suelen ofrecerse algunas recomendaciones acerca de su estructu-
ra, con el fin de facilitar su posterior traducción a VHDL sintetizable. Una posible
estructura del programa RT es la mostrada a continuación.

525
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Paso o. Inicializa variables;


while (true) do begin
Paso 1. Paso 1 del algoritmo;
Paso 2. Paso 2 del algoritmo;

Paso k. for i <-Oto max-1 do begin ...

Paso m. Llamada a la función FUNCION_1;

Paso n. Paso n del algoritmo;


end 1* de while *1
En esta "plantilla" de programa RT hay un paso de inicialización (Paso O), seguido
de un bucle while infinito, dentro del cual se definen una serie de pasos. Este
programa RT puede traducirse a VHDL aplicando la plantilla mostrada en el Código
VHDL 7.1.

Obsérvese que se define una señal, llamada state, cuyo valor indica qué paso del
algoritmo se está ejecutando en cada momento. En el Código VHDL 7.1 esta señal
es de tipo integer, si bien puede ser de otro tipo.

El seudocódigo es traducido esencialmente a un bloque process, que es sensible


a la señal de reset (reset_n) y a la señal de reloj (clk). El circuito descrito por la
plantilla tiene reset asíncrono activado LOW. Las acciones de reset son las definidas
en el Paso O del seudocódigo. Además, en la operación de reset se asigna a la señal
state su valor inicial.

Cada vez que se produce un flanco de subida de la señal de reloj se ejecutan dos
sentencias concurrentes. La primera de ellas incrementa el valor de la señal state.
La otra es un bloque case, que ejecuta las sentencias del correspondiente paso del
seudocódigo.

Obsérvese que el bucle for del seudocódigo, mostrado en la parte de la izquierda,


se ha traducido de la forma mostrada en la parte de la derecha:

Paso k. for i <- O to max-1 do begin when k =>


i <= O; -- Inicialización
Paso k+1. Paso 1 dentro del bucle when k + 1 =>
. .. --Paso 1 dentro del bucle

Paso k+x. Paso x dentro del bucle when k + x =>


. .. --Paso x dentro del bucle
if (i < max) then
state <= k + 1;
end if;
end 1* del bucle for *1 i <= i + 1;

526
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

package DEFS is
constant FUNCION 1 : integer := z; -- z es un número de estado que define unívocamente
-- esta función. D ebe satisfa cerse: z > m + x + 1
end package DEFS;

architecture ...
signal state : integer; -- Contador que indica el paso del seudocodigo ejecutandose

seudocodigo : process ( reset_n, clk ) is


begin
if ( reset_n = 'O') then
-- Operaciones de inicialización (Paso O del seudocódigo)
state <= 1; -- Inicializa state
elsif rising_edge( clk ) then
state <= state + 1; -- Incrementa state
case ( state ) is -- state codifica los pasos del algoritmo
when 1 =>
. . . -- Operaciones del Paso 1 del seudocodigo
when 2 =>
. . . -- Operaciones del Paso 2 del seudocodigo

when k=>
i <= O; -- Inicialización del bucle for
when k+ 1 = >
. . . -- Primer paso dentro del bucle for
when k+ 2 =>
. . . -- Segundo paso dentro del bucle for

when k+ x = >
. . . -- Último paso dentro del bucle for
if (i < max) then
state <= k+1;
end if;
i <= i + 1;

when m + x = > -- Se supone que FUNCION_1 es llamada aquí


ret_state <= m + x + 1; -- Return state
state <= FUNCION_1; -- Va a la FUNCION_1
when m + x + 1 = >

when FUNCION_1 =>


-- Operaciones del Paso 1 de la función FUNCION_1
when FUNCION_1 + 1 =>
-- Operaciones del Paso 2 de la función FUNCION_1

when FUNCION_1 + y = > -- Último paso de FUNCION_1


state <= ret_state; -- return al procedimiento que hace la llamada

when others => -- Paso n del seudocodigo


state < =O;
end case;
end if; -- de rising_edge( clk)
end process seudocodigo;
end architecture ... ;

Código VHDL 7.1: Codificación en VHDL de un algoritmo RT.

527
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

7.5. CIRCUITO DETECTOR DE SECUENCIA

Para ilustrar cómo puede realizarse una descripción VHDL de alto nivel a partir
de una descripción algorítmica RT, consideraremos nuevamente el diseño de un
circuito detector de patrones en una secuencia de bits.

Supongamos que deseamos diseñar un circuito para la detección de la siguiente


secuencia de entrada serie: O111 111 O (esta secuencia de emplea frecuentemente
como marcadora de final de paquete). El siguiente programa RT permite resolver
este problema:

Paso O. prev_data <- 1111 1111; 1* Almacena 8 bits anteriores *1


Paso 1. while (true) do 1* Se repite indefinidamente *1
data_in <- siguiente dato de entrada;
prev_data <- prev_data << 1 1* Desplazamiento izqda *1
prev_data[O] <- data_in; 1* Se almacena data_in en LSB *1
if (prev_data == 0111 1110) then
detectado <- 1; 1* Secuencia detectada *1
el se
detectado <- O; 1* Secuencia no detectada *1
end while

El código VHDL del circuito detector de secuencia puede escribirse directamente


basándose en el algoritmo anterior. En el Código VHDL 7.2 se muestran dos versiones
de la descripción del circuito: una en la cual prev _data es una variable y otra en la
cual es una señal. Ambas descripciones de la architecture son igualmente válidas.

La única diferencia entre la descripción en VHDL y la descripción algorítmica,


aparte del uso de la sintaxis de VHDL, es que en el código VHDL no se ha incluido
la sentencia

data_in <- siguiente dato de entrada;

En el código VHDL no es necesario realizar la asignación del siguiente bit de la


secuencia de entrada a data_in, porque se supone que los bits de datos entran en
sincronía con el flanco de subida de la señal de reloj.

La sentencia

prev_data <= (prev_data(6 downto O) & 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 desplazamiento

528
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

-- Circuito detector de secuencia 0111 111 O


-- Pichero: det ector._sec. vhd
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 sec1 of detector sec is
begin
process (reset_n, clk) is
variable prev_data : unsigned (7 downto O);
begin
if (reset_n = 'O') then
prev_data := B"1111_1111";
elsif rising_edge( clk) then
prev _data := prev _data sll 1;
prev_data(O) := data_in;
if (prev_data = B"0111_1110") then
detectado <= '1 ';
el se
detectado <= '0';
end if;
end if;
end process;
end architecture detector_sec1;
architecture detector _sec2 of detector _sec is
signal prev_data : unsigned (7 downto O);
begin
process (reset_n, clk) is
begin
if (reset_n = 'O') then
prev_data <= B"1111_1111";
elsif rising_edge( clk) then
prev_data <= (prev_data(6 downto o) & data_in);
if ((prev_data(6 downto O) & data_in) = B"0111_1110") then
detectado <= '1 ';
else
detectado <= '0';
end if;
end if;
end process;
end architecture detector _sec2;

Código VHDL 7.2: Dos diseños de un circuito detector de la secuencia 0111 1110.

529
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

se ejecuta concurrentemente con la sentencia if que comprueba la igualdad con


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

7.6. CONTROL DE UNA MÁQUINA EXPENDEDORA

Se plantea el problema de diseñar un circuito de control para una máquina


automática expendedora de dos tipos de bebida: botellas de agua y latas de refresco.
La máquina sólo acepta monedas de 10 céntimos, 20 céntimos y 50 céntimos. El precio
de una botella de agua es 70 céntimos y el de una lata de refresco es 60 céntimos.

Además de introducir las monedas, el cliente puede pulsar uno de los botones
de selección de producto (agua y refresco). También puede pulsar el botón de
devolución, con el fin de obtener el dinero que ha introducido en la máquina. En la
Tabla 7.2 se resumen las entradas al circuito descritas anteriormente. Se supone que
dos de estas entradas al circuito no pueden estar activas simultáneamente.

Tabla 7.2: Algunas de las entradas al circuito.

Entrada Descripción
m10 Introducida moneda de 10 céntimos.
m20 Introducida moneda de 20 céntimos.
m50 Introducida moneda de 50 céntimos.
devolución Solicitud de devolución del dinero.
selec_agua Selección de producto: una botella de agua.
selec_refresco Selección de producto: una lata de refresco.

En la Tabla 7.3 se muestran algunas de las señales de salida del circuito. Las
señales dispensa_refresco, dispensa_aguay devuelve_cambio se usan para controlar
la entrega al cliente de una lata de refresco, una botella de agua, y del dinero que
ha introducido en la máquina y aun no ha gastado (es decir, del cambio).

La señal beep sirve para indicar al cliente que no ha introducido dinero suficiente
para comprar el producto que ha seleccionado. Por tanto, esta señal se activa cuando
el cliente selecciona un producto sin haber introducido el dinero suficiente para
comprarlo.

En la señal total, de 5 bits, se lleva la cuenta del dinero que ha introducido el


cliente en la máquina y que todavía no ha gastado.

530
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

Tabla 7.3: Algunas de las señales de salida del circuito.

Señal Descripción
total Dinero total introducido por el cliente.
beep Se activa cuando el cliente selecciona el producto
sin haber introducido dinero suficiente.
devuelve_moneda Se activa para devolver la última moneda intro-
ducida, si esta moneda hace que se exceda el
dinero total máximo que acepta la máquina.
dispensa_refresco Dispensa una lata de refresco.
dispensa_ agua Dispensa una botella de agua.
devuelve_ cambio Devuelve el dinero restante.

La señal devuel ve_moneda se activa si el cliente introduce más dinero del que
puede ser almacenado en la señal total. En este caso, se devuelve la última moneda
introducida por el cliente.

7.6.1. Protocolo de handshaking

El circuito de control de la máquina expendedora se diseñará usando un protocolo


de handshaking de cuatro fases. En este circuito, la interfaz de handshaking se
establece entre el cliente, que realiza una selección, y la máquina, que responde
a la selección del cliente.

El protocolo handshaking de cuatro fases permite comunicar asíncronamente dos


circuitos, que llamaremos A y B. Los dos circuitos están comunicados mediante un
bus, por el que circulan los datos que se desean transmitir desde A a B, y por
dos señales, req (petición) y ack (recepción), que se emplean para implementar el
protocolo, el cual funciona de la manera siguiente:

l. El circuito A comprueba si ack=' O'. En caso afirmativo, pone en el bus el dato


que quiere transmitir al circuito B y cambia el valor de la señal req de 'O' a
'1'.

2. El circuito B, al detectar que req pasa de valer 'O' a valer '1 ', carga el dato
(por ejemplo, en latches), lo procesa y entonces cambia el valor de la señal ack
de 'O' a '1'. Con ello indica al circuito A que ha recibido los datos y los ha
procesado.

3. El circuito A espera hasta que detecta ack=' 1 ', lo cual indica que los datos
han sido recibidos y procesados, y entonces el circuito A pone req=' O'.

531
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

4. Al ver el circuito B que el circuito A ha puesto req=' O', entonces pone ack=' O',
quedando así preparado para la recepción del siguiente dato.

5. Finalmente, el circuito A debe esperar hasta que ack=' O' para enviar el si-
guiente dato y poner de nuevo req=' 1 ' (que es nuevamente el primer paso del
protocolo).

7.6.2. Descripción del algoritmo

A continuación, se muestra el algoritmo que debe implementar el circuito de la


máquina expendedora. En el algoritmo se representa el dinero en unidades de 10
céntimos, ya que todas las entradas, salidas y cálculos internos pueden realizarse
usando múltiplos de 10 céntimos. Esto permite usar menos bits en el registro total.

Todas las selecciones del cliente (agua, refresco o devolución del dinero), así como
la entrada de monedas (10 céntimos, 20 céntimos y 50 céntimos), están codificadas
en una única señal de entrada al circuito, llamada data, de 3 bits. La codificación es
la mostrada en la Tabla 7.4. Obsérvese que la codificación de las monedas coincide
con su valor en múltiplos de 10 céntimos. Esta codificación simplifica el algoritmo.

Tabla 7.4: Codificación de la señal data.

Entrada data
miO "001"
m20 "010"
m50 "101"
devolución "100"
selec_agua "011"
selec_refresco ''000"

Al observar req=' 1', el circuito decodifica la señal de 3 bits data para determinar
la acción solicitada, realiza las acciones solicitadas y a continuación, usando la señal
ack, notifica que ya ha realizado la acción solicitada.

7.6.3. Diseño del circuito de control

El diseño del circuito de control de la máquina expendedora puede realizarse


siguiendo la metodología explicada en la Sección 7.4. La definición de las constantes
se agrupa en un package, tal como se muestra en el Código VHDL 7.3.

532
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

Algoritmo del circuito de la máquina expendedora:

Paso O. total<4:0> <- O; ack <- O;


beep <- O; devuelve_moneda <- O;
dispensa_refresco <- O; dispensa_agua <- O;
devuelve_cambio <- O; MAX <- 31;

while (true) do begin

Paso 1. wait until (req=1);

Paso 2. case (data) is begin


m10, m20 or m50:
if (total + data > MAX) then
devuelve_moneda <- 1;
el se
total <- total + data;
end if;
selec_refresco:
if (total < 6) then
beep <- 1;
el se
total <- total - 6;
dispensa_refresco <- 1;
end if;
selec_agua:
if (total < 7) then
beep <- 1;
el se
total <- total - 7;
dispensa_agua <- 1;
end if;
devolucion:
devuelve cambio <- 1;
total <- O;
end 1* de case (data) *1

Paso 3. ack <- 1 until (req=O);

Paso 4. ack <- O; beep <- O;


devuelve_moneda <- O; dispensa_refresco <- O;
dispensa_agua <- O; devuelve_cambio <- O;

end 1* del bucle while *1

533
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Las constantes TOTAL_BITS y DATA_BITS representan el número de bits del registro


total y el número de bits de la señal data, respectivamente. También se define una
constante por cada uno de los valores que puede tener la señal data. Este package
se usará al diseñar el circuito y al programar su banco de pruebas.

-- Definición de las constantes


-- Fich ero: maqExpend_defs. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
package maqExpend_defs is
constant TOTAL_BITS : integer := 5; -- Bits del registro total
constant MAX : integer := 31; -- Num. máx. en el registro total
constant ESTADO_BITS : integer := 2; -- Bits del estado de la máquina
constant DATA_BITS : integer := 3; -- Bits de la señal data
constant DATA_m10 : unsigned(DATA_BITS-1 downto O) := 11
001 11 ;
constant DATA_m20 : unsigned(DATA_BITS-1 downto O) := 11
010 11 ;
constant DATA_m50 : unsigned(DATA_BITS-1 downto O) := 11
101 11 ;
constant DATA_devolucion : unsigned(DATA_BITS-1 downto O) := 11
100 11 ;
constant DATA_selec_agua : unsigned(DATA_BITS-1 downto O) := 11
011";
constant DATA_selec_refresco : unsigned(DATA_BITS-1 downto O) := 11
000 11 ;
end package maqExpend_defs;

Código VHDL 7.3: Package con la definición de las constantes del circuito de la máquina
expendedora.

El diseño del circuito de control de la máquina expendedora se muestra en el


Código VHDL 7.4 y 7.5. La señal de entrada data está codificada tal como se indica
en la Tabla 7.4. La señal reset_n es una señal de reset asíncrono activada LOW.

Obsérvese que las operaciones del Paso O del seudocódigo se ejecutan cuando
(reset_n = 'O'). Asimismo, en esta parte del código se inicializa la señal estado,
que representa el estado actual en el que se encuentra la máquina.

En cada flanco de subida de la señal de reloj, un bloque case comprueba el valor


del estado (señal estado). Las operaciones del Paso 1 del seudocódigo son ejecutadas
cuando estado=O. Las operaciones del Paso 2 son ejecutadas cuando estado=!.
Continuando de esta manera, las operaciones del Paso k + 1 del seudocódigo son
ejecutadas cuando estado=k.

534
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

-- Circuito de la máquina expendedora


-- Fichero: maquinaExpend. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
use work . maqExpend_def s. all;
entity maquinaExpend is
port ( total : out unsigned(TDTAL_BITS-1 downto O);
ack : out std_logic;
beep : out std_logic;
devuelve_moneda : out std_logic;
dispensa_refresco : out std_logic;
dispensa_ agua : out std_logic;
devuelve_ cambio : out std_logic;
req : in std_logic;
data : in . unsigned(DATA_BITS-1 downto O);
reset_n : in std_logic; -- Reset asíncrono activado LOW
el k : in std_logic ) ;
end entity maquinaExpend;
architecture maquinaExpend of maquinaExpend is
signal total_int : unsigned(TDTAL_BITS-1 downto O);
signa} estado : unsigned(ESTADO_BITS-1 downto O);

begin
total <= total_int;

algoritmo : process (reset_n, clk) is


begin
if (reset_n = 'O') then
total_int <= (others = > 'O'); -- Inicializa el registro
ack <= '0';
beep <= '0';
devuel ve_moneda <= 'O';
dispensa_refresco <= 'O';
dispensa_agua <= '0';
devuelve_ cambio <= 'O';
estado <= "00"; --Estado inicial
elsif rising_edge( clk) then
estado <= estado +1; -- Actualiza estado para el siguiente pulso de reloj
case estado is -- Los pasos del algoritmo se codifican como estados
when "00" =>
if (req = '0') then --Espera hasta que (req='l')
estado <= "00";
end if;

Código VHDL 7.4: Entity y comienzo de la architecture del circuito de control de la máquina
expendedora.

535
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Continuación del diseño del circuito de la máquina expendedora


-- Fichero: maquinaExpend. vhd

when "01" = >


case (data) is
when DATA_m10 1 DATA_m20 1 DATA_m50 = >
if ( (total_int + data) > MAX ) then
devuelve_moneda <= '1';
el se
total_int <= total_int + data;
end if;
when DATA_selec_refresco =>
if (total_int < 6) then
beep <= '1';
else
total_int <= total_int - 6;
dispensa_refresco <= '1';
end if;
when DATA_selec_agua =>
if (total_int < 7) then
beep <= '1';
else
total_int <= total_int - 7;
dispensa_agua <= '1';
end if;
when DATA_devolucion =>
total_int <= (others = > '0');
devuelve_cambio <= '1';
w hen others = >
assert false report "Caso indefinido.";
end case;
when "10" =>
ack <= '1';
if (req = '1 ') then -- Espera hasta que {req= 'O')
estado <= "10";
end if;
when others =>
ack <= '0';
beep <= '0';
devuel ve_moneda <= 'O';
dispensa_refresco <= 'O';
dispensa_agua <= '0';
devuelve_cambio <= '0';
end case; -- case estado
end if;
end process algoritmo;
end architecture maquinaExpend;

Código VHDL 7.5: Continuación del diseño del circuito de control de la máquina expendedora.

536
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

7.6.4. Programación del banco de pruebas

El Código VHDL 7.6 y 7.7 es un banco de pruebas para el circuito de control de


la máquina expendedora. Para comprobar el correcto funcionamiento del circuito,
se inspeccionarán visualmente las formas de onda obtenidas de la simulación. Se
emplea una señal de reloj con un periodo de 100 ns. En el entorno de simulación, se
fija el tiempo final de la simulación en 5100 ns. El mensaje "Final de la simulación"
se obtiene en el instante 5025 ns. Se propone como ejercicio realizar la simulación
del banco de pruebas e interpretar las formas de onda obtenidas.

537
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas para el circuito de la máquina expendedora


-- Fichero: bp_maquinaExpend.vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE.numeric_std.all;
use work. maqExpend_defs. all;

entity bp_maquinaExpend is
end entity bp_maquinaExpend;

architecture bp_maquinaExpend of bp_maquinaExpend is

component maquinaExpend is
port ( total : out unsigned(TOTAL_BITS-1 downto O);
ack : out std_logic;
beep : out std_logic;
devuel ve_moneda : out std_logic;
dispensa_refresco : out std_logic;
dispensa_agua : out std_logic;
devuelve_cambio : out std_logic;
req : in std_logic;
data : in unsigned(DATA_BITS-1 downto O);
reset_n : in std_logic;
el k : in std_logic ) ;
end component maquinaExpend;

constant PERIODO : time := 100 ns; -- Periodo señal de Teloj

signal total : unsigned(TOTAL_BITS-1 downto O);


signal ack : std_logic;
signal beep : std_logic;
signal devuelve_moneda : std_logic;
signal dispensa_refresco : std_logic;
signal dispensa_ agua : std_logic;
signal devuelve_ cambio : std_logic;
signal req : std_logic;
signal data : unsigned(DATA_BITS-1 downto O);
signal reset n : std_logic;
signal clk : std_logic;

begin

uut : maquinaExpend port


map ( total, ack ,beep, devuelve_moneda,
dispensa_refresco, dispensa_agua,
devuelve_cambio, req, data, reset_n, clk );

-- Crea un pulso de reset


reset_n <= '1',
'O' after (PERIOD0*3/ 4),
'1' after (2*PERIODO);

Código VHDL 7.6: Banco de pruebas del circuito de control de la máquina expendedora.

538
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

-- Continuación del banco de pruebas. Fichero: bp_maquinaExpend. vhd


-- Señal de reloj
clock : process is
begin
clk <= 'O'; wait for (PERIOD0/2);
clk <= '1'; wait for (PERIOD0/2);
end process clock;
-- Vectores de test
generar_vectores: process is
begin
req <= '0'; data <= (others = > '0');
wait for (PERIOD0*3); wait for (PERIOD0/4);
req <= '1 '; data <= DATA_m50; -- Introdu ce moneda de 50 cent.
wait for (PERIOD0*5);
req <= 'O'; wait for (PERIOD0*2);

req <= '1 '; data <= DATA_m20; -- Introdv,ce moneda de 20 cent.
wait for (PERIOD0*3);
req <= 'O'; wait for (PERIOD0*2);

req <= '1'; data <= DATA_selec_agua; -- Selecciona agua


wait for (PERIOD0*3);
req <= '0'; wait for (PERIOD0*2);

req <= '1'; data <= DATA_m50; -- Introdu ce moneda de 50 cent.


wait for (PERIOD0*3);
req <= '0'; wait for (PERIOD0*2);

req <= '1 '; data <= DATA_m10; -- Introdu ce moneda de 10 cent.
wait for (PERIOD0*3);
req <= 'O'; wait for (PERIOD0*2);

req <= '1 '; data <= DATA_selec_refresco; -- Selecciona refresco


wait for (PERIOD0*3);
req <= 'O'; wait for (PERIOD0*2);

req <= '1'; data <= DATA_m20; -- Introduce moneda de 20 cent.


wait for (PERIOD0*3);
req <= 'O'; wait for (PERIOD0*2);

req <= '1'; data <= DATA_selec_refresco; -- Selecciona refresco


wait for (PERIOD0*3);
req <= '0'; wait for (PERIOD0*2);

req <= '1'; data <= DATA_devolucion; -- Devolución del dinero


wait for (PERIOD0*3);
req <= 'O'; wait for (PERIOD0*2);

report "Final de la simulación"; wait;


end process generar_ vectores;
end architecture bp_maquinaExpend;

Código VHDL 7.7: Continuación del banco de pruebas del circuito de la máquina expendedora.

539
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

7.7. LECTURAS RECOMENDADAS

El Capítulo 11 de (Chu 2006) describe el diseño de circuitos siguiendo la meto-


dología RT, mediante el empleo de diagramas ASMD (diagrama ASM con camino
de datos), y en el Capítulo 12 se desarrollan varios casos de estudio.

El Capítulo 5 de (Lee 2006) proporciona información adicional acerca del diseño


aplicando la metodología RT, así como ejemplos de diseño detallados, como es el
caso de un controlador LCD.

En (Perry 2002) puede encontrarse un ejemplo de diseño de relativa compleji-


dad usando VHDL: una pequeña CPU, compuesta de un array de registros, una
AL U, varios registros (de desplazamiento, contador de programa, de dirección y de
instrucción), un comparador y una unidad de control.

También en (Lee 2006) pueden encontrarse diseños completos de relativa com-


plejidad: un analizador de protocolo USB, varias unidades aritméticas rápidas y un
microprocesador RISC.

540
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

7.8. EJERCICIOS DE AUTOCOMPROBACIÓN

Ejercicio 7.1

Escriba el programa RT correspondiente al diseño de un termostato digital:


un circuito que enciende y apaga un sistema de aire acondicionado y un sistema
calentador, con el fin de mantener la temperatura de una habitación dentro de un
cierto rango determinado de valores.

Supongamos que el circuito termostato tiene un registro de 8 bits llamado temp ,


que almacena la temperatura a la que se encuentra actualmente la habitación, y
otro registro de 8 bits llamado consigna, que almacena el valor de consigna para la
temperatura de la habitación. El valor del registro consigna cambia cuando el usuario
ajusta el valor deseado de la temperatura. El valor almacenado en el registro temp
va refrescándose con las medidas tomadas de la temperatura de la habitación. La
actualización de los valores de estos dos registros no es tarea del termostato.

El circuito termostato tiene dos señales digitales de salida, calentador _on y


ac_on, que actúan sobre los sistemas de calefacción y aire acondicionado, respec-
tivamente. Cuando la señal calentador_on se pone a '1', se enciende el sistema
calentador. Cuando se pone a 'O', se apaga. Igualmente, cuando la señal ac_on se
pone a '1', se enciende el sistema de aire acondicionado. Cuando se pone a 'O', se
apaga. El termostato usa estas dos señales para actuar sobre el sistema calentador
y de aire acondicionado.

El funcionamiento del circuito termostato debe ser el siguiente. El controlador


pone a '1' la correspondiente señal cuando la diferencia entre la temperatura de la
habitación y la temperatura de consigna excede de un determinado valor umbral,
umbral, que es una constante de diseño. Es decir, cuando la temperatura de la
habitación es mayor que el valor de consigna más el valor umbral, el controlador
enciende el aire acondicionado. Igualmente, cuando la temperatura de la habitación
es menor que el valor de consigna menos el umbral, el controlador enciende el sistema
calentador.

Por otra parte, si cuando está encendido el sistema calefactor la temperatura de


la habitación supera la temperatura de consigna, entonces el termostato debe apagar
el sistema calefactor. Igualmente, si el sistema de aire acondicionado está encendido
y la temperatura de la habitación se hace inferior al valor de consigna, entonces el
termostato debe apagar el sistema de aire acondicionado.

541
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 7.2

Escriba un programa RT que describa la operación de multiplicación de dos


números binarios sin signo de 8 bits. Emplee 3 registros de desplazamiento (A,
B, P) y un contador descendente ( count). Los registros de desplazamiento A y B,
de 8 bits, almacenan los operandos (multiplicando y multiplicador). El registro de
desplazamiento P, de 16 bits, almacena el resultado de los cálculos intermedios y el
resultado final del producto.

Indique el número de estados que deberá tener la lógica de control del circuito
FSMD resultante. Asimismo, indique el número de flip-flops D que resultarán de la
síntesis de la lógica de control.

Ejercicio 7.3

Diseñe en VHDL un circuito que, dados dos números de entrada de 4 bits (opA
y opB), calcule su máximo común divisor empleando el algoritmo de Euclides. El
circuito debe tener una señal reset asíncrona y una señal de salida, fin, para indicar
que se ha obtenido el máximo común divisor de los dos números.

El algoritmo de Euclides del cálculo del máximo común divisor es el siguiente:

Paso O. a <- opA;


b <- opB;
fin <- O;
Paso 1. if (b=a) then begin
result <- b;
else if(b > a) then begin
b <- (b- a);
goto Paso 1
else if (b < a) then begin
a<- (a- b);
go to Paso 1
end 1* if *1
Paso 2. fin<- 1;

542
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

Ejercicio 7.4

Diseñe en VHDL un circuito que calcule la media aritmética de 4 números de


entrada de 4 bits. El circuito debe tener una señal reset asíncrona y una señal de
salida, fin, para indicar que se ha obtenido el resultado.

Ejercicio 7.5

En los circuitos lógicos digitales se emplean diferentes códigos binarios. En oca-


siones, dos circuitos que usan diferente código necesitan comunicarse entre sí, siendo
preciso emplear otro circuito para realizar la conversión de un código a otro. Como
ejemplo de este tipo de circuitos conversores de código, en este ejercicio se propone
realizar el diseño de un conversor para números en código BCD de longitud fija a
código binario.

En el código BCD ( binary-coded decimal), cada grupo de cuatro bits consecutivos


es convertido a un dígito decimal. El número completo es interpretado como un
número decimal compuesto por estos dígitos decimales. Por ejemplo, 0101 1001BcD
es interpretado como 59 10 , ya que los primeros cuatro bits (0101) corresponden a
un 5 decimal y los últimos cuatro bits (1001) corresponden a un 9 decimal. El
equivalente binario al número 59 10 es 00111011 2 . El circuito descrito en esta sección
debe realizar la conversión de 0101 1001BcD a 0011 1011 2 .

El algoritmo siguiente realiza la conversión de código BCD a binario:

Paso 1. bcd <- bcd_data_input;


bin <- O (mismo número de bits que bcd)
Paso 2. For count <- 1 to bcd_bit_size do begin
Paso 2a. {bcd,bin} <- {bcd,bin} >> 1;
Paso 2b. For cada secuencia de 4 bits en bcd do
If secuencia de 4 bits > 7 then
restar 3 de esa secuencia de 4 bits;
end //del bucle For
Paso 3. bin contiene el número convertido

Diseñe empleando VHDL un circuito cuyo comportamiento sea el descrito en el


algoritmo anterior. A continuación, programe un banco de pruebas para testear el
circuito diseñado. Considere que el número BCD tiene 16 bits, es decir, suponga que
bcd_bi t_size vale 16.

543
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Ejercicio 7.6

El seudo código mostrado a continuación calcula z = xY (x elevado a la potencia


y), dados los dos números x e y binarios sin signo de 8 bits. Se supone que el
resultado z es también un número de 8 bits, ignorándose las excepciones debidas al
rebosamiento.

Paso 1. 11 Inicialización
expo <- y;
base <- x;
if (start)
if (x==O)
resultado <- O;
go to Paso 3;
else if (y==O)
resultado <- 1;
go to Paso 3;
el se
resultado <- 1;
go to Paso 2;
end if;
end if;
Paso 2. 11 Repetición de las multiplicaciones
resultado <- resultado * base;
expo--;
if (expo==O)
go to Paso 3;
el se
go to Paso 2;
end if;
Paso 3. 11 Almacena el resultado
z <- resultado;
go to Paso 1;

Diseñe usando VHDL un circuito cuyo comportamiento venga descrito por este
seudocódigo. A continuación, programe un banco de prueba que aplique al circuito
los tres vectores de test siguientes:

Test 1: x = O, y= l. Valor esperado: z =O.

Test 2: x = 1, y= O. Valor esperado: z = l.

Test 3: x = 3, y = 2. Valor esperado: z = 9.

Realice la simulación e inspeccione visualmente los resultados, para ver si el


circuito funciona correctamente.

544
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

7.9. SOLUCIONES DE LOS EJERCICIOS

Solución al Ejercicio 7.1

El programa RT siguiente describe la operación del circuito termostato descrito


en el enunciado:

Paso O. calentador_on <- O;


ac_on <- O;
Paso 1. while (TRUE) do begin
Paso 1a. if ( temp < (consigna-umbral) ) then
calentador_on <- 1;
ac_on <- O;
Paso 1b. else if ( calentador_on and (temp>consigna) ) then
calentador_on <- O;
Paso 1c. else if ( temp > (consigna+umbral) ) then
calentador_on <- O;
ac_on <- 1;
Paso 1d. else if ( ac_on and (temp<consigna) ) then
ac_on <- O;
end if;
end while;

Solución al Ejercicio 7.2

El siguiente programa RT realiza la operación de multiplicación de dos operandos


de 8 bits, empleando para ello los componentes del camino de datos indicados en el
enunciado.

Paso 1. A <- multiplicando;


B <- multiplicador;
P <-O; 11 Variable que almacena el resultado
count <- 8; /1 Usada para el bucle for
Paso 2. if ( count > O ) then
Paso 2a. P[15:8] <- P[15:8] + ( A[O] and B );
Paso 2b. P <- P >> 1; // Desplzto Drcha, Introduce O en P[15]
A <-A >> 1;
count <- count - 1;
go to Paso 2
end if;

El programa tiene 4 pasos, con lo cual la FSM de la lógica de control tendrá


4 estados. La síntesis puede realizarse o bien empleando un fl.ip-fl.op D por estado

545
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

(codificación one-hot), en cuyo caso de emplearían 4 flip-flops D, o bien codificando


los estados (codificación binaria). En este último caso, hacen falta 2 variables de
estado para codificar 4 estados, con lo cual se emplearían 2 flip-flops D (uno por
cada variable de estado).

Solución al Ejercicio 7.3

El Código VHDL 7.8 es el diseño del circuito que calcula el máximo común divisor
de 2 números de 4 bits.

El Código VHDL 7.9 es el diseño del banco de pruebas del circuito. Obsérvese
que el banco de pruebas testea únicamente dos casos.

En el caso 1, los operados de entrada son "1100" (12 en decimal) y "1000" (8 en


decimal). El máximo común divisor será "0100" (4 en decimal). Para obtener este
valor el Paso 1 del algoritmo se repite 3 veces. Primero, se comparan los valores 12
y 8 y se realiza la resta de 12 menos 8. Después, se comparan los valores 8 y 4 y se
realiza la resta de 8 menos 4. Por último, se compara 4 y 4. Entonces, se avanza al
paso 2.

En el caso 2, los operandos de entrada son "1100" (12 en decimal) y "0010" (2


en decimal). La salida debería ser "0010" (2 en decimal). Para obtener este valor el
Paso 1 del algoritmo se repite 6 veces.

546
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

--Calcula el máximo cornun divisor. FicheTO: gcd. vhd


library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
entity gcd is
port ( result : out std_logic_vector(3 downto O);
fin : out std_logic;
opA, opB : in std_logic_vector(3 downto O);
reset,clk : in std_logic);
end entity gcd;
architecture gcd of gcd is
signa} state : integer; -- Contador que indica el paso
signa} A, B : std_logic_vector(3 downto O);
begin
process ( reset, clk ) is
begin
if ( reset = '1' ) then
state < = 1; -- Inicializa state
A < =opA;
B < = opB;
fin < = '0';
elsif rising_edge( clk ) then
state < = state +1; -- In cr-ementa state
case ( state ) is -- state codifica los pasos del algor-itmo
when 1 = >
if (B = A) then
result < = B;
fin < = '1';
state < = 2;
elsif (B > A) then
B < = std_logic_vector ( signed(B) - signed(A) );
state < = 1;
el se
A < = std_logic_vector ( signed(A) - signed(B) );
state < = 1;
end if;
when others = >
state < = 2; --Espera a q'ue la señal r-eset sea 1
end case;
end if; -- de r-ising_edge( clk )
end process;
end architecture gcd;

Código VHDL 7.8: Diseño del circuito que calcula el máximo común divisor de dos números.

547
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del cir-cuito


-- calculador del máximo común divisor. Fichero: gcd....bp
library IEEE;
use IEEE. std_logic_1164. all;

entity bp_gcd is
end entity bp_gcd;

architecture bp_gcd of bp_gcd is


constant PERIODO : time := 100 ns; -- Reloj
signal result : std_logic_vector (3 downto O); -- Salidas UUT
signal opA, opB : std_logic_vector ( 3 downto O);
signal clk : std_logic := 'O'; -- Entradas UUT
signal reset, fin : std_logic;
component gcd is
port ( result : out std_logic_vector(3 downto O);
fin : out std_logic;
opA, opB : in std_logic_vector(3 downto O);
reset,clk : in std_logic);
end component gcd;
begin
uut : component gcd port map
(result, fin, opA, opB, reset, clk);

clk <= not clk after (PERIOD0/2);


process
variable err _cnt: integer :=0 ;
begin
-- caso 1: la salida debería ser 0100
reset<='1'; opA < ="1100"; opB < ="1000";
wait for PERIOD0/3; reset < =' O';
wait for 4*PERIODO;

-- caso 2: la salida debería ser 001 O


reset < ='1'; opA < ="1100"; opB < ="0010";
wait for PERIOD0/3; reset < =' O';
wait for ?*PERIODO;
wait; --Final bloque process
end process;
end architecture bp_gcd;

Código VHDL 7.9: Banco de pruebas del circuito que calcula el máximo común divisor de dos
números.

548
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

Solución al Ejercicio 7.4

Un posible algoritmo para calcular la media se muestra a continuación. Las


señales de entrada son A, B, e y D. La señal de salida fin a 1 indica que se ha
obtenido el resultado de la media aritmética.

Paso O. Sum <- o·


R(O) <- A·'
R(1) <- B·'
R(2) <- C;'
R(3) <- D·
'
i <- o·'
fin <- O;

Paso 1. Sum <- Sum + R(i);


if (i >= 3) then
goto Paso 2;
el se
i <- i + 1·
'
goto Paso 1·
'
end if;

Paso 2. result <- Sum/4;


fin <- 1·
'
goto Paso 3;

Paso 3. goto Paso 3;

El Código VHDL 7.10 es el diseño del circuito que calcula la media de 4 números
de 4 bits.

El Código VHDL 7.11 es el diseño del banco de pruebas del circuito. Obsérvese
que el banco de pruebas testea únicamente dos casos.

549
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

--Circuito que calcula la media aritm ética


--de 4 núm eros de 4 bits. Fichero: media. vhd
library IEEE;
use IEEE . std_logic_1164. all;
use IEEE. numeric_std. all;
entity media is
port ( resul t : out std_logic_vector ( 3 downto O);
fin : out std_logic;
A, B, C, D : in std_logic_vector(3 downto O);
reset,clk : in std_logic);
end entity media;
architecture media of media is
signal state : integer; -- Contador que indica el paso
type vector_array is array (O to 3) of
std_logic_vector(3 downto O);
signal R : vector _array;
signal i : integer range O to 3;
signal Sum : std_logic_vector ( 3 downto O);
begin
process ( reset, clk ) is
begin
if( reset = '1') then
state < = 1; -- Inicializa state
Sum < = 11 0000 11 ;
R(O) < =A;
R(1) < = B;
R(2) < = C;
R(3) < = D;
fin < = '0';
elsif rising_edge( clk ) then
case ( state ) is -- state codifica los pasos del algoritmo
when 1 = >
i < = O; state < = 2;
when 2 = >
Sum < = std_logic_vector ( unsigned(Sum) + unsigned( R(i) ) );
if ( i > = 3 ) then
state < = 3;
el se
state < = 2;
i <= i + 1;
end if;
when 3 = >
fin < = '1';state < =4;
result < = std_logic_vector (unsigned(Sum)/4);
w hen others = >
state < = 4; --Espera a que la señal reset sea 1
end case;
end if; -- de rising_edge( clk)
end process;
end architecture media;

Código VHDL 7.10: Diseño del circuito que calcula la media de 4 números de 4 bits.

550
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

-- Banco de pruebas del circuito


-- calculadoT de la media. Fichem: bp_media.vhd
library IEEE;
use IEEE. std_logic_1164. all;
entity bp_media is
end entity bp_media;
architecture bp_media of bp_media is
constant PERIODO : time := 100 ns; --Reloj
signal result : std_logic_vector (3 downto O); --Salidas UUT
signal A, B, e, D : std_logic_vector (3 downto O);
signal clk : std_logic := 'O'; -- Entradas UUT
signal reset, fin : std_logic;
component media is
port ( result : out std_logic_vector(3 downto O);
fin : out std_logic;
A, B, e, D : in std_logic_vector(3 downto O);
reset,clk : in std_logic);
end component media;
begin
uut : component media port map
(result, fin, A, B, e, D, reset, clk);

clk <= not clk after (PERIOD0/2);


process
variable err _cnt: integer :=0 ;
begin
-- caso 1: la salida debería ser 0001
reset < ='1'; A< ="0001"; B< ="0001"; e < ="0001"; D< ="0001";
wait for PERIOD0/3; reset < =' O';
wait for 6*PERIODO;
-- caso 2: la salida debeTÍa seT 001 O
reset < ='1'; A< ="0010"; B< ="0010"; e<="0010"; D< ="0010";
wait for PERIOD0/3; reset<= 'O';
wait for ?*PERIODO;

wait; --Final bloque process


end process;
end architecture bp_media;

Código VHDL 7.11: Banco de pruebas del diseño del circuito que calcula la media de 4 números
de 4 bits.

551
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 7.5

El Código VHDL 7.12 describe el algoritmo de conversión de BCD a binario dado


en el enunciado:

Paso 1. bcd <- bcd_data_input;


bin <- O (mismo número de bits que bcd)
Paso 2. For count <- 1 to bcd_bit_size do begin
Paso 2a. {bcd,bin} <- {bcd,bin} >> 1;
Paso 2b. For cada secuencia de 4 bits en bcd do
If secuencia de 4 bits > 7 then
restar 3 de esa secuencia de 4 bits;
end //del bucle For
Paso 3. bin contiene el número convertido

La constante global que almacena el número de bits del número en BCD es


declarada en un package, que será usado desde la descripción del circuito y desde
la descripción del banco de pruebas.

Obsérvese que un bloque process puede dar lugar a un circuito combinacional


si en la lista de señales a las cuales el bloque es sensible incluye todas las entradas
al circuito. Dado que ese bloque process sería activado cada vez que una de las
señales de entrada cambia, este código representa un circuito combinacional.

Igualmente, un bucle for no implica necesariamente que el circuito sintetizado


deba ser secuencial. En este caso, el bucle for únicamente representa la interconexión
de puertas lógicas combinacionales.

El Código VHDL 7.13 y 7.14 es el banco de pruebas del circuito conversor. Para
probar el circuito, se generan todos los posibles números en BCD con LENGTH bits.
En este caso, todos los posibles números de 16 bits. Puesto que un número BCD de
16 bits puede representar cualquier número entero comprendido entre O y 9999 10 ,
ese será el rango de números que se emplee en el test.

552
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

-- Definición de constantes globales


--Fichero: BCD_CONST.vhd

package BCD_CONST is
constant LENGTH : integer := 16; -- Longitud ( # bits) del número BCD
end package BCD_ CONST;

-- Circuito conversor de BCD a binario


-- Fichero: bccLto_bin. vhd
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 O);
bcd: in std_logic_vector(LENGTH-1 downto O) ) ;
end entity bcd_ to_bin;

architecture bcd_ to_bin of bcd_ to_bin is


begin

process (bcd) is -- bloque sensible a cambios en la entrada


variable bcd_concat_bin : unsigned(2*LENGTH-1 downto O);
variable temp : unsigned(3 downto O);
begin
bcd_concat_bin := unsigned(bcd) & TO_UNSIGNED(O,LENGTH);
for i in O to LENGTH-1 loop -- Paso 2
bcd_concat_bin := bcd_concat_bin srl 1; -- Paso 2a
for j in O 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 O));
end process;
end architecture bcd_ to_bin;

Código VHDL 7.12: Package con la definición de constantes y diseño del conversor de código
BCD a binario.

553
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas para el circuito conversor de BCD a binario


-- Fichero : bp_bcd_to_bin. vhd
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;

architecture bp_bcd_ to_bin of bp_bcd_ to_bin is


signal bin: std_logic_vector(LENGTH-1 downto O); -- Salida de UUT
signal bcd: std_logic_vector(LENGTH-1 downto O); -- Entrada a UUT
-- D eclaración del componente (UUT)
component bcd_to_bin is
port( bin: out std_logic_vector(LENGTH- 1 downto O);
bcd: in std_logic_vector(LENGTH-1 downto O) );
end component bcd_to_bin;
begin
-- Instancia la unidad a testear
UUT : component bcd_to_bin port map(bin,bcd);

-- Genera vectores de test y comprue ba resultados


main: process is
variable temp : uns igned (LENGTH-1 downto O);
variable digi t : unsigned (LENGTH-1 downto O); -- Un digito BCD
variable digi ts : unsigned (LENGTH-1 downto O); -- Todos digitos
variable expected : unsigned (LENGTH-1 downto O);
variable error _count : integer := O; -- Número de errores
begin
report "Comienza la simulación.";
-- Generar todos los posibles valores
for i in O to MAX_BCD loop
temp := TO_UNSIGNED(i,LENGTH);
for j in O to (LENGTH/ 4-1) loop
digi t := temp mod 10; -- Obtiene el digito BCD menos significativo
digits(j*4+3 downto j*4) := digit(3 downto O);
temp := temp/10;
end loop;
bcd <= std_logic_vector( digi ts ); -- Asigna vector de test
expected := TO_UNSIGNED(i, LENGTH);
wait for DELAY;
assert ( expected = unsigned(bin))
report "ERROR: Resultado esperado " &
integer' image(TO_INTEGER( expected)) &
", resultado obtenido " &
integer' image(TD_INTEGER(unsigned(bin))) &
" en el instante " & time'image(now);
if ( expected /= unsigned(bin)) then
error_count := error_count + 1;
end if;
end loop;

Código VHDL 7.13: Parte inicial del banco de pruebas del conversor de código BCD a binario.

554
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

-- Continua banco de pruebas para el circuito conversor (fichero: bp_bcd_to_bin. vhd)

wait for DELAY;

-- Informe final
if (error_count =o) then
report "Simulación finalizada sin errores";
else
report "ERROR: Hay " & integer'image(error_count) & " errores.";
end if;

wait; -- Final de la simulación

end process main;

end architecture bp_bcd_ to_bin;

Código VHDL 7.14: Parte final del banco de pruebas del conversor de código BCD a binario.

555
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Solución al Ejercicio 7.6

En el package del Código VHDL 7.15 se han definido las constantes globales, que
serán usadas en el diseño del circuito y en el banco de pruebas. Asimismo, el Código
VHDL 7.15 contiene la definición de la entity del circuito. El Código VHDL 7.16
es la architecture del diseño del circuito exponenciador.

El Código VHDL 7.17 y 7.18 es el banco de pruebas con los 3 vectores de test
indicados en el enunciado. Obsérvese que la señal fin se emplea para finalizar el
bloque process que genera la señal de reloj, una vez ha finalizado la aplicación de
los vectores de test. Con ello se consigue que la simulación finalice por sí misma. En
la Figura 7.4 se muestra el resultado de la simulación del banco de pruebas.

-- Exponenciación. Constantes globales


-- Fichero: exponerLCONST.vhd
library IEEE;
use IEEE. std_logic_1164. all;

package exponen_ CONST is


constant MAX_DATA_BITS : integer := 8; -- Bits de los datos
constant BITS_PASO : integer := 2; -- Bits para codificar el estado
constant PAS01 : std_logic_vector(1 downto O) := "01"; --Estados
constant PAS02 : std_logic_vector ( 1 downto O) := "10";
constant PAS03 : std_logic_vector(1 downto O) : = "11";
end package exponen_ CONST;

-- Circuito exponenciación: z = x **y


-- Fichero: exponen. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use IEEE. numeric_std. all;
use work. exponen_CONST. all;

entity exponen is
port ( z : out std_logic_vector (MAX_DATA_BITS-1 downto O);
-- Resultado de la exponenciación
paso : out std_logic_vector (BITS_PAS0-1 downto O);
-- Paso en ejecución del algoritmo
reset_n : in std_logic; -- Reset asíncrono activado LOW
clk : in std_logic;
start : in std_logic;
x : in std_logic_vector(MAX_DATA_BITS-1 downto O);
y : in std_logic_vector(MAX_DATA_BITS-1 downto O) );
end entity exponen;

Código VHDL 7.15: Package con la definición de las constantes globales y entity del circuito
exponenciador.

556
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

-- Continuación definición circuito exponenciación: z = x ** y


-- Fichero: exponen. vhd
architecture exponen of exponen is
begin
seudocodigo: process (reset_n, clk) is
variable resultado : unsigned(MAX_DATA_BITS*2-1 downto O);
variable base : unsigned(MAX_DATA_BITS-1 downto O);
variable expo : unsigned(MAX_DATA_BITS-1 downto O);
variable paso_v : std_logic_vector (BITS_PAS0-1 downto O);
-- Paso en ejecución del algoritmo
begin
if (reset_n = 'O') then
paso_v := PASD1; --Al resetear, ir al Paso 1
elsif rising_edge( clk) then
case paso_ v is
when PAS01 = > -- Ini cialización
base := unsigned(x);
expo := unsigned(y);
if (start = '1 ') then
if (x = B"OOOO_OOOO") then
resultado := ( others => '0');
paso_ v := PASD3;
elsif (y = B"OOOO_OOOO") then
resultado:= (O=> '1',others=> '0');
paso_ v := PASD3;
el se
resultado:= (O=> '1',others=> '0');
paso_ v := PASD2;
end if;
end if;
when PAS02 => -- Repetición de las multiplicaciones
resultado := resultado(MAX_DATA_BITS-1 downto O)*base;
-- 8 bits * 8 bits = 16 bits
expo := expo - 1;
if ( expo = o) then
paso_ v := PASD3; -- Termina
else
paso_ v := PASD2; -- Multiplica de nuevo
end if;
when PAS03 => --Almacena el resultado
z <= std_logic_vector(resultado(MAX_DATA_BITS-1 downto O));
paso_ v := PASD1;
when others =>
null;
end case;
paso <= paso_ v;
end if;
end process seudocodigo;
end architecture exponen;

Código VHDL 7.16: Diseño del circuito exponenciador.

557
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Banco de pruebas del circuito exponenciación: z = x ** y


-- Fichero: bp_ exponen. vhd
library IEEE;
use IEEE. std_logic_1164. all;
use work. exponen_CONST. all;

entity bp_exponen is
constant PERIODO : time := 100 ns; -- Periodo del reloj
end entity bp_exponen;

architecture bp_exponen of bp_exponen is

-- Declaración de señales para conectar la UUT


signal z : std_logic_vector (MAX_DATA_BITS-1 downto O);
signal paso : std_logic_vector (BITS_PAS0-1 downto O);
signal reset_n : std_logic;
signal clk : std_logic;
signal start : std_logic;
signal x : std_logic_vector(MAX_DATA_BITS-1 downto O);
signal y : std_logic_vector(MAX_DATA_BITS-1 downto O);

-- Declaración de otras señales


signal fin : boolean := false;

component exponen is
port ( z : out std_logic_vector (MAX_DATA_BITS-1 downto O);
paso : out std_logic_vector (BITS_PAS0-1 downto O);
reset_n : in std_logic; -- Reset asíncrono activado LOW
clk : in std_logic;
start : in std_logic;
x : in std_logic_vector(MAX_DATA_BITS-1 downto O);
y : in std_logic_vector(MAX_DATA_BITS-1 downto O) );
end component exponen;

begin
uut : component exponen
port map (z, paso, reset_n , clk , start, x , y);
-- Pulso de reset
reset_n <= '1',
'O' after (PERIODO/ 4),
' 1 'after (PERIODO + PERIODO/ 4);
-- Señal de reloj
reloj : process is
begin
clk <= 'O'; wait for (PERIOD0/2);
clk <= '1'; wait for (PERIOD0/2);
if (fin) then
wait; -- Termina este proceso
end if;
end process reloj;

Código VHDL 7.17: Principio del banco de pruebas del circuito exponenciador.

558
METODOLOGÍA DE TRANSFERENCIA ENTRE REGISTROS

Con t. del banco de pruebas del circuito exponen ciación. Fichero: bp_ exponen. vhd
-- Gen eración de los vectores de test
genera_ vectores : process is
begin
wait until falling_edge( clk);
-- Test 1: x vale O, y vale 1
x <= (others => '0'); y<= (O=> '1', others => '0');
wait for PERIODO;
start <= '1 '; -- Comienza el cálculo x**y
wait until (z = B"OOOO_OOOO"); --Espera hasta obtener z= O
-- Test 2: x vale 1, y vale O
x <=(o => '1', others = > '0'); y < = (others = > '0');
wait for PERIODO;
start <= '1'; -- Comienza el cálculo x**y
wait until (z = B"0000_0001"); -- Espera hasta obtener z=1
-- Test 3: :r; vale 0000_0011 , y vale 0000_0010
X <= "00000011"; y <= 11 00000010";
wait for PERIODO;
start <= '1'; -- Comienza el cálculo x**y
wait until (z = B"0000_1001"); -- Espera hasta obtener z=9
-- Final de la simulación
report "Fin de la simulación";
fin < = true; -- Finaliza el proceso del reloj
wait; -- Finaliza est e proceso
end process genera_ vectores;
end architecture bp_exponen;

Código VHDL 7.18: Parte final del banco de pruebas del circuito exponenciador.

[±J + /bp_exponen/z 00001001 uuuuuuuu 100000000 ].(0000001 o ..


[±J + /bp_exponen/paso 01 uu 101 11 101 11 lC1 10 11 1
+ /bp_exponen/reset_n 1 'l
+ /bp_exponen/clk 1 -
+ /bp_exponen/start 1
[±J + /bp_exponen/x 00000011 uuuuuuuu 100000000 100000001 lCOOOOOll
[±J + /bp_exponen/y 00000010 uuuuuuuu 100000001 100000000 l:00000010
+ /bp_exponen/fin true 1 -

l l l l l l l l t l t t l l l l l l l l t t l l l l l l l l t t l l l l l t l l t t l l l l l l t l t t l l l l l l ,,, l l l l l l t l l t t l l l l l l t l t t l l l l l l t l t t l l l l t ,,,,,
& ]¡¡}© Now 1000 ns 1s 200 ns 400 ns 600 ns 800 ns · 000 ns
~;·o Cursor 1 975 ns ~
..!J ...t.JJ ~
-'
1 1 I /
1 Ons to 1041 ns 1 Now: 1 us Delta: 1

Figura 7.4: Resultado de la simulación del banco de pruebas del circuito exponenciador.

559
APÉNDICE A

VERIBEST VB99.0

A.l. Instalación
A.2. Edición y compilación de un modelo
A.3. Simulación y visualización de los resultados
A.4. Depurado usando el debugger
VERIBEST VB99.0

A.l. 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:

l. Ejecute el fichero setup. exe, que se encuentra dentro del directorio VHDL_Si-
mulator.

2. Acepte los términos de la licencia.

3. Escoja el directorio en el cual desea que se instale el simulador.

4. Seleccione para su instalación "VeriBest VHDL Simulator', que es la opción


señalada por defecto.

5. El programa de instalación copia todos los ficheros necesanos en el disco,


creando en el grupo de programas de Windows un nuevo grupo llamado Ve-
riBest VB99. O. Dentro de éste hay una carpeta," VeriBest VHDL Simulator',
en la que se encuentra el simulador VHDL ( VeriBest VHDL), un tutorial y la
documentación en línea.

A.2. EDICIÓN Y COMPILACIÓN DE UN MODELO

En esta sección se describe cómo editar y compilar modelos con el simulador VeriBest
VHDL.

A.2.1. Arranque del simulador VeriBest VHDL

Seleccione el icono VeriBest VHDL del grupo de programas Inicio --+ Programas--+
Veribest VB99.0 --+ Veribest VHDL Simulator.

A.2.2. Creación de un espacio de trabajo

Para crear un espacio de trabajo, puede seguir una de las dos opciones siguientes:

l. Despliegue el menú "Workspace" y seleccione la opción "New ... "

563
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

2. Seleccione el comando "New ... " del menú "File". Se mostrará una ventana en
la que tiene que seleccionar la opción "VHDL Workspace".

Tras seguir una de estas dos opciones, se mostrará una ventana (véase la Fi-
gura A.l). Teclee en dicha ventana el nombre del espacio de trabajo, que en este
caso se ha llamado bufferTriestado, y seleccione el directorio en el cual quiere crear
el espacio de trabajo. El path a dicho directorio (Workspace Path) no debe tener
espacios en blanco, ya que en caso de tenerlos se producirá un error y no se creará
correctamente el espacio de trabajo.

Workspace Name:
Create
1buffer Trie~tad?
Cancel
Workspace Path:
I BASE\\AfOR~S,~~CEVE"RIBEST\ , Help
127 d:\
127 Docencia
127 ETCIII
127 TextoB ase
CJ vbvhdl.chkpt
_ ~ WORKLIB-LVS

n Use Synopsys IEEE library (IEEE_SYN)

! Network... 1

Figura A.l: Espacio de trabajo.

Aparecerá en el lateral izquierdo de la ventana principal del simulador una nueva


ventana con el título buffer Triestado. vpd. Inicialmente, la ventana sólo muestra una
carpeta vacía, denominada bufferTriestado source (véase la Figura A.2).

En dicha ventana ubicaremos todos los ficheros necesarios para simular el buffer
triestado, que son los dos siguientes, tal como se describió en las Secciones 1.9.1 y
l. 9. 2: buffer Triestado. vhd y bp_bufferTriestado. vhd.

A.2.3. Edición de un fichero

Puede crearse un nuevo fichero utilizando el comando "New ... " del menú "File".
Obtendrá una ventana en blanco en la que puede teclear el código VHDL. Escriba el
código que describe el buffer triestado y que se muestra en la Sección 1.9.1. Una vez
haya concluido, guárdelo con el nombre buffer Triestado. vhd mediante el comando

564
VERIBEST VB99 .0

Command

vbinit .exe
Working 1 ibrary i s : D : '-DOCENCIA '-ETCI I I '-TEXTOBASE'-WORKSPACEVERIBEST'-WORKLIB
Reference to library WORKLIB (physical name : D: '-DOCENCIA'-ETCIII '-TEXTOBASE'-WORKSPACEVERIBEST'-WORKLIB) added
Done

Figura A.2: Entorno de simulación tras crear el espacio de trabajo.

"Save", situado en el menú "File". El path al directorio en el que va a guardar el


fichero no debe tener espacios en blanco, ya que si los tiene se producirá error al
compilar el modelo.

A.2.4. Añadir un fichero al espacio de trabajo

Incluya el fichero buffer Triestado. vhd en el espacio de trabajo bufferTriestado. vpd.


Hay dos formas equivalentes de hacerlo:

l. Haga die 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.

2. O bien, utilice el comando "Add Files into Workspace ... " situado en el menú
"Workspace".

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

565
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

-- Modelo del buffer triestado


El·· ~ buffer Triestado Source -- bufferTriestado.vhd
:. ... [!) buffer Triestado.vhd library IEEE ;
use IEEE . std_logic_1164 .all ;
entity Buffer_TriEstado is port
( y : out std_logic ;
E in std_logic ;
d in std_logic ) ;
end entity Buffer_TriEstado ;
architecture Behavioral of Buffer_TriEstado is
begin
process (E , d)
begin
if (E = '1') then
y <= d;
el se
y <= 'Z' ;
end if ;
end process ;
end architecture Behavioral ;

Figura A.3: Entorno de simulación tras incluir el fichero bufferTriestado.vhd en el espacio de


trabajo.

A.2.5. Compilación de un fichero

Para establecer las opciones de compilación, seleccionamos la opción "Settings ... "
del menú "Workspace", o bien recurrimos al icono "Workspace Settings" que está
situado en la barra de herramientas. Con ello, se mostrará una ventana, en la cual
seleccionamos la pestaña "Compile". De este modo, accedemos al cuadro de diálogo
donde se muestran, entre otras, las siguientes opciones de compilación:

566
VERIBEST VB99 .0

~~-~%::2;i~z~=r:bJrt;;·""r;r:;;r;a6r~-c""++--++~~+-
-:-:..-pi.i H~:r::Tr;i:~~ t ád9 :. y~d,
librarv .. I'EEE;·
J.l.s~ · I,É;EE·>std_,:)·ocii.c.:_ l16. ~:. aH.; .
enti~y Í3üÍfe:r_Tr-i:És .taqo i s ·· por t
e~- : ·{~~ ~~~~i~~l6 : ,
,d. :. i ~ )~:t d_,) ogiq .. •);
. end :·é~ti ty :13tH f e;r:-::,..Tri'E~tá,pq
áf ch'l :tect ur'ei i3eha:v i oi al "6 i Bu f'fer~.TriEst; ació
be9j:n · . · : · · ··· · ·
is
·· prqc~s ~ ' (:E " d .)
begin•
H '( E, ;= ~·· 1 ' ), .then.
y ':<= ·. d; '
-'els e:
.• Y <:.' ·.z:· ;.
; élid' if ;
eM·tJroqess.:
end, archit.ec .t .í.txe · Beha~dorál ;

Cpm¡ji :I'ing É:nfi ty pecl,aration BUFFER,;:TRIESTliDÓ


~oini:l ~:Vng Ar,c;hit ~'? t ~r.e
BJi:RAV,J;ORA;L 9 t BJJFFER.:. :.TRIESJADQ

Figura A.4: Entorno de simulación tras compilar el fichero buffer Triestado. vhd.

"Debug" Activando esta opción el archivo seleccionado será compi-


lado con la opción de depuración. Con esta opción activa
antes de una compilación, es posible utilizar todos los
comandos del menú Debug durante la fase de simulación.
Si se desea que todos los archivos del espacio de trabajo
sean compilados con esta opción, basta con seleccionar la
carpeta del espacio de trabajo en la ventana y activar la
opción.
"Index Checks" Si esta opción se encuentra activa, el compilador com-
prueba la existencia de errores en los índices de los arrays.
"Range Checks" Si esta opción se encuentra activa, el compilador com-
prueba la existencia de errores en los rangos de los
subtipos que se hayan definido.

567
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

~File Edit Search Workspace Simulate Library Tools Window Help .. :::J.::i'L.~.]
~~--;t~~rcir~r~r~r~~~Jfoo -------¡
~ g-~ ¡----------------·---·-

iirl~ l~l lll l


¡g¡ Library Browser
g .. Source Location 1Compilation Time 1Ce
IEEE D C:\VeriBest\vbvhdl\lib93\IEEE
STO D C:\VeriBest\vbvhdl\lib93\STD
f2:l
VB D C:\VeriBest\vbvhdl\lib93\VB
B·iil
WORK,WORKLIB DwoRKLIB
B·O BUFFER_TRIESTADO D D:\DOCENCIA\ETCIII\TEXTOBASE\MODELOSVHDL\TUTORIALSIMULADORES\BUFFERTRIESTADO. VHD Sat Feb 09 19:35:01 .. .
fl
i. .. BEHAVIORAL D D:\DOCENCIA\ETCIII\TEXTOBASE\MODELOSVHDL\TUTORIALSIMULADORES\BUFFERTRIESTADO. VHD Sat Feb 09 19:35:01 .. .

l< d.

Couand 1 .

: (;;~e~:ai 1Build 1 Simula te 1


vbinit
Working library i s : D: '-DOCENCIA'-ETCIII '-TEXTOBASE'-IJORI<SPACEVERIBEST'-IJORI<LIB
Ref erence t o 1 ibrary WORI<LIB ( phys ical name : D : '-DOCENCIA'-ETC! I l '-TEXTOBASE'-IJORI<SPACEVERIBEST'-IJORI<LIB) added
Done
libbrows

Ready Jlllllllllll lt iiiiiii J

Figura A.5: Library Browser.

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 (véase la Figura A.4).
Observe que la ventana de información contiene las tres pestañas siguientes:

"General" Proporciona información sobre cualquier acción que se


realice en la herramienta.
"Build" Muestra la información referente al proceso de compila-
ción de ficheros. En el caso de que haya habido errores en
la compilación muestra la línea de código donde aparece
cada error y el tipo de error que es.
"Simulate" Proporciona información sobre la fase de simulación.

La unidad compilada se almacena en la librería WORK. Para ver su ubicación, se


selecciona el comando "Library Browser", ubicado en el menú "Library", o se pincha
en el icono correspondiente. Aparecen las diferentes librerías, IEEE, STD, VE, y
en rojo WORK, WORKLIB. Si pinchamos en ésta, aparecen la interfaz (entity)
y arquitectura (architecture) de los diferentes circuitos que hayamos compilado.
Podemos ver otra información en la parte derecha de la ventana: la fecha y las
opciones de compilación (véase la Figura A.5). Observe que el chip asociado a la
interfaz aparece en color blanco y el asociado a la arquitectura en color rojo.

568
VERIBEST VB99.0

Se puede reinicializar la librería en la que se está trabajando mediante el co-


mando "Reinitialize Lib environment", que está situado en el menú "Workspace". Al
reinicializar la librería, desaparecen de ella las unidades compiladas.

A.2.6. Banco de pruebas

Una vez editado y compilado el diseño del buffer triestado, debemos editar y compilar
su banco de pruebas. Para ello:

l. Cree un nuevo fichero con el código del banco de pruebas, que se muestra en
la Sección 1.9.2. Una vez haya concluido, guárdelo en un fichero con el nombre
bp_bufferTriestado. vhd. Recuerde que el path hasta ese fichero no debe contener
espacios en blanco.

2. Incluya el fichero bp_bufferTriestado. vhd en el espacio de trabajo bufferTries-


tado. vpd. La ventana principal del simulador tiene que quedar tal y como se
muestra en la Figura A.6. El orden de compilación de un fichero se puede
modificar mediante las flechas situadas en la esquina superior derecha de la
ventana del espacio de trabajo bufferTriestado. vpd.

S- ~ buffer Triestado Source


\ ·[!) buffer Triestado.vhd
i - ~ bp_bufferTriestado.vhd

vbinit .exe
Working library i s : D : '-DOCENCIA'-ETCIII '-TEXTOBASE'-WORI<SPACEVERIBEST'-WORI<LIB
Reference to library WORI<LIB (physical name : D: '-DOCENCIA'-ETCIII '-TEXTOBASEWORI<SPACEVERIBEST'-WORI<LIB) added
Done

Figura A.6: Entorno de simulación tras incluir el banco de pruebas en el espacio de trabajo.

3. Compile el fichero bp_bufferTriestado. vhd.

569
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

A.3. SIMULACIÓN Y VISUALIZACIÓN DE LOS RESULTADOS

A continuación, se describen los pasos a seguir para simular el banco de pruebas del
buffer triestado y para visualizar los resultados de la simulación.

A.3.1. Establecer las condiciones de la simulación

Para fijar las condiciones de la simulación, siga los pasos siguientes:

l. Seleccione la opción "Settings ... " del menú "Workspace" o haga clic sobre
el icono correspondiente, denominado "Workspace Settings", de la barra de
herramientas. Se abrirá la ventana mostrada en la Figura A.7.

; r- Design Root ---~------~~---·-·;


BQ
¡ , ..
BUFFER TRIESTADO
BEHAVIDRAL
i \o: Ent1ty/Arch
li ¡ . . . .
C: Conflg
r
¡
·
Set
· · ¡11
Ei Q BP_BUFFER_TRIESTADO J 1 . . i
: . . BP_BUFFER_TRIESTA91 Entlty. 1~~~B~F~~~:::!RI~~T~D? 1

ji Arch: I BP_BUFFER_TRI~STADO . J

¡ ~----------------~
i
1 Time Unit:j none[!J Terminate Level:j FAILURE
! ············· ········· ....
GJ
1 R: Trace On
i
1 Suppress lnit Phase Message: GJ
1NO~E __

j Suppress Message: ~~O~~ GJ


l Additional Options:
~ ~------------------
1!;..:4! ••,. -~~,.,;:::;...~"-'-"-. C~il

Figura A. 7: Opciones de simulación.

2. Para acceder al cuadro de diálogo con las opciones de simulación, seleccione la


pestaña "Simulate" de la ventana.

3. Despliegue la carpeta "WORK" para visualizar los elementos sobre los que se
puede realizar una simulación. Obtendrá las interfaces (entity) y arquitecturas
(architecture) que ha programado en los pasos anteriores. Para realizar el test
de la puerta lógica debe seleccionar la arquitectura BP_BUFFER._TRIESTADO
(que es el banco de pruebas) y la interfaz que lleva asociada esa arquitectura
(BP _BUFFER._TRIESTADO).
Para ello, seleccione la architecture BP _BUFFER._TRIESTADO con el cur-
sor del ratón (haga clic sobre ella) y pulse el botón "Set". Tras esta acción, los

570
VERIBEST VB99.0

campos "Entity" y "Arch" se rellenarán automáticamente con los nombres de


la entity y de la architecture.
Por último, activamos la opción "Trace On" (que nos permite visualizar las for-
mas de onda resultantes). Esto también se logra desplegando Simulate-* Trace.

4. Una vez fijadas las condiciones de simulación, pulse el botón "Aceptar".

A.3.2. Activación del simulador

Para realizar la simulación hay que arrancar el simulador. Esto se puede realizar
de dos formas: mediante la opción "Execute Simulator" del menú "Workspace", o
mediante el icono correspondiente, denominado "Execute Simulator", situado en la
barra de herramientas.

Mediante cualquiera de las dos opciones, el simulador se activa. Durante el proce-


so de activación del simulador aparecerá una ventana de aviso (véase la Figura A.8),
en la que se indica que se está utilizando la versión del simulador que no necesita
licencia. Pulse el botón "Aceptar" para continuar trabajando.

No license was found.


The simulator will run in reduced capacity mode.

If you would like a license for full capacity operation)


please contact us at sales@veribest.com
or in the USA call us at 1-888 482-3322.

http: //www. veribest. com/vhdl .html

1 Aceptar 1

Figura A.8: Mensaje de aviso sobre la ausencia de licencia.

Tras la activación del simulador, en la ventana denominada "Simulate", situada


en la parte inferior del espacio de trabajo, aparece un texto. En la última línea del
texto se indica si ha habido errores o avisos ( warnings).

A.3.3. Simulación y visualización de los resultados

Una vez activado el simulador, puede configurar la duración de la simulación (véase


la Figura A.9). Una lista desplegable permite seleccionar las unidades del tiempo de
simulación. Por defecto, la unidad de tiempo es nanosegundos (ns). En una casilla

571
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

File Edit Search Workspace Simulate Debug Libr ary Tools Window Help
-~~--¿iJ~T~fr~r:~~iriT:§fliJ1r~¡-;---;~~·---·-----------------------··-·----·-----·-·-··-·---·-·····---··-···-·-······-·

•~~~~~ l.e.tl m • m • m• m o m ••••mmmmmm

TJI Ti'ltJl!lfual • 1• 1611'1~I ~I&OI@JI


E-· ~ bufferT riestado Source

Run Tiempo de Unidades del


simulación tiempo de
simulación

Figura A.9: Botones para el control de la simulación.

numérica se indica la duración de la simulación. Escriba en esa casilla 40 y seleccione


ns como unidad de tiempo.

Para seleccionar qué formas de onda desea visualizar, puede pinchar con el ratón
sobre el icono "WaveForm Window", que está situado en la barra de herramientas.
Equivalentemente, puede ejecutar "New WaveForm Window", que se encuentra en
el menú "Tools ... ".

Obtendrá una ventana con una escala de tiempos, en la que no se muestra ninguna
señal. Para seleccionar las señales, pulse el botón "Add signals" en la ventana de
visualización de señales. Dicho botón se encuentra indicado en la Figura A.lO.

Obtendrá una nueva ventana, mostrada también en la Figura A.lO, en la que


puede seleccionar las señales que desea representar. Pueden seleccionarse las señales
del banco de pruebas o las señales del UUT.

Para seleccionar todas las señales de la architecture del banco de pruebas,


seleccione BP _BUFFER._TRIESTADO(BP _BUFFER._TRIESTADO), tal como se
muestra en la Figura A.lO, y a continuación pulse sobre el botón "Add All". Pulse
"Close" para cerrar la ventana.

Para iniciar la ejecución de la simulación, puede presionarse el botón con el


triángulo de color verde, "Run (F5)", que está situado en la barra de herramientas
(véase la Figura A.9). Equivalentemente, puede seleccionarse la opción "Run" del
menú "Simulate". Las formas de onda obtenidas se muestran en la Figura A.ll.

Para salir del simulador, podemos hacer clic con el ratón sobre el icono "Quit",
el cual se encuentra señalado en la Figura A. 9.

572
VERIBEST VB99 .0

Figura A.lO: Selección de las señales a visualizar.

,f'l y
'li"l! D
. li"l!E

Colll.llland

Gene~al

Run for 40 ns.


Report [NOTE] in :BP_BUFFER_TRIESTADO(BP_BUFFER_TRIESTIIDO) :GEN_VEC_TEST at time 40 ns. cycle O:
Final de la simulación

Figura A.ll: Resultados de la simulación.

573
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

A.4. DEPURADO USANDO EL DEBUGGER

Para usar el depurador, es preciso previamente haber compilado los ficheros con la
opción "Debug" habilitada. Una vez activado el simulador, aparece el menú "Debug",
si bien hasta que no se inicie la simulación no aparecerán habilitados todos los
comandos del depurador. Entre los comandos del depurador habilitados antes de
iniciar la simulación, cabe destacar los siguientes (véase la Figura A.12):

- "Insert/Remove a Breakpoint": permite introducir un punto de ruptura (break-


point) o eliminar un punto de ruptura introducido previamente.

- "Clear All Breakpoints": elimina todos los puntos de ruptura.

- "New Watch Window": abre una ventana que permite observar la evolución
de las señales de forma numérica. Esta ventana, mostrada en la Figura A.13,
dispone de hasta cuatro paneles de observación independientes ("Watchl" 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, o bien las señales de forma
independiente (se selecciona la señal y se pulsa el botón "Watch"), o bien 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 "So urce Breakpoint Condition", en la que
se pueden establecer las condiciones de activación de un punto de ruptura
determinado.
Desde la ventana "So urce Breakpoint Condition", podrá indicar que el punto
de ruptura permanezca activo únicamente para una instancia o proceso espe-
cí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": 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 die sobre una de
las entradas que aparecen en la ventana "Call Stack", se obtendrá una nueva

574
VERIBEST VB99.0

lnsert/Remove Show
a Breakpoint Breakpoi
Clear All Breakpoints NewWatch
~!'~· Watch Winaow
Show.Br~a!<Points ... Examine Call Window
caHStack Stack
~chi tect,).lre BehaviCJral of BuHer_TriÉst.ad,o is
14 bli¡gin
15 process (E,d)
16 begin
17 i f (E= '1') them
18 y <= d;
19. el se
20 y <= 'Z' ;
21 end if,;
22 end PrOCSS<;l;
23 end archi tecture Behaviorál ;
24

Figura A.12: Opciones de depuración habilitadas al arrancar el simulador.

Figura A.13: Configuración de una ventana de observación (watch window).

Figura A.14: Opciones de depuración una vez iniciada la simulación.

575
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

ventana en la que se muestra el código fuente VHDL que se indica en la entrada


que ha seleccionado.
Si el diseño contiene subprogramas, la ventana "Call Stack" se incrementará
con una nueva entrada cuando comience la ejecución de un subprograma,
correspondiente a la llamada al subprograma. Cuando concluya la ejecución
del subprograma, la correspondiente entrada en la ventana será eliminada.

Para empezar el proceso de depuración hay que comenzar la simulación. Una


vez comenzada la simulación, se habilitarán, entre otros, los siguientes comandos de
depuración (véase la Figura A.14):

- "Continue": continúa la ejecución de la simulación hasta el siguiente punto de


ruptura o hasta que concluya el tiempo de simulación.

- "Step": avanza la simulación una línea del código fuente VHDL.

576
APÉNDICE B

MODELSIM PE STUDENT EDITION

B .l. Instalación
B.2. Edición y compilación de un modelo
B.3. Simulación, visualización y depurado
MODELSIM PE STUDENT EDITION

B.l. 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 ModelSim
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 M odelSim.

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.

l. Descargar el fichero ejecutable de instalación de la dirección:

http: / /www.model.com/resources/ student_edition/ download.asp

para lo cual en primer lugar tendrá que rellenar un formulario electrónico con
sus datos y señalar una casilla que indica que sólo va a usar la herramienta
para fines educativos.

2. Ejecutar dicho fichero, el cual realiza la instalación del simulador. En la fase


final de la instalación, el programa de instalación se conecta a una página web
en la cual hay un formulario para la solicitud de la licencia.

3. En la hoja de solicitud de licencia, debemos indicar a qué dirección de correo


electrónico deseamos que nos envíen el fichero de licencia. En esa dirección de
correo recibiremos un correo con el fichero de licencia y las indicaciones de
dónde debe guardarse. La licencia tiene una validez de 180 días, transcurridos
los cuales debe repetirse la instalación y la solicitud de la licencia. La licencia
sólo es válida para el ordenador en el que se hizo la descarga del ejecutable.
Si se quiere instalar ModelSim en otro ordenador, debe repetirse el proceso de
descarga del ejecutable y solicitud de la licencia.

B.2. EDICIÓN Y COMPILACIÓN DE UN MODELO

En esta sección se describe cómo editar y compilar modelos con el simulador Model-
Sim. Para ilustrar las explicaciones, se va a usar el modelo del buffer triestado y su
banco de pruebas, descritos en las Secciones 1.9.1 y 1.9.2 respectivamente.

579
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

B.2.1. Arranque del simulador

Seleccione el icono M odelSim PE del grupo de programas Inicio --+ Programas --+
ModelSim PE Student Edition 6.3c --+ ModelSim. Inicialmente aparecerá la ventana
de bienvenida. Si desea que no vuelva a aparecer marque la casilla "Don't show
this dialog again". Para cerrar esta ventana y acceder a la aplicación pulse el botón
"Close".

Workspace _ _ _ _ ,;:.;;; ·.:ti


;¡¡:j~~;-· ...................... . . . ·-· ·······¡-:¡:;;;;~ ····---J¡;~;¡;-···-· -· --

l±l-iWJ. mtiAvm Library $MODEL_TEO


l±l-iWJ. sv_std Libr ary
l±l-iWJ. vital2000 Libr ary
l±l-iWJ. ieee Library
(j}:.{tj. modelsimjib Library
l±l-iWJ. std Library
l±l-iWJ. std_developerskit Library
l±l-iWJ. synopsys Ubr ary
l±l-iWJ. verilog Library

~ Transcript

Figura B.l: Ventana principal de ModelSim.

Se abrirá entonces la ventana principal del entorno (véase la Figura B.l), que
está compuesta por la barra de menús, la barra de iconos y por los dos elementos
siguientes:

580
MODELSIM PE STUDENT EDITION

"Workspace" Panel situado a la izquierda de la ventana principal.


Al arrancar la aplicación este panel tiene una única
pestaña denominada "Library". En esta pestaña aparecen
los nombres lógicos de las librerías de recursos.
"Transcript" Panel de texto situado en la parte inferior de la ventana
principal. Este panel tiene una doble finalidad:

l. Mostrar los mensajes producidos por la ejecución


de comandos.

2. Permitir teclear comandos en línea. Se mantiene un


histórico de todos los comandos ejecutados. Usando
las teclas j y l se puede acceder a comandos
anteriores y posteriores para ejecutarlos de nuevo.

B.2.2. Creación de un proyecto

Para crear un proyecto, pueden seguirse los pasos siguientes:

l. Seleccione la opción File New ---7 Project. Aparecerá la ventana de diálogo


---7

para la creación de proyectos. En dicha ventana se establece el nombre del


proyecto, su ubicación y el nombre de la librería por defecto.

2. En la casilla "Project N ame", teclee bufferTriestado como nombre del proyecto.

3. En la casilla "Project Location", seleccione el directorio dónde va a ubicar


los ficheros del proyecto. Puede ayudarse del botón "Browse ... " para moverse
por el disco. Si el directorio introducido no existe, la herramienta le pedirá
confirmación para su creación. En este directorio se creará el fichero buffer-
Triestado. mpf

4. En la casilla "Default Library Name", se escribe el nombre de la librería de


trabajo. Por defecto aparece work y, en general, suele emplearse este nombre. El
nombre dado a la librería será el que, una vez creado el proyecto, la herramienta
asigne automáticamente a un directorio ubicado debajo del indicado en el
cuadro "Project Location". En este directorio se almacenarán las unidades de
diseño VHDL compiladas. En la Figura B.2 se muestra el cuadro de diálogo
una vez realizados estos pasos.

5. Pulse el botón "O K".

581
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Copy Settíngs From- - - - - - - - - - - .


!ch_pe_edu_6.3c/modelsim.ini ~ow~ ... 1
~ Copy libraty Mapplngs C' Referente Library Mappings

Figura B.2: Ventana de diálogo para la creación de un proyecto.

u
Create New File
D
Add Existing File

Create Simulation Create New Folder

~ Transcrfpt

Figura B.3: Entorno de simulación tras crear un nuevo proyecto.

B.2.3. Añadir ficheros al proyecto

Al crear un proyecto, se producen los siguientes cambios en el entorno de simulación


(véase la Figura B.3):

Aparece una nueva pestaña en el panel "Workspace" denominada "Project".


Al seleccionar dicha pestaña, se muestran los ficheros que forman parte del
proyecto.

Se muestra el nombre del proyecto en la barra de estado de la parte inferior


izquierda de la ventana principal.

582
MODELSIM PE STUDENT EDITION

- Se abre una ventana de diálogo denominada "Add items to the Project".


Esta ventana, que permite añadir elementos al proyecto, incluye las siguientes
opciones (véase la Figura B.3):

"Create New File" Permite crear un nuevo fichero de diseño.


"Add Existing File" Permite incluir un fichero ya existente en el pro-
yecto actual copiándolo al directorio del proyecto o
referenciándolo desde su ubicación actual.
"Create Simulation" Permite crear configuraciones para simulación.
"Create New Folder" Permite crear directorios virtuales. Estos directo-
rios tienen, sobre la pestaña "Project" del panel
"Workspace", un aspecto similar al de los direc-
torios del sistema operativo. Estos directorios son
internos al proyecto y no se crean realmente en el
disco.

Para crear un nuevo fichero se pueden usar las opciones de la ventana de diálogo
"Add items to the Project". Se pueden acceder a estas mismas opciones a través del
menú Project - t Add to Project.

Creación de un nuevo fichero con código VHDL

Para crear un nuevo fichero con código VHDL, se puede realizar cualquiera de las
dos acciones siguientes:

- Seleccionar el icono "Create New File" en el cuadro de diálogo "Add items to


the Project", que es mostrado en la Figura B.3.

- O bien, seleccionar del menú el comando Project - t Add to Project - t New


File ... Para poder usar el menú, si está abierta la ventana de diálogo "Add
items to the Project", hay que cerrarla presionando el botón "Close".

Con ello, aparece una ventana de diálogo denominada "Create Project File",
que en nuestro caso puede rellenarse como se muestra en la Figura B.4. Tiene los
elementos siguientes:

583
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

u Add file as type


IVHDL
l rFolder
[Top Level ~ 1

Figura B.4: Ventana de diálogo "Create Project File".

File Edit View Compile Simulate Add Source Tools Layout Window Help

~
l iHJ bufferTriestado.vhd 1

Figura B.5: Entorno de simulación tras crear el fichero bufferTriestado.vhd.

"File Name" Permite especificar la ubicación y nombre del


fichero fuente. El botón "Browse ... " nos permite
especificar la ubicación del fichero navegando a
través de las carpetas del sistema. Si especificamos
un nombre del fichero, sin indicar ningún directorio,
éste se guardará en el directorio del proyecto.
"Add File As Type" Permite seleccionar el tipo de fichero.
"Folder" Lista desplegable donde aparecen todos los direc-
torios existentes en el proyecto. En el caso de que
no se haya creado ningún directorio esta lista sólo
tendrá un elemento: "Top Level".

Una vez finalizado este proceso, se crea un fichero denominado buffer Tries-
tado. vhd en el directorio del proyecto. En la Figura B.5 se muestra la ventana
principal tras seguir estos pasos. Observe que en la pestaña "Project" del panel
"Workspace" aparece la información sobre el fichero creado. La información mostrada
es la siguiente:

584
MODELSIM PE STUDENT EDITION

"N ame" Nombre del fichero.


"Status" Símbolo que refleja el estado del fichero:
? El fichero aún no ha sido compilado.
X El fichero se ha compilado y contiene errores.
v El fichero ha sido compilado con éxito.
"Type" Indica el tipo de fichero (VHDL, Verilog, Folder, Simula-
tion).
"Order" Indica la posición del fichero en la secuencia de compila-
ción cuando hay varios ficheros fuente. El primer fichero
de la secuencia de compilación es aquél con un número
menor.
"Modified" Muestra la fecha y hora en que el fichero fue modificado
por última vez.

Al crear el fichero, se abre automáticamente una ventana del editor de texto


del entorno con el fichero vacío como muestra la Figura B.5. Edite, empleando la
ventana del editor de texto mostrada en la Figura B.5, el código VHDL mostrado
en la Sección 1.9.1. Salve el fichero seleccionando la opción File ---t Save del menú
de la ventana del editor o bien pulsando el icono correspondiente. De al fichero el
nombre bufferTriestado. vhd.

u, ft afiré tó Profec ' '' • ff ~

J :Add file as typ


1 !(ietault-

r. Reference from current locatlon r Copy to project dlrectory


~ Cancel !

Figura B.6: Ventana de diálogo "Add file to Project".

Inserción de un fichero existente en el proyecto

Para incorporar al proyecto un fichero ya existente, puede seleccionarse del menú


Project ---t Add to Project ---t Existing File ... Puede realizarse esta misma acción
desde la ventana de diálogo "Add items to the Project", seleccionando la opción "Add
Existing File". Aparece una ventana de diálogo denominada "Add file to Project"
(véase la Figura B.6). Esta ventana tiene los elementos siguientes:

585
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

"File Name" Nombre del fichero. El botón "Browse ... " facilita la
selección de dicho fichero navegando a través de las
carpetas del sistema.
"Add File As Type" Nos permite seleccionar el tipo de fichero.
"Folder" Lista desplegable donde aparecen todos los direc-
torios existentes en el proyecto. En el caso de que
no se haya creado ningún directorio esta lista sólo
tendrá un elemento: "Top Level".
"Copy to project di- Realiza una copia física del fichero desde su locali-
rectory" zación al directorio del proyecto.
"Reference from cu- El fichero se incluye en el proyecto, pero no se copia
rrent location" al directorio del mismo.

B.2.4. Compilación de los ficheros

Para verificar que el código VHDL de un fichero es correcto, es necesario compilar


dicho fichero. Además, con ello se genera el fichero binario que posteriormente
se empleará en la simulación. Algunas formas de realizar la compilación son las
siguientes:

- Seleccionar la opción Compile ----+ Compile All. Mediante esta opción se com-
pilan todos los ficheros del proyecto. El orden de compilación que se sigue es
el indicado en la columna "Order" del panel "Workspace".

Seleccionar la opción Compile ----+ Compile Selected. Mediante esta opción se


compila únicamente el fichero seleccionado.

Situar el ratón en el panel "Workspace" de la ventana principal y pulsar el


botón derecho. Aparece un menú contextua! con varias opciones para lanzar
directamente la compilación. Mediante la opción Compile ----+ Compile Out-
of-Date de este menú se compila únicamente los ficheros que no hayan sido
compilados con éxito anteriormente. Es decir, todos los que no presenten el
icono J en la columna "Status".

- Teclear vcom buffer Triestado. vhd en el panel "Transcript".

La unidad compilada se almacena en la librería work. Para ver su ubicación, se


selecciona la pestaña "Library" del panel "Workspace". Pulsando sobre el signo"+",

586
MODELSIM PE STUDENT EDITION

que aparece a la izquierda de la librería work, podemos ver su contenido (véase la


Figura B. 7). En la librería existe una interfaz (entity) denominada buffer Triestado
y una arquitectura (architecture) llamada behavioral.

G"J 1 o eiSim P S u en Hhhon . e ~


File Edit View Compile Simulate Add Transcript Tools Layout Window Help

Name Path

~
Library work
- E. buffer _triestado Entity D: \Docencia\ETCIII\ TextoBase\ Works ooo
A behavior al Architecture
i1HJl. mtiAvm Library $MODEL_TECH/o o/avm
l±J-1ll sv _std Library $MODEL_TECH/o o/sv _std
8-1Jl vital2000 Library $MODEL_TECH/o o/vital2000
~ieee Library $MODEL_TECH/o o/ieee
l±J-1ll modelsim_lib Library $MODEL_TECH/o o/modelsim_lib
~std Library $MODEL_TECH/o o/std
~ std_developerskit Library $MODEL_TECH/o o/std_developerskit
L:!:Hll synopsys Library $MODEL_TECH/o o/synopsys
~ verilog Library $MODEL_TECH/ .. /verilog

Figura B. 7: Contenido de la librería work tras compilar el fichero buffer Triestado. vhd.

Errores de compilación

Para describir qué sucede cuando hay errores de compilación, vamos a modificar el
fichero buffer Triestado. vhd introduciendo intencionadamente un error: eliminamos
el punto y coma final (;) en la sentencia de asignación siguiente y <= d;

Al guardar el fichero así modificado, su nuevo "status" es ? . Al compilar el fichero,


su "status" cambia a X (véase la Figura B.8), ya que hay un error de compilación.
También, aparece un mensaje de error en color rojo en el panel "Transcript".

Si se hace doble die sobre este mensaje de error del panel "Transcript", se abre
una ventana de diálogo (Unsuccessful Compile), con información sobre el tipo de
error que se ha producido y el número de línea en que aparece.

Si se hace doble die sobre uno de los mensajes mostrados en la ventana Un-
successful Compile, se abre la ventana de edición mostrando el código VHDL del
fichero, con la línea de código que ha producido el error marcada en color naranja

587
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

~~~~~C:j}~~~~~~,~~- ~~~-~~-1;-;-~;;--;;;-]1~~ 7 Loadinq packaqe standard


Loadinq packaqe std_loqic_ll64
Compilinq entity buffer_triestado
Compilinq archi tecture behavioral of buffer triestado
Error: D: /Docencia/ETCIII/Textf:,Base/lJJorkspa;;el1odelSim/bufferTriestado . vhd ( 16)
"else": expecting •; •
Error: D: /Docencia/ETCIII/TextoBase/lJJorkspaceModelSim/bufferTriestado. vhd ( 20)
: VHDL Compiler exitinq

i 11

Figura B.8: Localización del error de compilación.

(véase la Figura B.8). En este caso, la línea 16 aparece en color naranja, debido a
que hemos eliminado el símbolo ; que debería aparecer al final de la línea 15.

B.2.5. Banco de pruebas

El código del banco de pruebas, mostrado en la Sección 1.9.2, debe guardarse en un


fichero llamado bp_bufferTriestado. vhd. Para ello, pueden seguirse los pasos descritos
anteriormente:

l. Seleccione del menú Project --7 Add to Project --7 New File ...

2. Complete la ventana de diálogo "Create Project File" del modo siguiente. En


el cuadro "File Name" escriba bp_bufferTriestado. En la lista desplegable "Add
file as type" seleccione VHDL. Finalmente, pulse "OK".

Tras seguir estos pasos, el panel "Workspace" queda tal como se muestra en la
Figura B.9. 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 --7 Compile All, el
fichero bp_bufferTriestado. vhd se compilará después del fichero bufferTriestado. vhd.
Compile el fichero bp_bufferTriestado. vhd, siguiendo para ello el procedimiento des-
crito en la Sección B.2.4.

588
MODELSIM PE STUDENT EDITION

Existen ocasiones en que el orden de compilación de los ficheros, tal como aparece
en la ventana Workspace, no es correcto y debe ser modificado. Por ejemplo, si en
el fichero paquete. vhd se define un paquete, que se usa en el fichero uso_ paquete. vhd,
entonces es necesario compilar antes el fichero paquete. vhd, ya que en caso contrario
se produce un error de compilación. Puede modificarse el orden de compilación de
los ficheros del modo siguiente:

l. Sitúe el ratón en el área del panel "Workspace" y pulse el botón derecho del
ratón. Aparece así un menú textual.

2. Seleccione en dicho menú la opción Compile---+ Compile Order. .. Aparece una


ventana denominada "Compile Order". Para cambiar el número de orden de un
fichero en la secuencia de compilación, seleccione dicho fichero en la ventana
"Compile Order" y pulse sobre los botones en los que aparece dibujado un
triángulo (véase la Figura B .1 O).
Obsérvese que en la parte inferior de la ventana "Compile Order" hay un botón
con la etiqueta "Auto Generate". Haciendo clic sobre él, ModelSim determina
automáticamente un orden válido de compilación de los ficheros.

589
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Figura B.9: Workspace tras incluir el fichero bp_bufferTriestado.vhd.

~ bufferTriestado.vhd
¡;j bp_butferTnestado .vhd

Botones para cambiar el


orden en la secuencia de~ ·.
compilación ~

Auto Generate 1 ~ Cancel 1

Figura B.lO: Modificación del orden de compilación de los ficheros.

590
MODELSIM PE STUDENT EDITION

B.3. SIMULACIÓN, VISUALIZACIÓN Y DEPURADO

En esta sección se describen los pasos a seguir para realizar la simulación y pa-
ra mostrar los resultados, usando nuevamente el diseño del buffer triestado como
ejemplo.

B.3.1. Activación del modo simulación

Para iniciar el simulador, en la pestaña "Library" se selecciona la entity que que-


remos simular. En este caso, seleccionamos la entity bp_buffer_triestado. Pulsando
sobre ella con el botón derecho del ratón, se abre un menú en el que seleccionamos
"Simulate" (véase la Figura B.ll).

bp_buffer _triestado
Simulate with Cover age
Edit
GJ-j,l sv _std Refresh
GJ-j,l vital2000 Recompile
GJ-j,l ieee Optimize
¡:±.J-Jll modelsim_lib Update
GJ-j,l std Delete
¡:±.J-Jll std_developerskit Copy
¡:±.J-Jll synopsys
GJ-j,l verilog New

Properties ...

1 fr1l Project [.il Library 1

Figura B.ll: Activación del modo simulación.

Al activarse el modo simulación, la ventana principal del simulador se modifica


(véase la Figura B.12). Aparecen tres nuevas pestañas en el panel "Workspace": "sim"
(muestra la jerarquía de diseño), "Files" (muestra los ficheros fuente) y "Memories"
(herramienta de análisis de los arrays de registros del sistema). Asimismo, aparece
el panel "Objects", en el que se muestran las variables, registros, etc., su valor y sus
características.

Para interaccionar con el simulador y visualizar los resultados de la simulación,


la herramienta dispone de un conjunto de paneles. Estos paneles pueden formar
parte de la ventana principal del simulador o pueden ser separados de dicha ventana

591
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

+acc=v
bp_buffer _t ... Process +acc=v
std_logic_l ... Package +acc=v
standard Package +acc=v

Figura B.12: Una vez activado el modo simulación.

a) ~ b) ~
Figura B.13: Botones: a) "undocked"; y b) "docked".

haciendo clic con el ratón sobre el botón "undocked" (véase la Figura B.13a). Para
volver a insertar el panel en la ventana principal, debe presionarse el botón "docked"
(véase la Figura B.13b).

Usando el menú "View", es posible seleccionar qué paneles se hacen visibles. A


continuación, se comenta brevemente la funcionalidad de algunos de los paneles:

"Datafiow" Permite visualizar, de modo gráfico, la conectividad


entre los elementos (procesos, sentencias de asignación
concurrente, etc.) del modelo y rastrear eventos.
"List" Muestra, en modo texto, los valores de las señales y
variables en un formato tabular.
"Process" Muestra la lista de procesos junto con información sobre
su estado.
"Objects" Muestra la lista de señales de la interfaz (entity) selec-
cionada en la pestaña "Sim".
"Wave" Permite visualizar la forma de onda de las señales y
variables.

592
MODELSIM PE STUDENT EDITION

Figura B.14: Panel "Wave".

B.3.2. Visualización de los resultados

En el panel "Wave" se representa la evolución de las señales. Es posible añadir las


señales de interés al panel "Wave" siguiendo uno de los dos procedimientos siguientes:

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 acciones siguientes:

l. Incluir en el panel "Wave" todas las señales que aparecen en el panel


"Objects". Para ello hacemos clic en la opción Add to Wave----+ Signals in
Region.
2. Mostrar una selección de las señales del panel. Para ello hacemos clic en
la opción Add to Wave ----+ Selected Signals. Para seleccionar un conjunto
de señales pulsamos el botón "Shift" del teclado al mismo tiempo que
hacemos clic con el ratón sobre las señales que queremos seleccionar.
Para quitar señales del conjunto seleccionado mantenemos pulsado el
botón "Control" mientras hacemos clic con el ratón sobre las señales que
queremos quitar.

Cabe destacar las siguientes características del panel "Wave" (véase la Figu-
ra B.14):

593
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Se puede adaptar la información visualizada en el panel "Wave" usando los


diferentes iconos de zoom. A continuación, se describe la funcionalidad de los
iconos de zoom:

"Zoom In" Amplia la escala de tiempos.


"Zoom Out" Reduce la escala de tiempos.
"Zoom Full" Cambia el rango de la escala de tiempo de modo que
vaya desde el instante inicial hasta el instante actual de
simulación.

Podemos añadir cursores presionando el botón "Insert Cursor". Al p1e del


cursor se indica el instante de tiempo en que se encuentra situado. Además,
aparece el valor de cada señal en dicho instante de tiempo en el área que hay
junto a los nombres de las señales. Se puede eliminar un cursor presionando el
botón "Delete Cursor", una vez hayamos seleccionando dicho cursor.

B.3.3. Ejecución de la simulación

Los siguientes botones permiten controlar la simulación y realizar el depurado del


modelo (ver Figura B.15):

~1 20 ns iJ ~~[!J!

l
Restart
l
Run Length
lll
Run Continue Run All Step Step Over
Run

Figura B.15: Botones para la simulación y depurado del modelo.

"Run" Ejecuta la simulación durante el tiempo indicado en el


cuadro Run Length de la ventana principal. La simulación
puede detenerse antes, si se han introducido puntos de
ruptura. También puede detenerse antes manualmente
(pulsando el botón Break) o debido a la ejecución de una
sentencia del banco de pruebas.

"Continue Run" Continúa la simulación en curso hasta agotar el tiempo


de simulación por defecto (la simulación puede detenerse
antes por los motivos indicados en el párrafo anterior).

594
MODELSIM PE STUDENT EDITION

"Run- All": Ejecuta la simulación durante tiempo indefinido. Ésta


podrá detenerse si se han incluido puntos de ruptura en el
código, si se interrumpe manualmente (pulsando el botón
Break) o si finaliza la ejecución del código VHDL. En la
zona de estado de la ventana principal (parte inferior) se
muestra el tiempo de simulación.

"Break" Detiene la simulación en curso.


"Restart" Reinicia la simulación. Carga de nuevo el modelo binario,
sitúa el tiempo de simulación en cero y, opcionalmente,
puede mantener el formato dado a algunas ventanas, los
puntos de ruptura, etc.

"Step" Ejecuta la simulación hasta la siguiente sentencia de


código. El valor de las variables en ese punto se puede
visualizar en el panel "Objects".
"Step Over" Ejecuta funciones y procedimientos en un solo paso.

B.3.4. Inserción de puntos de ruptura

A continuación, se describen los pasos a seguir para insertar puntos de ruptura


( breakpoints) en el código:

l. Seleccionamos la unidad de diseño en cuyo código queremos introducir el punto


de ruptura. Las unidades de diseño se muestran en la pestaña "Sim" del panel
"Workspace".

2. Hacemos doble clic sobre la unidad de diseño seleccionada. Aparece así un


panel con el código de dicha unidad de diseño.

3. En el código mostrado en el panel podemos insertar puntos de ruptura usando


el ratón. Las líneas en las que podemos introducir puntos de ruptura son
aquellas cuyo número de línea está en color rojo. Para introducir el punto de
ruptura hacemos die con el ratón en la columna BP de la línea donde queremos
introducir el punto de ruptura.

Para modificar los puntos de ruptura, accedemos a una ventana de diálogo


denominada "Modify Breakpoints". Para ello, seguimos los pasos siguientes:

595
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

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

2. En el menú textual que aparece, seleccionamos la opción "Breakpoints ... ".

end entity Buffer ~


architecture Beha~j
11 begin
12 process (E, d)
13 begin
14 if (E '1' ) then
• - _1._5_ _ 1u__ ,C..:;_
Dtsable Bteakpotnt 15
Remove Breakpoint 15
Edit Breakpoint 15 ...
Edit All Breakpoints .. ,
Cancel
Add/Remove Bookmark

Figura B.16: Inserción de puntos de ruptura.

A continuación, se describe cómo introducir un punto de ruptura en la línea


número 15 del fichero buffer Triestado. vhd (véase la Figura B.16):

l. Hacemos doble clic sobre la unidad de diseño uut. Aparece así un panel que
muestra el código del fichero bufferTriestado. vhd.

2. 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, nos situamos con el ratón sobre el círculo y hacemos clic
con el botón derecho. Se despliega un menú de texto que permite deshabilitar el
punto de ruptura ("Disable Breakpoint") y quitar el punto de ruptura ("Remove
Breakpoint").

596
Índice alfabético

- (don't care), 151 Banco de pruebas, 56, 76, 80, 281, 285,
O, 1 lógicos, 149 296, 302, 308, 426, 433, 440, 445
acceso a fichero, 371
Abierto, 52
Binario, 147
Abstracción, 58
Buffer, 47
nivel de procesador, 62
triestado, 79, 278, 376
nivel de puertas, 60
árbol, 50
nivel de RTL, 61
Bus bidireccional, 389
nivel de transistor, 60
Acoplo, 52 CAD, 34
after, 48, 67, 105, 424 Calidad del test, 54
Agregación de vectores, 155 case, 128, 423
Algoritmo, 73, 517 Casting, 161
Alta impedancia, 79, 151 Ciclo de diseño, 36
Architecture Codificador, 108, 111, 125, 129, 151, 159
comportamiento, 285, 291 Comentarios, 66
estructura, 293, 437 Compilación, 207
architecture, 65, 95, 102 component, 70
comportamiento, 102 Componente
estructura, 102 conexión, 72, 136
sintaxis, 103 Declaración, 135
array, 384 declaración, 70
Asignación concurrente, 67, 104, 278, 286 instanciación, 72, 136
condicional, 107 configuration, 78
de selección, 110 constant, 101
simple, 104 Constante, 101, 143
síntesis, 105, 108, 112 generic, 100, 142, 386
Asignación secuencial, 117, 122 Corto, 52
a señal, 122 Coste, 45
a variable, 124 Código VHDL
assert, 101, 169, 298 análisis, 206
Atributos, 166 compilación, 207
ejecución, 206

597
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

elaboración, 206 event (atributo), 167


inicialización, 206, 211 Evento, 216
simulación, 226 exit, 132

Decodificador, 107, 111, 125, 129, 278, failure, 169


378 falling_edge, 167, 398
delayed (atributo), 217 Fichero, 96, 371
Descripción del hardware lectura, 372
mediante esquemático, 34 modo de acceso, 372
mediante lenguaje, 34 file, 372
modular y jerárquica, 135 file_close, 372
Detector file_open, 372
de paridad, 64, 66, 70, 73, 76, 139 Flip-fiop, 422
de secuencias, 420, 528 D, 121
Diagrama JK, 425
conceptual, 67, 73, 105, 109, 112 for, 73, 115, 132, 361, 368, 372
de estados, 419 FSM, 517
Diseño marginal, 50 FSMD, 518
Don't care, 151, 159 Fuertemente tipado, 146
downto, 192, 284 Función, 170, 298
Driver, 208, 378 de resolución, 209, 378
lógica, 280
Ejecución
function, 170
concurrente, 49, 114
Enable, 378, 422 generate, 115, 139
endfile, 372 generic, 100
Entidad de diseño, 95 Glitch, 47
entity, 65, 95, 97
HDL, 33
constant, 101
aplicaciones, 35
puerto, 98
flujo de desarrollo, 63
sintaxis, 101
ventajas, 34
error, 169
Hexadecimal, 147, 377, 384
Estructura, 70
high (atributo), 166
Estándar IEEE
1067-1987 (VHDL'87), 36 if, 124, 285, 423
1076-1993 (VHDL'93), 36 sin rama else, 127
1076-2001 (VHDL-AMS), 36 image (atributo), 166
1076.6 (VHDL sintetizable), 95 Inicialización, 122, 206, 211, 424
1364-1995 (Verilog), 36 Interfaz, 95
1666-2005 (SystemC), 36

598
ÍNDICE ALFABÉTICO

Latch, 422 concatenación, 155


left (atributo), 166 paquete IEEE.numeric_std, 158
length (atributo), 166 paquete IEEE.std_logic_1164, 153
Ley de Moore, 33 precedencia, 14 7
library, 150, 168 relacional, 154
Librerías VHDL, 167 sobrecarga, 153
IEEE.matlLreal, 168 others, 156, 376, 449
IEEE.numeric_std, 157, 158, 168
package, 168, 176, 302, 308, 430, 552
IEEE.std_logic_1164, 149, 168
package body, 176
std, 169
Palabras reservadas, 65
work, 169
Parametrización, 142
Lista de sensibilidad, 73, 117, 118, 120,
121, 21 1 Patrón de fallo, 52
port, 98
low (atributo), 166
Procedimiento, 172, 298
Memoria procedure, 172, 427
de lectura y escritura, 388 Procesamiento del código, 206
de sólo lectura, 386 process, 72, 76, 116, 211, 280, 285, 424
Metodología RT, 517 Programa de test, 52
Modelo de fallo, 52 Programa RT, 520
ModelSim, 79, 579 Protocolo de handshaking, 531
Multiplexor, 107, 111, 125, 129, 136, 139, Puerta
278, 285 AND, 103, 139
Multiplicador, 279 NAND , 278
Máquina de estado finito NOT, 70, 103, 278
segura, 448 XOR, 70, 103, 133, 278
de Mealy, 419, 439 Puerto, 95, 97
de Moore, 419, 430 in, 98
método de diseño, 419 inout, 98
out, 98
Netlist, 36
next, 132 quiet (atributo), 217
Notación RT, 517
range (atributo), 166
note, 169
read, 372
now, 163, 298
readline, 372
Octal, 147 Red de prioridad, 109
One-hot encoding, 449 Registro
Operaciones RT, 518 de 4 bits, 35 7
Operador, 147 de desplazamiento, 368

599
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

entity, 102 atributos, 166, 216


multifunción, 360 bloque process, 117
register file, 375 declaración, 67, 72
triestado, 376 evento, 216
Rendimiento, 52 fortaleza, 50
report, 163, 169, 298 implícita, 217
Representación puerto, 97
comportamiento, 57 transacción, 216
estructura, 58 shift, 159
física, 58 Simulación, 35
Reset eventos discretos, 49
asíncrono, 121, 425 stable (atributo), 166, 217
síncrono, 358, 368, 375, 376, 439 std_match, 159
resize, 159 string, 298
Restador, 291 Subprograma, 170
completo de 1 bit, 291 Sumador, 279, 301
Retardo, 423 SystemC, 36
de transporte, 47, 105, 225 Síntesis, 35, 36, 105, 108, 109, 112, 115,
della, 49, 69, 105, 219 127, 131, 133, 134, 147
diseño marginal, 50 de lógica combinacional, 277
inercial, 47, 105, 222 de lógica secuencial, 422
puro, 47
Tabla
return, 170
de la verdad, 64
Reutilización, 70
de transición de estados, 419
reverse_range (atributo), 166
Tecnología
right (atributo), 166
ASIC, 38
rising_edge, 16 7
circuitos estándar, 42
rotate, 159
comparación, 42
Sean fiip-fiops, 54 coste, 45
Sensibilidad CPLD, 41
bloque process, 117 field programmable, 41
Sentencia FPGA, 38, 41- 43
concurrente, 104, 107, 110, 114, 278, full-custom ASIC, 39
286 gate array ASIC, 40, 43
secuencial, 117, 122 non-ASIC, 38
severity, 169 PAL, 42
Señal, 143 PLA, 42
activa, 216 PLD, 38, 42

600
ÍNDICE ALFABÉTICO

potencia consumida, 44 transport, 48, 105


programable en campo, 41 type, 164, 384
PROM, 42
U (unini tialized) , 151
standard-cell ASIC, 40, 43
Uni dad Aritmético Lógica, 306
velocidad, 44
Unidad de diseño, 95
área, 43
use, 150, 168
Test, 51
UUT (Unit Under Test), 56
banco de pruebas, 56
cobertura de fallos, 53 Variable, 143
funcional, 54, 55 asignación, 124
manufactura, 54 declaración, 117
modelo de fallos, 52 Variable de estado, 419, 421
modos de fallo, 52 Vector de bits, 147
programa, 34 Vector de test, 52
vector, 34, 52 VeriBest VHDL, 79, 563
Tipo de datos, 145 Verificación
atributos, 166 de tiempos, 37
bit, 146 funcional, 36
bit_vector, 146 Verilog HDL, 35
boolean, 146 VHDL, 34
conversión, 153, 160 sintetizable, 95
definido por usuario, 163
enumerado, 164 wait, 118, 121, 170, 187, 360, 423, 425
integer, 146, 286 wait for , 120, 284
operadores, 147 wait on, 118, 211
paquete IEEE.numeric_std, 156 wait until, 119
paquete IEEE.std_logic_ll64, 149 warning, 169
predefinidos en VHDL, 146 when, 107, 277
signed, 157 while, 132, 372
stcLlogic, 150, 151 with, 423
std_logic_vector, 150, 152 with-select, 110
string, 163
X (unknown), 151
time, 163
unsigned, 157 Z (alta impedancia), 151
to_integer, 160
to_signed, 161
to_unsigned, 161
Transacción, 216
transaction (atributo), 217

601
Bibliografía

Armstrong, J. & Gray, F. (2000), VHDL Design, Representation and Synthesis,


Prentice Hall.

Ashenden, P. J. (2002), The designer's guide to VHDL, Margan Kaufmann Publis-


hers.

Brown, S. & Vranesic, Z. (2006), Fundamentos de Lógica Digital con Diseño VHDL,
Me Graw-Hill.

Chang, K. C. (1997), Digital Design and Modeling with VHDL and synthesis, IEEE
Computer Society Press.

Chu, P. P. (2006) , RTL Hardware Design using VHDL , Wiley-Interscience.

Cohen, B. (1995), VHDL Coding Styles and Methodologies, Kluwer Academic


Publishers.

Heinkel, U. (2000), The VHDL reference, John Wiley & Sons.

Hwang, E. O. (2005), Digital Logic and Microprocessor Design with VHDL, Cengage-
Engineering.

IEEE-SA Standards Board (2000), IEEE Standard VHDL Language Reference


M anual, IEEE.

Lee, S. (2006), Advanced Digital Logic Design: Using VDHL, State Machines and
Syntesis for FPGAs, Thomsom Canada Limited.

Mentor Graphics Corporation (2008), ModelSim LE/PE


User's Manual. Software Version 6.3e. Disponible en:
http:/ /www.model.com/resources/resources_manuals.asp.

Pardo, F. & Boluda, J. A. (2004) , VHDL, Lenguaje de Síntesis y Modelado de


Circuitos, RA-MA.

603
DISEÑO Y ANÁLISIS DE CIRCUITOS DIGITALES CON VHDL

Pedroni, V. A. (2004), Circuit Design with VHDL, MIT Press.

Perry, D. L. (2002), VHDL: Programming by Example, McGraw-Hill.

Salcic, Z. & Smailagic, A. (2000), Digital Systems Design and Prototyping, Kluwer
Academic Publishers.

Sjoholm, S. & Lindh, L. (1997), VHDL for Designers, Prentice Hall.

Vahid, F. & Lysecky, R. (2007), VHDL for Digital Design, Wiley.

VeriBest Inc. (1998), Documentación en línea de VeriBest VB99.0. Suministrada


con VeriBest VB99.0.

604

También podría gustarte