This is a video game implemented with FPGA Basys 3 board on a VGA interface using VHDL language.

The player’s goal is to avoid obstacles generated in the game by controlling the buttons on the FPGA. The final score displayed is determined based on the time the player survived without bumping into obstacles.

This game is based on NinJump by Backflip Studios, a popular mobile-phone game in the early 2010s.

How did I make this game? Starting with the concepts… and work down to the details

Identifying major milestones… How to make the game enjoyable and challenging

I envisioned the game to be displayed on the VGA and the players could use buttons to control their character. With this vision in mind, I outlined the major milestones and game features I need to accomplish. 

First, I need to control the VGA color display as this is the foundation of everything. Specifically, Colors should be correctly displayed and updated on the VGA display

Second, I need to program the game logic. The game should display at a reasonable speed and the obstacles should appear in a complicated and unpredictable pattern to make it exciting and challenging for the players. To acknowledge the player’s accomplishment, there should be a score display to recognize the player’s achievement. To ensure great player experiences, The button should respond smoothly to reflect the player’s input on the screen (no glitch!)

Turning ideas into reality with a top-down approach!

I first drew out the higher-level blocks from the user input and FPGA clock input to the final display on the monitor. For each higher-level block, I create data path and state machine diagrams on paper before translating my paper design to VHDL code. 

Getting VGA display to work — the basis of everything else, the bones

I first started with the VGA display block because it is essential to visually see how the game logics works on the actual VGA screen later. 

The theory behind the VGA display is how the pixels on the screen update from left to right as well as top to bottom at the frequency of 25M Hz. The following figure is used as a graphic illustration of the timings. 

ABOUT THIS DIAGRAM: This is VGA timing diagram for 640×480 display, from Prof. Hansen. The idea is to create signals that turn on and off based on the pixel’s location (active, blacked areas for retrace, and low-true horizontal sync pulses areas on the screen). This is because not all pixels are being seen. Only displays on the active region could be captured by human eyes. Therefore signal timings dictate the displays, and it is crucial to get it right.

How to make the game enjoyable and fun?

There are three objects in this game: the player, the obstacle, and the scoreboard. 

The interface is divided into larger pixel blocks, and each block is considered as one unit. This will ensure the right functionalities as well as adaptability for the development of possible advanced features, while being sufficient to illustrate the concept of the game.

The player movement could be simply modeled as a state machine controlled by the signal of the debounced button monopulse input as it is always jumping from one side of the screen to the other. The button debouncer count was adjusted in reference to the internal 25M clock to ensure the button operation is smooth and not lagged.

The obstacle movement is implemented with shift registers. To address the difficulties needed for the game, the pattern input into the shift register could be complicated and thus difficult to predict. After the pattern is shifted out, it will wrap around again to the top of the screen like a belt. The speed of the shift register is controlled by a separate counter that resets after reaching 20M, which is roughly 1s/unit. (Basys 3 has an external clock at 100M Hz, the program runs on the 25M clock divider output). This speed is challenging enough for “ninja” to jump around.

The collision checker detects when the player and the obstacle are at the same block location using asynchronous logic. The output signal is used to determine when to end the game.

The score indicates how long the player has played in the game. Therefore score generator is running at the background, supplying the numbers going on the scoreboard display.

The core of the scoreboard display is a binary to BCD conversion block. The binary result from the score generator was converted into BCD numbers. The number could later be used to display the decimal number needed for the scoreboard, by taking for consecutive digits in the BCD number at a time and converting to score display using a “0-9” lookup table.

In the RTL diagram on the left, I made my BCD number 20 digits. This means I could have my decimal number go up to 99999, despite I ended up only using four digits (going up to 9999).

How to display 10011010010 as 1234?

Assemble everything piece by piece

After testing out the logics for the player, obstacle, and the scoreboard with both VGA and VHDL simulations, the major features of the game were done. To make this game complete, I created a game flow with a start page, game page, and game-over page using a simple state machine, where the transitions between states are motivated by the button press signal. The output of each state is the corresponding screen display pattern on the VGA.

Why did I make this game?

Growing up as a kid during the years when touchscreen smartphones first became popular, I was drawn to the smartphone game NinJump by Backflip Studios. I loved it because it was simple, easy to play, and had a cool ninja character. Unfortunately, the game was taken down after Backflip Studios went out of business in 2019. 


Therefore, I could not be more excited when given the opportunity to create my own video game on a VGA interface for my digital electronics class -- I wanted to recreate this childhood classic using my knowledge of FPGA programming. This game was played by multiple players (including my cousins) and the highest score is at 1246!

This project showed me the importance of going for a systematic top-down approach. At first, I did not know how to get to my final goal of making a game on VGA. However, after breaking this project down into small pieces and identifying my priorities, I was able to work through it one step at a time and eventually piece all these parts together. Paper designs are also very important, writing everything on paper before coding gives me more time to appreciate these small sub-projects and think through the details that might end up being a pain in debugging. If I had more time with the project, I would try to randomize my obstacle patterns and use memory to create icons for my ninja and obstacle characters.