Table des matières:

Jeu Mastermind en VHDL : 3 étapes
Jeu Mastermind en VHDL : 3 étapes

Vidéo: Jeu Mastermind en VHDL : 3 étapes

Vidéo: Jeu Mastermind en VHDL : 3 étapes
Vidéo: Как мультиплексировать семисегментные дисплеи на Z80 2024, Novembre
Anonim
Jeu Mastermind en VHDL
Jeu Mastermind en VHDL
Jeu Mastermind en VHDL
Jeu Mastermind en VHDL

Pour notre projet, nous avons créé le jeu « Mastermind » en VHDL à jouer sur la carte Basys3. Mastermind est un jeu de décryptage traditionnellement joué avec des chevilles et un plateau de jeu. Le joueur un place des piquets de couleurs assorties dans une rangée de 4, cachés au joueur deux. Le joueur deux a alors un nombre « x » de suppositions en plaçant des piquets sur le plateau dans une rangée visible par le joueur un. Après chaque estimation, le joueur 2 est informé de 2 nombres: combien de piquets sont de la bonne couleur et combien de piquets sont à la bonne position dans la rangée. En utilisant ces indices, le joueur deux doit deviner la séquence correcte d'épingles que le joueur un a placée dans le nombre de devinettes attribué.

Dans notre implémentation, le jeu est solo. Une combinaison aléatoire de chevilles est générée par le programme, et le joueur doit utiliser la carte Basys3 pour deviner la séquence correcte. Il y a quatre « couleurs », représentées par des valeurs binaires. L'affichage à 7 segments affiche trois valeurs: tours restants, nombre de broches dans la bonne position et nombre de broches de la bonne couleur dans la mauvaise position (ces valeurs commencent à 9, 0 et 0). Le joueur utilise les interrupteurs du tableau pour sélectionner les valeurs binaires de sa proposition, et actionne un autre interrupteur pour soumettre la proposition. S'ils sont corrects, le jeu se termine et l'affichage à 7 segments affiche « GG ». Sinon, le compteur de tours diminue de 1 et le joueur reçoit un retour basé sur le nombre de quilles dans son estimation qui correspondent à la couleur ou à la position des quilles dans la combinaison. Si le joueur manque de tours sans avoir deviné correctement, l'écran affiche « GO » (représentant la fin de la partie). Le joueur peut également appuyer sur l'interrupteur de réinitialisation pour recommencer à tout moment.

Étape 1: Matériaux

Matériaux
Matériaux
Matériaux
Matériaux
Matériaux
Matériaux

Étant donné que tout le jeu peut être joué sur la carte elle-même, les seuls matériaux nécessaires sont la carte Basys3, un câble micro USB pour se connecter à la carte et un ordinateur/ordinateur portable que vous pouvez utiliser pour coder !

Étape 2: le code

Le code
Le code
Le code
Le code

Pour que ce jeu fonctionne sur le FPGA, la façon la plus simple de l'écrire serait de créer une machine à états. Avoir une machine d'état permet l'expérience séquentielle et interactive nécessaire pour que le jeu fonctionne réellement. Pour que tout se passe bien, la machine d'état sera basée sur le signal d'horloge interne du FPGA, garantissant que tout est synchronisé. Le module principal est une machine à états à quatre états; État initial (Initial), État SubmitAnswer (SubAns), État d'affichage (Dis) et État CheckEndGame (CheckEnd). Avec la machine d'état, le module principal a deux sous-modules, un affichage à sept segments à 4 chiffres (qui a son propre sous-module ClkDivider) et le générateur de nombres aléatoires (en fait un générateur de nombres pseudo-aléatoires). Il existe également un bloc de processus de base pour que les LED au-dessus de chaque interrupteur s'allument lorsqu'elles sont allumées afin que les gens voient plus facilement ce qu'ils saisissent. Un aperçu de base du code peut être vu dans la carte mentale illustrée.

