memoria main

141
TRABAJO DE FINAL DE CARRERA TÍTULO DEL TFC: Introducción al diseño de sistemas digitales reconfigurables en FPGA con VHDL y la tarjeta Spartan-3AN de Xilinx TITULACIÓN: Ingeniería Técnica de Telecomunicaciones, especialidad Sistemas de Telecomunicaciones. AUTOR: Sergio García López DIRECTOR: Francesc Josep Sánchez y Robert DATA: 29 de junio de 2010

Upload: miguel-panduro

Post on 08-Nov-2014

31 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Memoria Main

TRABAJO DE FINAL DE

CARRERA

TÍTULO DEL TFC: Introducción al diseño de sistemas digitales reconfigurables en FPGA

con VHDL y la tarjeta Spartan-3AN de Xilinx

TITULACIÓN: Ingeniería Técnica de Telecomunicaciones, especialidad Sistemas de

Telecomunicaciones.

AUTOR: Sergio García López

DIRECTOR: Francesc Josep Sánchez y Robert

DATA: 29 de junio de 2010

Page 2: Memoria Main

2

Page 3: Memoria Main

3

Resumen

Este trabajo pretende ser una guía para conocer el funcionamiento de la FPGA

Spartan-3AN de Xilinx y su software.

En el capítulo 2 se explicará cómo crear un proyecto simple, compilarlo,

simularlo y grabarlo en la placa para ver su funcionamiento de forma visual.

En el capítulo 3 se elaborará un doble contador síncrono de 4 bits. Uno de los

contadores vendrá gestionado por un divisor de frecuencia creado

manualmente y el otro por la herramienta de gestión de reloj que nos

proporciona el fabricante (Direct Clock Manager). Mediante estos contadores

analizaremos la eficiencia de los divisores de frecuencia utilizados, realizando

simulaciones a nivel de circuito (gate-level) del ModelSim para comparar

retardos de propagación.

La última parte de la explicación será la creación de una máquina de estados

para gobernar un conjunto de componentes compuestos. Los datos

provenientes de estos componentes serán convertidos al formato correcto

para ser visualizados mediante la pantalla LCD, que es un periférico de la

Spartan-3AN.

La explicación de esta última parte vendrá adscrita a la realización del

proyecto de este documento, que será la creación de un reloj en tiempo real

similar en prestaciones y funcionamiento al que se pueda llevar en la muñeca.

Titulo: Introducción al diseño de sistemas digitales reconfigurables en FPGA

con VHDL y la tarjeta Spartan-3AN de Xilinx

Autor: Sergio García López

Director: Francesc Josep Sánchez y Robert

Fecha: 29 Junio de 2010

Page 4: Memoria Main

4

Overview

This project is a guide to understand the operation process of the FPGA Spartan

3AN of Xilins and its programmation.

Chapter 2 explains how to create a simple project, compile, simulate it and record

it on the plate to see it working visually.

Chapter 3 will develop a dual 4-bit synchronous counter. The first counter is

controlled by a frequency divider created manually and the second is controlled by

a Xilinx management tool (Direct Clock Manager). Using these counters will

analyze the efficiency of crossovers used by circuit level simulations of ModelSim

to compare the propagation delays.

The last part of the explanation is the creation of a state machine to control

composite components. The information on these components will be converted

into the correct format for viewing through the LCD screen, the screen is a

peripheral of the Spartan-3AN.

The explanation for this latter part is the realization of the project, the project is the

creation of a real time clock similar in features and performance to a personal

wristwatch.

Title: Introduction to digital systems design with VHDL FPGA reconfigurable

card and Xilinx Spartan-3AN

Author: Sergio García López

Director: Francesc Josep Sánchez y Robert

Date: 29 Junio de 2010

Page 5: Memoria Main

5

Page 6: Memoria Main

6

Índice

1. Introducción .................................................................................... 12

2. Sistemas combinacionales. .............................................................. 14

2.1. Flujo de diseño..................................................................................................... 14

2.2. Uso de los Leeds y los pulsadores. ...................................................................... 15

2.2.1. RTL y Código de la aplicación. .......................................................................... 15

2.2.1.1. RTL ................................................................................................................ 15

2.2.1.2. Código de la aplicación. ................................................................................ 15

2.2.2. Simulación del código. ..................................................................................... 16

2.2.2.1. Archivo DO para simulaciones en ModelSim. .............................................. 17

2.3. Spartan-3AN Non-Volatile FPGA Starter Kit. ....................................................... 19

2.3.1. Arquitectura interna. ....................................................................................... 19

2.3.1.1. Lógica de bloques configurable o Configurable Logic Blocks (CLBs) . .......... 19

2.3.1.2. Entradas y salidas de los bloques o Input/Output Blocks (IOBs). ................ 20

2.3.1.3. RAM. ............................................................................................................. 20

2.3.1.4. Multiplicador de bloques. ............................................................................ 20

2.3.1.5. Control de Reloj o Digital Clock Manager (DCM). ........................................ 20

2.4. ISE Project Navigator. .......................................................................................... 21

2.4.1. Creación de un proyecto. ................................................................................. 22

2.4.2. Escritura del código. ......................................................................................... 26

2.4.3. Asignación de pines. ........................................................................................ 28

2.4.3.1. Editar el archivo .UCF de forma manual. ..................................................... 28

2.4.3.2. PlanAhead .................................................................................................... 29

2.5. Síntesis y Simulación temporal de circuito. ......................................................... 32

2.5.1. TestBench para simulaciones en ModelSim. ................................................... 33

2.5.1.1. Código TestBench ......................................................................................... 35

2.5.2. Simulación temporal. ....................................................................................... 36

2.6. Grabado del código. ............................................................................................ 37

2.6.1. Alimentación y comunicación con la placa. ..................................................... 37

Page 7: Memoria Main

7

2.6.2. Identificación de la Spartan-3AN. .................................................................... 38

2.6.3. Introducir un código. ....................................................................................... 38

2.6.4. Configuración de los Jumpers a la hora de grabar un código en la memoria de

la Spartan-3AN. ............................................................................................................... 39

2.6.4.1. Master Internal SPI. ...................................................................................... 40

2.6.5. Grabar el código. .............................................................................................. 41

2.6.5.1. Programar la memoria Flash y cargar la FPGA. ............................................ 41

2.6.5.2. Programas FPGA únicamente. ..................................................................... 42

2.7. Comprobación del funcionamiento. .................................................................... 43

3. Sistemas secuenciales. .................................................................... 44

3.1. Metodología para dividir la frecuencia de entrada y gestionar un contador

binario síncrono de Modulo 11. ..................................................................................... 44

3.1.1. Divisor de frecuencia. ...................................................................................... 45

3.1.1.1. Especificaciones. .......................................................................................... 45

3.1.1.2. Esquema divisor de frecuencia. ................................................................... 46

3.1.1.3. Diagrama de estados Divisor de frecuencia. ................................................ 47

3.1.1.4. Código divisor de frecuencia. ....................................................................... 48

3.1.1.5. Simulación divisor de frecuencia. ................................................................ 49

3.1.2. Contador síncrono binario de Modulo 11. ...................................................... 51

3.1.2.1. Especificaciones. .......................................................................................... 51

3.1.2.2. Esquema del Contador. ................................................................................ 52

3.1.2.3. Diagrama de estados del Contador. ............................................................. 52

3.1.2.4. Código del Contador. .................................................................................... 53

3.1.3. Código top Contador. ....................................................................................... 54

3.1.3.1. Código archivo top Contador. ...................................................................... 55

3.1.3.2. Simulación funcional Contador + Divisor de frecuencia. ............................. 56

3.1.4. DCM (Digital Clock Manager) ........................................................................... 60

3.1.4.1. Especificaciones. .......................................................................................... 60

3.1.4.2. Esquema del componente. .......................................................................... 60

3.1.4.3. Configuración del componente DCM. .......................................................... 61

3.1.4.4. Código Top del sistema completo ................................................................ 63

Page 8: Memoria Main

8

3.1.4.5. RTL del Contador + DCM + Divisor de frecuencia. ....................................... 67

3.1.5. Simulación funcional Contador + DCM + Divisor de frecuencia. ..................... 68

3.1.6. Síntesis y simulación temporal Contador + DCM + Divisor de frecuencia. ..... 69

4. Reloj en tiempo real programable. .................................................. 71

4.1. Especificaciones del Reloj. ................................................................................... 71

4.2. Esquema de control del sistema. ........................................................................ 72

4.2.1. Controlador. ..................................................................................................... 72

4.2.2. DATAPATH ........................................................................................................ 73

4.2.2.1. Gestión del tiempo. ...................................................................................... 73

4.2.2.2. Preparación de datos. .................................................................................. 73

4.2.2.3. Efecto de parpadeo. ..................................................................................... 74

4.2.2.4. Visualización. ................................................................................................ 74

4.2.3. Gestión del reloj. .............................................................................................. 74

4.3. Divisor de frecuencia. .......................................................................................... 75

4.3.1. Divisores de frecuencia conectados en cascada. ............................................. 75

4.3.1.1. Esquema divisores de frecuencia en cascada. ............................................. 75

4.3.2. DCM (Direct Clock Manager) + Divisores en cascada. ..................................... 76

4.3.2.1. Esquema de conexione DCM + Divisores en cascada. ................................. 77

4.3.2.2. Códigos Divisor de frecuencia. ..................................................................... 78

4.3.2.3. Simulación Divisor de frecuencias. ............................................................... 78

4.3.2.4. Medida real de las frecuencias a la salida de los Divisores y el componente

DCM………… ..................................................................................................................... 78

4.4. Control horas, minutos y segundos. .................................................................... 80

4.4.1. Modulo 60. ....................................................................................................... 80

4.4.1.1. Comportamiento bloque Modulo 60. .......................................................... 80

4.4.1.2. Estructura interna Modulo 60. ..................................................................... 81

4.4.1.3. Código Modulo 60 ........................................................................................ 82

4.4.1.4. Simulación Modulo 60. ................................................................................ 82

4.4.2. Modulo de horas. ............................................................................................. 83

4.4.2.1. Codigo modulo horas. .................................................................................. 84

4.4.2.2. Simulación modulo horas. ............................................................................ 84

Page 9: Memoria Main

9

4.5. Maquina de estados. ........................................................................................... 85

4.5.1. Esquema estados de la Maquina de estados. .................................................. 85

4.5.2. Código del CASE de control. ............................................................................. 86

4.5.3. Esquema conexiones Maquina Estados. .......................................................... 87

4.5.4. Código Máquina estados. ................................................................................ 87

4.5.5. Simulación Maquina estados. .......................................................................... 88

4.6. LCD ....................................................................................................................... 89

4.6.1. Comportamiento del código. ........................................................................... 89

4.6.2. Modificación del código inicial. ....................................................................... 90

4.6.2.1. Proceso de adquisición de datos a mostrar. ................................................ 91

4.7. Convertidor de 4 bits a ASCII. .............................................................................. 92

4.7.1. Método de conversión. .................................................................................... 92

4.7.2. Código Convertidor. ......................................................................................... 93

4.7.3. Simulación se la conversión. ............................................................................ 93

4.8. Parpadeo del número seleccionado. ................................................................... 94

4.8.1. Método de funcionamiento del parpadeo de la cifra. .................................... 94

4.8.2. Código parpadeo. ............................................................................................. 96

4.8.3. Simulación parpadeo. ...................................................................................... 96

4.9. Esquema final completo. ..................................................................................... 97

4.9.1. Código archivo top global. ............................................................................... 97

4.9.2. Esquema teórico global. .................................................................................. 98

4.9.3. RTL del sistema completo. ............................................................................... 99

4.9.4. Comprobación de la aplicación ...................................................................... 100

4.9.4.1. UCF Aplicación. ........................................................................................... 100

5. Posibles mejoras. .......................................................................... 101

6. Conclusiones ................................................................................. 102

7. Bibliografía .................................................................................... 103

7.1. Tutoriales en formato PDF que proporción la Web de Xilinx. ........................... 103

Page 10: Memoria Main

10

7.2. Control Flash. ..................................................................................................... 103

7.3. Control del LCD .................................................................................................. 103

7.4. VHDL Test Bench ................................................................................................ 104

7.5. EPSC Pagina Electrónica digital y Sistema Electrónicos Digitales. ..................... 104

8. Anexos .......................................................................................... 105

8.1. Códigos. ............................................................................................................. 105

8.1.1. Freg_divider_top ............................................................................................ 105

8.1.1.1. Freg_divider_49999. .................................................................................. 106

8.1.1.2. Freg_divider_100. ...................................................................................... 107

8.1.1.3. Freg_divier_10. ........................................................................................... 107

8.1.1.4. TestBench para simulación (freg_divider_top). ......................................... 108

8.1.2. Control Temporal. .......................................................................................... 110

8.1.2.1. Modulo 60. ................................................................................................. 110

8.1.2.2. TestBench para simulación (Modulo60). ................................................... 115

8.1.2.3. Modulo 24. ................................................................................................. 116

8.1.2.4. TestBench para simulación (Modulo24). ................................................... 117

8.1.3. Conversión de datos. ..................................................................................... 119

8.1.3.1. Prub3. ......................................................................................................... 119

8.1.3.2. TestBench para simulación (Prub1). .......................................................... 120

8.1.4. Control Visual. ................................................................................................ 121

8.1.4.1. Parpadeo. ................................................................................................... 121

8.1.4.2. TestBench para simulación (Parpadeo). .................................................... 123

8.1.4.3. LCD. ............................................................................................................. 125

8.1.5. Control. .......................................................................................................... 130

8.1.5.1. Máquina de estados. .................................................................................. 130

8.1.5.2. TestBench para simulación (Máquina estados). ........................................ 134

8.1.6. Archivo top de todo el sistema. ..................................................................... 136

8.1.7. Archivo .UCF. .................................................................................................. 141

Page 11: Memoria Main

11

Page 12: Memoria Main

12

1. Introducción

En este proyecto se pretende hacer una pequeña guía para introducir al lector

en la programación de la Spartan-3AN. Se explicara el uso del software que

proporciona el fabricante para escribir, simular, compilar y grabar el código en

la placa.

La explicación intentará seguir el proceso lógico que haría un inexperto en la

materia, ofreciéndole paulatinamente las herramientas y las soluciones para ir

resolviendo los problemas que se le van planteando.

Se partirá de la base que el lector conoce las instrucciones básicas del

lenguaje VHDL, puesto que la finalidad del proyecto es que esta información

pueda ser útil para impartir clase en la escuela.

La estructura del trabajo empieza desde un código muy simple, que establece

una asignación directa entre entradas y salidas de la placa. A partir de este

primer diseño se hará una descripción del programa Project Navigator para su

familiarización. Se explicara como introducir un código de forma correcta en la

placa, como comprobar su funcionamiento mediante la simulación en

ModelSim, en sus diferente escalones de simulación, y finalmente como

asignar las entradas y salidas a ping físicos de la placa, a fin de grabar el

programa y ver su comportamiento de forma visual, siempre que esto sea

posible.

El segundo punto de interés es realizar un código dependiente de un reloj

interno o externo, puesto que la mayoría de tecnología que nos rodea está

plagada de procesos síncronos. En este nuevo diseño se implementara un

contador síncrono de 4 bits, el cual estará controlado por un divisor de

frecuencia que modificara la entrada de reloj de 50 MHz disponible en la placa,

a un valor predefinido por el usuario. Para el control del contador mediante este

componente, se explicara como declara el divisor y como definir entradas y

salidas del mismo dentro del archivo global contador. Este código permitirá la

declaración y el uso del reloj a la hora de simular diseños síncronos.

En este punto de la narración ya se dispondrán de las herramientas necesarias

para crear un componente, usar el reloj de la placa adecuando la frecuencia a

un valor predefinido y declarar un componente dentro de otro o en un archivo

global a fin de crear dependencias entre ellos.

Siguiendo la filosofía descrita, el siguiente paso a realizar es crear un bloque

capaz de hacer uso del reloj, compuesto por un conjunto de componentes que

establezca una relación de dependencia o sumisión unos de otros, a fin de ser

capaces de transmitir una cierta información a un periférico de la placa.

Page 13: Memoria Main

13

Para lograr este propósito, se diseñara un reloj en tiempo real igual al que se

puede llevar en la muñeca, en el cual se podrá elegir su método de

funcionamiento y puesta en hora.

Este dispositivo será la aplicación, propiamente dicho, del proyecto y dará pie a

la introducción de la última parte que se desea explicar en este documento. El

reloj estará controlado por una maquina de estados, la cual será descrita

cuidadosamente.

Finalmente los datos podrán ser visualizados mediante la pantalla LCD de la

placa. Esto evoca al último bloque del condigo que será la incorporación de un

periférico al diseño.

Al parecer del autor del proyecto, esto es todo lo necesario para programar la

FPGA, y pese a que los bloques y los periféricos pueden ser tan complicados

como la imaginación de su creador, deja al lector con las instrucciones básicas

para este nivel de programación, situándolo así en la antesala del siguiente

nivel, que es la compilación del código utilizando el micro controlador.

Page 14: Memoria Main

14

2. Sistemas combinacionales.

Son aquellos códigos en que las salidas dependen exclusivamente de las

entradas y su respuesta es constante y deducible matemáticamente.

Circuito

Combinacional.

X( n-1 ...0 ) Y( m-1 ...0 )

Figura 1 Circuito combinacional.

2.1. Flujo de diseño.

La metodología de trabajo a seguir para el diseño de cualquier proyecto es la

mostrada en la figura siguiente ( Figura 2 Flujo de diseño. ) y se ha de seguir

escrupulosamente para realizar cualquier recurso.

Especificaciones

Crear RTL

Y Código de la aplicación

Simulaciones funcionales

Simulación a nivel de

puertas lógicas.

Configuración de pines para

una FPGA concreta.

Grabar el codigo en la

FPGA

Prototipo de la aplicación.

No correcto.

Flu

jo d

e d

ise

ño

.

Síntesis del código

Correcto

Correcto

Correcto

No correcto.

No correcto.

Correcto.

Correcto.

Correcto.

Figura 2 Flujo de diseño.

Page 15: Memoria Main

15

2.2. Uso de los Leeds y los pulsadores.

Se desea establecer una asignación entre los 4 selectores de entrada y 4 leeds

de salida.

2.2.1. RTL y Código de la aplicación.

El código estará escrito en VHDL y el esquema de conexiones mostrara el

encapsulado del componente.

2.2.1.1. RTL

4 Entradas

4 Salidas

LDR[0]SW[0]

SW[1]

SW[2]

SW[3]

LDR[1]

LDR[2]

LDR[3]

Figura 3 RTL 4 Entradas 4 Salidas.

2.2.1.2. Código de la aplicación.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity Prub1 is

Port ( SW : in STD_LOGIC_VECTOR (3 downto 0);

LDR : out STD_LOGIC_VECTOR (3 downto 0));

end Prub1;

architecture Behavioral of Prub1 is

begin

LDR <= NOT(SW);

end Behavioral;

Código 1 Prub1.

Page 16: Memoria Main

16

2.2.2. Simulación del código.

La simulación del código se realizara mediante ModelSim.

El programa muestra el aspecto siguiente:

Figura 4 Ventana principal ModelSim.

-En la ventada señalada con el número 1 aparecen todas las bibliotecas

utilizadas por el programa y el código seleccionado para su simulación.

-La siguiente ventana contiene las señales activas para simular, en esta

ventana se pueden añadir o eliminar las señales que se desee mostrar.

-En la tercera muestra el seguimiento grafico de la simulación.

-Finalmente en la última ventana señalada con el numero 4, se podrán ver

todas las incidencias en la simulación y acceder al los archivos .DO que

contendrán las directrices de la simulación, siempre que no se implemente el

TestBench desde el mismo programa de diseño.

Page 17: Memoria Main

17

2.2.2.1. Archivo DO para simulaciones en ModelSim.

Dentro del archivo .DO se definen las señales que se utilizarán para las

simulaciones, el periodo de reloj y el paso a paso en la simulación. Este último

vendrá dividido temporalmente según los tiempos de espera definidos por el

usuario y las condiciones para cada espera.

restart

add wave SW

add wave LDR

force SW 1011

run 100

force SW 0011

run 100

force SW 1100

run 100

force SW 1001

run 100

force SW 0101

run 100

run 200

Código 2 Archivo .DO.

Se reinician los registros.

Se definen las variables a utilizar.

Add wave” nombre señal”.

Se fuerza un valor de entrada y se espera un tiempo prudencial de ejecución

para observar los resultados.

Forcé “nombre entrada” “valor deseado”

Run “Tiempo deseado”

El archivo .DO se debe introducir en la raíz de la carpeta que contenga el código a simular. La forma de ejecutar el archivo es desde la ventana señalada con el número 4, dentro de la presentación de la página principal del ModelSim.

En esta ventana ( Figura 4 Ventana principal ModelSim. ) se puede introducir texto. La forma de introducir el comando de ejecución es la siguiente:

Do “nombre_archivo”.do

Una vez hecho lo anterior aparecerá una tabla de opciones, tras restaurar, en la ventana de representación grafica aparecerá la simulación efectuada.

Page 18: Memoria Main

18

Figura 5 1era Simulación paso 4.

La simulación funcional es correcta y como se puede observar en el código y en las especificaciones de los leeds, éstos son activos a nivel bajo. Es por esa razón que en el código las salidas están negadas, y en la simulación las señales va a la inversa entradas respecto salidas.

Page 19: Memoria Main

19

2.3. Spartan-3AN Non-Volatile FPGA Starter Kit.

La placa en la cual se implementarán los diseños es la Spartan-3AN de Xilinx.

Figura 6 Spartan-3AN.

La FPGA tiene prácticamente la misma conectividad que una placa base de un ordenador convencional a diferencia, claro, que es totalmente programable.

2.3.1. Arquitectura interna.

La arquitectura de la FPGA Spartan-3AN es compatible con el de la FPGA

