• No se han encontrado resultados

Videojuego FPGA en VHDL

N/A
N/A
Protected

Academic year: 2021

Share "Videojuego FPGA en VHDL"

Copied!
21
0
0

Texto completo

(1)

 Videojuego FPGA en VHDL

 Videojuego FPGA en VHDL

Realizaremos paso a paso un sencillo ejemplo de entretenimiento para aprender a programar nuestra

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

FPGA, para ello usaremos la tarjeta de Xilinxs, Spartan III Starter Kit.

Kit.

Objetivo

Objetivo

Se trata de implementar un sencillo videojuego que ponga a prueba los reflejos del jugador. El 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

del juego se trata de atrapar a los escurridizos bits que irán apareciendo de forma aleatoria en los LED

(LD0, LD1, LD2). Para

(LD0, LD1, LD2). Para ello habrá que accionar los pulsadores (BTN0, BTN1, BTN2) mientras los LED

ello habrá que accionar los pulsadores (BTN0, BTN1, BTN2) mientras los LED

correspond

correspondientes estén todavía encendidos. La partida

ientes estén todavía encendidos. La partida se iniciará tras pulsar el

se iniciará tras pulsar el Reset del sistema (BTN3)

Reset del sistema (BTN3)

y durará 30 segundos. Los led permanecerán quietos durante 0.25 segundos antes de pasar a su siguiente

y durará 30 segundos. Los led permanecerán quietos durante 0.25 segundos antes de pasar a su siguiente

configuración.

configuración.

El visualizador de cuatro dígitos mostrará en todo momento el número de bits atrapados desde el

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 

comienzo de la partida.No será válido dejar los pulsadores permanentemente actuados (emplear 

monoestabl

monoestable no r

e no redisparable en estas entradas, por ejemplo,

edisparable en estas entradas, por ejemplo, versiones basadas en el circuito antirrebote

versiones basadas en el circuito antirrebote

que se menciona en las sugerencias).

que se menciona en las sugerencias).

Para generar la

Para generar la secuenci

secuencia pseudoaleatoría se

a pseudoaleatoría se empleará un LFSR

empleará un LFSR (Linear FeedBackShift

(Linear FeedBackShiftRegister). Los

Register). Los

circuitos LFSR se utilizan en infinidad de sistemas electronicos para generar secuencias pseudoaleatorias

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

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

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.

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

La elección de las salidas reañimentadas es fundamental para conseguir una máxima longitud de la

secuencia sin repeticione

secuencia sin repeticiones. Para

s. Para este trabajo emplearemo

este trabajo emplearemos un

s un LFSR de 31

LFSR de 31 bits realimentando las salidas

bits realimentando las salidas

2 y 30

2 y 30 (numerandol

(numerandolas desde cero),

as desde cero), lo que generará

lo que generará secuenc

secuencias sin repeticiones de a

ias sin repeticiones de aproximad

proximadamente

amente

2.200 millones de números. Utilizaremos las tres de menor peso como patrón para encender los led.

2.200 millones de números. Utilizaremos las tres de menor peso como patrón para encender los led.

Una característi

Una característica de los LFSR

ca de los LFSR es que quedan bloqueados si su contenido es cero. P

es que quedan bloqueados si su contenido es cero. P or ello es necesario

or ello es necesario

inicializarlos con una semilla (un valor distinto de cero).

inicializarlos con una semilla (un valor distinto de cero).

Mejoras realizadas:

Mejoras realizadas:

Inclusión de varios niveles de dificultad, aumentando y disminiyundo el tiempo que los leds permanecen

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.

(2)

Incluir varios niveles de dificultad aumentando o disminuyendo el número de leds que pueden

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

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.

contendrían los led a encender. La selección se realizará mediante los interruptores deslizantes.

Métodos empleados:

Métodos empleados:

Usar contadores BCD con acarreo y

Usar contadores BCD con acarreo y permiso para almacenar la puntuación. El contador sólo

permiso para almacenar la puntuación. El contador sólo contará en

contará en

los flancos de subida de se señal de reloj cuando el permiso esté a 1. El acarreo valdrá 1 mientras el

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 

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.

