Sommario:

VHDL Basys3: Connect 4 Game: 5 passaggi
VHDL Basys3: Connect 4 Game: 5 passaggi

Video: VHDL Basys3: Connect 4 Game: 5 passaggi

Video: VHDL Basys3: Connect 4 Game: 5 passaggi
Video: 4.FPGA FOR BEGINNERS- Combining logic gates in VHDL (DIGILENT Basys3) 2024, Novembre
Anonim
VHDL Basys3: Connect 4 Game
VHDL Basys3: Connect 4 Game

Introduzione:

Questo è un gioco di logica digitale Connect 4 progettato in VHDL utilizzando il software Vivado e programmato sulla scheda Basys3. La costruzione e il design di questo progetto sono intermedi, ma i nuovi arrivati possono copiare i passaggi e costruire il gioco digitale.

Il gioco funziona come il gioco Connect 4. I giocatori possono spostare il cursore sullo schermo utilizzando i pulsanti sinistro e destro che si trovano sul tabellone. Premendo il pulsante centrale sul tabellone, il giocatore posizionerà il proprio segnalino su quella colonna e poi sarà il turno del giocatore successivo. Una volta che un giocatore vince, il gioco può essere resettato premendo il pulsante su sul tabellone.

Passaggio 1: dettagli rapidi e materiali

Dettagli tecnici rapidi:

  • Utilizza tre set di connessioni PMOD sulla scheda (JA, JB, JC)

    • 8 pin (esclusi i pin Vcc e GND) utilizzati per ciascun connettore PMOD
    • JA - Controllo delle righe
    • JB - Controllo delle colonne verdi
    • JC - Controllo delle colonne rosse
  • L'orologio dello schermo funziona a 960Hz

    Sono accesi solo 8 LED alla volta. Lo schermo si aggiorna a una velocità di clock sufficientemente elevata da dare l'illusione che più di 8 LED siano accesi in un determinato momento

  • L'orologio del pulsante funziona a 5Hz; Facoltativamente può essere perfezionato modificando il codice VHDL.
  • La resistenza interna dei Darlington Array è sufficiente per prevenire l'esaurimento dei LED

Il gioco è costruito utilizzando i seguenti componenti e strumenti:

  • (1) Scheda Basys3
  • (2) Matrice LED bicolore 8x5:
  • (2) ULN2803 - Array di transistor Darlington - Scheda tecnica
  • Bobine di filo
  • Cavi per ponticelli
  • Spelafili
  • Tagliere (un quadrato grande dovrebbe essere sufficiente)
  • Multimetro e alimentatore (risoluzione dei problemi)

Passaggio 2: collegamento dell'hardware

Collegamento dell'hardware
Collegamento dell'hardware
Collegamento dell'hardware
Collegamento dell'hardware

Linee guida:

Il cablaggio del progetto può essere estremamente complicato, prenditi il tuo tempo e verifica che tutte le connessioni siano corrette un set alla volta.

Il progetto prevede l'utilizzo di due schermi a LED, ma sono combinati per formare un unico grande schermo. Ciò può essere ottenuto collegando tutte le righe allo stesso punto. Poiché ogni schermo è bicolore, le righe rossa e verde di uno schermo devono essere collegate anche alle righe rossa e verde dell'altro schermo. In questo modo possiamo controllare tutte le righe con solo 8 pin. Gli altri 16 pin sono usati per controllare le colonne del display. Gli 8 pin per il possono essere collegati direttamente tramite cavi jumper ai connettori pmod. Le connessioni Pmod vanno prima all'ingresso dell'ULN2083A e l'uscita dell'ULN2083A è collegata direttamente alla colonna sullo schermo. Poiché il design è un 8x8, alcune colonne non saranno fisicamente collegate.

  • JA: Connessioni riga: dalla riga 1 a JA:1 alla riga 8 per JA:10.
  • JA: Rosso Collegamenti della colonna:
  • JC: Collegamenti colonna verde

Si prega di fare riferimento alle immagini pubblicate per sapere quali pin corrispondono a quali righe/colonne.

Nota: i transistor hanno resistenze integrate, quindi i LED non richiedono resistenza aggiuntiva per essere collegati in serie.

Passaggio 3: spiegazione tecnica: schermata

