Introduction: FPGA Reaction Game
By Summer Rutherford and Regita Soetandar
Step 1: Introduction
For our final project for CPE 133, we designed a reaction game in VHDL for a Basys3 board. This game can be most closely compared to the arcade game “Stacker” where the player has to drop the blocks at the right time. The Basys3 board is connected to a breadboard, which has the alternating LEDs. These LED lights will alternate at a specific frequency, depending on the level. This game uses the clock divider and the 4 digit 7 segment display, as well as a finite state machine. When the player activates the correct switch as the middle LED lights up, the player will advance to the next level of the game, increasing the frequency of the alternating LEDs. This makes each successive level harder than the previous level. When the player successfully beats level 7, the highest level, a message will display on the segment display and all the LEDs will simultaneously flash on and off.
Step 2: Materials
- Digilent Basys3 board with micro USB cable
- 5 LEDs
- 5 resistors (we used 220 ohms)
- 11 jumper wires
- Computer with Vivado
Step 3: Top Level Diagram Black Box Design
As you can see, our top level block diagram starts by getting the required clocks from our submodule, ClkDivide. These clocks are inputs into the various process blocks. Essentially, the game has to recognize that when a user correctly turns on the switch, the LEDs must start alternating faster and the display needs to go up one level. The block diagram might look a little crazy, but that is because there are many signals that are established in a certain process and then that signal defines another signal in another process block.
In the end, the only inputs the game takes are the input clock on the Basys3 board that runs at 100 Mhz, seven switches on the Basys3 board, and the reset button. What is outputted is the anode for the seven segment display, the seven segments for the display, and the LEDs.
Step 4: CLKDivide
This clock divider submodule created a slower clock depending on the value we mapped to it in our main file. We used this submodule to determine Clk400, PushClk, and newlck.This submodule takes a clock and a 32 bit divider as inputs. A slowed clock is outputted. There is a process block for the divider and the slowed clock. In the process is a temporary variable, which we called count, that counts up one every time a rising edge of the inputted clock is hit. Once it reaches the divisor number, the slowed clock toggled and count resets to zero.
Step 5: Shift Process Block
The Shift process block controls the alternating motion and speed of the LEDs. In the sensitivity list are the newclk and Stop signals. Stop causes a brief delay when the user passes the level. If Stop is not high, then the LEDs alternate as normal based on the speed of newclk. This alternating pattern is controlled by two variables: Track and count. Count determines which LED should be on, while Track determines if count should be counting up or down. There is another signal, Final, that applies only when the Level is “111,” indicating the player has beat the game. Final alternates between 0 and 1 every clock edge to turn the LEDs on and off continuously. This is just a visual element for the final display.
This shift process is the perfect place to start for this project. If you can get your LEDs alternating correctly and consistently, then from here you just have to add in the behavior when levelling up!
Step 6: Finite State Machine
We created a Finite State Machine to dictate the behavior when the input switch or reset button is pressed. Each state is a “level” and if the switch is turned on at the wrong time or reset is pressed, level reverts back to “000.” Otherwise, if the switch is correctly turned on then the level moves up until it reaches the final state, “111” and the ending display occurs. The FSM is based on the two process blocks sync_proc and comb_proc. Sync_proc uses the clock that we called PushClk. This clock controls how fast the next state becomes the present state. This clock should be quite fast; we chose a speed that was about two times faster than our fastest LED speed.
We implemented this code using an FSM for the levels; however, after this project we realized a more efficient use of an FSM might have been to have a count-up state, a reset state, or a stay state. If nothing is being pressed, it is in the stay state. If reset is being pressed or the player messed up, it is in reset state. If correctly pressed, it is in the count up state. There are many other ways to use an FSM in this game as well!
Step 7: Controlling Display Process Block With Level
Level controls the Display process block. The variables in the sensitivity list are Level, Reset, and Clk400. The 7 segment display starts by displaying ‘1’ for the first level. It counts up until 7 every time the user passes a level to show the user what level they are on. Once the user has passed level 7, it displays “COOL” to signify that the player has beat the game. This “COOL” display runs off of a 400 Hz clock that we called Clk400. If Reset is pressed, the display goes back to “1.”
Step 8: Controlling LED Speed With Level
Finally, Level controls the speed of the LEDs. Level is the only signal in the sensitivity list. D1 is the signal that goes into the Clock Divider process to get newclk. Every time Level is changed, or the state changes, the process block “Speed.” This process determines the value of D1. There are 8 defined values of D1 that we chose based on how fast we wanted each level to run. D1 gets smaller every time level increases so that the newclk runs faster.
Step 9: Hardware Assembly
We connected the breadboard to the Basys3 with one of the pmod connectors. Six of the pmod ports were used to plug in a male to male connector, one for ground and the other five for the 5 LEDs. We also placed a resistor for each LED. These resistors are 220Ω and prevent the LEDs from being short circuited and burnt out. Although each LED has some resistance, the resistance is not enough to impede the voltage from the source.
Step 10: Have Fun!
This game is very easy to play. The player starts on the far right switch 1 of the board, V17. They must flip the switch high when the middle LED is on. They then move one switch to the left and do the same thing! If the player makes it to the end, they will end up on the seventh switch, W14. If they beat the game they get to see a really fun ending display!
Something to note is that when creating this game the speeds are totally up to you! If the speeds we have chosen are too slow, feel free to speed it up and make it even more challenging! There is also no set number of levels. If you want to make it have even more levels, there are modifications that must be made to the FSM and the process blocks determined by Level, but these are very simple changes.
We also chose to use switches on the board as the user input, but this is also possible with a button on the Basys3 board; the button will eliminate the need to reset the switches every time the user starts over. We initially used a button, however this caused errors in defining the level because it would jump multiple levels if two rising edges of PushClk were hit when the button was being held down.
Below is a video demonstrating how to play, going through the first 4 levels, and the final ending display.
The main file for this project is included below.