Videojuego FPGA en VHDL
Short Description
Download Videojuego FPGA en VHDL...
Description
Videojuego FPGA en VHDL Realizaremos paso a paso un sencillo ejemplo de entretenimiento para aprender a programar nuestra FPGA, para ello usaremos la tarjeta de Xilinxs, Spartan III Starter Kit.
Objetivo Se trata de implementar un sencillo videojuego que ponga a prueba los reflejos del jugador. El objetivo del juego se trata de atrapar a los escurridizos bits que irán apareciendo de forma aleatoria en los LED (LD0, LD1, LD2). Para ello habrá que accionar los pulsadores (BTN0, BTN1, BTN2) mientras los LED correspondientes correspondientes estén todavía encendidos. La partida se iniciará tras pulsar el Reset del sistema (BTN3) y durará 30 segundos. Los led permanecerán quietos durante 0.25 segundos antes de pasar a su siguiente configuración. El visualizador de cuatro dígitos mostrará en todo momento el número de bits atrapados desde el comienzo de la partida.No será válido dejar los pulsadores permanentemente actuados (emplear monoestable monoestable no redisparable r edisparable en estas entradas, por ejemplo, versiones basadas en el circuito antirrebote que se menciona en las sugerencias). Para generar la secuencia secuencia pseudoaleatoría se empleará un LFSR (Linear FeedBackShiftRegister). FeedBackShiftRegister). Los circuitos LFSR se utilizan en infinidad de sistemas electronicos para generar secuencias pseudoaleatorias con un periodo garantizado arbitrariamente largo, de forma simple y eficiente. Consiste en un registro de desplazamiento formado por una serie de biestables conectados en serie con realimentación XOR de sus salidas. A continuación puede verse un ejemplo de un LFSR de 5 bits.
La elección de las salidas reañimentadas es fundamental para conseguir una máxima longitud de la secuencia sin repeticiones. repeticiones. Para este trabajo emplearemos emplearemos un LFSR de 31 bits realimentando las salidas 2 y 30 (numerandolas (numerandolas desde cero), lo que generará secuencias secuencias sin repeticiones de aproximad a proximadamente amente 2.200 millones de números. Utilizaremos las tres de menor peso como patrón para encender los led. Una característica característica de los LFSR es que quedan bloqueados si su contenido es cero. P or ello es necesario inicializarlos con una semilla (un valor distinto de cero). Mejoras realizadas: Inclusión de varios niveles de dificultad, aumentando y disminiyundo el tiempo que los leds permanecen quietos. Esta seleccion se ha realizado mediante los interruptores delizantes.
Incluir varios niveles de dificultad aumentando o disminuyendo el número de leds que pueden encenderse a la vez. Para ello emplearemos una tabla de búsqueda o lookup de ocho elementos que contendrían los led a encender. La selección se realizará mediante los interruptores deslizantes. Métodos empleados: Usar contadores BCD con acarreo y permiso para almacenar la puntuación. El contador sólo contará en los flancos de subida de se señal de reloj cuando el permiso esté a 1. El acarreo valdrá 1 mientras el contador se halle en su valor máximo y 0 para el resto de valores posibles. El accareo de cada contador será el permiso del siguiente. Emplear un único decodificador de 7 segmentos y la técnica de multiplexación (ver manual) para controlar los cuatro dígitos de la placa para encender un número. Usar un prescaler o divisor que genere a partir de los 50MHz disponibles en la placa las frecuencias necesarias para la aplicación. Incluir circuitos antirrebote en las entradas conectadas a pulsadores (ver "lenguaje Templates"Templates">"VHDL"->"SynthesisTemplate >"VHDL"->"SynthesisTemplates"->"Debouncecircu s"->"Debouncecircuit" it" en la herramienta herramienta Xilinx ISE).
Manual de usuario Primeramente vamos a explicar el procedimiento lineal que sigue el sistema para realizar el videojuego. El juego no comienza hasta que pulsemos el botón 3, lo que quiere decir que el sistema está siempre esperando a que se pulse dicho botón. Antes de pulsar el botón 3 deberemos seleccionar el tiempo de juego de cada partida así como la dificultad del juego, ya sea con la velocidad en que aparecen los leds o si pueden aparecer 1 o varios leds a la vez, estas opciones de juego las seleccionaremos con los deslizadores de la tarjeta, tal y como aparece a continuación: Duración de juego:
10 SEG
SW1 0
SW0 0
30 SEG 40 SEG 60 SEG
0 1 1
1 0 1
SW3
SW2
0 0 1 1
0 1 0 1
Velocidad de los leds:
1 HZ 2 HZ 4 HZ 8 HZ
Número de leds:
UN LED VARIOS LED
SW4 1 0
Hay que tener en cuenta que 0 será el deslizador hacia abajo y 1 será hacia arriba. Se sugiere que para una mayor comprensión y seguimiento del proyecto puede bajarse el archivo "disposición ordenada de bloques y s eñales", el cual se puede encontrar en el punto Download de este mismo link. Es recomendable a la hora de hacer una aplicación en una FPGA se si ga un orden establecido en bloques y señales que se haya hecho previamente sobre papel, ya que este paso nos hará ahorrar tiempo a la hora de pasarlo a código. F uncionami en to
Una vez seleccionado las opciones de nuestro juego pulsaremos el botón 3, dicho botón será el encargado de iniciar o activar el componente Selector tiempo de Juego , el cual mantendrá un pulso a nivel alto el tiempo que hayamos seleccionado en el juego mediante los deslizadores SW0 y SW1, cuando acabe el tiempo de juego volverá a poner a nivel bajo el pulso con la consecuencia de la finalización del juego. Este pulso será a su vez el que active el componente Selector de Frecuencia, esté será el encargado se sacar un tren de pulsos a la frecuencia que hemos seleccionado previamente mediante los deslizadores SW2 y SW3, el cual actúa como habilitación a los monoestables, tanto el monoestable de la salida aleatoria como el monoestable de los pulsadores. El componente Monoestable Salida Aleatoria recibe la habilitación del tren de pulsos del selector de frecuencia y la salida de la semilla producida por el componente Salida Aleatoria el cual actúa como ³simulador´ de alguien que pulsa otros pulsadores distintos a los nuestros, ya que nosotros pulsamos unos botones (BTN0, BTN1, BTN2) cuya señal llega al componente Monoestable y es activado por el tren de pulsos del selector de frecuencia. Por lo tanto ya tenemos dos pulsaciones, una producida por la máquina (LEDs) y otra producida por nosotros mismos, lo que hacemos es comparar dichas pulsaciones para ver si han sido iguales mediante el componente Comparador. La semilla generada es aleatoria con lo que hay si queremos que se encienda sólo un led hay que codificar la señal de la semilla mediante el componente Codificador. Aquí por tanto tenemos dos procesos en paralelo. 1.- Comparador: Este comparará lo pulsado por el jugador con el resultado de la salida aleatoria y dará un pulso alto si la comparación es correcta. 2.- Codificador + comparador: La salida aleatoria la pasamos por el codificador con lo que sólo se encenderá un led. La salida del codificador irá a parar a la entrada del comparador como si fuese la nueva salida aleatoria pero que en este caso es sólo un led, para luego comparar la nueva salida aleatoria con lo pulsado por el jugador y dar un pulso alto si la comparación es correcta. Tenemos un proceso en paralelo, ¿entonces como sabemos que salida nos interesa y que comparador nos interesa?, es aquí donde entra en juego el deslizador SW4 y el componente Multiplexor Encender Leds, dicho multiplexor tiene como entrada controladora el SW4 y como entradas las entradas y salidas
del codificador y la comparación, si el SW4 es cero seleccionaremos el proceso paralelo del comparador y si SW4 es uno, entonces seleccionaremos el proceso paralelo del codificador + comparador. Las salidas del multiplexor encienden o apagan los led de la FPGA así como también tiene una salida que dará un pulso alto si la comparación ha sido correcta. Disponemos un componente llamado Contador de Aciertos el cual cuenta los pulsos que nos llega del multiplexor encender leds, los cuales son los aciertos que el jugador a realizado. Dicha suma se saca por los display gracias a los componentes Multiplexor de Display yConmutador de display, el conmutador enciende de forma continuada sólo un determinado display habilitándolo durante un periodo de tiempo y dándole el valor correspondiente de la suma de aciertos.
nzado Manual a va Vamos a ver más internamente el proceso viendo el código de cada componente.
1.- SELECTOR TIEMPO DE JUEGO: Este componente es el encargado de decir el tiempo del juego, para ello está distribuido en otras 5 entidades, de las cuales 4 son para cada tiempo de juego (10 seg, 30 seg, 40 seg y 60 seg) o la quinta es un multiplexor de selección de dichos tiempos. Estos tiempos se realizan mediante un contador de pulsos de reloj de la placa que son 50Mhz que son 20 ns, si queremos un tiempo de 10 segundos (10.000.000.000 ns), entonces no es más que hacer el siguiente cociente: 10.000.000.000 / 20 = 500.000.000 cuentas 1.1 Selector tiempo de juego:
Entidad que contiene los cinco componentes ya citados anteriormente. entity selector TiempoDeJuego is Port ( CLK : in std_logic; r st : in std_logic; seleccion:IN STD _ LOGIC _VECTOR(1 DOWNTO 0); output_tiempo_juego : out std_logic); end selector TiempoDeJuego; architecture STRUCTURAL of selector TiempoDeJuego is component contador 10seg is Port ( CLK : in std_logic; r st : in std_logic; output_ 10seg : out std_logic); end component; component contador30seg is Port ( CLK : in std_logic; r st : in std_logic; output_30seg : out std_logic); end component;
component contador40seg is Port ( CLK : in std_logic; r st : in std_logic; output_40seg : out std_logic); end component; component contador60seg is Port ( CLK : in std_logic; r st : in std_logic; output_60seg : out std_logic); end component; component muxSelector TiempoDeJuego is Port ( input_ 10seg : in std_logic; input_30seg : in std_logic; input_40seg : in std_logic; input_60seg : in std_logic; seleccion : in std_logic_vector (1 downto 0); salida _tiempo_juego : out std_logic); end component; SIGNAL SAL10S:std_logic; SIGNAL SAL30S:std_logic; SIGNAL SAL40S:std_logic; SIGNAL SAL1M:std_logic; SIGNAL SAL _ MUX:std_logic; begin TIEMPO _ 10S:contador 10seg PORT MAP( CLK=>CLK, output_ 10seg=>SAL10S, r st=>r st); TIEMPO _30S:contador30seg PORT MAP( CLK=>CLK, output_30seg=>SAL30S, r st=>r st); TIEMPO _40S:contador40seg PORT MAP( CLK=>CLK, output_40seg=>SAL40S, r st=>r st); TIEMPO _ 1M:contador60seg PORT MAP( CLK=>CLK, output_60seg=>SAL1M, r st=>r st); SELECTOR:muxSelector TiempoDeJuego PORT MAP( seleccion=>seleccion, input_ 10seg=>SAL10S, input_30seg=>SAL30S, input_40seg=>SAL40S, input_60seg=>SAL1M, salida _tiempo_juego=>SAL _ MUX);
output_tiempo_juego
View more...
Comments