Lo schermo sta operando sulla persistenza della visione. Lo schermo si aggiorna così velocemente che l'occhio umano non può rilevare visibilmente che alcuni LED si stanno spegnendo e riaccendendo rapidamente. Infatti, rallentando l'orologio del display, si può notare il lampeggio.

Il display attiva tutte le otto righe in base ai dati memorizzati per quelle righe e il display attiva una colonna. Quindi passa rapidamente alla successiva immissione di dati per le otto righe e attiva la colonna successiva, mentre tutte le altre colonne sono disattivate. Questo processo continua a una velocità di clock sufficientemente elevata da rendere impercettibile lo sfarfallio del LED.

L'archiviazione dei dati per il display viene inizializzata immediatamente dopo l'architettura nel file VHDL nel modo seguente:

segnale RedA, RedB, RedC, RedD, RedE, RedF, RedG, RedH: std_logic_vector (7 fino a 0):= "00000000";

segnale GreenA, GreenB, GreenC, GreenD, GreenE, GreenF, GreenG, GreenH: std_logic_vector (da 7 a 0):= "00000000"; -- Dati riga a seconda della colonna: VERDE

Di seguito un piccolo frammento del processo che controlla la matrice del display a LED.

-- Processo che controlla il display a matrice del display a LED: processo (ColCLK) -- 0 - 16 per aggiornare sia la variabile della matrice 8X8 RED che 8x8 VERDE RowCount: intervallo intero da 0 a 16:= 0; begin if (rising_edge(ColCLK)) then if (RowCount = 0) then DORow <= RedA; -- Dati riga per colonna corrispondente DOCol <= "1000000000000000"; -- Trigger di colonna -- Ripeti questo codice fino a "000000000000000001"-- Passa a RedB, RedC…GreenA, GreenB…GreenH

Alla fine di GreenH, subito prima che il processo termini, questo frammento viene incluso per reimpostare RowCount a zero.

if (RowCount = 15) then -- Riavvia l'aggiornamento dalla colonna A RowCount:= 0; else ConteggioRighe:= ConteggioRighe + 1; -- Sposta tra le colonne end if;

Ora, per spiegare l'orologio che si trova nell'elenco di sensibilità del processo di visualizzazione. La scheda Basys3 ha un clock interno che opera a 100MHz. Per i nostri scopi, questo è un clock troppo veloce, quindi dovremo dividere questo clock in un clock a 960Hz usando il seguente processo.

-- Processo di clock funzionante a 960HzCLKDivider: variabile di processo (CLK) clkcount: range intero da 0 a 52083:= 0; begin if (rising_edge(CLK)) then clkcount:= clkcount + 1; if (clkcount = 52083) then ColCLK <= not(ColCLK); clkcount:= 0; finisci se; finisci se; fine del processo;

Passaggio 4: spiegazione tecnica: modifica delle informazioni visualizzate

Spiegazione tecnica: modifica delle informazioni visualizzate
Spiegazione tecnica: modifica delle informazioni visualizzate

Nel codice VHDL, le informazioni oi dati che verranno visualizzati sullo schermo sono controllati dal processo del cursore, che ha un orologio diverso nella sua lista di sensibilità. Questo codice è stato chiamato BtnCLK, un orologio progettato per ridurre al minimo il debouching dei pulsanti quando vengono premuti. Questo è incluso in modo che se si preme un pulsante, il cursore sulla riga superiore non si sposta molto rapidamente tra le colonne.

-- Processo di clock funzionante a 5 Hz. ButtonCLK: variabile di processo (CLK) btnclkcount: range intero da 0 a 10000001:= 0; begin if (rising_edge(CLK)) then if (btnclkcount = 10000000) then btnclkcount:= 0; BtnCLK <= not(BtnCLK); else btnclkcount:= btnclkcount + 1; finisci se; finisci se; fine del processo;

Con l'uscita del segnale BtnCLK di questo processo, ora possiamo spiegare il processo del cursore. Il processo del cursore ha solo BtnCLK nella sua lista di sensibilità ma nel blocco di codice, lo stato dei pulsanti è controllato e questo farà cambiare i dati per RedA, RedB…GreenH. Ecco un frammento del codice del cursore, che include il blocco di ripristino e il blocco per la prima colonna.

