-
Notifications
You must be signed in to change notification settings - Fork 1
/
simon_dice.vhd
executable file
·343 lines (321 loc) · 14.5 KB
/
simon_dice.vhd
1
2
3
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
----------------------------------------------------------------------------------
-- Company: University of Seville
-- Engineer: Santiago Fernandez Scagliusi
--
-- Create Date: 19:48:39 05/25/2019
-- Design Name: Main
-- Module Name: simon_dice - Behavioral
-- Project Name: Simon Game
-- Target Devices: Nexys 4 DDR
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity simon_dice is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
btnu : in STD_LOGIC;
btnd : in STD_LOGIC;
btnr : in STD_LOGIC;
btnl : in STD_LOGIC;
btnc : in STD_LOGIC;
inicio_juego : in STD_LOGIC;
fila : out STD_LOGIC_VECTOR (7 downto 0);
col : out STD_LOGIC_VECTOR (7 downto 0);
led_r : out STD_LOGIC;
led_g : out STD_LOGIC;
led_b : out STD_LOGIC;
an : out STD_LOGIC_VECTOR (7 downto 0);
ca : out STD_LOGIC;
cb : out STD_LOGIC;
cc : out STD_LOGIC;
cd : out STD_LOGIC;
ce : out STD_LOGIC;
cf : out STD_LOGIC;
cg : out STD_LOGIC);
end simon_dice;
architecture Behavioral of simon_dice is
COMPONENT lfsr16
PORT(
clk : IN std_logic;
reset : IN std_logic;
secuencia : OUT std_logic_vector(15 downto 0)
);
END COMPONENT;
COMPONENT ram_datos
PORT(
clk : IN std_logic;
wea : IN std_logic;
ena : IN std_logic;
enb : IN std_logic;
addra : IN std_logic_vector(6 downto 0);
addrb : IN std_logic_vector(6 downto 0);
dia : IN std_logic_vector(2 downto 0);
doa : OUT std_logic_vector(2 downto 0);
dob : OUT std_logic_vector(2 downto 0)
);
END COMPONENT;
COMPONENT Rom_simon
PORT(
addr_fila : IN std_logic_vector(5 downto 0);
data_fila : OUT std_logic_vector(7 downto 0)
);
END COMPONENT;
COMPONENT bcd7seg
PORT(
clk : IN std_logic;
reset : IN std_logic;
ud : IN std_logic_vector(3 downto 0);
dec : IN std_logic_vector(3 downto 0);
cen : IN std_logic_vector(3 downto 0);
an : OUT std_logic_vector(7 downto 0);
ca : OUT std_logic;
cb : OUT std_logic;
cc : OUT std_logic;
cd : OUT std_logic;
ce : OUT std_logic;
cf : OUT std_logic;
cg : OUT std_logic
);
END COMPONENT;
COMPONENT bin2bcd
PORT(
clk : IN std_logic;
reset : IN std_logic;
nivel : IN std_logic_vector(6 downto 0);
ud : OUT std_logic_vector(3 downto 0);
dec : OUT std_logic_vector(3 downto 0);
cen : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;
COMPONENT debounce_cod
PORT(
clk : IN std_logic;
btnu : IN std_logic;
btnd : IN std_logic;
btnr : IN std_logic;
btnl : IN std_logic;
btnc : IN std_logic;
cod : OUT std_logic_vector(2 downto 0)
);
END COMPONENT;
signal cont : unsigned(16 downto 0);
signal clk_mostrar : unsigned(25 downto 0); -- Tiempo de muestra de figuras por la matriz de LEDs
signal clk_apagar : unsigned(24 downto 0); -- Tiempo de apagado de la matriz de LEDs
signal secuencia : std_logic_vector(15 downto 0); -- Secuencia generada por el lfsr_16
signal sec_cargada : std_logic; -- Bandera que indica secuencia cargada en la RAM
signal sec_cont : unsigned(3 downto 0) := "0000"; -- Contador de espera de 8 ciclos entre cada dato de secuencia
signal sec_dato : unsigned(6 downto 0) := "0000000"; -- Contador de cantidad de datos cargados (de 0 a 127)
signal wea, ena, enb : std_logic; -- Señales de habilitacion y escritura de la RAM
signal addra, addrb : std_logic_vector(6 downto 0) := "0000000"; -- Entrada de direccion de la RAM
signal dia, doa, dob : std_logic_vector(2 downto 0); -- Datos de entrada y salida de la RAM
signal addr_fila : std_logic_vector(5 downto 0) := "000000"; -- Entrada de direccion de la ROM
signal data_fila : std_logic_vector(7 downto 0) := "00000000"; -- Dato de salida de la ROM
type tipo_estado is (inicio, mostrar, apagar, espera_boton, boton_pulsado, comparar, error); -- Estados del proceso principal
signal estado : tipo_estado;
signal cod: std_logic_vector(2 downto 0) := "000"; -- Salida de debounce que señala que boton se ha pulsado
signal copia: std_logic_vector(2 downto 0) := "000"; -- Copia el valor de cod para analizar en otro momento
signal ud, dec, cen: std_logic_vector(3 downto 0) := "0000";
signal nivel: std_logic_vector(6 downto 0); -- Señal que marca el nivel actual
signal nivel_aux: unsigned(6 downto 0) := "0000000"; -- Señal auxiliar para convertir nivel en unsigned
signal enciende_fila : std_logic_vector(2 downto 0); -- 3 LSB que se incrementaran para encender la fila correspondiente y para recorrer la ROM
signal i : unsigned(6 downto 0); -- Indice para recorrer toda la secuencia almacenada en la RAM
signal cargar : std_logic; -- Bandera para activar la carga de la secuencia
begin
Inst_lfsr16: lfsr16 PORT MAP(
clk => clk,
reset => reset,
secuencia => secuencia
);
Inst_ram_datos: ram_datos PORT MAP(
clk => clk,
wea => wea,
ena => ena,
enb => enb,
addra => addra,
addrb => addrb,
dia => dia,
doa => doa,
dob => dob
);
Inst_Rom_simon: Rom_simon PORT MAP(
addr_fila => addr_fila,
data_fila => data_fila
);
Inst_bcd7seg: bcd7seg PORT MAP(
clk => clk ,
reset => reset ,
ud => ud ,
dec => dec ,
cen => cen ,
an => an ,
ca => ca ,
cb => cb ,
cc => cc ,
cd => cd ,
ce => ce ,
cf => cf ,
cg => cg
);
Inst_bin2bcd: bin2bcd PORT MAP(
clk => clk ,
reset => reset ,
nivel => nivel ,
ud => ud ,
dec => dec ,
cen => cen
);
Inst_debounce_cod: debounce_cod PORT MAP(
clk => clk ,
btnu => btnu ,
btnd => btnd ,
btnr => btnr ,
btnl => btnl ,
btnc => btnc ,
cod => cod
);
contador: process (clk, reset) -- Contador para encender las filas de la matriz de LEDs con una frecuencia mas lenta
begin
if reset = '1' then
cont <= (others => '0');
elsif rising_edge(clk) then
cont <= cont + 1;
end if;
end process;
enciende_fila <= std_logic_vector(cont(16 downto 14));
addr_fila <= (dob & enciende_fila) when estado = mostrar else -- 3 MSB indican la figura a mostrar + 3 LSB que se incrementan continuamente
("101" & enciende_fila) when estado = error else -- Si esta en estado error, muestra la cruz
("111" & enciende_fila); -- Si no esta en el estado de mostrar apaga matriz (111 = codigo de apagar)
col <= data_fila; -- En cada momento se iluminara la columna que diga la ROM por su salida data_fila
fila <= "00000001" when enciende_fila = "000" else -- Se encendera la fila correspondiente de forma continua
"00000010" when enciende_fila = "001" else
"00000100" when enciende_fila = "010" else
"00001000" when enciende_fila = "011" else
"00010000" when enciende_fila = "100" else
"00100000" when enciende_fila = "101" else
"01000000" when enciende_fila = "110" else
"10000000" when enciende_fila = "111";
nivel <= std_logic_vector(nivel_aux);
addrb <= std_logic_vector(i); -- Obtiene por la salida dob la figura correspondiente al nivel i
P_carga_secuencia:process(clk, reset) -- Guarda la secuencia generada por lsfr16 en la RAM
begin
if (reset = '1') then
sec_dato <= (others => '0');
sec_cont <= (others => '0');
sec_cargada <= '0';
elsif rising_edge(clk) then
if cargar = '1' then -- Juego iniciado, cargar secuencia
if sec_dato < 127 then -- Secuencia incompleta, seguir
if sec_cont = 8 then -- Pasados 8 ciclos
sec_cont <= (others => '0'); -- Reinicia contador
if (secuencia(15 downto 13) < "101") then -- Codigo valido (4 flechas y 1 circulo = 5 figuras)
wea <= '1'; -- Configura puerto A de RAM como escritura
ena <= '1'; -- Enable puerto A RAM
addra <= std_logic_vector(sec_dato); -- Señala fila a escribir en RAM
dia <= secuencia(15 downto 13); -- Data Input A. Escribe codigo en RAM
sec_dato <= sec_dato + 1; -- Incrementa contador de datos cargados
end if;
else
sec_cont <= sec_cont + 1; -- Todavia no pasaron 8 ciclos
end if;
else -- Secuencia completa guardada (128 datos)
wea <= '0'; -- Desactiva escritura puerto A RAM
ena <= '0'; -- Deshabilita puerto A RAM
sec_cargada <= '1'; -- Secuencia cargada, continuar juego
end if;
end if;
end if;
end process;
Pprincipal: process (clk, reset)
begin
if reset = '1' then
cargar <= '0';
i <= (others => '0');
nivel_aux <= (others => '0');
clk_mostrar <= (others => '0');
clk_apagar <= (others => '0');
estado <= inicio;
led_b <= '0';
led_g <= '0';
led_r <= '0';
elsif rising_edge(clk) then
case estado is
when inicio => -- Inicializacion. Carga secuencia en RAM
if inicio_juego = '1' then -- Switch de inicio de juego activado
cargar <= '1'; -- Bandera para cargar secuencia (proceso P1_secuencia)
if sec_cargada = '1' then -- Secuencia cargada completamente
cargar <= '0'; -- Desactiva bandera de carga
estado <= mostrar; -- Salta a estado de pedir dato
end if;
end if;
when mostrar => -- Carga figura de la RAM y la muestra por la matriz de LEDs
led_b <= '0'; -- Apaga el LED azul por si viene del estado comparar
if i <= nivel_aux then -- Se han cargado todas las figuras hasta el nivel actual?
enb <= '1'; -- No. Activar lectura del puerto B de la RAM
if clk_mostrar < 40000000 then -- Ha pasado 1 segundo?
clk_mostrar <= clk_mostrar + 1; -- No. Incrementa contador
else
clk_mostrar <= (others => '0'); -- Si. Reinicia contador
i <= i + 1; -- Incrementa indice
estado <= apagar; -- Salta a estado apagar
end if;
else
i <= (others => '0'); -- Mostradas todas las figuras. Limpia indice
estado <= espera_boton; -- Ahora comparara los botones pulsados por el jugador
end if;
when apagar => -- El apagado se hace de forma concurrente (Ver asignacion de addr_fila)
if clk_apagar < 20000000 then -- Han pasado 0,5 segundos?
clk_apagar <= clk_apagar + 1; -- No. Incrementa contador
else
clk_apagar <= (others => '0'); -- Si. Reinicia contador
estado <= mostrar; -- Vuelve a estado mostrar para obtener otra figura
end if;
when espera_boton =>
led_b <= '1'; -- Enciende LED azul para indicar que el jugador puede empezar a pulsar los botones
if cod /= "110" then -- Se ha pulsado algun boton? (Cod = 110 es ningun boton pulsado)
copia <= cod; -- Si. Copia el valor del pulsador
estado <= boton_pulsado;
end if; -- No. Permanece en este estado hasta que se pulse
when boton_pulsado =>
if cod = "110" then -- Se ha soltado el pulsador?
estado <= comparar; -- Si. Entonces compara valor
end if; -- No. Permanece en este estado hasta que se suelte
when comparar => -- Compara los botones pulsados con la figura correspondiente al nivel. Compara solo 1 cada vez que entra en el estado
if (copia = dob) then -- Pulsador correcto?
if i < nivel_aux then
i <= i + 1; -- Si. Incrementa indice
estado <= espera_boton; -- Vuelve para esperar siguiente boton a comparar
else
led_b <= '0'; -- Secuencia introducida correctamente
led_g <= '1'; -- Enciende LED verde
nivel_aux <= nivel_aux + 1; -- Sube de nivel
i <= (others => '0'); -- Reinicia indice
estado <= mostrar; -- Vuelve a mostrar toda la secuencia + una figura adicional
end if;
else
estado <= error; -- No. Salta a estado de error
end if;
when error => -- Pulsador incorrecto. Juego terminado
led_b <= '0'; -- Apaga LED azul
led_g <= '0'; -- Apaga LED verde
led_r <= '1'; -- Enciende LED rojo
i <= (others => '0'); -- Reinicia indice
end case;
end if;
end process;
end Behavioral;