será el permiso del siguiente.

Emplear un único decodificador de 7 segmentos y la técnica de multiplexación (ver manual) para

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.

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

Usar un prescaler o divisor que genere a partir de los 50MHz disponibles en la placa las frecuencias

necesarias para la aplicación.

necesarias para la aplicación.

Incluir circuitos antirrebote en las entradas conectadas a pulsadores (ver

Incluir circuitos antirrebote en las entradas conectadas a pulsadores (ver "lenguaje Template

"lenguaje Templates"-

s"->"VHDL"->"Syn

>"VHDL"->"SynthesisTemplate

thesisTemplates"->"Debouncecircu

s"->"Debouncecircuit" en

it" en la

la herram

herramienta

ienta Xilinx ISE).

Xilinx ISE).

Manual 

Manual 

de

de

usuario 

usuario 

Primeramente vamos a explicar el procedimiento lineal que sigue el sistema para realizar el videojuego.

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

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.

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

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

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

a la vez, estas opciones de juego las seleccionaremos con los deslizadores de la tarjeta, tal y como

aparece a continuación:

aparece a continuación:

Duración de juego:

Duración de juego:

SW1 SW0 SW1 SW0 10 10 SEG SEG 0 0 00 30 30 SEG SEG 0 0 11 40 40 SEG SEG 1 1 00 60 60 SEG SEG 1 1 11

Velocidad de los leds:

Velocidad de los leds:

SW3 SW2 SW3 SW2 1 1 HZ HZ 0 0 00 2 2 HZ HZ 0 0 11 4 4 HZ HZ 1 1 00 8 8 HZ HZ 1 1 11

 Número de leds:

 Número de leds:

SW4 SW4 UN UN LED LED 11 VARIOS

(3)

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 

e

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

(4)

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.

Manual a 

anzado 

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;

(5)

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);

(6)

output_tiempo_juego<= SAL _ MUX; endStr uctur al;

1.2

Cont 

dor

10

segundos:

Contador es un acumulador de ciclos de reloj que pone a uno una salida el tiempo de dicho contador.

entity contador 10seg is

Port ( CLK : in std_logic; r st : in std_logic;

output_ 10seg : out std_logic); end contador 10seg;

architecture Behavior al of contador 10seg is

SIGNAL SALIDA _ TIEMPO _ COPY: STD _ LOGIC:='0'; SIGNAL ACU1:INTEGER RANGE 0 TO 500000000:=0; begin

output_ 10seg<=SALIDA _ TIEMPO _ COPY ; PROCESS(CLK,r st,salida _tiempo_copy,ACU1) BEGIN

IF r st'EVENT AND r st='0'THEN SALIDA _ TIEMPO _ COPY<='1'; END IF;

IF CLK'EVENT AND CLK='1' AND SALIDA _ TIEMPO _ COPY='1'THEN ACU1<=ACU1+1; END IF;

IF ACU1=500000000 AND SALIDA _ TIEMPO _ COPY='1' THEN SALIDA _ TIEMPO _ COPY<='0'; END IF;

IF ACU1=500000000 THEN ACU1<=0; END IF;

END PROCESS ; end Behavior al;

1.3

Cont 

dor

30

segundos:

Contador es un acumulador de ciclos de reloj que pone a uno una salida el tiempo de dicho contador.

entity contador30seg is

Port ( CLK : in std_logic; r st : in std_logic;

output_30seg : out std_logic); end contador30seg;

architecture Behavior al of contador30seg is SIGNAL SALIDA _ TIEMPO _ COPY: STD _ LOGIC;

SIGNAL ACU2:INTEGER RANGE 0 TO 1500000000:=0; begin

output_30seg<=SALIDA _ TIEMPO _ COPY ;

PROCESS(CLK,r st,SALIDA _ TIEMPO _ COPY,ACU2) BEGIN

IF r st'EVENT AND r st='0'THEN SALIDA _ TIEMPO _ COPY<='1'; END IF;

(7)

IF CLK'EVENT AND CLK='1' AND SALIDA _ TIEMPO _ COPY='1'THEN ACU2<=ACU2+1; END IF;

