Inhaltsverzeichnis:

Mastermind-Spiel in VHDL - Gunook
Mastermind-Spiel in VHDL - Gunook

Video: Mastermind-Spiel in VHDL - Gunook

Video: Mastermind-Spiel in VHDL - Gunook
Video: Mastermind Game on Basys3 2024, November
Anonim
Mastermind-Spiel in VHDL
Mastermind-Spiel in VHDL
Mastermind-Spiel in VHDL
Mastermind-Spiel in VHDL

Für unser Projekt haben wir das Spiel „Mastermind“in VHDL erstellt, das auf dem Basys3-Board gespielt werden soll. Mastermind ist ein Code-Breaking-Spiel, das traditionell mit Stiften und einem Spielbrett gespielt wird. Spieler eins platziert Spielsteine in verschiedenen Farben in einer Viererreihe, die vor Spieler zwei verborgen ist. Spieler zwei hat dann „x“Anzahl von Vermutungen, indem er Spielsteine auf dem Brett in einer Reihe platziert, die für Spieler eins sichtbar ist. Nach jedem Tipp erhält Spieler 2 2 Zahlen: Wie viele der Spielsteine haben die richtige Farbe und wie viele Spielsteine befinden sich an der richtigen Position in der Reihe. Mit diesen Hinweisen muss Spieler 2 die richtige Reihenfolge der Pins erraten, die Spieler 1 in die zugeteilte Zahl gesetzt hat.

In unserer Implementierung ist das Spiel Einzelspieler. Das Programm erzeugt eine zufällige Kombination von Spielsteinen, und der Spieler muss das Basys3-Brett verwenden, um die richtige Reihenfolge zu erraten. Es gibt vier „Farben“, die durch binäre Werte dargestellt werden. Die 7-Segment-Anzeige zeigt drei Werte an: verbleibende Umdrehungen, Anzahl der Pins in der richtigen Position und Anzahl der Pins mit der richtigen Farbe in der falschen Position (diese Werte beginnen bei 9, 0 und 0). Der Spieler verwendet die Schalter auf dem Brett, um die binären Werte für seine Schätzung auszuwählen, und legt einen anderen Schalter um, um die Schätzung abzugeben. Wenn sie richtig sind, endet das Spiel und die 7-Segment-Anzeige zeigt „GG“. Wenn nicht, verringert sich der Rundenzähler um 1 und der Spieler erhält Feedback basierend darauf, wie viele Pins in seiner Schätzung der Farbe oder Position der Pins in der Kombination entsprechen. Wenn der Spieler keine Züge mehr hat, ohne richtig zu raten, zeigt das Display „GO“(das bedeutet, dass das Spiel vorbei ist). Der Spieler kann auch den Reset-Schalter umlegen, um jederzeit von vorne zu beginnen.

Schritt 1: Materialien

Materialien
Materialien
Materialien
Materialien
Materialien
Materialien

Da das gesamte Spiel auf dem Board selbst gespielt werden kann, benötigen Sie nur das Basys3-Board, ein Micro-USB-Kabel zum Anschluss an das Board und einen Computer/Laptop, mit dem Sie programmieren können!

Schritt 2: Der Code

Der Code
Der Code
Der Code
Der Code

Damit dieses Spiel auf dem FPGA funktioniert, wäre der einfachste Weg, es zu schreiben, eine Zustandsmaschine zu erstellen. Eine Zustandsmaschine ermöglicht die sequentielle und interaktive Erfahrung, die für das tatsächliche Funktionieren des Spiels erforderlich ist. Damit alles reibungslos abläuft, basiert die Zustandsmaschine auf dem internen Taktsignal des FPGA, um sicherzustellen, dass alles synchron ist. Das Hauptmodul ist eine Zustandsmaschine mit vier Zuständen; Initial State (Initial), SubmitAnswer State (SubAns), Display State (Dis) und CheckEndGame State (CheckEnd). Zusammen mit der Zustandsmaschine hat das Hauptmodul zwei Untermodule, eine 4-stellige Sieben-Segment-Anzeige (die über ein eigenes ClkDivider-Untermodul verfügt) und den Zufallszahlengenerator (eigentlich ein Pseudo-Zufallszahlengenerator). Es gibt auch einen grundlegenden Prozessblock, bei dem die LEDs über jedem Schalter beim Einschalten eingeschaltet werden, damit die Benutzer leichter sehen können, was sie eingeben. Eine grundlegende Übersicht über den Code ist in der abgebildeten Mindmap zu sehen.

