User Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
labs:pong_part_1 [2019/06/11 11:55]
jgoeders [Exercise #3 - Drawing Pong Objects on the VGA Display]
labs:pong_part_1 [2019/11/15 10:30] (current)
jgoeders [Exercise #2 - BallDrawer SystemVerilog Module]
Line 1: Line 1:
 ====== Pong: Part 1 ====== ====== Pong: Part 1 ======
  
-This lab and the next lab work together to build a Pong game on the VGA display. ​  +This lab and the next lab work together to build a Pong game on the VGA display.  ​In this lab you will create two modules, a ball drawer and a vertical line drawer. 
-  * Exercise 1 & 2Creating ​a BallDrawer ​module that will output (xy) coordinates that can be used to draw a ball+  * Exercise 1: Designing ​a BallDrawer ​state machine on paper. 
-  * Exercise 3: Connecting ​your BallDrawer ​module to BitmapToVga module that is given to you, to display your ball on the screen.  +  * Exercise 2: Implementing the BallDrawer state machine in SystemVerilogand verify with simulation
-  * Exercise 4: Create a VLineDrawer module that draws vertical lines. ​+  * Exercise 3: Testing that your BallDrawer ​state machine correctly displays ​a ball on the VGA display
 +  * Exercise 4: Create a VLineDrawer module that draws vertical lines, simulate, and test with the VGA display.
  
 /* **Note:** Exercise 4 is optional. ​ You might not have time to complete it in this lab.  You will still get full points for pass-off without it, but if you want to complete a full Pong game next lab you will need it.  If you choose not to complete it, next week you will make a ball bounce around the screen (but without paddles and user interaction). */ /* **Note:** Exercise 4 is optional. ​ You might not have time to complete it in this lab.  You will still get full points for pass-off without it, but if you want to complete a full Pong game next lab you will need it.  If you choose not to complete it, next week you will make a ball bounce around the screen (but without paddles and user interaction). */
Line 14: Line 15:
 =====Preliminary===== =====Preliminary=====
  
-Read about the [[resources:​vga_drawer|BitmapToVga]] module ​that is given to you.  ​This allows ​you to draw pixels to the VGA monitor. ​ You should read about how the module works now, but you won't need to add it to your design until Exercise #3.+In this lab you will again be using the [[resources:​vga_drawer|BitmapToVga]] module.  ​Make sure you remember ​how this module works.
  
-<color #ed1c24>How many bits are required ​to specify ​the x-coordinate in the 320x240 bitmap image?</​color>​+<color #ed1c24>What 3-bit binary value would you provide ​to the module to set the color of a pixel to cyan ​Provide your answer in SystemVerilog literal form (ex 3'​b000).</​color>​
  
- +<color #ed1c24>Assuming you can write 1 pixel per clock cycle, what is the minimum number of cycles required to change the entire image to blue? How many microseconds would this take, given your system clock?
-<color #ed1c24>How many bits are required to specify the y-coordinate in the 320x240 bitmap image?</​color>​ +
- +
-<color #​ed1c24>​What ​is the minimum number of cycles required to change the entire image to blue? How many microseconds would this take, given your system clock?+
 </​color>​ </​color>​
  
-<color #​ed1c24>​What is the purpose of the ''​wr_en''​ signal?</​color>​ 
  
  
Line 38: Line 35:
 | clk | Input | 1 | 100 MHz Input Clock | | clk | Input | 1 | 100 MHz Input Clock |
 | reset | Input | 1 | Reset | | reset | Input | 1 | Reset |
-| start | Input | 1 | High to start drawing a ball |+| start| Input | 1 | High to start drawing a ball, must go back low before drawing another ball. | 
 +| draw | Output | 1 | High when the module is outputting a valid pixel location to draw|
 | done | Output | 1 | High on cycle that last pixel location is output |  | done | Output | 1 | High on cycle that last pixel location is output | 
 | x_in | Input | 9 | Leftmost x-Coordinate of ball to be drawn | | x_in | Input | 9 | Leftmost x-Coordinate of ball to be drawn |
Line 45: Line 43:
 | y_out | Output | 8 | y-Coordinate to be drawn | | y_out | Output | 8 | y-Coordinate to be drawn |
  
-The module should output (''​x_out'',​ ''​y_out''​) coordinates to write to, starting with the cycle immediately following the assertion of the ''​start''​ signal, and continue each cycle until complete. ​ The ''​done''​ signal should be asserted during the cycle of the last pixel. + The following shows a diagram of a ball with 5 pixels, and corresponding waveform for drawing this ball at (100,​50).  ​
- +
- The following shows a diagram of a ball with 5 pixels, and the corresponding waveform for drawing this ball at (100,​50).  ​+
  
 {{:​labs:​lab_pong:​ball_drawing_5.png| }} {{:​labs:​lab_pong:​ball_drawing_5.png| }}
 +{{:​labs:​lab_pong:​ball_drawing2.png| }}
  
-{{:labs:​lab_pong:​ball_drawing_waveform.png| }}+Your state machine does not need to produce the exact same timing as the waveform above, but it does not to obey a few rules: 
 +  * The state machine should wait for the ''​start''​ signal before starting to draw a ball.  
 +  * For each pixel that needs to be drawn, the state machine should output an (x,y) coordinate using the ''​x_out''​ and ''​y_out''​ outputs, and assert the ''​draw''​ signal to indicate that a valid pixel is being output. ​  
 +  * The ''​done''​ signal should be asserted for exactly 1 cycle after the ball is done being drawn (or during the last pixel). ​  
 +  * The state machine should wait for the ''​start''​ signal to go low before allowing another ball to be drawn.
  
  
Line 60: Line 61:
  
  
-<color #​ed1c24>​Did you make sure that your state machine will produce the correct behavior, based on the timing diagram above?  Make sure that the first pixel location is output in the cycle immediately after start goes high, that a new pixel is output every cycle, and that the done signal is asserted during the last pixel (not afterwards</​color>​). 
  
 ** Exercise #1 Pass-off:** Show the TA your state machine and describe how you verified that it meets the requirements described above. ** Exercise #1 Pass-off:** Show the TA your state machine and describe how you verified that it meets the requirements described above.
Line 69: Line 69:
 Create the ''​BallDrawer''​ SystemVerilog module that implements your state machine. Create the ''​BallDrawer''​ SystemVerilog module that implements your state machine.
  
-Simulate your ''​BallDrawer''​ module to ensure it meets the timing behavior shown above. ​  +<code SystemVerilog>​ 
- +module ​BallDrawer ​(
-<color #​ed1c24>​Include a copy of your TCL file in your lab report.</​color>​ +
- +
- +
-** Exercise #2 Pass-off:** Show the TA a simulation of your ''​BallDrawer''​ module. ​ The waveform should be similar to above. ​ You can choose the (''​x_in'',​ ''​y_in''​) values, but make sure they are non-zero values. +
- +
----- +
-==== Exercise #3 - Drawing Pong Objects on the VGA Display ==== +
- +
-In this exercise you will create a ''​Pong''​ module that draws draws two balls to the screen. +
- +
-The top-level ​SystemVerilog ​file is provided below. ​ It instantiates the ''​BitmapToVga''​ module and the ''​glk_generator''​ module needed to draw graphics on the VGA monitor. ​ Your ''​Pong''​ module is also instantiated,​ and note how the modules are connected. ​ Your ''​Pong''​ module is responsible for generating the signals to write pixels to the bitmap.  +
- +
- ​**Note:​ You shouldn'​t change the top-level file**. ​ However, be sure to add a constraints file to your project that is configured appropriately. ​  The top-level module contains connections for the buttons. ​ You don't need to use the buttons in this lab, but you will be using them in the next lab.  Make sure you include the appropriate constraints for them now, otherwise Vivado will error when compiling the project. +
- +
-<file verilog top_pong.sv+
-/​*************************************************************************** +
-* Module: top_pong +
-+
-* Author: Jeff Goeders +
-* Date: May 13, 2019 +
-+
-* Description:​ Top-level ​module ​for Pong on Nexys4DDR board. +
-****************************************************************************/​ +
- +
-`default_nettype none +
- +
-module top_pong(+
     input wire logic            clk,     input wire logic            clk,
-    input wire logic            ​CPU_RESETN, +    input wire logic            ​reset
- +    ​input wire logic            start
-    ​output ​logic        ​[3:​0] ​  ​VGA_R,​ +    output logic                ​draw
-    output logic        [3:0]   ​VGA_G,​ +    output logic                ​done,     
-    output logic        [3:0]   VGA_B+    input wire logic    ​[8:​0] ​  x_in
-    output logic                ​VGA_HS+    input wire logic    ​[7:​0] ​  y_in
-    output logic                ​VGA_VS, +    ​output ​logic        ​[8:​0] ​  x_out
- +    ​output ​logic        ​[7:​0] ​  y_out
-     +
-    input wire logic            btnu+
-    input wire logic            btnd+
-    ​input wire logic            btnl+
-    ​input wire logic            btnr+
 ); );
- 
-logic           ​clk_100;​ 
-logic           ​clk_25;​ 
-logic           ​reset;​ 
- 
-logic   ​[2:​0] ​  ​vga_color;​ 
-logic   ​[8:​0] ​  ​vga_x;​ 
-logic   ​[7:​0] ​  ​vga_y;​ 
-logic           ​vga_wr_en;​ 
- 
-assign reset = ~CPU_RESETN;​ 
- 
-Pong Pong_inst( 
-    .clk(clk_100),​ 
-    .reset(reset),​ 
-    .paddle1_up(btnu),​ 
-    .paddle1_down(btnl),​ 
-    .paddle2_up(btnr),​ 
-    .paddle2_down(btnd),​ 
-    .vga_x(vga_x),​ 
-    .vga_y(vga_y),​ 
-    .vga_wr_en(vga_wr_en),​ 
-    .vga_color(vga_color) 
-); 
- 
-clk_generator clk_generator_inst 
- ( 
-    .clk_100(clk_100),​ 
-    .clk_25(clk_25),​ 
-    .clk_in_100(clk) 
- ); 
- 
-BitmapToVga BitmapToVga_inst( 
-    .VGA_R(VGA_R),​ 
-    .VGA_G(VGA_G),​ 
-    .VGA_B(VGA_B),​ 
-    .clk(clk_100),​ 
-    .clk_vga(clk_25),​ 
-    .VGA_hsync(VGA_HS),​ 
-    .VGA_vsync(VGA_VS),​ 
-    .reset(reset),​ 
-    .wr_en(vga_wr_en),​ 
-    .x(vga_x), 
-    .y(vga_y), 
-    .color(vga_color) 
-); 
- 
  
 endmodule endmodule
-</file>+</code>
  
-Your ''​Pong''​ module contains the ports described here: 
  
-^ Module Name = Pong ^^^^ +Simulate your ''​BallDrawer''​ module. ​ You can use the following TCL script. ​ It will test drawing your Ball in two different locations. ​ Make sure your state machine doesn'​t draw the second ball until the ''​start''​ signal goes low and then back high the second time. (Remember that on the waveform you can select multiple signals and right-click to change the radix. ​ It may be helpful to display the x,y coordinates as unsigned decimal).
-^ Port Name ^ Direction ^ Width ^ Description ^ +
-| clk | Input | 1 | 100 MHz Clock | +
-| reset | Input | 1 | Active-high reset | +
-| paddle1_up | Input | 1 | When high, move left paddle up | +
-| paddle1_down | Input | 1 | When high, move left paddle down| +
-| paddle2_up | Input | 1 | When high, move right paddle up | +
-| paddle2_down | Input | 1 | When highmove right paddle down | +
-| vga_x | Output | 9 | BitmapToVga X-Coordinate | +
-| vga_y | Output | 8 | BitmapToVga Y-Coordinate | +
-| vga_color | Output | 3 | BitmapToVga Color | +
-| vga_wr_en | Output | 1 | BitmapToVga Write Enable |+
  
 +<file tcl>
 +restart
  
-A file has been provided to you to get started:+add_force clk {0 0} {1 5ns} -repeat_every 10ns 
 +add_force reset 1 
 +add_force start 0 
 +run 10ns 
 +add_force reset 0 
 +run 10ns
  
-<file verilog Pong.sv> +# Draw ball at 100, 200 
-// Add your header here+add_force x_in -radix dec 100 
 +add_force y_in -radix dec 200 
 +add_force start 1 
 +run 120ns
  
-`default_nettype none+# Lower start signal 
 +add_force start 0 
 +run 20ns
  
-module Pong ( +# Draw ball at 15020 
-    input wire logic        clk, +add_force ​x_in -radix dec 150 
-    input wire logic        reset, +add_force ​y_in -radix dec 20 
- +add_force start 1 
-    input wire logic        paddle1_up,​ +run 120ns
-    input wire logic        paddle1_down,​ +
-    input wire logic        paddle2_up,​ +
-    input wire logic        paddle2_down,​ +
- +
-    output logic    [8:0]   ​vga_x,​ +
-    output logic    [7:0]   ​vga_y,​ +
-    output logic    [2:0]   ​vga_color,​ +
-    output logic            vga_wr_en +
-); +
- +
- +
-/////// Create a state machine here ////// +
-// +
-// Your state machine should provide start, x_in and y_in to the BallDrawer +
-// Use the done signal from the BallDrawer to determine when a ball is done drawing +
-// +
-// Your state machine should also control the vga_color and vga_wr_en signals  +
- +
- +
-//////////////////​ Ball Drawing /////////////////////​ +
-BallDrawer BallDrawer_inst( +
-    .clk(clk)+
-    ​.reset(reset),​ +
-    .start(/* Todo */), +
-    .done(/* Todo */), +
-    .x_in(/* Todo */), +
-    .y_in(/* Todo */), +
-    .x_out(/* Todo */), +
-    .y_out(/* Todo */) +
-); +
- +
-endmodule+
 </​file>​ </​file>​
  
  
-** For this exercise, ​your ''​Pong''​ module ​should draw 2 or more balls on the screen of different colorYou can choose the locations.**+** Exercise #2 Pass-off:** Show the TA a simulation of your ''​BallDrawer''​ module ​and explain how you tested its functionality.
  
-__ You may notice that the ''​Pong''​ module includes one instantiation of the ''​BallDrawer''​. ​ You SHOULD NOT add any more instantiations of this module. ​ This one instantiation will be used to draw all of the balls.__+---- 
 +==== Exercise #3 - Drawing ​Pong Objects on the VGA Display ====
  
-The provided ​''​Pong''​ module ​provides ​good starting point. ​ You will need to add a state machine that: +In this exercise you will verify that your ''​BallDrawer''​ module ​works correctly, by drawing ​ball to the VGA display.  ​The following top-level module can be used.  ​Look it over and make sure you understand it
-  * Draws the first ball, then draws the second ball +
-  * Your state machine will need to control the start, x and y signals that are input to the BallDrawer. +
-  * Your state machine will also need to control the ''​vga_color'' ​and ''​vga_wr_en''​ outputs, to instruct the VgaDrawer when to draw pixels, and which color to draw them. +
-  * Decide how you will connect the ''​vga_x''​ and ''​vga_y''​ outputs. +
-  * Remember to use the ''​done''​ signal from the ''​BallDrawer''​ to determine when the ball is done drawing, allowing your state machine to transition to drawing the next ball.+
  
-**Tip:** //So far, when you have designed your state machine modules, you have placed all of your input/​output logic in a single ​''​always_comb'' ​block. ​ However, as you begin to design larger and more complex modules (including this lab), you may find your code is more readable if you split the logic into multiple blocks.  ​There are many different ways you can structure your circuits in SystemVerilog,​ and it takes experience ​to learn which ways are best.  In this part of the lab, you might want to try organizing your code using a few always blocks. ​ For example, you might use one ''​always_comb''​ for the next state logic, another block to control the x/y/color VGA outputs, and perhaps another ​to control ​the x/y inputs to your ball and line drawer modules.//+The module works by connecting up the appropriate signals from your ''​BallDrawer'' ​module ​to the ''​BitmapToVga''​ module.  ​You shouldn'​t have to change ​this file to get it to work properly; however, you may decide ​to change it later to modify ​the ball location or color.
  
 +{{ :​labs:​lab_pong:​top_object_drawer.sv |}}
  
-**Exercise #3 Pass-Off:** Show your display ​to the TA.  ​The TA will verify that you are drawing two balls on the screen of different color, and that you are using only one instance of your ''​BallDrawer''​ module.+Add the above file to your Vivado project and make sure it is configured as the top-level module.  ​Add a constraints file to your project that is configured appropriately  ​
  
 +**Exercise #3 Pass-Off:** Show your display to the TA.  The TA will verify that you are successfully drawing a ball on the screen.
  
 ---- ----
-==== Exercise #4 - Line Drawer ​(10% of lab pass-off grade) ​====+==== Exercise #4 - Line Drawer ====
 /* ** You only need to complete this exercise if you want to complete the full Pong game next lab.** */ /* ** You only need to complete this exercise if you want to complete the full Pong game next lab.** */
  
 +Now that you have created a module to draw a ball, you will follow the same process to create a module that can draw vertical lines of arbitrary height.
  
-Create the following module ​that can be used to draw a vertical line.  Use a state machine to implement the described behavior.+Create the following module. ​ Use a state machine to implement the described behavior.
  
 ^ Module Name = VLineDrawer ^^^^ ^ Module Name = VLineDrawer ^^^^
Line 256: Line 144:
 | reset | Input | 1 | Reset | | reset | Input | 1 | Reset |
 | start | Input | 1 | High to start drawing a line | | start | Input | 1 | High to start drawing a line |
-| done | Output | 1 | High one cycle that last pixel is drawn | +| draw | Output | 1 | High when the module is outputting a valid pixel location to draw | 
 +| done | Output | 1 | High on cycle that last pixel is drawn | 
 | x_in | Input | 9 | x-Coordinate of line to be drawn | | x_in | Input | 9 | x-Coordinate of line to be drawn |
 | y_in | Input | 8 | y-Coordinate of top of the line | | y_in | Input | 8 | y-Coordinate of top of the line |
Line 263: Line 152:
 | y_out | Output | 8 | y-Coordinate to be drawn | | y_out | Output | 8 | y-Coordinate to be drawn |
  
-The module should ​output (''​x_out'',​ ''​y_out''​) coordinates to write to, starting with the cycle immediately following the assertion ​of the ''​start''​ signal, and continue each cycle until complete.  ​The ''​done''​ signal should be asserted during the cycle of the last pixel.+This module should ​work very similarly to your ''​BallDrawer'' ​moduleexcept now there is a ''​height'' ​input that dictates ​the height ​of the line.  Since the height can be changed, you can't use one state per pixel being drawn.  ​Instead, your state machine will need to interact with a counter to keep track of how many pixels you need to draw.
  
-The following shows a diagram of a line 6 pixels tall, and the corresponding ​waveform for drawing this line at (100, 50).+The following shows a diagram of a line 6 pixels tall, and waveform for drawing this line at (100, 50).
  
 {{:​labs:​lab_pong:​line_drawing.png |}} {{:​labs:​lab_pong:​line_drawing.png |}}
Line 271: Line 160:
 {{:​labs:​lab_pong:​line_drawing_waveform.png|}} {{:​labs:​lab_pong:​line_drawing_waveform.png|}}
  
 +Simulate your ''​VLineDrawer''​ module to ensure it is working correctly. ​ You can probably re-use the TCL above with minimal changes. ​ Make sure to set the ''​height''​ input, and test drawing two lines of different height.
 +
 +<color #​ed1c24>​Paste your TCL simulation file in your lab report.</​color>​
 +
 +Modify the top-level from the last exercise to draw a vertical line instead of a ball.
  
 \\ \\
-** Exercise #4 Pass-off:​** ​Add the VLineDrawer to your top-level ​module ​from the last exercise, ​and change your state machine to draw a line and a ball.  Show the TA the display.+** Exercise #4 Pass-off:​** ​Show the TA your ''​VLineDrawer'' ​module and the line drawing correctly on the monitor. 
 + 
 +---- 
 + 
 +==== Final Pass-Off ===
  
 +<color red>​Submit your final lab report on Learning Suite. ​ Submit the SystemVerilog code of your two modules.</​color> ​
  
 +There is no personal exploration for this lab.