cursor: variabile di processo (BtnCLK) OCursorCol: STD_LOGIC_VECTOR (da 2 a 0):= "000"; -- OCursorCol tiene traccia della variabile di colonna precedente NCursorCol: STD_LOGIC_VECTOR (da 2 a 0):= "000"; -- NCursorCol imposta l'inizio della nuova colonna del cursore --Condizione RESET (pulsante SU) --Il tabellone viene cancellato per il riavvio del gioco se (rising_edge(BtnCLK)) poi se (RST = '1') quindi RedA <= "00000000"; RossoB <= "00000000"; RedC <= "00000000"; RedD <= "00000000"; RedE <= "00000000"; RedF <= "00000000"; RedG <= "00000000"; RedH <= "00000000"; VerdeA <= "00000000"; VerdeB <= "00000000"; GreenC <= "00000000"; GreenD <= "00000000"; VerdeE <= "00000000"; VerdeF <= "00000000"; VerdeG <= "00000000"; GreenH if (Lbtn = '1') then NCursorCol:= "111"; -- Colonna H elsif (Rbtn = '1') quindi NCursorCol:= "001"; -- Colonna B elsif (Cbtn = '1') then NCursorCol:= OCursorCol; -- La colonna rimane la stessa NTurnState <= not(TurnState); -- Attiva il turno del giocatore successivo -- Controlla la colonna corrente dal basso verso l'alto e accende il primo LED che non è acceso. Il colore dipende dal colore del cursore del giocatore corrente. for ck in 7 downto 1 loop if (RedA(0) = '1') e (RedA(ck) = '0') e (GreenA(ck) = '0') allora RedA(Ck) <= '1'; RossoA(0) <= '0'; USCITA; finisci se;

se (GreenA(0) = '1') e (RedA(ck) = '0') e (GreenA(ck) = '0') allora

VerdeA(Ck) <= '1'; VerdeA(0) -- Giocatore rosso VerdeA(0) <= '0'; if (NCursorCol = OCursorCol) then -- Se non è stato premuto nulla RedA(0) <= '1'; elsif (NCursorCol = "111") then -- Se è stato premuto Lbtn RedH(0) <= '1'; RossoA(0) <= '0'; elsif (NCursorCol = "001") then -- Iff Rbtn è stato premuto RedB(0) <= '1'; RedA(0) -- Giocatore verde RedA(0) <= '0'; if (NCursorCol = OCursorCol) then GreenA(0) <= '1'; elsif (NCursorCol = "111") then GreenH(0) <= '1'; VerdeA(0) <= '0'; elsif (NCursorCol = "001") then GreenB(0) <= '1'; VerdeA(0) <= '0'; finisci se; caso finale;

Nota, la prima istruzione case chiamata: OCursorCol (che sta per Old Cursor Column) è l'inizio della macchina a stati finiti. Ciascuna colonna del display viene trattata come il proprio stato nell'FSM. Sono presenti 8 colonne, quindi è stato utilizzato un set di numeri binari a 3 bit per identificare ogni colonna come stato. Il modo in cui l'FSM si sposta tra gli stati dipende dal pulsante premuto. Nello snippet sopra, se viene premuto il pulsante sinistro, l'FSM si sposterà su "111" che sarebbe l'ultima colonna del display. Se viene premuto il pulsante destro, l'FSM si sposterà su "001" che sarebbe la seconda colonna del display.

Se viene premuto il pulsante centrale, l'FSM NON si sposterà in un nuovo stato ma attiverà invece un cambiamento nel segnale TurnState, che è un segnale di un bit per notare quale sia il turno del giocatore. Inoltre, il pulsante centrale eseguirà un blocco di codice che controlla se c'è una riga vuota in fondo alla parte superiore. Cercherà di posizionare un marcatore nella riga più bassa e non riempita. Ricorda, questo è un gioco Connect Four.

Nell'istruzione nested case chiamata: TurnState, alteriamo il colore del cursore e la colonna della prima riga di cui vogliamo modificare i dati in modo che il processo di visualizzazione possa riflettere la modifica.

Ripetiamo questo codice di base per i restanti sette casi. Il diagramma FSM può essere utile per capire come cambiano gli stati.

Passaggio 5: codice

Codice
Codice

Questo è il codice funzionale per Connect 4 che può essere compilato in VHDL utilizzando il software Vivado.

Viene inoltre fornito un vincolo per consentire di avviare il gioco.

Abbiamo fornito uno schema a blocchi che spiega come gli ingressi e le uscite di ciascun processo sono interconnessi.

Consigliato: