Índice:

Jogo Mastermind em VHDL: 3 etapas
Jogo Mastermind em VHDL: 3 etapas

Vídeo: Jogo Mastermind em VHDL: 3 etapas

Vídeo: Jogo Mastermind em VHDL: 3 etapas
Vídeo: Mastermind 2018 - How To Play 2024, Julho
Anonim
Jogo Mastermind em VHDL
Jogo Mastermind em VHDL
Jogo Mastermind em VHDL
Jogo Mastermind em VHDL

Para o nosso projeto, criamos o jogo “Mastermind” em VHDL para ser jogado no tabuleiro Basys3. Mastermind é um jogo de quebra de códigos tradicionalmente jogado com pinos e um tabuleiro de jogo. O jogador um coloca pinos de cores variadas em uma linha de 4, escondidos do jogador dois. O jogador dois então tem um número 'x' de palpites colocando pinos no tabuleiro em uma linha visível para o jogador um. Depois de cada palpite, o jogador dois é informado de 2 números: quantos pinos têm a cor correta e quantos pinos estão na posição correta na linha. Usando essas pistas, o jogador dois deve adivinhar a sequência correta de pinos que o jogador um colocou no número estimado alocado.

Em nossa implementação, o jogo é para um jogador. Uma combinação aleatória de pinos é gerada pelo programa, e o jogador deve usar o tabuleiro Basys3 para adivinhar a sequência correta. Existem quatro “cores”, representadas por valores binários. O display de 7 segmentos mostra três valores: voltas restantes, número de pinos na posição correta e número de pinos que são da cor correta na posição errada (esses valores começam em 9, 0 e 0). O jogador usa os interruptores no tabuleiro para selecionar os valores binários de sua estimativa e aciona outro interruptor para enviar a estimativa. Se estiverem corretos, o jogo termina e o display de 7 segmentos mostra “GG”. Caso contrário, o contador de giros diminui em 1 e o jogador recebe feedback com base em quantos pinos em sua estimativa correspondem à cor ou posição dos pinos na combinação. Se o jogador ficar sem turnos sem adivinhar corretamente, o visor mostra “GO” (representando o fim do jogo). O jogador também pode girar o botão de reinicialização para reiniciar a qualquer momento.

Etapa 1: Materiais

Materiais
Materiais
Materiais
Materiais
Materiais
Materiais

Uma vez que todo o jogo pode ser jogado no próprio tabuleiro, os únicos materiais necessários são o Tabuleiro Basys3, um cabo micro USB para conectar ao tabuleiro e um computador / laptop que você pode usar para codificar!

Etapa 2: O Código

O código
O código
O código
O código

Para que este jogo funcione no FPGA, a maneira mais simples de escrevê-lo seria criando uma máquina de estados. Ter uma máquina de estados permite a experiência sequencial e interativa necessária para que o jogo realmente funcione. Para que tudo corra bem, a máquina de estado será baseada no sinal de clock interno do FPGA, garantindo que tudo esteja em sincronia. O módulo principal é uma máquina de estados com quatro estados; Estado inicial (inicial), estado de SubmitAnswer (SubAns), estado de exibição (Dis) e o estado de CheckEndGame (CheckEnd). Junto com a máquina de estado, o módulo principal tem dois submódulos, um Display de Sete Segmentos de 4 dígitos (que tem seu próprio submódulo ClkDivider) e o Gerador de Números Aleatórios (na verdade, um gerador de números psuedo-aleatórios). Há também um bloco de processo básico para que os LEDs acima de cada interruptor sejam ligados quando ligados, para que as pessoas vejam mais facilmente o que estão inserindo. Uma visão geral básica do código pode ser vista no mapa mental ilustrado.

O primeiro componente a ser examinado é o Gerador de números aleatórios (randomgen). Visto que não é tecnicamente possível obter verdadeiros números aleatórios gerados a partir do hardware, a solução mais simples era ter o randomgen na verdade um Registro de deslocamento de feedback linear (LFSR). O LFSR tem uma entrada de clk e uma saída “a” (um número de 12 bits). A cada ciclo de clock, um novo número de 12 bits é gerado começando em "000000000001", eventualmente passando por todas as combinações de 12 bits de 1 e 0 antes de se repetir. A saída “a” é fornecida a cada ciclo de clock, portanto, está continuamente em execução. O clk é mapeado para o Clk do módulo principal e “a” é mapeado para o sinal RandNum no módulo principal.

O segundo submódulo é o Display de Sete Segmentos de 4 dígitos. Esta é uma maneira bastante direta de apresentar um Display de 7 segmentos de 4 dígitos. A exibição é definida no Clk do módulo principal, mas este submódulo tem seu próprio submódulo de um ClkDivider. O ClkDivider (definido para 1298 Hz) é usado para acelerar o relógio para o Segmento Sete de modo que todos os dígitos pareçam estar ativados ao mesmo tempo (já que apenas um dígito pode estar ativado de cada vez). A variável “dígito” é usada para percorrer os pontos no display, e com cada dígito vêm as condições de um display de entrada básico de 4 bits, com opções para mostrar os dígitos de 0 a 9 e também nada. O dígito mais à esquerda na tela é definido como nada, pois não é usado neste jogo.

