Tabla de contenido:

VHDL Basys3: Juego Connect 4: 5 pasos
VHDL Basys3: Juego Connect 4: 5 pasos

Video: VHDL Basys3: Juego Connect 4: 5 pasos

Video: VHDL Basys3: Juego Connect 4: 5 pasos
Video: Install Vivado board files for Basys 3, Nexys 4, Arty, Genesys 2, Zybo, and Zedboard 2024, Noviembre
Anonim
VHDL Basys3: Juego Connect 4
VHDL Basys3: Juego Connect 4

Introducción:

Este es un juego de lógica digital Connect 4 diseñado en VHDL usando el software Vivado y programado en la placa Basys3. La construcción y el diseño de este proyecto es intermedio, pero los recién llegados pueden copiar los pasos y construir el juego digital.

El juego funciona como el juego Connect 4. Los jugadores pueden mover el cursor por la pantalla usando los botones izquierdo y derecho que se encuentran en el tablero. Al presionar el botón central en el tablero, el jugador colocará su marcador en esa columna y luego se convertirá en el turno del siguiente jugador. Una vez que un jugador gana, el juego se puede reiniciar presionando el botón hacia arriba en el tablero.

Paso 1: Detalles y materiales rápidos

Detalles técnicos rápidos:

  • Utiliza tres conjuntos de conexiones PMOD en la placa (JA, JB, JC)

    • 8 pines (sin incluir los pines Vcc y GND) utilizados para cada conector PMOD
    • JA - Control de filas
    • JB - Control de columnas verdes
    • JC - Control de columnas rojas
  • El reloj de pantalla funciona a 960 Hz

    Solo hay 8 LED encendidos a la vez. La pantalla se actualiza a una velocidad de reloj lo suficientemente rápida que da la ilusión de que hay más de 8 LED encendidos en un momento dado

  • El reloj de botón funciona a 5 Hz; Opcionalmente se puede afinar mediante la edición del código VHDL.
  • La resistencia interna de las matrices Darlington es suficiente para evitar que los LED se quemen

El juego se construye utilizando los siguientes componentes y herramientas:

  • (1) Tablero Basys3
  • (2) Matriz LED Bicolor 8x5:
  • (2) ULN2803 - Matrices de transistores Darlington - Ficha técnica
  • Carretes de alambre
  • Cables de puente
  • Pelacables
  • Protoboards (un cuadrado grande debería ser suficiente)
  • Multímetro y fuente de alimentación (solución de problemas)

Paso 2: Conexión del hardware

Conexión del hardware
Conexión del hardware
Conexión del hardware
Conexión del hardware

Pautas:

El cableado del proyecto puede ser extremadamente complicado, tómese su tiempo y verifique que todas las conexiones sean correctas, un juego a la vez.

El proyecto implica el uso de dos pantallas LED pero se combinan para formar una pantalla grande. Esto se puede lograr conectando todas las filas al mismo punto. Debido a que cada pantalla es bicolor, las filas roja y verde de una pantalla también deben estar vinculadas a las filas roja y verde de la otra pantalla. Al hacer esto, podemos controlar todas las filas con solo 8 pines. Los otros 16 pines se utilizan para controlar las columnas de la pantalla. Los 8 pines para el se pueden conectar directamente mediante cables de puente a los conectores pmod. Las conexiones Pmod van primero a la entrada del ULN2083A y la salida del ULN2083A se conecta directamente a la columna en la pantalla. Debido a que el diseño es de 8x8, algunas columnas no estarán conectadas físicamente.

  • JA: Conexiones de fila: Fila 1 a JA: 1 a Fila 8 para JA: 10.
  • JA: Conexiones de la columna roja:
  • JC: conexiones de columna verde

Consulte las imágenes publicadas para saber qué pines corresponden a qué filas / columnas.

Nota: Los transistores tienen resistencias integradas, por lo que los LED no requieren resistencia adicional para conectarse a ellos en serie.

Paso 3: Explicación técnica: Pantalla

La pantalla funciona con la persistencia de la visión. La pantalla se actualiza tan rápido que el ojo humano no puede detectar visiblemente que algunos LED se apagan y encienden rápidamente. De hecho, al ralentizar el reloj de la pantalla, se puede notar el parpadeo.

La pantalla enciende las ocho filas de acuerdo con los datos almacenados para esas filas, y la pantalla enciende una columna. Luego, pasa rápidamente a la siguiente entrada de datos para las ocho filas y enciende la siguiente columna, mientras que todas las demás columnas están desactivadas. Este proceso continúa a una velocidad de reloj lo suficientemente rápida como para que el parpadeo del LED se vuelva imperceptible.

El almacenamiento de datos para la pantalla se inicializa inmediatamente después de la arquitectura en el archivo VHDL de la siguiente manera:

señal RedA, RedB, RedC, RedD, RedE, RedF, RedG, RedH: std_logic_vector (7 downto 0): = "00000000";

señal GreenA, GreenB, GreenC, GreenD, GreenE, GreenF, GreenG, GreenH: std_logic_vector (7 downto 0): = "00000000"; - Datos de fila dependiendo de la columna: VERDE

A continuación, un pequeño fragmento del proceso que controla la matriz de la pantalla LED.

- Proceso que controla la visualización de la matriz de la pantalla LED: proceso (ColCLK) - 0 - 16 para actualizar la variable matricial 8X8 RED y 8x8 GREEn RowCount: rango de números enteros 0 a 16: = 0; comenzar si (aumento_de_borde (ColCLK)) luego si (RowCount = 0) entonces DORow <= RedA; - Datos de fila para la columna correspondiente DOCol <= "1000000000000000"; - Activador de columna - Repita este código hasta "0000000000000001" - Cambie a RedB, RedC… GreenA, GreenB… GreenH

Al final de GreenH, justo antes de que finalice el proceso, se incluye este fragmento para restablecer RowCount a cero.

si (RowCount = 15) entonces - Reinicie la actualización desde la columna A RowCount: = 0; más RowCount: = RowCount + 1; - Desplazarse por el final de las columnas si;

Ahora, para explicar el reloj que está en la lista de sensibilidad del proceso de visualización. La placa Basys3 tiene un reloj interno que funciona a 100MHz. Para nuestros propósitos, este es un reloj demasiado rápido, por lo que tendremos que dividir este reloj en un reloj de 960Hz usando el siguiente proceso.

- Reloj de proceso operando a 960HzCLKDivider: proceso (CLK) variable clkcount: rango de enteros 0 a 52083: = 0; comenzar si (aumento_de_borde (CLK)) luego clkcount: = clkcount + 1; si (clkcount = 52083) entonces ColCLK <= no (ColCLK); clkcount: = 0; terminara si; terminara si; proceso finalizado;

Paso 4: Explicación técnica: cambio de la información mostrada

Explicación técnica: cambio de la información mostrada
Explicación técnica: cambio de la información mostrada

En el código VHDL, la información o los datos que se mostrarán en la pantalla están controlados por el proceso del cursor, que tiene un reloj diferente en su lista de sensibilidad. Este código se llamó BtnCLK, un reloj diseñado para minimizar la desaparición de los botones cuando se presionan. Esto se incluye para que si se presiona un botón, el cursor en la fila superior no se mueva muy rápidamente a través de las columnas.

- Reloj de proceso operando a 5 Hz. Botón CLK: variable de proceso (CLK) btnclkcount: rango de enteros 0 a 10000001: = 0; begin if (rising_edge (CLK)) luego if (btnclkcount = 10000000) then btnclkcount: = 0; BtnCLK <= no (BtnCLK); más btnclkcount: = btnclkcount + 1; terminara si; terminara si; proceso finalizado;

Con la salida de la señal BtnCLK de este proceso, ahora podemos explicar el proceso del cursor. El proceso del cursor solo tiene BtnCLK en su lista de sensibilidad, pero en el bloque de código, se verifica el estado de los botones y esto hará que cambien los datos de RedA, RedB… GreenH. Aquí hay un fragmento del código del cursor, que incluye el bloque de reinicio y el bloque de la primera columna.

