mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-07-05 19:29:03 +00:00
107 lines
3.0 KiB
Coq
107 lines
3.0 KiB
Coq
|
`include "hvsync_generator.v"
|
||
|
|
||
|
module ball_paddle_top(clk, hpaddle, hsync, vsync, rgb);
|
||
|
|
||
|
input clk;
|
||
|
input hpaddle;
|
||
|
output hsync, vsync;
|
||
|
output [2:0] rgb;
|
||
|
wire display_on;
|
||
|
wire [8:0] hpos;
|
||
|
wire [8:0] vpos;
|
||
|
|
||
|
reg [8:0] paddle_pos;
|
||
|
|
||
|
reg [8:0] ball_x = 128;
|
||
|
reg [8:0] ball_y = 128;
|
||
|
reg signed [1:0] ball_vel_x = 0;
|
||
|
reg ball_vel_y = BALL_VEL_DOWN;
|
||
|
|
||
|
localparam BALL_VEL_DOWN = 1;
|
||
|
localparam BALL_VEL_UP = 0;
|
||
|
|
||
|
localparam PADDLE_WIDTH = 31;
|
||
|
localparam BALL_SIZE = 8;
|
||
|
|
||
|
hvsync_generator hvsync_gen(
|
||
|
.clk(clk),
|
||
|
.hsync(hsync),
|
||
|
.vsync(vsync),
|
||
|
.display_on(display_on),
|
||
|
.hpos(hpos),
|
||
|
.vpos(vpos)
|
||
|
);
|
||
|
|
||
|
// TODO: only works when paddle at bottom of screen!
|
||
|
always @(posedge hsync)
|
||
|
if (!hpaddle)
|
||
|
paddle_pos <= vpos;
|
||
|
|
||
|
// TODO: unsigned compare doesn't work in JS
|
||
|
wire [8:0] paddle_rel_x = ((hpos-paddle_pos) & 9'h1ff);
|
||
|
wire paddle_gfx = paddle_rel_x < PADDLE_WIDTH;
|
||
|
|
||
|
wire [8:0] ball_rel_x = (hpos-ball_x);
|
||
|
wire [8:0] ball_rel_y = (vpos-ball_y);
|
||
|
|
||
|
wire ball_gfx = ball_rel_x < BALL_SIZE
|
||
|
&& ball_rel_y < BALL_SIZE;
|
||
|
|
||
|
wire [5:0] hcell = hpos[8:3];
|
||
|
wire [5:0] vcell = vpos[8:3];
|
||
|
wire lr_border = hcell==0 || hcell==31;
|
||
|
|
||
|
wire main_gfx;
|
||
|
|
||
|
always @(posedge clk)
|
||
|
case (vpos[8:3])
|
||
|
0: main_gfx = 1;
|
||
|
28: main_gfx = paddle_gfx | lr_border;
|
||
|
default: main_gfx = lr_border;
|
||
|
endcase;
|
||
|
|
||
|
wire ball_pixel_collide = main_gfx & ball_gfx;
|
||
|
|
||
|
/* verilator lint_off MULTIDRIVEN */
|
||
|
reg [4:0] ball_collide_bits = 0;
|
||
|
/* verilator lint_on MULTIDRIVEN */
|
||
|
|
||
|
always @(posedge clk)
|
||
|
if (ball_pixel_collide) begin
|
||
|
if (paddle_gfx) begin // did we collide w/ paddle?
|
||
|
ball_collide_bits[4] <= 1;
|
||
|
end else begin // collided with playfield
|
||
|
if (!ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[0] <= 1;
|
||
|
if (ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[1] <= 1;
|
||
|
if (!ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[2] <= 1;
|
||
|
if (ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[3] <= 1;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
always @(posedge vsync)
|
||
|
begin
|
||
|
if (ball_collide_bits[4]) begin // collided with paddle?
|
||
|
reg signed [1:0] ball_paddle_dx = ball_x[6:5] - paddle_pos[6:5];
|
||
|
ball_vel_y <= BALL_VEL_UP; // paddle top
|
||
|
ball_vel_x <= ball_vel_x + ball_paddle_dx;
|
||
|
end else casez (ball_collide_bits[3:0]) // collided with playfield
|
||
|
0: ;
|
||
|
4'b01?1: if (ball_vel_x<0) ball_vel_x <= -ball_vel_x-1; // left
|
||
|
4'b101?: if (ball_vel_x>=0) ball_vel_x <= -ball_vel_x-1; // right
|
||
|
4'b1100: ball_vel_y <= BALL_VEL_UP;
|
||
|
4'b0011: ball_vel_y <= BALL_VEL_DOWN;
|
||
|
endcase;
|
||
|
ball_collide_bits <= 0;
|
||
|
ball_x <= ball_x + 9'(ball_vel_x) + 9'(ball_vel_x>=0); // TODO: signed?
|
||
|
ball_y <= ball_y + (ball_vel_y==BALL_VEL_DOWN?1:-1);
|
||
|
end;
|
||
|
|
||
|
wire grid_gfx = (((hpos&7)==0) || ((vpos&7)==0));
|
||
|
|
||
|
wire r = display_on && (grid_gfx | ball_gfx);
|
||
|
wire g = display_on && (main_gfx | ball_gfx);
|
||
|
wire b = display_on && ball_gfx;
|
||
|
assign rgb = {b,g,r};
|
||
|
|
||
|
endmodule
|