Skip to content

Instantly share code, notes, and snippets.

@peterzhu2118
Created November 29, 2018 23:43
Show Gist options
  • Save peterzhu2118/b215ce4d8ebdb7e050617615cf0c9aa4 to your computer and use it in GitHub Desktop.
Save peterzhu2118/b215ce4d8ebdb7e050617615cf0c9aa4 to your computer and use it in GitHub Desktop.
CSC258 Project
// start is the signal that (when low) starts the game
// refresh_clk is the clock for the refresh (60Hz)
// adjustment_factor is the number of pixels vertically to adjust by (updates with refresh_clk)
// col_0 to col_5 contains the location of the box on the screen (left most bit is for bottom of screen, right most bit for top)
module beatmap(CLOCK_50, refresh_clk, resetn, start, col_0, col_1, col_2, col_3, col_4, col_5, beatmap_clk);
input CLOCK_50, refresh_clk, resetn, start;
output [4:0] col_0, col_1, col_2, col_3, col_4, col_5;
reg [4:0] col_0, col_1, col_2, col_3, col_4, col_5;
output beatmap_clk;
localparam INIT_BEATMAP_COL_0 = 100'b0000010000000000000000000000000000000000100001001001001000001000000000000000000000000000000000000001;
localparam INIT_BEATMAP_COL_1 = 100'b0000000010000000000000000000000000000000000000000000000001000000100000000000000000010000000000001000;
localparam INIT_BEATMAP_COL_2 = 100'b0000000000010000000000000000000000000000000000000000000000000000000010000001000100000000100000000000;
localparam INIT_BEATMAP_COL_3 = 100'b0000000000000010000000000000000000001000000000000000000000000000000000010000000000010000000010000000;
localparam INIT_BEATMAP_COL_4 = 100'b0000000000000000010000000000000000100000000000000000000000000000000000000001000100000000100000000000;
localparam INIT_BEATMAP_COL_5 = 100'b0000000000000000000010000100100100000000000000000000000000000000000000000000000000000000000010000000;
localparam BEATMAP_LEN = 99;
// reg to hold the beatmaps to shift
// Update this width to match localparam above
reg [BEATMAP_LEN:0] beatmap_col_0, beatmap_col_1, beatmap_col_2, beatmap_col_3, beatmap_col_4, beatmap_col_5;
beatmap_clk bm(
.CLOCK_50(CLOCK_50),
.resetn(resetn),
.clk(beatmap_clk)
);
always @(posedge CLOCK_50)
begin
if (!resetn) begin
col_0 <= 0;
col_1 <= 0;
col_2 <= 0;
col_3 <= 0;
col_4 <= 0;
col_5 <= 0;
beatmap_col_0 <= 0;
beatmap_col_1 <= 0;
beatmap_col_2 <= 0;
beatmap_col_3 <= 0;
beatmap_col_4 <= 0;
beatmap_col_5 <= 0;
end
else if (!start) begin
beatmap_col_0 <= INIT_BEATMAP_COL_0;
beatmap_col_1 <= INIT_BEATMAP_COL_1;
beatmap_col_2 <= INIT_BEATMAP_COL_2;
beatmap_col_3 <= INIT_BEATMAP_COL_3;
beatmap_col_4 <= INIT_BEATMAP_COL_4;
beatmap_col_5 <= INIT_BEATMAP_COL_5;
end
else if (beatmap_clk) begin
col_0 <= beatmap_col_0[BEATMAP_LEN:BEATMAP_LEN-4];
col_1 <= beatmap_col_1[BEATMAP_LEN:BEATMAP_LEN-4];
col_2 <= beatmap_col_2[BEATMAP_LEN:BEATMAP_LEN-4];
col_3 <= beatmap_col_3[BEATMAP_LEN:BEATMAP_LEN-4];
col_4 <= beatmap_col_4[BEATMAP_LEN:BEATMAP_LEN-4];
col_5 <= beatmap_col_5[BEATMAP_LEN:BEATMAP_LEN-4];
beatmap_col_0 = beatmap_col_0 << 1;
beatmap_col_1 = beatmap_col_1 << 1;
beatmap_col_2 = beatmap_col_2 << 1;
beatmap_col_3 = beatmap_col_3 << 1;
beatmap_col_4 = beatmap_col_4 << 1;
beatmap_col_5 = beatmap_col_5 << 1;
end
end
endmodule
module beatmap_adjustment(refresh_clk, beatmap_clk, resetn, adjustment_factor);
input refresh_clk, beatmap_clk, resetn;
output [4:0] adjustment_factor;
reg [4:0] adjustment_factor;
localparam COUNT_TO = 4'd11;
always @(posedge refresh_clk)
begin
if (!resetn)
adjustment_factor <= 0;
else begin
if (beatmap_clk)
adjustment_factor <= 0;
else
adjustment_factor <= adjustment_factor + 1;
end
end
endmodule
// Clock for the beatmap (currently 5Hz)
module beatmap_clk(CLOCK_50, resetn, clk);
input CLOCK_50, resetn;
output clk;
reg clk;
// Count to 9,999,999 for 5Hz
localparam COUNT_TO = 24'd9999999;
//localparam COUNT_TO = 24'd2;
reg [23:0] counter;
always @(posedge CLOCK_50)
begin
if (!resetn) begin
clk <= 0;
counter <= 0;
end
else begin
if (counter == 0) begin
clk <= 0;
counter <= counter + 1;
end
else if (counter == COUNT_TO) begin
clk <= 1;
counter <= 0;
end
else
counter <= counter + 1;
end
end
endmodule
// Each beat is 15x7 (width x height)
module display(CLOCK_50, resetn, col_0, col_1, col_2, col_3, col_4, col_5,
refresh_clk, plot, x, y, color);
input CLOCK_50, resetn;
input [4:0] col_0, col_1, col_2, col_3, col_4, col_5;
output refresh_clk;
output plot;
output [7:0] x;
output [6:0] y;
output [2:0] color;
reg plot;
reg [7:0] x;
reg [6:0] y;
reg [2:0] color;
refresh_clk rc(
.CLOCK_50(CLOCK_50),
.resetn(resetn),
.refresh_clk(refresh_clk)
);
localparam PIECE_HEIGHT = 7'd7,
PIECE_WIDTH = 7'd15;
reg refresh_enable;
reg [2:0] col_counter; // The column we are on (0 to 5, left to right)
reg [2:0] height_block_counter; // The height block we are on (0 to 4, top to bottom)
reg [6:0] draw_counter;
reg [14:0] blk_draw_counter;
reg done_draw_blk;
always @(posedge CLOCK_50)
begin
if (!resetn) begin
refresh_enable <= 0;
col_counter <= 0;
height_block_counter <= 0;
draw_counter <= 0;
plot <= 0;
color <= 3'b0;
x <= 0;
y <= 0;
blk_draw_counter <= 0;
done_draw_blk <= 0;
end
/*********************************
* Clearing the display (drawing black)
**********************************/
else if (!done_draw_blk && refresh_enable) begin
x <= blk_draw_counter / 145;
y <= blk_draw_counter % 145;
plot <= 1;
color <= 0;
blk_draw_counter <= blk_draw_counter + 1;
if (blk_draw_counter == (145 * 120)) begin
blk_draw_counter <= 0;
done_draw_blk <= 1;
end
end
else begin
if (refresh_enable) begin
/*********************************
* Displaying column 0
**********************************/
if (col_counter == 3'd0) begin
if (col_0[height_block_counter] == 1) begin // If there is piece in this block in the column
x <= draw_counter / PIECE_WIDTH + 8'd5; // 5px left margin
y <= draw_counter % PIECE_WIDTH + (7'd24 * height_block_counter);
color <= 3'b111;
if (!(y > 119)) // Plot only if y is still within bounds
plot <= 1;
draw_counter <= draw_counter + 1;
if (draw_counter == PIECE_WIDTH * PIECE_HEIGHT - 1) begin // If the last pixel has been drawn
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
else begin // If there is no piece in this block
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
/*********************************
* Displaying column 1
**********************************/
else if (col_counter == 3'd1) begin
if (col_1[height_block_counter] == 1) begin // If there is piece in this block in the column
x <= draw_counter / PIECE_WIDTH + 8'd25;
y <= draw_counter % PIECE_WIDTH + (7'd24 * height_block_counter);
color <= 3'b111;
if (!(y > 119)) // Plot only if y is still within bounds
plot <= 1;
draw_counter <= draw_counter + 1;
if (draw_counter == PIECE_WIDTH * PIECE_HEIGHT - 1) begin // If the last pixel has been drawn
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
else begin // If there is no piece in this block
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
/*********************************
* Displaying column 2
**********************************/
else if (col_counter == 3'd2) begin
if (col_2[height_block_counter] == 1) begin // If there is piece in this block in the column
x <= draw_counter / PIECE_WIDTH + 8'd45;
y <= draw_counter % PIECE_WIDTH + (7'd24 * height_block_counter);
color <= 3'b111;
if (!(y > 119)) // Plot only if y is still within bounds
plot <= 1;
draw_counter <= draw_counter + 1;
if (draw_counter == PIECE_WIDTH * PIECE_HEIGHT - 1) begin // If the last pixel has been drawn
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
else begin // If there is no piece in this block
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
/*********************************
* Displaying column 3
**********************************/
else if (col_counter == 3'd3) begin
if (col_3[height_block_counter] == 1) begin // If there is piece in this block in the column
x <= draw_counter / PIECE_WIDTH + 8'd65;
y <= draw_counter % PIECE_WIDTH + (7'd24 * height_block_counter);
color <= 3'b111;
if (!(y > 119)) // Plot only if y is still within bounds
plot <= 1;
draw_counter <= draw_counter + 1;
if (draw_counter == PIECE_WIDTH * PIECE_HEIGHT - 1) begin // If the last pixel has been drawn
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
else begin // If there is no piece in this block
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
/*********************************
* Displaying column 4
**********************************/
else if (col_counter == 3'd4) begin
if (col_4[height_block_counter] == 1) begin // If there is piece in this block in the column
x <= draw_counter / PIECE_WIDTH + 8'd85;
y <= draw_counter % PIECE_WIDTH + (7'd24 * height_block_counter);
color <= 3'b111;
if (!(y > 119)) // Plot only if y is still within bounds
plot <= 1;
draw_counter <= draw_counter + 1;
if (draw_counter == PIECE_WIDTH * PIECE_HEIGHT - 1) begin // If the last pixel has been drawn
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
else begin // If there is no piece in this block
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= col_counter + 1;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
/*********************************
* Displaying column 5
**********************************/
else if (col_counter == 3'd5) begin
if (col_5[height_block_counter] == 1) begin // If there is piece in this block in the column
x <= draw_counter / PIECE_WIDTH + 8'd105;
y <= draw_counter % PIECE_WIDTH + (7'd24 * height_block_counter);
color <= 3'b111;
if (!(y > 119)) // Plot only if y is still within bounds
plot <= 1;
draw_counter <= draw_counter + 1;
if (draw_counter == PIECE_WIDTH * PIECE_HEIGHT - 1) begin // If the last pixel has been drawn
draw_counter <= 0;
if (height_block_counter == 4) begin // If it is time to loop to the next column
height_block_counter <= 0;
col_counter <= 0;
refresh_enable <= 0;
done_draw_blk <= 0;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
else begin // If there is no piece in this block
draw_counter <= 0;
if (height_block_counter == 4) begin // If this refresh is over
height_block_counter <= 0;
col_counter <= 0;
refresh_enable <= 0;
done_draw_blk <= 0;
end
else begin // Otherwise, loop to the next block
height_block_counter <= height_block_counter + 1;
end
end
end
end
else begin
if (refresh_clk) begin
refresh_enable <= 1;
col_counter <= 0;
height_block_counter <= 0;
end
end
end
end
endmodule
// Clock for refresh (60Hz)
module refresh_clk(CLOCK_50, resetn, refresh_clk);
input CLOCK_50, resetn;
output refresh_clk;
reg refresh_clk;
// Count to 833,332 (=50,000,000/60) for 60Hz
localparam COUNT_TO = 20'd833332;
//localparam COUNT_TO = 20'd2;
reg [19:0] counter;
always @(posedge CLOCK_50)
begin
if (!resetn) begin
refresh_clk <= 0;
counter <= 0;
end
else begin
if (counter == 0) begin
refresh_clk <= 0;
counter <= counter + 1;
end
else if (counter == COUNT_TO) begin
refresh_clk <= 1;
counter <= 0;
end
else
counter <= counter + 1;
end
end
endmodule
module keyboard(resetn, CLOCK_50, key_pressed, key_code,
col_0, col_1, col_2, col_3, col_4, col_5,
score_changed, correct_press, score, total_score);
input resetn, CLOCK_50;
input key_pressed;
input [7:0] key_code;
input [4:0] col_0, col_1, col_2, col_3, col_4, col_5;
output score_changed, correct_press;
output [7:0] score, total_score;
reg score_changed, correct_press;
reg [7:0] score, total_score;
reg [7:0] prev_key_code;
always @(posedge CLOCK_50)
begin
score_changed <= 0;
correct_press <= 0;
if (!resetn) begin
score <= 0;
prev_key_code <= 0;
total_score <= 0;
end
else if (key_pressed == 1) begin // If a key is pressed
// If this is a key release
if (key_code == 8'b11110000) begin
if (prev_key_code == 8'h1B) begin // If S key is pressed
if (col_0[4] == 1) begin // If this is correct key press
score <= score + 1;
correct_press <= 1;
end
else begin // Otherwise, this is not correct key press
if (score > 0) begin // Only decrease score if score is positive
score <= score - 1;
correct_press <= 0;
end
end
total_score <= total_score + 1;
score_changed <= 1;
end
if (prev_key_code == 8'h23) begin // If D key is pressed
if (col_1[4] == 1) begin // If this is correct key press
score <= score + 1;
correct_press <= 1;
end
else begin // Otherwise, this is not correct key press
if (score > 0) begin // Only decrease score if score is positive
score <= score - 1;
correct_press <= 0;
end
end
total_score <= total_score + 1;
score_changed <= 1;
end
if (prev_key_code == 8'h2B) begin // If F key is pressed
if (col_2[4] == 1) begin // If this is correct key press
score <= score + 1;
correct_press <= 1;
end
else begin // Otherwise, this is not correct key press
if (score > 0) begin // Only decrease score if score is positive
score <= score - 1;
correct_press <= 0;
end
end
total_score <= total_score + 1;
score_changed <= 1;
end
if (prev_key_code == 8'h3B) begin // If J key is pressed
if (col_3[4] == 1) begin // If this is correct key press
score <= score + 1;
correct_press <= 1;
end
else begin // Otherwise, this is not correct key press
if (score > 0) begin // Only decrease score if score is positive
score <= score - 1;
correct_press <= 0;
end
end
total_score <= total_score + 1;
score_changed <= 1;
end
if (prev_key_code == 8'h42) begin // If K key is pressed
if (col_4[4] == 1) begin // If this is correct key press
score <= score + 1;
correct_press <= 1;
end
else begin // Otherwise, this is not correct key press
if (score > 0) begin // Only decrease score if score is positive
score <= score - 1;
correct_press <= 0;
end
end
total_score <= total_score + 1;
score_changed <= 1;
end
if (prev_key_code == 8'h4B) begin // If L key is pressed
if (col_5[4] == 1) begin // If this is correct key press
score <= score + 1;
correct_press <= 1;
end
else begin // Otherwise, this is not correct key press
if (score > 0) begin // Only decrease score if score is positive
score <= score - 1;
correct_press <= 0;
end
end
total_score <= total_score + 1;
score_changed <= 1;
end
prev_key_code <= 0;
end
else begin
prev_key_code <= key_code;
end
end
end
endmodule
module project(
CLOCK_50,
KEY,
HEX0,
HEX1,
HEX2,
HEX3,
PS2_DAT, // PS2 data line
PS2_CLK, // PS2 clock line
VGA_CLK, // VGA Clock
VGA_HS, // VGA H_SYNC
VGA_VS, // VGA V_SYNC
VGA_BLANK_N, // VGA BLANK
VGA_SYNC_N, // VGA SYNC
VGA_R, // VGA Red[9:0]
VGA_G, // VGA Green[9:0]
VGA_B // VGA Blue[9:0]
);
input CLOCK_50;
input [3:0] KEY;
output [6:0] HEX0;
output [6:0] HEX1;
input PS2_DAT; // PS2 data line
input PS2_CLK; // PS2 clock line
// VGA stuff
output VGA_CLK; // VGA Clock
output VGA_HS; // VGA H_SYNC
output VGA_VS; // VGA V_SYNC
output VGA_BLANK_N; // VGA BLANK
output VGA_SYNC_N; // VGA SYNC
output [9:0] VGA_R; // VGA Red[9:0]
output [9:0] VGA_G; // VGA Green[9:0]
output [9:0] VGA_B; // VGA Blue[9:0]
wire resetn;
assign resetn = KEY[0];
wire [2:0] color;
wire [7:0] x;
wire [6:0] y;
wire writeEn;
vga_adapter VGA(
.resetn(resetn),
.clock(CLOCK_50),
.colour(color),
.x(x),
.y(y),
.plot(writeEn),
/* Signals for the DAC to drive the monitor. */
.VGA_R(VGA_R),
.VGA_G(VGA_G),
.VGA_B(VGA_B),
.VGA_HS(VGA_HS),
.VGA_VS(VGA_VS),
.VGA_BLANK(VGA_BLANK_N),
.VGA_SYNC(VGA_SYNC_N),
.VGA_CLK(VGA_CLK));
defparam VGA.RESOLUTION = "160x120";
defparam VGA.MONOCHROME = "FALSE";
defparam VGA.BITS_PER_COLOUR_CHANNEL = 1;
defparam VGA.BACKGROUND_IMAGE = "black.mif";
wire key_pressed;
wire [7:0] out_code;
keyboard_scancoderaw_driver key(
.CLOCK_50(CLOCK_50),
.scan_ready(key_pressed),
.scan_code(out_code),
.PS2_DAT(PS2_DAT),
.PS2_CLK(PS2_CLK),
.reset(reset)
);
wire refresh_clk;
wire [4:0] col_0, col_1, col_2, col_3, col_4, col_5;
wire start;
assign start = KEY[1];
wire beatmap_clk;
beatmap bm(
.CLOCK_50(CLOCK_50),
.refresh_clk(refresh_clk),
.resetn(resetn),
.start(start),
.col_0(col_0),
.col_1(col_1),
.col_2(col_2),
.col_3(col_3),
.col_4(col_4),
.col_5(col_5)
);
display d0(
.CLOCK_50(CLOCK_50),
.resetn(resetn),
.col_0(col_0),
.col_1(col_1),
.col_2(col_2),
.col_3(col_3),
.col_4(col_4),
.col_5(col_5),
.refresh_clk(refresh_clk),
.plot(writeEn),
.x(x),
.y(y),
.color(color)
);
wire score_changed, correct_press;
wire [7:0] score;
wire [7:0] total_score;
keyboard kb(
.resetn(resetn),
.CLOCK_50(CLOCK_50),
.key_pressed(key_pressed),
.key_code(out_code),
.col_0(col_0),
.col_1(col_1),
.col_2(col_2),
.col_3(col_3),
.col_4(col_4),
.col_5(col_5),
.score_changed(score_changed),
.correct_press(correct_press),
.score(score),
.total_score(total_score)
);
hex_decoder h0(
.hex_digit(total_score[3:0]),
.segments(HEX0)
);
hex_decoder h1(
.hex_digit(total_score[7:4]),
.segments(HEX1)
);
hex_decoder h2(
.hex_digit(score[3:0]),
.segments(HEX2)
);
hex_decoder h3(
.hex_digit(score[7:4]),
.segments(HEX3)
);
endmodule
module hex_decoder(hex_digit, segments);
input [3:0] hex_digit;
output reg [6:0] segments;
always @(*)
case (hex_digit)
4'h0: segments = 7'b100_0000;
4'h1: segments = 7'b111_1001;
4'h2: segments = 7'b010_0100;
4'h3: segments = 7'b011_0000;
4'h4: segments = 7'b001_1001;
4'h5: segments = 7'b001_0010;
4'h6: segments = 7'b000_0010;
4'h7: segments = 7'b111_1000;
4'h8: segments = 7'b000_0000;
4'h9: segments = 7'b001_1000;
4'hA: segments = 7'b000_1000;
4'hB: segments = 7'b000_0011;
4'hC: segments = 7'b100_0110;
4'hD: segments = 7'b010_0001;
4'hE: segments = 7'b000_0110;
4'hF: segments = 7'b000_1110;
default: segments = 7'h7f;
endcase
endmodule
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment