Checkoff 02: Some Shapes

Fall 2023

The questions below are due on Wednesday October 04, 2023; 11:59:00 PM.
 
You are not logged in.

Please Log In for full access to the web site.
Note that this link will take you to an external site (https://shimmer.mit.edu) to authenticate, and then you will be redirected back to this page.

For this last part you're going to make some blob shapes (a rectangle and a circle) and then move them around using some of your switches. The behavior is shown below:

A square and circle living on a screen.
The Block Sprite

As a starting point, consider the code below. This simple module builds what is called a "block sprite". Using the specified WIDTH and HEIGHT parameters, this will take in:

  • The x,y location of a shape "concept" you want to draw on screen
  • A hcount and vcount

And will determine what color the output should be. If the hcount and vcount are within the bounds of the block, it'll output the block's color on the red, green, and blue channels. If not, it'll output black.

module block_sprite #(
  parameter WIDTH=128, HEIGHT=128, COLOR=24'hFF_FF_FF)(
  input wire [10:0] hcount_in,
  input wire [9:0] vcount_in,
  input wire [10:0] x_in,
  input wire [9:0]  y_in,
  output logic [7:0] red_out,
  output logic [7:0] green_out,
  output logic [7:0] blue_out);

  logic in_sprite;
  assign in_sprite = ((hcount_in >= x_in && hcount_in < (x_in + WIDTH)) &&
                      (vcount_in >= y_in && vcount_in < (y_in + HEIGHT)));
  always_comb begin
    if (in_sprite)begin
      red_out = COLOR[23:16];
      green_out = COLOR[15:8];
      blue_out = COLOR[7:0];
    end else begin
      red_out = 0;
      green_out = 0;
      blue_out = 0;
    end
  end
endmodule

The bounds of the block sprite are done using rectangular collision detection. Note x and y locations of the sprite are inputs (not parameters) so they can change. This would allow the sprite represnted by this module to move around the screen.

Circles

Now let's consider making a "circle" sprite. Your starting skeleton would look like this:

module circle_sprite #(
  parameter RADIUS=64, COLOR=24'hFF_FF_FF)(
  input wire clk_in,
  input wire rst_in,
  input wire [10:0] hcount_in,
  input wire [9:0] vcount_in,
  input wire [10:0] x_in,
  input wire [9:0]  y_in,
  output logic [7:0] red_out,
  output logic [7:0] green_out,
  output logic [7:0] blue_out);

  //your code here.
endmodule

This module should work largely the same as the box sprite. The big difference though is that it needs to draw a circle. And determining if you are inside/outside a circle is going to involve more "advanced" math. The more math you do, the more logic is needed to do the math. As a result, you may need to split up your logic to fit timing (keep an eye on your Vivado output log. If you try to do much math in one combinational pile, it'll violate timing.

Do you need a square root to determine if you're in a circle? Do you actually?

A Party for Shapes

In the last part we want you to write and then integrate a module that manages two sprite-like objects (as discussed in lecture). One should be a box sprite and one should be a circle sprite. You should use switches as inputs to move the two shapes around the screen. The shapes should be prevented from going off the screen.

Shown again for convenience is how your system should behave (roughly):

It is a party for shapes! Your colors don't have to be the same, but your shapes general movement and behavior should be as shown!

A starter skeleton for this is shown below:

module shape_party(
  input wire clk_in, //
  input wire rst_in,
  input wire [10:0] hcount_in,
  input wire [9:0] vcount_in,
  input wire nf_in,
  input wire [3:0] b_con_in,
  input wire [3:0] c_con_in,
  output logic [7:0] red_out,
  output logic [7:0] green_out,
  output logic [7:0] blue_out
  );
  localparam BOX_DIM = 128;
  localparam CIRC_RAD = 64;

  logic [7:0] box_r, box_g, box_b;
  logic [7:0] circle_r, circle_g, circle_b;
  logic [7:0] shapes_r, shapes_g, shapes_b;

  logic [10:0] box_x;
  logic [9:0] box_y;
  logic [10:0] circle_x;
  logic [9:0] circle_y;

  block_sprite #(
  .WIDTH(BOX_DIM), .HEIGHT(BOX_DIM),.COLOR(24'hFF_7F_00))
  bs(
    .hcount_in(hcount_in),
    .vcount_in(vcount_in),
    .x_in(box_x),
    .y_in(box_y),
    .red_out(box_r),
    .green_out(box_g),
    .blue_out(box_b));

  circle_sprite #(
  .RADIUS(CIRC_RAD),.COLOR(24'hFF_FF_FF))
  cs(
    .clk_in(clk_in),
    .rst_in(rst_in),
    .hcount_in(hcount_in),
    .vcount_in(vcount_in),
    .x_in(circle_x),
    .y_in(circle_y),
    .red_out(circle_r),
    .green_out(circle_g),
    .blue_out(circle_b));

  localparam MOVE_AMT = 5; //amount to move per frame
  //Instructions:
  /*
  Create two sprites:
  * One rectangle with H and W 128 pixels
  * One circle with radius of 64 pixels
  * The two sprites should be able to move around the screen
    using four bits of input directions.  How you use them is up to you.
  * The sprites should not be able to move off the edge of the screen.
  * The sprites are allowed to collide/overlap. How you handle that is up
    to you.
  */
  //your code here.
endmodule //shape_party

Your full, selectable video pipeline with the test pattern generator and the shape party in place. You should be able to alternate between the two of them using sw[2].

Checkoff 2:
For checkoff 2, show your shapes moving around, including: limits on the edge of the screens and independent movement and control of both shapes.