IF ACU2=1500000000 AND SALIDA _ TIEMPO _ COPY='1' THEN SALIDA _ TIEMPO _ COPY<='0'; END IF;

IF ACU2=1500000000 THEN ACU2<=0; END IF;

END PROCESS ; endBehavioral;

1.4

Cont 

dor

40

segundos:

Contador es un acumulador de ciclos de reloj que pone a uno una salida el tiempo de dicho contador.

entity contador40seg is

Port ( CLK : in std_logic; r st : in std_logic;

output_40seg : out std_logic); end contador40seg;

architecture Behavior al of contador40seg is SIGNAL SALIDA _ TIEMPO _ COPY: STD _ LOGIC;

SIGNAL ACU3:INTEGER RANGE 0 TO 2000000000:=0; begin

output_40seg<=SALIDA _ TIEMPO _ COPY ;

PROCESS(CLK,r st,SALIDA _ TIEMPO _ COPY,ACU3) BEGIN

IF r st'EVENT AND r st='0'THEN SALIDA _ TIEMPO _ COPY<='1'; END IF;

IF CLK'EVENT AND CLK='1' AND SALIDA _ TIEMPO _ COPY='1'THEN ACU3<=ACU3+1; END IF;

IF ACU3=2000000000 AND SALIDA _ TIEMPO _ COPY='1' THEN SALIDA _ TIEMPO _ COPY<='0'; END IF;

IF ACU3=2000000000 THEN ACU3<=0; END IF;

END PROCESS ; endBehavior al;

1.5

Cont 

dor 6

0

segundos:

Contador es un acumulador de ciclos de reloj que pone a uno una salida el tiempo de dicho contador.

entity contador60seg is

Port ( CLK : in std_logic; r st : in std_logic;

output_60seg : out std_logic); end contador60seg;

architecture Behavior al of contador60seg is SIGNAL SALIDA _ TIEMPO _ COPY: STD _ LOGIC;

(8)

SIGNAL ACU4:INTEGER RANGE 0 TO 1500000000:=0; SIGNAL ACU5:INTEGER RANGE 0 TO 10:=0;

--SIGNAL ACU5:REAL RANGE 0 TO 10:=0; begin

output_60seg<=SALIDA _ TIEMPO _ COPY ;

PROCESS(CLK,r st,SALIDA _ TIEMPO _ COPY,ACU4,ACU5) BEGIN

IF r st'EVENT AND r st='0'THEN SALIDA _ TIEMPO _ COPY<='1'; END IF;

IF CLK'EVENT AND CLK='1' AND SALIDA _ TIEMPO _ COPY='1'THEN ACU4<=ACU4+1; END IF;

IF ACU4=1500000000 AND SALIDA _ TIEMPO _ COPY='1' THEN  ACU5<=ACU5+1;

END IF;

IF ACU4=1500000000 AND ACU5=2 AND SALIDA _ TIEMPO _ COPY='1' THEN SALIDA _ TIEMPO _ COPY<='0';

END IF;

IF ACU4=1500000000 AND ACU5=2 AND SALIDA _ TIEMPO _ COPY='0' THEN  ACU5<=0;

END IF;

IF ACU4=1500000000 AND ACU5=0 AND SALIDA _ TIEMPO _ COPY='0' THEN  ACU5<=0;

END IF;

END PROCESS ; endBehavior al;

1.

6 Multiplexor selector de tiempo:

Selector  del contador que vamos a aplacar a nuestro juego, par a ello las entr adas de

selección son los deslizadores cero y uno

.

entity 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 muxSelector TiempoDeJuego;

architecture Behavior al of muxSelector TiempoDeJuego is SIGNAL O _ COPY: STD _ LOGIC;

begin

salida _tiempo_juego<=O _ COPY;

PROCESS (input_ 10seg,input_30seg,input_40seg,input_60seg,seleccion) BEGIN

IF seleccion="00" THEN O _ COPY<=input_ 10seg; END IF;

IF seleccion="01" THEN O _ COPY<=input_30seg; END IF;

IF seleccion="10" THEN O _ COPY<=input_40seg; END IF;

(9)

END IF; END PROCESS; endBehavior al;

