Yoshi’s Nightmare: FPGA Based Video Game


Introduction

Video games are typically designed around a microprocessor that is embedded within a console or computer system. While this is the typical case these days, it is not the way that video games always been crafted. In its infancy, the first video game experience was that of a fully analog system which implemented a crude form of table tennis on the quaint black and white CRT televisions of the time. With the introduction of TTL and then CMOS logic chips, there existed a new toolset to create simple logic games. The introduction of the microprocessor and its evolution over the many decades has provided a powerful and flexible platform for which to design video game systems and to write software around.

Why would one consider implementing a video game with the reconfigurable logic of an FPGA? There are many ways that FPGA technology can help in the realm of video games. Graphics co-processors can be developed and tested using FPGA technology, providing a more flexible and affordable testing platform than the ASIC. In consideration of small toys and low cost game devices, FPGAs can be used to test standalone digital systems that can later be translated to an ASIC design and mass manufactured to provide an affordable and fun experience for the consumer. Beyond these possibilities, the intellectual challenge of coordinating a digital system that interprets inputs from a game controller and output graphics to a VGA monitor is very intriguing to me, and I have strived to make the experience as compelling as possible.

 

The Game: A broad overview

The game that I envisioned when beginning this project revolved around a small green dinosaur named Yoshi, a popular character from Nintendo’s Mario series. The first objective was to fully animate his actions, allowing the player to make him run around, and jump up and down from platforms on the screen.

This involved fully implementing a form of 2D Physics for his motion in the x and y dimensions on the screen, keeping in mind conservation of momentum and accelerations, as well as collisions with objects, walls, and platforms.

Next there needed to be reasons for Yoshi to move about, and these are eggs and ghosts. Eggs are objects which Yoshi usually collects in his classic games, so I made his purpose in my game to collect randomly placed eggs on the screen to gain points. Ghosts are traditional enemy characters from the Mario series, and were a fitting object for use as an enemy in the game. These ghosts chase Yoshi around as he collects eggs, and introduce a sense of urgency and challenge to the otherwise simple task at hand.

To create the environment for the game, stationary platforms and an outer wall around the screen are drawn on the monitor, and a separate collision detection circuit is used to determine when Yoshi encounters them. Other assets to the game, such as score display, life hearts display, gameover display, background, as well as title screen were implemented at the end of the design as finishing touches to the game.

To play the game, I decided to use a classic Nintendo NES controller, as this would provide sufficient buttons to control the gameplay and would add to the retro feel of the game. I harvested a female controller port from a scrap Nintendo console and soldered jumper wires from the pins to interface with GPIO on the FPGA board. The controller uses a serial protocol for communicating button states, and therefore a receiver module needed to be implemented to use the controller with the game.

I based the project around the affordable and capable Basys 3 development board which uses a Xilinx Artix-7 series FPGA, with 33k logic cells, and 1800 kbits of block RAM.  The board has “p-mod” connector which allow for outside input, as well as a seven-segment display to display the score on.

Continue reading

Advertisement

Storing Image Data in Block RAM on a Xilinx FPGA

Now that we have a VGA synchronization circuit we can move on to designing a pixel generation circuit that specifies unique RGB data for certain pixels (i.e. an image). Before we actually go there, I thought I would separately talk a little bit about how to store image data on an FPGA. This discussion will focus mainly with using a Xilinx FPGA, more specifically the Basys 3, which uses 12-bit color.

Raw images are arrays of pixel data. Each pixel has a number of bits that specifies the intensity of the red, green, and blue color components. Assuming that an image is stored in 24-bit “True Color”, there are 8 bits specifying each respective color component. Since we are using the Basys 3 FPGA, we will need only the upper four bits of each color component (3 colors * 4 bits/color = 12 bits). So we need 12 bits per pixel to represent color, and y*x pixels, where y is the image height, and y is the image width.

The image of Yoshi shown above is scaled up such that we can easily see each pixel as a block of color on our screen. This image has a height of 32 pixels, and a width of25 pixels. That means that in total we have 800 pixels, each needing 12 bits to represent color, so 9600 bits altogether. There are a few ways to store all of these bits.

Continue reading

Driving a VGA Monitor Using an FPGA

Learning how to directly drive a VGA monitor with an FPGA opens up a window for many potential projects: video games, image processing, a terminal window for a custom processor, and many more. To get started, we will need to learn how to drive the necessary signals to display things on a VGA monitor. We will then use a test circuit to display some colors on the screen. In future posts I will detail how to design pixel generating circuits for displaying custom graphics and animations. More on that soon!

Computer monitors used to be bulky cathode ray tube (CRT) devices. VGA technology was developed with driving the physical CRT in mind, so knowing how that device works can be instructive in understanding why VGA signals are driven the way they are. That being said, computer monitors nowadays are LCD monitors without a CRT, yet the VGA interfaces for these monitors still use the same signals to display images on their screens. Instead of going into the details of CRTs in this post, we will instead inspect the necessary signals for a VGA monitor and their timing diagrams, and implement a synchronization circuit in Verilog HDL.

Keep in mind that different FPGA development boards have different color depth capabilities. I will focus here on using the Basys 2 which has 8-bit color and the Basys 3 which has 12-bit color. While I am covering the Basys 2 here, in the future I will focus on and use the more capable Basys 3 for my VGA projects.
Continue reading

FIFO Buffer Using Block RAM on a Xilinx Spartan 3 FPGA

A FIFO (first in first out) buffer allows for temporary storage for transmission of data between subsystems. It is a very common construct used in digital systems, but why do we need them?

As an example, let’s say that we have a keyboard subsystem that, when a key is pressed, sends corresponding ASCII data to a UART subsystem, which then serially passes the data on to a receiving PC. Assuming that data is directly relayed between the keyboard and UART subsystems, there is risk of data corruption if another key is pressed before the last  key’s ASCII data has been processed by the UART subsystem. This condition is known as data overrun, and can be avoided by inserting a data buffer such as a FIFO between the keyboard and UART subsystems. If the baud rate for a UART is high enough, then the likelihood of data overrun occurring is limited by how fast a user can mash the keyboard’s keys (which for the previous implementation was unlikely). Regardless, it is a good idea to provide data buffers between subsystems that are not instantaneous in their processing of sent and received data.

In this post I will briefly detail how to implement a FIFO buffer in Verilog HDL using the Block RAM on a Xilinx Spartan 3 FPGA. The implementation will allow us to specify the number of words (pieces of data) in the FIFO as well as word width (number of bits per word). We will be able to read from and write to the FIFO, assuming it isn’t in an empty or full state, which we will keep track of and signal out from the FIFO to make the utilizing subsystem aware.

Continue reading

FPGA Keyboard Interface

The keyboard is a tool whose utility needs no introduction. Right now I using a keyboard to type this blog post. I find the keyboard to be an interesting device that deserves a look into how it works. By learning a little about the insides we can then plan to interface the keyboard with an FPGA and use it as an input device. I for one am really looking forward to learning how to drive VGA signals, and eventually making an FPGA based game that plays on a VGA monitor and uses keyboard as a controller. Until then, let’s start learning how to interface with the keyboard.

The keys on a keyboard have various purposes, with the majority being alphanumeric or symbol keys. There are also common modification keys, such as space, enter, shift, caps lock, backspace, etc. Many of the other key groups such as the F#, directional, and navigation keys serve special purposes within a computer system (i.e. Print Screen).

We will implement an FPGA keyboard interface that is simplified to process the alphanumeric & symbol keys, as well as the space, backspace, enter, tab, shift, and capslock keys. The keyboard used will have a PS2 connection, so we will need to implement a PS2 receiver circuit to receive scan codes from the keyboard when a key is pressed. We will then implement a keyboard interface circuit that processes the scan codes in a way that will make the keystroke responses natural and akin to how they would be in a simple text editor. Finally to test the keyboard circuit we will interface it with a UART transmitter to send the corresponding ASCII codes (converted from scan codes) to a PC serial monitor for viewing. This will allow us to type characters, words, and sentences, with the basic functionality of the text modification keys.

Continue reading

UART Controlled Stopwatch Using an FPGA


Being able to interface an FPGA project with a device that has a serial port allows for a basic means of sending and receiving data between the FPGA and a PC. For this we need to implement a Universal Asynchronous Receiver Transmitter (UART) circuit within the FPGA system. You can then use a PC with an RS232 Serial port (shown above) to interface the FPGA with a PC, assuming your development board has the port and voltage conversion circuitry.

