Sommario:

Mastermind Game in VHDL: 3 passaggi
Mastermind Game in VHDL: 3 passaggi

Video: Mastermind Game in VHDL: 3 passaggi

Video: Mastermind Game in VHDL: 3 passaggi
Video: Mastermind Game on Basys3 2024, Dicembre
Anonim
Mastermind Game in VHDL
Mastermind Game in VHDL
Mastermind Game in VHDL
Mastermind Game in VHDL

Per il nostro progetto abbiamo creato il gioco “Mastermind” in VHDL da giocare sulla Basys3. Mastermind è un gioco che decifra il codice tradizionalmente giocato con pioli e un tabellone. Il giocatore uno mette pioli di colori assortiti in una fila di 4, nascosti dal giocatore due. Il giocatore due ha quindi un numero "x" di ipotesi posizionando i pioli sul tabellone in una riga visibile al giocatore uno. Dopo ogni ipotesi, il giocatore due viene informato di 2 numeri: quanti pioli sono del colore corretto e quanti pioli sono nella posizione corretta nella riga. Usando questi indizi, il giocatore due deve indovinare la corretta sequenza di birilli che il giocatore uno ha piazzato nel numero indovinato assegnato.

Nella nostra implementazione, il gioco è per giocatore singolo. Il programma genera una combinazione casuale di pioli e il giocatore deve utilizzare la scheda Basys3 per indovinare la sequenza corretta. Ci sono quattro "colori", rappresentati da valori binari. Il display a 7 segmenti mostra tre valori: giri rimanenti, numero di pin nella posizione corretta e numero di pin del colore corretto nella posizione sbagliata (questi valori iniziano da 9, 0 e 0). Il giocatore usa gli interruttori sul tabellone per selezionare i valori binari per la sua ipotesi e gira un altro interruttore per inviare l'ipotesi. Se sono corrette, il gioco termina e il display a 7 segmenti mostra "GG". In caso contrario, il contatore dei turni diminuisce di 1 e il giocatore riceve un feedback in base a quanti birilli nella sua ipotesi corrispondono al colore o alla posizione dei birilli nella combinazione. Se il giocatore esaurisce i turni senza indovinare correttamente, il display mostra "GO" (che rappresenta la fine del gioco). Il giocatore può anche capovolgere l'interruttore di ripristino per ricominciare in qualsiasi momento.

Passaggio 1: materiali

Materiali
Materiali
Materiali
Materiali
Materiali
Materiali

Poiché l'intero gioco può essere giocato sulla scheda stessa, gli unici materiali necessari sono la Basys3 Board, un cavo micro USB per connettersi alla scheda e un computer/laptop che puoi usare per codificare!

Passaggio 2: il codice

Il codice
Il codice
Il codice
Il codice

Affinché questo gioco funzioni sull'FPGA, il modo più semplice per scriverlo sarebbe creare una macchina a stati. Avere una macchina a stati consente l'esperienza sequenziale e interattiva necessaria affinché il gioco funzioni effettivamente. Affinché tutto funzioni senza intoppi, la macchina a stati si baserà sul segnale di clock interno dell'FPGA, assicurando che tutto sia sincronizzato. Il modulo principale è una macchina a stati con quattro stati; Stato iniziale (Initial), Stato SubmitAnswer (SubAns), Stato di visualizzazione (Dis) e Stato CheckEndGame (CheckEnd). Insieme alla macchina a stati, il modulo principale ha due sottomoduli, un display a sette segmenti a 4 cifre (che ha il suo sottomodulo ClkDivider) e il generatore di numeri casuali (in realtà un generatore di numeri pseudo-casuali). C'è anche un blocco di processo di base per fare in modo che i LED sopra ogni interruttore si accendano quando vengono accesi in modo che le persone possano vedere più facilmente cosa stanno inserendo. Una panoramica di base del codice può essere vista nella mappa mentale nella foto.

Il primo componente da considerare è il generatore di numeri casuali (randomgen). Dal momento che non è tecnicamente possibile ottenere numeri casuali reali generati dall'hardware, la soluzione più semplice era che il randomgen fosse effettivamente un registro a scorrimento a feedback lineare (LFSR). L'LFSR ha un ingresso di clk e un'uscita "a" (un numero a 12 bit). Ogni ciclo di clock, viene generato un nuovo numero a 12 bit a partire da "00000000001", che alla fine attraversa tutte le combinazioni di 12 bit di 1 e 0 prima di ripetersi. L'uscita "a" riceve ogni ciclo di clock, quindi è continuamente in esecuzione. Il clk è mappato al Clk dal modulo principale e "a" è mappato al segnale RandNum nel modulo principale.

Il secondo sottomodulo è il display a sette segmenti a 4 cifre. Questo è un modo abbastanza semplice per mostrare un display a sette segmenti a 4 cifre. Il display è impostato sul Clk dal modulo principale, tuttavia questo sottomodulo ha il proprio sottomodulo di ClkDivider. Il ClkDivider (impostato a 1298 Hz) viene utilizzato per accelerare l'orologio per i sette segmenti in modo che tutte le cifre sembrino accese contemporaneamente (poiché solo una cifra alla volta può essere attiva). La variabile "cifra" viene utilizzata per scorrere i punti sul display e con ogni cifra vengono le condizioni di un display di input di base a 4 bit, con opzioni per mostrare le cifre da 0 a 9 e anche niente. La cifra più a sinistra sul display non è impostata su nulla poiché non viene utilizzata in questo gioco.

Il modulo principale è costituito dalla macchina a stati. I quattro stati nel processo sono Initial, SubAns, Dis e CheckEnd. Nello stato iniziale, se SubmitBtn (interruttore utilizzato per inviare la risposta per il controllo) è impostato su "1", la macchina passa allo stato SubAns. Ogni volta che Rbtn (interruttore utilizzato per ripristinare la macchina) è impostato su "1", la macchina torna allo stato iniziale. Quando si trova nello stato SubAns, quando SubmitBtn = '0' di nuovo, si passa allo stato Dis. Nello stato Dis, se il conto alla rovescia = 0 (i giri a sinistra per indovinare scendono a 0) o se RSpotCount = 4 (indicando il giocatore con tutti i colori corretti nei punti corretti), la macchina passa allo stato di check-end. Se nessuno di questi si verifica, quando SubmitBtn = '1' di nuovo, torna allo stato SubAns per consentire un'altra ipotesi. Quando sei nello stato CheckEnd, questa è la fine del gioco e l'unica via d'uscita è premere il reset, riportandolo allo stato iniziale. Questo è facilmente visibile nel diagramma della macchina a stati. Comportamentalmente lo stato iniziale inizializza tutto nella posizione iniziale. Il conto alla rovescia (segnale che salva quanti turni mancano al giocatore) è impostato su 9, RSpotCount (segnale che salva quanti dei colori indovinati sono nel posto giusto) è impostato su 0, RColorCount (segnale che salva quanti colori i colori che hai indovinato sono giusti ma nel punto sbagliato) è impostato su 0 e il piccolo conto alla rovescia (segnale che alla fine viene mappato su Countdown che cambia effettivamente ogni turno negli stati successivi) è impostato su 9. Inoltre, nello stato iniziale il RandNum (numero pseudo-casuale generato) è suddiviso in quattro diversi controlli (uno per ogni colore a 3 bit) e salvato nei segnali check1, check2, check3, check4. Questi controlli sono ciò a cui viene effettivamente confrontata la tua ipotesi, quindi anche se l'LFSR fa sì che RandNum cambi ogni ciclo, una volta lasciato lo stato iniziale i controlli rimangono gli stessi, consentendo a un valore salvato di confrontare la tua risposta. Ciò significa anche che ogni volta che la macchina viene ripristinata, il giocatore ha un nuovo valore da indovinare.

Lo stato SubmitAnswer (SubAns) cambia l'abilitatore del conto alla rovescia (segnale "cambia") in "1". Ciò è necessario in seguito affinché il monitoraggio del turno funzioni. Successivamente, lo stato confronta gli input del giocatore dagli interruttori con i controlli effettuati nello stato precedente. I segnali rs1, rs2, rs3, rs4 e i segnali rc1, rc2, rc3, rc4 sono tipi interi che, a seconda delle istruzioni If, sono impostati su 1 o 0. I segnali rs sono per il punto destro e rc per il colore destro. Ad esempio, se il colore 1 indovinato dal giocatore è uguale al check1 del RandNum, allora rs1 = 1 poiché ciò significa che il colore giusto è nel posto giusto. Se il colore 1 non è uguale a check1, ma è uguale a uno degli altri controlli, allora rc = 1. Questo viene fatto per ogni colore e per ogni controllo.

Lo stato di visualizzazione (Dis) cerca prima l'attivatore del conto alla rovescia. Se è "1", il piccolo conto alla rovescia scende di 1 (quindi al primo turno va da 9 a 8 ecc.). Altrimenti il turno non cambia. Indipendentemente dall'abilitazione in, tutti i valori rs dall'alto vengono sommati e assegnati al segnale RSpotCounter. Inoltre tutti i valori rc vengono aggiunti e assegnati a RColorCounter. Infine Countdown viene assegnato il valore di smallcountdown. I segnali RSpotCounter, RColorCounter e Countdown vengono tutti convertiti in std_logic_vectors a 4 bit al di fuori del processo e inviati al sottomodulo del display a sette segmenti tramite una mappa delle porte. In questo modo, il display mostra le cose giuste finché non invii una nuova risposta.

Il CheckEnd State è per se hai vinto o perso. Se hai vinto (tutti e 4 i colori sono nel posto giusto, altrimenti noto come RSpotCounter = 4), allora "GG" (mostrato tecnicamente come 66) viene visualizzato sul Sette Segmento per mostrare che hai vinto. Se hai perso (il conto alla rovescia ha raggiunto lo 0), allora "GO" (mostrato tecnicamente come 60) viene visualizzato sul display per Game Over. Con entrambi i risultati, premendo l'interruttore di ripristino su on, la macchina tornerà allo stato iniziale per giocare di nuovo.

Il codice sorgente può essere trovato qui.

Passaggio 3: conclusione

Il completamento di questo progetto ci ha insegnato molto sulla costruzione di circuiti più complicati. Il nostro progetto iniziale non era una macchina a stati finiti. Abbiamo trovato difficile eseguire il debug e riscrivere il codice un numero di volte utilizzando metodi diversi (incluso un FSM). Su suggerimento dell'istruttore, siamo rimasti fedeli all'approccio FSM e siamo riusciti a finire il gioco. Abbiamo appreso che è molto più efficace progettare il codice basato sull'hardware rispetto a un approccio di programmazione tradizionale. Abbiamo anche affrontato diverse sfide relative al display a sette segmenti. Farlo visualizzare più numeri senza "fantasma" è stato difficile e abbiamo dovuto usare un divisore di orologio per farlo. Se dovessimo sviluppare ulteriormente questo progetto, collegheremmo LED colorati al Basys3 in modo che l'utente possa vedere i colori (come nel gioco tradizionale) piuttosto che le rappresentazioni numeriche dei colori. Alla fine, abbiamo acquisito una maggiore comprensione della progettazione di circuiti complessi, delle applicazioni della vita reale e delle sfide legate all'utilizzo dell'hardware anziché all'esecuzione di simulazioni con condizioni perfette.

Consigliato: