├── LICENSE ├── tetris.v ├── tetris_blocks.v ├── tetris_tb.v └── tetris_vga.v /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 jeremycw 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /tetris.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: UNB 4 | // Engineer: Jeremy Williams 5 | // 6 | // Create Date: 17:59:21 11/20/2009 7 | // Design Name: 8 | // Module Name: tetris 9 | // Description: Main module for a 14x20 tetris game. 10 | // 11 | // INPUTS: 12 | // clk 50 mhz system clock 13 | // start pulse to tell the game to start 14 | // left pulse to signal the move left button has been pushed 15 | // right pulse to signal the move right button has been pushed 16 | // rot pulse to signal the rotate button has been pushed 17 | // drop pulse to signal the drop button has been pushed 18 | // 19 | // OUTPUTS: 20 | // r VGA red component 21 | // g VGA green component 22 | // b VGA blue component 23 | // h_sync VGA horizontal sync 24 | // v_sync VGA vertical sync 25 | // 26 | // PIN ASSIGNMENTS: 27 | // clk PIN_N2 28 | // start PIN_V2 (switch 17) 29 | // left PIN_G26 (button 0) 30 | // right PIN_N23 (button 1) 31 | // rot PIN_P23 (button 2) 32 | // drop PIN_W26 (button 3) 33 | // 34 | // h_sync PIN_A7 35 | // v_sync PIN_D8 36 | // 37 | // r[9] PIN_E10 38 | // r[8] PIN_F11 39 | // r[7] PIN_H12 40 | // r[6] PIN_H11 41 | // r[5] PIN_A8 42 | // r[4] PIN_C9 43 | // r[3] PIN_D9 44 | // r[2] PIN_G10 45 | // r[1] PIN_F10 46 | // r[0] PIN_C8 47 | // 48 | // g[9] PIN_D12 49 | // g[8] PIN_E12 50 | // g[7] PIN_D11 51 | // g[6] PIN_G11 52 | // g[5] PIN_A10 53 | // g[4] PIN_B10 54 | // g[3] PIN_D10 55 | // g[2] PIN_C10 56 | // g[1] PIN_A9 57 | // g[0] PIN_B9 58 | // 59 | // b[9] PIN_B12 60 | // b[8] PIN_C12 61 | // b[7] PIN_B11 62 | // b[6] PIN_C11 63 | // b[5] PIN_J11 64 | // b[4] PIN_J10 65 | // b[3] PIN_G12 66 | // b[2] PIN_F12 67 | // b[1] PIN_J14 68 | // b[0] PIN_J13 69 | // 70 | ////////////////////////////////////////////////////////////////////////////////// 71 | 72 | //------------------------------------------------------------------------ 73 | // Top module, connects the ticker to the logic and the logic to the vga 74 | //------------------------------------------------------------------------ 75 | module tetris(input clk, input start, input left, input right, input rotate, input drop, 76 | output h_sync, output v_sync, output blank, output vga_clk, 77 | output[9:0] r, output[9:0] g, output[9:0] b, output[15:0] score); 78 | 79 | wire gfx_clk, game_over, down; 80 | wire[9:0] x,y; 81 | wire[4:0] addr_row; 82 | wire[0:13] d; 83 | wire[7:0] level; 84 | wire left_db, right_db, rotate_db, locked; 85 | 86 | reg[31:0] seed = 0; 87 | 88 | wire rst = start | game_over; 89 | assign vga_clk = ~gfx_clk; 90 | 91 | pll pll(start, clk, gfx_clk, locked); 92 | debounce db_lft(clk, ~left, left_db, rst); 93 | debounce db_rght(clk, ~right, right_db, rst); 94 | debounce db_rt(clk, ~rotate, rotate_db, rst); 95 | debounce db_drp(clk, ~drop, drop_db, rst); 96 | ticker down_ctrl(clk, level, down, rst); 97 | tetris_logic log(clk, gfx_clk, rst, game_over, left_db, right_db, down, rotate_db, drop_db, seed, 98 | addr_row, d, score, level); 99 | sync_gen sg(clk, h_sync, v_sync, blank, gfx_clk, x, y, start); 100 | colour_gen cg(gfx_clk, x, y, d, addr_row, r, g, b, start); 101 | 102 | always @(posedge clk) 103 | seed <= seed+1; 104 | 105 | endmodule 106 | 107 | //------------------------------------------------------------------------ 108 | // Main tetris logic block that controls check_move and the grid 109 | //------------------------------------------------------------------------ 110 | module tetris_logic(input clk, input gfx_clk, input start, output reg game_over, 111 | input left, input right, input down, input rotate, input drop, input[31:0] seed, 112 | input[4:0] addr_row_vga, output[0:13] d_vga, 113 | output[15:0] score, output[7:0] level); 114 | 115 | //state registers 116 | wire[2:0] type; 117 | wire[1:0] rot; 118 | wire[4:0] row; 119 | wire[3:0] col; 120 | reg hit_flag; 121 | reg left_buf, right_buf, down_buf, rotate_buf, drop_buf; 122 | reg[2:0] count; 123 | 124 | wire grid_ready, check_done, ok, hit; 125 | wire[4:0] addr_row; 126 | wire[0:13] d; 127 | wire[2:0] n_lines; 128 | wire[2:0] number; 129 | 130 | wire next = grid_ready & hit_flag | start; 131 | 132 | grid grid(clk, gfx_clk, row, col, type, rot, d, d_vga, addr_row, addr_row_vga, hit, n_lines, start, grid_ready); 133 | check_move chk(clk, d, addr_row, next, left_buf, right_buf, down_buf, rotate_buf, type, row, col, rot, ok, hit, check_done); 134 | scorer sc(clk, n_lines, grid_ready, score, level, start); 135 | rand rand_gen(clk, seed, start, number); 136 | next_block nb(clk, next, number, type, start); 137 | 138 | //hold hit until grid is done writing 139 | always @(posedge clk) 140 | begin 141 | if(hit) 142 | hit_flag <= 1; 143 | if(grid_ready) 144 | hit_flag <= 0; 145 | if(start) 146 | hit_flag <= 0; 147 | end 148 | 149 | //buffer input 150 | always @(posedge clk) 151 | begin 152 | if(left) 153 | left_buf <= left; 154 | if(right) 155 | right_buf <= right; 156 | if(down || drop_buf) 157 | down_buf <= 1; 158 | if(rotate) 159 | rotate_buf <= rotate; 160 | if(drop) 161 | drop_buf <= drop; 162 | if(hit) 163 | drop_buf <= 0; 164 | if(count == 0) begin 165 | right_buf <= right; 166 | left_buf <= left; 167 | down_buf <= down; 168 | rotate_buf <= rotate; 169 | end 170 | if(count < 5) 171 | count <= count+3'd1; 172 | if(next || count == 5) 173 | count <= 0; 174 | if(start) begin 175 | right_buf <= 0; 176 | left_buf <= 0; 177 | down_buf <= 0; 178 | rotate_buf <= 0; 179 | end 180 | end 181 | 182 | //check for game over 183 | always @* 184 | begin 185 | if(row == 0 && col == 6 && check_done && !ok) 186 | game_over = 1; 187 | else 188 | game_over = 0; 189 | end 190 | 191 | endmodule 192 | 193 | //------------------------------------------------------------------------ 194 | // generate pseudo random numbers from 0-7 195 | //------------------------------------------------------------------------ 196 | module rand(input clk, input[31:0] seed, input start, output[2:0] number); 197 | 198 | reg[31:0] seed_reg; 199 | 200 | assign number = start ? seed[31:29] : seed_reg[31:29]; 201 | 202 | always @(posedge clk) 203 | begin 204 | seed_reg <= seed_reg * 1103515245; 205 | if(start) 206 | seed_reg <= seed; 207 | end 208 | 209 | endmodule 210 | 211 | //------------------------------------------------------------------------ 212 | // grid memory writes the current block to memory if en is high 213 | //------------------------------------------------------------------------ 214 | module grid(input clk, input gfx_clk, input[4:0] row, input[3:0] col, input[2:0] type, input[1:0] rot, 215 | output reg[0:13] d, output reg[0:13] d_vga, input[4:0] addr_row, input[4:0] addr_row_vga, 216 | input en, output reg[2:0] n_lines, input rst, output ready); 217 | 218 | reg[0:13] grid[0:19]; 219 | reg[2:0] count; 220 | 221 | wire[0:15] block; 222 | wire[0:13] block_row[0:3]; 223 | 224 | assign block_row[0] = {block[0:3], 10'b0000000000}; 225 | assign block_row[1] = {block[4:7], 10'b0000000000}; 226 | assign block_row[2] = {block[8:11], 10'b0000000000}; 227 | assign block_row[3] = {block[12:15], 10'b0000000000}; 228 | 229 | assign ready = count == 4; 230 | 231 | JIZLOTS_sel write(type, rot, block); 232 | 233 | reg[4:0] i; 234 | always @(posedge clk) 235 | begin 236 | i = 0; 237 | if(en == 1) begin 238 | for(i = 0; i < 4; i = i+5'd1) begin //write the block to the grid 239 | if(col != 15) 240 | grid[row+i] <= (block_row[i] >> col) | grid[row+i]; 241 | else 242 | grid[row+i] <= (block_row[i] << 1) | grid[row+i]; 243 | end 244 | end 245 | //after writing a block to the grid clear lines if they are full 246 | if(count < 4) begin 247 | if(grid[row+count] == 14'b11111111111111) begin 248 | n_lines <= n_lines + 3'd1; 249 | for(i = 5'd20; i > 0; i = i-5'd1) 250 | if(i-1 <= row+count) 251 | if(i-1 > 0) 252 | grid[i-5'd1] <= grid[i-5'd2]; 253 | else 254 | grid[i-5'd1] <= 0; 255 | end 256 | end 257 | if(en) 258 | n_lines <= 0; 259 | if(rst) begin 260 | for(i = 0; i < 20; i = i+5'd1) 261 | grid[i] <= 0; 262 | n_lines <= 0; 263 | end 264 | end 265 | 266 | always @(posedge clk) 267 | begin 268 | if(en) 269 | count <= 0; 270 | if(count < 5) 271 | count <= count+3'd1; 272 | if(rst) begin 273 | count <= 3'd5; 274 | end 275 | end 276 | 277 | always @(posedge clk) 278 | d <= grid[addr_row]; 279 | 280 | 281 | //overlay the current falling block before sending a row off to the vga 282 | wire[0:13] row_overlay = col != 15 ? (block_row[addr_row_vga-row] >> col) : (block_row[addr_row_vga-row] << 1); 283 | always @(posedge gfx_clk) 284 | begin 285 | if(addr_row_vga >= row && addr_row_vga < row+4) 286 | d_vga <= grid[addr_row_vga] | row_overlay; 287 | else 288 | d_vga <= grid[addr_row_vga]; 289 | end 290 | 291 | endmodule 292 | 293 | //------------------------------------------------------------------------ 294 | // check_move checks if a move is valid, signals ok if it is and 295 | // changes the current column, row and rotation to the new ones 296 | //------------------------------------------------------------------------ 297 | module check_move(input clk, input[0:13] d, output reg[4:0] addr_row, input rst, 298 | input left, input right, input down, input rotate, input[2:0] type, 299 | output reg[4:0] row, output reg[3:0] col, output reg[1:0] rot, 300 | output reg ok, output hit, output reg done); 301 | 302 | reg[0:13] row_buf[0:3]; 303 | reg[2:0] count; 304 | reg left_buf, right_buf, down_buf, rotate_buf; 305 | reg[2:0] type_buf; 306 | 307 | wire[0:15] block; 308 | wire[0:13] block_row[0:3]; 309 | wire[0:3] block_col[0:3]; 310 | 311 | assign block_row[0] = {block[0:3], 10'b0000000000}; 312 | assign block_row[1] = {block[4:7], 10'b0000000000}; 313 | assign block_row[2] = {block[8:11], 10'b0000000000}; 314 | assign block_row[3] = {block[12:15], 10'b0000000000}; 315 | 316 | assign block_col[0] = {block[0], block[4], block[8], block[12]}; 317 | assign block_col[1] = {block[1], block[5], block[9], block[13]}; 318 | assign block_col[2] = {block[2], block[6], block[10], block[14]}; 319 | assign block_col[3] = {block[3], block[7], block[11], block[15]}; 320 | 321 | wire[3:0] new_col = col-left_buf+right_buf; 322 | wire[4:0] new_row = row+down_buf; 323 | wire[1:0] new_rot = rot+rotate_buf; 324 | 325 | assign hit = !ok & done & down_buf; 326 | 327 | JIZLOTS_sel check(type_buf, new_rot, block); 328 | 329 | //read in the 4 rows under the current block from grid memory 330 | always @(posedge clk) 331 | begin 332 | case(count) 333 | 1: row_buf[0] <= d; 334 | 2: row_buf[1] <= d; 335 | 3: row_buf[2] <= d; 336 | 4: row_buf[3] <= d; 337 | endcase 338 | end 339 | 340 | always @* 341 | begin 342 | case(count) 343 | 0: addr_row = new_row; 344 | 1: addr_row = new_row+5'd1; 345 | 2: addr_row = new_row+5'd2; 346 | 3: addr_row = new_row+5'd3; 347 | default: addr_row = 0; 348 | endcase 349 | end 350 | 351 | //buffer input 352 | always @(posedge clk) 353 | begin 354 | if(count == 0) begin 355 | left_buf <= left; 356 | right_buf <= right; 357 | rotate_buf <= rotate; 358 | down_buf <= down; 359 | type_buf <= type; 360 | end 361 | if(count < 5) 362 | count <= count + 3'd1; 363 | if(rst || count == 5) 364 | count <= 0; 365 | end 366 | 367 | reg[2:0] i,j; 368 | always @* 369 | begin 370 | ok = 1; 371 | for(i = 0; i < 4; i = i+3'd1) begin //general case 372 | if(new_col != 15) begin 373 | if(((block_row[i] >> new_col) & row_buf[i]) > 0) 374 | ok = 0; 375 | end 376 | else begin 377 | if(((block_row[i] << 1) & row_buf[i]) > 0) 378 | ok = 0; 379 | end 380 | end 381 | if(new_col == 14) //special case: 2 columns off the left 382 | ok = 0; 383 | if(new_col == 15) //special case: 1 column off the left 384 | if(block_col[0] > 0) 385 | ok = 0; 386 | j = 0; 387 | if(new_col > 10 && new_col != 15) begin //special case: off the right of the grid 388 | for(i = 3'd3; i > 0; i = i-3'd1) begin 389 | if(j < (4'd4 - (4'd14-new_col))) begin 390 | if(block_col[i] > 0) 391 | ok = 0; 392 | j = j+3'd1; 393 | end 394 | end 395 | end 396 | j = 0; 397 | if(new_row > 16) begin //special case: off the bottom of the grid 398 | for(i = 3'd3; i > 0; i = i-3'd1) begin 399 | if(j < (5'd4 - (5'd20-new_row))) begin 400 | if(block_row[i] > 0) 401 | ok = 0; 402 | j = j+3'd1; 403 | end 404 | end 405 | end 406 | end 407 | 408 | always @* 409 | begin 410 | if(count == 5) 411 | done = 1; 412 | else 413 | done = 0; 414 | end 415 | 416 | //update row, column and rotation of the block if it is valid 417 | always @(posedge clk) 418 | begin 419 | if(ok && done) begin 420 | col <= new_col; 421 | row <= new_row; 422 | rot <= new_rot; 423 | end 424 | if(rst) begin 425 | col <= 4'd6; 426 | row <= 0; 427 | rot <= 0; 428 | end 429 | end 430 | 431 | endmodule 432 | 433 | //------------------------------------------------------------------------ 434 | // keeps score, the forumal is 435 | // new score = current score + 436 | // (lines cleared with the last move)^2 * current level 437 | // when 6 lines are cleared the level increases 438 | //------------------------------------------------------------------------ 439 | module scorer(input clk, input[2:0] n_lines, input start, output reg[15:0] score, output reg[7:0] level, input rst); 440 | 441 | reg[3:0] lines; 442 | 443 | //calculate score and level 444 | always @(posedge clk) 445 | begin 446 | if(start) begin 447 | score <= score + n_lines * n_lines * level; 448 | lines <= lines + n_lines; 449 | end 450 | if(lines >= 6) begin 451 | lines <= 0; 452 | level <= level + 8'd1; 453 | end 454 | if(rst) begin 455 | level <= 1; 456 | lines <= 0; 457 | score <= 0; 458 | end 459 | end 460 | 461 | endmodule 462 | 463 | //------------------------------------------------------------------------ 464 | // gets the next block 465 | //------------------------------------------------------------------------ 466 | module next_block(input clk, input next, input[2:0] rand, output reg[2:0] type, input rst); 467 | 468 | reg[2:0] count; 469 | 470 | always @(posedge clk) 471 | begin 472 | if(next) begin 473 | if(rand > 6) begin //compensates for when rand = 7 474 | type <= count; 475 | count <= count+3'd1; 476 | end 477 | else 478 | type <= rand; 479 | end 480 | if(count == 6) 481 | count <= 0; 482 | if(rst) begin 483 | count <= 0; 484 | if(rand > 6) 485 | type <= 0; 486 | else 487 | type <= rand; 488 | end 489 | end 490 | 491 | endmodule 492 | 493 | //------------------------------------------------------------------------ 494 | // make an input only last one clock cycle 495 | //------------------------------------------------------------------------ 496 | module debounce(input clk, input d, output q, input rst); 497 | 498 | reg down; 499 | 500 | assign q = d & !down; 501 | 502 | always @(posedge clk) 503 | begin 504 | if(q) 505 | down <= 1; 506 | if(!d) 507 | down <= 0; 508 | if(rst) 509 | down <= 0; 510 | end 511 | 512 | endmodule 513 | 514 | //------------------------------------------------------------------------ 515 | // based on the level generate a constant tick for the down input 516 | //------------------------------------------------------------------------ 517 | module ticker(input clk, input[7:0] level, output reg tick, input rst); 518 | 519 | reg[31:0] cycles; 520 | reg[4:0] count; 521 | 522 | always @(posedge clk) 523 | begin 524 | if(cycles < 2000000) //1/25th of a second 525 | cycles <= cycles+1; 526 | else begin 527 | cycles <= 0; 528 | count <= count+5'd1; 529 | end 530 | if(count == 5'd25-level) begin //25 levels until blocks fall at the rate of the clock 531 | count <= 0; 532 | tick <= 1; 533 | end 534 | if(tick) 535 | tick <= 0; 536 | if(rst) begin 537 | tick <= 0; 538 | count <= 0; 539 | cycles <= 0; 540 | end 541 | end 542 | 543 | endmodule 544 | -------------------------------------------------------------------------------- /tetris_blocks.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 19:41:11 11/25/2009 7 | // Design Name: 8 | // Module Name: tetris_blocks 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | 22 | //------------------------------------------------------------------------ 23 | // given a type and rotation outputs the block encoded in a 16 bit int 24 | //------------------------------------------------------------------------ 25 | module JIZLOTS_sel(input[2:0] type, input[1:0] rot, output reg[0:15] block); 26 | 27 | wire[0:15] block_t, block_z, block_s, block_j, block_l, block_o, block_i; 28 | 29 | T_sel t(rot, block_t); 30 | Z_sel z(rot, block_z); 31 | S_sel s(rot, block_s); 32 | J_sel j(rot, block_j); 33 | L_sel l(rot, block_l); 34 | O_sel o(rot, block_o); 35 | I_sel i(rot, block_i); 36 | 37 | always @* 38 | begin 39 | case(type) 40 | 0: block = block_t; 41 | 1: block = block_z; 42 | 2: block = block_s; 43 | 3: block = block_j; 44 | 4: block = block_l; 45 | 5: block = block_o; 46 | 6: block = block_i; 47 | default: block = 0; //shouldn't happen 48 | endcase 49 | end 50 | 51 | endmodule 52 | 53 | module T_sel(input[1:0] rot, output reg[0:15] block); 54 | 55 | wire[0:15] t0 = 16'b1110010000000000; 56 | wire[0:15] t1 = 16'b0010011000100000; 57 | wire[0:15] t2 = 16'b0000010011100000; 58 | wire[0:15] t3 = 16'b1000110010000000; 59 | 60 | always @* 61 | begin 62 | case(rot) 63 | 0: block = t0; 64 | 1: block = t1; 65 | 2: block = t2; 66 | 3: block = t3; 67 | default: block = t0; 68 | endcase 69 | end 70 | 71 | endmodule 72 | 73 | module Z_sel(input[1:0] rot, output reg[0:15] block); 74 | 75 | wire[0:15] z0 = 16'b1100011000000000; 76 | wire[0:15] z1 = 16'b0010011001000000; 77 | wire[0:15] z2 = 16'b0000110001100000; 78 | wire[0:15] z3 = 16'b0100110010000000; 79 | 80 | always @* 81 | begin 82 | case(rot) 83 | 0: block = z0; 84 | 1: block = z1; 85 | 2: block = z2; 86 | 3: block = z3; 87 | default: block = z0; 88 | endcase 89 | end 90 | 91 | endmodule 92 | 93 | module S_sel(input[1:0] rot, output reg[0:15] block); 94 | 95 | wire[0:15] s0 = 16'b0110110000000000; 96 | wire[0:15] s1 = 16'b0100011000100000; 97 | wire[0:15] s2 = 16'b0000011011000000; 98 | wire[0:15] s3 = 16'b1000110001000000; 99 | 100 | always @* 101 | begin 102 | case(rot) 103 | 0: block = s0; 104 | 1: block = s1; 105 | 2: block = s2; 106 | 3: block = s3; 107 | default: block = s0; 108 | endcase 109 | end 110 | 111 | endmodule 112 | 113 | module J_sel(input[1:0] rot, output reg[0:15] block); 114 | 115 | wire[0:15] j0 = 16'b0100010011000000; 116 | wire[0:15] j1 = 16'b1000111000000000; 117 | wire[0:15] j2 = 16'b0110010001000000; 118 | wire[0:15] j3 = 16'b0000111000100000; 119 | 120 | always @* 121 | begin 122 | case(rot) 123 | 0: block = j0; 124 | 1: block = j1; 125 | 2: block = j2; 126 | 3: block = j3; 127 | default: block = j0; 128 | endcase 129 | end 130 | 131 | endmodule 132 | 133 | module L_sel(input[1:0] rot, output reg[0:15] block); 134 | 135 | wire[0:15] l0 = 16'b0100010011000000; 136 | wire[0:15] l1 = 16'b0000111010000000; 137 | wire[0:15] l2 = 16'b1100010001000000; 138 | wire[0:15] l3 = 16'b0010111000000000; 139 | 140 | always @* 141 | begin 142 | case(rot) 143 | 0: block = l0; 144 | 1: block = l1; 145 | 2: block = l2; 146 | 3: block = l3; 147 | default: block = l0; 148 | endcase 149 | end 150 | 151 | endmodule 152 | 153 | module O_sel(input[1:0] rot, output reg[0:15] block); 154 | 155 | wire[0:15] o0 = 16'b1100110000000000; 156 | 157 | always @* 158 | begin 159 | case(rot) 160 | default: block = o0; 161 | endcase 162 | end 163 | 164 | endmodule 165 | 166 | module I_sel(input[1:0] rot, output reg[0:15] block); 167 | 168 | wire[0:15] i0 = 16'b1000100010001000; 169 | wire[0:15] i1 = 16'b0000000011110000; 170 | 171 | always @* 172 | begin 173 | case(rot) 174 | 0: block = i0; 175 | 1: block = i1; 176 | 2: block = i0; 177 | 3: block = i1; 178 | default: block = i0; 179 | endcase 180 | end 181 | 182 | endmodule 183 | 184 | -------------------------------------------------------------------------------- /tetris_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 23:51:39 11/23/2009 7 | // Design Name: 8 | // Module Name: tetris_tb 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | ////////////////////////////////////////////////////////////////////////////////// 21 | module grid_tb; 22 | 23 | reg clk; 24 | reg[4:0] row; 25 | reg[3:0] col; 26 | reg[2:0] type; 27 | reg[1:0] rot; 28 | reg en, start; 29 | wire ready; 30 | 31 | reg[2:0] count; 32 | 33 | wire[2:0] n_lines; 34 | 35 | grid mem(clk, row, col, type, rot, en, n_lines, start, ready); 36 | 37 | initial begin 38 | start <= 1; 39 | type <= 5; 40 | rot <= 0; 41 | clk <= 1; 42 | row <= 18; 43 | end 44 | 45 | always @(posedge clk) begin 46 | if(count == 4) 47 | count <= 0; 48 | else 49 | count <= count +1; 50 | if(start == 1) begin 51 | start <= 0; 52 | count <= 4; 53 | col <= 0; 54 | end 55 | end 56 | 57 | always @(posedge clk) begin 58 | if(count == 3) 59 | col <= col + 2; 60 | if(count == 4) 61 | en <= 1; 62 | else 63 | en <= 0; 64 | end 65 | 66 | always begin 67 | #5 clk = !clk; 68 | end 69 | 70 | endmodule 71 | 72 | module jizlots_tb; 73 | 74 | reg clk; 75 | 76 | reg[2:0] type; 77 | reg[1:0] rot; 78 | 79 | wire[0:15] block_out; 80 | 81 | JIZLOTS_sel write(type, rot, block_out); 82 | 83 | initial begin 84 | clk <= 0; 85 | type <= 0; 86 | rot <= 0; 87 | end 88 | 89 | always begin 90 | #5 clk = !clk; 91 | end 92 | 93 | endmodule 94 | 95 | module check_move_tb; 96 | 97 | reg clk; 98 | wire[4:0] row; 99 | wire[3:0] col; 100 | reg[2:0] type; 101 | wire[1:0] rot_out; 102 | reg start, left, right, down, rot, rst; 103 | wire done, ok, hit; 104 | 105 | reg[0:13] d; 106 | wire[4:0] addr_row; 107 | 108 | wire[0:15] fake[0:19]; 109 | 110 | assign fake[0] = 14'b00000000000000; 111 | assign fake[1] = 14'b00000000000000; 112 | assign fake[2] = 14'b00000000000000; 113 | assign fake[3] = 14'b00000000000000; 114 | assign fake[4] = 14'b00000000000000; 115 | assign fake[5] = 14'b00000000000000; 116 | assign fake[6] = 14'b00000000000000; 117 | assign fake[7] = 14'b00000000000000; 118 | assign fake[8] = 14'b00000000000000; 119 | assign fake[9] = 14'b00000000000000; 120 | assign fake[10] = 14'b00000000000000; 121 | assign fake[11] = 14'b00000000000000; 122 | assign fake[12] = 14'b00000000000000; 123 | assign fake[13] = 14'b00000000000000; 124 | assign fake[14] = 14'b00000000000000; 125 | assign fake[15] = 14'b00000000000000; 126 | assign fake[16] = 14'b00000000000000; 127 | assign fake[17] = 14'b00000000000000; 128 | assign fake[18] = 14'b00000000000000; 129 | assign fake[19] = 14'b11111111111111; 130 | 131 | check_move chk1(clk, d, addr_row, rst, left, right, down, rot, type, row, col, rot_out, ok, hit, done); 132 | 133 | initial begin 134 | rst = 1; 135 | left <= 0; 136 | right <= 0; 137 | down <= 1; 138 | rot <= 1; 139 | type <= 5; 140 | clk = 1; 141 | #10 rst <= 0; 142 | end 143 | 144 | always @(posedge clk) 145 | begin 146 | d <= fake[addr_row]; 147 | end 148 | 149 | always begin 150 | #5 clk = !clk; 151 | end 152 | 153 | endmodule 154 | 155 | module sync_gen_tb; 156 | 157 | reg clk; 158 | reg rst; 159 | wire h_sync, v_sync, gfx_clk; 160 | wire[9:0] x,y; 161 | wire[3:0] r,g,b; 162 | wire[4:0] addr_row; 163 | 164 | reg[0:13] d; 165 | wire[0:13] fake[0:3]; 166 | 167 | assign fake[0] = 14'b00001100010001; 168 | assign fake[1] = 14'b00011100010011; 169 | assign fake[2] = 14'b11110000010001; 170 | assign fake[3] = 14'b11000000011001; 171 | 172 | sync_gen sg(clk, h_sync, v_sync, gfx_clk, x, y, rst); 173 | colour_gen cg(gfx_clk, x, y, d, addr_row, r, g, b, rst); 174 | 175 | initial begin 176 | rst = 1; 177 | clk <= 1; 178 | #10 rst <= 0; 179 | end 180 | 181 | always @(posedge clk) 182 | begin 183 | d <= fake[addr_row]; 184 | end 185 | 186 | always begin 187 | #5 clk = !clk; 188 | end 189 | 190 | endmodule 191 | 192 | module tetris_tb; 193 | 194 | reg clk = 1; 195 | reg start = 1; 196 | reg left, right, rot; 197 | wire h_sync, v_sync; 198 | wire[9:0] r,g,b; 199 | reg drop; 200 | 201 | tetris tet(clk, start, left, right, rot, drop, h_sync, v_sync, r, g, b); 202 | 203 | initial begin 204 | #10 start <= 0; 205 | left <= 0; 206 | right <= 0; 207 | rot <= 0; 208 | #120 rot <= 1; 209 | drop <= 1; 210 | end 211 | 212 | always begin 213 | #5 clk = !clk; 214 | end 215 | 216 | endmodule 217 | -------------------------------------------------------------------------------- /tetris_vga.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | ////////////////////////////////////////////////////////////////////////////////// 3 | // Company: 4 | // Engineer: 5 | // 6 | // Create Date: 17:37:41 11/25/2009 7 | // Design Name: 8 | // Module Name: tetris_vga 9 | // Project Name: 10 | // Target Devices: 11 | // Tool versions: 12 | // Description: 13 | // 14 | // Dependencies: 15 | // 16 | // Revision: 17 | // Revision 0.01 - File Created 18 | // Additional Comments: 19 | // 20 | // H_SYNC: 21 | // Scanline time 800 cycles@25mhz 22 | // Pulse length 96 cycles@25mhz 23 | // Back porch 47 cycles@25mhz 24 | // 25 | // 26 | ////////////////////////////////////////////////////////////////////////////////// 27 | 28 | //------------------------------------------------------------------------ 29 | // generate the vga control signals and x/y, the current pixel position 30 | //------------------------------------------------------------------------ 31 | module sync_gen(input clk, output h_sync, output v_sync, output blank, 32 | input gfx_clk, output[9:0] x, output[9:0] y, input rst); 33 | 34 | reg[9:0] hcount, vcount; 35 | 36 | assign h_sync = hcount < 96 ? 1'b0 : 1'b1; 37 | assign v_sync = vcount < 2 ? 1'b0 : 1'b1; 38 | assign blank = h_sync & v_sync; 39 | 40 | assign x = hcount - 10'd144; //Pulse length + back porch 41 | assign y = vcount - 10'd34; 42 | 43 | always @(posedge gfx_clk) 44 | begin 45 | if(hcount < 800) 46 | hcount <= hcount+10'd1; 47 | else begin 48 | hcount <= 0; 49 | vcount <= vcount+10'd1; 50 | end 51 | if(vcount == 525) 52 | vcount <= 0; 53 | if(rst) begin 54 | hcount <= 0; 55 | vcount <= 0; 56 | end 57 | end 58 | 59 | endmodule 60 | 61 | //------------------------------------------------------------------------ 62 | // given x and y generate the pixel colour 63 | //------------------------------------------------------------------------ 64 | module colour_gen(input clk, input[9:0] x, input[9:0] y, input[0:13] d, output reg[4:0] addr_row, 65 | output reg[9:0] r, output reg[9:0] g, output reg[9:0] b, input rst); 66 | 67 | reg[0:13] row_buf; 68 | reg[4:0] ycount; 69 | 70 | //read in the row at addr_row from grid memory 71 | always @(posedge clk) 72 | row_buf <= d; 73 | 74 | //determine which row is needed from grid memory 75 | always @(posedge clk) 76 | begin 77 | if(x == 640 && y < 480) 78 | ycount <= ycount+5'd1; 79 | if(ycount == 24) begin 80 | ycount <= 0; 81 | addr_row <= addr_row+5'd1; 82 | end 83 | if(addr_row == 19 && ycount == 24) 84 | addr_row <= 0; 85 | if(rst) begin 86 | addr_row <= 0; 87 | ycount <= 0; 88 | end 89 | end 90 | 91 | //based on the the current contents of row_buf generate r, g and b 92 | always @(posedge clk) 93 | begin 94 | if(x > 639 || y > 479) begin 95 | r <= 0; 96 | g <= 0; 97 | b <= 0; 98 | end 99 | else if(x < 152 || x >= 488) begin 100 | r <= {8'd136,2'b0}; 101 | g <= {8'd138,2'b0}; 102 | b <= {8'd133,2'b0}; 103 | end 104 | else if(x < 176) begin 105 | if(row_buf[0]) begin 106 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 107 | end 108 | else begin 109 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 110 | end 111 | end 112 | else if(x < 200) begin 113 | if(row_buf[1]) begin 114 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 115 | end 116 | else begin 117 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 118 | end 119 | end 120 | else if(x < 224) begin 121 | if(row_buf[2]) begin 122 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 123 | end 124 | else begin 125 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 126 | end 127 | end 128 | else if(x < 248) begin 129 | if(row_buf[3]) begin 130 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 131 | end 132 | else begin 133 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 134 | end 135 | end 136 | else if(x < 272) begin 137 | if(row_buf[4]) begin 138 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 139 | end 140 | else begin 141 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 142 | end 143 | end 144 | else if(x < 296) begin 145 | if(row_buf[5]) begin 146 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 147 | end 148 | else begin 149 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 150 | end 151 | end 152 | else if(x < 320) begin 153 | if(row_buf[6]) begin 154 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 155 | end 156 | else begin 157 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 158 | end 159 | end 160 | else if(x < 344) begin 161 | if(row_buf[7]) begin 162 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 163 | end 164 | else begin 165 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 166 | end 167 | end 168 | else if(x < 368) begin 169 | if(row_buf[8]) begin 170 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 171 | end 172 | else begin 173 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 174 | end 175 | end 176 | else if(x < 392) begin 177 | if(row_buf[9]) begin 178 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 179 | end 180 | else begin 181 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 182 | end 183 | end 184 | else if(x < 416) begin 185 | if(row_buf[10]) begin 186 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 187 | end 188 | else begin 189 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 190 | end 191 | end 192 | else if(x < 440) begin 193 | if(row_buf[11]) begin 194 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 195 | end 196 | else begin 197 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 198 | end 199 | end 200 | else if(x < 464) begin 201 | if(row_buf[12]) begin 202 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 203 | end 204 | else begin 205 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 206 | end 207 | end 208 | else if(x < 488) begin 209 | if(row_buf[13]) begin 210 | r <= {8'd115,2'b0}; g <= {8'd210,2'b0}; b <= {8'd22,2'b0}; 211 | end 212 | else begin 213 | r <= {8'd85,2'b0}; g <= {8'd87,2'b0}; b <= {8'd83,2'b0}; 214 | end 215 | end 216 | end 217 | 218 | endmodule 219 | --------------------------------------------------------------------------------