O módulo principal consiste na máquina de estado. Os quatro estados no processo são Initial, SubAns, Dis e CheckEnd. Quando estiver no estado inicial, se o SubmitBtn (switch usado para enviar sua resposta para verificação) estiver definido como '1', a máquina se moverá para o estado SubAns. Sempre que Rbtn (interruptor usado para reiniciar a máquina) é definido como '1', a máquina retorna ao estado inicial. Quando no estado SubAns, quando SubmitBtn = ‘0’ novamente, ele passa para o estado Dis. Quando no estado Dis, se a contagem regressiva = 0 (a curva para a esquerda para adivinhar cair para 0) ou se o RSpotCount = 4 (significando que o jogador tem todas as cores corretas nos pontos corretos), a máquina vai para o estado CheckEnd. Se nenhum desses ocorrer, então, quando SubmitBtn = ‘1’ novamente, ele volta ao estado SubAns para permitir outra suposição. Quando no estado CheckEnd, este é o fim do jogo, e a única saída é acertar o reset, retornando-o ao estado inicial. Isso pode ser facilmente visualizado no diagrama da máquina de estados. Comportamentalmente, o estado inicial inicializa tudo de volta à posição inicial. O Countdown (sinal que salva quantas voltas restantes o jogador tem) é definido como 9, RSpotCount (sinal que salva quantas das cores que você adivinhou estão no ponto certo) é definido como 0, RColorCount (sinal que salva quantos de as cores que você adivinhou estão certas, mas no local errado) é definido como 0, e o smallcountdown (sinal que é eventualmente mapeado para Countdown que realmente muda a cada curva nos estados posteriores) é definido como 9. Além disso, no estado inicial, o RandNum (número gerado aleatoriamente psuedo) é dividido em quatro verificações diferentes (uma para cada cor de 3 bits) e salvo nos sinais check1, check2, check3, check4. Essas verificações são o que seu palpite é realmente comparado, portanto, embora o LFSR esteja sempre fazendo com que RandNum mude a cada ciclo, uma vez que você sai do estado inicial as verificações permanecem as mesmas, permitindo um valor salvo para comparar sua resposta. Isso também significa que sempre que a máquina for reiniciada, o jogador terá um novo valor para adivinhar.

O estado de SubmitAnswer (SubAns) muda o ativador de contagem regressiva (sinal de "mudança") para '1'. Isso é necessário mais tarde para que o rastreamento de virada funcione. Depois disso, o estado compara as entradas do jogador nas chaves com as verificações feitas no estado acima. O sinal rs1, rs2, rs3, rs4 e os sinais rc1, rc2, rc3, rc4 são tipos inteiros que, dependendo das declarações If, são configurados para 1 ou 0. O sinal rs é para o ponto certo e rc para a cor certa. Por exemplo, se a cor 1 palpite do jogador for igual ao check1 do RandNum, então rs1 = 1, pois isso significa que a cor certa está no local certo. Se a cor 1 não for igual a verificação1, mas for igual a uma das outras verificações, então rc = 1. Isso é feito para cada cor e cada verificação.

O estado de exibição (Dis) procura primeiro o ativador de contagem regressiva. Se for '1', então a contagem decrescente desce 1 (portanto, na primeira volta vai de 9 para 8, etc.). Caso contrário, a curva não muda. Independentemente de ativar, todos os valores rs acima são somados e atribuídos ao sinal RSpotCounter. Além disso, todos os valores rc são adicionados e atribuídos ao RColorCounter. Finalmente, Countdown recebe o valor de smallcountdown. Os sinais RSpotCounter, RColorCounter e Countdown são todos convertidos em std_logic_vectors de 4 bits fora do processo e enviados para o submódulo de exibição de sete segmentos por meio de um mapa de porta. Dessa forma, o visor mostra as coisas certas até que você envie uma nova resposta.

O CheckEnd State é para saber se você ganhou ou perdeu. Se você ganhou (todas as 4 cores estão no lugar certo, também conhecido como RSpotCounter = 4), então “GG” (mostrado tecnicamente como 66) é exibido no Sete Segmento para mostrar que você ganhou. Se você perdeu (a contagem regressiva chegou a 0), “GO” (tecnicamente mostrado como 60) é exibido no visor para Game Over. Com qualquer um dos resultados, acionar o botão de reinicialização fará com que a máquina volte ao estado inicial para jogar novamente.

O código-fonte pode ser encontrado aqui.

Etapa 3: Conclusão

A conclusão deste projeto nos ensinou muito sobre a construção de circuitos mais complicados. Nosso projeto inicial não era uma máquina de estados finitos. Achamos difícil depurar e reescrevemos o código várias vezes usando métodos diferentes (incluindo um FSM). Seguindo a sugestão do instrutor, mantivemos a abordagem FSM e conseguimos terminar o jogo. Aprendemos que é muito mais eficaz projetar o código com base no hardware do que com uma abordagem de programação tradicional. Também enfrentamos vários desafios relacionados ao display de sete segmentos. Fazer com que ele exibisse vários números sem “fantasmas” foi difícil, e tivemos que usar um divisor de relógio para fazer isso. Se tivéssemos que desenvolver este projeto, conectaríamos LEDs coloridos ao Basys3 para que o usuário pudesse ver as cores (como no jogo tradicional) em vez de representações numéricas das cores. No final das contas, ganhamos uma compreensão maior de projetos de circuitos complexos, aplicações da vida real e os desafios de usar hardware em vez de executar simulações em condições perfeitas.

Recomendado: