Professional Documents
Culture Documents
Introduccin al diseo de sistemas digitales reconfigurables en FPGA con VHDL y la tarjeta Spartan-3AN de Xilinx Ingeniera Tcnica de Telecomunicaciones, especialidad Sistemas de Telecomunicaciones. Sergio Garca Lpez Francesc Josep Snchez y Robert 29 de junio de 2010
TITULACIN:
Titulo: Introduccin al diseo de sistemas digitales reconfigurables en FPGA con VHDL y la tarjeta Spartan-3AN de Xilinx Autor: Sergio Garca Lpez Director: Francesc Josep Snchez y Robert Fecha: 29 Junio de 2010
Resumen
Este trabajo pretende ser una gua para conocer el funcionamiento de la FPGA Spartan-3AN de Xilinx y su software. En el captulo 2 se explicar cmo crear un proyecto simple, compilarlo, simularlo y grabarlo en la placa para ver su funcionamiento de forma visual. En el captulo 3 se elaborar un doble contador sncrono de 4 bits. Uno de los contadores vendr gestionado por un divisor de frecuencia creado manualmente y el otro por la herramienta de gestin 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 propagacin. La ltima parte de la explicacin ser la creacin de una mquina de estados para gobernar un conjunto de componentes compuestos. Los datos provenientes de estos componentes sern convertidos al formato correcto para ser visualizados mediante la pantalla LCD, que es un perifrico de la Spartan-3AN. La explicacin de esta ltima parte vendr adscrita a la realizacin del proyecto de este documento, que ser la creacin de un reloj en tiempo real similar en prestaciones y funcionamiento al que se pueda llevar en la mueca.
Title: Introduction to digital systems design with VHDL FPGA reconfigurable card and Xilinx Spartan-3AN Author: Sergio Garca Lpez Director: Francesc Josep Snchez y Robert Date: 29 Junio de 2010
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.
Spartan-3AN Non-Volatile FPGA Starter Kit. ....................................................... 19 Arquitectura interna. ....................................................................................... 19 Lgica de bloques configurable o Configurable Logic Blocks (CLBs) . .......... 19 Entradas y salidas de los bloques o Input/Output Blocks (IOBs). ................ 20 RAM. ............................................................................................................. 20 Multiplicador de bloques. ............................................................................ 20 Control de Reloj o Digital Clock Manager (DCM). ........................................ 20
ISE Project Navigator. .......................................................................................... 21 Creacin de un proyecto. ................................................................................. 22 Escritura del cdigo.......................................................................................... 26 Asignacin de pines. ........................................................................................ 28 Editar el archivo .UCF de forma manual. ..................................................... 28 PlanAhead .................................................................................................... 29
Sntesis y Simulacin temporal de circuito. ......................................................... 32 TestBench para simulaciones en ModelSim. ................................................... 33 Cdigo TestBench ......................................................................................... 35 Simulacin temporal. ....................................................................................... 36 Grabado del cdigo. ............................................................................................ 37 Alimentacin y comunicacin con la placa. ..................................................... 37
2.6.2. 2.6.3.
2.6.4. Configuracin de los Jumpers a la hora de grabar un cdigo en la memoria de la Spartan-3AN................................................................................................................ 39 2.6.4.1. 2.6.5. 2.6.5.1. 2.6.5.2. 2.7. Master Internal SPI. ...................................................................................... 40 Grabar el cdigo. .............................................................................................. 41 Programar la memoria Flash y cargar la FPGA. ............................................ 41 Programas FPGA nicamente. ..................................................................... 42
RTL del Contador + DCM + Divisor de frecuencia. ....................................... 67 Simulacin funcional Contador + DCM + Divisor de frecuencia. ..................... 68 Sntesis y simulacin temporal Contador + DCM + Divisor de frecuencia. ..... 69
4.3.2.4. Medida real de las frecuencias a la salida de los Divisores y el componente DCM ..................................................................................................................... 78 4.4. 4.4.1. 4.4.1.1. 4.4.1.2. 4.4.1.3. 4.4.1.4. 4.4.2. 4.4.2.1. 4.4.2.2. Control horas, minutos y segundos. .................................................................... 80 Modulo 60. ....................................................................................................... 80 Comportamiento bloque Modulo 60. .......................................................... 80 Estructura interna Modulo 60. ..................................................................... 81 Cdigo Modulo 60 ........................................................................................ 82 Simulacin Modulo 60. ................................................................................ 82 Modulo de horas. ............................................................................................. 83 Codigo modulo horas. .................................................................................. 84 Simulacin modulo horas. ............................................................................ 84 8
Maquina de estados. ........................................................................................... 85 Esquema estados de la Maquina de estados................................................... 85 Cdigo del CASE de control.............................................................................. 86 Esquema conexiones Maquina Estados........................................................... 87 Cdigo Mquina estados. ................................................................................ 87 Simulacin Maquina estados. .......................................................................... 88 LCD ....................................................................................................................... 89 Comportamiento del cdigo. ........................................................................... 89 Modificacin del cdigo inicial. ....................................................................... 90 Proceso de adquisicin de datos a mostrar. ................................................ 91
4.6.2.1. 4.7. 4.7.1. 4.7.2. 4.7.3. 4.8. 4.8.1. 4.8.2. 4.8.3. 4.9. 4.9.1. 4.9.2. 4.9.3. 4.9.4. 4.9.4.1.
Convertidor de 4 bits a ASCII. .............................................................................. 92 Mtodo de conversin. .................................................................................... 92 Cdigo Convertidor. ......................................................................................... 93 Simulacin se la conversin. ............................................................................ 93 Parpadeo del nmero seleccionado. ................................................................... 94 Mtodo de funcionamiento del parpadeo de la cifra. .................................... 94 Cdigo parpadeo. ............................................................................................. 96 Simulacin parpadeo. ...................................................................................... 96 Esquema final completo. ..................................................................................... 97 Cdigo archivo top global. ............................................................................... 97 Esquema terico global. .................................................................................. 98 RTL del sistema completo. ............................................................................... 99 Comprobacin de la aplicacin ...................................................................... 100 UCF Aplicacin. ........................................................................................... 100
Control Flash. ..................................................................................................... 103 Control del LCD .................................................................................................. 103 VHDL Test Bench................................................................................................ 104 EPSC Pagina Electrnica digital y Sistema Electrnicos Digitales. ..................... 104
10
11
1. Introduccin
En este proyecto se pretende hacer una pequea gua para introducir al lector en la programacin de la Spartan-3AN. Se explicara el uso del software que proporciona el fabricante para escribir, simular, compilar y grabar el cdigo en la placa. La explicacin intentar seguir el proceso lgico que hara un inexperto en la materia, ofrecindole 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 bsicas del lenguaje VHDL, puesto que la finalidad del proyecto es que esta informacin pueda ser til para impartir clase en la escuela. La estructura del trabajo empieza desde un cdigo muy simple, que establece una asignacin directa entre entradas y salidas de la placa. A partir de este primer diseo se har una descripcin del programa Project Navigator para su familiarizacin. Se explicara como introducir un cdigo de forma correcta en la placa, como comprobar su funcionamiento mediante la simulacin en ModelSim, en sus diferente escalones de simulacin, y finalmente como asignar las entradas y salidas a ping fsicos 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 inters es realizar un cdigo dependiente de un reloj interno o externo, puesto que la mayora de tecnologa que nos rodea est plagada de procesos sncronos. En este nuevo diseo se implementara un contador sncrono 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 cdigo permitir la declaracin y el uso del reloj a la hora de simular diseos sncronos. En este punto de la narracin ya se dispondrn 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 filosofa 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 relacin de dependencia o sumisin unos de otros, a fin de ser capaces de transmitir una cierta informacin a un perifrico de la placa. 12
Para lograr este propsito, se diseara un reloj en tiempo real igual al que se puede llevar en la mueca, en el cual se podr elegir su mtodo de funcionamiento y puesta en hora. Este dispositivo ser la aplicacin, propiamente dicho, del proyecto y dar pie a la introduccin 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 podrn ser visualizados mediante la pantalla LCD de la placa. Esto evoca al ltimo bloque del condigo que ser la incorporacin de un perifrico al diseo. Al parecer del autor del proyecto, esto es todo lo necesario para programar la FPGA, y pese a que los bloques y los perifricos pueden ser tan complicados como la imaginacin de su creador, deja al lector con las instrucciones bsicas para este nivel de programacin, situndolo as en la antesala del siguiente nivel, que es la compilacin del cdigo utilizando el micro controlador.
13
2. Sistemas combinacionales.
Son aquellos cdigos en que las salidas dependen exclusivamente de las entradas y su respuesta es constante y deducible matemticamente.
X( n-1 ...0 )
Circuito Combinacional.
Y( m-1 ...0 )
Especificaciones
Simulaciones funcionales
Correcto
No correcto.
Correcto.
Flujo de diseo.
Correcto
No correcto.
Correcto.
Correcto
No correcto.
Correcto.
Prototipo de la aplicacin.
14
LDR[0]
4 Entradas 4 Salidas
2.2.1.2.
Cdigo de la aplicacin.
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;
Cdigo 1 Prub1.
15
-En la ventada sealada con el nmero 1 aparecen todas las bibliotecas utilizadas por el programa y el cdigo seleccionado para su simulacin. -La siguiente ventana contiene las seales activas para simular, en esta ventana se pueden aadir o eliminar las seales que se desee mostrar. -En la tercera muestra el seguimiento grafico de la simulacin. -Finalmente en la ltima ventana sealada con el numero 4, se podrn ver todas las incidencias en la simulacin y acceder al los archivos .DO que contendrn las directrices de la simulacin, siempre que no se implemente el TestBench desde el mismo programa de diseo.
16
2.2.2.1.
Dentro del archivo .DO se definen las seales que se utilizarn para las simulaciones, el periodo de reloj y el paso a paso en la simulacin. Este ltimo vendr dividido temporalmente segn los tiempos de espera definidos por el usuario y las condiciones para cada espera.
restart add wave SW add wave LDR force SW run 100 force SW run 100 force SW run 100 force SW run 100 force SW run 100 run 200 1011 0011 1100 1001 0101
Se reinician los registros. Se definen las variables a utilizar. Add wave nombre seal. Se fuerza un valor de entrada y se espera un tiempo prudencial de ejecucin para observar los resultados. Forc nombre entrada valor deseado Run Tiempo deseado
El archivo .DO se debe introducir en la raz de la carpeta que contenga el cdigo a simular. La forma de ejecutar el archivo es desde la ventana sealada con el nmero 4, dentro de la presentacin de la pgina principal del ModelSim. En esta ventana ( Figura 4 Ventana principal ModelSim. ) se puede introducir texto. La forma de introducir el comando de ejecucin es la siguiente: Do nombre_archivo.do Una vez hecho lo anterior aparecer una tabla de opciones, tras restaurar, en la ventana de representacin grafica aparecer la simulacin efectuada.
17
La simulacin funcional es correcta y como se puede observar en el cdigo y en las especificaciones de los leeds, stos son activos a nivel bajo. Es por esa razn que en el cdigo las salidas estn negadas, y en la simulacin las seales va a la inversa entradas respecto salidas.
18
Figura 6 Spartan-3AN.
La FPGA tiene prcticamente la misma conectividad que una placa base de un ordenador convencional a diferencia, claro, que es totalmente programable.
Contiene tablas de consulta flexibles o Look-Up Tables (LUTs) que implementan la lgica de los circuitos y configuran la estructura bsica de los flip-flops internos.
19
2.3.1.2.
Controla el flujo de datos entre los pines y la lgica interna del dispositivo, gestionan la prioridad de seales 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 nmeros 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 calibracin del reloj de entrada y diferentes operaciones sobre el mismo, como pueden ser multiplicaciones y divisiones de frecuencia o cambios de fase.
20
Estos elementos estn organizados como se muestra en la Figura 7 Arquitectura interna Spartan-3AN ( Spartan-3AN FPGA Family Data Sheet). en una doble disposicin de salidas que rodea el conjunto. Cada dispositivo tiene dos columnas de RAM a excepcin XC3S50AN que dispone nicamente de una. Los bloques de memoria estn 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 seales internas.
El programa que se utilizar para programar es ISE Project Navigator de Xilinx que proporciona la pagina web (http://www.xilinx.com/) en su versin ISE WebPACK edicin. La ventana principal muestra el aspecto siguiente:
21
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 diseo. En la parte media de la ventana a la izquierda presenta los archivos que estn cargados en el diseo, y en la parte derecha actualmente est cargado Design Summary, que muestra un resumen detallado de las configuraciones del diseo. Por ltimo, en la parte inferior presenta un gran espacio en blanco que est destinado a mostrar los posibles errores de programacin es sus diferentes etapas, ya sea de compilacin, en sus diferentes niveles, como de simulacin.
22
En esta ventana se definir el nombre del proyecto y la localizacin, en cuanto a la localizacin 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 atencin a 3 puntos, pero hay que tener en cuenta que es necesario conocer en qu placa se implementara el cdigo y las caractersticas de la misma a la hora de rellenar correctamente la totalidad de los campos de este formulario.
23
En el primer punto marcado en rojo en la (Figura 10 Paso 2 Creacin proyecto.) corresponde al los lenguajes de programacin que soporta la placa que se ha descrito en el resto del formulario. El segundo punto muestra los diferentes programas de simulacin 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 simulacin utilizado por la escuela en asignaturas como ED (Electrnica digital) o SED (Sistemas electrnicos digitales). Por ltimo el lenguaje utilizado para describir el funcionamiento del proyecto ser VHDL.
24
En el tercer paso se agruparan los dos siguientes saltos en la creacin, puesto que estas dos ventanas son muy similares. ( Figura 11 Paso 3 Creacin proyecto. ) La primera est destinada a aadir 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 explicacin se vern el resto. La ventana de la derecha sirve para aadir al proyecto un fichero ya existente en el ordenador y ser implementado junto al diseo. El ltimo paso es un resumen de lo seleccionado anteriormente y da pie a comenzar a redactar el cdigo.
25
En la parte derecha aparecer una ventana de texto que contendr las directivas bsicas de cualquier diseo, es en esta ventana en donde se introducir el primer cdigo. En este primer cdigo, como se ha comentado se hace una asignacin directa entre los selectores de entrada de la placa (SW) y los Leeds situados encima (LDR). Como se puede ver este primer cdigo est compuesto de la declaracin del componente con sus entradas y la arquitectura del mismo, en la cual solo consta la asignacin directa, que sera comparable a unir fsicamente los interruptores con los Leeds mediante un cable.
26
El siguiente paso es comprobar que el cdigo compila correctamente, para esto se utilizara el men desplegable situado en la ventana inferior a la que contiene la declaracin de archivos ( Figura 14 1er Cdigo paso 2. ).
Despus 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 pestaa sintetizar, emergern ms opciones, de la cuales cabe destacar por ahora View RTL, que muestra el esquema del componente.
El siguiente paso para grabar el diseo es asignar las entradas y salidas con los pines correspondientes de la placa. La pgina Web proporciona para descargar un archivo .UCF, que contiene toda la informacin de pines de la Spartan-3AN, nombrando cada pin de cada componente con la nomenclatura que viene inscrita fsicamente en la placa.
27
2.4.3.1.
El modelo de archivo UCF que contiene toda la informacin de la localizacin 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
################################################################# # Discrete Indicators (LED) # ################################################################# NET "LED<0>" LOC = "R20" NET "LED<1>" LOC = "T19" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
Este documento tendr que ser editado siempre que no se utilicen los mismos nombres para definir las entradas y salidas. Para el diseo se ha extrado la informacin de los componentes a utilizar, y tras ser editado queda de la forma siguiente.
"LDR[0]" LOC = R20; "LDR[1]" LOC = T19; "LDR[2]" LOC = U20; "LDR[3]" LOC = U19; "SW[0]" LOC = V8; "SW[1]" LOC = U10; "SW[2]" LOC = U8; "SW[3]" LOC = T9;
28
2.4.3.2.
PlanAhead
Otro mtodo para introducir las asignaciones de pines, es mediante la herramienta PlanAhead que nos proporciona Xilinx.
Esta aplicacin permite introducir uno a uno los nmeros de los puertos necesarios.
29
En el formulario nmero 1 se puede ver si el puerto es de entrada o salida, el nombre y la situacin. Es en este ltimo campo donde se introducir el nmero 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 cdigo. Para poder modificar alguna de ellas mediante el formulario nmero 1, sta tendr que estar seleccionada. Cuando se termine de rellenar todos los campos se tendr que grabar el proceso desde la misma aplicacin, cerrar la ventana y volver a sintetizar el cdigo. Un mtodo para comprobar que la asignacin ha sido correcta, es mediante Design Summary, que como se ha comentado al principio, da un amplio informe de todos los eventos del proyecto.
A partir de este punto ya se dispone de todo lo necesario para introducir el cdigo en la placa y hacerlo funcionar. Para esto se ejecutar toda la secuencia de sintetizado y compilacin.
30
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
31
2.5.
Cuando se ha definido el proyecto se ha elegido un programa de simulacin, este queda totalmente integrado en Xilinx, de modo que al pasar de uno a otro se enva toda la configuracin. Esto supone que a la hora de hacer simulaciones temporales el programa de simulacin tiene en cuenta los retardos propios de cada placa utilizada en el diseo. A la hora de realizar la simulacin es muy simple. El primer paso es pasar del mtodo implementacin a simulacin, esto se hace seleccionando la casilla situada encima de la ventana que contiene los archivos del programa.
Desde la nueva ventana que aparece, se ha de tener en cuenta bsicamente tres cosas a la hora de simular.
32
El primer punto es nivel de simulaciones que se quiere realizar, de los cuales se utilizaran 2. -Behavioral es el nivel de simulacin ms primario, slo tiene en cuenta la estructura del cdigo y su funcionamiento terico. Generalmente si el cdigo compila correctamente podr ser simulado. Este mtodo sirve para comprobar que el diseo cumple las especificaciones iniciales previstas. -Post-Route es el paso siguiente al mtodo anterior. En este mtodo s que se tiene en cuenta los retardos entre puertas. Es en este punto donde no slo es importante que el cdigo funcione a nivel terico, 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 simulacin, es elegir que cdigo se desea simular. En este primer diseo no es muy relevante porque slo 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 diseo, se dar cuenta que es mucho ms til simular un bloque por separado a la hora de extraer conclusiones. Por ltimo, el tercer punto marcado en rojo en la Figura 21 Simulacin paso 2., muestra el programa que actualmente esta seleccionado y junto a l, el mtodo de simulacin elegido. Haciendo doble clic sobre esta ltima opcin se accede al programa de simulacin. ModelSim Simulator es el programa por defecto que utiliza la EPSC (Escuela Politcnica Superior de Castelldefels) para simular, la versin Xilinx de este programa se puede descargar en el apartado de soporte de la pgina Web. Esta simulacin se realizara mediante TestBench, que es una herramienta mucho ms cmoda e inmediata de realizar simulaciones.
33
El primer paso es aadir 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 slo 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 simulacin esta seleccionada. Automticamente se abrir en la ventana de cdigo. Dentro del modo de simulacin este hace las funciones de archivo principal gobernando sobre los dems. Como se puede ver el propio programa te gua en la utilizacin del cdigo con comentarios en cada punto relevante del mismo. Otro aspecto interesante es que en la creacin del cdigo viene implementado un clock automticamente. Gracias a este factor, en cdigos dependientes de un reloj externo se podr hacer funcionar. Por la simplicidad de este primer diseo, las modificaciones del cdigo modelo de origen sern pocas, pero servirn para entender cmo funciona este archivo de simulacin. 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 introducirn los estados y las separaciones temporales nicamente en donde nos indica el cdigo mediante un comentario de ayuda (insert stimulus here). 34
2.5.1.1.
Cdigo TestBench
El cdigo 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;
-Se ha de aadir la informacin 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;
Tras realizar estas modificaciones se puede ejecutar la simulacin y ver como sta, si no se ha producido ningn error, aparece automticamente. Para ejecutar la simulacin se ha de hacer doble clic sobre el nombre del simulador seleccionado.
35
Si se realiza el proceso usando la opcin de Post-Route para simular el cdigo, se ver en la representacin grafica, haciendo el zoom necesario, los retardos entre las seales. Recordar que si no se ven las seales adecuadamente, un error muy comn es poner una base de tiempo muy pequea a simular o que las opciones de zoom de la ventana no sean las correctas.
Ms 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 razn es un parmetro a tener en cuenta a la hora de exigir cierta velocidad de computo a un proceso.
36
Figura 26 Conexiones.
37
El siguiente paso es hacer que el programa identifique la placa y establezca comunicacin con ella. Para conseguir este propsito se utilizara la opcin de deteccin automtica.
38
39
En esta configuracin, el mtodo de entrada a la memoria es Master Internal SPI (Serial Peripheral Interface). Quiere decir que un perifrico 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 perifrico el proceso ser el inverso que el de la carga del cdigo 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.
Las pautas de escritura en este modo son las siguientes: Solamente el perifrico de escritura principal gobierna la transmisin. 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 lnea Master In Slave Out (MISO). La transmisin es serializada, dura 8 ciclos de reloj y todos los datos transmitidos por el perifrico principal estn sincronizados.
40
Es en este perifrico externo donde permanece el cdigo cuando se elige la opcin de programa y grabar la memoria flash de la FPGA.
2.6.5.1.
Clicando con el botn secundario sobre el componente al cual se desea insertar el cdigo, aparece un men de opciones. En este apartado se seleccionara la primera opcin que har permanecer el cdigo en la placa, sobre reinicios y prdidas de energa, en el perifrico de memoria descrito anteriormente.
41
2.6.5.2.
De este modo se podrn hacer escrituras ms rpidas de cdigo para pruebas de funcionamiento puntuales.
42
La asignacin de las salidas viene regida por la condicin -> LDR <= NOT(SW); Esta condicin evoca el funcionamiento siguiente, ya que los Leeds son activos a nivel bajo.
43
3. Sistemas secuenciales.
Una vez comprendida la metodologa para llevar un cdigo desde el papel a la placa, el siguiente paso lgico es realizar un cdigo dependiente de un reloj interno, puesto que la mayora de sistemas electrnicos 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 tambin dependen del estado anterior o estado interno. La mayora de los sistemas secuenciales estn gobernados por seales de reloj. A stos se los denomina "sncronos" o "sincrnicos", a diferencia de los "asncronos" o "asincrnicos" que son aquellos que no son controlados por seales de reloj. Wikipedia.
X
Sistema combinacional.
Y
Sistema de memoria.
3.1. Metodologa para dividir la frecuencia de entrada y gestionar un contador binario sncrono de Modulo 11.
Se diseara 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 cdigo 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).
44
CD CE CLK
Contador
TC_out TC_out2 contador_out contador_out2
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" ;
3.1.1.1.
Especificaciones.
Se pretende obtener una salida de reloj a 1 MHz mediante este componente de la forma ms 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 condicin predefinida, nos proporcionar una salida de reloj a la frecuencia deseada.
Ejemplo.
Contador 1: 1 2 3 4 5 (Condicin) 1 2 3 4 5 (Condicin) Contador 2: 1 2
Condicin: 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.
45
Para realizar el divisor de frecuencias se utilizar el modelo de mquina de estados que se imparte en la escuela.
En cada iteracin se decide la configuracin del estado siguiente, y el estado presente pasa a ser el estado futuro de forma sncrona con cada golpe de reloj. En caso de que no se produzca un cambio de estado, la metodologa 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 cdigos que contengan estados de funcionamiento seguirn este modelo.
3.1.1.2.
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 iteracin.
Salida
CD CE CLK
freq_divider_10
TC_10
3.1.1.3.
Vistas las condiciones anteriores se pensar en un diagrama de estado que proporcione dicho funcionamiento.
TC10 = 1
While CE = 0
CE = 1 While CE = 0
0
TC10 = 0
CE = 1 While CE = 0
(N - 1)
TC10 = 1
1
TC10 = 0
CE = 1
2
TC10 = 0
While CE = 0
3
CE = 1
CE = 1
TC10 = 0
4
TC10 = 0
CE = 1
While CE = 0
47
3.1.1.4.
Se necesitan dos seales de longitud igual al nmero de bits necesario para representar el nmero por el cual queremos dividir la frecuencia de entrada.
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 divisin ha sido elegido para facilitar la posterior simulacin, 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 TC10 ); END freq_div_10; : : IN std_logic; OUT std_logic
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 ;
48
Se puede ver como en cada evento de reloj se actualiza el estado y el funcionamiento de la entrada CD anteriormente descrita. Tambin el comportamiento de la entrada CE, que es la que habilita el contador, y como esta implementada la condicin que fuerza la puesta a 0 del contador cuando llega al valor esperado. Este diseo forma parte de la teora de la escuela, se puede encontrar dentro de la pgina 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.
La simulacin se realizar mediante TestBench. En este diseo 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,
49
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;
Este componente divide 50 veces la entrada que se le introduzca, por esa razn, y para facilitar la grafica, si definimos un periodo de CLK de 1ns el resultado de la simulacin es el siguiente.
50
En la grafica anterior se pude ver como la divisin 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.
CD CE CLK
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 aadir una salida llamada contador_out y contador_out2 para su posterior visualizacin, ya sea en la placa o mediante la simulacin.
51
3.1.2.2.
CD CE CLK
CD CE CLK
CLKIN_IN RST_IN
CLKDV_OUT CLKFX_OUT
freq_divider_10
TC_10
Bloque_DCM
CD CE CLK
CD CE
Contador1
CLK
Contador21
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.
52
TC_out = 1
While CE = 0
CE = 1 While CE = 0
0
TC_out = 0
CE = 1 While CE = 0
(N - 1)
TC_out = 1
1
TC_out = 0
CE = 1
2
TC_out = 0
While CE = 0
3
CE = 1
CE = 1
TC_out = 0
4
TC_out = 0
CE = 1
While CE = 0
3.1.2.4.
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;
53
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 contador_out <= '1' WHEN (present_state = "1010" AND CE = '1') ELSE '0'; <= present_state;
end Behavioral;
: :
IN OUT
std_logic; std_logic
2: Asignar dentro del contador las entradas y salidas del divisor de frecuencia, y si es necesario las seales que se utilizarn para conectar las salidas o entradas con otros componentes.
Uut
freq_div_10 PORT MAP ( CD => CD, CLK => CLK, CE => CE, TC10 => TC10 );
54
TC10 est conectada al pulso a 1MHz y se utiliza como condicin dentro del proceso para incrementar el valor del contador
Para declarar el contador, el cdigo 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 );
3.1.3.1.
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
55
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 end Behavioral; <= TC10;
3.1.3.2.
Como se ha decidido anteriormente la metodologa de simulacin que se utilizar ser mediante TestBench. Se ha de aadir al proyecto el archivo como se ha explicado anteriormente. El periodo inicial del reloj son 10 ns y segn las especificaciones se necesita una entrada a 50MHz, por esta razn ser el primer punto a modificar en el cdigo.
-- Clock period definitions constant CLK_period : time := 20 ns;
Hecho esto se empezar a introducir el cdigo dentro del proceso de simulacin para definir las pautas a seguir. 56
3.1.3.2.1.
Para este proyecto a fin de seguir el comportamiento del reloj, ya que es un elemento autnomo, es interesante introducir una herramienta nueva de control. Las afirmaciones lgicas son un mtodo fiable para obtener informacin del correcto funcionamiento del cdigo. 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 Condicin 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 compilacin. Error: Muestra un error dentro de la ventana de compilacin e interrumpe el flujo del programa.
Esquema:
Si la afirmacin introducida dentro de la secuencia de simulacin es correcta, no se producir el evento definido. Tras introducir esta herramienta dentro del proceso de simulacin el cdigo queda de la siguiente manera:
57
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 signal TC_out signal div_10out : std_logic_vector(3 downto 0); : std_logic; 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 = report "<Paso 1 error!>" severity note; wait for CLK_period*50; "1001"
58
CD <= '0'; CE <= '0'; wait for CLK_period*500; assert contador_out = report "<Paso 2 error!>" severity note; wait for CLK_period*50; CD <= '1'; CE <= '0'; wait for CLK_period*500; assert contador_out = report "<Paso 3 error!>" severity note; wait for CLK_period*50; CD <= '0'; CE <= '1'; wait for CLK_period*500; assert contador_out = report "<Paso 4 error!>" severity note; wait for CLK_period*50; -- insert stimulus here wait; end process; END;
"1010"
"0001"
"1001"
Se fuerza un error o una afirmacin 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.
59
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.
CLKIN_IN RST_IN
CLKDV_OUT CLKFX_OUT
Bloque_DCM
Todas las salidas tendrn que ser declaradas como seales y a partir de la inclusin de este componente en el proyecto, el resto de elementos dependientes del reloj tendrn 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. 60
3.1.4.3.
Se ha de aadir un nuevo archivo al diseo, 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.
Tras seleccionar esta herramienta y finalizar el formulario para aadir el componente, se abrir automticamente la primera ventana de configuracin del mismo. En esta nueva ventana ( Figura 49 1er ventana configuracin 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 divisin y multiplicacin 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 seal 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.
61
En la siguiente ventana se pueden renombrar las entradas y salidas del componente. Se utilizara la configuracin por defecto. La tercera ventana ( Figura 50 Seleccin frecuencia de salida. ) es ms interesante, ofrece la opcin 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 configuracin de salida automtica a 5MHz y tras calcular el resultado la ventana presenta el aspecto siguiente.
62
Como en la mayora 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
Una vez terminado el proceso volver a la ventana principal y solo quedara declarar este componente como otro cualquiera.
3.1.4.4.
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 instanciacin del componente. Proporciona tanto la estructura de puertos como la asignacin de entradas y salidas. ( Figura 51 Instanciacin. )
63
Figura 51 Instanciacin.
Seales: 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;
Asignacin de seales:
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
);
Para comprobar el funcionamiento se duplicar el cdigo del contador, controlando el segundo con la salida CLKDV_OUT que proporciona 5 MHz. El archivo de simulacin se puede crear de nuevo o editarlo a mano aadiendo todo el cdigo necesario. Para evitar que se produzca el error de mltiples conexiones para el reloj de entrada, ser necesario utilizar la salida CLK0_OUT para la entrada del divisor de frecuencia que ya se haba implementado.
uut: freq_div_10 PORT MAP ( CD => CD, CLK => CLK0_OUT, CE => CE, TC10 => TC10 );
64
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 signal signal signal signal CLKIN_IBUFG_OUT : std_logic; CLK0_OUT : std_logic; LOCKED_OUT : std_logic; CLKDV_OUT : std_logic; CLKFX_OUT : std_logic;
begin Inst_Contador1: Contador PORT MAP( CD =>CD , CLK => CLK0_OUT, CE =>TC10 ,
65
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 );
66
3.1.4.5.
Gracias a este esquema se puede ver la solucin anteriormente descrita para el error de mltiples conexiones del reloj de entrada, y la forma en la cual queda anexo al diseo este nuevo componente.
67
El archivo de simulacin utilizado es el mismo del apartado 3.1.3.2 y solo se han declarado las seales necesarias para mostrar la segunda salida. Tras realizar la simulacin con dos contadores la grafica resultante es la siguiente.
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.
68
Y si se hace el suficiente zoom se podr ver como los retardos son muy similares a los comentados con anterioridad. Se han aadido las salidas div_10out y dcmout para poder estudiar el trato de estas seales, y la eficiencia del DCM y del divisor de frecuencia que se ha hecho.
69
La seal de reloj proveniente de la salida CLKDV_OUT del componente DCM presenta un periodo de 200 ns ( 5 MHz). La seal resultante del divisor de frecuencia presenta un pulso ms estrecho, ya que no tiene correccin 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 4077 ns, esto demuestra que el componente DCM da un trato mucho ms eficiente al reloj de entrada.
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 podrn observar las diferencias de funcionamiento con ms facilidad, como por ejemplo el retardo acumulativo que se produce.
70
Reloj
Hora
71
CONTROL SEALES
Controlador
CONTROL ENTRADAS ESTADOS SEALES
DATA PATH
SALIDA DATOS
Igual que a la hora de disear una aplicacin ( Figura 2 Flujo de diseo. ) 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 funcin de controlador es la mquina de estados, que es la encargada de regir y controlar todas las seales y estados de funcionamiento.
CD CE UD_L
CLK CLK2
SET MODE
STATE MACHINE
Figura 61 Mquina de estados.
72
4.2.2. DATAPATH
Los elementos controlados por la mquina de estados y encargados de efectuar todas las operaciones necesarias para mostrar la informacin correcta, son los englobados en este apartado.
4.2.2.1.
CE Modulo 12 (Horas)
TC24
CE Modulo 60 (Minutos)
TC60
CE
CD CLK UD_L
CD CLK UD_L
CD CLK
UD_L
HT(3..0) HU(3..0)
MT(3..0) MU(3..0)
ST(3..0) SU(3..0)
4.2.2.2.
Preparacin de datos.
Count
LDR1
LDR1
Count
Count
LDR1
LDR1
Count
Count
LDR1
LDR1
Count
Estos 6 componentes convierten las unidades y decenas de segundos, minutos y horas al formato necesario para ser procesado por el LCD.
73
4.2.2.3.
Efecto de parpadeo.
Parpadeo
Este componente hace parpadear el dato con el cual se est interaccionando para ser modificado.
4.2.2.4.
Visualizacin.
(7 downto 0)
CLK
DB RS
rst
RW
lcd
Figura 65 Visualizacin.
Este elemento es el encargado de gestionar al LCD integrado en la Spartan3AN y de captar, procesar y mostrar los segundos, minutos y horas provenientes de los convertidores.
CD CLK_1Hz CE CLK
CLKIN_IN RST_IN
CLKDV_OUT CLKFX_OUT
freq_divider_top
CLK_10Hz CLK_1000Hz
DCMclock
Estos dos elementos generan las frecuencias necesarias para todo el sistema.
74
Para realizar esta parte se crear un archivo top para los tres divisores de frecuencia que se utilizaran, en el tendrn que esta declaradas las seales y las salidas necesarias para extraer las tres salidas resultantes, con la finalidad ser utilizadas por el resto del programa.
4.3.1.1.
Entradas
CE CD CLK
CD CLK
CD CLK
CD CLK
freq_div_10
CE CE
freq_div_100
CE
freq_div_49999
TC10
CE1
TC100
TC49999
CE2
CE3
Salidas
75
El comportamiento del divisor de frecuencia por separado ya ha sido explicado, en este esquema interconectamos los componentes para conseguir dividir por un nmero diferente la frecuencia en cada iteracin. Ejemplo:
50 MHz 1 KHz 10 Hz 1 Hz
Ya se conoce la manera de crear un componente e instanciarlo en un bloque jerrquico superior, ahora solo se ha de seguir el esquema y redactar el cdigo necesario.
Divisor DCM
Crear un archivo superior que contenga el divisor de frecuencia y la declaracin del bloque DCM.
76
4.3.2.1.
CD CLK
CD CE CLK CLK_1Hz
CLKIN_IN RST_IN
CLKDV_OUT CLKFX_OUT
freq_divider_top
CLK_10Hz CLK_1000Hz
DCMclock
CLK_10000hez
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 seales. La declaracin 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 );
Ahora la salida CLK_10000hez ser la entrada de reloj del divisor de frecuencia, y por lo tanto se tendr que modificar la primera divisin, 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 seal el bloque DCM y las inconveniencias del divisor de frecuencia. 77
4.3.2.2.
Se puede comprobar cmo el pulso de reloj generado es muy estrecho en tiempo y como todas las seales se generan sncronamente con el reloj de entrada. 4.3.2.4. Medida real de las frecuencias a la salida de los Divisores y el componente DCM
Se puede comprobar la calidad de la seal a la salida del componente DCM que justifica su uso para realizar saltos abruptos en frecuencia.
78
Con ms detalle se puede ver la brevedad de sus transitorios y lo comprobado anteriormente un retraso de ~7ns.
79
En estas graficas se puede ver que la forma de la seal a la salida del DCM es prcticamente una seal cuadrada normal, mientras que a la salida del divisor de frecuencia es un pulso estrecho en tiempo al periodo definido.
4.4.1.1.
Los dos bloques son idnticos, 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. 80
Anteriormente ya se adelantaba que en los modulos 60 el encargado de los segundos hara actuar el de los minutos, en este caso se baja un escaln en los contadores para ver cmo gestionar las unidades y las decenas de los mismos.
4.4.1.2.
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 opcin 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.
81
Los contadores como se deduce del comportamiento pueden contar adelante o hacia atrs, esta funcin viene controlada por la entrada UD_L, que tambin gestiona un MUX externo, que se encarga de ofrecer el valor a cargar en cada caso.
4.4.1.3.
Cdigo Modulo 60
Anexo: 8.1.2.1.
4.4.1.4.
En la simulacin 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 activacin de la salida TC60, que ser la encargada de accionar al siguiente bloque.
82
Este componente se diseo de forma compacta y no tiene la opcin 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 condicin mltiple final, siempre que la variable de control sea 10, 11 o 12 las salida de decenas ser 1.
El componente s que conserva la opcin de contar o descontar, y en un futuro ser implementada de forma global.
83
4.4.2.1.
En la simulacin 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 atrs del contador.
84
Mientras el sistema este en reposo el funcionamiento ser el de un reloj normal, cuando se pulse el botn 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 segn la condicin UD_L.
85
Todas estas asignaciones controlan la seleccin de los multiplexores para hacer conmutar el sistema desde la posicin de reposo a la posicin de control. En esta posicin ninguno est activo, dejando funcionar al contador de forma normal. 1 posicin de control:
MCEH MCEM MCES MSel <= <= <= <= '0'; '0'; MODE; '1';
En esta posicin 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 posicin de control el funcionamiento es el mismo y su configuracin queda de la siguiente manera respectivamente:
MCEH MCEM MCES MSel MCEH MCEM MCES MSel <= <= <= <= <= <= <= <= '0'; MODE; '0'; '1'; MODE; '0'; '0'; '1';
Para gestionar este conjunto de contadores y la mquina de estados, se tendr que crear el archive top de la STATE MACHINE, y declarar en el todos los componentes necesarios para su funcionamiento. 86
CD CE UD_L
CLK_1Hz CLK_2Hz
STATE MACHINE
1Hz 2Hz S CEHor CEMin CESeg
Mux2 1
CH2
CLK
CH1
CEH
CE Modulo 12 (Horas)
TC24 TC24
CEM
CE Modulo 60 (Minutos)
TC60
CES TC60m
CE
TC60s
CD CLK UD_L
CD CLK UD_L
CD CLK
UD_L
HT(3..0) HU(3..0)
MT(3..0) MU(3..0)
ST(3..0) SU(3..0)
CLK UD_L CD
Ahora, como en casos anteriores, se debe declarar todas las seales necesarias y seguir la nomenclatura y las conexiones del esquema.
87
En esta primera figura se puede ver como se pasa de un estado a otro mediante la condicin SETE. Igual que en todo el proyecto el cambio de estados se produce con un evento de reloj.
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 mdulos 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
88
4.6. LCD
Ahora solo queda la visualizacin 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 cdigo ejemplo para mostrar una frase corporativa por pantalla. Se reciclar y modificar este cdigo para que se comporte de forma adecuada a la visualizacin de los datos.
http://www.digilentinc.com/Data/Products/NXLCD/lcd.vhd
El cdigo 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 patrn 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 cdigo 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 mltiples, se ha de conecta la entrada de reloj del componente LCD a la salida CLK0_OUT del DCM mediante la seal pertinente. Este cdigo muestra los datos precargados en una variable y una vez que llena el mximo de caracteres visibles por el LCD desplaza el contenido de derecha
89
a izquierda mediante tabulaciones. Esto significa que el LCD es capaz de cargar ms datos de los que es capaz de mostrar a tiempo real.
Si se quiere que los datos siempre sean visibles, se tendr que tabular de tal manera la informacin que se enviara a la pantalla, para que el contenido deseado siempre este dentro del margen visible.
Las casillas en blanco sern espacios, a fin de desplazar el texto til a derecha o izquierda segn se necesite.
Otro punto a modifica es el hecho que este condigo funcionaba de forma autnoma, una vez que empezaba, cargaba la variable fija de entrada y 90
mostraba su contenido automticamente sin posibilidad de intervencin externa. nicamente permita 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 seal para poder modificar su informacin mediante la declaracin de un proceso para esta tarea. El evento ms rpido del reloj, es la actualizacin en tiempo real de los datos de los segundos, por esa razn se utilizara la salida a 1 Hz del divisor de frecuencia para reiniciar el proceso de presentacin de datos. De este modo cada vez se modifique el valor de los segundo, el programa automticamente recargara la seal de datos y realizara todo el proceso necesario para rellenar la parrilla a mostrar por pantalla. Algunos datos a mostrar por pantalla sern 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 cdigo, el proceso que gestiona la adquisicin y actualizacin de datos a mostrar es el siguiente: 4.6.2.1.
begin
Las posiciones asignadas han seguido el patrn descrito para situarlos en el margen visible de la pantalla. Tras efectuar estas modificaciones se har uso de la funcin RTL para visualizar el resultado, y as se dispondr de la nomenclatura del componente de forma general para su declaracin en el archivo general, que contendr todos los bloques anteriormente explicados.
91
Este componente se declarara para cada uno de los valores a mostrar por pantalla.
Ejemplo:
WHEN "1000" => LDR1 <= "10"&X"38";
10 -> Forma parte del vector de posicionamiento en pantalla. 28 -> Corresponde al nmero 8 en ASCII.
El la figura se puede observar la conversin de 6 valores a ASCII, y la correspondencia del estado 10 del CASE con un espacio en blanco, a fin de propiciar el parpadeo.
93
Este componente es controlado por la salida a 10 Hz del divisor de frecuencia, por esa razn se tendr que incluir una segunda entrada de reloj al componente maquina de estados (CLK2) y definir la seal necesaria para llevar el segundo pulso a la entrada de reloj del componente.
94
En la condicin 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 ms rpido del programa era la actualizacin 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 razn 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 condicin PAR y la entrada estado proveniente de la mquina de estados.
ELSIF (PAR='0' And estado="11" ) THEN STout<=STin; SUout<=SUin; MTout<=MTin; MUout<=MUin; HTout<="1010"; HUout<="1010";
Cada estado menos el de reposo tiene un bloque de condicin igual. En este caso se muestra el modo de control de las horas. Cuando al nmero le corresponda parpadear, se le asignara un valor definido por el usuario que corresponder a una posicin del case del Convertidor de datos. Este valor est definido fuera del mtodo normal de funcionamiento para que no se produzcan errores, y corresponde a la posicin 10 del case. En esta posicin se asigna a la salida el valor correspondiente a un espacio en cdigo ASCII para que cuando el LCD lo capture, pinte por pantalla un hueco en blanco.
WHEN
Par
->
1 Dato
1 Dato
1 Dato
HTout ->
95
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 condicin 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 mquina 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.
96
4.9.
Se ha ido describiendo las conexiones bloque a bloque, pero para facilitar y comprobar el diseo, se ha elaborado el esquema completo que interconecta todos los componentes. El cdigo final tiene ms 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.
97
Entradas
CLK CD CE UD_L SETE MODE
CLKIN_IN RST_IN
CLK_10000hez CLKFX_OUT
CLK CD CE CLK_1Hz
CLK0_OUT
CLK0_OUT
LOCKED_OUT
CLK_1000Hz
CD CE UD_L HT TENS3sig (3 downto 0) HU UNIS3sig (3 downto 0) MT TENS2sig (3 downto 0) CLK CLK2 MU UNIS2sig (3 downto 0)
SET MODE
STATE MACHINE
Count
LDR1
LDR1
Count
Count
LDR1
LDR1
Count
LDR1
LDR1
Count
lcd
Salidas
DB (7 downto 0) RS RW ADR1 ADR2 rdone CS OE
CLK_10hez CLK_1hez
DCMclock
CLKIN_IBUFG_OUT
freq_divider_top
CLK_10Hz
98
99
4.9.4.1.
UCF Aplicacin.
Anexo: 8.1.7.
Tras introducir el cdigo 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.
100
5. Posibles mejoras.
Hoy en da se pueden encontrar en el mercado multitud de relojes diferentes, desde los ms sencillos a relojes destinados a senderismo y escalada que disponen de brjula, altmetro, GPS y barmetro.
Por las dimensiones del hardware en el que se trabaja, no sera viable hacer un dispositivo mvil similar, pero se podran incluir los perifricos necesarios para construir una estacin fija para recopilar esta informacin. 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 informacin a un ordenador o mvil mediante su tarjeta de red. Finalmente se podra abordar una tecnologa emergente como la domtica para incorporar la informacin de los perifricos que controlan un hogar o sistema de alarma en el abanico de informacin que recopilamos con la Spartan-3AN, o incluso utilizar el dispositivo para gobernar el domicilio, ya sea fsicamente o mediante la tarjeta de red desde un lugar remoto.
101
6. Conclusiones
Este trabajo surgi de la necesidad de conocer la forma de programar las diferentes FPGAs que nos rodean de los distintos fabricantes. El documento ira destinado a gente similar al creador de este proyecto, que hasta hace menos de un ao desconoca por completo la programacin de este tipo de dispositivos, y cuando empez careca 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 elaboracin de proyectos, se han construidos cdigos sencillos y cdigos compuestos gobernados por un reloj de entrada. En cuando a los diferentes mtodos de adecuar la frecuencia de entrada a nuestro dispositivo, se han implementado divisores de frecuencia y utilizado IPs (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 seal de salida, pero presenta un abanico de frecuencias muy elevadas para conseguir un pulso a un 1 Hz. Simulando los diseos se ha podido comprobar la practicidad frente al archivo .DO del uso del TestBench, por su incrustacin dentro del programa de diseo y su inmediatez tanto por la cantidad de cdigo que ofrece resuelto, como puede ser la implementacin del reloj, o en la obtencin de los datos de la simulacin. 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 mquina es la encargada de gestionar el modo de funcionamiento y la puesta en hora del dispositivo. Para su creacin se ha seguido un diagrama de estados y un modelo circuital creado previamente de forma terica. La visualizacin se ha resuelto incorporando el uso del perifrico LCD. Se ha podido ver cmo funciona y como modificar un cdigo origen para un uso deseado. La adecuacin de la informacin de entrada ha sido resuelta mediante un convertidor de datos a un formato esperado, a fin de ser correctamente procesada la informacin por el LCD. Finalmente se han implementado pequeas mejoras estticas como el parpadeo del dato seleccionado para ser modificado, dentro de los estados de control en la STATE MACHINE.
102
7. Bibliografa
103
104
8. Anexos
8.1. Cdigos.
En este apartado se incluirn todos los cdigos necesarios para realizar la aplicacin y que resultaran 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 CLK_1000Hz CLK_10Hz CLK_1Hz ); END freq_divider_top; ARCHITECTURE schematic OF freq_divider_top IS -- Components COMPONENT freq_div_100 IS PORT(CD,CLK,CE : IN TC100 : ); END COMPONENT; COMPONENT freq_div_49999 IS PORT(CD,CLK,CE TC49999 ); END COMPONENT; COMPONENT freq_div_10 IS PORT(CD,CLK,CE TC10 ); END COMPONENT; : IN
IN : : :
IN :
-- 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 );
105
: freq_div_100 CLK CD CE TC100 => CE2, => CD, => CE, => CE3
); -freq_div_10_Comp1 PORT MAP ( : freq_div_10 CLK CD CE TC10 ); --- connections and logic between components CLK_1000Hz <= CE2; CLK_10Hz <= CE3; CLK_1Hz <= CE1; END schematic ; => CE3, => CD, => CE, => CE1
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 TC49999 ); END freq_div_49999; : IN std_logic; : OUT std_logic
ARCHITECTURE FSM_style OF freq_div_49999 IS SIGNAL present_state, future_state 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 future_state <= "00000000000000"; ELSE future_state <= present_state + 1; END IF; ELSE future_state <= present_state; END IF; END PROCESS CS1; : std_logic_vector(13 DOWNTO 0);
-- 0x18 == 0d24
-- combinational logic to determine the outputs -- CS2: TC49999 <= '1' WHEN (present_state = "10011100001111" AND CE = '1') ELSE '0'; END FSM_style ;
106
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 TC100 ); END freq_div_100; : IN : std_logic; OUT std_logic
ARCHITECTURE FSM_style OF freq_div_100 IS SIGNAL present_state, future_state 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 ; : std_logic_vector(6 DOWNTO 0);
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 TC10 ); END freq_div_10; : IN : std_logic; OUT std_logic
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
107
-- 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.
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
108
-- 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';
109
wait for CLK_period*10000; -- insert stimulus here wait; end process; END;
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 TC60 TENS UNIS ); 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 Q : OUT STD_LOGIC_VECTOR(3 DOWNTO TC10 : OUT STD_LOGIC ); END COMPONENT; COMPONENT four_bit_mux IS PORT ( s : a : IN b : IN z : END COMPONENT;
: : : :
0); 0);
IN STD_LOGIC; STD_LOGIC_VECTOR (3 downto 0); STD_LOGIC_VECTOR (3 downto 0); OUT STD_LOGIC_VECTOR (3 downto 0));
110
PORT
-- Signals -- For connecting components together SIGNAL TCUNITS, TCTENS, DET5, TC60UP, TC60DOWN, LDTENS : SIGNAL ITENS,T,U : std_logic_vector (3 downto 0); --SIGNAL clk2hz : STD_LOGIC;
std_logic;
CONSTANT Reset : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000"; CONSTANT Cinco : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0101"; BEGIN -- Instantiation of components
=> to signal or port name CLK => CLK, LD => LDTENS, CD => CD, CE => TCUNITS, UD_L => UD_L, I => ITENS, Q => T, TC10 => TCTENS
);
: Counter -- 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 s => a => b => z => ); QUADMUX2 : two_bit_mux PORT MAP ( -- from component name s => a => b => z => ); Detector : detect5 PORT MAP ( -- from component name => to signal or port name x => T, z => DET5 ); => to signal or port name UD_L, TC60DOWN, TC60UP, LDTENS
111
-- 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 Port ( CLK LD : IN CD : IN CE : IN UD_L I : IN Q : OUT TC10 ); END Counter; -- Internal desciption in FSM style ARCHITECTURE FSM_like OF Counter IS CONSTANT Max_Count : -- terminal_count after CONSTANT Max_Count2 : CONSTANT Reset : CONSTANT Reset2 -- Internal wires STD_LOGIC_VECTOR(3 DOWNTO 13 states STD_LOGIC_VECTOR(3 DOWNTO STD_LOGIC_VECTOR(3 DOWNTO : STD_LOGIC_VECTOR(3 0) := "1001"; 0) := "0000"; 0) := "0000"; DOWNTO 0) := "1001"; IS : IN STD_LOGIC; STD_LOGIC; STD_LOGIC; STD_LOGIC; : IN STD_LOGIC; STD_LOGIC_VECTOR(3 DOWNTO STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC
0); 0);
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 ;
112
ELSE future_state <= Reset2; END IF; END IF; ELSE future_state <= present_state; END IF; ELSE future_state <= I; END IF; END PROCESS CS_1;
-- count disable
------------------------- 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: z: OUT ); IN STD_LOGIC_VECTOR (3 DOWNTO 0);
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 (
113
s: a, b: z: OUT );
IN IN
STD_LOGIC; STD_LOGIC;
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
z: ); END detect5;
OUT
STD_LOGIC
ARCHITECTURE dec5 OF detect5 IS BEGIN z <= '1' WHEN (x = "0101") ELSE '0'; END dec5;
114
8.1.2.2.
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';
115
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 : 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 WHEN IN std_logic;
116
WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN OTHERS
"0010" => UNIS<= "0010"; "0011" => UNIS<= "0011"; "0100" => UNIS<= "0100"; "0101" => UNIS<= "0101"; "0110" => UNIS<= "0110"; "0111" => UNIS<= "0111"; "1000" => UNIS<= "1000"; "1001" => UNIS<= "1001"; "1010" => UNIS<= "0000"; "1011" => UNIS<= "0001"; "1100" => UNIS<= "0010"; "1101" => UNIS<= "0000"; "1110" => UNIS<= "0000"; => UNIS<= "0000";
END CASE;
END PROCESS;
end Behavioral;
8.1.2.4.
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)
117
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 <= CE <= '0'; dir <= '0'; wait for clock_period*10; CD <= CE <= '1'; dir <= '1'; wait for clock_period*10; CD <= CE <= '1'; dir <= '0'; wait for clock_period*10; '1';
'0';
'0';
118
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 --signal --signal 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 WHEN WHEN WHEN WHEN WHEN WHEN WHEN WHEN "0000" => LDR1<= "10"&X"30"; --LDR2<= "10"&X"30"; "0001" => LDR1<= "10"&X"31"; --LDR2<= "10"&X"31"; "0010" => LDR1<= "10"&X"32"; --LDR2<= "10"&X"32"; "0011" => LDR1<= "10"&X"33"; --LDR2<= "10"&X"33"; "0100" => LDR1<= "10"&X"34"; --LDR2<= "10"&X"34"; "0101" => LDR1<= "10"&X"35"; --LDR2<= "10"&X"35"; "0110" => LDR1<= "10"&X"36"; --LDR2<= "10"&X"36"; "0111" => LDR1<= "10"&X"37"; --LDR2<= "10"&X"37"; "1000" => LDR1<= "10"&X"38"; --LDR2<= "10"&X"38"; lcd_rw_control : std_logic; lcd_output_data : std_logic_vector(7 downto 4); lcd_drive : std_logic;
119
WHEN WHEN WHEN WHEN WHEN WHEN WHEN OTHERS END CASE;
"1001" => LDR1<= "10"&X"39"; --LDR2<= "10"&X"39"; "1010" => LDR1<= "10"&X"20"; --LDR2<= "10"&X"30"; "1011" => LDR1<= "10"&X"31"; --LDR2<= "10"&X"31"; "1100" => LDR1<= "10"&X"31"; --LDR2<= "10"&X"32"; "1101" => LDR1<= "10"&X"31"; --LDR2<= "10"&X"33"; "1110" => LDR1<= "10"&X"31"; --LDR2<= "10"&X"34"; => LDR1<= "10"&X"31"; --LDR2<= "10"&X"35";
END PROCESS; --lcd_rw(0)<='1'; --LCD_DB(3 DOWNTO 0 )<=Count(3 DOWNTO 0); end Behavioral;
8.1.3.2.
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 LDR1 : OUT ); 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';
120
-----
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.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 estado HTin HUin MTin MUin STin SUin HTout HUout MTout MUout STout SUout --TC24 : OUT : IN STD_LOGIC; STD_LOGIC_VECTOR(1 DOWNTO : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO STD_LOGIC : IN 0); DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO 0); 0); 0); 0); 0); 0) 0); 0); 0); 0); 0); 0);
121
); end Parpadeo; architecture Behavioral of Parpadeo is SIGNAL DIV : STD_LOGIC_VECTOR(1 DOWNTO -SIGNAL HUsig : STD_LOGIC_VECTOR(3 -SIGNAL MTsig : STD_LOGIC_VECTOR(3 -SIGNAL MUsig : STD_LOGIC_VECTOR(3 -SIGNAL STsig : STD_LOGIC_VECTOR(3 -SIGNAL SUsig : STD_LOGIC_VECTOR(3 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";
122
END IF; END PROCESS Parpadeo; PAR<='1' WHEN (DIV="00" or DIV="01") ELSE '0'; end Behavioral;
8.1.4.2.
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 : signal HUout : signal MTout : signal MUout : signal STout : signal SUout : std_logic_vector(3 std_logic_vector(3 std_logic_vector(3 std_logic_vector(3 std_logic_vector(3 std_logic_vector(3 downto downto downto downto downto downto 0); 0); 0); 0); 0); 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,
123
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; HTin HUin MTin MUin STin SUin estado <="01"; <="1100"; <="1100"; <="0110"; <="0110"; <="0011"; <="0011";
wait for CLK_period*10; HTin HUin MTin MUin STin SUin estado <="10"; <="1100"; <="1100"; <="0110"; <="0110"; <="0011"; <="0011";
wait for CLK_period*10; HTin HUin MTin MUin STin SUin estado <="11"; <="1100"; <="1100"; <="0110"; <="0110"; <="0011"; <="0011";
124
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); RS:out std_logic; RW:out std_logic; CLK:in std_logic; ADR1:out std_logic; ADR2:out std_logic; entrada1 : in std_logic_vector(9 entrada2 : in std_logic_vector(9 entrada3 : in std_logic_vector(9 entrada4 : in std_logic_vector(9 entrada5 : in std_logic_vector(9 entrada6 : in std_logic_vector(9 CS:out std_logic; OE:out std_logic; rst:in std_logic; 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, stEnable, stIdle );
--DB( 7 through 0) --WE --ADR(0) --GCLK2 --ADR(1) --ADR(2) downto 0); downto 0); downto 0); downto 0); downto 0); downto 0); --CSC --OE --BTN
------------------------------------------------------------------- Signal Declarations and Constants -------------------------------------------------------------------These constants are used to initialize the LCD pannel. --FunctionSet: --Bit 0 and 1 are arbitrary
125
--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 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => "10"&X"43", "10"&X"6F", "10"&X"6E", "10"&X"74", "10"&X"61", "10"&X"64", "10"&X"6F", "10"&X"72", "10"&X"3A", "10"&X"20", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", "10"&X"18", --C --o --n --t --a --d --o --r --: -- Space ------------------------Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts Shifts left left left left left left left left left left left left left left left left left left left left left left left left
126
38 39 40 41 42 43
-------
44 45 46 47 48 49 50 51 52
--entrada5sig --entrada6sig --: --entrada3sig --entrada4sig --: --entrada1sig --entrada2sig -- 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;
127
--
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;
128
--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;
129
--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;
8.1.5. Control.
8.1.5.1. Mquina 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 CLK2 : IN SETE : IN MODE : IN
130
STD_LOGIC; STD_LOGIC; STD_LOGIC; STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC
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 TENS : UNIS : ); END COMPONENT; COMPONENT two_bit_mux IS PORT ( s a,b : z ); END COMPONENT; COMPONENT Parpadeo is PORT ( CLK estado HTin HUin MTin MUin STin SUin HTout HUout MTout MUout STout SUout --TC24 : OUT ); END COMPONENT;
: IN :
: IN STD_LOGIC; STD_LOGIC_VECTOR(1 DOWNTO : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : IN STD_LOGIC_VECTOR(3 : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO : OUT STD_LOGIC_VECTOR(3 DOWNTO STD_LOGIC : IN
0); DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO 0); 0); 0); 0); 0); 0)
SIGNAL present_state : std_logic_vector(1 SIGNAL future_state : std_logic_vector(1 downto --SIGNAL estados2 : std_logic_vector(2 downto --SIGNAL Control : std_logic_vector(3 downto --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';
131
SIGNAL CES : SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL MCEH MCEM MCES MSel : : : :
std_logic:= '0'; std_logic:= std_logic:= std_logic:= std_logic:= : : : : : : '0'; '0'; '0'; '0'; DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO DOWNTO 0); 0); 0); 0); 0); 0);
--SIGNAL TC60minsig : std_logic; begin Segun1: module60 PORT MAP( CD CLK CE UD_L TC60 TENS => UNIS => ); Minutos1: module60 PORT MAP( CD CLK CE UD_L TC60 TENS => UNIS => ); Horas: Contador24 PORT MAP( CD clock CE dir TENS => UNIS => ); MUX2_1 : two_bit_mux PORT MAP ( -- from component name s => a => b => z => ); MUX2_2 : two_bit_mux PORT MAP ( -- from component name s => a => b => z => ); MUX2_3 : two_bit_mux PORT MAP ( -- from component name s => a => b => z => ); => CD, =>CLKsig, => CEH, => UD_L, HTsig, HUsig => => => => => MTsig, MUsig CD, CLKsig, CEM, UD_L, TC60minsig, => => => => => STsig, SUsig CD, CLKsig, CES, UD_L, TC60segsig,
132
MUX2_4 : two_bit_mux PORT MAP ( -- from component name s => a => b => z => );
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 HUin =>HUsig,-: IN STD_LOGIC_VECTOR(3 DOWNTO MTin =>MTsig,-: IN STD_LOGIC_VECTOR(3 DOWNTO MUin =>MUsig,-: IN STD_LOGIC_VECTOR(3 DOWNTO STin =>STsig,-: IN STD_LOGIC_VECTOR(3 DOWNTO SUin =>SUsig,-: IN STD_LOGIC_VECTOR(3 DOWNTO 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;
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';
133
end Behavioral;
134
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;
135
wait for CLK_period*10; -- insert stimulus here wait; end process; END;
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;
136
: : :
COMPONENT Maquina_Estados is Port ( CLK : IN CLK2 : IN SETE : IN MODE : IN CD : IN CE : IN UD_L : IN HT : OUT HU : OUT MT : OUT MU : OUT ST : OUT SU : OUT --TC24 : OUT ); end COMPONENT;
STD_LOGIC; STD_LOGIC; STD_LOGIC; STD_LOGIC; STD_LOGIC; STD_LOGIC; STD_LOGIC; STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC_VECTOR(3 STD_LOGIC
COMPONENT lcd IS Port ( DB:out std_logic_vector(7 RS:out std_logic; RW:out std_logic; CLK:in std_logic; ADR1:out std_logic; ADR2:out std_logic; entrada1 : in std_logic_vector(9 entrada2 : in std_logic_vector(9 entrada3 : in std_logic_vector(9 entrada4 : in std_logic_vector(9 entrada5 : in std_logic_vector(9 entrada6 : in std_logic_vector(9 CS:out std_logic; OE:out std_logic; rst:in std_logic; rdone: out std_logic); --WriteDone output to work with DI05 test END COMPONENT; SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL SIGNAL LDR1sig LDR2sig LDR3sig LDR4sig LDR5sig LDR6sig : : : : : :
downto 0); --WE --ADR(0) --GCLK2 --ADR(1) --ADR(2) downto 0); downto 0); downto 0); downto 0); downto 0); downto 0); --CSC --OE --BTN
--DB( 7 through 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) ----); END COMPONENT; SIGNAL CLK_1hz : std_logic; SIGNAL CLKDV_OUT : std_logic; SIGNAL CLKIN_IBUFG_OUT : std_logic; 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)
137
SIGNAL CLK0_OUT : SIGNAL LOCKED_OUT : --SIGNAL CLK_50 : SIGNAL CLK_1hez : SIGNAL CLK_10hez : SIGNAL CLK_1000hez : SIGNAL CLK_10000hez : SIGNAL TENS3sig : SIGNAL UNIS3sig : SIGNAL TENS2sig : SIGNAL UNIS2sig : SIGNAL TENSsig : SIGNAL UNISsig :
std_logic; std_logic; std_logic; std_logic; std_logic; std_logic; std_logic; std_logic_vector(3 downto 0); std_logic_vector(3 downto 0); std_logic_vector(3 downto 0); std_logic_vector(3 downto 0); std_logic_vector(3 downto 0); std_logic_vector(3 downto 0);
std_logic; std_logic;
std_logic; std_logic;
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 CLK CE CLK_1Hz CLK_10Hz CLK_1000Hz ); 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 HU =>UNIS3sig,--: OUT STD_LOGIC_VECTOR(3 DOWNTO MT =>TENS2sig,--: OUT STD_LOGIC_VECTOR(3 DOWNTO MU =>UNIS2sig,--: OUT STD_LOGIC_VECTOR(3 DOWNTO =>
=>
CLK_1000hez
138
ST =>TENSsig,--: OUT STD_LOGIC_VECTOR(3 DOWNTO 0); SU =>UNISsig--: OUT STD_LOGIC_VECTOR(3 DOWNTO --TC24 : OUT STD_LOGIC );
0)
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 ----); Convnum2: Prub3 PORT MAP ( Count => UNISsig, --LDR1 => LDR1sig, LDR1 => LDR2sig ----); Convnum3: Prub3 PORT MAP ( Count => TENS2sig, --LDR1 => LDR1sig, LDR1 => LDR3sig ----); Convnum4: Prub3 PORT MAP ( Count => UNIS2sig, --LDR1 => LDR1sig, LDR1 => LDR4sig ----); Convnum5: Prub3 PORT MAP ( Count => TENS3sig, --LDR1 => LDR1sig, LDR1 => LDR5sig LCD_DB => LCD_DB, LCD_E => LCD_E, LCD_RS => LCD_RS, LCD_RW => LCD_RW LCD_DB => LCD_DB, LCD_E => LCD_E, LCD_RS => LCD_RS, LCD_RW => LCD_RW LCD_DB => LCD_DB, LCD_E => LCD_E, LCD_RS => LCD_RS, LCD_RW => LCD_RW LCD_DB => LCD_DB, LCD_E => LCD_E, LCD_RS => LCD_RS, LCD_RW => LCD_RW
139
LCD_DB => LCD_DB, LCD_E => LCD_E, LCD_RS => LCD_RS, LCD_RW => LCD_RW
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 --Control_50Meg Control_10Meg Control_1000 Control_10 Control_1 --UNIS <= --TENS <= --------<= CLK; <= CLK_50; CLK_10000hez; CLK_1000hez; CLK_10hez; CLK_1hez;
UNISsig; 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;
140
############################################################################## # Character Display (LCD) ############################################################################## NET NET NET NET NET NET NET NET NET NET NET "DB<0>" "DB<1>" "DB<2>" "DB<3>" "DB<4>" "DB<5>" "DB<6>" "DB<7>" "ADR2" "RS" "RW" LOC = "Y13" | LOC = "AB18" | LOC = "AB17" | LOC = "AB12" | LOC = "AA12" | LOC = "Y16" | LOC = "AB16" | LOC = "Y15" | LOC = "AB4" LOC = "Y14" | LOC = "W13" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ; IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = SLOW ;
############################################################################## # Mechanical Switches (SW) ############################################################################## NET "CD" NET "CE" NET "UD_L" ##NET "SETE" LOC = "V8" | IOSTANDARD = LVCMOS33 ; LOC = "U10" | IOSTANDARD = LVCMOS33 ; LOC = "U8" | IOSTANDARD = LVCMOS33 ; 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;
141