Cuprins:

Jocul Mastermind în VHDL: 3 pași
Jocul Mastermind în VHDL: 3 pași

Video: Jocul Mastermind în VHDL: 3 pași

Video: Jocul Mastermind în VHDL: 3 pași
Video: Mastermind Game on Basys3 2024, Iulie
Anonim
Jocul Mastermind în VHDL
Jocul Mastermind în VHDL
Jocul Mastermind în VHDL
Jocul Mastermind în VHDL

Pentru proiectul nostru, am creat jocul „Mastermind” în VHDL pentru a fi jucat pe placa Basys3. Mastermind este un joc de rupere a codului care se joacă în mod tradițional cu chei și o masă de joc. Jucătorul unu plasează cârlige de culori asortate într-un rând de 4, ascunse de jucătorul doi. Jucătorul doi are apoi numărul „x” de presupuneri care plasează cârlige pe tablă într-un rând vizibil jucătorului unu. După fiecare presupunere, jucătorul doi este informat despre 2 numere: câte dintre ace sunt de culoarea corectă și câte ace sunt în poziția corectă pe rând. Folosind acele indicii, jucătorul doi trebuie să ghicească secvența corectă de ace pe care jucătorul a plasat-o în ghiciul alocat.

În implementarea noastră, jocul este un singur jucător. O combinație aleatorie de cârlige este generată de program, iar jucătorul trebuie să folosească placa Basys3 pentru a ghici secvența corectă. Există patru „culori”, reprezentate de valori binare. Afișajul cu 7 segmente arată trei valori: rotații rămase, numărul de pini în poziția corectă și numărul de pini care au culoarea corectă în poziția greșită (aceste valori încep de la 9, 0 și 0). Jucătorul folosește comutatoarele de pe tablă pentru a selecta valorile binare pentru ghiciul său și rotește un alt comutator pentru a trimite ghiciul. Dacă sunt corecte, jocul se termină și afișajul pe 7 segmente afișează „GG”. În caz contrar, contorul de ture scade cu 1 și jucătorul primește feedback în funcție de câte pini din presupunerea lor se potrivesc cu culoarea sau poziția pinilor din combinație. Dacă jucătorul rămâne fără ture fără a ghici corect, afișajul arată „GO” (reprezentând jocul terminat). De asemenea, jucătorul poate răsuci comutatorul de resetare pentru a porni din nou în orice moment.

Pasul 1: Materiale

Materiale
Materiale
Materiale
Materiale
Materiale
Materiale

Deoarece întregul joc poate fi jucat pe tablă, singurele materiale necesare sunt placa Basys3, un cablu micro USB pentru conectarea la tablă și un computer / laptop pe care îl puteți utiliza pentru codificare!

Pasul 2: Codul

Codul
Codul
Codul
Codul

Pentru ca acest joc să funcționeze pe FPGA, cel mai simplu mod de a scrie despre acesta ar fi crearea unei mașini de stat. A avea o mașină de stare permite experiența secvențială și interactivă necesară pentru ca jocul să funcționeze efectiv. Pentru ca totul să funcționeze fără probleme, mașina de stat se va baza pe semnalul de ceas intern al FPGA, asigurându-se că totul este sincronizat. Modulul principal este o mașină de stare cu patru stări; Stare inițială (Initial), SubmitAnswer State (SubAns), Display State (Dis) și CheckEndGame State (CheckEnd). Împreună cu mașina de stat, modulul principal are două submodule, un afișaj cu șapte segmente din 4 cifre (care are propriul submodul ClkDivider) și generatorul de numere aleatorii (de fapt un generator de numere psuedo-aleatorii). Există, de asemenea, un bloc de proces de bază pentru ca LED-urile de deasupra fiecărui comutator să fie aprinse la pornire, ca o modalitate prin care oamenii să vadă mai ușor ce introduc. O imagine de ansamblu de bază a codului poate fi văzută în harta mentală din imagine.