Because RS232 is a dated protocol that sometimes isn’t available on modern PC’s, another option is to use a USB-Serial converter chip, which connects to a USB port.

In this post I will detail a UART controlled stopwatch, designed for the Basys 2, using the same stopwatch implementation as in my previous post. To communicate with the PC through serial  we will implement a UART receiver and transmitter circuit, as well as a master control circuit that routes all the pieces together. We will then be able to control the stopwatch’s start, stop, and clear functions by sending ascii characters from the PC to the FPGA’s UART receiver circuit, and also send the current stopwatch time from the FPGA’s Transmitter circuit to the PC for viewing.

Continue reading

FPGA Reaction Timer

Reaction time is the duration of time it takes for the brain to interpret a stimulus and do something in reaction to it. The stimulus may be something visual such as a light turning on, something auditory such as a beep, or a touch cue such as a poke. The time it takes for the brain to interpret a stimulus and respond to it can be used as a basic benchmark to measure and compare mental acuity.

We will be implementing a reaction timer on an FPGA that turns on an LED after a psuedorandom period of time, and uses a pushbutton as a reaction input. There will be 3 input buttons: clear, start, and stop. The system will begin in an idle state waiting for the user to press the start button. When the start button is pressed, a random time interval will elapse before the LED turns on. When the LED turns on a reaction timer will begin counting the number of milliseconds until the user presses the stop button. When the stop button is pressed, the reaction time will be shown on a 4 digit 7-segment display in the format “0.000” seconds, up to a value of 9.999 seconds. The user can then press the clear button to reset the time display and go back to the idle state.

For this project we will be using the Basys 2 FPGA development board to implement the design, as it has the 4 digit display, pushbuttons, and LED that we need onboard.

Continue reading

BCD to Binary Conversion on an FPGA

Binary Coded Decimal format is a binary encoding of decimal numbers that represents each decimal digit by a fixed binary number. For example, 42 is represented in BCD format by the binary representations of 4 and 2, as shown above. The BCD format is common in electronic systems where numeric digits are displayed, as well as in systems where the rounding and conversion errors introduced by binary floating point representation and arithmetic are undesirable.

We will focus on designing a conversion circuit that converts a BCD formatted number to to a binary formatted number. I chose to detail this direction of conversion as binary to BCD conversion circuits are easily be found by a quick web search.

We will consider two algorithms to perform the conversion, the first being a direct arithmetic approach, and the second an iterative algorithm using a finite state machine with data path (FSMD).

We will be designing for the Basys 2 FPGA board which has 8 input switches. We can use the 8 input switches to encode 2 BCD numbers of 4 bits each. We will therefore concern ourselves with designing a circuit to convert a 2 digit BCD number to a 7 bit binary representation (27 = 128 > 99, the largest 2 digit BCD number we can input).

Continue reading

Stopwatch with the Basys 2 FPGA

A stopwatch is a good FPGA project that covers many basic, yet interesting areas of FPGA design. We will need display multiplexing for the multi-digit display, synchronous cascaded counter circuits to increment time registers for seconds and minutes, and a finite state machine to give us start, stop, and reset functionality.

I recently acquired a Basys 2 FPGA development board, which has an on-board 4 digit seven-segment display that lends itself nicely to keeping track of time in MM.SS format. Let’s build a stopwatch.
Continue reading

Square Wave Generator and PWM with a Numato Elbert v2 FPGA

Last time we outlined how to divide down an FPGAs clock frequency using a basic counter circuit. This allowed us to have varying blinking frequencies for our LEDs depending on which bits of the counter register we tied them to.

What if we needed to adjust for a specific frequency of blinking, of wanted to adjust the time the LED is on vs off? What we are looking for is a programmable square wave generator. I will show you how we can program an FPGA in Verilog to act as one that takes two 4-bit inputs to control the on/off periods of the square wave.

Once we have went through the process of adjusting the on/off timing of a square wave, creating an adjustable PWM output for an LED comes naturally. We will see how to program an FPGA to output a PWM signal that allows us to adjust the brightness of an LED based on a 4 bit input signal.

Continue reading