Spartan-3ª. La arquitectura se compone de cinco elementos fundamentales,

funcionales y programables.

2.3.1.1. Lógica de bloques configurable o Configurable Logic Blocks

(CLBs) .

Contiene tablas de consulta flexibles o Look-Up Tables (LUTs) que

implementan la lógica de los circuitos y configuran la estructura básica de los

flip-flops internos.

Page 20: Memoria Main

20

2.3.1.2. Entradas y salidas de los bloques o Input/Output Blocks

(IOBs).

Controla el flujo de datos entre los pines y la lógica interna del dispositivo,

gestionan la prioridad de señales y estados de los registros

2.3.1.3. RAM.

Este bloque es el encargado del almacenamiento de datos del circuito, en

forma de bloques de dos puertos de 18K-bits cada uno de ellos.

2.3.1.4. Multiplicador de bloques.

Multiplica dos números binarios de 18 bits como sumas de ellos para calcular el

producto.

2.3.1.5. Control de Reloj o Digital Clock Manager (DCM).

Ofrece una auto calibración del reloj de entrada y diferentes operaciones sobre

el mismo, como pueden ser multiplicaciones y divisiones de frecuencia o

cambios de fase.

Figura 7 Arquitectura interna Spartan-3AN ( Spartan-3AN FPGA Family Data Sheet).

Page 21: Memoria Main

21

Estos elementos están organizados como se muestra en la Figura 7

Arquitectura interna Spartan-3AN ( Spartan-3AN FPGA Family Data Sheet). en

una doble disposición de salidas que rodea el conjunto.

Cada dispositivo tiene dos columnas de RAM a excepción XC3S50AN que

dispone únicamente de una. Los bloques de memoria están asociados

mediante un multiplicador dedicado.

La Spartan-3AN dispone de una amplia red de conexiones en forma matricial

para conectar cada uno de los dispositivos, con la finalidad de ofrecer una

buena calidad de señales internas.

2.4. ISE Project Navigator.

Siguiendo la metodología de trabajo, ahora es el momento de realizar la

asignación de pines, y es en este punto donde se explicará el funcionamiento

de la herramienta utilizada para llevar esto a cavo.

Ilustración 1 Marca corporativa.

El programa que se utilizará para programar es ISE Project Navigator de Xilinx