Le premier composant à examiner est le générateur de nombres aléatoires (randomgen). Puisqu'il n'est techniquement pas possible d'obtenir de vrais nombres aléatoires générés à partir du matériel, la solution la plus simple consistait à faire en sorte que le randomgen soit en fait un registre à décalage à rétroaction linéaire (LFSR). Le LFSR a une entrée clk et une sortie « a » (un nombre de 12 bits). À chaque cycle d'horloge, un nouveau nombre de 12 bits est généré à partir de « 000000000001 », passant finalement par toutes les combinaisons de 12 bits de 1 et de 0 avant de se répéter. La sortie "a" est donnée à chaque cycle d'horloge, elle fonctionne donc en continu. Le clk est mappé au Clk du module principal, et « a » est mappé au signal RandNum dans le module principal.

Le deuxième sous-module est l'affichage à sept segments à 4 chiffres. C'est une façon assez simple de présenter un affichage à sept segments à 4 chiffres. L'affichage est défini sur le Clk à partir du module principal, mais ce sous-module a son propre sous-module de ClkDivider. Le ClkDivider (réglé sur 1298 Hz) est utilisé pour accélérer l'horloge du Sept Segment afin que tous les chiffres semblent être activés en même temps (puisqu'un seul chiffre peut être activé à la fois). La variable "chiffre" est utilisée pour faire défiler les points sur l'affichage, et avec chaque chiffre vient les conditions d'un affichage d'entrée de base à 4 bits, avec des options pour afficher les chiffres 0 à 9 et aussi rien. Le chiffre le plus à gauche sur l'écran est réglé sur rien car il n'est pas utilisé dans ce jeu.

Le module principal est constitué de la machine d'état. Les quatre états du processus sont Initial, SubAns, Dis et CheckEnd. Dans l'état initial, si le SubmitBtn (commutateur utilisé pour soumettre votre réponse pour vérification) est réglé sur « 1 », alors la machine passe à l'état SubAns. Chaque fois que Rbtn (commutateur utilisé pour réinitialiser la machine) est réglé sur « 1 », la machine revient à l'état initial. Lorsqu'il est dans l'état SubAns, lorsque SubmitBtn = '0' à nouveau, il passe à l'état Dis. Dans l'état Dis, si le compte à rebours = 0 (les tours à gauche pour deviner tombent à 0) ou si le RSpotCount = 4 (ce qui signifie que le joueur a toutes les couleurs correctes aux bons endroits), la machine passe à l'état CheckEnd. Si aucun de ceux-ci ne se produit, alors lorsque SubmitBtn = '1' à nouveau, il revient à l'état SubAns pour permettre une autre supposition. Dans l'état CheckEnd, c'est la fin du jeu, et le seul moyen de sortir est d'appuyer sur la réinitialisation, le ramenant à l'état initial. Ceci est facilement visualisable dans le diagramme de la machine d'état. Sur le plan comportemental, l'état initial initialise tout à la position de départ. Le compte à rebours (signal qui enregistre le nombre de tours qu'il reste au joueur) est défini sur 9, RSpotCount (signal qui enregistre le nombre de couleurs que vous avez devinées sont au bon endroit) est défini sur 0, RColorCount (signal qui enregistre combien de les couleurs que vous avez devinées sont correctes mais au mauvais endroit) est défini sur 0, et le petit compte à rebours (signal qui est finalement mappé sur le compte à rebours qui change en fait à chaque tour dans les états ultérieurs) est défini sur 9. De plus, dans l'état initial, le RandNum (numéro généré pseudo-aléatoire) est divisé en quatre contrôles différents (un pour chaque couleur à 3 bits) et enregistré dans les signaux check1, check2, check3, check4. Ces vérifications sont ce à quoi votre estimation est réellement comparée, donc même si le LFSR fait toujours changer RandNum à chaque cycle, une fois que vous quittez l'état initial, les vérifications restent les mêmes, permettant à une valeur enregistrée de comparer votre réponse. Cela signifie également que chaque fois que la machine est réinitialisée, le joueur a une nouvelle valeur à deviner.

L'état SubmitAnswer (SubAns) modifie l'activateur de compte à rebours (signal « changement ») en « 1 ». Ceci est nécessaire plus tard pour que le suivi des virages fonctionne. Après cela, l'état compare les entrées du joueur des commutateurs aux vérifications effectuées dans l'état ci-dessus. Le signal rs1, rs2, rs3, rs4 et les signaux rc1, rc2, rc3, rc4 sont des types entiers qui, selon les instructions If, sont définis sur 1 ou 0. Le signal rs est pour le bon endroit et rc pour la bonne couleur. Par exemple, si la couleur 1 devinée par le joueur est égale au check1 du RandNum, alors rs1 = 1 car cela signifie que la bonne couleur est au bon endroit. Si la couleur 1 n'est pas égale à check1, mais est égale à l'un des autres contrôles, alors rc = 1. Ceci est fait pour chaque couleur et chaque contrôle.

L'état d'affichage (Dis) recherche d'abord l'activateur de compte à rebours. Si c'est « 1 », alors le petit compte à rebours diminue de 1 (donc au premier tour, il passe de 9 à 8, etc.). Sinon, le tour ne change pas. Indépendamment de cette activation, toutes les valeurs rs ci-dessus sont additionnées et affectées au signal RSpotCounter. De plus, toutes les valeurs rc sont ajoutées et affectées au RColorCounter. Enfin, Countdown reçoit la valeur smallcountdown. Les signaux RSpotCounter, RColorCounter et Countdown sont tous convertis en std_logic_vectors 4 bits en dehors du processus, et poussés vers le sous-module d'affichage à sept segments via une carte de port. De cette façon, l'écran affiche les bonnes choses jusqu'à ce que vous soumettiez une nouvelle réponse.

L'état CheckEnd indique si vous avez gagné ou perdu. Si vous avez gagné (les 4 couleurs sont au bon endroit, autrement connu sous le nom de RSpotCounter = 4), alors « GG » (indiqué techniquement par 66) s'affiche sur le Sept Segment pour montrer que vous avez gagné. Si vous avez perdu (le compte à rebours a atteint 0) alors « GO » (indiqué techniquement par 60) s'affiche à l'écran pour Game Over. Avec l'un ou l'autre résultat, appuyer sur l'interrupteur de réinitialisation ramènera la machine à l'état initial pour jouer à nouveau.

Le code source peut être trouvé ici.

Étape 3: Conclusion

La réalisation de ce projet nous a beaucoup appris sur la construction de circuits plus complexes. Notre conception initiale n'était pas une machine à états finis. Nous avons eu du mal à déboguer et avons réécrit le code plusieurs fois en utilisant différentes méthodes (y compris un FSM). Sur la suggestion de l'instructeur, nous sommes restés avec l'approche FSM et nous avons pu terminer le jeu. Nous avons appris qu'il est beaucoup plus efficace de concevoir le code basé sur le matériel qu'avec une approche de programmation traditionnelle. Nous avons également été confrontés à plusieurs défis liés à l'affichage à sept segments. Faire en sorte qu'il affiche plusieurs nombres sans « fantômes » était difficile, et nous avons dû utiliser un diviseur d'horloge pour y parvenir. Si nous devions développer davantage ce projet, nous connecterions des LED colorées au Basys3 afin que l'utilisateur puisse voir les couleurs (comme dans le jeu traditionnel) plutôt que des représentations numériques des couleurs. En fin de compte, nous avons acquis une meilleure compréhension de la conception de circuits complexes, des applications réelles et des défis liés à l'utilisation de matériel plutôt qu'à l'exécution de simulations dans des conditions parfaites.

Conseillé: