182 lines
4.1 KiB
Coq
182 lines
4.1 KiB
Coq
|
module Pong(
|
||
|
input i_Clk,
|
||
|
input i_HSync,
|
||
|
input i_VSync,
|
||
|
|
||
|
input i_GameStart,
|
||
|
|
||
|
input i_Player1_Up,
|
||
|
input i_Player1_Down,
|
||
|
input i_Player2_Up,
|
||
|
input i_Player2_Down,
|
||
|
|
||
|
output reg o_HSync,
|
||
|
output reg o_VSync,
|
||
|
output [2:0] o_Red,
|
||
|
output [2:0] o_Green,
|
||
|
output [2:0] o_Blue
|
||
|
);
|
||
|
parameter TOTAL_COLUMNS = 800;
|
||
|
parameter TOTAL_ROWS = 525;
|
||
|
|
||
|
parameter ACTIVE_COLUMNS = 640;
|
||
|
parameter ACTIVE_ROWS = 480;
|
||
|
|
||
|
localparam SCREEN_WIDTH_CELLS = 40;
|
||
|
localparam SCREEN_HEIGHT_CELLS = 30;
|
||
|
localparam SCORE_LIMIT = 9;
|
||
|
localparam PADDLE_HEIGHT = 6;
|
||
|
localparam PADDLE_PLAYER1_X = 0;
|
||
|
localparam PADDLE_PLAYER2_X = SCREEN_WIDTH_CELLS - 1;
|
||
|
|
||
|
localparam STATE_IDLE = 0;
|
||
|
localparam STATE_RUNNING = 1;
|
||
|
localparam STATE_P1_WINNER = 2;
|
||
|
localparam STATE_P2_WINNER = 3;
|
||
|
localparam STATE_CLEANUP = 4;
|
||
|
|
||
|
reg [2:0] r_currentState = STATE_IDLE;
|
||
|
|
||
|
wire w_HSync, w_VSync;
|
||
|
wire [9:0] w_X, w_Y;
|
||
|
|
||
|
wire w_P1_DoDrawPaddle, w_P2_DoDrawPaddle;
|
||
|
wire [5:0] w_P1_PaddleY, w_P2_PaddleY;
|
||
|
wire w_DoDrawBall, w_DrawAny;
|
||
|
wire [5:0] w_BallX, w_BallY;
|
||
|
wire w_IsGameActive;
|
||
|
|
||
|
reg [3:0] r_P1_Score = 0;
|
||
|
reg [3:0] r_P2_Score = 0;
|
||
|
|
||
|
wire [5:0] w_CellX, w_CellY;
|
||
|
|
||
|
VGA_Current_Beam_Position #(
|
||
|
.TOTAL_COLUMNS(TOTAL_COLUMNS),
|
||
|
.TOTAL_ROWS(TOTAL_ROWS)
|
||
|
) CurrentPosition (
|
||
|
.i_Clk(i_Clk),
|
||
|
.i_HSync(i_HSync),
|
||
|
.i_VSync(i_VSync),
|
||
|
.o_HSync(w_HSync),
|
||
|
.o_VSync(w_VSync),
|
||
|
.o_X(w_X),
|
||
|
.o_Y(w_Y)
|
||
|
);
|
||
|
|
||
|
always @(posedge i_Clk) begin
|
||
|
o_HSync <= w_HSync;
|
||
|
o_VSync <= w_VSync;
|
||
|
end
|
||
|
|
||
|
// right shift 4
|
||
|
assign w_CellX = w_X[9:4];
|
||
|
assign w_CellY = w_Y[9:4];
|
||
|
|
||
|
// paddles
|
||
|
|
||
|
PongPaddle #(
|
||
|
.X_POS_CELLS(PADDLE_PLAYER1_X),
|
||
|
.SCREEN_HEIGHT_CELLS(SCREEN_HEIGHT_CELLS),
|
||
|
.PADDLE_HEIGHT_CELLS(PADDLE_HEIGHT)
|
||
|
) P1_Paddle (
|
||
|
.i_Clk(i_Clk),
|
||
|
.i_CellX(w_CellX),
|
||
|
.i_CellY(w_CellY),
|
||
|
.i_PaddleUp(i_Player1_Up),
|
||
|
.i_PaddleDown(i_Player1_Down),
|
||
|
.o_DoDrawPaddle(w_P1_DoDrawPaddle),
|
||
|
.o_PaddleY(w_P1_PaddleY)
|
||
|
);
|
||
|
|
||
|
PongPaddle #(
|
||
|
.X_POS_CELLS(PADDLE_PLAYER2_X),
|
||
|
.SCREEN_HEIGHT_CELLS(SCREEN_HEIGHT_CELLS),
|
||
|
.PADDLE_HEIGHT_CELLS(PADDLE_HEIGHT)
|
||
|
) P2_Paddle (
|
||
|
.i_Clk(i_Clk),
|
||
|
.i_CellX(w_CellX),
|
||
|
.i_CellY(w_CellY),
|
||
|
.i_PaddleUp(i_Player2_Up),
|
||
|
.i_PaddleDown(i_Player2_Down),
|
||
|
.o_DoDrawPaddle(w_P2_DoDrawPaddle),
|
||
|
.o_PaddleY(w_P2_PaddleY)
|
||
|
);
|
||
|
|
||
|
PongBall #(
|
||
|
.SCREEN_WIDTH_CELLS(SCREEN_WIDTH_CELLS),
|
||
|
.SCREEN_HEIGHT_CELLS(SCREEN_HEIGHT_CELLS)
|
||
|
) Ball (
|
||
|
.i_Clk(i_Clk),
|
||
|
.i_IsGameActive(w_IsGameActive),
|
||
|
.i_CellX(w_CellX),
|
||
|
.i_CellY(w_CellY),
|
||
|
.o_DoDrawBall(w_DoDrawBall),
|
||
|
.o_BallX(w_BallX),
|
||
|
.o_BallY(w_BallY)
|
||
|
);
|
||
|
|
||
|
always @(posedge i_Clk) begin
|
||
|
case (r_currentState)
|
||
|
STATE_IDLE:
|
||
|
begin
|
||
|
if (i_GameStart) begin
|
||
|
r_currentState <= STATE_RUNNING;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
STATE_RUNNING:
|
||
|
begin
|
||
|
if (
|
||
|
w_BallX == 0 && (
|
||
|
w_BallY < w_P1_PaddleY ||
|
||
|
w_BallY > w_P1_PaddleY + PADDLE_HEIGHT
|
||
|
)
|
||
|
) begin
|
||
|
r_currentState <= STATE_P1_WINNER;
|
||
|
end else if (
|
||
|
w_BallX == SCREEN_WIDTH_CELLS - 1 && (
|
||
|
w_BallY < w_P2_PaddleY ||
|
||
|
w_BallY > w_P2_PaddleY + PADDLE_HEIGHT
|
||
|
)
|
||
|
) begin
|
||
|
r_currentState <= STATE_P2_WINNER;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
STATE_P1_WINNER:
|
||
|
begin
|
||
|
if (r_P1_Score == SCORE_LIMIT - 1) begin
|
||
|
r_P1_Score <= 0;
|
||
|
end else begin
|
||
|
r_P1_Score <= r_P1_Score + 1;
|
||
|
r_currentState <= STATE_CLEANUP;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
STATE_P2_WINNER:
|
||
|
begin
|
||
|
if (r_P2_Score == SCORE_LIMIT - 1) begin
|
||
|
r_P2_Score <= 0;
|
||
|
end else begin
|
||
|
r_P2_Score <= r_P2_Score + 1;
|
||
|
r_currentState <= STATE_CLEANUP;
|
||
|
end
|
||
|
end
|
||
|
|
||
|
STATE_CLEANUP:
|
||
|
begin
|
||
|
r_currentState <= STATE_IDLE;
|
||
|
end
|
||
|
endcase
|
||
|
end
|
||
|
|
||
|
assign w_IsGameActive = (r_currentState == STATE_RUNNING) ? 1 : 0;
|
||
|
|
||
|
assign w_DrawAny = w_DoDrawBall | w_P1_DoDrawPaddle | w_P2_DoDrawPaddle;
|
||
|
|
||
|
assign o_Red = w_DrawAny ? 7 : 0;
|
||
|
assign o_Green = w_DrawAny ? 7 : 0;
|
||
|
assign o_Blue = w_DrawAny ? 7 : 0;
|
||
|
endmodule
|