que proporciona la pagina web (http://www.xilinx.com/) en su versión ISE

WebPACK™ edición.

La ventana principal muestra el aspecto siguiente:

Figura 8 Principal ISE.

Page 22: Memoria Main

22

La ventana es similar a la que puede proporcionar cualquier programa de

Windows, en su parte superior izquierda aparece el menú de opciones y

accesos directos a diferentes herramientas de diseño.

En la parte media de la ventana a la izquierda presenta los archivos que están

cargados en el diseño, y en la parte derecha actualmente está cargado Design

Summary, que muestra un resumen detallado de las configuraciones del

diseño.

Por último, en la parte inferior presenta un gran espacio en blanco que está

destinado a mostrar los posibles errores de programación es sus diferentes

etapas, ya sea de compilación, en sus diferentes niveles, como de simulación.

2.4.1. Creación de un proyecto.

El proceso a seguir a la hora de crear nuestro proyecto es File->New Project y

aparecerá la ventana siguiente:

Page 23: Memoria Main

23

Figura 9 Paso 1 Creación proyecto.

En esta ventana se definirá el nombre del proyecto y la localización, en cuanto

a la localización es recomendable no utilizar direcciones muy largas para evitar

errores a la hora de cargar ficheros. El nombre podrá ser modificado

posteriormente.

En el siguiente paso se prestara atención a 3 puntos, pero hay que tener en

cuenta que es necesario conocer en qué placa se implementara el código y las

características de la misma a la hora de rellenar correctamente la totalidad de

los campos de este formulario.

Page 24: Memoria Main

24

Figura 10 Paso 2 Creación proyecto.

En el primer punto marcado en rojo en la (Figura 10 Paso 2 Creación proyecto.)

corresponde al los lenguajes de programación que soporta la placa que se ha

descrito en el resto del formulario.

El segundo punto muestra los diferentes programas de simulación que se

pueden utilizar a la hora de comprobar el correcto funcionamiento del proyecto.

Se seleccionara Modelsim-SE VHDL puesto que es el recurso de simulación

utilizado por la escuela en asignaturas como ED (Electrónica digital) o SED

(Sistemas electrónicos digitales).

Por último el lenguaje utilizado para describir el funcionamiento del proyecto

será VHDL.

Page 25: Memoria Main

25

Figura 11 Paso 3 Creación proyecto.

En el tercer paso se agruparan los dos siguientes saltos en la creación, puesto

que estas dos ventanas son muy similares. ( Figura 11 Paso 3 Creación

proyecto. )

La primera está destinada a añadir un nuevo fichero al proyecto y definir si se

desea las entradas y salidas desde un principio. Entre las opciones de fichero a

elegir se utilizara de momento VHDL Module y progresivamente a lo largo de la

explicación se verán el resto.

La ventana de la derecha sirve para añadir al proyecto un fichero ya existente

en el ordenador y ser implementado junto al diseño.

El último paso es un resumen de lo seleccionado anteriormente y da pie a

comenzar a redactar el código.

Figura 12 Paso 4 Creación proyecto.

Page 26: Memoria Main

26

2.4.2. Escritura del código.

Se creará un proyecto nuevo, con nombre “Prub1” y a la hora de añadir un

fichero se nombrara de igual modo y no se definirán por el momento entradas

ni salidas.

Si se ha realizado todo correctamente a la izquierda de la ventana principal

aparecerá lo siguiente:

Figura 13 1er Código paso 1.

En la parte derecha aparecerá una ventana de texto que contendrá las

directivas básicas de cualquier diseño, es en esta ventana en donde se

introducirá el primer código.

En este primer código, como se ha comentado se hace una asignación directa entre los selectores de entrada de la placa (SW) y los Leeds situados encima (LDR).

Como se puede ver este primer código está compuesto de la declaración del componente con sus entradas y la arquitectura del mismo, en la cual solo consta la asignación directa, que sería comparable a unir físicamente los interruptores con los Leeds mediante un cable.

Page 27: Memoria Main

27

El siguiente paso es comprobar que el código compila correctamente, para esto se utilizara el menú desplegable situado en la ventana inferior a la que contiene la declaración de archivos ( Figura 14 1er Código paso 2. ).

Figura 14 1er Código paso 2.

Después de hacer clic en Run, si todo ha sido correcto en la ventana de texto

de la parte inferior de la ventana aparecerá el mensaje siguiente:

Process "Synthesis" completed successfully

Si se despliega la pestaña sintetizar, emergerán más opciones, de la cuales

cabe destacar por ahora View RTL, que muestra el esquema del componente.

Figura 15 1er Código paso 3.

El siguiente paso para grabar el diseño es asignar las entradas y salidas con

los pines correspondientes de la placa. La página Web proporciona para

descargar un archivo .UCF, que contiene toda la información de pines de la

Spartan-3AN, nombrando cada pin de cada componente con la nomenclatura

que viene inscrita físicamente en la placa.

Page 28: Memoria Main

28

2.4.3. Asignación de pines.

El programa nos permite introducir los datos de forma manual en el archivo

.UCF de configuración, o de forma automática mediante una aplicación que

será descrita posteriormente.

2.4.3.1. Editar el archivo .UCF de forma manual.

El modelo de archivo UCF que contiene toda la información de la localización

de pines en la Spartan-3AN se puede encontrar en:

https://secure.xilinx.com/webreg/register.do?group=spartan_kits&exitURL=http://www.xilinx.com

/products/boards/s3astarter/files/s3astarter.ucf&SVY_DOC_FILE=s3astarter.ucf

El formato del documento es el siguiente:

#################################################################

# Discrete Indicators (LED) #

#################################################################

NET "LED<0>" LOC = "R20" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "LED<1>" LOC = "T19" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

Código 3 Modelo .UCF.

Este documento tendrá que ser editado siempre que no se utilicen los mismos

nombres para definir las entradas y salidas. Para el diseño se ha extraído la

información de los componentes a utilizar, y tras ser editado queda de la

forma siguiente.

NET "LDR[0]" LOC = R20;

NET "LDR[1]" LOC = T19;

NET "LDR[2]" LOC = U20;

NET "LDR[3]" LOC = U19;

NET "SW[0]" LOC = V8;

NET "SW[1]" LOC = U10;

NET "SW[2]" LOC = U8;

NET "SW[3]" LOC = T9;

Código 4 .UCF Modificado.

Page 29: Memoria Main

29

2.4.3.2. PlanAhead

Otro método para introducir las asignaciones de pines, es mediante la

herramienta PlanAhead que nos proporciona Xilinx.

Figura 16 1er Código paso 4.

Esta aplicación permite introducir uno a uno los números de los puertos

necesarios.

Figura 17 1er Código paso 5.

Page 30: Memoria Main

30

En el formulario número 1 se puede ver si el puerto es de entrada o salida, el

nombre y la situación. Es en este último campo donde se introducirá el número

del puerto a utilizar siguiendo el archivo .UCF que proporciona el fabricante.

El formulario numero 2 presenta una lista de todas las entradas y salida del

código. Para poder modificar alguna de ellas mediante el formulario número 1,

ésta tendrá que estar seleccionada.

Cuando se termine de rellenar todos los campos se tendrá que grabar el

proceso desde la misma aplicación, cerrar la ventana y volver a sintetizar el

código.

Un método para comprobar que la asignación ha sido correcta, es mediante

Design Summary, que como se ha comentado al principio, da un amplio

informe de todos los eventos del proyecto.

Figura 18 1er Código paso 6.

A partir de este punto ya se dispone de todo lo necesario para introducir el

código en la placa y hacerlo funcionar. Para esto se ejecutará toda la

secuencia de sintetizado y compilación.

Page 31: Memoria Main

31

Figura 19 1er Código paso 7.

Si todo ha sido correcto la ventana de notificaciones mostrara el mensaje

siguiente:

Generating Report ...

Number of warnings: 0

Total time: 2 secs

Process "Generate Post-Place & Route Static Timing" completed successfully

Started : "Generate Programming File".

Process "Generate Programming File" completed successfully

Código 5 Información sucesos.

Page 32: Memoria Main

32

2.5. Síntesis y Simulación temporal de circuito.

Cuando se ha definido el proyecto se ha elegido un programa de simulación,

este queda totalmente integrado en Xilinx, de modo que al pasar de uno a otro

se envía toda la configuración. Esto supone que a la hora de hacer

simulaciones temporales el programa de simulación tiene en cuenta los

retardos propios de cada placa utilizada en el diseño.

A la hora de realizar la simulación es muy simple. El primer paso es pasar del

método implementación a simulación, esto se hace seleccionando la casilla

situada encima de la ventana que contiene los archivos del programa.

Figura 20 Simulación paso 1

Desde la nueva ventana que aparece, se ha de tener en cuenta básicamente

tres cosas a la hora de simular.

Figura 21 Simulación paso 2.

Page 33: Memoria Main

33

El primer punto es nivel de simulaciones que se quiere realizar, de los cuales

se utilizaran 2.

-Behavioral es el nivel de simulación más primario, sólo tiene en cuenta la

estructura del código y su funcionamiento teórico. Generalmente si el código

compila correctamente podrá ser simulado. Este método sirve para comprobar

que el diseño cumple las especificaciones iniciales previstas.

-Post-Route es el paso siguiente al método anterior. En este método sí que se

tiene en cuenta los retardos entre puertas. Es en este punto donde no sólo es

importante que el código funcione a nivel teórico, puesto que si el sistema no

es capaz de conmutar con suficiente velocidad no será capaz de realizar las

operaciones programadas.

El segundo punto de la simulación, es elegir que código se desea simular. En

este primer diseño no es muy relevante porque sólo aparece un archivo que

hace las funciones de Main y proceso de datos o funciones conjuntamente,

pero a medida que aumente la complejidad en el diseño, se dará cuenta que es

mucho más útil simular un bloque por separado a la hora de extraer

conclusiones.

Por último, el tercer punto marcado en rojo en la Figura 21 Simulación paso 2.,

muestra el programa que actualmente esta seleccionado y junto a él, el método

de simulación elegido. Haciendo doble clic sobre esta última opción se accede

al programa de simulación.

ModelSim Simulator es el programa por defecto que utiliza la EPSC (Escuela

Politécnica Superior de Castelldefels) para simular, la versión Xilinx de este

programa se puede descargar en el apartado de soporte de la página Web.

Esta simulación se realizara mediante TestBench, que es una herramienta

mucho más cómoda e inmediata de realizar simulaciones.

2.5.1. TestBench para simulaciones en ModelSim.

Este archivo da la posibilidad de integrar aun más la simulación dentro del Project Navigator, ya que éste aparecerá dentro de la lista de archivos del código, siendo uno más a programar y modificar al gusto. Como contendrá la información que anteriormente se definía en el archivo .DO, cuando se ejecute ModelSim automáticamente aparecerá la simulación programada, agilizando considerablemente el proceso.

Page 34: Memoria Main

34

El proceso de creación del archivo TestBench es el siguiente:

Figura 22 Simulación paso 3.

El primer paso es añadir un nuevo archivo al proyecto (1), acto seguido se abrirá una ventana con los archivos disponibles para seleccionar (2), de los cuales interesa VHDL Test Bench. Por último sólo queda nombrar el archivo (3) y pulsar siguiente hasta cerrar la ventana actual.

Ahora aparece el archivo Test Bench dentro de la lista, siempre que la casilla de simulación esta seleccionada.

Automáticamente se abrirá en la ventana de código. Dentro del modo de simulación este hace las funciones de archivo principal gobernando sobre los demás. Como se puede ver el propio programa te guía en la utilización del código con comentarios en cada punto relevante del mismo. Otro aspecto interesante es que en la creación del código viene implementado un clock automáticamente. Gracias a este factor, en códigos dependientes de un reloj externo se podrá hacer funcionar.

Por la simplicidad de este primer diseño, las modificaciones del código modelo de origen serán pocas, pero servirán para entender cómo funciona este archivo de simulación.

Tomando como modelo el archivo .DO de apartados anteriores y teniendo en cuenta que ahora éste ya está identificado como componente, y no hará falta inicializar las variables, se introducirán los estados y las separaciones temporales únicamente en donde nos indica el código mediante un comentario de ayuda (insert stimulus here).

Page 35: Memoria Main

35

2.5.1.1. Código TestBench

El código queda de la forma siguiente:

-Primero es necesario comentar la parte del clock para que no de errores y porque no se hará uso de ella.

-- constant <clock>_period := 10 ns;

-- <clock>_process :process

-- begin

-- <clock> <= '0';

-- wait for <clock>_period/2;

-- <clock> <= '1';

-- wait for <clock>_period/2;

-- end process;

Código 6 Código Reloj Test Bench.

-Se ha de añadir la información del archivo .DO con las modificaciones adecuadas al VHDL.

-- Stimulus process

stim_proc: process

begin

-- hold reset state for 100 ms.

SW<="1111";

wait for 100 ns;

--wait for <clock>_period*10;

-- insert stimulus here

SW<="1011";

wait for 100 ns;

SW<="0011";

wait for 100 ns;

SW<="1100";

wait for 100 ns;

SW<="1001";

wait for 100 ns;

SW<="0101";

wait for 100 ns;

wait for 200 ns;

wait;

end process;

Código 7 Pautas de la simulación.

Tras realizar estas modificaciones se puede ejecutar la simulación y ver como ésta, si no se ha producido ningún error, aparece automáticamente.

Para ejecutar la simulación se ha de hacer doble clic sobre el nombre del

simulador seleccionado.

Page 36: Memoria Main

36

2.5.2. Simulación temporal.

Figura 23 Simulación paso 4.

Si se realiza el proceso usando la opción de Post-Route para simular el código, se verá en la representación grafica, haciendo el zoom necesario, los retardos entre las señales.

Recordar que si no se ven las señales adecuadamente, un error muy común es

poner una base de tiempo muy pequeña a simular o que las opciones de zoom

de la ventana no sean las correctas.

Figura 24 Simulación paso 5.

Más adelante cuando se simulen bloques mas grandes se verá como el retardo es una constante que va de entre 6 ns a 8ns, por esa razón es un parámetro a tener en cuenta a la hora de exigir cierta velocidad de computo a un proceso.

Page 37: Memoria Main

37

2.6. Grabado del código.

El siguiente paso es grabar el código en la memoria interna de la placa, para su

posterior ejecución. Esto se realiza mediante la aplicación ISE iMPACT, que se

nos abrirá automáticamente al ejecutar el paso siguiente al seleccionado

anteriormente, Configure Target Device.

Figura 25 ISE iMPACT

2.6.1. Alimentación y comunicación con la placa.

En esta aplicación el primer paso es identificar nuestra placa, para ello ésta

tendrá que estar conectada al PC mediante el cable USB, enchufada a la

corriente y encendida.

Figura 26 Conexiones.

Page 38: Memoria Main

38

2.6.2. Identificación de la Spartan-3AN.

Figura 27 Identificación Spartan-3AN.

El siguiente paso es hacer que el programa identifique la placa y establezca

comunicación con ella. Para conseguir este propósito se utilizara la opción de

detección automática.

2.6.3. Introducir un código.

Cuando la placa sea identificada, automáticamente se abrirán los formularios

para introducir los programas a ejecutar, y acto seguido una ventana que

contendrá los parámetros de configuración. La configuración utilizada será la

que viene por defecto y los programas tendrán que ser localizados en la raíz de

la carpeta donde se halla guardado el código en su creación.

Page 39: Memoria Main

39

Figura 28 Introducción del programa a ejecutar.

2.6.4. Configuración de los Jumpers a la hora de grabar un

código en la memoria de la Spartan-3AN.

La Spartan-3AN dispone de diferentes métodos para grabar un código en la

placa. El utilizado en este tutorial permite introducir un código y ser guardado

de forma sencilla y sin establecer ninguna configuración adicional, para que

éste permanezca de forma permanente.

La configuración de los Jumpers es la siguiente:

Figura 29 Configuraciones posibles en los Jumpers.

Page 40: Memoria Main

40

Figura 30 Configuración Jumpers.

En esta configuración, el método de entrada a la memoria es Master Internal

SPI (Serial Peripheral Interface). Quiere decir que un periférico de memorial

residente en la placa establece las pautas y el contenido de carga para el

programa a ejecutar. Cuando se grabe el programa en este periférico el

proceso será el inverso que el de la carga del código en la FPGA.

El esquema completo está disponible en:

http://www.xilinx.com/support/documentation/boards_and_kits/s3astarter_schematic.pdf

2.6.4.1. Master Internal SPI.

Las pautas de escritura en este modo son las siguientes:

- Solamente el periférico de escritura principal gobierna la transmisión.

- Cada dato es desplazado un slot de memoria hacia fuera mediante la

linea Master Out Slave In (MOSI).

- Cada dato es desplazado un slot de memoria hacia dentro mediante la

línea Master In Slave Out (MISO).

- La transmisión es serializada, dura 8 ciclos de reloj y todos los datos

transmitidos por el periférico principal están sincronizados.

Figura 31 Comunicación SPI Flash Memory.

Page 41: Memoria Main

41

Es en este periférico externo donde permanece el código cuando se elige la

opción de programa y grabar la memoria flash de la FPGA.

2.6.5. Grabar el código.

El código se puede grabar para que quede de forma permanente o para que se

pierda una vez se apague o se pierda la alimentación del sistema.

2.6.5.1. Programar la memoria Flash y cargar la FPGA.

Clicando con el botón secundario sobre el componente al cual se desea

insertar el código, aparece un menú de opciones.

En este apartado se seleccionara la primera opción que hará permanecer el

código en la placa, sobre reinicios y pérdidas de energía, en el periférico de

memoria descrito anteriormente.

Figura 32 Configuración permanente.

Page 42: Memoria Main

42

2.6.5.2. Programas FPGA únicamente.

Dentro de este menú, en este caso interesa la segunda opción.

Figura 33 Configuración eventual.

De este modo se podrán hacer escrituras más rápidas de código para pruebas

de funcionamiento puntuales.

Page 43: Memoria Main

43

2.7. Comprobación del funcionamiento.

Tras introducir el código se podrá comprobar de forma visual el

comportamiento del mismo.

La asignación de las salidas viene regida por la condición -> LDR <= NOT(SW);

Esta condición evoca el funcionamiento siguiente, ya que los Leeds son activos

a nivel bajo.

Figura 34 Entrada "0110" Salida "1001"

Figura 35 Entrada "0010" Salida "1101"

El comportamiento es correcto y satisfactorio.

Page 44: Memoria Main

44

3. Sistemas secuenciales.

Una vez comprendida la metodología para llevar un código desde el papel a la placa, el siguiente paso lógico es realizar un código dependiente de un reloj interno, puesto que la mayoría de sistemas electrónicos que nos rodean funcionan de este modo.

“A diferencia de los sistemas combinacionales, en los sistemas secuenciales,

los valores de las salidas, en un momento dado, no dependen exclusivamente

de los valores de las entradas en dicho momento, sino también dependen del

estado anterior o estado interno.

La mayoría de los sistemas secuenciales están gobernados por señales de

reloj. A éstos se los denomina "síncronos" o "sincrónicos", a diferencia de los

"asíncronos" o "asincrónicos" que son aquellos que no son controlados por

señales de reloj.”

Wikipedia.

Sistema

combinacional.

Sistema de

memoria.

ZX

Y

Figura 36 Sistemas secuenciales.

3.1. Metodología para dividir la frecuencia de entrada y

gestionar un contador binario síncrono de Modulo 11.

Se diseñara un doble contador de 4 bits, el cual incrementara su valor mediante un pulso a una determinada frecuencia proporcionada por un divisor de frecuencia, que será un componente de menor rango o sumiso al código principal.

La primera salida vendrá gestionada por un divisor de frecuencia creado

manualmente, y la segunda salida por el gestor de reloj interno (Digital Clock

Manager).

Page 45: Memoria Main

45

Contador

CD

CE

CLK

contador_out contador_out2

TC_out

TC_out2

Figura 37 Encapsulado sistema completo..

3.1.1. Divisor de frecuencia.

La Spartan tiene un ping de clock a 50 MHz, que mediante el archivo UCF se puede identificar en la placa y el en pinout.

NET "CLK_50M" LOC = "E12"|IOSTANDARD=LVCMOS33|PERIOD = 20.000 ;

OFFSET = IN 10.000 VALID 20.000 BEFORE "CLK_50M" ;

OFFSET = OUT 20.000 AFTER "CLK_50M" ;

Código 8 Descripción Clock en .UCF.

3.1.1.1. Especificaciones.

Se pretende obtener una salida de reloj a 1 MHz mediante este componente de la forma más efectiva y sencilla posible.

Para obtener la frecuencia deseada a partir de los 50MHz de entrada, se realizará un divisor de frecuencia. Cada vez que el contador general llegue a un valor esperado, cumpliendo la condición predefinida, nos proporcionará una salida de reloj a la frecuencia deseada.

Ejemplo.

Contador 1: 1 2 3 4 5 (Condición) 1 2 3 4 5 (Condición)

Contador 2: 1 2

Condición: Cuando sea 5 reiniciamos el contador principal (50MHz) y aumentamos el contador secundario, de este modo se divide la frecuencia inicial por 5, obteniendo así una salida a 10MHz.

Page 46: Memoria Main

46

Para realizar el divisor de frecuencias se utilizará el modelo de máquina de estados que se imparte en la escuela.

Figura 38 Esquema maquina de estados.

En cada iteración se decide la configuración del estado siguiente, y el estado presente pasa a ser el estado futuro de forma síncrona con cada golpe de reloj. En caso de que no se produzca un cambio de estado, la metodología es no actualizar el estado futuro, para que no sea modificado cuando se produzca un el evento de reloj.

A partir de este punto, todos los códigos que contengan estados de funcionamiento seguirán este modelo.

3.1.1.2. Esquema divisor de frecuencia.

El componente tendrá 3 entradas y una salida.

Entradas CLK: Es la entrada de 50MHz disponible en la placa.

CD: Reiniciara el contador cuando se active.

CE: Habilitara el contador para que pueda incrementar en cada iteración.

Salida TC10: Esta salida proporcionara la nueva frecuencia resultante del divisor.

Page 47: Memoria Main

47

freq_divider_10

CD

CE

CLK

TC_10

Figura 39 Componente divisor de frecuencia.

3.1.1.3. Diagrama de estados Divisor de frecuencia.

Vistas las condiciones anteriores se pensará en un diagrama de estado que

proporcione dicho funcionamiento.

0

TC10 = ‘0’

4

TC10 = ‘0’

(Nº - 1)

TC10 = ‘1’

1

TC10 = ‘0’

3

TC10 = ‘0’

2

TC10 = ‘0’

Nota:

N es el valor por el cual se quiere

dividir la frecuencia de entrada.

While CE = „0‟

TC10 = ‘1’

While CE = „0‟

While CE = „0‟ While CE = „0‟

While CE = „0‟

While CE = „0‟

CE = „1‟

CE = „1‟

CE = „1‟

CE = „1‟

CE = „1‟CE = „1‟

Figura 40 Diagrama de Estados divisor de frecuencia.

Page 48: Memoria Main

48

3.1.1.4. Código divisor de frecuencia.

Se necesitan dos señales de longitud igual al número de bits necesario para representar el número por el cual queremos dividir la frecuencia de entrada.

SIGNAL present_state, future_state:std_logic_vector(6 DOWNTO 0);

Código 9 Vectores estados Divisor de frecuencia.

La frecuencia de entrada estará dividida por 50, y teniendo en cuenta que el contador empieza a contar en 0, el valor correcto será 49 y su equivalente binario es 110001, que tiene una longitud de 6 bits. Este valor de división ha sido elegido para facilitar la posterior simulación, si se desea implementar en la placa y comprobar visualmente que el divisor funciona correctamente, este tendrá que ser mucho mayor.

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_ARITH.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY freq_div_10 IS

PORT(CD,CLK,CE : IN std_logic;

TC10 : OUT std_logic

);

END freq_div_10;

ARCHITECTURE FSM_style OF freq_div_10 IS

SIGNAL present_state, future_state:std_logic_vector(5 DOWNTO 0);

--signal senal : std_logic;

--signal control : std_logic_vector(1 DOWNTO 0);

BEGIN

-- State register, normally in FF-D

state_register: PROCESS (CD,CLK)

BEGIN

IF (CD='1') THEN

present_state <= "000000";

ELSIF (CLK='1' AND CLK'event) THEN

present_state <= future_state;

END IF;

END PROCESS state_register;

-- combinational logic for determining the next state

CS1: PROCESS (present_state,CE)

BEGIN

IF CE = '1' THEN

IF (present_state = "110001") THEN -- 0x18 == 0d24

future_state <= "000000";

ELSE

future_state <= present_state + 1;

END IF;

ELSE

future_state <= present_state;

END IF;

END PROCESS CS1;

TC10 <= '1' WHEN (present_state = "110001" AND CE = '1') ELSE '0';

END FSM_style ;

Código 10 Código Divisor de frecuencia.

Page 49: Memoria Main

49

Se puede ver como en cada evento de reloj se actualiza el estado y el funcionamiento de la entrada CD anteriormente descrita.

También el comportamiento de la entrada CE, que es la que habilita el contador, y como esta implementada la condición que fuerza la puesta a 0 del contador cuando llega al valor esperado. Este diseño forma parte de la teoría de la escuela, se puede encontrar dentro de la página web y su funcionamiento es sencillo y efectivo.

Por último y no menos importante, la salida TC10 y su puesta a uno en el

momento deseado.

3.1.1.5. Simulación divisor de frecuencia.

La simulación se realizará mediante TestBench. En este diseño si será necesario editar el reloj que nos genera el programa. El primer paso es comprobar que la nomenclatura con la que ha implementado el reloj es la misma que se ha utilizado.

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

USE ieee.std_logic_unsigned.all;

USE ieee.numeric_std.ALL;

ENTITY diezMHz IS

END diezMHz;

ARCHITECTURE behavior OF diezMHz IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT freq_div_10

PORT(

CD : IN std_logic;

CLK : IN std_logic;

CE : IN std_logic;

TC10 : OUT std_logic

);

END COMPONENT;

--Inputs

signal CD : std_logic := '0';

signal CLK : std_logic := '0';

signal CE : std_logic := '0';

--Outputs

signal TC10 : std_logic;

-- Clock period definitions

constant CLK_period : time := 1 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)

uut: freq_div_10 PORT MAP (

CD => CD,

CLK => CLK,

CE => CE,

Page 50: Memoria Main

50

TC10 => TC10

);

-- Clock process definitions

CLK_process :process

begin

CLK <= '0';

wait for CLK_period/2;

CLK <= '1';

wait for CLK_period/2;

end process;

-- Stimulus process

stim_proc: process

begin

-- hold reset state for 100 ms.

CD <= '1';

CE <= '0';

wait for 100 ns;

CD <= '0';

CE <= '1';

wait for CLK_period*500;

CD <= '0';

CE <= '0';

wait for CLK_period*500;

CD <= '1';

CE <= '0';

wait for CLK_period*500;

CD <= '0';

CE <= '1';

wait for CLK_period*500;

-- insert stimulus here

wait;

end process;

END;

Código 11 Código Simulación funcional Divisor de frecuencia.

Este componente divide 50 veces la entrada que se le introduzca, por esa razón, y para facilitar la grafica, si definimos un periodo de CLK de 1ns el resultado de la simulación es el siguiente.

Figura 41 Simulación del componente divisor de frecuencia.

Page 51: Memoria Main

51

En la grafica anterior se pude ver como la división es perfecta y como el periodo de clock resultante es 50 veces mayor que el de la entrada, recordad que la frecuencia es el inverso del periodo.

3.1.2. Contador síncrono binario de Modulo 11.

El contador tendrá las mismas entradas que el divisor de frecuencia, y para

facilitar el diseño funcionará de forma autónoma. Si en el futuro se desea

añadir alguna funcionalidad, solo se tendrán que declarar las entradas

pertinentes e implementar las condiciones o procesos necesarios.

Contador

CD

CE

CLK

contador_out

( 3 downto 0 )

TC_out

Figura 42 Esquema contador.

3.1.2.1. Especificaciones.

El contador funcionará a la misma frecuencia que el divisor de frecuencia al

que este asociado, y contará desde 0 a 10 mediante un vector de 4 bits.

Se añadirá una salida llamada contador_out y contador_out2 para su posterior

visualización, ya sea en la placa o mediante la simulación.

Page 52: Memoria Main

52

3.1.2.2. Esquema del Contador.

freq_divider_10 Bloque_DCM

CD

CE

CLK

TC_10

CLKIN_IN

RST_IN

CLKDV_OUT

CLKFX_OUT

CLKIN_IBUFG_OUT

CLK0_OUT

LOCKED_OUT

CD

CLK

Contador1

CD

CE

CLK

contador_out

Contador21

CD

CE

CLK

contador_out2

CE

( 3 downto 0 ) ( 3 downto 0 )

TC_out TC_out2

Figura 43 Esquema Contador (Contador 1 + Divisor frecuencia) y (Contador 21 + Bloque DCM).

La primera salida vendrá gestionada por el divisor de frecuencia creado

manualmente y la segunda salida por el gestor de reloj interno (Digital Clock

Manager), el cual se implementará posteriormente.

3.1.2.3. Diagrama de estados del Contador.

El diagrama de estados es muy similar al del divisor de frecuencia.

Page 53: Memoria Main

53

0

TC_out = ‘0’

4

TC_out = ‘0’

(Nº - 1)TC_out = ‘1’

1

TC_out = ‘0’

3

TC_out = ‘0’

2

TC_out = ‘0’

Nota:

N es el valor máximo del vector.

While CE = „0‟

TC_out = ‘1’

While CE = „0‟

While CE = „0‟ While CE = „0‟

While CE = „0‟

While CE = „0‟

CE = „1‟

CE = „1‟

CE = „1‟

CE = „1‟

CE = „1‟CE = „1‟

Figura 44 Estados contador.

Los dos contadores que se implementaran serán idénticos.

3.1.2.4. Código del Contador.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity Contador is

PORT (CD,CLK,CE : IN std_logic;

TC_out : out std_logic;

contador_out : out std_logic_vector(3 downto 0)

);

end Contador;

architecture Behavioral of Contador is

SIGNAL present_state, future_state : std_logic_vector(3 DOWNTO 0);

begin

state_register1: PROCESS (CD,CLK)

BEGIN

IF (CD='1') THEN

present_state <= "0000";

ELSIF (CLK='1' AND CLK'event) THEN

present_state <= future_state;

END IF;

Page 54: Memoria Main

54

END PROCESS state_register1;

conta :process (present_state,CE)

BEGIN

IF (CE = '1') THEN

IF (present_state = "1010") THEN -- 0x18 == 0d24

future_state <= "0000";

ELSE

future_state <= present_state + 1;

END IF;

ELSE

future_state <= present_state;

END IF;

end process;

TC_out <= '1' WHEN (present_state = "1010" AND CE = '1') ELSE '0';

contador_out <= present_state;

end Behavioral;

Código 12 Código contador.

3.1.3. Código top Contador.

Este es el archivo top que engloba todas las declaraciones, asignaciones y

salidas a fin de ser visualizadas en la simulación o tras grabar el programa en

la placa.

Para declarar el divisor de frecuencia dentro del contador se tienen que hacer básicamente dos definiciones:

1ª: Definir las entras y salidas del componente.

COMPONENT freq_div IS

Port ( CD,CLK,CE : IN std_logic;

TC10 : OUT std_logic

);

END COMPONENT;

Código 13 Declaración Divisor.

2º: Asignar dentro del contador las entradas y salidas del divisor de frecuencia, y si es necesario las señales que se utilizarán para conectar las salidas o entradas con otros componentes.

Uut : freq_div_10

PORT MAP (

CD => CD,

CLK => CLK,

CE => CE,

TC10 => TC10

);

Código 14 Asignación entradas/salidas Divisor.

Page 55: Memoria Main

55

En el caso del contador las señales declaradas son:

signal TC10 : std_logic;

Código 15 Señales necesarias Divisor.

TC10 está conectada al pulso a 1MHz y se utiliza como condición dentro del proceso para incrementar el valor del contador

Para declarar el contador, el código y las asignaciones necesarias son las

siguientes.

COMPONENT Contador

PORT(

CD : IN std_logic;

CLK : IN std_logic;

CE : IN std_logic;

TC_out : OUT std_logic;

contador_out : OUT std_logic_vector(3 downto 0)

);

END COMPONENT;

Inst_Contador1: Contador PORT MAP(

CD =>CD ,

CLK => CLK0_OUT,

CE =>TC10 ,

TC_out =>TC_out,

contador_out => contador_out

);

Código 16 Declaración y asignación Contador 1.

3.1.3.1. Código archivo top Contador.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity Sumador is

PORT (CD,CLK,CE : IN std_logic;

TC_out,TC_out2 : out std_logic;

div_10out,DCMout : out std_logic;

contador_out2 : out std_logic_vector(3 downto 0);

contador_out : out std_logic_vector(3 downto 0)

);

end Sumador;

architecture Behavioral of Sumador is

Page 56: Memoria Main

56

COMPONENT Contador

PORT(

CD : IN std_logic;

CLK : IN std_logic;

CE : IN std_logic;

TC_out : OUT std_logic;

contador_out : OUT std_logic_vector(3 downto 0)

);

END COMPONENT;

COMPONENT freq_div_10

PORT(

CD : IN std_logic;

CLK : IN std_logic;

CE : IN std_logic;

TC10 : OUT std_logic

);

END COMPONENT;

signal TC10 : std_logic;

begin

Inst_Contador1: Contador PORT MAP(

CD =>CD ,

CLK => CLK0_OUT,

CE =>TC10 ,

TC_out =>TC_out,

contador_out => contador_out

);

uut: freq_div_10 PORT MAP (

CD => CD,

CLK => CLK0_OUT,

CE => CE,

TC10 => TC10

);

div_10out <= TC10;

end Behavioral;

Código 17 Top Contador (freq_div_10 + Inst_Contador1)

3.1.3.2. Simulación funcional Contador + Divisor de frecuencia.

Como se ha decidido anteriormente la metodología de simulación que se utilizará será mediante TestBench. Se ha de añadir al proyecto el archivo como se ha explicado anteriormente.

El periodo inicial del reloj son 10 ns y según las especificaciones se necesita una entrada a 50MHz, por esta razón será el primer punto a modificar en el código.

-- Clock period definitions

constant CLK_period : time := 20 ns;

Código 18 Modificación Reloj Test Bench.

Hecho esto se empezará a introducir el código dentro del proceso de simulación para definir las pautas a seguir.

Page 57: Memoria Main

57

3.1.3.2.1. Assert o afirmaciones lógicas.

Para este proyecto a fin de seguir el comportamiento del reloj, ya que es un elemento autónomo, es interesante introducir una herramienta nueva de control.

Las afirmaciones lógicas son un método fiable para obtener información del correcto funcionamiento del código. Se muestra como un evento en el panel de notificaciones, ofreciendo así la posibilidad de saber que error se ha producido o donde se ha producido, y el instante temporal en el cual este ha ocurrido.

Estructura:

assert “Condición”

report "<Texto que queremos mostrar>"

severity note/warning/error;

Note: Texto simple que notifica del evento.

Warning: Muestra un warning dentro de la ventana de compilación.

Error: Muestra un error dentro de la ventana de compilación e interrumpe el flujo del programa.

Esquema:

Figura 45 Esquema funcionamiento Assert's.

Si la afirmación introducida dentro de la secuencia de simulación es correcta, no se producirá el evento definido.

Tras introducir esta herramienta dentro del proceso de simulación el código queda de la siguiente manera:

Page 58: Memoria Main

58

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

USE ieee.std_logic_unsigned.all;

USE ieee.numeric_std.ALL;

ENTITY Simulacion IS

END Simulacion;

ARCHITECTURE behavior OF Simulacion IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT Sumador

PORT(

CD : IN std_logic;

CLK : IN std_logic;

CE : IN std_logic;

div_10out,DCMout : out std_logic;

TC_out,TC_out2 : out std_logic;

contador_out2 : OUT std_logic_vector(3 downto 0);

contador_out : OUT std_logic_vector(3 downto 0)

);

END COMPONENT;

--Inputs

signal CD : std_logic := '0';

signal CLK : std_logic := '0';

signal CE : std_logic := '0';

--Outputs

signal contador_out : std_logic_vector(3 downto 0);

signal TC_out : std_logic;

signal div_10out : std_logic;

-- Clock period definitions

constant CLK_period : time := 20 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)

uut: Sumador PORT MAP (

CD => CD,

CLK => CLK,

CE => CE,

TC_out=> TC_out,

TC_out2=> TC_out2,

div_10out=> div_10out,

contador_out => contador_out

);

-- Clock process definitions

CLK_process :process

begin

CLK <= '0';

wait for CLK_period/2;

CLK <= '1';

wait for CLK_period/2;

end process;

-- Stimulus process

stim_proc: process

begin

-- hold reset state for 100 ms.

CD <= '1';

CE <= '0';

wait for 100 ns;

CD <= '0';

CE <= '1';

wait for CLK_period*500;

assert contador_out = "1001"

report "<Paso 1 error!>"

severity note;

wait for CLK_period*50;

Page 59: Memoria Main

59

CD <= '0';

CE <= '0';

wait for CLK_period*500;

assert contador_out = "1010"

report "<Paso 2 error!>"

severity note;

wait for CLK_period*50;

CD <= '1';

CE <= '0';

wait for CLK_period*500;

assert contador_out = "0001"

report "<Paso 3 error!>"

severity note;

wait for CLK_period*50;

CD <= '0';

CE <= '1';

wait for CLK_period*500;

assert contador_out = "1001"

report "<Paso 4 error!>"

severity note;

wait for CLK_period*50;

-- insert stimulus here

wait;

end process;

END;

Código 19 Código simulación funcional Contador.

Se fuerza un error o una afirmación falsa para ver el comportamiento del Assert.

Tras simular esta secuencia, en donde como se puede ver se ha producido el evento error en el paso 3, el resultado es el siguiente.

Figura 46 Simulación sumador + divisor frecuencia.

Se puede observar la ejecución del assert y el correcto funcionamiento del

sistema.

Page 60: Memoria Main

60

3.1.4. DCM (Digital Clock Manager)

Esta herramienta es un método de gestionar el reloj de entrada, que permitirá

realizar diferentes operaciones para adecuarlo tanto en frecuencia como en

fase a un modo de trabajo deseado.

Este componente es una propiedad intelectual (IP) que proporciona el

programa de forma gratuita. Al estar implementada dentro del programa, su uso

es mediante formularios y la mayoría del código vendrá prediseñado, como a la

hora de crear el archivo de simulación TestBench.

Para implementar este componente y ver su funcionamiento se hará una

ampliación del sumador anterior.

3.1.4.1. Especificaciones.

Se pretende, a la salida del componente DCM obtener una frecuencia de 5

MHz simple y de fase fija.

3.1.4.2. Esquema del componente.

Bloque_DCM

CLKIN_IN

RST_IN

CLKDV_OUT

CLKFX_OUT

CLKIN_IBUFG_OUT

CLK0_OUT

LOCKED_OUT

Figura 47 Esquema componente DCM.

Todas las salidas tendrán que ser declaradas como señales y a partir de la

inclusión de este componente en el proyecto, el resto de elementos

dependientes del reloj tendrán que estar conectados a la salida CLK0_OUT.

La salida CLK0_OUT proporciona la misma frecuencia que insertamos al

componente DCM en su entrada de reloj, a fin de ser utilizada por el resto de

sistemas.

Page 61: Memoria Main

61

3.1.4.3. Configuración del componente DCM.

Se ha de añadir un nuevo archivo al diseño, en la lista de tipos de archivos se

selecciona IP (Core Generator & Architecture Wizard) y como nombre

Bloque_DCM.

En la siguiente ventana se buscara el bloque de reloj.

Figura 48 Busqueda de la propiedad intelectual.

Tras seleccionar esta herramienta y finalizar el formulario para añadir el

componente, se abrirá automáticamente la primera ventana de configuración

del mismo.

En esta nueva ventana ( Figura 49 1er ventana configuración DCM. ) se

pueden ver las posibilidades que presenta el componente, de las cuales las

principales son: cambios de fases manuales, cambios de fase tabulados y

división y multiplicación de la frecuencia de entrada.

Para el proyecto se establece la frecuencia de entrada a 50Mhz. El reloj será

externo, simple y de fase fija.

Las salidas habilitadas son las siguientes:

CLKDV: La señal de entrada dividida por un valor, en nuestro caso será

10.

CLKFX: La salida principal del componente, estará sometida a todas las

operaciones configuradas en las siguientes ventanas.

Page 62: Memoria Main

62

Figura 49 1er ventana configuración DCM.

En la siguiente ventana se pueden renombrar las entradas y salidas del

componente. Se utilizara la configuración por defecto.

La tercera ventana ( Figura 50 Selección frecuencia de salida. ) es más

interesante, ofrece la opción de definir una frecuencia de salida o introducir las

divisiones y multiplicaciones necesarias para conseguirla.

En la parte superior vienen descritas la limitaciones del componente, el cual

nos da un abanico de frecuencias que van desde los 333 MHz a los 5Mhz.

Se utilizará la configuración de salida automática a 5MHz y tras calcular el

resultado la ventana presenta el aspecto siguiente.

Page 63: Memoria Main

63

Figura 50 Selección frecuencia de salida.

Como en la mayoría de formularios el último paso es un resumen de lo

seleccionado, en el cual se puede justificar que todo es correcto y esperado.

Attributes for DCM_SP, blkname = DCM_SP_INST

CLK_FEEDBACK = 1X

CLKDV_DIVIDE = 10

CLKFX_DIVIDE = 20

CLKFX_MULTIPLY = 2

CLKIN_DIVIDE_BY_2 = FALSE

CLKIN_PERIOD = 20.000

CLKOUT_PHASE_SHIFT = FIXED

DESKEW_ADJUST = SYSTEM_SYNCHRONOUS

DFS_FREQUENCY_MODE = LOW

DLL_FREQUENCY_MODE = LOW

DUTY_CYCLE_CORRECTION = TRUE

FACTORY_JF = 16'hC080

PHASE_SHIFT = 0

STARTUP_WAIT = FALSE

Código 20 Resumen especificaciones DCM.

Una vez terminado el proceso volverá a la ventana principal y solo quedara

declarar este componente como otro cualquiera.

3.1.4.4. Código Top del sistema completo

Seleccionando el componente DCM, en la misma ventana desde donde se

sintetiza el condigo, podemos ver que nos da dos opciones, de las cuales

interesa la instanciación del componente. Proporciona tanto la estructura de

puertos como la asignación de entradas y salidas. ( Figura 51 Instanciación. )

Page 64: Memoria Main

64

Figura 51 Instanciación.

Se declara el componente dentro del sumador y se definen las señales

necesarias.

Señales: signal CLKIN_IBUFG_OUT : std_logic;

signal CLK0_OUT : std_logic;

signal LOCKED_OUT : std_logic;

signal CLKDV_OUT : std_logic;

signal CLKFX_OUT : std_logic;

Asignación de señales: Inst_Bloque_DCM: Bloque_DCM PORT MAP(

CLKIN_IN => CLK ,

RST_IN =>CD ,

CLKDV_OUT =>CLKDV_OUT ,

CLKFX_OUT =>CLKFX_OUT ,

CLKIN_IBUFG_OUT =>CLKIN_IBUFG_OUT ,

CLK0_OUT =>CLK0_OUT ,

LOCKED_OUT =>LOCKED_OUT

);

Código 21 Declaración y asignación señales Bloque DCM.

Para comprobar el funcionamiento se duplicará el código del contador,

controlando el segundo con la salida CLKDV_OUT que proporciona 5 MHz. El

archivo de simulación se puede crear de nuevo o editarlo a mano añadiendo

todo el código necesario.

Para evitar que se produzca el error de múltiples conexiones para el reloj de

entrada, será necesario utilizar la salida CLK0_OUT para la entrada del divisor

de frecuencia que ya se había implementado.

uut: freq_div_10 PORT MAP (

CD => CD,

CLK => CLK0_OUT,

CE => CE,

TC10 => TC10

);

Código 22 Nueva asignación para freg_div_10.

Page 65: Memoria Main

65

Implementados todos los cambios el código queda de la manera siguiente.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity Sumador is

PORT (CD,CLK,CE : IN std_logic;

TC_out,TC_out2 : out std_logic;

div_10out,DCMout : out std_logic;

contador_out2 : out std_logic_vector(3 downto 0);

contador_out : out std_logic_vector(3 downto 0)

);

end Sumador;

architecture Behavioral of Sumador is

COMPONENT Contador

PORT(

CD : IN std_logic;

CLK : IN std_logic;

CE : IN std_logic;

TC_out : OUT std_logic;

contador_out : OUT std_logic_vector(3 downto 0)

);

END COMPONENT;

COMPONENT freq_div_10

PORT(

CD : IN std_logic;

CLK : IN std_logic;

CE : IN std_logic;

TC10 : OUT std_logic

);

END COMPONENT;

signal TC10 : std_logic;

COMPONENT Bloque_DCM

PORT(

CLKIN_IN : IN std_logic;

RST_IN : IN std_logic;

CLKDV_OUT : OUT std_logic;

CLKFX_OUT : OUT std_logic;

CLKIN_IBUFG_OUT : OUT std_logic;

CLK0_OUT : OUT std_logic;

LOCKED_OUT : OUT std_logic

);

END COMPONENT;

signal CLKIN_IBUFG_OUT : std_logic;

signal CLK0_OUT : std_logic;

signal LOCKED_OUT : std_logic;

signal CLKDV_OUT : std_logic;

signal CLKFX_OUT : std_logic;

begin

Inst_Contador1: Contador PORT MAP(

CD =>CD ,

CLK => CLK0_OUT,

CE =>TC10 ,

Page 66: Memoria Main

66

TC_out =>TC_out,

contador_out => contador_out

);

Inst_Contador2: Contador PORT MAP(

CD =>CD ,

CLK =>CLK0_OUT ,

CE => CLKDV_OUT,

TC_out =>TC_out2,

contador_out => contador_out2

);

uut: freq_div_10 PORT MAP (

CD => CD,

CLK => CLK0_OUT,

CE => CE,

TC10 => TC10

);

Inst_Bloque_DCM: Bloque_DCM PORT MAP(

CLKIN_IN => CLK,

RST_IN =>CD ,

CLKDV_OUT =>CLKDV_OUT ,

CLKFX_OUT =>CLKFX_OUT ,

CLKIN_IBUFG_OUT =>CLKIN_IBUFG_OUT ,

CLK0_OUT =>CLK0_OUT ,

LOCKED_OUT =>LOCKED_OUT

);

div_10out <= TC10;

DCMout <= CLKDV_OUT;

end Behavioral;

Código 23 Contador sistema completo.

Page 67: Memoria Main

67

3.1.4.5. RTL del Contador + DCM + Divisor de frecuencia.

Gracias a este esquema se puede ver la solución anteriormente descrita para

el error de múltiples conexiones del reloj de entrada, y la forma en la cual

queda anexo al diseño este nuevo componente.

Figura 52 Esquema del Contador + DCM + Div. Frecuencia.

Page 68: Memoria Main

68

3.1.5. Simulación funcional Contador + DCM + Divisor de

frecuencia.

El archivo de simulación utilizado es el mismo del apartado 3.1.3.2 y solo se

han declarado las señales necesarias para mostrar la segunda salida.

Tras realizar la simulación con dos contadores la grafica resultante es la

siguiente.

Figura 53 Simulación doble contador + DCM.

En un periodo del contador 1 se producen 5 periodos del contador 2, que

corresponden con las frecuencias de 1 MHz y 5 MHz correspondientemente.

Figura 54 Comparación contadores.

Page 69: Memoria Main

69

3.1.6. Síntesis y simulación temporal Contador + DCM + Divisor

de frecuencia.

Como ya se conoce la forma de asignar los pines y la forma de grabar el código

en la placa, este será el último apartado de sistemas secuenciales.

La simulación temporal proporcionara la justificación necesaria para obviar el

grabado y la asignación específica, afirmando que el sistema funciona en la

placa sin errores. Hay que tener en cuenta que las frecuencias de trabajo son

muy altas para la percepción visual del contador mediante los Leeds.

Utilizando el mismo archivo TestBench, ahora sin modificar nada, la simulación

queda de la forma siguiente.

Figura 55 Simulación temporal Contador + DCM + Divisor de frecuencia.

Y si se hace el suficiente zoom se podrá ver como los retardos son muy

similares a los comentados con anterioridad.

Se han añadido las salidas div_10out y dcmout para poder estudiar el trato de

estas señales, y la eficiencia del DCM y del divisor de frecuencia que se ha

hecho.

Figura 56 Comparación de las señales de reloj.

Page 70: Memoria Main

70

La señal de reloj proveniente de la salida CLKDV_OUT del componente DCM

presenta un periodo de 200 ns ( 5 MHz).

La señal resultante del divisor de frecuencia presenta un pulso más estrecho,

ya que no tiene corrección del ciclo de trabajo, y tiene un periodo de 1000 ns (1

MHz).

El retardo entre el pulso a 1 MHz y a 5 MHz es de 40‟77 ns, esto demuestra

que el componente DCM da un trato mucho más eficiente al reloj de entrada.

Figura 57 Retardo de los componentes DCM y Divisor de frecuencia.

En la última figura ( Figura 57 Retardo de los componentes DCM y Divisor de

frecuencia. ) se demuestra lo comentado anteriormente, el retardo resultante de

la salida del componente DCM con respecto la entrada de reloj del sistema es

sensiblemente inferior.

Si se hace funcionar al divisor de frecuencia y al componente DCM a la misma

frecuencia, se podrán observar las diferencias de funcionamiento con más

facilidad, como por ejemplo el retardo acumulativo que se produce.

Figura 58 Retrasos funcionando a la misma frecuencia.

Page 71: Memoria Main

71

4. Reloj en tiempo real programable.

Se desea diseñar un reloj a tiempo real, utilizando todas las herramientas

descritas anteriormente, que incorpore una maquina de control. Esto permitirá

ponerlo en hora y ser visualizado mediante la pantalla LCD incorporada en la

placa.

El código necesario para mostrar los datos por pantalla está disponible en

www.digilentinc.com, se explicará su funcionamiento y las modificaciones

necesarias para adecuar su comportamiento a los requerimientos del proyecto.

El modelo de esquema general a seguir es el siguiente, a medida que se

avance con el desarrollo seguramente se añadan entradas y salidas de control

para confirmar el correcto funcionamiento de cada una de las partes.

RelojCE

CLK

CD

MODE

SETE

Hora

UD_L

Figura 59 Esquema completo de la aplicación.

4.1. Especificaciones del Reloj.

El reloj será capaz de mostrar horas, minutos y segundos.

Efectuara las operaciones de parado (CE) o puesta a cero (CD) en un instante

determinado y cuenta adelante o atrás (UD_L).

Permitirá aumentar o reducir el valor de horas, minutos o segundos al antojo

del usuario (MODE<=>SETE).

Los datos serán visualizados mediante una pantalla LCD integrada en la

Spartan-3AN, y cuando el usuario decida modificar un dato este parpadeara

para facilitar su uso.

Page 72: Memoria Main

72

4.2. Esquema de control del sistema.

ControladorDATA

PATH

RELOJ

CONTROL

ENTRADAS

CONTROL

SEÑALES

ESTADOS

SEÑALES

ENTRADA

DATOS

SALIDA

DATOS

Figura 60 Esquema de control.

Igual que a la hora de diseñar una aplicación ( Figura 2 Flujo de diseño. ) para

gestionar un sistema en el cual intervienen muchos componentes, se ha de

seguir el esquema de la Figura 60 Esquema de control. para gestionar el

sistema de forma correcta.

4.2.1. Controlador.

El elemento que hace la función de controlador es la máquina de estados, que

es la encargada de regir y controlar todas las señales y estados de

funcionamiento.

UD_L

STATE

MACHINESET

MODE

CLK

CLK2

CD

CE

Figura 61 Máquina de estados.

Page 73: Memoria Main

73

4.2.2. DATAPATH

Los elementos controlados por la máquina de estados y encargados de

efectuar todas las operaciones necesarias para mostrar la información correcta,

son los englobados en este apartado.

4.2.2.1. Gestión del tiempo.

Modulo

12

(Horas)

Modulo

60

(Minutos)

Modulo

60

(Segundos)

TC60CECE

CD

CLK

UD_L

CD

CLK

UD_L

TC60TC24

HT(3..0)

T

HU(3..0)

U

MT(3..0) MU(3..0)

T U

ST(3..0) SU(3..0)

T U

CE

CD

CLK

UD_L

Figura 62 Control del tiempo.

Estos componentes procesan segundos, minutos y horas.

4.2.2.2. Preparación de datos.

Convnum1Count LDR1

Convnum2Count LDR1

Convnum3Count LDR1

Convnum4CountLDR1

Convnum5CountLDR1

Convnum6CountLDR1

Figura 63 Preparación de datos.

Estos 6 componentes convierten las unidades y decenas de segundos, minutos

y horas al formato necesario para ser procesado por el LCD.

Page 74: Memoria Main

74

4.2.2.3. Efecto de parpadeo.

Parpadeo

CLK

estado

HTin

HUin

MTin

MUin

STin

SUin

HTout

HUout

MTout

MUout

STout

SUout

Figura 64 Efecto parpadeo.

Este componente hace parpadear el dato con el cual se está interaccionando

para ser modificado.

4.2.2.4. Visualización.

lcd

CLK

rst

DB

RS

RW

ADR1

ADR2

CS

OE

rdone

(7 downto 0)

Figura 65 Visualización.

Este elemento es el encargado de gestionar al LCD integrado en la Spartan-

3AN y de captar, procesar y mostrar los segundos, minutos y horas

provenientes de los convertidores.

4.2.3. Gestión del reloj.

freq_divider_top DCMclock

CLK_1Hz

CLK_10Hz

CLK_1000Hz

CLKIN_IN

RST_IN

CLKDV_OUT

CLKFX_OUT

CLKIN_IBUFG_OUT

CLK0_OUT

LOCKED_OUT

CD

CE

CLK

Figura 66 Gestión del reloj.

Estos dos elementos generan las frecuencias necesarias para todo el sistema.

Page 75: Memoria Main

75

4.3. Divisor de frecuencia.

Anteriormente se ha comentado como gestionar el clock de entrada de la placa,

ahora para el diseño se replicará el componente divisor de frecuencia para

conectarlo en cascada y así poder conseguir la frecuencia deseada mediante

un número definido de pasos. De este modo se podrán tener diferentes

frecuencias a elección del usuario.

4.3.1. Divisores de frecuencia conectados en cascada.

Para realizar esta parte se creará un archivo top para los tres divisores de

frecuencia que se utilizaran, en el tendrán que esta declaradas las señales y

las salidas necesarias para extraer las tres salidas resultantes, con la finalidad

ser utilizadas por el resto del programa.

4.3.1.1. Esquema divisores de frecuencia en cascada.

El esquema general a seguir para redactar el código es el siguiente:

freq_div_10

TC10

CD

CE

CLK

freq_div_100

TC100

CD

CE

CLK

freq_div_49999

TC49999

CD

CE

CLK

CD

CLK

CE

CLK_1000Hz

CLK_10Hz

CLK_1Hz

CE2

CE3

CE1

Entradas

Salidas

Figura 67 Divisores de frecuencia en cascada.

Page 76: Memoria Main

76

El comportamiento del divisor de frecuencia por separado ya ha sido explicado,

en este esquema interconectamos los componentes para conseguir dividir por

un número diferente la frecuencia en cada iteración.

Ejemplo:

10 Hz

1 KHz

1 Hz

50 MHz

Figura 68 Ejemplo funcionamiento divisores de frecuencia conectados en cascada.

Ya se conoce la manera de crear un componente e instanciarlo en un bloque

jerárquico superior, ahora solo se ha de seguir el esquema y redactar el código

necesario.

4.3.2. DCM (Direct Clock Manager) + Divisores en cascada.

Se incorporará también al diseño el bloque DCM para gestionar el clock de

entrada, y para evitar hacer un salto en frecuencia tan abrupto utilizando el

divisor de frecuencia. Una de las razones para utilizar este componente es que

la reconstrucción de la señal que realiza es mucho mejor, puesto que el divisor

genera un pulso muy estrecho a la frecuencia deseada, mientras que el bloque

DCM ofrece una señal más uniforme dentro del periodo de la misma y con

menos retardos.

Divisor

DCM

Figura 69 Trato de la frecuencia por Divisores y DCM.

Crear un archivo superior que contenga el divisor de frecuencia y la declaración

del bloque DCM.

Page 77: Memoria Main

77

4.3.2.1. Esquema de conexione DCM + Divisores en cascada.

freq_divider_top DCMclock

CD

CE

CLK

CLK_1Hz

CLK_10Hz

CLK_1000Hz

CLKIN_IN

RST_IN

CLKDV_OUT

CLKFX_OUT

CLKIN_IBUFG_OUT

CLK0_OUT

LOCKED_OUT

CLK_10000hez

CD

CLK

Figura 70 Esquema conexiones DCM + Divisores en cascada.

Se tiene que configurar el componente para que la salida CLKDV_OUT

proporcione una frecuencia de 10 MHz y como se ha explicado declarar el resto

de salidas como señales.

La declaración tendrá la forma siguiente:

Segun2: DCMclock

PORT MAP(

CLKIN_IN =>CLK ,

RST_IN =>CD ,

CLKDV_OUT =>CLK_10000hez ,

CLKFX_OUT =>CLKDV_OUT ,

CLKIN_IBUFG_OUT =>CLKIN_IBUFG_OUT ,

CLK0_OUT =>CLK0_OUT ,

LOCKED_OUT => LOCKED_OUT

);

Código 24 Declaración DCM en Aplicación.

Ahora la salida CLK_10000hez será la entrada de reloj del divisor de

frecuencia, y por lo tanto se tendrá que modificar la primera división, puesto

que ahora la entrada no son 50 MHz.

49999 (1100001101001111) 9999 (10011100001111)

Si se declaran todas las salidas de reloj, les asignamos un pin y grabamos en

la placa el proyecto, podremos comprobar mediante un osciloscopio como

genera la señal el bloque DCM y las inconveniencias del divisor de frecuencia.

Page 78: Memoria Main

78

4.3.2.2. Códigos Divisor de frecuencia.

Anexos: 8.1.1.

4.3.2.3. Simulación Divisor de frecuencias.

Figura 71 Simulación divisores en cascada.

Se puede comprobar cómo el pulso de reloj generado es muy estrecho en

tiempo y como todas las señales se generan síncronamente con el reloj de

entrada.

4.3.2.4. Medida real de las frecuencias a la salida de los Divisores y el

componente DCM

Comportamiento real del bloque DCM 10MHz:

Figura 72 Barrido de la señal de 10KHz.

Se puede comprobar la calidad de la señal a la salida del componente DCM

que justifica su uso para realizar saltos abruptos en frecuencia.

Page 79: Memoria Main

79

Figura 73 Señal 10KHz en detalle.

Con más detalle se puede ver la brevedad de sus transitorios y lo comprobado

anteriormente un retraso de ~7ns.

Control 1 KHz // 10Hz // 1 Hz:

Figura 74 Detalle de la salida de 1KHz.

Figura 75 Barrido de las frecuencias de 10 y 1 Hz respectivamente.

Page 80: Memoria Main

80

En estas graficas se puede ver que la forma de la señal a la salida del DCM es

prácticamente una señal cuadrada normal, mientras que a la salida del divisor

de frecuencia es un pulso estrecho en tiempo al periodo definido.

4.4. Control horas, minutos y segundos.

En este apartado se describirá la metodología para realizar el control temporal

que seguirá el reloj.

4.4.1. Modulo 60.

Para simular el comportamiento de los minutos y segundos se necesita un

bloque capaz de contar desde 0 a 59. Se utilizara la salida a 1 Hz para el reloj

de entrada.

Como en el caso del divisor de frecuencia estarán conectados en cascada y el

modulo que se encargue de los segundos, cuando se desborde, incrementará

el valor de los minutos. En un futuro, el bloque de minutos incrementará un

contador de 1 a 12 que simulará el comportamiento de las horas.

Figura 76 Componente Modulo 60.

4.4.1.1. Comportamiento bloque Modulo 60.

Los dos bloques son idénticos, tienen las mismas entradas y salida, y su

comportamiento es similar, solo difieren el uno del otro en el trato que se hace

de las entradas.

Page 81: Memoria Main

81

Anteriormente ya se adelantaba que en los modulos 60 el encargado de los

segundos haría actuar el de los minutos, en este caso se baja un escalón en

los contadores para ver cómo gestionar las unidades y las decenas de los

mismos.

4.4.1.2. Estructura interna Modulo 60.

Figura 77 Estructura interna Modulo 60.

Son dos contadores de 4 bits, el contador de unidades llegara hasta 9 ( 0 1 2 3

4 5 6 7 8 9) y el de decenas hasta 5 ( 0 1 2 3 4 5). Cuando se desborde el

contador de unidades dará la orden de incrementar el contador decenas.

En el caso del contador de decenas se utiliza la opción de carga paralela para

que cuando se desborde ya sea por encima (superior:” 0000”) o por debajo

(inferior:” 0101”) cargue el valor necesario.

Para el contador de unidades cuando se desborde superiormente cargara

“0000” y cuando sea inferiormente cargara “1001”.

Page 82: Memoria Main

82

Figura 78 Ejemplo recorrido del vector unidades y decenas.

Los contadores como se deduce del comportamiento pueden contar adelante o

hacia atrás, esta función viene controlada por la entrada UD_L, que también

gestiona un MUX externo, que se encarga de ofrecer el valor a cargar en cada

caso.

4.4.1.3. Código Modulo 60

Anexo: 8.1.2.1.

4.4.1.4. Simulación Modulo 60.

Figura 79 Simulación modulo 60.

En la simulación se hace trabajar al contador de unidades a la misma

frecuencia que el reloj de entrada. Se puede observar el recorrido de los

vectores y la activación de la salida TC60, que será la encargada de accionar al

siguiente bloque.

Page 83: Memoria Main

83

4.4.2. Modulo de horas.

Este modulo es el encargado de simular el comportamiento de la horas. Las

salidas y el nombre, pese a que su recorrido es de 1 a 12, adoptará la

nomenclatura de contador 24 y la variable de control TC24.

Figura 80 Componente Modulo 12.

Este componente se diseño de forma compacta y no tiene la opción de carga

paralela, los eventos de desborde se gestionan dentro del proceso de cuenta

del componente.

Su comportamiento viene regido por un único contador de 4 bits y las salidas

se gestionan mediante un case.

Unidades copia el comportamiento del contador en su recorrido de 0 hasta 9, a

partir de ese momento se le asigna manualmente los valores 0, 1 y 2, de este

modo ya tenemos solventada la parte de las unidades.

Las decenas se controlan mediante una condición múltiple final, siempre que la

variable de control sea 10, 11 o 12 las salida de decenas será 1.

TENS<="0001" WHEN(control="1100" OR control="1011" OR control="1010")ELSE "0000"

Código 25 Gestión Decenas horas.

El componente sí que conserva la opción de contar o descontar, y en un futuro

será implementada de forma global.

Page 84: Memoria Main

84

4.4.2.1. Codigo modulo horas.

Anexo: 8.1.2.3.

4.4.2.2. Simulación modulo horas.

Figura 81 Simulación modulo horas.

En la simulación se pueden comprobar las salidas generadas por el CASE y el

funcionamiento de todas las variables de control de nuestros contadores.

CD: Reinicia el contador.

CE: Habilita el contador.

Dir: Habilita la cuenta adelante o hacia atrás del contador.

Page 85: Memoria Main

85

4.5. Maquina de estados.

Como se ha explicado, se pretende controlar el contador para poder ponerlo en

hora en un momento determinado y poder gestionar la cuenta atrás o adelante.

Para ello utilizaremos una maquina de estados.

4.5.1. Esquema estados de la Maquina de estados.

Figura 82 Esquema de estados Maquina de estados.

Mientras el sistema este en reposo el funcionamiento será el de un reloj

normal, cuando se pulse el botón de SETE entraremos en el modo de control.

Para controlar los estados del contador se utilizara un vector de 2 bits.

Cada vez que se accione la entrada SETE, el vector avanzara por el diagrama

de funcionamiento, recorriendo todos los estados hasta volver al punto de

reposo. Si en alguno de los estados de control se acciona MODE, el valor

temporal seleccionado aumentará o decrecerá según la condición UD_L.

Page 86: Memoria Main

86

4.5.2. Código del CASE de control.

La gestión en cada posición de control se hace mediante un case:

En la posición de reposo la configuración de las entradas es la siguiente:

MCEH <= '0';

MCEM <= '0';

MCES <= '0';

MSel <= '0';

Código 26 Case Reposo Maquina Estados.

Todas estas asignaciones controlan la selección de los multiplexores para

hacer conmutar el sistema desde la posición de reposo a la posición de control.

En esta posición ninguno está activo, dejando funcionar al contador de forma

normal.

1º posición de control:

MCEH <= '0';

MCEM <= '0';

MCES <= MODE;

MSel <= '1';

Código 27 Case posición 1 Maquina Estados.

En esta posición la entrada del selector de control esta activa, y como se ha

comentado, la entrada que habilita el contador del bloque se controla con la

entrada MODE.

En la segunda y tercera posición de control el funcionamiento es el mismo y su

configuración queda de la siguiente manera respectivamente:

MCEH <= '0';

MCEM <= MODE;

MCES <= '0';

MSel <= '1';

MCEH <= MODE;

MCEM <= '0';

MCES <= '0';

MSel <= '1';

Código 28 Case posición 3 y 4 Maquina de Estados.

Para gestionar este conjunto de contadores y la máquina de estados, se tendrá

que crear el archive top de la STATE MACHINE, y declarar en el todos los

componentes necesarios para su funcionamiento.

Page 87: Memoria Main

87

4.5.3. Esquema conexiones Maquina Estados.

Mux2

2

Modulo

12

(Horas)

Modulo

60

(Minutos)

Modulo

60

(Segundos)

Mux2

3Mux2

4

CH1

TC60CECE

CH2 CH1 CH2 CH1 CH2S S S

CD

CLK

UD_L

CD

CLK

UD_L

TC60TC24

UD_L

STATE

MACHINESET

MODE

HT(3..0)

CEHor CEMin CESeg

T

HU(3..0)

U

CEH

MT(3..0) MU(3..0)

T U

ST(3..0) SU(3..0)

T U

Mu

x2

1

CH

1

CH

2

S

CLK_1Hz

CLK_2Hz

CD

CE

S2Hz1HzUD_LCECD

CE

CD

UD_L

CLK

CLK

CD

CLK

UD_L

TC24TC60sTC60m

CEM CES

Figura 83 Esquema conexiones Maquina Estados.

Ahora, como en casos anteriores, se debe declarar todas las señales

necesarias y seguir la nomenclatura y las conexiones del esquema.

4.5.4. Código Máquina estados.

Anexo: 8.1.5.1.

Page 88: Memoria Main

88

4.5.5. Simulación Maquina estados.

Figura 84 Comportamiento maquina estados.

En esta primera figura se puede ver como se pasa de un estado a otro

mediante la condición SETE. Igual que en todo el proyecto el cambio de

estados se produce con un evento de reloj.

Figura 85 Comportamiento en el estado 01.

En esta figura, al principio se puede ver el comportamiento normal del reloj

incrementado el valor de segundos con cada pulso de reloj.

La segunda parte corresponde al funcionamiento de los módulos 60 dentro de

los estados de control, al cual se accede pulsando una vez SETE.

Cuando se acciona la entrada MODE el valor de segundos aumenta y cuando

no el valor permanece constante.

Este valor conmuta de su valor real a 10, que corresponde al valor

seleccionado dentro de los Convertidores, para mostrar un espacio en blanco

por pantalla. Gracias a esto se consigue el efecto de parpadeo que se

describirá posteriormente

Page 89: Memoria Main

89

4.6. LCD

Ahora solo queda la visualización del proyecto y para eso se implementará el

control de la pantalla LCD que dispone la placa. La web de

www.digilentinc.com tiene un código ejemplo para mostrar una frase

corporativa por pantalla. Se reciclará y modificará este código para que se

comporte de forma adecuada a la visualización de los datos.

http://www.digilentinc.com/Data/Products/NXLCD/lcd.vhd

Figura 86 Componente LCD.

4.6.1. Comportamiento del código.

El código ejemplo carga una variable con el contenido a mostrar, y sigue un

proceso secuencial para visualizar los datos. El proceso de forma general sigue

el patrón de cargar datos, enviar dato y visualizar dato. Este proceso se

controla mediante una serie de contadores fijos que gestionan el retardo entre

datos a mostrar, y los tiempos necesarios para enviar un dato correctamente y

visualizar dato correctamente.

Este código ejemplo dispone de un divisor de frecuencia propio, que adecua la

entrada de reloj de los 50 MHz a 10MHz. Hay que recordar que para evitar el

error de relojes múltiples, se ha de conecta la entrada de reloj del componente

LCD a la salida CLK0_OUT del DCM mediante la señal pertinente.

Este código muestra los datos precargados en una variable y una vez que llena

el máximo de caracteres visibles por el LCD desplaza el contenido de derecha

Page 90: Memoria Main

90

a izquierda mediante tabulaciones. Esto significa que el LCD es capaz de

cargar más datos de los que es capaz de mostrar a tiempo real.

Figura 87 Comportamiento pantalla LCD.

Si se quiere que los datos siempre sean visibles, se tendrá que tabular de tal

manera la información que se enviara a la pantalla, para que el contenido

deseado siempre este dentro del margen visible.

Figura 88 Introducción datos en pantalla.

Las casillas en blanco serán espacios, a fin de desplazar el texto útil a derecha

o izquierda según se necesite.

4.6.2. Modificación del código inicial.

Para corregir el tiempo de refresco de las letras en pantalla, puesto que el

diseño inicial del condigo se establecía un tiempo elevado entre la aparición de

una letra y la siguiente, se modificará el patrón para esta parte del código.

((stCur = stCharDelay and count = "00000000000011111"))

Código 29 Condición de retardo en la lectura de un carácter.

Otro punto a modifica es el hecho que este condigo funcionaba de forma

autónoma, una vez que empezaba, cargaba la variable fija de entrada y

Page 91: Memoria Main

91

mostraba su contenido automáticamente sin posibilidad de intervención

externa. Únicamente permitía reiniciar el proceso mediante la entrada rst.

Se hará uso precisamente de esto para gestionar como actualizar el contenido

de la variable de entrada, que será convertida en una señal para poder

modificar su información mediante la declaración de un proceso para esta

tarea.

El evento más rápido del reloj, es la actualización en tiempo real de los datos

de los segundos, por esa razón se utilizara la salida a 1 Hz del divisor de

frecuencia para reiniciar el proceso de presentación de datos. De este modo

cada vez se modifique el valor de los segundo, el programa automáticamente

recargara la señal de datos y realizara todo el proceso necesario para rellenar

la parrilla a mostrar por pantalla.

Algunos datos a mostrar por pantalla serán cargados inicialmente y solo se

tendrá que ir actualizando 6 variables, correspondientes a las unidades de

decenas de segundo, minutos y horas.

Tras declarar las entradas necesarias en el código, el proceso que gestiona la

adquisición y actualización de datos a mostrar es el siguiente:

4.6.2.1. Proceso de adquisición de datos a mostrar.

begin process

begin

LCD_CMDS(44) <= entrada5;

LCD_CMDS(45) <= entrada6;

LCD_CMDS(47) <= entrada3;

LCD_CMDS(48) <= entrada4;

LCD_CMDS(50) <= entrada1;

LCD_CMDS(51) <= entrada2;

end process;

Código 30 Proceso de adquisición.

Las posiciones asignadas han seguido el patrón descrito para situarlos en el

margen visible de la pantalla.

Tras efectuar estas modificaciones se hará uso de la función RTL para

visualizar el resultado, y así se dispondrá de la nomenclatura del componente

de forma general para su declaración en el archivo general, que contendrá

todos los bloques anteriormente explicados.

Page 92: Memoria Main

92

Figura 89 RTL componente LCD.

4.7. Convertidor de 4 bits a ASCII.

Los datos para ser enviados al componente LCD tiene que estar en formato

ASCII, pero las salidas de todos los componentes son 4 bits tanto para

unidades como para las decenas.

A fin de proporciona la entrada necesaria se ha diseñado un convertidor de

datos, capaz de transformar la entrada de 4 bits a la entrada de 10 bits, con la

estructura y el contenido en ASCII, necesaria para su correcto procesado por el

sistema de adquisición de datos del componente LCD.

Figura 90 Convertidor 4 bits a ASCII.

Este componente se declarara para cada uno de los valores a mostrar por

pantalla.

4.7.1. Método de conversión.

El método de conversión viene gestionado por un case que asigna la salida

adecuada en cada caso, recorriendo valores que van desde 0 a 9, ya que son

los necesarios para mostrar todas las configuraciones posibles en un reloj

tradicional.

Page 93: Memoria Main

93

Ejemplo:

WHEN "1000" => LDR1 <= "10"&X"38";

“10” -> Forma parte del vector de posicionamiento en pantalla.

“28” -> Corresponde al número 8 en ASCII.

4.7.2. Código Convertidor.

Anexo: 8.1.3.1.

4.7.3. Simulación se la conversión.

Figura 91 Simulación de la conversión.

El la figura se puede observar la conversión de 6 valores a ASCII, y la

correspondencia del estado 10 del CASE con un espacio en blanco, a fin de

propiciar el parpadeo.

Page 94: Memoria Main

94

4.8. Parpadeo del número seleccionado.

El último componente dentro del espacio de visualización, es el encargado de

hacer parpadear la cifra a modificar dentro de los estados de control de la

máquina de estados.

Aunque este componente pertenece propiamente a la máquina de estados, y

será declarado dentro de su componente, su explicación se ha relegado a la

parte visual del proyecto para seguir con la linealidad del desarrollo del mismo.

Esto se justifica porque hasta este punto no era necesario incluir ningún

método visual que permitiera al usuario saber en qué punto se encuentra la

máquina de estados.

Figura 92 Componente parpadeo.

Este componente es controlado por la salida a 10 Hz del divisor de frecuencia,

por esa razón se tendrá que incluir una segunda entrada de reloj al

componente maquina de estados (CLK2) y definir la señal necesaria para llevar

el segundo pulso a la entrada de reloj del componente.

4.8.1. Método de funcionamiento del parpadeo de la cifra.

Como hacer parpadear la cifra a 10 Hz era un número muy elevado se ha

implementado un divisor de frecuencia muy simple para conseguir

aproximadamente un parpadeo a 2 Hz.

PAR<='1' WHEN (DIV="00" or DIV="01") ELSE '0';

Figura 93 División simple de frecuencia.

Page 95: Memoria Main

95

En la condición anterior DIV, es un vector de 2 bits que incrementa su valor con

cada pulso de reloj, de este modo se consigue que la cifra solo parpadee la

mitad de su recorrido.

Antes se consideraba que el evento más rápido del programa era la

actualización del valor de segundos, ahora para poder visualizar el evento

parpadeo se necesita que el proceso del componente LCD se reinicie a mayor

velocidad. Por esa razón se substituirá la entrada rst del componente que

anteriormente estaba conectada la salida a 1 Hz del divisor de frecuencia, por

la salida de 10 Hz del mismo.

El control del dato que debe parpadear viene regido por la condición PAR y la

entrada estado proveniente de la máquina de estados.

ELSIF (PAR='0' And estado="11" ) THEN

STout<=STin;

SUout<=SUin;

MTout<=MTin;

MUout<=MUin;

HTout<="1010";

HUout<="1010";

Figura 94 Condición del parpadeo.

Cada estado menos el de reposo tiene un bloque de condición igual. En este

caso se muestra el modo de control de las horas. Cuando al número le

corresponda parpadear, se le asignara un valor definido por el usuario que

corresponderá a una posición del case del Convertidor de datos. Este valor

está definido fuera del método normal de funcionamiento para que no se

produzcan errores, y corresponde a la posición 10 del case. En esta posición

se asigna a la salida el valor correspondiente a un espacio en código ASCII

para que cuando el LCD lo capture, pinte por pantalla un hueco en blanco.

WHEN "1010" => LDR1<= "10"&X"20";

“Espacio”

Asi el comportamiento queda de la forma siguiente:

Par -> 1 1 0 0 1 1

HTout -> Dato Dato Espacio Espacio Dato Dato

Page 96: Memoria Main

96

4.8.2. Código parpadeo.

Anexo: 8.1.4.1.

4.8.3. Simulación parpadeo.

Figura 95 Simulación Parpadeo.

En la figura se puede observar como la cifra pasa de su valor origina a 1010

(correspondiente a un espacio en blanco en ASCII) cada dos pulsos del reloj de

entrada.

La condición que decide que cifra parpadea en cada instante es el estado en

que se encuentra, este estado concuerda con el valor de present_state en la

máquina de estados, haciendo coincidir así el parpadeo con el estado con el

cual se está interaccionando.

Con estas últimas modificaciones ya se tienen todas las herramientas que

fomentaran un buen funcionamiento del dispositivo.

Page 97: Memoria Main

97

4.9. Esquema final completo.

Se ha ido describiendo las conexiones bloque a bloque, pero para facilitar y comprobar el diseño, se ha elaborado el esquema completo que interconecta todos los componentes.

El código final tiene más salidas que las que se muestran, se han ido utilizando para seguir el funcionamiento y para mostrar el comportamiento de algunos elementos, como por ejemplo el bloque de reloj y sus medidas en el laboratorio.

4.9.1. Código archivo top global.

Anexo: 8.1.6.

Page 98: Memoria Main

98

4.9.2. Esquema teórico global.

lcd

CLKDB

RS

RW

ADR1

ADR2

CS

OE

rdone

(7 downto 0)

Convnum1Count LDR1

freq_divider_topDCMclock

CLK_1Hz

CLK_10Hz

CLK_1000Hz

CLKIN_IN

RST_IN

CLK_10000hez

CLKFX_OUT

CLKIN_IBUFG_OUT

CLK0_OUT

LOCKED_OUT

UD_L

STATE

MACHINESET

MODE

CLK

CLK2

CD

CEHT

HU

MT

MU

ST

SU

CLK

CD

CE

UD_L

SETE

MODE

OE

CS

rdone

ADR2

ADR1

RW

RS

DB (7 downto 0)

Salidas

Entradas

rst

CLK

CD

CE

CL

K0

_O

UT

CL

K_

1h

ez

CL

K_

10

he

z

Convnum2Count LDR1

Convnum3Count LDR1

Convnum4CountLDR1

Convnum5CountLDR1

Convnum6CountLDR1

TENS3sig (3 downto 0)

UNIS3sig (3 downto 0)

TENS2sig (3 downto 0)

UNIS2sig (3 downto 0)

TENSsig (3 downto 0)

UNISsig (3 downto 0)

LDR1sigLDR2sigLDR3sigLDR4sigLDR5sigLDR6sig

entrada1entrada2entrada3entrada4entrada5entrada6

Figura 96 Esquema completo de la aplicación.

Page 99: Memoria Main

99

4.9.3. RTL del sistema completo.

Por causa de su tamaño solo se muestra la primera parte, pero aun así se ve

que las pautas de conexiones son las mismas que en el esquema teórico.

Figura 97 RTL de la aplicación.

Page 100: Memoria Main

100

4.9.4. Comprobación de la aplicación.

4.9.4.1. UCF Aplicación.

Anexo: 8.1.7.

Tras introducir el código en la Spartan-3AN y tras un lago peregrinaje uniendo

todas las partes, por fin se puede ver el comportamiento del reloj en tiempo real

funcionando, y funcionando de forma predecible y satisfactoria.

Figura 98 Plano general funcionamiento aplicación.

Figura 99 Plano detalle aplicación.

Page 101: Memoria Main

101

5. Posibles mejoras.

Hoy en día se pueden encontrar en el mercado multitud de relojes diferentes,

desde los más sencillos a relojes destinados a senderismo y escalada que

disponen de brújula, altímetro, GPS y barómetro.

Figura 100 Reloj de montaña (RS800CX G3 - polar).

Por las dimensiones del hardware en el que se trabaja, no sería viable hacer un

dispositivo móvil similar, pero se podrían incluir los periféricos necesarios para

construir una estación fija para recopilar esta información.

El paso siguiente seria instalar este dispositivo en un determinado lugar y que

fuera capaz de realizar una tabla o base de datos de las condiciones del

entorno que le rodean, o incluso enviar dicha información a un ordenador o

móvil mediante su tarjeta de red.

Finalmente se podría abordar una tecnología emergente como la domótica para

incorporar la información de los periféricos que controlan un hogar o sistema de

alarma en el abanico de información que recopilamos con la Spartan-3AN, o

incluso utilizar el dispositivo para gobernar el domicilio, ya sea físicamente o

mediante la tarjeta de red desde un lugar remoto.

Figura 101 Hogar domótico.

Page 102: Memoria Main

102

6. Conclusiones

Este trabajo surgió de la necesidad de conocer la forma de programar las

diferentes FPGA‟s que nos rodean de los distintos fabricantes.

El documento iría destinado a gente similar al creador de este proyecto, que

hasta hace menos de un año desconocía por completo la programación de este

tipo de dispositivos, y cuando empezó carecía de un documento compacto y en

castellano para introducirse en el mundo de la Spartan-3AN, ya que la mayora

de tutoriales abarcaban proyectos mucho mayores y complejos.

En la elaboración de proyectos, se han construidos códigos sencillos y códigos

compuestos gobernados por un reloj de entrada. En cuando a los diferentes

métodos de adecuar la frecuencia de entrada a nuestro dispositivo, se han

implementado divisores de frecuencia y utilizado IP‟s (Intelectual Properties),

como el componente DCM para evitar saltos abruptos en frecuencia.

Se ha visto que el uso del componente DCM es mucho mejor, ya que

reconstruye mucho mejor la señal de salida, pero presenta un abanico de

frecuencias muy elevadas para conseguir un pulso a un 1 Hz.

Simulando los diseños se ha podido comprobar la practicidad frente al archivo

.DO del uso del TestBench, por su incrustación dentro del programa de diseño

y su inmediatez tanto por la cantidad de código que ofrece resuelto, como

puede ser la implementación del reloj, o en la obtención de los datos de la

simulación.

Se ha implementado un maquina de estados capaz de gobernar un buen grupo

de componentes sumisos a ella y a su vez dependiente de un reloj de entrada.

Esta máquina es la encargada de gestionar el modo de funcionamiento y la

puesta en hora del dispositivo. Para su creación se ha seguido un diagrama de

estados y un modelo circuital creado previamente de forma teórica.

La visualización se ha resuelto incorporando el uso del periférico LCD. Se ha

podido ver cómo funciona y como modificar un código origen para un uso

deseado. La adecuación de la información de entrada ha sido resuelta

mediante un convertidor de datos a un formato esperado, a fin de ser

correctamente procesada la información por el LCD.

Finalmente se han implementado pequeñas mejoras estéticas como el

parpadeo del dato seleccionado para ser modificado, dentro de los estados de

control en la STATE MACHINE.

Page 103: Memoria Main

103

7. Bibliografía

7.1. Tutoriales en formato PDF que proporción la Web de

Xilinx.

Spartan-3 Generation Configuration User Guide (PDF)

Spartan-3 Generation FPGA User Guide (PDF)

Device Reliability Report, First Quarter 2010 (PDF)

Spartan-3AN FPGA In-System Flash User Guide (PDF)

http://www.xilinx.com/support/documentation/spartan-3an.htm

7.2. Control Flash.

Esquemas de funcionamiento de la memoria.

http://www.edudevices.com.ar/download/articulos/cursoMCUs/ParteII_Capitulo_

11.pdf

http://www.xilinx.com/support/documentation/boards_and_kits/s3astarter_sche

matic.pdf

7.3. Control del LCD

2x16 LCD display program in VHDL

http://www.edaboard.com/ftopic348429.html

Digilent Sample VHDL Code for LCD - Same model of LCD

http://www.digilentinc.com/Data/Products/NXLCD/lcd.vhd

Page 104: Memoria Main

104

7.4. VHDL Test Bench

VHDL Test Bench.

http://webdocs.cs.ualberta.ca/~amaral/courses/329/labs/Testbench.html

7.5. EPSC Página Electrónica digital y Sistema Electrónicos

Digitales.

Divisores de frecuencia.

Modelo Maquina Estados.

http://digsys.upc.es/ed/

Page 105: Memoria Main

105

8. Anexos

8.1. Códigos.

En este apartado se incluirán todos los códigos necesarios para realizar la

aplicación y que resultarían farragosos insertados dentro de la lectura.

8.1.1. Freg_divider_top

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_ARITH.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY freq_divider_top IS

PORT(CD,CLK,CE : IN std_logic;

CLK_1000Hz : OUT std_logic;

CLK_10Hz : OUT std_logic;

CLK_1Hz : OUT std_logic

);

END freq_divider_top;

ARCHITECTURE schematic OF freq_divider_top IS

-- Components

COMPONENT freq_div_100 IS

PORT(CD,CLK,CE : IN std_logic;

TC100 : OUT std_logic

);

END COMPONENT;

COMPONENT freq_div_49999 IS

PORT(CD,CLK,CE : IN std_logic;

TC49999 : OUT std_logic

);

END COMPONENT;

COMPONENT freq_div_10 IS

PORT(CD,CLK,CE : IN std_logic;

TC10 : OUT std_logic

);

END COMPONENT;

-- Signals

-- For connecting components together

SIGNAL CE2, CE3, CE1 : std_logic;

BEGIN

-- Instantiation of components

freq_div_49999_Comp1 : freq_div_49999

PORT MAP (

-- from component name => to signal or port name

CLK => CLK,

CD => CD,

CE => CE,

TC49999 => CE2

);

Page 106: Memoria Main

106

freq_div_100_Comp1 : freq_div_100

PORT MAP (

CLK => CE2,

CD => CD,

CE => CE,

TC100 => CE3

);

--

freq_div_10_Comp1 : freq_div_10

PORT MAP (

CLK => CE3,

CD => CD,

CE => CE,

TC10 => CE1

);

--

-- connections and logic between components

CLK_1000Hz <= CE2;

CLK_10Hz <= CE3;

CLK_1Hz <= CE1;

END schematic ;

8.1.1.1. Freg_divider_49999.

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_ARITH.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY freq_div_49999 IS

PORT(CD,CLK,CE : IN std_logic;

TC49999 : OUT std_logic

);

END freq_div_49999;

ARCHITECTURE FSM_style OF freq_div_49999 IS

SIGNAL present_state, future_state : std_logic_vector(13 DOWNTO 0);

BEGIN

-- State register, normally in FF-D

state_register: PROCESS (CD,CLK)

BEGIN

IF (CD='1') THEN

present_state <= "00000000000000";

ELSIF (CLK='1' AND CLK'event) THEN

present_state <= future_state;

END IF;

END PROCESS state_register;

-- combinational logic for determining the next state

CS1: PROCESS (present_state,CE)

BEGIN

IF CE = '1' THEN

IF (present_state = "10011100001111") THEN -- 0x18 == 0d24

future_state <= "00000000000000";

ELSE

future_state <= present_state + 1;

END IF;

ELSE

future_state <= present_state;

END IF;

END PROCESS CS1;

-- combinational logic to determine the outputs

-- CS2:

TC49999 <= '1' WHEN (present_state = "10011100001111" AND CE = '1') ELSE '0';

END FSM_style ;

Page 107: Memoria Main

107

8.1.1.2. Freg_divider_100.

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_ARITH.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY freq_div_100 IS

PORT(CD,CLK,CE : IN std_logic;

TC100 : OUT std_logic

);

END freq_div_100;

ARCHITECTURE FSM_style OF freq_div_100 IS

SIGNAL present_state, future_state : std_logic_vector(6 DOWNTO 0);

BEGIN

-- State register, normally in FF-D

state_register: PROCESS (CD,CLK)

BEGIN

IF (CD='1') THEN

present_state <= "0000000";

ELSIF (CLK='1' AND CLK'event) THEN

present_state <= future_state;

END IF;

END PROCESS state_register;

-- combinational logic for determining the next state

CS1: PROCESS (present_state,CE)

BEGIN

IF CE = '1' THEN

IF (present_state = "1100011") THEN --> 0x3EE == 0d1006

future_state <= "0000000";

ELSE

future_state <= present_state + 1;

END IF;

ELSE

future_state <= present_state;

END IF;

END PROCESS CS1;

-- combinational logic to determine the outputs

-- CS2:

TC100 <= '1' WHEN (present_state = "1100011" AND CE = '1') ELSE '0';

END FSM_style ;

8.1.1.3. Freg_divier_10.

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_ARITH.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY freq_div_10 IS

PORT(CD,CLK,CE : IN std_logic;

TC10 : OUT std_logic

);

END freq_div_10;

ARCHITECTURE FSM_style OF freq_div_10 IS

SIGNAL present_state, future_state : std_logic_vector(4 DOWNTO 0);

--signal senal : std_logic;

--signal control : std_logic_vector(1 DOWNTO 0);

BEGIN

Page 108: Memoria Main

108

-- State register, normally in FF-D

state_register: PROCESS (CD,CLK)

BEGIN

IF (CD='1') THEN

present_state <= "00000";

ELSIF (CLK='1' AND CLK'event) THEN

present_state <= future_state;

END IF;

END PROCESS state_register;

-- combinational logic for determining the next state

CS1: PROCESS (present_state,CE)

BEGIN

IF CE = '1' THEN

IF (present_state = "01001") THEN -- 0x1387 == 0d4999

future_state <= "00000";

ELSE

future_state <= present_state + 1;

END IF;

ELSE

future_state <= present_state;

END IF;

END PROCESS CS1;

TC10 <= '1' WHEN (present_state = "01001" AND CE = '1') ELSE '0';

END FSM_style ;

8.1.1.4. TestBench para simulación (freg_divider_top).

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

USE ieee.std_logic_unsigned.all;

USE ieee.numeric_std.ALL;

ENTITY blorelojsim IS

END blorelojsim;

ARCHITECTURE behavior OF blorelojsim IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT freq_divider_top

PORT(

CD : IN std_logic;

CLK : IN std_logic;

CE : IN std_logic;

CLK_1000Hz : OUT std_logic;

CLK_10Hz : OUT std_logic;

CLK_1Hz : OUT std_logic

);

END COMPONENT;

--Inputs

signal CD : std_logic := '0';

signal CLK : std_logic := '0';

signal CE : std_logic := '0';

--Outputs

signal CLK_1000Hz : std_logic;

signal CLK_10Hz : std_logic;

signal CLK_1Hz : std_logic;

-- Clock period definitions

constant CLK_period : time := 1 ns;

-- constant CLK_1000Hz_period : time := 10 ns;

-- constant CLK_10Hz_period : time := 10 ns;

-- constant CLK_1Hz_period : time := 10 ns;

BEGIN

Page 109: Memoria Main

109

-- Instantiate the Unit Under Test (UUT)

uut: freq_divider_top PORT MAP (

CD => CD,

CLK => CLK,

CE => CE,

CLK_1000Hz => CLK_1000Hz,

CLK_10Hz => CLK_10Hz,

CLK_1Hz => CLK_1Hz

);

-- Clock process definitions

CLK_process :process

begin

CLK <= '0';

wait for CLK_period/2;

CLK <= '1';

wait for CLK_period/2;

end process;

-- CLK_1000Hz_process :process

-- begin

-- CLK_1000Hz <= '0';

-- wait for CLK_1000Hz_period/2;

-- CLK_1000Hz <= '1';

-- wait for CLK_1000Hz_period/2;

-- end process;

--

-- CLK_10Hz_process :process

-- begin

-- CLK_10Hz <= '0';

-- wait for CLK_10Hz_period/2;

-- CLK_10Hz <= '1';

-- wait for CLK_10Hz_period/2;

-- end process;

--

-- CLK_1Hz_process :process

-- begin

-- CLK_1Hz <= '0';

-- wait for CLK_1Hz_period/2;

-- CLK_1Hz <= '1';

-- wait for CLK_1Hz_period/2;

-- end process;

-- Stimulus process

stim_proc: process

begin

-- hold reset state for 100 ms.

CD <='0';

CE<= '0';

wait for CLK_period*10;

CD <='0';

CE<= '1';

wait for CLK_period*100;

CD <='1';

CE<= '1';

wait for CLK_period*100;

CD <='0';

CE<= '1';

wait for CLK_period*100;

CD <='0';

CE<= '0';

wait for CLK_period*100;

CD <='0';

CE<= '1';

Page 110: Memoria Main

110

wait for CLK_period*10000;

-- insert stimulus here

wait;

end process;

END;

8.1.2. Control Temporal.

8.1.2.1. Modulo 60.

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_ARITH.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY module60 IS

PORT

(CD,CLK,CE, UD_L : IN std_logic;

TC60 : OUT std_logic;

TENS : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);

UNIS : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)

);

END module60;

ARCHITECTURE schematic OF module60 IS

-- Components

COMPONENT Counter IS

Port (

CLK : IN STD_LOGIC;

LD : IN STD_LOGIC;

CD : IN STD_LOGIC;

CE : IN STD_LOGIC;

UD_L : IN STD_LOGIC;

I : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

Q : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

TC10 : OUT STD_LOGIC

);

END COMPONENT;

COMPONENT four_bit_mux IS

PORT (

s : IN STD_LOGIC;

a : IN STD_LOGIC_VECTOR (3 downto 0);

b : IN STD_LOGIC_VECTOR (3 downto 0);

z : OUT STD_LOGIC_VECTOR (3 downto 0));

END COMPONENT;

COMPONENT two_bit_mux IS

PORT (

s : IN STD_LOGIC;

a,b : IN STD_LOGIC;

z : OUT STD_LOGIC

);

END COMPONENT;

COMPONENT detect5 IS

Page 111: Memoria Main

111

PORT (

x: IN STD_LOGIC_VECTOR (3 downto 0);

z: OUT STD_LOGIC

);

END COMPONENT;

-- Signals

-- For connecting components together

SIGNAL TCUNITS, TCTENS, DET5, TC60UP, TC60DOWN, LDTENS : std_logic;

SIGNAL ITENS,T,U : std_logic_vector (3 downto 0);

--SIGNAL clk2hz : STD_LOGIC;

CONSTANT Reset : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";

CONSTANT Cinco : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0101";

BEGIN

-- Instantiation of components

CounterTENS: Counter

PORT MAP (

-- from component name => to signal or port name

CLK => CLK,

LD => LDTENS,

CD => CD,

CE => TCUNITS,

UD_L => UD_L,

I => ITENS,

Q => T,

TC10 => TCTENS

);

CounterUNITS : Counter

PORT MAP (

-- from component name => to signal or port name

CLK => CLK,

LD => '0',

CD => CD,

CE => CE,

UD_L => UD_L,

I => Reset,

Q => U,

TC10 => TCUNITS

);

QUADMUX1 : four_bit_mux

PORT MAP (

-- from component name => to signal or port name

s => UD_L,

a => Cinco,

b => Reset,

z => ITENS

);

QUADMUX2 : two_bit_mux

PORT MAP (

-- from component name => to signal or port name

s => UD_L,

a => TC60DOWN,

b => TC60UP,

z => LDTENS

);

Detector : detect5

PORT MAP (

-- from component name => to signal or port name

x => T,

z => DET5

);

Page 112: Memoria Main

112

-- SORTIDES:

TC60 <= LDTENS;

TC60UP <= (DET5 AND TCUNITS);

TC60DOWN <= (TCTENS AND TCUNITS);

TENS <= T;

UNIS <= U;

END schematic ;

8.1.2.1.1. Counter.

LIBRARY ieee;

USE IEEE.STD_LOGIC_1164.all;

USE IEEE.STD_LOGIC_ARITH.all;

USE IEEE.STD_LOGIC_UNSIGNED.all;

ENTITY Counter IS

Port (

CLK : IN STD_LOGIC;

LD : IN STD_LOGIC;

CD : IN STD_LOGIC;

CE : IN STD_LOGIC;

UD_L : IN STD_LOGIC;

I : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

Q : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

TC10 : OUT STD_LOGIC

);

END Counter;

-- Internal desciption in FSM style

ARCHITECTURE FSM_like OF Counter IS

CONSTANT Max_Count : STD_LOGIC_VECTOR(3 DOWNTO 0) := "1001";

-- terminal_count after 13 states

CONSTANT Max_Count2 : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";

CONSTANT Reset : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000";

CONSTANT Reset2 : STD_LOGIC_VECTOR(3 DOWNTO 0) := "1001";

-- Internal wires

SIGNAL present_state,future_state: STD_LOGIC_VECTOR(3 DOWNTO 0);

BEGIN

------------------------------ the only clocked block : the state register

state_register: PROCESS (CD,CLK)

BEGIN

IF CD = '1' THEN -- reset counter

present_state <= Reset;

ELSIF (CLK'EVENT and CLK = '1') THEN -- Synchronous register (D-type flip-flop)

present_state <= future_state;

END IF;

END PROCESS state_register;

------------------------- combinational system for calculating next state

CS_1: PROCESS (present_state,CE,I,LD, UD_L)

BEGIN

IF LD = '0' THEN

IF CE = '1' THEN

IF UD_L = '1' THEN

IF(present_state < Max_Count ) THEN

future_state <= present_state + 1 ;

ELSE

future_state <= Reset;

END IF;

ELSE

IF(present_state > Max_Count2 ) THEN

future_state <= present_state - 1 ;

Page 113: Memoria Main

113

ELSE

future_state <= Reset2;

END IF;

END IF;

ELSE

future_state <= present_state; -- count disable

END IF;

ELSE

future_state <= I;

END IF;

END PROCESS CS_1;

------------------------- CS_2: combinational system for calculating extra outputs

-------------------------- and outputing the present state (the actual count)

TC10 <= '1' WHEN ((present_state = Max_count)AND CE = '1'AND UD_L= '1') OR

((present_state = Max_count2)AND CE = '1' AND UD_L = '0') ELSE '0'; --terminal count

Q <= present_state;

END FSM_like;

8.1.2.1.2. Four_bit_mux.

LIBRARY ieee;

USE IEEE.STD_LOGIC_1164.all;

USE IEEE.STD_LOGIC_ARITH.all;

USE IEEE.STD_LOGIC_UNSIGNED.all;

ENTITY four_bit_mux IS

PORT (

s: IN STD_LOGIC;

a, b: IN STD_LOGIC_VECTOR (3 DOWNTO 0);

z: OUT STD_LOGIC_VECTOR (3 DOWNTO 0)

);

END four_bit_mux;

ARCHITECTURE mux OF four_bit_mux IS

-- specific names 'mux' and '4_bit_mux are not important

BEGIN

WITH s SELECT

z <= a WHEN '0' ,

b WHEN others;

END mux;

8.1.2.1.3. Two_bit_mux.

LIBRARY ieee;

USE IEEE.STD_LOGIC_1164.all;

USE IEEE.STD_LOGIC_ARITH.all;

USE IEEE.STD_LOGIC_UNSIGNED.all;

ENTITY two_bit_mux IS

PORT (

Page 114: Memoria Main

114

s: IN STD_LOGIC;

a, b: IN STD_LOGIC;

z: OUT STD_LOGIC

);

END two_bit_mux;

ARCHITECTURE mux OF two_bit_mux IS

-- specific names 'mux' and '4_bit_mux are not important

BEGIN

WITH s SELECT

z <= a WHEN '0' ,

b WHEN others;

END mux;

8.1.2.1.4. Detect5.

LIBRARY ieee;

USE IEEE.STD_LOGIC_1164.all;

USE IEEE.STD_LOGIC_ARITH.all;

USE IEEE.STD_LOGIC_UNSIGNED.all;

ENTITY detect5 IS

PORT (

x: IN STD_LOGIC_VECTOR (3 downto 0);

z: OUT STD_LOGIC

);

END detect5;

ARCHITECTURE dec5 OF detect5 IS

BEGIN

z <= '1' WHEN (x = "0101") ELSE '0';

END dec5;

Page 115: Memoria Main

115

8.1.2.2. TestBench para simulación (Modulo60).

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

USE ieee.std_logic_unsigned.all;

USE ieee.numeric_std.ALL;

ENTITY segundos IS

END segundos;

ARCHITECTURE behavior OF segundos IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT module60

PORT(

CD : IN std_logic;

CLK : IN std_logic;

CE : IN std_logic;

UD_L : IN std_logic;

TC60 : OUT std_logic;

TENS : OUT std_logic_vector(3 downto 0);

UNIS : OUT std_logic_vector(3 downto 0)

);

END COMPONENT;

--Inputs

signal CD : std_logic := '0';

signal CLK : std_logic := '0';

signal CE : std_logic := '0';

signal UD_L : std_logic := '0';

--Outputs

signal TC60 : std_logic;

signal TENS : std_logic_vector(3 downto 0);

signal UNIS : std_logic_vector(3 downto 0);

-- Clock period definitions

constant CLK_period : time := 10 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)

uut: module60 PORT MAP (

CD => CD,

CLK => CLK,

CE => CE,

UD_L => UD_L,

TC60 => TC60,

TENS => TENS,

UNIS => UNIS

);

-- Clock process definitions

CLK_process :process

begin

CLK <= '0';

wait for CLK_period/2;

CLK <= '1';

wait for CLK_period/2;

end process;

-- Stimulus process

stim_proc: process

begin

CD <= '0';

CE <= '0';

UD_L <= '1';

-- hold reset state for 100 ms.

wait for 10 ns;

CD <='0';

CE <= '1';

Page 116: Memoria Main

116

UD_L <= '1';

wait for CLK_period*20;

-- insert stimulus here

wait;

end process;

END;

8.1.2.3. Modulo 24.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity Contador24 is

PORT(CD,clock,CE,dir : IN std_logic;

TENS : out std_logic_vector(3 DOWNTO 0);

UNIS : out std_logic_vector(3 DOWNTO 0)

);

end Contador24;

architecture Behavioral of Contador24 is

signal control : std_logic_vector(3 DOWNTO 0):= "0001";

begin

sumador: PROCESS (CD,CE,clock,dir)

begin

IF (CE='1') THEN

IF (CD='1') THEN

control <= "0001";

ELSIF (clock='1' AND clock'event) THEN

IF (control="1100" and dir='1') THEN

--Reset a 0

control <= "0001";

ELSIF (control="0001" and dir='0') THEN --Reset a 12

control <= "1100";

ELSE

IF (dir='1') THEN

control <= control + 1;

END IF;

IF (dir='0') THEN

control <= control - 1;

END IF;

END IF;

-- IF (control = "0011") then

-- report "Contador en 0011 OK!"

-- severity Note;

-- end if;

END IF;

END IF;

END PROCESS sumador;

PROCESS (control(3 DOWNTO 0))

BEGIN

CASE control IS

WHEN "0000" => UNIS<= "0000";

WHEN "0001" => UNIS<= "0001";

Page 117: Memoria Main

117

WHEN "0010" => UNIS<= "0010";

WHEN "0011" => UNIS<= "0011";

WHEN "0100" => UNIS<= "0100";

WHEN "0101" => UNIS<= "0101";

WHEN "0110" => UNIS<= "0110";

WHEN "0111" => UNIS<= "0111";

WHEN "1000" => UNIS<= "1000";

WHEN "1001" => UNIS<= "1001";

WHEN "1010" => UNIS<= "0000";

WHEN "1011" => UNIS<= "0001";

WHEN "1100" => UNIS<= "0010";

WHEN "1101" => UNIS<= "0000";

WHEN "1110" => UNIS<= "0000";

WHEN OTHERS => UNIS<= "0000";

END CASE;

END PROCESS;

TENS<= "0001" WHEN (control="1100" OR control="1011" OR control="1010" ) ELSE "0000";

end Behavioral;

8.1.2.4. TestBench para simulación (Modulo24).

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

USE ieee.std_logic_unsigned.all;

USE ieee.numeric_std.ALL;

ENTITY horassim IS

END horassim;

ARCHITECTURE behavior OF horassim IS

-- Component Declaration for the Unit Under Test (UUT)

Page 118: Memoria Main

118

COMPONENT Contador24

PORT(

CD : IN std_logic;

clock : IN std_logic;

CE : IN std_logic;

dir : IN std_logic;

TENS : OUT std_logic_vector(3 downto 0);

UNIS : OUT std_logic_vector(3 downto 0)

);

END COMPONENT;

--Inputs

signal CD : std_logic := '0';

signal clock : std_logic := '0';

signal CE : std_logic := '0';

signal dir : std_logic := '0';

--Outputs

signal TENS : std_logic_vector(3 downto 0);

signal UNIS : std_logic_vector(3 downto 0);

-- Clock period definitions

constant clock_period : time := 10 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)

uut: Contador24 PORT MAP (

CD => CD,

clock => clock,

CE => CE,

dir => dir,

TENS => TENS,

UNIS => UNIS

);

-- Clock process definitions

clock_process :process

begin

clock <= '0';

wait for clock_period/2;

clock <= '1';

wait for clock_period/2;

end process;

-- Stimulus process

stim_proc: process

begin

CD <= '0';

CE <= '0';

dir <= '0';

-- hold reset state for 100 ms.

wait for clock_period*10;

CD <= '0';

CE <= '1';

dir <= '0';

wait for clock_period*10;

CD <= '1';

CE <= '0';

dir <= '0';

wait for clock_period*10;

CD <= '0';

CE <= '1';

dir <= '1';

wait for clock_period*10;

CD <= '0';

CE <= '1';

dir <= '0';

wait for clock_period*10;

Page 119: Memoria Main

119

-- insert stimulus here

wait;

end process;

END;

8.1.3. Conversión de datos.

8.1.3.1. Prub3.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity Prub3 is

Port ( Count : in STD_LOGIC_VECTOR (3 downto 0);

--LDR1 : out std_logic_vector(9 downto 0);

LDR1 : out std_logic_vector(9 downto 0));

-- LCD_DB : inout STD_LOGIC_VECTOR (7 downto 0);

-- LCD_E : out STD_LOGIC_VECTOR (0 downto 0);

-- LCD_RS : out STD_LOGIC_VECTOR (0 downto 0);

-- LCD_RW : out STD_LOGIC_VECTOR (0 downto 0));

end Prub3;

architecture Behavioral of Prub3 is

--signal lcd_rw_control : std_logic;

--signal lcd_output_data : std_logic_vector(7 downto 4);

--signal lcd_drive : std_logic;

begin

PROCESS (Count(3 DOWNTO 0))

BEGIN

--LDR(0)<=Count(0);

--LDR(1)<=Count(1);

--LDR(2)<=Count(2);

--LDR(3)<=Count(3);

CASE Count IS

WHEN "0000" => LDR1<= "10"&X"30";

--LDR2<= "10"&X"30";

WHEN "0001" => LDR1<= "10"&X"31";

--LDR2<= "10"&X"31";

WHEN "0010" => LDR1<= "10"&X"32";

--LDR2<= "10"&X"32";

WHEN "0011" => LDR1<= "10"&X"33";

--LDR2<= "10"&X"33";

WHEN "0100" => LDR1<= "10"&X"34";

--LDR2<= "10"&X"34";

WHEN "0101" => LDR1<= "10"&X"35";

--LDR2<= "10"&X"35";

WHEN "0110" => LDR1<= "10"&X"36";

--LDR2<= "10"&X"36";

WHEN "0111" => LDR1<= "10"&X"37";

--LDR2<= "10"&X"37";

WHEN "1000" => LDR1<= "10"&X"38";

--LDR2<= "10"&X"38";

Page 120: Memoria Main

120

WHEN "1001" => LDR1<= "10"&X"39";

--LDR2<= "10"&X"39";

WHEN "1010" => LDR1<= "10"&X"20";

--LDR2<= "10"&X"30";

WHEN "1011" => LDR1<= "10"&X"31";

--LDR2<= "10"&X"31";

WHEN "1100" => LDR1<= "10"&X"31";

--LDR2<= "10"&X"32";

WHEN "1101" => LDR1<= "10"&X"31";

--LDR2<= "10"&X"33";

WHEN "1110" => LDR1<= "10"&X"31";

--LDR2<= "10"&X"34";

WHEN OTHERS => LDR1<= "10"&X"31";

--LDR2<= "10"&X"35";

END CASE;

END PROCESS;

--lcd_rw(0)<='1';

--LCD_DB(3 DOWNTO 0 )<=Count(3 DOWNTO 0);

end Behavioral;

8.1.3.2. TestBench para simulación (Prub1).

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

USE ieee.std_logic_unsigned.all;

USE ieee.numeric_std.ALL;

ENTITY convsim IS

END convsim;

ARCHITECTURE behavior OF convsim IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT Prub3

PORT(

Count : IN std_logic_vector(3 downto 0);

LDR1 : OUT std_logic_vector(9 downto 0)

);

END COMPONENT;

--Inputs

signal Count : std_logic_vector(3 downto 0) := (others => '0');

--Outputs

signal LDR1 : std_logic_vector(9 downto 0);

BEGIN

-- Instantiate the Unit Under Test (UUT)

uut: Prub3 PORT MAP (

Count => Count,

LDR1 => LDR1

);

-- No clocks detected in port list. Replace <clock> below with

-- appropriate port name

-- constant <clock>_period := 20 ns;

--

-- <clock>_process :process

-- begin

-- <clock> <= '0';

Page 121: Memoria Main

121

-- wait for <clock>_period/2;

-- <clock> <= '1';

-- wait for <clock>_period/2;

-- end process;

-- Stimulus process

stim_proc: process

begin

-- hold reset state for 100 ms.

Count <="0000";

wait for 2000 ns;

Count <="0001";

wait for 20 ns;

Count <="0010";

wait for 20 ns;

Count <="0011";

wait for 20 ns;

Count <="0100";

wait for 20 ns;

Count <="0101";

wait for 20 ns;

Count <="0110";

wait for 20 ns;

Count <="1010";

wait for 20 ns;

-- insert stimulus here

wait;

end process;

END;

8.1.4. Control Visual.

8.1.4.1. Parpadeo.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity Parpadeo is

PORT (

CLK : IN STD_LOGIC;

estado : IN STD_LOGIC_VECTOR(1 DOWNTO 0);

HTin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

HUin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

MTin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

MUin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

STin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

SUin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

HTout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

HUout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MTout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MUout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

STout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

SUout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)

--TC24 : OUT STD_LOGIC

Page 122: Memoria Main

122

);

end Parpadeo;

architecture Behavioral of Parpadeo is

SIGNAL DIV : STD_LOGIC_VECTOR(1 DOWNTO 0);

-- SIGNAL HUsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

-- SIGNAL MTsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

-- SIGNAL MUsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

-- SIGNAL STsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

-- SIGNAL SUsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

SIGNAL PAR : STD_LOGIC:= '0';

begin

state_register: PROCESS (CLK)

BEGIN

IF (CLK='1' AND CLK'event) THEN

DIV<= DIV+1;

END IF;

END PROCESS state_register;

Parpadeo : PROCESS (PAR,estado)

BEGIN

IF (estado="00" ) THEN

STout<=STin;

SUout<=SUin;

MTout<=MTin;

MUout<=MUin;

HTout<=HTin;

HUout<=HUin;

--END IF;

ELSIF (PAR='1' And estado="01" ) THEN

STout<=STin;

SUout<=SUin;

MTout<=MTin;

MUout<=MUin;

HTout<=HTin;

HUout<=HUin;

ELSIF (PAR='0' And estado="01" ) THEN

STout<="1010";

SUout<="1010";

MTout<=MTin;

MUout<=MUin;

HTout<=HTin;

HUout<=HUin;

--END IF;

ELSIF (PAR='1' And estado="10" ) THEN

STout<=STin;

SUout<=SUin;

MTout<=MTin;

MUout<=MUin;

HTout<=HTin;

HUout<=HUin;

ELSIF (PAR='0' And estado="10" ) THEN

STout<=STin;

SUout<=SUin;

MTout<="1010";

MUout<="1010";

HTout<=HTin;

HUout<=HUin;

--END IF;

ELSIF (PAR='1' And estado="11" ) THEN

STout<=STin;

SUout<=SUin;

MTout<=MTin;

MUout<=MUin;

HTout<=HTin;

HUout<=HUin;

ELSIF (PAR='0' And estado="11" ) THEN

STout<=STin;

SUout<=SUin;

MTout<=MTin;

MUout<=MUin;

HTout<="1010";

HUout<="1010";

Page 123: Memoria Main

123

END IF;

END PROCESS Parpadeo;

PAR<='1' WHEN (DIV="00" or DIV="01") ELSE '0';

end Behavioral;

8.1.4.2. TestBench para simulación (Parpadeo).

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

USE ieee.std_logic_unsigned.all;

USE ieee.numeric_std.ALL;

ENTITY parpasim2 IS

END parpasim2;

ARCHITECTURE behavior OF parpasim2 IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT Parpadeo

PORT(

CLK : IN std_logic;

estado : IN std_logic_vector(1 downto 0);

HTin : IN std_logic_vector(3 downto 0);

HUin : IN std_logic_vector(3 downto 0);

MTin : IN std_logic_vector(3 downto 0);

MUin : IN std_logic_vector(3 downto 0);

STin : IN std_logic_vector(3 downto 0);

SUin : IN std_logic_vector(3 downto 0);

HTout : OUT std_logic_vector(3 downto 0);

HUout : OUT std_logic_vector(3 downto 0);

MTout : OUT std_logic_vector(3 downto 0);

MUout : OUT std_logic_vector(3 downto 0);

STout : OUT std_logic_vector(3 downto 0);

SUout : OUT std_logic_vector(3 downto 0)

);

END COMPONENT;

--Inputs

signal CLK : std_logic := '0';

signal estado : std_logic_vector(1 downto 0) := (others => '0');

signal HTin : std_logic_vector(3 downto 0) := (others => '0');

signal HUin : std_logic_vector(3 downto 0) := (others => '0');

signal MTin : std_logic_vector(3 downto 0) := (others => '0');

signal MUin : std_logic_vector(3 downto 0) := (others => '0');

signal STin : std_logic_vector(3 downto 0) := (others => '0');

signal SUin : std_logic_vector(3 downto 0) := (others => '0');

--Outputs

signal HTout : std_logic_vector(3 downto 0);

signal HUout : std_logic_vector(3 downto 0);

signal MTout : std_logic_vector(3 downto 0);

signal MUout : std_logic_vector(3 downto 0);

signal STout : std_logic_vector(3 downto 0);

signal SUout : std_logic_vector(3 downto 0);

-- Clock period definitions

constant CLK_period : time := 40 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)