cursor: variable de proceso (BtnCLK) OCursorCol: STD_LOGIC_VECTOR (2 hacia abajo 0): = "000"; - OCursorCol realiza un seguimiento de la variable de columna anterior NCursorCol: STD_LOGIC_VECTOR (2 downto 0): = "000"; - NCursorCol establece el inicio de la nueva columna del cursor - Condición de RESET (botón ARRIBA) - El tablero se borra para que el juego se reinicie si (rising_edge (BtnCLK)) luego if (RST = '1') then RedA <= "00000000"; RedB <= "00000000"; RedC <= "00000000"; RedD <= "00000000"; RedE <= "00000000"; RedF <= "00000000"; RedG <= "00000000"; RedH <= "00000000"; GreenA <= "00000000"; GreenB <= "00000000"; GreenC <= "00000000"; GreenD <= "00000000"; GreenE <= "00000000"; GreenF <= "00000000"; GreenG <= "00000000"; VerdeH si (Lbtn = '1') entonces NCursorCol: = "111"; - Columna H elsif (Rbtn = '1') luego NCursorCol: = "001"; - Columna B elsif (Cbtn = '1') luego NCursorCol: = OCursorCol; - La columna permanece igual NTurnState <= no (TurnState); - Activa el turno del siguiente jugador - Comprueba la columna actual de abajo hacia arriba y enciende el primer LED que no está encendido. El color depende del color del cursor del jugador actual. para ck en 7 downto 1 bucle si (RedA (0) = '1') y (RedA (ck) = '0') y (GreenA (ck) = '0') entonces RedA (Ck) <= '1'; RedA (0) <= '0'; SALIDA; terminara si;

si (GreenA (0) = '1') y (RedA (ck) = '0') y (GreenA (ck) = '0') entonces

GreenA (Ck) <= '1'; GreenA (0) - Jugador rojo GreenA (0) <= '0'; if (NCursorCol = OCursorCol) entonces - Si no se presionó nada RedA (0) <= '1'; elsif (NCursorCol = "111") entonces - Si se presionó Lbtn RedH (0) <= '1'; RedA (0) <= '0'; elsif (NCursorCol = "001") entonces - Se presionó Iff Rbtn RedB (0) <= '1'; RedA (0) - Jugador verde RedA (0) <= '0'; si (NCursorCol = OCursorCol) entonces GreenA (0) <= '1'; elsif (NCursorCol = "111") luego GreenH (0) <= '1'; GreenA (0) <= '0'; elsif (NCursorCol = "001") luego GreenB (0) <= '1'; GreenA (0) <= '0'; terminara si; caso final;

Tenga en cuenta que la primera declaración de caso llamada: OCursorCol (que significa Old Cursor Column) es el comienzo de la máquina de estados finitos. Cada columna de la pantalla se trata como su propio estado en el FSM. Hay 8 columnas, por lo que se utilizó un conjunto de números binarios de 3 bits para identificar cada columna como un estado. La forma en que el FSM se mueve entre los estados depende del botón que se presione. En el fragmento de arriba, si se presiona el botón izquierdo, el FSM se moverá a "111", que sería la última columna de la pantalla. Si se presiona el botón derecho, el FSM se moverá a "001", que sería la segunda columna de la pantalla.

Si se presiona el botón central, el FSM NO se moverá a un nuevo estado, sino que activará un cambio en la señal TurnState, que es una señal de un bit para señalar el turno de qué jugador es. Además, el botón central ejecutará un bloque de código que verifica si hay una fila vacía en la parte inferior hasta la parte superior. Intentará colocar un marcador en la fila más baja sin llenar. Recuerde, este es un juego de conectar cuatro.

En la declaración de caso anidada llamada: TurnState, modificamos el color del cursor y en qué columna de la primera fila queremos cambiar los datos para que el proceso de visualización pueda reflejar el cambio.

Repetimos este código básico para los siete casos restantes. El diagrama FSM puede ser útil para comprender cómo están cambiando los estados.

Paso 5: Código

Código
Código

Este es el código funcional para Connect 4 que se puede compilar en VHDL usando el software Vivado.

También se proporciona una restricción para permitirle poner en marcha el juego.

Proporcionamos un diagrama de bloques que explica cómo se interconectan las entradas y salidas de cada proceso.

Recomendado: