Whac-A-Mole is a popular arcade game in which electromechanical moles randomly pop out of holes. In order to score points, the player uses a foam mallet to hit these moles before they disappear back into their hole. A lesser known variant of this game, seen in 1990s arcades, is Wacky Gator. In this version of the game, the classic 2-dimensional array of moles is replaced with a linear arrangement of alligators. For this project, we chose to implement Wacky Gator, rather than the more traditional Wack-A-Mole, for several reasons. Primarily we did so because the linear layout of Wacky Gator could be more accurately adapted to our FPGA, but there was also a nostalgia factor. One of the group members grew up near an arcade with a Wacky Gator machine and has many fond memories of playing the game.
Our version of Wacky Gator is designed to run on the Digilent Basys3 development board. The Basys3 board is an FPGA development board made by digilent which integrates an Artix-7 FPGA along with switches, buttons, LEDs, a 7-segment display, and PMOD inputs and outputs. If you have access to a Basys3, you can make and play your own Wacky Gator game!
Step 1: Materials
In order to create this Instructable, you will need:
- A Digilent Basys3 FPGA Trainer Board
- Xilinx Vivado 2016 Software (free Webpack Edition)
- Cardstock and Markers (if you wish to create a cover for your game)
FPGA stands for field programmable gate array. It is an integrated circuit in which the hardware itself can be reconfigured to create an arbitrary digital circuit. The Basys3 board integrates an FPGA and hardware to interface with the outside world, much like an Arduino with an FPGA instead of a micro controller. FPGAs are programmed using a hardware description language such as VHDL or Verilog. For this project we have used VHDL.
The Basys3 can be programed using the Xilinx Vivado Design Suite, which integrates a text editor and each of the components required in order to synthesize and implement the design. Vivado can be purchased at https://www.xilinx.com. There are several versions available, including a free edition available here.
This project will assume familiarity with FPGAs as well as programming in VHDL using Vivado. Many tutorials are available online and an explanation of the basics of digital design is beyond the scope of this Instructable.
If you would like to further embellish your FPGA, you can design a custom cover that fits over the top of the board. We used glossy cardstock and sharpies to create our own cover, but many variations could be created using materials of your own choosing.
Step 2: Understanding Desired Operation
As previously explained, in the traditional arcade version of Whac-A-Mole electromechanical “moles” randomly appear from various holes on a playing surface. They remain raised for a variable length of time, during which the player must strike them. The mole will return to the hole either after being struck or after a given amount of time has passed. If the player manages to strike the mole before it disappears, they are awarded points. As the game progresses, the rate at which the moles appear increases and the amount of time that the player has to hit the mole decreases. After a preset time interval, the game ends, and the score is tallied. The same basic game logic applies to Wacky Gator, the variant of this game that we chose to implement. The main difference between Whac-A-Mole and Wacky Gator is simply the layout. While the moles in Whac-A-Mole are placed in a grid-like orientation, the gators in Wacky Gator are oriented linearly. Additionally, in Whac-A-Mole, the moles move vertically, while in Wacky Gator, the alligators move horizontally.
The arcade version of this game is implemented using electromechanical alligators that physically pop out of the game surface. Since we needed to adapt the game to a purely digital implementation on the Basys3 hardware. The gators are represented by the 16 LED’s which are “whacked” by flipping the corresponding switch up and down. Additionally, one of the push buttons is used to start and reset the game, and the built-in 7 segment display is used as a scoreboard.
As shown in the short video clip, the basic game play logic mimics the arcade game as closely as possible. An LED will be randomly illuminated, representing an alligator popping out. The LED will remain illuminated either until the corresponding switch is flipped up and down or until the allotted amount of time has passed. If the player flips the switch up and down before the LED turns off, a point will be scored and the number displayed on the seven segment display will increment. As the game goes on, the player moves through several "phases" of difficulty. In each phase, the rate at which the LEDs light up and turn off get slightly faster. The number of LEDs that can be illuminated simultaneously also increases. At the beginning of the game, only a single LED can be lit up at once. By the end of the game, up to three LEDs can all be illuminated at once. The game ends after one minute, at which point the total score is displayed. At any point during or after a game the player can start a new game by pressing the 'Start' push button.
Step 3: Design Overview
Before diving in and creating the game, it's important to understand the structure of the design. In order to simplify and compartmentalize the overall design, there is a main “Game Logic” module which handles the inputs and outputs of lighting up the LEDs, recognizes when points are scored, and tallies the score. This is a clocked module which runs at a speed based on the clock signal it is passed. Rather than internally modifying the clock signal as the game progresses, there are several modules outside the game logic. This design allows the game module to follow the same timing logic throughout the game, as though it is running at a single speed. There are speed modules, a speed selector, and a phase counter.
The Game Logic module needs a random number generator in order to make the gators appear in a random order. The output of this module is fed as an input into the Game Logic.
This random number generator also requires a clock signal. For this project, it is driven by the fastest game speed signal since that is the fastest rate that the Game Logic will ever need a new random number.
Finally, the Four Digit Display module is used to display the game score. This score is tabulated internally in the Game Logic module and is it output as a 16-bit binary standard logic vector.
Step 4: Implementation
The first module you want to create is WackyGator. This is the most top level module, which will contain the other modules and interfaces to the switches, LEDs , buttons and display. This module has three inputs: a clock signal (clk), a vector representing which switches are flipped (switch), and an indicator of when the start button is pressed (start). It also has three outputs: a vector dictating which LEDs should be illuminated (LED), and two outputs that drive the four digit display (segments and digits).
You also can set up your constraints file at this time, which dictates how the pins on the board are connected to the ports.
Step 5: Create the Game Logic
The GameLogic Module contains the bulk of the behavioral code. This module determines when a gator will appear and disappear, drives the LEDs, responds to input from the switches and the start buttons, and stores and passes the score.
Step 6: Create Clock Divider Module
In order to run the game at different speeds, you will need to create several clock dividers. The clock divider is implemented similar to a binary counter. It takes in two inputs: the system clock frequency, and a divisor, which is used to determine the output clock signal as a fraction of the input frequency.
This same module can be reused with various divisors in order to create each necessary clock speed. In our implementation we used the module 7 times (6 for speed, once for seven segment display).
Step 7: Create Phase Counter
As the game progresses, it moves through several "phases" of difficulty. The phase counter module is responsible for keeping track of which phase the game is currently in. It runs off of the system clock and counts how many clock cycles (and therefore how much time) has elapsed since the "Start" button was pressed. It then outputs the appropriate phase signal.
Step 8: Create the Speed Selector
As the game continues, the gators appear more frequently and remain visible for a shorter duration of time. In order to accomplish this, each successive phase of the game runs at a slightly faster clock speed. As previously described, the GameLogic module is designed to be independent of clock speed, and is simply fed a single clock signal. The speed selector is responsible for selecting the appropriate speed for the current phase, and sending this clock speed to the GameLogic module.
Step 9: Create Random Number Generator
In Wacky Gator, the alligators appear randomly. To mimic this behavior, the LEDs need to be illuminated randomly as well. This requires a random number generator. Rather than creating a random number generator from scratch, we chose to use a pre-existing implementation, created by Cal Poly professors Jeffrey Gerfen and Bryan Mealy. This is based on a linear feedback shift register. The only adaption we had to make to this module to was such that it output a four bit binary number.
Step 10: Create the Digit Display Logic
This module is responsible for displaying the score using the seven segment display. There is a single bit input, Clk, which functions as the clock signal, and a 16-bit vector that holds the current score, as tallied by the game logic module. The outputs are a 7-bit vector, Segments, and a 4-bit vector, Digits.The Four Digit Display module takes the current score vector, converts it to decimal, and outputs it on the seven segment display.
This display module must also run at a clocked refresh rate to make the numbers visible. Ours generates this clock speed from a final clock divider instance which is utilized as an internal component. This display driver outputs signals to the segment and digit outputs which utilize a multiplexor and the refresh clock to make visible numbers on the display.
Step 11: (optional) Design Game Cover
In order to increase the authenticity of our game and give it a more polished appearance, we decided to create a decorative cover. We did so by tracing the basic shape of the board on a piece of card stock and drawing on the card stock with sharpie in order to mimic the design of the original Wacky Gator arcade game.
Step 12: Play the Game!
If you managed to successfully complete each of the previous steps, you should now be able to play your game! After programing your Basys 3, use the start button to begin the game, or reset to a new game.