2.- SELECTOR FRECUENCIAS LEDS:

Es la entidad encargada de sacar un tren de pulsos a una frecuencia determinada por el usuario mediante

los deslizadores dos y tres.

2.1

Selector de frecuenci

s leds:

Entidad compuesta por un multiplexor cuyas entradas de selección son los deslizadores dos y tres y otra

entidad denominada preescaler encargada de dividir la señal del reloj en un tren de pulsos a la frecuencia

seleccionada por el usuario.

Entity Selector FrecuenciaLeds is Port ( CLK : in std_logic;

ENABLE : in std_logic;

output_frecuencia _leds : out std_logic; seleccion : in std_logic_vector (1 downto 0)); end Selector FrecuenciaLeds;

architecture STRUCTURAL of Selector FrecuenciaLeds is component muxSelector FrecuenciaLeds is

Port ( input_ 1hz : in std_logic; input_ 2hz : in std_logic; input_4hz : in std_logic; input_8hz : in std_logic; enable : in std_logic;

seleccion : in std_logic_vector (1 downto 0); salida _frecuencia _leds : out std_logic); end component;

component preescaler is

Port ( input_ 50MHz : in std_logic;

output_8Hz : OUT std_logic; output_4Hz : OUT std_logic ; output_ 2Hz : OUT std_logic; output_ 1Hz : OUT std_logic);

end component; SIGNAL SAL8:std_logic; SIGNAL SAL4:std_logic; SIGNAL SAL2:std_logic; SIGNAL SAL1:std_logic; SIGNAL SAL _ MUX:std_logic; begin

SELECTOR:muxSelector FrecuenciaLeds PORT MAP(

(10)

enable=>ENABLE, input_ 1hz=>SAL1, input_ 2hz=>SAL2, input_4hz=>SAL4, input_8hz=>SAL8, salida _frecuencia _leds=>SAL _ MUX ); GENERATOR:preescaler PORT MAP( input_ 50MHz=>CLK, output_ 1HZ=>SAL1, output_ 2HZ=>SAL2, output_4HZ=>SAL4, output_8HZ=>SAL8); output_frecuencia _leds<= SAL _ MUX; end Structural;

2.2

Multiplexor selector de frecuenci

s leds:

Selección de frecuencia de los dependiendo de los deslizadores, cuyas entradas del multiplexor son las

salidas de las diferentes frecuencias del preescaler.

entity muxSelector FrecuenciaLeds is Port ( input_ 1hz : in std_logic;

input_ 2hz : in std_logic; input_4hz : in std_logic; input_8hz : in std_logic; enable : in std_logic;

seleccion : in std_logic_vector (1 downto 0); salida _frecuencia _leds : out std_logic); end muxSelector FrecuenciaLeds;

architecture Behavior al of muxSelector FrecuenciaLeds is SIGNAL O _ COPY: STD _ LOGIC;

begin salida _frecuencia _leds<=O _ COPY; PROCESS (input_ 1hz,input_ 2hz,input_4hz,input_8hz,enable,seleccion) BEGIN IF enable='0' THEN O _ COPY<='0'; END IF;

IF seleccion="00" AND enable='1' THEN O _ COPY<=input_ 1hz; END IF;

IF seleccion="01" AND enable='1' THEN O _ COPY<=input_ 2hz; END IF;

IF seleccion="10" AND enable='1' THEN O _ COPY<=input_4hz; END IF;

IF seleccion="11" AND enable='1' THEN O _ COPY<=input_8hz; END IF;

END PROCESS; endBehavior al;

(11)

Entidad constituida por un divisor de ocho hercios y divisores de frecuencia a la mitad.

entity preescaler is

Port ( input_ 50MHz : in std_logic;

output_8Hz : OUT std_logic; output_4Hz : OUT std_logic ; output_ 2Hz : OUT std_logic; output_ 1Hz : OUT std_logic);

end preescaler;

architecture Str uctur al of preescaler is component divisor8Hz is

Port ( CLK : in std_logic;

output_8hz : out std_logic); end component;

