KABOOOOOOM!! and 6.111



description


Tasked to design and implement a digital project in areas such as games, music, digital filters, wireless communications, video, and graphics. I worked with teammates Devin Murphy and Willie Zhu to implement an FPGA-based multiplayer bomb defusing game (Kaboom!) inspired by Keep Talking and Nobody Explodes. I implemented 3 of our bomb defusing minigames and helped design and implement the graphics and instuction/user manual. This was the final project for a larger class offered at MIT - 6.111 (Digital Systems Laboratory).

skills used/developed


- digital logic
- finite-state machines
- FPGAs
- timing and synchronization
- signal processing
- SystemVerilog

documentation


Kaboom consists of a series of back-to-back minigames that you must complete to defuse the bomb before time runs out. We aimed to utilize as much built-in FPGA functionality as we could when designing these minigames, utilizing the FPGA's microphone, temperature sensor, and accelerometer. Our system also utilized a speaker and VGA to display our game audio and custom graphics.

Block diagram of our system:


System Block Diagram

my implemented minigames

1. Wire Cutting Module
This module takes in 6 3 bit numbers from the randomizer, one for the color of each of the 6 wires. These three bit numbers are mapped to colors via case statements. The instructions to disarm this module are based on the first wire color and the number of wires of that color. To count the number of wires that were the first color, I wrote a short module that takes in two input colors and returns 1 if they are the same, and 0 otherwise. I then put all the combinations of the first wire and others through this module ((1,2), (1,3), (1,4), (1,5), (1,6)) and added the results + 1 (to account for the first wire). I then used an always_comb to assign the wire that the user needed to cut for each first wire color / number of wires of that color combination. If the defuser cuts the correct wire (flips the correct switch), then an always_ff block will signal that the module was completed, while if the user cuts a wrong wire, the always_ff will signal that the module was failed. If no wires are cut, the module remains in the playable state. The graphics for this module were based on one wire image, where the wire itself was white. The wire was intentionally made white so that the module that stored the wire image could take in a wire input color, then check for pixels in the image that were white and replace them with the needed color in real time. This made it easy to generate wires of multiple random colors without taking up too much BRAM.





2. Uncovered Button Module
This module takes in one 2 bit number, and two 1 bit numbers from the randomizer. The two bit number assigns the button to a color using a case statement, and one of the 1 bit numbers is used to assign a color strip under the button to one of two colors. The last 1 bit random number is used to determine whether the button will be blank or have text (say “Hold”). This module also takes in the minutes, tens, and ones position of the timer. The instructions to disarm this module are based on all of the randomized inputs. Depending on the button color, strip color, and whether the button has text the user must press the pushed_button when there is a certain number in the timer and release when there is a different number in the timer. A few always_ff blocks were used to keep track of the times the user pushed/released the button. Upon reset, a previous_button logic was set to the input pushed_button value. A counter was used, and once it got to 1_000_000 clock cycles, I checked to see if the previous_button was 0 and the current pushed_button was 1. If this was true, I stored the inputted timer’s minutes, tens, and ones as the pushed minutes, tens, ones. I also did this in reverse (checking if the button was previously 1 and now 0 after 1_000_000 clock cycles) to store the timer’s values when the button was released. The count to one million was added as an additional debounce precaution and to ensure that I was actually seeing a transition from not pushed/pushed/released. There was a different push/release button time condition for each color/strip/text combination. If the Defuser pushed and released the button at the correct times according to the rules, then the always_ff will signal that the module was completed. If the user does not push or release the button at the correct time, then a failed signal will be raised.





3. Covered Button/Microphone Module
The module begins by displaying a glass covered button on the screen and a rectangular color strip to the right. The user must hold a correct note long enough to shatter the glass and push the button. The graphics also update when the note is held long enough, showing the covering cracked, and then gone (all these images created in inkscape and stored in BRAM via COEs). Once the cover is gone, the user can press the corresponding button on the FPGA to complete the module. The audio was put through an analog-digital converter IP (ADC). This measures the microphone output voltage and converts it to a digital signal. This data was then put through a Fast Fourier Transform IP (FFT) to convert the time-domain signal into its frequency domain representation so that we could compare the frequency we are receiving most of to the needed input frequency to complete the module.





Below you can see the final report for this project!