This Bouncing Ball program was built through Vivado VHDL on the XILINX Digilent A7-100T FPGA board. The project uses five VHDL source files (clk_wiz_0.vhd, clk_wiz_0_clk_wiz.vhd, vga_sync.vhd, ball.vhd, and vga_top.vhd) and one Vivado constraint file (vga_top.xdc) to generate a game of pong on a 800x600 Video Graphics Array (VGA) monitor.
Once synthesizing, implementing and programming the FPGA with the baseline program, a red, square pong ball of size 8 will be shown through the VGA output monitor, bouncing back and forth on a single vertical axis.
Below, I detail a few methods to customize this baseline program, including a new ball size, changing foreground and background colors, changing the shape of the pong ball, and adding a second axis of motion horizontally. The VGA output of this updated code can be found to the left, and the project's source code can be reviewed by navigating to my GitHub repository.
This base functionality of this program can be altered by editing the aforementioned source files included in the Vivado project. Specifically, the state and dynamic behavior of the pong ball can be altered with a few edits in the ball.vhd source file. For instance, the size of our pong ball can be modified by editing the code snippet included here, found just within the architecture body declaration. The pong ball's 'radius' is defined by the constant value of 'size' - altering the constant value of this constant from its initial value of 8 to 32 produces a pong ball quadrupled in size.
Likewise, the RGB colors of our VGA output can be changed by manipulating the steady state of three standard logic output signals for the 'ball' entity: 'red', 'green', and 'blue'. These ports are declared in the first code snippet to the right, containing the entity declaration for our 'ball'.
Though the ball was initially loaded to red, one can change this ball color by editing the value of these output signals; this is accomplished within the architecture body, just below the signal declaration section (shown in the bottom code snippet on the right). These signals can take one of four discrete states: 1 (implying this color is active for all screen pixels), 0 (implying this color is off for all screen pixels), ball_on (a signal from the architecture declarations, containing ball pixels), and NOT ball_on (every pixel not contained within the ball). Initially, red was set to be on for all screen pixels, while green and blue were on for all non-ball pixels - the result was a red ball on a white background. This code has been reconfigured to turn green on for ball pixels, blue on for non-ball pixels, and red off completely - the result should be a green ball on a blue background.
Changing the shape of our pong ball requires a deep dive into the bdraw process, a process defined within the body of our 'ball' architecture responsible for drawing the pong ball per frame (the entire process is shown provided to the right). As addressed above in "Change Size of Pong Ball", there is a constant within the architecture called 'size', which defines the radius of our pong ball. Likewise, the "Manipulate RGB Color Output" section addresses a signal called 'ball_on', a boolean that is true if a pixel is within the boundary of our ball. As shown in the commented-out snippet of code, the initial program draws a square by taking the current position of the ball (pixel_col,pixel_row), and encompassing any pixels plus or minus the value of our radius 'size' within ball_on. To draw a circle with the same radius, this computation must be replaced by the equation for a circle, x^2 + y^2 = r^2. Positions for x and y can be computed by taking the difference between the pixel in question, pixel_col/row, and the center of the ball, ball_x/y (since we are taking squared values, negative values are inconsequential). To avoid VGA weirdness, each constituent value must be cast to an integer before evaluation with the IEEE function CONV_INTEGER().
Finally, we can expect most users to desire two-dimensional movement from the pong ball - baseline functionality only sees the pong ball move vertically along a single axis. In order to add a horizontal axis to the pong ball's motion, two changes must be made to the ball.vhd source code. First of all, a new signal, named 'ball_x_motion', must be defined within the architecture declaration section - this is shown in the top snippet to the right, containing the architecture's signal declaration section. Note the default value, '00000000000', refers to the initial velocity of the ball when bouncing in the respective axis.
Once a signal has been added for the x-axis motion of our ball in architecture declarations, the signal behavior must be defined in the 'mball' process, wherein the ball's movement per frame is delineated. The upper section defines the ball's movement along the vertical axis, while the bottom section defines the ball's new movement along the horizontal axis. The value of 800 is specific to the monitor I am using, and may need to be customized according to the dimensions of the VGA monitor this program is ran on.