component divisor FrecuenciaMitad is Port ( CLK : in std_logic;

SALIDA : out std_logic); end component; SIGNAL SAL8HZ:std_logic; SIGNAL SAL4HZ:std_logic; SIGNAL SAL2HZ:std_logic; SIGNAL SAL1HZ:std_logic; begin

PRIMER _ DIVISOR:divisor8Hz PORT MAP(

CLK=>input_ 50MHz, output_8hz=>SAL8HZ); SEGUNDO _ DIVISOR: divisor FrecuenciaMitad PORT MAP(

CLK=>SAL8HZ, SALIDA=>SAL4HZ); TERCER _ DIVISOR: divisor FrecuenciaMitad PORT MAP(

CLK=>SAL4HZ, SALIDA=>SAL2HZ); CUARTO _ DIVISOR: divisor FrecuenciaMitad PORT MAP(

CLK=>SAL2HZ, SALIDA=>SAL1HZ); output_8Hz <=SAL8HZ; output_4Hz <=SAL4HZ; output_ 2Hz <=SAL2HZ; output_ 1Hz <=SAL1HZ; endStr uctur al;

(12)

Este componente tiene como entrada la salida del divisor de 8Hz, dicha entrada que es un tren de pulsos

la divide cada 4 pulsos para generar un nievo tren de pulsos con la mitad de frecuencia y así

sucesivamente con los continuos divisores de frecuencias ya que están dispuestos en serie unos con los

otros.

entity divisor FrecuenciaMitad is Port ( CLK : in std_logic;

SALIDA : out std_logic); end divisor FrecuenciaMitad;

architecture Behavior al of divisor FrecuenciaMitad is SIGNAL SAL _ COPY: STD _ LOGIC:='0'; SIGNAL ACU:INTEGER RANGE 0 TO 10:=0; begin

SALIDA<=SAL _ COPY; PROCESS(CLK) BEGIN

IF CLK'EVENT AND CLK='1' THEN ACU<=ACU+1; END IF;

IF ACU=4 AND SAL _ COPY='0' THEN SAL _ COPY<='1'; END IF;

IF ACU=4 AND SAL _ COPY='1' THEN SAL _ COPY<='0'; END IF;

IF ACU=4 THEN ACU<=0; END IF;

END PROCESS; endBehavior al;

2.3.2 Divisor 8 Hz:

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 8Hz (125.000.000 ns ), entonces no es más que hacer el siguiente cociente:

125.000.000 / 20 = 6.250.000 cuentas

Si 6.250.000 cuentas las dividimos entre dos para hacer un tren de pulsos y dar un pulso alto cada

6.250.000 cuentas, lo que quiere decir que cada 3.125.000 cuentas invertimos el pulso pasando de alto a

 bajo así generamos un pulso de nivel alto cada 8 Hz.

entity divisor8Hz is Port ( CLK : in std_logic;

output_8hz : out std_logic); end divisor8Hz;

architecture Behavior al of divisor8Hz is

SIGNAL SAL8_ COPY: STD _ LOGIC:='0';

SIGNAL ACU:INTEGER RANGE 0 TO 35000000:=0; begin

(13)

PROCESS(CLK,SAL8_ COPY,ACU) BEGIN

IF CLK'EVENT AND CLK='1' THEN ACU<=ACU+1; END IF;

IF ACU=3125000 AND SAL8_ COPY='0' THEN SAL8_ COPY<='1'; END IF;

IF ACU=3125000 AND SAL8_ COPY='1' THEN SAL8_ COPY<='0'; END IF;

IF ACU=3125000 THEN ACU<=0; END IF;

END PROCESS; endBehavior al;

3.- MONOESTABLE:

Entidad encargada de estabilizar las entradas asincronas y convertirlas en salidas síncronas ya que tiene

como entrada habilitadora la salida del selector de frecuencias.

entity monoestable is

Port ( pulsadores : in std_logic_vector (2 downto 0); enable : in std_logic;

output_mon : out std_logic_vector (2 downto 0) );

end monoestable;

architecture Behavior al of monoestable is begin

PROCESS(enable,pulsadores) begin

if ENABLE'EVENT AND enable='1' then output_mon<="000"; end if;

if pulsadores(0)='1' then output_mon(0)<='1'; end if;

if pulsadores(1)='1' then output_mon(1)<='1'; end if;

if pulsadores(2)='1' then output_mon(2)<='1'; end if;

end PROCESS; end Behavior al;

4.- SALIDA ALEATORIA:

Consiste en la implementación del circuito LFSR propuesto en la documentación del trabajo.

entity salidaAleatoria is

Port ( CLK : in std_logic;

r st : in std_logic;

puls _ aleat_ 0 : out std_logic; puls _ aleat_ 1 : out std_logic;

(14)

puls _ aleat_ 2 : out std_logic); end salidaAleatoria;

architecture Behavior al of salidaAleatoria is begin

PROCESS (r st, clk)

V ARIABLE sr : std_logic_vector (30 DOWNTO 0); BEGIN

IF r st = '1' THEN

sr := "0100101010110100010110100100110"; ELSIF clk = '1' AND clk'event THEN

sr := sr (29 DOWNTO 0) & (sr (1) XOR sr (30)); END IF; puls _ aleat_ 0 <= sr (0); puls _ aleat_ 1 <= sr (1); puls _ aleat_ 2 <= sr (2); END PROCESS; endBehavior al;

5.- COMPARADOR:

Componente que como bien dice su nombre compara dos entradas de arrays de vectores de dimensión

tres, cuya salida será un flanco de subida si la comparación es correcta y un flanco de bajada si la

comparación es errónea.

entity compar ador is

Port ( inputa _comp : in std_logic_vector (2 downto 0); inputb _comp : in std_logic_vector (2 downto 0); output_comp : out std_logic);

end compar ador;

architecture Behavior al of compar ador is begin

PROCESS(inputa _comp,inputb _comp) BEGIN

IF inputa _comp=inputb _comp THEN output_comp<='1'; ELSE output_comp<='0';

END IF; END PROCESS; end Behavior al;

6.- CODIFICADOR:

Componente encargado de codificar la señal aleatoria que le llega del LFSR para así encender un único

led.

(15)

entity codificador is

Port ( input_cod : in std_logic_vector (2 downto 0); output_cod : out std_logic_vector (2 downto 0)); end codificador;

architecture Behavior al of codificador is begin

process(input_cod) begin

if input_cod="000" then output_cod<="000" ; elsif input_cod="001" then output_cod<="000" ; elsif input_cod="010" then output_cod<="001" ; elsif input_cod="011" then output_cod<="001" ; elsif input_cod="100" then output_cod<="010" ; elsif input_cod="101" then output_cod<="010" ; elsif input_cod="110" then output_cod<="100" ; else output_cod<="100" ;

end if; end process; endBehavior al;

7.- MULTIPLEXOR ENCENDER LEDS:

Este componente es el encargado de realizar la selección de las entradas que le llegan o bien del

monoestable de la salida aleatoria, del monoestable de la salida de los botones y de los comparadores.

La salida del multiplexor  representa la salida de los leds que se van a encender  y si se ha producido o no el acierto del jugador o lo que es lo mismo si la compar ación ha sido correcta.

entity muxEncender Leds is Port ( A1 : in std_logic;  A2 : in std_logic; B1 : in std_logic; B2 : in std_logic; C1 : in std_logic; C2 : in std_logic; D1 : in std_logic; D2 : in std_logic; seleccion : in std_logic;  A : out std_logic;

B : out std_logic; C : out std_logic; D : out std_logic); end muxEncender Leds;

architecture Behavior al of muxEncender Leds is SIGNAL OUTA _ COPY : std_logic; SIGNAL OUTB _ COPY : std_logic; SIGNAL OUTC _ COPY : std_logic; SIGNAL OUTD _ COPY : std_logic; begin

 A <=OUTA _ COPY; B <=OUTB _ COPY;

(16)

C <=OUTC _ COPY; D <=OUTD _ COPY; PROCESS( A1,A2,B1,B2,C1,C2,D1,D2,seleccion) BEGIN IF seleccion='0' THEN OUTA _ COPY<=A1; ELSE OUTA _ COPY<=A2; END IF; IF seleccion='0' THEN OUTB _ COPY<=B1; ELSE OUTB _ COPY<=B2; END IF; IF seleccion='0' THEN OUTC _ COPY<=C1; ELSE OUTC _ COPY<=C2; END IF; IF seleccion='0' THEN OUTD _ COPY<=D1; ELSE OUTD _ COPY<=D2; END IF; END PROCESS; end Behavior al;

8.- CONTADOR:

Entidad constituida por una serie de componentes denominados sumador de display, sumador de aciertos

y habilitación.

entity contador is

Port ( acierto : in std_logic; r st : in std_logic;

pulsadores : in std_logic_vector  (2 downto 0); d0 : out std_logic_vector (6 downto 0);

d1 : out std_logic_vector (6 downto 0); d2 : out std_logic_vector (6 downto 0)); end contador;

architecture Str uctur al of contador is component sumador De Aciertos is

Port ( r st : in std_logic;

salida : out integer  r ange 0 to 9:=0;

carry : out std_logic; suma : in std_logic);

end component;

component habilitacion is

(17)

acierto : in std_logic;

salida _habilitacion : out std_logic); end component;

component sumador Displays is

Port ( entr ada : integer  r ange 0 to 9;

salida : out std_logic_vector (6 downto 0)); end component;

signal salida0 _copy:integer  r ange 0 to 9; signal salida1 _copy:integer  r ange 0 to 9; signal salida2 _copy:integer  r ange 0 to 9; signal carry0 _copy:std_logic;

signal carry1 _copy:std_logic; signalhabilitacion_copy :std_logic; begin

PRIMER _contador :sumador De Aciertos PORT MAP( r st=>r st,

carry =>carry0 _copy, suma=>habilitacion_copy, salida=>salida0 _copy); segundo_contador :sumador De Aciertos PORT MAP(

r st=>r st,

carry =>carry1 _copy, suma=> carry0 _copy, salida=>salida1 _copy); tercer_contador :sumador De Aciertos PORT MAP(

r st=>r st,

suma=> carry1 _copy, salida=>salida2 _copy); deco0: sumador Displays PORT MAP(

entr ada=>salida0 _copy , salida=>d0);

deco1: sumador Displays PORT MAP(

entr ada=>salida1 _copy , salida=>d1);

deco2: sumador Displays PORT MAP(

entr ada=>salida2 _copy , salida=>d2);

habilit: habilitacion PORT MAP(

pulsadores=>pulsadores , acierto=>acierto,

salida _habilitacion=>habilitacion_copy); endStr uctur al;

(18)

8.1

Sum

dor de

ciertos:

Contador de pulsos que te llegan de la salida del componente habilitación, el cual tiene una entrada del

 botón reset para poner a cero el contador. El su mador está constituido por 3 sumadores encargados cada

uno de realizar hasta un total de 999 aciertos, ya que cuando el sumador de unidad se desborda tiene una

salida de carrier que le llega al siguiente sumador y así sucesivamente.

entity sumador De Aciertos is Port ( r st : in std_logic;

salida : out integer  r ange 0 to 9:=0;

carry : out std_logic; suma : in std_logic);

end sumador De Aciertos;

architecture Behavior al of sumador De Aciertos is signal cont_copy: integer  r ange 0 to 9 :=0 ; signal carry_copy: std_logic:='0' ;

begin

salida<=cont_copy;

carry<= carry_copy; process(suma,r st)

begin

if suma'event and suma='1' and r st='0' then if cont_copy<9 then cont_copy<=cont_copy+1; carry_copy<='0'; end if; if cont_copy=9 then carry_copy<='1'; cont_copy<=0; end if; end if; if r st='1' then cont_copy<=0; carry_copy<='0'; end if; end process; endBehavior al;

8.2

Sum

dor displ

ay

s:

Es un codificador que tiene como entrada la suma de los aciertos y como salida la codificación que le

corresponde a cada número respecto a los displays de la placa.

entity sumador Displays is

Port ( entr ada : integer  r ange 0 to 9;

salida : out std_logic_vector (6 downto 0)); end sumador Displays;

(19)

begin process(entr ada) begin case entr ada is when 0 => salida <="0000001"; when 1 => salida <="1001111"; when 2 => salida <="0010010"; when 3 => salida <="0000110"; when 4 => salida <="1001100"; when 5 => salida <="0100100"; when 6 => salida <="0100000"; when 7 => salida <="0001111"; when 8 => salida <="0000000"; when 9 => salida <="0000100"; when other s => salida <="1111110"; end case; end process; endBehavioral;

8.3

H

ab

ilit 

ción:

Componente encargado de asegurarnos que el usuario a pulsado algún botón y si el botón a sido pulsado

y se ha producido un acierto, este saca un pulso alto, el cual será contado por el sumador de aciertos.

entityhabilitacionis

Port ( pulsadores : in std_logic_vector (2 downto 0); acierto : in std_logic;

salida _habilitacion : outstd_logic); endhabilitacion;

architecture Behavior al of habilitacion is begin

process(acierto,pulsadores) begin

IF pulsadores/="000" AND acierto='1' THEN salida _habilitacion<=acierto; end if;

if pulsadores="000" then salida _habilitacion<='0'; END IF;

end process; endBehavior al;

(20)

9.- MULTIPLEXOR DISPLAY:

La disposición de la placa respecto a los display no es tener una un array de conexiones para cada

display, sino tener un solo array de conexiones para los tres display y multiplexar la salida. Para ellos se

realiza un multiplexor que tenga como entradas las señales numéricas de los tres display para luego

conmutarlos a una velocidad que al ojo humano piense que es continuo (aprox 15 fps).

Para dicha conmutación se ha realizado un componente denominado conmutador display el cual ataca a

las entradas de selección del multiplexor de displays.

entity muxDisplays is

Port ( d0 : in std_logic_vector (6 downto 0); d1 : in std_logic_vector (6 downto 0); d2 : in std_logic_vector (6 downto 0); display : out std_logic_vector (6 downto 0); a : in std_logic;

b : in std_logic; c : in std_logic); end muxDisplays;

architecture Behavior al of muxDisplays is begin

process(a,b,c,D0,D1,D2) begin

if c='1' and b='1' and a='0' then display <= d0; end if;

if c='1' and b='0' and a='1' then display <= d1; end if;

if c='0' and b='1' and a='1' then display <= d2; end if;

end process; endBehavior al;

10.- CONMUTADOR DISPLAY:

Teniendo en cuenta que los displays se activan mediante lógica negativa ( enable = 0 ), se conmutan

estos cada cierto tiempo, para ellos se ha realizado un contador de pulsos de reloj de la placa.

entity conmutador Display is Port ( CLK : in std_logic;

 A : OUT std_logic; B : OUT std_logic;

C : OUT std_logic); end conmutador Display;

architecture Behavior al of conmutador Display is

SIGNAL ACUMULADOR:INTEGER RANGE 0 TO 300000:=0; SIGNAL A _ COPY:std_logic:='0'; SIGNAL B _ COPY:std_logic:='1'; SIGNAL C _ COPY:std_logic:='1'; begin PROCESS(CLK) BEGIN

(21)

IF CLK'EVENT AND CLK='1' THEN ACUMULADOR<=ACUMULADOR+1; IF ACUMULADOR=299999 THEN ACUMULADOR<=0;

END IF; IF ACUMULADOR<100000 THEN  A _ COPY<='0'; B _ COPY<='1'; C _ COPY<='1'; END IF;

IF ACUMULADOR>99999 AND ACUMULADOR<200000 THEN  A _ COPY<='1'; B _ COPY<='0'; C _ COPY<='1'; END IF; IF ACUMULADOR>199999 THEN  A _ COPY<='1'; B _ COPY<='1'; C _ COPY<='0'; END IF; END IF; END PROCESS;  A<=A _ COPY; B<=B _ COPY; C<=C _ COPY; endBehavior al;

isposición ord 

e

nada d 

e b 

loqu 

e

eñ 

al 

e

Podemos ver que se ha dispuesto un documento anexo en pdf en el apartado descarga de este link, donde

se encuentran las señales, entradas y salidas y bloques de forma ordenada para poder seguir de forma

fácil y sencilla todo el proceso.

Referencias

Documento similar