Purpose
Having familiarized ourselves with the GPIO of an FPGA and what it is capable of. lab 3 takes a look at driving a Video Graphics Array (VGA) interface which is connected to a monitor. This lab will reinforce the VGA protocol, including the pinout, screen synchronization, and video signals necessary to utilize the VGA standard.
VGA Standard
Similar to the four-digit seven-segment display from the previous labs, the VGA standard was originally created to drive a cathode ray tube (CRT) display by continuously refreshing the screen. This CRT display is made up on an electron beam being raster scanned across the screen, which is summarized effectively by the image below. In each video frame, the electrons are scanned across the screen 480 times to create 480 horizontal lines of displayable information, each comprising of 640 pixels of displayable information. Note that the values of 480 and 640 come from the original image format for the VGA standard, 640x480. Each of these pixels allow us to define individual red, green, and blue intensities that we input into the VGA interface. This display refreshes at the exact same rate as the display from labs 1 and 2, which is 60 Hz. As long as the refresh rate is greater than 60 Hz, the display runs quick enough for us to see a smooth image.
VGA Pinout
If you are utilizing the Cmod A7 board, you should have realized by now there's no VGA port built into the board (unless they hid it really well!), which means in order to interact with a VGA interface, we must directly correlate GPIO pins to the pins on a VGA cable. To make this easiest for me, I connected my board to a male interface of a VGA cable, meaning I could use the male/female jumper wires I had available to me. The pinout below shows the relevant pins in order for us to drive the VGA display.
Here, we need to interact with pins 1, 2, and 3 to drive the colors red, green, and blue, respectively. Pins 5, 6, 7, 8, 9, 10 all need to be connected to ground. Lastly, pins 13 and 14 are the horizontal and vertical syncs for the video screen. However, the values utilized by a VGA port are analog. That means that the intensity of each color is represented as a ratio of the voltage out of the maximum possible (here, it is 3.3 Volts max). Since the FPGA board I am utilizing only has digital input/output pins, we need to convert from digital to analog. Traditionally this is done inside of the VGA cable using a digital to analog converter (DAC), but we will create our own using resistors. This can be done by including resistor values according to the diagram below.
The given pin values are arbitrary and will be replaced with whatever you decide to assign in your constraint file. By sending the digital signals through these resistor combinations, an analog output is simulated. We don't need to focus on how this actually works for the scope of this lab, but you can research further if you are interested.
Demonstration of Program
Below you can see the wiring needed to complete this lab using the Cmod A7 FPGA.
Size and Color Modification
The first recommended modification to the program was to change the size and color of the bouncing square. This was relatively simple, as 'ball.vhd' allows you to specify the radius and color. With the following modifications outlined in red, I was able to create a blue ball that was twice the size of the original.
Horizontal Motion Modification
The next modification was to add horizontal motion to the bouncing ball, so that it would not solely be moving up and down. By defining a new signal called 'ball_x_motion' with the same magnitude as the initial y motion, I was able to implement this very simply. The changes to position calculations are outlined to the left in red.
The only difference between horizontal and vertical motion is the limit imposed by the screen size.
Shape Modification
The last modification suggested was to make the ball a circle, which proved to be the most challenging as you cannot traditionally represent float values in HDL languages. This is because HDL languages are very digital focused, only using values of '0' and '1' for signals. The CONV_INTEGER function converts a value of a specific pixel position to an integer and then creates a ball with the radius of "pixel_col - ball_x".