Prima componentă care trebuie privită este generatorul de numere aleatorii (randomgen). Deoarece nu este posibil din punct de vedere tehnic să se obțină numere aleatoare adevărate generate de hardware, cea mai simplă soluție a fost ca genul aleator să fie de fapt un registru de schimbare a feedbackului liniar (LFSR). LFSR are o intrare de clk și o ieșire „a” (un număr de 12 biți). În fiecare ciclu de ceas, se generează un nou număr de 12 biți începând cu „000000000001”, trecând în cele din urmă prin toate combinațiile de 12 biți de 1 și 0 înainte de a se repeta. Ieșirea „a” este dată la fiecare ciclu de ceas, deci rulează continuu pe tot parcursul. Clk este mapat la Clk de la modulul principal, iar „a” este mapat la semnalul RandNum din modulul principal.

Al doilea submodul este afișajul cu șapte segmente din 4 cifre. Acesta este un mod destul de simplu de a prezenta un afișaj cu șapte segmente din 4 cifre. Afișajul este setat pe Clk din modulul principal, dar acest submodul are propriul submodul al unui ClkDivider. ClkDivider (setat la 1298 Hz) este utilizat pentru a accelera ceasul pentru cel de-al șaptelea segment, astfel încât toate cifrele să pară activate în același timp (deoarece doar o singură cifră poate fi activată la un moment dat). Variabila „cifră” este utilizată pentru a parcurge punctele de pe afișaj și cu fiecare cifră apar condițiile unui afișaj de intrare de bază pe 4 biți, cu opțiuni pentru a afișa cifrele de la 0 la 9 și, de asemenea, nimic. Cea mai îndepărtată cifră stângă de pe ecran este setată la nimic, deoarece nu este utilizată în acest joc.

Modulul principal este format din mașina de stare. Cele patru stări din proces sunt Initial, SubAns, Dis și CheckEnd. Când se află în starea inițială, dacă SubmitBtn (comutatorul utilizat pentru a trimite răspunsul pentru verificare) este setat la „1”, atunci aparatul se mută în starea SubAns. Oricând Rbtn (comutatorul utilizat pentru resetarea mașinii) este setat la „1”, atunci mașina revine la starea inițială. Când se află în statul SubAns, când SubmitBtn = ‘0’ din nou, trece la starea Dis. În starea Dis, dacă Numărătoarea inversă = 0 (virajele la stânga pentru a ghici scad la 0) sau dacă RSpotCount = 4 (adică jucătorul ca toate culorile corecte în punctele corecte), aparatul merge în starea CheckEnd. Dacă niciuna dintre acestea nu apare, atunci când SubmitBtn = ‘1’ din nou, revine la starea SubAns pentru a permite o altă presupunere. Când sunteți în starea CheckEnd, acesta este sfârșitul jocului și singura cale de ieșire este să atingeți resetarea, readucându-l în starea inițială. Acest lucru poate fi vizualizat cu ușurință în diagrama mașinii de stare. Comportamental, starea inițială inițializează totul înapoi la poziția inițială. Numărătoarea inversă (semnal care salvează câte răsuciri are jucătorul) este setată la 9, RSpotCount (semnal care salvează câte dintre culorile pe care le-ați ghicit sunt la locul potrivit) este setat la 0, RColorCount (semnal care salvează câte dintre culorile pe care le-ați ghicit sunt corecte, dar în locul nepotrivit) este setat la 0, iar numărătoarea inversă mică (semnalul care este în cele din urmă mapat la Numărătoarea inversă care se schimbă de fapt la fiecare viraj în stările ulterioare) este setat la 9. De asemenea, în starea inițială RandNum (numărul generat psuedo-aleatoriu) este împărțit în patru verificări diferite (unul pentru fiecare culoare pe 3 biți) și salvat în semnale check1, check2, check3, check4. Aceste verificări sunt comparate cu presupunerile dvs., astfel încât, deși LFSR determină întotdeauna RandNum să schimbe fiecare ciclu, odată ce părăsiți starea inițială, verificările rămân aceleași, permițând unei valori salvate să compare răspunsul dvs. cu. Acest lucru înseamnă, de asemenea, de fiecare dată când aparatul este resetat, jucătorul are o nouă valoare de ghicit.