uut: Parpadeo PORT MAP (

CLK => CLK,

estado => estado,

Page 124: Memoria Main

124

HTin => HTin,

HUin => HUin,

MTin => MTin,

MUin => MUin,

STin => STin,

SUin => SUin,

HTout => HTout,

HUout => HUout,

MTout => MTout,

MUout => MUout,

STout => STout,

SUout => SUout

);

-- Clock process definitions

CLK_process :process

begin

CLK <= '0';

wait for CLK_period/2;

CLK <= '1';

wait for CLK_period/2;

end process;

-- Stimulus process

stim_proc: process

begin

estado <="00";

HTin <="1100";

HUin <="1100";

MTin <="0110";

MUin <="0110";

STin <="0011";

SUin <="0011";

-- hold reset state for 100 ms.

wait for 1000 ns;

estado <="01";

HTin <="1100";

HUin <="1100";

MTin <="0110";

MUin <="0110";

STin <="0011";

SUin <="0011";

wait for CLK_period*10;

estado <="10";

HTin <="1100";

HUin <="1100";

MTin <="0110";

MUin <="0110";

STin <="0011";

SUin <="0011";

wait for CLK_period*10;

estado <="11";

HTin <="1100";

HUin <="1100";

MTin <="0110";

MUin <="0110";

STin <="0011";

SUin <="0011";

wait for CLK_period*10;

-- insert stimulus here

wait;

end process;

END;

Page 125: Memoria Main

125

8.1.4.3. LCD.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity lcd is

Port ( DB:out std_logic_vector(7 downto 0); --DB( 7 through 0)

RS:out std_logic; --WE

RW:out std_logic; --ADR(0)

CLK:in std_logic; --GCLK2

ADR1:out std_logic; --ADR(1)

ADR2:out std_logic; --ADR(2)

entrada1 : in std_logic_vector(9 downto 0);

entrada2 : in std_logic_vector(9 downto 0);

entrada3 : in std_logic_vector(9 downto 0);

entrada4 : in std_logic_vector(9 downto 0);

entrada5 : in std_logic_vector(9 downto 0);

entrada6 : in std_logic_vector(9 downto 0);

CS:out std_logic; --CSC

OE:out std_logic; --OE

rst:in std_logic; --BTN

rdone: out std_logic);

--WriteDone output to work with DI05 test

end lcd;

architecture Behavioral of lcd is

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

-- Component Declarations

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

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

-- Local Type Declarations

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

-- Symbolic names for all possible states of the state machines.

--LCD control state machine

type mstate is (

stFunctionSet,

--Initialization states

stDisplayCtrlSet,

stDisplayClear,

stPowerOn_Delay,

--Delay states

stFunctionSet_Delay,

stDisplayCtrlSet_Delay,

stDisplayClear_Delay,

stInitDne,

--Display charachters and perform standard operations

stActWr,

stCharDelay

--Write delay for operations

--stWait

--Idle state

);

