Have a full cycle to load playfield and char data
[AtosmChip.git] / gtia.v
blob2de25163b65bdbe845bd2bd7b83d6fcf6b1c8c05
1 // Atosm Chip
2 // Copyright (C) 2008 Tomasz Malesinski <tmal@mimuw.edu.pl>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 module gtia_pmunit(clk_i, dat_i, pmdat_i, dmadat_i,
19 hpos_we, size_we, graf_we, grafdma_we,
20 vdelay_we, vdelay,
21 clk2_i,
22 hcount,
23 out);
24 parameter size = 8;
26 input clk_i, dat_i, pmdat_i, dmadat_i;
27 input hpos_we, size_we, graf_we, grafdma_we;
28 input vdelay_we, vdelay;
29 input clk2_i;
30 input hcount;
32 output out;
34 wire clk_i;
35 wire [7:0] dat_i;
36 wire [size - 1:0] pmdat_i, dmadat_i;
37 wire hpos_we, size_we, graf_we, grafdma_we;
38 wire vdelay_we, vdelay;
39 wire clk2_i;
40 wire [7:0] hcount;
42 wire out;
44 reg [7:0] hpos;
45 reg [1:0] size;
46 reg [size - 1:0] graf;
47 reg [size - 1:0] shift;
49 reg [1:0] cyccnt;
50 wire shift_en;
52 assign out = shift[size - 1];
54 always @ (posedge clk_i) begin
55 if (hpos_we)
56 hpos <= dat_i;
57 if (size_we)
58 size <= pmdat_i[1:0];
59 if (graf_we)
60 graf <= pmdat_i;
61 else if (grafdma_we)
62 graf <= dmadat_i;
63 // TODO: vdelay
64 end
66 always @ (posedge clk2_i)
67 if (hcount == hpos)
68 shift <= graf;
69 else if (shift_en)
70 shift <= {shift[size - 2:0], 1'b0};
72 always @ (posedge clk2_i)
73 if (hcount == hpos)
74 cyccnt <= 0;
75 else
76 cyccnt <= cyccnt + 1;
78 assign shift_en = (size == 2'b00) || (size == 2'b10) ||
79 (size == 2'b01 && cyccnt[0]) ||
80 (size == 2'b11 && cyccnt == 2'b11);
82 endmodule
84 module gtia_antic_input(clk2_i,
85 nrm, cl9,
86 antic_out,
87 pf, b, adpl,
88 pf2c, pf1lum_sel,
89 vsync, blank);
90 input clk2_i;
91 input nrm, cl9;
92 input antic_out;
93 output pf, b, adpl;
94 output pf2c, pf1lum_sel;
95 output vsync, blank;
97 wire clk2_i;
98 wire nrm, cl9;
99 wire [2:0] antic_out;
101 wire [3:0] pf;
102 reg [3:0] b;
103 reg [3:0] adpl;
104 wire pf2c, pf1lum_sel;
105 wire vsync, blank;
107 reg chr40l;
108 reg even;
110 integer i;
112 assign vsync = (antic_out == 3'b001);
113 assign blank = (antic_out == 3'b010 || antic_out == 3'b011);
115 always @ (posedge clk2_i)
116 if (!nrm || antic_out == 3'b010)
117 chr40l <= 0;
118 else if (antic_out == 3'b011)
119 chr40l <= 1;
121 // TODO: replace it with HCOUNT?
122 always @ (posedge clk2_i)
123 if (blank)
124 even <= 1;
125 else
126 even <= ~even;
128 always @ (posedge clk2_i)
129 if (even)
130 b[3:2] <= antic_out[1:0];
131 else
132 b[1:0] <= antic_out[1:0];
134 assign pf[0] = (nrm && !chr40l && antic_out == 3'b100) ||
135 (cl9 && b[2:0] == 3'b100);
136 assign pf[1] = (nrm && !chr40l && antic_out == 3'b101) ||
137 (cl9 && b[2:0] == 3'b101);
138 assign pf[2] = (nrm && !chr40l && antic_out == 3'b110) ||
139 (chr40l && antic_out[2]) ||
140 (cl9 && b[2:0] == 3'b110);
141 assign pf[3] = (nrm && !chr40l && antic_out == 3'b111) ||
142 (cl9 && b[2:0] == 3'b111);
143 assign pf2c = (nrm && !chr40l && antic_out == 3'b110) ||
144 (cl9 && b[2:0] == 3'b110) ||
145 (chr40l && (antic_out[1] || antic_out[0]));
147 always @ (cl9 or b)
148 for (i = 0; i < 4; i = i + 1)
149 adpl[i] = cl9 && (b == i);
151 assign pf1lum_sel = chr40l && !blank &&
152 (clk2_i ? antic_out[1] : antic_out[0]);
153 endmodule
155 module gtia_out(clk_i,
156 dat_i,
157 colpm_we, colpf_we, colbak_we, gtiactl_we,
158 nrm, cl9,
159 blank, pl, adpl, mi, pf, pf1lum_sel, b,
160 color);
161 input clk_i;
162 input dat_i;
163 input colpm_we, colpf_we, colbak_we, gtiactl_we;
164 input blank, pl, adpl, mi, pf, pf1lum_sel, b;
166 output nrm, cl9;
167 output color;
169 wire clk_i;
170 wire [7:0] dat_i;
172 wire [3:0] colpm_we;
173 wire [3:0] colpf_we;
174 wire colbak_we;
175 wire gtiactl_we;
177 wire nrm, cl9, c, lu;
179 wire blank;
180 wire [3:0] pl, adpl;
181 wire [3:0] mi;
182 wire [3:0] pf;
183 wire pf1lum_sel;
184 wire [3:0] b;
186 reg [7:0] color;
188 wire [3:0] pm;
189 wire pf3_p5;
191 wire [3:0] sf, sp;
192 wire sb;
194 reg [7:1] colpf[0:3];
195 wire [7:1] colpf1 = colpf[1];
196 reg [7:1] colpm[0:3];
197 reg [7:1] colbak;
198 reg [3:0] prior;
199 reg pl5th;
200 reg multi_colp;
201 reg [1:0] mode;
203 integer i, si;
205 always @ (posedge clk_i) begin
206 for (i = 0; i < 4; i = i + 1)
207 if (colpm_we[i])
208 colpm[i] <= dat_i[7:1];
209 else if (colpf_we[i])
210 colpf[i] <= dat_i[7:1];
211 if (colbak_we)
212 colbak <= dat_i[7:1];
213 if (gtiactl_we) begin
214 prior <= dat_i[3:0];
215 pl5th <= dat_i[4];
216 multi_colp <= dat_i[5];
217 mode <= dat_i[7:6];
221 assign pm = pl | adpl | (mi & {4{~pl5th}});
223 assign nrm = (mode == 2'b00);
224 assign cl9 = (mode == 2'b10) && ! blank;
225 assign c = (mode == 2'b11) && !blank && (pm == 0);
226 assign lu = (mode == 2'b01) && !blank && (pm == 0);
228 assign pf3_p5 = pf[3] || (pl5th && (mi != 0));
230 assign sp[0] = !blank && pm[0] &&
231 (!(pf[0] || pf[1]) || (!prior[2] && !prior[3])) &&
232 (!(pf[2] || pf3_p5) || !prior[2]);
233 assign sp[1] = !blank && pm[1] &&
234 (!(pf[0] || pf[1]) || (!prior[2] && !prior[3])) &&
235 (!(pf[2] || pf3_p5) || !prior[2]) &&
236 (multi_colp || !pm[0]);
237 assign sp[2] = !blank && pm[2] && !(pm[0] || pm[1]) &&
238 (!(pf[0] || pf[1]) || prior[0]) &&
239 (!(pf[2] || pf3_p5) || (!prior[1]) && !prior[2]);
240 assign sp[3] = !blank && pm[3] && !(pm[0] || pm[1]) &&
241 (!(pf[0] || pf[1]) || prior[0]) &&
242 (!(pf[2] || pf3_p5) || (!prior[1]) && !prior[2]) &&
243 (multi_colp || !pm[2]);
245 assign sf[3] = !blank && pf3_p5 &&
246 (!(pm[0] || pm[1]) || prior[2]) &&
247 (!(pm[2] || pm[3]) || (!prior[0] && !prior[3]));
248 assign sf[2] = !blank && pf[2] && !sf[3] &&
249 (!(pm[0] || pm[1]) || prior[2]) &&
250 (!(pm[2] || pm[3]) || (!prior[0] && !prior[3]));
251 assign sf[1] = !blank && pf[1] && !sf[3] &&
252 (!(pm[0] || pm[1]) || (!prior[0] && !prior[1])) &&
253 (!(pm[2] || pm[3]) || !prior[0]);
254 assign sf[0] = !blank && pf[0] && !sf[3] &&
255 (!(pm[0] || pm[1]) || (!prior[0] && !prior[1])) &&
256 (!(pm[2] || pm[3]) || !prior[0]);
258 assign sb = !blank && (pf[2:0] == 0) && !pf3_p5 && (pm == 0);
260 always @ (sf or sp or sb or pf1lum_sel or b or lu or c or
261 colpf[0] or colpf[1] or colpf[2] or colpf[3] or
262 colpm[0] or colpm[1] or colpm[2] or colpm[3] or colbak) begin
263 color = 0;
264 for (si = 0; si < 4; si = si + 1) begin
265 if (sp[si])
266 color = color | {colpm[si], 1'b0};
267 if (sf[si])
268 color = color | {colpf[si], 1'b0};
270 if (sb)
271 color = color | {colbak, 1'b0};
272 if (pf1lum_sel)
273 color = {color[7:4], colpf1[3:1], 1'b0};
274 if (lu)
275 color = {color[7:4], b};
276 if (c)
277 color = {b, color[3:0]};
279 endmodule
281 module gtia(rst_i, clk_i,
282 adr_i,
283 dat_i,
284 dat_o,
285 we_i,
286 stb_i,
287 ack_o,
288 clk2_i,
289 dmadat_i,
290 antic_out,
291 color,
292 hsync,
293 vsync,
294 trig_in,
295 consol_in,
296 consol_out);
297 input rst_i;
298 input clk_i;
299 input adr_i;
300 input dat_i;
301 input we_i;
302 input stb_i;
303 input clk2_i;
304 input dmadat_i;
305 input antic_out;
306 input trig_in;
307 input consol_in;
309 output dat_o;
310 output ack_o;
311 output color;
312 output hsync;
313 output vsync;
314 output consol_out;
316 wire rst_i, clk_i;
317 wire [4:0] adr_i;
318 wire [7:0] dat_i;
319 wire we_i;
320 wire stb_i;
321 wire clk2_i;
322 wire [7:0] dmadat_i;
323 wire [2:0] antic_out;
325 wire ack_o;
326 reg [7:0] dat_o;
328 reg [3:0] colpm_we;
329 reg [3:0] colpf_we;
330 reg colbak_we;
331 reg gtiactl_we;
333 reg [3:0] hposp_we;
334 reg [3:0] hposm_we;
335 reg [3:0] sizep_we;
336 reg sizem_we;
337 reg [3:0] grafp_we;
338 reg [3:0] grafpdma_we;
339 reg grafm_we;
340 reg grafmdma_we;
341 reg vdelay_we;
343 reg [3:0] mxpf[3:0];
344 reg [3:0] pxpf[3:0];
345 reg [3:0] mxpl[3:0];
346 reg [3:0] pxpl[3:0];
347 reg hitclr;
349 wire [3:0] pf, b;
350 wire [3:0] pl, mi, adpl;
352 wire blank;
353 reg last_blank;
354 wire [7:0] color;
355 wire hsync, vsync;
357 reg [7:0] hcount;
359 reg dmam, dmap;
361 wire [3:0] consol_in, consol_out;
362 reg [3:0] consol_out_reg;
363 wire [3:0] trig_in;
364 reg [3:0] trig_reg;
365 reg trig_latch;
367 integer ki, gi, i;
369 assign ack_o = stb_i;
371 // Read registers.
372 always @ (adr_i or trig_reg or consol_in or consol_out_reg)
373 if (adr_i >= 0 && adr_i < 4)
374 dat_o = {4'h0, mxpf[adr_i]};
375 else if (adr_i >= 4 && adr_i < 8)
376 dat_o = {4'h0, pxpf[adr_i - 4]};
377 else if (adr_i >= 8 && adr_i < 'hc)
378 dat_o = {4'h0, mxpl[adr_i - 8]};
379 else if (adr_i >= 'hc && adr_i < 'h10)
380 dat_o = {4'h0, pxpl[adr_i - 'hc]};
381 else if (adr_i >= 'h10 && adr_i < 'h14)
382 dat_o = {7'h0, trig_reg[adr_i - 'h10]};
383 else if (adr_i == 'h14)
384 dat_o = 8'h1; // 'h0f for NTSC
385 else if (adr_i == 'h1f)
386 dat_o = {4'h0, consol_in &~ consol_out_reg};
387 else
388 dat_o = 'hff;
390 always @ (posedge clk_i)
391 if (stb_i && we_i)
392 if (adr_i == 'h1d) begin
393 dmam <= dat_i[0];
394 dmap <= dat_i[1];
395 trig_latch <= dat_i[2];
396 end else if (adr_i == 'h1f) begin
397 consol_out_reg <= dat_i[3:0];
400 always @ (posedge clk_i)
401 trig_reg <= trig_latch ? (trig_reg & trig_in) : trig_in;
403 always @ (we_i or stb_i or adr_i) begin
404 hposp_we = 0;
405 hposm_we = 0;
406 sizep_we = 0;
407 sizem_we = 0;
408 grafp_we = 0;
409 grafm_we = 0;
410 vdelay_we = 0;
411 colpm_we = 0;
412 colpf_we = 0;
413 colbak_we = 0;
414 gtiactl_we = 0;
415 if (stb_i && we_i)
416 if (adr_i >= 0 && adr_i < 4)
417 hposp_we[adr_i] = 1;
418 else if (adr_i >= 4 && adr_i < 8)
419 hposm_we[adr_i - 4] = 1;
420 else if (adr_i >= 8 && adr_i < 'hc)
421 sizep_we[adr_i - 8] = 1;
422 else if (adr_i == 'hc)
423 sizem_we = 1;
424 else if (adr_i >= 'hd && adr_i < 'h11)
425 grafp_we[adr_i - 'hd] = 1;
426 else if (adr_i == 'h11)
427 grafm_we = 1;
428 else if (adr_i >= 'h12 && adr_i < 'h16)
429 colpm_we[adr_i - 'h12] = 1;
430 else if (adr_i >= 'h16 && adr_i < 'h1a)
431 colpf_we[adr_i - 'h16] = 1;
432 else if (adr_i == 'h1a)
433 colbak_we = 1;
434 else if (adr_i == 'h1b)
435 gtiactl_we = 1;
436 else if (adr_i == 'h1c)
437 vdelay_we = 1;
440 always @ (dmap or dmam or hcount) begin
441 // TODO: GTIA count cycles from HALT (see datasheet).
442 for (gi = 0; gi < 4; gi = gi + 1)
443 grafpdma_we[gi] = dmap && (hcount == 4 + 2 * gi);
444 grafmdma_we = dmam && (hcount == 0);
447 assign hsync = (hcount < 16);
449 gtia_antic_input u_antic_input(clk2_i, nrm, cl9,
450 antic_out,
451 pf, b, adpl,
452 pf2c, pf1lum_sel,
453 vsync, blank);
455 // Collisions.
456 always @ (posedge clk_i)
457 if (stb_i && we_i && adr_i == 'h1e)
458 hitclr <= 1;
459 else
460 hitclr <= 0;
462 // TODO: pf2c
463 always @ (posedge clk2_i)
464 if (hitclr)
465 for (ki = 0; ki < 4; ki = ki + 1) begin
466 mxpf[ki] <= 0;
467 pxpf[ki] <= 0;
468 mxpl[ki] <= 0;
469 pxpl[ki] <= 0;
471 else
472 for (ki = 0; ki < 4; ki = ki + 1) begin
473 if (mi[ki]) begin
474 mxpf[ki] <= mxpf[ki] | pf[ki];
475 mxpl[ki] <= mxpl[ki] | pl[ki];
477 if (pl[ki]) begin
478 pxpf[ki] <= pxpf[ki] | pf[ki];
479 pxpl[ki] <= pxpl[ki] | (pl[ki] & ~(1 << ki));
483 always @ (posedge clk2_i)
484 last_blank <= blank;
486 always @ (posedge clk2_i)
487 if (!last_blank && blank)
488 hcount <= 223;
489 else if (hcount == 227)
490 hcount <= 0;
491 else
492 hcount <= hcount + 1;
494 gtia_out u_out(.clk_i(clk_i), .dat_i(dat_i),
495 .colpm_we(colpm_we), .colpf_we(colpf_we),
496 .colbak_we(colbak_we), .gtiactl_we(gtiactl_we),
497 .nrm(nrm), .cl9(cl9),
498 .blank(blank), .pl(pl), .adpl(adpl), .mi(mi), .pf(pf), .b(b),
499 .pf1lum_sel(pf1lum_sel),
500 .color(color));
502 gtia_pmunit u_pl0(.clk_i(clk_i), .dat_i(dat_i), .pmdat_i(dat_i),
503 .dmadat_i(dmadat_i),
504 .hpos_we(hposp_we[0]), .size_we(sizep_we[0]),
505 .graf_we(grafp_we[0]), .grafdma_we(grafpdma_we[0]),
506 .vdelay_we(vdelay_we), .vdelay(dat_i[4]),
507 .clk2_i(clk2_i), .hcount(hcount), .out(pl[0]));
508 gtia_pmunit u_pl1(.clk_i(clk_i), .dat_i(dat_i), .pmdat_i(dat_i),
509 .dmadat_i(dmadat_i),
510 .hpos_we(hposp_we[1]), .size_we(sizep_we[1]),
511 .graf_we(grafp_we[1]), .grafdma_we(grafpdma_we[1]),
512 .vdelay_we(vdelay_we), .vdelay(dat_i[5]),
513 .clk2_i(clk2_i), .hcount(hcount), .out(pl[1]));
514 gtia_pmunit u_pl2(.clk_i(clk_i), .dat_i(dat_i), .pmdat_i(dat_i),
515 .dmadat_i(dmadat_i),
516 .hpos_we(hposp_we[2]), .size_we(sizep_we[2]),
517 .graf_we(grafp_we[2]), .grafdma_we(grafpdma_we[2]),
518 .vdelay_we(vdelay_we), .vdelay(dat_i[6]),
519 .clk2_i(clk2_i), .hcount(hcount), .out(pl[2]));
520 gtia_pmunit u_pl3(.clk_i(clk_i), .dat_i(dat_i), .pmdat_i(dat_i),
521 .dmadat_i(dmadat_i),
522 .hpos_we(hposp_we[3]), .size_we(sizep_we[3]),
523 .graf_we(grafp_we[3]), .grafdma_we(grafpdma_we[3]),
524 .vdelay_we(vdelay_we), .vdelay(dat_i[7]),
525 .clk2_i(clk2_i), .hcount(hcount), .out(pl[3]));
527 defparam u_m0.size = 2;
528 defparam u_m1.size = 2;
529 defparam u_m2.size = 2;
530 defparam u_m3.size = 2;
531 gtia_pmunit u_m0(.clk_i(clk_i), .dat_i(dat_i), .pmdat_i(dat_i[1:0]),
532 .dmadat_i(dmadat_i[1:0]),
533 .hpos_we(hposm_we[0]), .size_we(sizem_we),
534 .graf_we(grafm_we), .grafdma_we(grafmdma_we),
535 .vdelay_we(vdelay_we), .vdelay(dat_i[0]),
536 .clk2_i(clk2_i), .hcount(hcount), .out(mi[0]));
537 gtia_pmunit u_m1(.clk_i(clk_i), .dat_i(dat_i), .pmdat_i(dat_i[3:2]),
538 .dmadat_i(dmadat_i[3:2]),
539 .hpos_we(hposm_we[1]), .size_we(sizem_we),
540 .graf_we(grafm_we), .grafdma_we(grafmdma_we),
541 .vdelay_we(vdelay_we), .vdelay(dat_i[1]),
542 .clk2_i(clk2_i), .hcount(hcount), .out(mi[1]));
543 gtia_pmunit u_m2(.clk_i(clk_i), .dat_i(dat_i), .pmdat_i(dat_i[5:4]),
544 .dmadat_i(dmadat_i[5:4]),
545 .hpos_we(hposm_we[2]), .size_we(sizem_we),
546 .graf_we(grafm_we), .grafdma_we(grafmdma_we),
547 .vdelay_we(vdelay_we), .vdelay(dat_i[2]),
548 .clk2_i(clk2_i), .hcount(hcount), .out(mi[2]));
549 gtia_pmunit u_m3(.clk_i(clk_i), .dat_i(dat_i), .pmdat_i(dat_i[7:6]),
550 .dmadat_i(dmadat_i[7:6]),
551 .hpos_we(hposm_we[3]), .size_we(sizem_we),
552 .graf_we(grafm_we), .grafdma_we(grafmdma_we),
553 .vdelay_we(vdelay_we), .vdelay(dat_i[3]),
554 .clk2_i(clk2_i), .hcount(hcount), .out(mi[3]));
556 assign consol_out = ~consol_out_reg;
558 endmodule