Statul SubmitAnswer (SubAns) schimbă activatorul de numărătoare inversă (semnalul „modificare”) la „1”. Acest lucru este necesar mai târziu pentru ca urmărirea turei să funcționeze. După aceea, starea compară intrările jucătorului de la comutatoare la verificările făcute în starea de mai sus. Semnalele rs1, rs2, rs3, rs4 și semnalele rc1, rc2, rc3, rc4 sunt tipuri întregi care, în funcție de instrucțiunile If, sunt setate la 1 sau 0. Semnalul rs este pentru punctul potrivit și rc pentru culoarea potrivită. De exemplu, dacă presupunerea jucătorului de culoare 1 este egală cu verificarea 1 a RandNum, atunci rs1 = 1, deoarece aceasta înseamnă că culoarea potrivită este în locul potrivit. Dacă culoarea 1 nu este egală cu verificarea1, dar este egală cu una dintre celelalte verificări, atunci rc = 1. Acest lucru se face pentru fiecare culoare și fiecare verificare.

Starea de afișare (Dis) caută mai întâi activatorul de numărătoare inversă. Dacă este „1”, atunci numărătoarea inversă mică coboară 1 (deci la prima tură merge de la 9 la 8 etc.). În caz contrar, rândul nu se schimbă. Indiferent de această activare, toate valorile rs de mai sus sunt adăugate și atribuite semnalului RSpotCounter. De asemenea, toate valorile rc sunt adăugate și atribuite RColorCounter. În cele din urmă, numărătoarea inversă este atribuită cu valoarea numărului mic. Semnalele RSpotCounter, RColorCounter și Countdown sunt toate convertite în std_logic_vectors pe 4 biți în afara procesului și sunt împinse la submodulul de afișare Seven Segment printr-o hartă de porturi. În acest fel, afișajul arată lucrurile corecte până când trimiteți un răspuns nou.

Starea CheckEnd este pentru dacă ați câștigat sau ați pierdut. Dacă ați câștigat (toate cele 4 culori sunt la locul potrivit, altfel cunoscut sub numele de RSpotCounter = 4), atunci „GG” (afișat tehnic ca 66) este afișat pe segmentul de șapte pentru a arăta că ați câștigat. Dacă ați pierdut (Numărătoarea inversă a atins 0), atunci „GO” (afișat tehnic ca 60) este afișat pe ecran pentru Game Over. Cu oricare dintre rezultate, apăsarea comutatorului de resetare la pornire va duce aparatul înapoi la starea inițială pentru a reda din nou.

Codul sursă poate fi găsit aici.

Pasul 3: Concluzie

Finalizarea acestui proiect ne-a învățat multe despre construirea unor circuite mai complicate. Proiectarea noastră inițială nu era o mașină cu stări finite. Ne-a fost dificil să depanăm și am rescris codul de mai multe ori folosind diferite metode (inclusiv un FSM). La sugestia instructorului, am rămas cu abordarea FSM și am reușit să terminăm jocul. Am aflat că este mult mai eficient să proiectăm codul pe baza hardware-ului decât cu o abordare tradițională de programare. De asemenea, ne-am confruntat cu mai multe provocări legate de afișajul cu șapte segmente. Obținerea afișării mai multor numere fără „fantomă” a fost dificilă și a trebuit să folosim un separator de ceas pentru a realiza acest lucru. Dacă ar fi să dezvoltăm în continuare acest proiect, am conecta LED-uri colorate la Basys3, astfel încât utilizatorul să poată vedea culori (ca în jocul tradițional), mai degrabă decât reprezentări numerice ale culorilor. În cele din urmă, am câștigat o mai bună înțelegere a proiectării circuitelor complexe, a aplicațiilor din viața reală și a provocărilor legate de utilizarea hardware, mai degrabă decât de a rula simulări în condiții perfecte.

Recomandat: