| 1 |
215 |
creep |
////////////////////////////////////////////////////////////////////////////
|
| 2 |
|
|
//// ////
|
| 3 |
|
|
//// t2600 IP Core ////
|
| 4 |
|
|
//// ////
|
| 5 |
|
|
//// This file is part of the t2600 project ////
|
| 6 |
|
|
//// http://www.opencores.org/cores/t2600/ ////
|
| 7 |
|
|
//// ////
|
| 8 |
|
|
//// Description ////
|
| 9 |
|
|
//// Video module ////
|
| 10 |
|
|
//// ////
|
| 11 |
|
|
//// TODO: ////
|
| 12 |
235 |
creep |
//// - Collision detection ////
|
| 13 |
|
|
//// - Pixel output ////
|
| 14 |
|
|
//// ////
|
| 15 |
215 |
creep |
//// Author(s): ////
|
| 16 |
|
|
//// - Gabriel Oshiro Zardo, gabrieloshiro@gmail.com ////
|
| 17 |
|
|
//// - Samuel Nascimento Pagliarini (creep), snpagliarini@gmail.com ////
|
| 18 |
|
|
//// ////
|
| 19 |
|
|
////////////////////////////////////////////////////////////////////////////
|
| 20 |
|
|
//// ////
|
| 21 |
|
|
//// Copyright (C) 2001 Authors and OPENCORES.ORG ////
|
| 22 |
|
|
//// ////
|
| 23 |
|
|
//// This source file may be used and distributed without ////
|
| 24 |
|
|
//// restriction provided that this copyright statement is not ////
|
| 25 |
|
|
//// removed from the file and that any derivative work contains ////
|
| 26 |
|
|
//// the original copyright notice and the associated disclaimer. ////
|
| 27 |
|
|
//// ////
|
| 28 |
|
|
//// This source file is free software; you can redistribute it ////
|
| 29 |
|
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
| 30 |
|
|
//// Public License as published by the Free Software Foundation; ////
|
| 31 |
|
|
//// either version 2.1 of the License, or (at your option) any ////
|
| 32 |
|
|
//// later version. ////
|
| 33 |
|
|
//// ////
|
| 34 |
|
|
//// This source is distributed in the hope that it will be ////
|
| 35 |
|
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
| 36 |
|
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
| 37 |
|
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
| 38 |
|
|
//// details. ////
|
| 39 |
|
|
//// ////
|
| 40 |
|
|
//// You should have received a copy of the GNU Lesser General ////
|
| 41 |
|
|
//// Public License along with this source; if not, download it ////
|
| 42 |
|
|
//// from http://www.opencores.org/lgpl.shtml ////
|
| 43 |
|
|
//// ////
|
| 44 |
|
|
////////////////////////////////////////////////////////////////////////////
|
| 45 |
|
|
|
| 46 |
|
|
`include "timescale.v"
|
| 47 |
|
|
|
| 48 |
235 |
creep |
module video(clk, reset_n, io_lines, enable, mem_rw, address, data, pixel, write_addr, write_data, write_enable_n);
|
| 49 |
215 |
creep |
parameter [3:0] DATA_SIZE = 4'd8;
|
| 50 |
|
|
parameter [3:0] ADDR_SIZE = 4'd10; // this is the *local* addr_size
|
| 51 |
|
|
|
| 52 |
|
|
localparam [3:0] DATA_SIZE_ = DATA_SIZE - 4'd1;
|
| 53 |
|
|
localparam [3:0] ADDR_SIZE_ = ADDR_SIZE - 4'd1;
|
| 54 |
|
|
|
| 55 |
|
|
input clk; // master clock signal, 1.19mhz
|
| 56 |
|
|
input reset_n;
|
| 57 |
|
|
input [15:0] io_lines; // inputs from the keyboard controller
|
| 58 |
|
|
input enable; // since the address bus is shared an enable signal is used
|
| 59 |
|
|
input mem_rw; // read == 0, write == 1
|
| 60 |
|
|
input [ADDR_SIZE_:0] address; // system address bus
|
| 61 |
235 |
creep |
inout [DATA_SIZE_:0] data; // controler <=> video data bus
|
| 62 |
|
|
output reg [2:0] pixel;
|
| 63 |
|
|
output reg [10:0] write_addr; // for the video memory
|
| 64 |
|
|
output reg [2:0] write_data;
|
| 65 |
|
|
output reg write_enable_n;
|
| 66 |
|
|
|
| 67 |
215 |
creep |
reg [DATA_SIZE_:0] data_drv; // wrapper for the data bus
|
| 68 |
|
|
|
| 69 |
|
|
assign data = (mem_rw || !reset_n) ? 8'bZ : data_drv; // if under writing the bus receives the data from cpu, else local data.
|
| 70 |
|
|
|
| 71 |
|
|
reg VSYNC; // vertical sync set-clear
|
| 72 |
216 |
creep |
reg [2:0] VBLANK; // vertical blank set-clear
|
| 73 |
222 |
creep |
reg WSYNC; // SEMI-strobe wait for leading edge of horizontal blank
|
| 74 |
215 |
creep |
reg RSYNC; // s t r o b e reset horizontal sync counter
|
| 75 |
216 |
creep |
reg [5:0] NUSIZ0; // number-size player-missile 0
|
| 76 |
|
|
reg [5:0] NUSIZ1; // number-size player-missile 1
|
| 77 |
|
|
reg [6:0] COLUP0; // color-lum player 0
|
| 78 |
|
|
reg [6:0] COLUP1; // color-lum player 1
|
| 79 |
|
|
reg [6:0] COLUPF; // color-lum playfield
|
| 80 |
|
|
reg [6:0] COLUBK; // color-lum background
|
| 81 |
|
|
reg [4:0] CTRLPF; // control playfield ball size & collisions
|
| 82 |
221 |
creep |
// D0 = REF (reflect playfield)
|
| 83 |
|
|
// D1 = SCORE (left half of playfield gets color of player 0, right half gets color of player 1)
|
| 84 |
|
|
// D2 = PFP (playfield gets priority over players so they can move behind the playfield)
|
| 85 |
|
|
// D4 & D5 = BALL SIZE
|
| 86 |
216 |
creep |
reg REFP0; // reflect player 0
|
| 87 |
|
|
reg REFP1; // reflect player 1
|
| 88 |
|
|
reg [3:0] PF0; // playfield register byte 0
|
| 89 |
|
|
reg [7:0] PF1; // playfield register byte 1
|
| 90 |
|
|
reg [7:0] PF2; // playfield register byte 2
|
| 91 |
237 |
creep |
// all the RES register became combinational logic
|
| 92 |
235 |
creep |
//reg RESP0; // s t r o b e reset player 0
|
| 93 |
237 |
creep |
//reg RESP1; // s t r o b e reset player 1
|
| 94 |
|
|
//reg RESM0; // s t r o b e reset missile 0
|
| 95 |
|
|
//reg RESM1; // s t r o b e reset missile 1
|
| 96 |
|
|
//reg RESBL; // s t r o b e reset ball
|
| 97 |
216 |
creep |
reg [3:0] AUDC0; // audio control 0
|
| 98 |
|
|
reg [4:0] AUDC1; // audio control 1
|
| 99 |
|
|
reg [4:0] AUDF0; // audio frequency 0
|
| 100 |
|
|
reg [3:0] AUDF1; // audio frequency 1
|
| 101 |
|
|
reg [3:0] AUDV0; // audio volume 0
|
| 102 |
|
|
reg [3:0] AUDV1; // audio volume 1
|
| 103 |
|
|
reg [7:0] GRP0; // graphics player 0
|
| 104 |
|
|
reg [7:0] GRP1; // graphics player 1
|
| 105 |
|
|
reg ENAM0; // graphics (enable) missile 0
|
| 106 |
|
|
reg ENAM1; // graphics (enable) missile 1
|
| 107 |
|
|
reg ENABL; // graphics (enable) ball
|
| 108 |
|
|
reg [3:0] HMP0; // horizontal motion player 0
|
| 109 |
|
|
reg [3:0] HMP1; // horizontal motion player 1
|
| 110 |
|
|
reg [3:0] HMM0; // horizontal motion missile 0
|
| 111 |
|
|
reg [3:0] HMM1; // horizontal motion missile 1
|
| 112 |
|
|
reg [3:0] HMBL; // horizontal motion ball
|
| 113 |
|
|
reg VDELP0; // vertical delay player 0
|
| 114 |
|
|
reg VDEL01; // vertical delay player 1
|
| 115 |
|
|
reg VDELBL; // vertical delay ball
|
| 116 |
|
|
reg RESMP0; // reset missile 0 to player 0
|
| 117 |
|
|
reg RESMP1; // reset missile 1 to player 1
|
| 118 |
215 |
creep |
reg HMOVE; // s t r o b e apply horizontal motion
|
| 119 |
|
|
reg HMCLR; // s t r o b e clear horizontal motion registers
|
| 120 |
|
|
|
| 121 |
216 |
creep |
reg [1:0] CXM0P; // read collision MO P1 M0 P0
|
| 122 |
|
|
reg [1:0] CXM1P; // read collision M1 P0 M1 P1
|
| 123 |
|
|
reg [1:0] CXP0FB; // read collision P0 PF P0 BL
|
| 124 |
|
|
reg [1:0] CXP1FB; // read collision P1 PF P1 BL
|
| 125 |
|
|
reg [1:0] CXM0FB; // read collision M0 PF M0 BL
|
| 126 |
|
|
reg [1:0] CXM1FB; // read collision M1 PF M1 BL
|
| 127 |
|
|
reg CXBLPF; // read collision BL PF unused
|
| 128 |
|
|
reg [1:0] CXPPMM; // read collision P0 P1 M0 M1
|
| 129 |
|
|
reg INPT0; // read pot port
|
| 130 |
|
|
reg INPT1; // read pot port
|
| 131 |
|
|
reg INPT2; // read pot port
|
| 132 |
|
|
reg INPT3; // read pot port
|
| 133 |
|
|
reg INPT4; // read input
|
| 134 |
222 |
creep |
reg INPT5; // read input
|
| 135 |
216 |
creep |
|
| 136 |
235 |
creep |
reg [8:0] vert_counter;
|
| 137 |
|
|
reg [7:0] hor_counter;
|
| 138 |
222 |
creep |
|
| 139 |
216 |
creep |
always @(posedge clk or negedge reset_n) begin
|
| 140 |
215 |
creep |
if (reset_n == 1'b0) begin
|
| 141 |
235 |
creep |
hor_counter <= 8'd0;
|
| 142 |
|
|
vert_counter <= 9'd0;
|
| 143 |
222 |
creep |
end
|
| 144 |
|
|
else begin
|
| 145 |
235 |
creep |
if (hor_counter == 8'd227) begin
|
| 146 |
|
|
hor_counter <= 8'd0;
|
| 147 |
|
|
WSYNC <= 1'b0; // TODO: check this on stella pdf
|
| 148 |
|
|
|
| 149 |
|
|
if (vert_counter == 9'd261) begin
|
| 150 |
|
|
vert_counter <= 9'd0;
|
| 151 |
|
|
end
|
| 152 |
|
|
else begin
|
| 153 |
|
|
vert_counter <= vert_counter + 9'd1;
|
| 154 |
|
|
end
|
| 155 |
222 |
creep |
end
|
| 156 |
|
|
else begin
|
| 157 |
|
|
hor_counter <= hor_counter + 6'd1;
|
| 158 |
|
|
end
|
| 159 |
|
|
end
|
| 160 |
|
|
end
|
| 161 |
|
|
|
| 162 |
|
|
always @(posedge clk or negedge reset_n) begin
|
| 163 |
|
|
if (reset_n == 1'b0) begin
|
| 164 |
215 |
creep |
data_drv <= 8'h00;
|
| 165 |
222 |
creep |
WSYNC <= 1'b0;
|
| 166 |
215 |
creep |
end
|
| 167 |
235 |
creep |
else if (enable == 1'b1) begin
|
| 168 |
216 |
creep |
if (mem_rw == 1'b0) begin // reading!
|
| 169 |
215 |
creep |
case (address)
|
| 170 |
216 |
creep |
6'h00: data_drv <= {CXM0P, 6'b000000};
|
| 171 |
|
|
6'h01: data_drv <= {CXM1P, 6'b000000};
|
| 172 |
|
|
6'h02: data_drv <= {CXP0FB, 6'b000000};
|
| 173 |
|
|
6'h03: data_drv <= {CXP1FB, 6'b000000};
|
| 174 |
|
|
6'h04: data_drv <= {CXM0FB, 6'b000000};
|
| 175 |
|
|
6'h05: data_drv <= {CXM1FB, 6'b000000};
|
| 176 |
|
|
6'h06: data_drv <= {CXBLPF, 7'b000000};
|
| 177 |
|
|
6'h07: data_drv <= {CXPPMM, 6'b000000};
|
| 178 |
|
|
6'h08: data_drv <= {INPT0, 7'b000000};
|
| 179 |
|
|
6'h09: data_drv <= {INPT1, 7'b000000};
|
| 180 |
|
|
6'h0A: data_drv <= {INPT2, 7'b000000};
|
| 181 |
|
|
6'h0B: data_drv <= {INPT3, 7'b000000};
|
| 182 |
|
|
6'h0C: data_drv <= {INPT4, 7'b000000};
|
| 183 |
|
|
6'h0D: data_drv <= {INPT5, 7'b000000};
|
| 184 |
|
|
default: ;
|
| 185 |
215 |
creep |
endcase
|
| 186 |
|
|
end
|
| 187 |
216 |
creep |
else begin // writing!
|
| 188 |
215 |
creep |
case (address)
|
| 189 |
216 |
creep |
6'h00: begin
|
| 190 |
217 |
creep |
VSYNC <= data[1];
|
| 191 |
215 |
creep |
end
|
| 192 |
216 |
creep |
6'h01: begin
|
| 193 |
217 |
creep |
VBLANK <= {data[7:6], data[1]};
|
| 194 |
215 |
creep |
end
|
| 195 |
216 |
creep |
6'h02: begin
|
| 196 |
217 |
creep |
WSYNC <= 1'b1; // STROBE
|
| 197 |
215 |
creep |
end
|
| 198 |
216 |
creep |
6'h03: begin
|
| 199 |
217 |
creep |
RSYNC <= 1'b1; // STROBE
|
| 200 |
215 |
creep |
end
|
| 201 |
216 |
creep |
6'h04: begin
|
| 202 |
217 |
creep |
NUSIZ0 <= data[5:0];
|
| 203 |
216 |
creep |
end
|
| 204 |
|
|
6'h05: begin
|
| 205 |
217 |
creep |
NUSIZ1 <= data[5:0];
|
| 206 |
216 |
creep |
end
|
| 207 |
|
|
6'h06: begin
|
| 208 |
217 |
creep |
COLUP0 <= data[7:1];
|
| 209 |
216 |
creep |
end
|
| 210 |
|
|
6'h07: begin
|
| 211 |
217 |
creep |
COLUP1 <= data[7:1];
|
| 212 |
216 |
creep |
end
|
| 213 |
|
|
6'h08: begin
|
| 214 |
217 |
creep |
COLUPF <= data[7:1];
|
| 215 |
216 |
creep |
end
|
| 216 |
|
|
6'h09: begin
|
| 217 |
217 |
creep |
COLUBK <= data[7:1];
|
| 218 |
216 |
creep |
end
|
| 219 |
|
|
6'h0a: begin
|
| 220 |
217 |
creep |
CTRLPF <= {data[5:4], data[2:0]};
|
| 221 |
216 |
creep |
end
|
| 222 |
|
|
6'h0b: begin
|
| 223 |
217 |
creep |
REFP0 <= data[3];
|
| 224 |
216 |
creep |
end
|
| 225 |
|
|
6'h0c: begin
|
| 226 |
217 |
creep |
REFP1 <= data[3];
|
| 227 |
216 |
creep |
end
|
| 228 |
217 |
creep |
6'h0d: begin
|
| 229 |
|
|
PF0 <= data[7:4 ];
|
| 230 |
|
|
end
|
| 231 |
|
|
6'h0e: begin
|
| 232 |
|
|
PF1 <= data;
|
| 233 |
|
|
end
|
| 234 |
|
|
6'h0f: begin
|
| 235 |
|
|
PF2 <= data;
|
| 236 |
|
|
end
|
| 237 |
|
|
6'h15: begin
|
| 238 |
|
|
AUDC0 <= data[3:0];
|
| 239 |
|
|
end
|
| 240 |
|
|
6'h16: begin
|
| 241 |
|
|
AUDC1 <= data[4:0];
|
| 242 |
|
|
end
|
| 243 |
|
|
6'h17: begin
|
| 244 |
|
|
AUDF0 <= data[4:0];
|
| 245 |
|
|
end
|
| 246 |
|
|
6'h18: begin
|
| 247 |
|
|
AUDF1 <= data[3:0];
|
| 248 |
|
|
end
|
| 249 |
|
|
6'h19: begin
|
| 250 |
|
|
AUDV0 <= data[3:0];
|
| 251 |
|
|
end
|
| 252 |
|
|
6'h1A: begin
|
| 253 |
|
|
AUDV1 <= data[3:0];
|
| 254 |
|
|
end
|
| 255 |
|
|
6'h1B: begin
|
| 256 |
|
|
GRP0 <= data;
|
| 257 |
|
|
end
|
| 258 |
|
|
6'h1C: begin
|
| 259 |
|
|
GRP1 <= data;
|
| 260 |
|
|
end
|
| 261 |
|
|
6'h1D: begin
|
| 262 |
|
|
ENAM0 <= data[1];
|
| 263 |
|
|
end
|
| 264 |
|
|
6'h1E: begin
|
| 265 |
|
|
ENAM1 <= data[1];
|
| 266 |
|
|
end
|
| 267 |
|
|
6'h1F: begin
|
| 268 |
|
|
ENABL <= data[1];
|
| 269 |
|
|
end
|
| 270 |
|
|
6'h20: begin
|
| 271 |
|
|
HMP0 <= data[7:4];
|
| 272 |
|
|
end
|
| 273 |
|
|
6'h21: begin
|
| 274 |
|
|
HMP1 <= data[7:4];
|
| 275 |
|
|
end
|
| 276 |
|
|
6'h22: begin
|
| 277 |
|
|
HMM0 <= data[7:4];
|
| 278 |
|
|
end
|
| 279 |
|
|
6'h23: begin
|
| 280 |
|
|
HMM1 <= data[7:4];
|
| 281 |
|
|
end
|
| 282 |
|
|
6'h24: begin
|
| 283 |
|
|
HMBL <= data[7:4];
|
| 284 |
|
|
end
|
| 285 |
|
|
6'h25: begin
|
| 286 |
|
|
VDELP0 <= data[0];
|
| 287 |
|
|
end
|
| 288 |
|
|
6'h26: begin
|
| 289 |
|
|
VDEL01 <= data[0];
|
| 290 |
|
|
end
|
| 291 |
|
|
6'h27: begin
|
| 292 |
|
|
VDELBL <= data[0];
|
| 293 |
|
|
end
|
| 294 |
|
|
6'h28: begin
|
| 295 |
|
|
RESMP0 <= data[1];
|
| 296 |
237 |
creep |
ENAM0 <= 1'b0;
|
| 297 |
217 |
creep |
end
|
| 298 |
|
|
6'h29: begin
|
| 299 |
|
|
RESMP1 <= data[1];
|
| 300 |
237 |
creep |
ENAM1 <= 1'b0;
|
| 301 |
217 |
creep |
end
|
| 302 |
|
|
6'h2a: begin
|
| 303 |
|
|
HMOVE <= 1'b1; // STROBE
|
| 304 |
|
|
end
|
| 305 |
|
|
6'h2b: begin
|
| 306 |
|
|
HMCLR <= 1'b1; // STROBE
|
| 307 |
|
|
end
|
| 308 |
221 |
creep |
6'h2c: begin // cxclr STROBE
|
| 309 |
237 |
creep |
CXM0P <= 2'b0; // collision MO P1 M0 P0
|
| 310 |
|
|
CXM1P <= 2'b0; // collision M1 P0 M1 P1
|
| 311 |
|
|
CXP0FB <= 2'b0; // collision P0 PF P0 BL
|
| 312 |
|
|
CXP1FB <= 2'b0; // collision P1 PF P1 BL
|
| 313 |
|
|
CXM0FB <= 2'b0; // collision M0 PF M0 BL
|
| 314 |
|
|
CXM1FB <= 2'b0; // collision M1 PF M1 BL
|
| 315 |
|
|
CXBLPF <= 1'b0; // collision BL PF unused
|
| 316 |
|
|
CXPPMM <= 2'b0; // collision P0 P1 M0 M1
|
| 317 |
217 |
creep |
end
|
| 318 |
215 |
creep |
default: begin
|
| 319 |
|
|
end
|
| 320 |
|
|
endcase
|
| 321 |
|
|
end
|
| 322 |
|
|
end
|
| 323 |
|
|
end
|
| 324 |
235 |
creep |
|
| 325 |
|
|
reg draw_p0;
|
| 326 |
|
|
reg draw_p1;
|
| 327 |
|
|
reg draw_m0;
|
| 328 |
|
|
reg draw_m1;
|
| 329 |
|
|
reg draw_bl;
|
| 330 |
|
|
|
| 331 |
237 |
creep |
reg [8:0] p0_position; // sized in the same way the vert counter is
|
| 332 |
|
|
reg [8:0] p1_position; // sized in the same way the vert counter is
|
| 333 |
|
|
reg [8:0] m0_position; // sized in the same way the vert counter is
|
| 334 |
|
|
reg [8:0] m1_position; // sized in the same way the vert counter is
|
| 335 |
|
|
reg [8:0] bl_position; // sized in the same way the vert counter is
|
| 336 |
|
|
|
| 337 |
|
|
always @(posedge clk or negedge reset_n) begin
|
| 338 |
|
|
if (reset_n == 1'b0) begin
|
| 339 |
|
|
p0_position <= 9'b000000000;
|
| 340 |
|
|
p1_position <= 9'b000000000;
|
| 341 |
|
|
m0_position <= 9'b000000000;
|
| 342 |
|
|
m1_position <= 9'b000000000;
|
| 343 |
|
|
bl_position <= 9'b000000000;
|
| 344 |
|
|
end
|
| 345 |
|
|
else begin
|
| 346 |
|
|
if (draw_p0) begin
|
| 347 |
|
|
p0_position <= vert_counter;
|
| 348 |
|
|
end
|
| 349 |
|
|
if (draw_p1) begin
|
| 350 |
|
|
p1_position <= vert_counter;
|
| 351 |
|
|
end
|
| 352 |
|
|
|
| 353 |
|
|
if (RESMP0) begin
|
| 354 |
|
|
m0_position <= p0_position;
|
| 355 |
|
|
end
|
| 356 |
|
|
else if (draw_m0) begin
|
| 357 |
|
|
m0_position <= vert_counter;
|
| 358 |
|
|
end
|
| 359 |
|
|
|
| 360 |
|
|
if (RESMP1) begin
|
| 361 |
|
|
m1_position <= p1_position;
|
| 362 |
|
|
end
|
| 363 |
|
|
else if (draw_m1) begin
|
| 364 |
|
|
m1_position <= vert_counter;
|
| 365 |
|
|
end
|
| 366 |
|
|
|
| 367 |
|
|
if (draw_bl) begin
|
| 368 |
|
|
bl_position <= vert_counter;
|
| 369 |
|
|
end
|
| 370 |
|
|
|
| 371 |
|
|
// collision detection. note that the playfield must be handled differently
|
| 372 |
|
|
CXM0P[0] <= (m0_position == p0_position);
|
| 373 |
|
|
CXM0P[1] <= (m0_position == p1_position);
|
| 374 |
|
|
CXM1P[0] <= (m1_position == p1_position);
|
| 375 |
|
|
CXM1P[1] <= (m1_position == p0_position);
|
| 376 |
|
|
CXP0FB[0] <= (p0_position == bl_position);
|
| 377 |
|
|
//CXP0FB[1] <= (p0_position == pf_position);
|
| 378 |
|
|
CXP1FB[0] <= (p1_position == bl_position);
|
| 379 |
|
|
//CXP1FB[1] <= (p1_position == pf_position);
|
| 380 |
|
|
CXM0FB[0] <= (m0_position == bl_position);
|
| 381 |
|
|
//CXM0FB[1] <= (m0_position == pf_position);
|
| 382 |
|
|
CXM1FB[0] <= (m1_position == bl_position);
|
| 383 |
|
|
//CXM1FB[1] <= (m1_position == pf_position);
|
| 384 |
|
|
//CXBLPF <= (bl_position == pf_position);
|
| 385 |
|
|
CXPPMM[0] <= (m0_position == m1_position);
|
| 386 |
|
|
CXPPMM[1] <= (p0_position == p1_position);
|
| 387 |
|
|
|
| 388 |
|
|
end
|
| 389 |
|
|
end
|
| 390 |
|
|
|
| 391 |
|
|
always @ (*) begin // always combinational block that handles strobe registers.
|
| 392 |
235 |
creep |
draw_p0 = 1'b0;
|
| 393 |
|
|
draw_p1 = 1'b0;
|
| 394 |
|
|
draw_m0 = 1'b0;
|
| 395 |
|
|
draw_m1 = 1'b0;
|
| 396 |
|
|
draw_bl = 1'b0;
|
| 397 |
|
|
|
| 398 |
237 |
creep |
if (enable == 1'b1 && mem_rw == 1'b1) begin //
|
| 399 |
235 |
creep |
case (address)
|
| 400 |
|
|
6'h10: begin
|
| 401 |
|
|
draw_p0 = 1'b1;
|
| 402 |
|
|
end
|
| 403 |
|
|
6'h11: begin
|
| 404 |
|
|
draw_p1 = 1'b1;
|
| 405 |
|
|
end
|
| 406 |
|
|
6'h12: begin
|
| 407 |
|
|
draw_m0 = 1'b1;
|
| 408 |
|
|
end
|
| 409 |
|
|
6'h13: begin
|
| 410 |
|
|
draw_m1 = 1'b1;
|
| 411 |
|
|
end
|
| 412 |
|
|
6'h14: begin
|
| 413 |
|
|
draw_bl = 1'b1;
|
| 414 |
|
|
end
|
| 415 |
|
|
endcase
|
| 416 |
|
|
end
|
| 417 |
|
|
end
|
| 418 |
|
|
|
| 419 |
|
|
|
| 420 |
|
|
always @(*) begin // comb logic
|
| 421 |
|
|
if (hor_counter < 68 || vert_counter < 40 || vert_counter > 232) begin
|
| 422 |
|
|
pixel = 3'd0;
|
| 423 |
|
|
write_enable_n = 1'b1;
|
| 424 |
|
|
write_addr = 0;
|
| 425 |
|
|
write_data = vert_counter[2:0];
|
| 426 |
|
|
end
|
| 427 |
|
|
else begin
|
| 428 |
|
|
write_enable_n = 1'b0;
|
| 429 |
|
|
write_addr = (hor_counter - 68) + (vert_counter - 40)*160;
|
| 430 |
|
|
write_data = 3'd4;
|
| 431 |
|
|
|
| 432 |
|
|
if (CTRLPF[2] == 1'b1) begin // playfield gets priority over players so they can move behind the playfield
|
| 433 |
|
|
// Priority Objects
|
| 434 |
|
|
// 1 PF, BL
|
| 435 |
|
|
// 2 P0, M0
|
| 436 |
|
|
// 3 P1, M1
|
| 437 |
|
|
// 4 BK
|
| 438 |
|
|
|
| 439 |
|
|
end
|
| 440 |
|
|
else begin // regular priority
|
| 441 |
|
|
// Priority Objects
|
| 442 |
|
|
// 1 P0, M0
|
| 443 |
|
|
// 2 P1, M1
|
| 444 |
|
|
// 3 BL, PF
|
| 445 |
|
|
// 4 BK
|
| 446 |
|
|
if (CTRLPF[0] == 1'b1) begin// reflected PF
|
| 447 |
246 |
creep |
if (vert_counter == p0 || vert_counter == m0) begin
|
| 448 |
|
|
pixel = COLUP0;
|
| 449 |
|
|
end
|
| 450 |
|
|
else if (vert_counter == p1 || vert_counter == m1) begin
|
| 451 |
|
|
pixel = COLUP1;
|
| 452 |
|
|
end
|
| 453 |
|
|
else if (ENABL == 1'b1) begin // the ball is enabled
|
| 454 |
238 |
creep |
if (vert_counter == bl_position) begin
|
| 455 |
|
|
pixel = COLUPF;
|
| 456 |
|
|
end
|
| 457 |
235 |
creep |
end
|
| 458 |
|
|
else begin
|
| 459 |
|
|
if (vert_counter < 4) begin
|
| 460 |
|
|
pixel = (PF0[vert_counter] == 1'b1) ? COLUPF : COLUBK;
|
| 461 |
|
|
end
|
| 462 |
|
|
else if (vert_counter < 12) begin
|
| 463 |
|
|
pixel = (PF1[vert_counter - 4] == 1'b1) ? COLUPF : COLUBK;
|
| 464 |
|
|
end
|
| 465 |
|
|
else if (vert_counter < 20) begin
|
| 466 |
|
|
pixel = (PF2[vert_counter - 12] == 1'b1) ? COLUPF : COLUBK;
|
| 467 |
|
|
end
|
| 468 |
|
|
else if (vert_counter < 28) begin
|
| 469 |
|
|
pixel = (PF2[vert_counter - 20] == 1'b1) ? COLUPF : COLUBK;
|
| 470 |
|
|
end
|
| 471 |
|
|
else if (vert_counter < 36) begin
|
| 472 |
|
|
pixel = (PF1[vert_counter - 28] == 1'b1) ? COLUPF : COLUBK;
|
| 473 |
|
|
end
|
| 474 |
|
|
else begin
|
| 475 |
|
|
pixel = (PF0[vert_counter - 36] == 1'b1) ? COLUPF : COLUBK;
|
| 476 |
|
|
end
|
| 477 |
|
|
end
|
| 478 |
|
|
end
|
| 479 |
|
|
else begin
|
| 480 |
|
|
if (vert_counter < 4) begin
|
| 481 |
|
|
pixel = (PF0[vert_counter] == 1'b1) ? COLUPF : COLUBK;
|
| 482 |
|
|
end
|
| 483 |
|
|
else if (vert_counter < 12) begin
|
| 484 |
|
|
pixel = (PF1[vert_counter - 4] == 1'b1) ? COLUPF : COLUBK;
|
| 485 |
|
|
end
|
| 486 |
|
|
else if (vert_counter < 20) begin
|
| 487 |
|
|
pixel = (PF2[vert_counter - 12] == 1'b1) ? COLUPF : COLUBK;
|
| 488 |
|
|
end
|
| 489 |
|
|
else if (vert_counter < 24) begin
|
| 490 |
|
|
pixel = (PF0[vert_counter - 20] == 1'b1) ? COLUPF : COLUBK;
|
| 491 |
|
|
end
|
| 492 |
|
|
else if (vert_counter < 32) begin
|
| 493 |
|
|
pixel = (PF1[vert_counter - 24] == 1'b1) ? COLUPF : COLUBK;
|
| 494 |
|
|
end
|
| 495 |
|
|
else begin
|
| 496 |
|
|
pixel = (PF2[vert_counter - 32] == 1'b1) ? COLUPF : COLUBK;
|
| 497 |
|
|
end
|
| 498 |
|
|
end
|
| 499 |
|
|
end
|
| 500 |
|
|
|
| 501 |
|
|
pixel = 3'd4;
|
| 502 |
|
|
|
| 503 |
|
|
end
|
| 504 |
|
|
end
|
| 505 |
215 |
creep |
|
| 506 |
|
|
endmodule
|
| 507 |
|
|
|