Die erste zu betrachtende Komponente ist der Zufallszahlengenerator (randomgen). Da es technisch nicht möglich ist, echte Zufallszahlen von Hardware zu generieren, bestand die einfachste Lösung darin, dass das Randomgen tatsächlich ein Linear-Feedback-Schieberegister (LFSR) ist. Das LFSR hat einen Eingang von clk und einen Ausgang „a“(eine 12-Bit-Zahl). In jedem Taktzyklus wird eine neue 12-Bit-Zahl erzeugt, beginnend bei „000000000001“, die schließlich alle Kombinationen von 12-Bit-Einsen und Nullen durchläuft, bevor sie sich wiederholt. Der Ausgang „a“wird in jedem Taktzyklus ausgegeben, läuft also durchgehend. Der clk wird dem Clk des Hauptmoduls zugeordnet, und „a“wird dem Signal RandNum im Hauptmodul zugeordnet.

Das zweite Submodul ist die 4-stellige Siebensegmentanzeige. Dies ist eine ziemlich einfache Möglichkeit, eine 4-stellige Siebensegmentanzeige zu präsentieren. Die Anzeige wird auf dem Clk des Hauptmoduls eingestellt, dieses Untermodul hat jedoch ein eigenes Untermodul eines ClkDivider. Der ClkDivider (auf 1298 Hz eingestellt) wird verwendet, um die Uhr für das Siebensegment zu beschleunigen, so dass alle Ziffern gleichzeitig eingeschaltet zu sein scheinen (da nur eine Ziffer gleichzeitig eingeschaltet sein kann). Die Variable „Ziffer“wird verwendet, um durch die Punkte auf dem Display zu blättern, und mit jeder Ziffer kommen die Bedingungen einer einfachen 4-Bit-Eingabeanzeige mit Optionen zum Anzeigen der Ziffern 0 bis 9 und auch nichts. Die Ziffer ganz links auf dem Display ist leer, da sie in diesem Spiel nicht verwendet wird.

Das Hauptmodul besteht aus der Zustandsmaschine. Die vier Zustände im Prozess sind Initial, SubAns, Dis und CheckEnd. Wenn im Anfangszustand der SubmitBtn (Schalter zum Senden Ihrer Antwort zur Überprüfung) auf „1“gesetzt ist, wechselt die Maschine in den SubAns-Zustand. Jedes Mal, wenn Rbtn (Schalter zum Zurücksetzen der Maschine) auf „1“gesetzt wird, kehrt die Maschine in den Ausgangszustand zurück. Im SubAns-Zustand, wenn SubmitBtn wieder = ‚0‘ist, geht es in den Dis-Zustand über. Im Dis-Zustand, wenn der Countdown = 0 (die Drehungen nach links zum Erraten fallen auf 0) oder wenn der RSpotCount = 4 (was bedeutet, dass der Spieler alle richtigen Farben an den richtigen Stellen hat), geht die Maschine in den CheckEnd-Zustand. Wenn keines von beiden auftritt, dann, wenn SubmitBtn wieder = „1“ist, kehrt es in den SubAns-Zustand zurück, um eine weitere Vermutung zu ermöglichen. Wenn Sie sich im CheckEnd-Zustand befinden, ist dies das Ende des Spiels und der einzige Ausweg besteht darin, den Reset zu drücken und ihn in den Anfangszustand zurückzusetzen. Dies ist im Zustandsmaschinendiagramm leicht ersichtlich. Vom Verhalten her initialisiert der Initial State alles zurück in die Ausgangsposition. Der Countdown (Signal, das speichert, wie viele Umdrehungen der Spieler noch hat) wird auf 9 gesetzt die Farben, die Sie erraten haben, sind richtig, aber an der falschen Stelle) wird auf 0 gesetzt, und der kleine Countdown (Signal, das schließlich auf Countdown abgebildet wird, das sich in späteren Zuständen tatsächlich jede Runde ändert) wird auf 9 gesetzt. Außerdem wird im Anfangszustand die RandNum (psuedo-zufallsgenerierte Zahl) wird in vier verschiedene Prüfungen (eine für jede 3-Bit-Farbe) aufgeteilt und in den Signalen check1, check2, check3, check4 gespeichert. Diese Überprüfungen sind das, was Ihre Schätzungen tatsächlich vergleichen. Obwohl das LFSR immer dazu führt, dass sich RandNum in jedem Zyklus ändert, bleiben die Überprüfungen gleich, sobald Sie den Anfangszustand verlassen, sodass ein gespeicherter Wert Ihre Antwort vergleichen kann. Dies bedeutet auch, dass der Spieler jedes Mal, wenn die Maschine zurückgesetzt wird, einen neuen Wert erraten kann.