--Write control state machine

type wstate is (

stRW, --set up RS and RW

stEnable, --set up E

stIdle --Write data on DB(0)-DB(7)

);

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

-- Signal Declarations and Constants

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

--These constants are used to initialize the LCD pannel.

--FunctionSet:

--Bit 0 and 1 are arbitrary

Page 126: Memoria Main

126

--Bit 2: Displays font type(0=5x8, 1=5x11)

--Bit 3: Numbers of display lines (0=1, 1=2)

--Bit 4: Data length (0=4 bit, 1=8 bit)

--Bit 5-7 are set

--DisplayCtrlSet:

--Bit 0: Blinking cursor control (0=off, 1=on)

--Bit 1: Cursor (0=off, 1=on)

--Bit 2: Display (0=off, 1=on)

--Bit 3-7 are set

--DisplayClear:

--Bit 1-7 are set

signal clkCount:std_logic_vector(5 downto 0);

signal activateW:std_logic:= '0';

--Activate Write sequence

signal count:std_logic_vector (16 downto 0):= "00000000000000000";

--15 bit count variable for timing delays

signal delayOK:std_logic:= '0';

--High when count has reached the right delay time

signal OneUSClk:std_logic;

--Signal is treated as a 1 MHz clock

signal stCur:mstate:= stPowerOn_Delay;

--LCD control state machine

signal stNext:mstate;

signal stCurW:wstate:= stIdle;

--Write control state machine

signal stNextW:wstate;

signal writeDone:std_logic:= '0';

--Command set finish

signal entrada1sig : std_logic_vector(9 downto 0);

signal entrada2sig : std_logic_vector(9 downto 0);

type LCD_CMDS_T is array(integer range 0 to 52) of std_logic_vector(9 downto 0);

signal LCD_CMDS : LCD_CMDS_T := ( 0 => "00"&X"3C",

--Function Set

1 => "00"&X"0C",

--Display ON, Cursor OFF, Blink OFF

2 => "00"&X"01",

--Clear Display

3 => "00"&X"02",

--return home

4 => "10"&X"43", --C

5 => "10"&X"6F", --o

6 => "10"&X"6E", --n

7 => "10"&X"74", --t

8 => "10"&X"61", --a

9 => "10"&X"64", --d

10 => "10"&X"6F", --o

11 => "10"&X"72", --r

12 => "10"&X"3A", --:

13 => "10"&X"20", -- Space

14 => "10"&X"18", -- Shifts left

15 => "10"&X"18", -- Shifts left

16 => "10"&X"18", -- Shifts left

17 => "10"&X"18", -- Shifts left

18 => "10"&X"18", -- Shifts left

19 => "10"&X"18", -- Shifts left

20 => "10"&X"18", -- Shifts left

21 => "10"&X"18", -- Shifts left

22 => "10"&X"18", -- Shifts left

23 => "10"&X"18", -- Shifts left

24 => "10"&X"18", -- Shifts left

25 => "10"&X"18", -- Shifts left

26 => "10"&X"18", -- Shifts left

27 => "10"&X"18", -- Shifts left

28 => "10"&X"18", -- Shifts left

29 => "10"&X"18", -- Shifts left

30 => "10"&X"18", -- Shifts left

31 => "10"&X"18", -- Shifts left

32 => "10"&X"18", -- Shifts left

33 => "10"&X"18", -- Shifts left

34 => "10"&X"18", -- Shifts left

35 => "10"&X"18", -- Shifts left

36 => "10"&X"18", -- Shifts left

37 => "10"&X"18", -- Shifts left

Page 127: Memoria Main

127

38 => "10"&X"18", -- Shifts left

39 => "10"&X"18", -- Shifts left

40 => "10"&X"18", -- Shifts left

41 => "10"&X"18", -- Shifts left

42 => "10"&X"18", -- Shifts left

43 => "10"&X"18", -- Shifts left

44 => "10"&X"20", --entrada5sig

45 => "10"&X"20", --entrada6sig

46 => "10"&X"3A", --:

47 => "10"&X"20", --entrada3sig

48 => "10"&X"20", --entrada4sig

49 => "10"&X"3A", --:

50 => "10"&X"72", --entrada1sig

51 => "10"&X"72", --entrada2sig

52 => "01"&X"18"); -- Shifts left

signal lcd_cmd_ptr : integer range 0 to LCD_CMDS'HIGH + 1 := 0;

begin

process

begin

LCD_CMDS(44) <= entrada5;

LCD_CMDS(45) <= entrada6;

LCD_CMDS(47) <= entrada3;

LCD_CMDS(48) <= entrada4;

LCD_CMDS(50) <= entrada1;

LCD_CMDS(51) <= entrada2;

end process;

-- This process counts to 50, and then resets. It is used to divide the clock signal time.

process (CLK, oneUSClk)

begin

if (CLK = '1' and CLK'event) then

clkCount <= clkCount + 1;

end if;

end process;

-- This makes oneUSClock peak once every 1 microsecond

oneUSClk <= clkCount(5);

-- This process incriments the count variable unless delayOK = 1.

process (oneUSClk, delayOK)

begin

if (oneUSClk = '1' and oneUSClk'event) then

if delayOK = '1' then

count <= "00000000000000000";

else

count <= count + 1;

end if;

end if;

end process;

--This goes high when all commands have been run

writeDone <= '1' when (lcd_cmd_ptr = LCD_CMDS'HIGH)

else '0';

--rdone <= '1' when stCur = stWait else '0';

--Increments the pointer so the statemachine goes through the commands

process (lcd_cmd_ptr, oneUSClk)

begin

if (oneUSClk = '1' and oneUSClk'event) then

if ((stNext = stInitDne or stNext = stDisplayCtrlSet or stNext =

stDisplayClear) and writeDone = '0') then

lcd_cmd_ptr <= lcd_cmd_ptr + 1;

elsif stCur = stPowerOn_Delay or stNext = stPowerOn_Delay then

lcd_cmd_ptr <= 0;

else

lcd_cmd_ptr <= lcd_cmd_ptr;

end if;

end if;

end process;

Page 128: Memoria Main

128

-- Determines when count has gotten to the right number, depending on the state.

delayOK <= '1' when ((stCur = stPowerOn_Delay and count = "00100111001010010") or

--20050

(stCur = stFunctionSet_Delay and count = "00000000000110010") or --50

(stCur = stDisplayCtrlSet_Delay and count = "00000000000110010") or --50

(stCur = stDisplayClear_Delay and count = "00000011001000000") or --1600

(stCur = stCharDelay and count = "00000000000011111"))

--Max Delay for character writes and shifts

--(stCur = stCharDelay and count = "00000000000100101"))

--37 This is proper delay between writes to ram.

else '0';

-- This process runs the LCD status state machine

process (oneUSClk, rst)

begin

if oneUSClk = '1' and oneUSClk'Event then

if rst = '1' then

stCur <= stPowerOn_Delay;

else

stCur <= stNext;

end if;

end if;

end process;

-- This process generates the sequence of outputs needed to initialize and write to the LCD

screen

process (stCur, delayOK, writeDone, lcd_cmd_ptr)

begin

case stCur is

-- Delays the state machine for 20ms which is needed for proper startup.

when stPowerOn_Delay =>

if delayOK = '1' then

stNext <= stFunctionSet;

else

stNext <= stPowerOn_Delay;

end if;

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '0';

-- This issuse the function set to the LCD as follows

-- 8 bit data length, 2 lines, font is 5x8.

when stFunctionSet =>

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '1';

stNext <= stFunctionSet_Delay;

--Gives the proper delay of 37us between the function set and

--the display control set.

when stFunctionSet_Delay =>

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '0';

if delayOK = '1' then

stNext <= stDisplayCtrlSet;

else

stNext <= stFunctionSet_Delay;

end if;

--Issuse the display control set as follows

--Display ON, Cursor OFF, Blinking Cursor OFF.

when stDisplayCtrlSet =>

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '1';

stNext <= stDisplayCtrlSet_Delay;

Page 129: Memoria Main

129

--Gives the proper delay of 37us between the display control set

--and the Display Clear command.

when stDisplayCtrlSet_Delay =>

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '0';

if delayOK = '1' then

stNext <= stDisplayClear;

else

stNext <= stDisplayCtrlSet_Delay;

end if;

--Issues the display clear command.

when stDisplayClear =>

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '1';

stNext <= stDisplayClear_Delay;

--Gives the proper delay of 1.52ms between the clear command

--and the state where you are clear to do normal operations.

when stDisplayClear_Delay =>

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '0';

if delayOK = '1' then

stNext <= stInitDne;

else

stNext <= stDisplayClear_Delay;

end if;

--State for normal operations for displaying characters, changing the

--Cursor position etc.

when stInitDne =>

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '0';

stNext <= stActWr;

when stActWr =>

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '1';

stNext <= stCharDelay;

--Provides a max delay between instructions.

when stCharDelay =>

RS <= LCD_CMDS(lcd_cmd_ptr)(9);

RW <= LCD_CMDS(lcd_cmd_ptr)(8);

DB <= LCD_CMDS(lcd_cmd_ptr)(7 downto 0);

activateW <= '0';

if delayOK = '1' then

stNext <= stInitDne;

else

stNext <= stCharDelay;

end if;

end case;

end process;

--This process runs the write state machine

process (oneUSClk, rst)

begin

if oneUSClk = '1' and oneUSClk'Event then

if rst = '1' then

stCurW <= stIdle;

else

stCurW <= stNextW;

end if;

end if;

end process;

Page 130: Memoria Main

130

--This genearates the sequence of outputs needed to write to the LCD screen

process (stCurW, activateW)

begin

case stCurW is

--This sends the address across the bus telling the DIO5 that we are

--writing to the LCD, in this configuration the adr_lcd(2) controls the

--enable pin on the LCD

when stRw =>

OE <= '0';

CS <= '0';

ADR2 <= '1';

ADR1 <= '0';

stNextW <= stEnable;

--This adds another clock onto the wait to make sure data is stable on

--the bus before enable goes low. The lcd has an active falling edge

--and will write on the fall of enable

when stEnable =>

OE <= '0';

CS <= '0';

ADR2 <= '0';

ADR1 <= '0';

stNextW <= stIdle;

--Waiting for the write command from the instuction state machine

when stIdle =>

ADR2 <= '0';

ADR1 <= '0';

CS <= '1';

OE <= '1';

if activateW = '1' then

stNextW <= stRw;

else

stNextW <= stIdle;

end if;

end case;

end process;

--LCD_CMDS(lcd_cmd_ptr)(50)<= entrada1;

--LCD_CMDS(lcd_cmd_ptr)(51)<= entrada2;

end Behavioral;

8.1.5. Control.

8.1.5.1. Máquina de estados.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity Maquina_Estados is

Port (

CLK : IN STD_LOGIC;

CLK2 : IN STD_LOGIC;

SETE : IN STD_LOGIC;

MODE : IN STD_LOGIC;

Page 131: Memoria Main

131

CD : IN STD_LOGIC;

CE : IN STD_LOGIC;

UD_L : IN STD_LOGIC;

HT : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

HU : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MT : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MU : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

ST : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

SU : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)

--TC24 : OUT STD_LOGIC

);

end Maquina_Estados;

architecture Behavioral of Maquina_Estados is

COMPONENT module60 IS

PORT

(CD,CLK,CE, UD_L : IN std_logic;

TC60 : OUT std_logic;

TENS : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);

UNIS : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)

);

END COMPONENT;

COMPONENT Contador24 IS

PORT

(CD,clock,CE, dir : IN std_logic;

TENS : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);

UNIS : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)

);

END COMPONENT;

COMPONENT two_bit_mux IS

PORT (

s : IN STD_LOGIC;

a,b : IN STD_LOGIC;

z : OUT STD_LOGIC

);

END COMPONENT;

COMPONENT Parpadeo is

PORT (

CLK : IN STD_LOGIC;

estado : IN STD_LOGIC_VECTOR(1 DOWNTO 0);

HTin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

HUin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

MTin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

MUin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

STin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

SUin : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

HTout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

HUout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MTout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MUout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

STout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

SUout : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)

--TC24 : OUT STD_LOGIC

);

END COMPONENT;

SIGNAL present_state : std_logic_vector(1 downto 0) := "00";

SIGNAL future_state : std_logic_vector(1 downto 0) := "00";

--SIGNAL estados2 : std_logic_vector(2 downto 0):= "000";

--SIGNAL Control : std_logic_vector(3 downto 0):= "0000";

--MODE_CONTROL

--SIGNAL MODE_CONTROL : std_logic;

SIGNAL TC60segsig : std_logic;

SIGNAL TC60minsig : std_logic;

SIGNAL CLKsig : std_logic;

SIGNAL CEH : std_logic:= '0';

SIGNAL CEM : std_logic:= '0';

Page 132: Memoria Main

132

SIGNAL CES : std_logic:= '0';

SIGNAL MCEH : std_logic:= '0';

SIGNAL MCEM : std_logic:= '0';

SIGNAL MCES : std_logic:= '0';

SIGNAL MSel : std_logic:= '0';

SIGNAL HTsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

SIGNAL HUsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

SIGNAL MTsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

SIGNAL MUsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

SIGNAL STsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

SIGNAL SUsig : STD_LOGIC_VECTOR(3 DOWNTO 0);

--SIGNAL TC60minsig : std_logic;

begin

Segun1: module60

PORT MAP(

CD => CD,

CLK => CLKsig,

CE => CES,

UD_L => UD_L,

TC60 => TC60segsig,

TENS => STsig,

UNIS => SUsig

);

Minutos1: module60

PORT MAP(

CD => CD,

CLK => CLKsig,

CE => CEM,

UD_L => UD_L,

TC60 => TC60minsig,

TENS => MTsig,

UNIS => MUsig

);

Horas: Contador24

PORT MAP(

CD => CD,

clock =>CLKsig,

CE => CEH,

dir => UD_L,

TENS => HTsig,

UNIS => HUsig

);

MUX2_1 : two_bit_mux

PORT MAP (

-- from component name => to signal or port name

s => MSel,

a => CLK,

b => CLK,

z => CLKsig

);

MUX2_2 : two_bit_mux

PORT MAP (

-- from component name => to signal or port name

s => MSel,

a => TC60minsig,

b => MCEH,

z => CEH

);

MUX2_3 : two_bit_mux

PORT MAP (

-- from component name => to signal or port name

s => MSel,

a => TC60segsig,

b => MCEM,

z => CEM

);

Page 133: Memoria Main

133

MUX2_4 : two_bit_mux

PORT MAP (

-- from component name => to signal or port name

s => MSel,

a => CE,

b => MCES,

z => CES

);

Parpadea : Parpadeo

PORT MAP (

CLK =>CLK2,-- : IN STD_LOGIC;

estado =>present_state,-- : IN STD_LOGIC_VECTOR(1 DOWNTO 0);

HTin =>HTsig,-- : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

HUin =>HUsig,-- : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

MTin =>MTsig,-- : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

MUin =>MUsig,-- : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

STin =>STsig,-- : IN STD_LOGIC_VECTOR(3 DOWNTO 0);

SUin =>SUsig,-- : IN STD_LOGIC_VECTOR(3 DOWNTO 0)

HTout =>HT,-- : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

HUout =>HU,-- : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MTout =>MT,-- : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MUout =>MU,-- : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

STout =>ST,-- : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

SUout =>SU-- : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)

);

state_register: PROCESS (CLK)

BEGIN

IF (CLK='1' AND CLK'event) THEN

present_state <= future_state;

END IF;

END PROCESS state_register;

Stateproces : PROCESS (SETE,present_state)

BEGIN

IF (SETE ='1') THEN

future_state<=present_state+1;

END IF;

END PROCESS Stateproces;

Maquina: PROCESS (present_state)

BEGIN

CASE present_state IS

WHEN "00" => MCEH <= '0';

MCEM <= '0';

MCES <= '0';

MSel <= '0';

WHEN "01" => MCEH <= '0';

MCEM <= '0';

MCES <= MODE;

MSel <= '1';

WHEN "10" => MCEH <= '0';

MCEM <= MODE;

MCES <= '0';

MSel <= '1';

WHEN OTHERS => MCEH <= MODE;

Page 134: Memoria Main

134

MCEM <= '0';

MCES <= '0';

MSel <= '1';

END CASE;

END PROCESS Maquina;

end Behavioral;

8.1.5.2. TestBench para simulación (Máquina estados).

LIBRARY ieee;

USE ieee.std_logic_1164.ALL;

USE ieee.std_logic_unsigned.all;

USE ieee.numeric_std.ALL;

ENTITY Simest IS

END Simest;

ARCHITECTURE behavior OF Simest IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT Maquina_Estados

PORT(

CLK : IN std_logic;

CLK2 : IN std_logic;

SETE : IN std_logic;

MODE : IN std_logic;

CD : IN std_logic;

CE : IN std_logic;

UD_L : IN std_logic;

estado : OUT std_logic_vector(1 downto 0);

HT : OUT std_logic_vector(3 downto 0);

HU : OUT std_logic_vector(3 downto 0);

MT : OUT std_logic_vector(3 downto 0);

MU : OUT std_logic_vector(3 downto 0);

ST : OUT std_logic_vector(3 downto 0);

SU : OUT std_logic_vector(3 downto 0)

);

END COMPONENT;

--Inputs

signal CLK : std_logic := '0';

signal CLK2 : std_logic := '0';

signal SETE : std_logic := '0';

signal MODE : std_logic := '0';

signal CD : std_logic := '0';

signal CE : std_logic := '1';

signal UD_L : std_logic := '1';

--Outputs

signal estado : std_logic_vector(1 downto 0);

signal HT : std_logic_vector(3 downto 0);

signal HU : std_logic_vector(3 downto 0);

signal MT : std_logic_vector(3 downto 0);

signal MU : std_logic_vector(3 downto 0);

signal ST : std_logic_vector(3 downto 0);

signal SU : std_logic_vector(3 downto 0);

-- Clock period definitions

constant CLK_period : time := 20 ns;

constant CLK2_period : time := 5 ns;

Page 135: Memoria Main

135

BEGIN

-- Instantiate the Unit Under Test (UUT)

uut: Maquina_Estados PORT MAP (

CLK => CLK,

CLK2 => CLK2,

SETE => SETE,

MODE => MODE,

CD => CD,

CE => CE,

UD_L => UD_L,

estado => estado,

HT => HT,

HU => HU,

MT => MT,

MU => MU,

ST => ST,

SU => SU

);

-- Clock process definitions

CLK_process :process

begin

CLK <= '0';

wait for CLK_period/2;

CLK <= '1';

wait for CLK_period/2;

end process;

CLK2_process :process

begin

CLK2 <= '0';

wait for CLK2_period/2;

CLK2 <= '1';

wait for CLK2_period/2;

end process;

-- Stimulus process

stim_proc: process

begin

-- hold reset state for 100 ms.

--wait for 100 ns;

SETE <='1';

MODE <='0';

wait for 10 ns;

SETE <='0';

MODE <='0';

wait for 10 ns;

wait for CLK_period*20;

SETE <='1';

MODE <='0';

wait for 10 ns;

SETE <='0';

MODE <='1';

wait for 100 ns;

MODE <='0';

wait for 100 ns;

MODE <='1';

wait for 100 ns;

MODE <='0';

wait for 100 ns;

MODE <='1';

wait for 100 ns;

MODE <='0';

wait for 100 ns;

Page 136: Memoria Main

136

wait for CLK_period*10;

-- insert stimulus here

wait;

end process;

END;

8.1.6. Archivo top de todo el sistema.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating

---- any Xilinx primitives in this code.

--library UNISIM;

--use UNISIM.VComponents.all;

entity Segundero is

PORT

(CD,CLK,CE, UD_L : IN std_logic;

DB:out std_logic_vector(7 downto 0); --DB( 7 through 0)

RS:out std_logic; --WE

RW:out std_logic; --ADR(0)

ADR1:out std_logic; --ADR(1)

ADR2:out std_logic; --ADR(2)

rdone: out std_logic;

--WriteDone output to work with DI05 test

CS:out std_logic; --CSC

OE:out std_logic; --OE

--Control_50Meg : OUT std_logic;

Control_10Meg : OUT std_logic;

Control_1000 : OUT std_logic;

Control_10 : OUT std_logic;

Control_1 : OUT std_logic;

SW : IN std_logic;

SW2 : IN std_logic;

SETE : IN std_logic;

MODE : IN std_logic;

TC60 : OUT std_logic;

TENS : OUT STD_LOGIC_VECTOR (3 DOWNTO 0);

UNIS : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)

);

end Segundero;

architecture Behavioral of Segundero is

COMPONENT DCMclock

PORT(

CLKIN_IN : IN std_logic;

RST_IN : IN std_logic;

CLKDV_OUT : OUT std_logic;

CLKFX_OUT : OUT std_logic;

CLKIN_IBUFG_OUT : OUT std_logic;

CLK0_OUT : OUT std_logic;

LOCKED_OUT : OUT std_logic

);

END COMPONENT;

COMPONENT freq_divider_top IS

PORT

(CD,CLK,CE : IN std_logic;

Page 137: Memoria Main

137

CLK_1000Hz : OUT std_logic

CLK_10Hz : OUT std_logic;

CLK_1Hz : OUT std_logic

);

END COMPONENT;

COMPONENT Maquina_Estados is

Port (

CLK : IN STD_LOGIC;

CLK2 : IN STD_LOGIC;

SETE : IN STD_LOGIC;

MODE : IN STD_LOGIC;

CD : IN STD_LOGIC;

CE : IN STD_LOGIC;

UD_L : IN STD_LOGIC;

HT : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

HU : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MT : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MU : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

ST : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

SU : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)

--TC24 : OUT STD_LOGIC

);

end COMPONENT;

COMPONENT lcd IS

Port ( DB:out std_logic_vector(7 downto 0); --DB( 7 through 0)

RS:out std_logic; --WE

RW:out std_logic; --ADR(0)

CLK:in std_logic; --GCLK2

ADR1:out std_logic; --ADR(1)

ADR2:out std_logic; --ADR(2)

entrada1 : in std_logic_vector(9 downto 0);

entrada2 : in std_logic_vector(9 downto 0);

entrada3 : in std_logic_vector(9 downto 0);

entrada4 : in std_logic_vector(9 downto 0);

entrada5 : in std_logic_vector(9 downto 0);

entrada6 : in std_logic_vector(9 downto 0);

CS:out std_logic; --CSC

OE:out std_logic; --OE

rst:in std_logic; --BTN

rdone: out std_logic);

--WriteDone output to work with DI05 test

END COMPONENT;

SIGNAL LDR1sig : std_logic_vector(9 downto 0);

SIGNAL LDR2sig : std_logic_vector(9 downto 0);

SIGNAL LDR3sig : std_logic_vector(9 downto 0);

SIGNAL LDR4sig : std_logic_vector(9 downto 0);

SIGNAL LDR5sig : std_logic_vector(9 downto 0);

SIGNAL LDR6sig : std_logic_vector(9 downto 0);

COMPONENT Prub3

PORT(

Count : IN std_logic_vector(3 downto 0);

--LDR1 : OUT std_logic_vector(9 downto 0);

LDR1 : OUT std_logic_vector(9 downto 0)

-- LCD_DB : INOUT std_logic_vector(7 downto 0);

-- LCD_E : OUT std_logic_vector(0 downto 0);

-- LCD_RS : OUT std_logic_vector(0 downto 0);

-- LCD_RW : OUT std_logic_vector(0 downto 0)

);

END COMPONENT;

SIGNAL CLK_1hz : std_logic;

SIGNAL CLKDV_OUT : std_logic;

SIGNAL CLKIN_IBUFG_OUT : std_logic;

Page 138: Memoria Main

138

SIGNAL CLK0_OUT : std_logic;

SIGNAL LOCKED_OUT : std_logic;

--SIGNAL CLK_50 : std_logic;

SIGNAL CLK_1hez : std_logic;

SIGNAL CLK_10hez : std_logic;

SIGNAL CLK_1000hez : std_logic;

SIGNAL CLK_10000hez : std_logic;

SIGNAL TENS3sig : std_logic_vector(3 downto 0);

SIGNAL UNIS3sig : std_logic_vector(3 downto 0);

SIGNAL TENS2sig : std_logic_vector(3 downto 0);

SIGNAL UNIS2sig : std_logic_vector(3 downto 0);

SIGNAL TENSsig : std_logic_vector(3 downto 0);

SIGNAL UNISsig : std_logic_vector(3 downto 0);

SIGNAL CLKsig : std_logic;

SIGNAL Veltemp : std_logic;

--SIGNAL LDR1sig : std_logic;

--SIGNAL LDR2sig : std_logic;

begin

Segun2: DCMclock

PORT MAP(

CLKIN_IN =>CLK ,

RST_IN =>CD ,

CLKDV_OUT =>CLK_10000hez ,

CLKFX_OUT =>CLKDV_OUT ,

CLKIN_IBUFG_OUT =>CLKIN_IBUFG_OUT ,

CLK0_OUT =>CLK0_OUT ,

LOCKED_OUT => LOCKED_OUT

);

Segun3: freq_divider_top

PORT MAP(

CD => CD,

CLK => CLK_10000hez,

CE => CE,

CLK_1Hz => CLK_1hez,

CLK_10Hz => CLK_10hez,

CLK_1000Hz => CLK_1000hez

);

MAC_EST: Maquina_Estados

PORT MAP (

CLK =>CLK_1hez,-- : IN STD_LOGIC;

CLK2 =>CLK_10hez,-- : IN STD_LOGIC;

SETE =>SETE,-- : IN STD_LOGIC;

MODE =>MODE,-- : IN STD_LOGIC;

CD =>CD,--: IN STD_LOGIC;

CE =>CE,--: IN STD_LOGIC;

UD_L =>UD_L,-- : IN STD_LOGIC;

HT =>TENS3sig,--: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

HU =>UNIS3sig,--: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MT =>TENS2sig,--: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

MU =>UNIS2sig,--: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

Page 139: Memoria Main

139

ST =>TENSsig,--: OUT STD_LOGIC_VECTOR(3 DOWNTO 0);

SU =>UNISsig--: OUT STD_LOGIC_VECTOR(3 DOWNTO 0)

--TC24 : OUT STD_LOGIC

);

Pantalla: lcd

PORT MAP ( DB=>DB,--:out std_logic_vector(7 downto 0); --DB( 7 through 0)

RS=>RS,--:out std_logic; --WE

RW=>RW,--:out std_logic; --ADR(0)

CLK=>CLKIN_IBUFG_OUT,--:in std_logic; --GCLK2

ADR1=>ADR1,--:out std_logic; --ADR(1)

ADR2=>ADR2,--:out std_logic; --ADR(2)

entrada1=>LDR1sig, --: in std_logic_vector(9 downto 0)

entrada2=>LDR2sig, --: in std_logic_vector(9 downto 0)

entrada3=>LDR3sig, --: in std_logic_vector(9 downto 0)

entrada4=>LDR4sig, --: in std_logic_vector(9 downto 0)

entrada5=>LDR5sig, --: in std_logic_vector(9 downto 0)

entrada6=>LDR6sig, --: in std_logic_vector(9 downto 0)

CS=>CS,--:out std_logic; --CSC

OE=>OE,--:out std_logic; --OE

rst=>CLK_10hez,--:in std_logic; --BTN

rdone=>rdone--: out std_logic);--WriteDone output to work with DI05 test

);

Convnum1: Prub3

PORT MAP (

Count => TENSsig,

LDR1 => LDR1sig

--LDR2 => LDR2sig

-- LCD_DB => LCD_DB,

-- LCD_E => LCD_E,

-- LCD_RS => LCD_RS,

-- LCD_RW => LCD_RW

);

Convnum2: Prub3

PORT MAP (

Count => UNISsig,

--LDR1 => LDR1sig,

LDR1 => LDR2sig

-- LCD_DB => LCD_DB,

-- LCD_E => LCD_E,

-- LCD_RS => LCD_RS,

-- LCD_RW => LCD_RW

);

Convnum3: Prub3

PORT MAP (

Count => TENS2sig,

--LDR1 => LDR1sig,

LDR1 => LDR3sig

-- LCD_DB => LCD_DB,

-- LCD_E => LCD_E,

-- LCD_RS => LCD_RS,

-- LCD_RW => LCD_RW

);

Convnum4: Prub3

PORT MAP (

Count => UNIS2sig,

--LDR1 => LDR1sig,

LDR1 => LDR4sig

-- LCD_DB => LCD_DB,

-- LCD_E => LCD_E,

-- LCD_RS => LCD_RS,

-- LCD_RW => LCD_RW

);

Convnum5: Prub3

PORT MAP (

Count => TENS3sig,

--LDR1 => LDR1sig,

LDR1 => LDR5sig

Page 140: Memoria Main

140

-- LCD_DB => LCD_DB,

-- LCD_E => LCD_E,

-- LCD_RS => LCD_RS,

-- LCD_RW => LCD_RW

);

Convnum6: Prub3

PORT MAP (

Count => UNIS3sig,

--LDR1 => LDR1sig,

LDR1 => LDR6sig

-- LCD_DB => LCD_DB,

-- LCD_E => LCD_E,

-- LCD_RS => LCD_RS,

-- LCD_RW => LCD_RW

);

--Salidas de control!!!

--CLK_50 <= CLK;

--Control_50Meg <= CLK_50;

Control_10Meg <= CLK_10000hez;

Control_1000 <= CLK_1000hez;

Control_10 <= CLK_10hez;

Control_1 <= CLK_1hez;

--UNIS <= UNISsig;

--TENS <= TENSsig;

-- Puls_CLK: PROCESS (SW2,CLK)

-- BEGIN

-- IF SW2 = '1' THEN

-- Veltemp <= CLK_1hez;

-- ELSE

-- Veltemp <= CLK_10hez;

-- END IF;

-- END PROCESS Puls_CLK;

--Veltemp <= CLK_1hez WHEN (SW2 = '1') ELSE CLK_10hez;

UNIS <= UNISsig WHEN (SW = '1') ELSE UNIS2sig;

TENS <= TENSsig WHEN (SW = '1') ELSE TENS2sig;

--TC60 <= TC60sig;

--CLKsig<=CLK;

end Behavioral;

Page 141: Memoria Main

141

8.1.7. Archivo .UCF.

##############################################################################

NET "CLK" LOC = "E12";

NET "CLK" TNM_NET = "CLK";

TIMESPEC TS_CLK = PERIOD "CLK" 20 ns HIGH 50 %;

TIMEGRP "CLK" OFFSET = IN 20 ns VALID 20 ns BEFORE "CLK" RISING;

##############################################################################

# Discrete Indicators (LED)

##############################################################################

NET "UNIS<0>" LOC = "R20" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "UNIS<1>" LOC = "T19" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "UNIS<2>" LOC = "U20" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "UNIS<3>" LOC = "U19" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "TENS<0>" LOC = "V19" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "TENS<1>" LOC = "V20" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "TENS<2>" LOC = "Y22" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "TENS<3>" LOC = "W21" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

##############################################################################

# Character Display (LCD)

##############################################################################

NET "DB<0>" LOC = "Y13" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "DB<1>" LOC = "AB18" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "DB<2>" LOC = "AB17" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "DB<3>" LOC = "AB12" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "DB<4>" LOC = "AA12" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "DB<5>" LOC = "Y16" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "DB<6>" LOC = "AB16" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "DB<7>" LOC = "Y15" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "ADR2" LOC = "AB4" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "RS" LOC = "Y14" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

NET "RW" LOC = "W13" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;

##############################################################################

# Mechanical Switches (SW)

##############################################################################

NET "CD" LOC = "V8" | IOSTANDARD = LVCMOS33 ;

NET "CE" LOC = "U10" | IOSTANDARD = LVCMOS33 ;

NET "UD_L" LOC = "U8" | IOSTANDARD = LVCMOS33 ;

##NET "SETE" LOC = "T9" | IOSTANDARD = LVCMOS33 ;

##############################################################################

# Directional Push-Buttons (BTN)

##############################################################################

NET "MODE" LOC = "T16" | IOSTANDARD = LVCMOS33 | PULLDOWN ;

##NET "BTN_NORTH" LOC = "T14" | IOSTANDARD = LVCMOS33 | PULLDOWN ;

NET "SETE" LOC = "T15" | IOSTANDARD = LVCMOS33 | PULLDOWN ;

NET "SW" LOC = "U15" | IOSTANDARD = LVCMOS33 | PULLDOWN ;

NET "SETE" CLOCK_DEDICATED_ROUTE = FALSE;

NET "MODE" CLOCK_DEDICATED_ROUTE = FALSE;