Der SubmitAnswer State (SubAns) ändert den Countdown-Enabler (Signal „change“) auf „1“. Dies wird später benötigt, damit die Abbiegeverfolgung funktioniert. Danach vergleicht der Zustand die Spielereingaben von den Schaltern mit den im obigen Zustand durchgeführten Prüfungen. Die Signale rs1, rs2, rs3, rs4 und die Signale rc1, rc2, rc3, rc4 sind Integer-Typen, die je nach If-Anweisung auf 1 oder 0 gesetzt werden. Das Signal rs steht für den rechten Fleck und rc für die rechte Farbe. Wenn zum Beispiel die Farbe 1 des Spielers gleich dem check1 der RandNum ist, dann ist rs1 = 1, da dies bedeutet, dass die richtige Farbe an der richtigen Stelle ist. Wenn Farbe 1 nicht gleich Check1 ist, aber gleich einem der anderen Checks, dann ist rc = 1. Dies wird für jede Farbe und jeden Check durchgeführt.

Der Anzeigestatus (Dis) sucht zuerst nach dem Countdown-Enabler. Wenn es „1“ist, geht der kleine Countdown um 1 zurück (also in der ersten Runde von 9 auf 8 usw.). Ansonsten ändert sich der Turn nicht. Unabhängig von dieser Freigabe werden alle rs-Werte von oben aufsummiert und dem Signal RSpotCounter zugewiesen. Außerdem werden alle rc-Werte hinzugefügt und dem RColorCounter zugewiesen. Schließlich wird Countdown der Wert von smallcountdown zugewiesen. Die Signale RSpotCounter, RColorCounter und Countdown werden alle außerhalb des Prozesses in 4-Bit-std_logic_vectors umgewandelt und über eine Port-Map an das Sieben-Segment-Anzeige-Submodul geschoben. Auf diese Weise zeigt das Display die richtigen Dinge an, bis Sie eine neue Antwort senden.

Der CheckEnd-Status dient dazu, ob Sie gewonnen oder verloren haben. Wenn Sie gewonnen haben (alle 4 Farben befinden sich an der richtigen Stelle, auch bekannt als RSpotCounter = 4), wird "GG" (technisch als 66 angezeigt) auf dem Sieben Segment angezeigt, um anzuzeigen, dass Sie gewonnen haben. Wenn Sie verloren haben (Countdown hat 0 erreicht), wird „GO“(technisch als 60 angezeigt) auf dem Display für Game Over angezeigt. Bei beiden Ergebnissen wird das Gerät durch Drücken des Reset-Schalters in den Ausgangszustand zurückversetzt, um erneut zu spielen.

Quellcode finden Sie hier.

Schritt 3: Fazit

Der Abschluss dieses Projekts hat uns viel über den Bau komplizierterer Schaltungen beigebracht. Unser ursprüngliches Design war kein endlicher Automat. Wir fanden es schwierig zu debuggen und haben den Code mehrmals mit verschiedenen Methoden (einschließlich eines FSM) neu geschrieben. Auf Anregung des Instruktors blieben wir beim FSM-Ansatz und konnten das Spiel beenden. Wir haben gelernt, dass es viel effektiver ist, den Code basierend auf der Hardware zu entwerfen, als mit einem traditionellen Programmieransatz. Auch im Zusammenhang mit der Sieben-Segment-Anzeige standen wir vor einigen Herausforderungen. Es war schwierig, mehrere Zahlen ohne "Ghosting" anzuzeigen, und wir mussten einen Taktteiler verwenden, um dies zu erreichen. Wenn wir dieses Projekt weiterentwickeln würden, würden wir farbige LEDs an das Basys3 anschließen, damit der Benutzer Farben (wie im traditionellen Spiel) anstelle von numerischen Farbdarstellungen sehen kann. Letztendlich haben wir ein besseres Verständnis für komplexes Schaltungsdesign, reale Anwendungen und die Herausforderungen gewonnen, Hardware zu verwenden, anstatt Simulationen unter perfekten Bedingungen durchzuführen.