Have a full cycle to load playfield and char data
[AtosmChip.git] / antic.v
blob0433da23ac1a6a54229c3fea7bd2ca7345a948e0
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 antic_ms_hcount_seq(clk_i, ms_hcount,
19 new_block, dma_block, char_block, dma_pf_width, ir,
20 shift_reg_shift, load_pf, load_char, load_out,
21 out_reg_shift);
22 input clk_i, ms_hcount;
23 input new_block, dma_block, char_block, dma_pf_width, ir;
24 output shift_reg_shift, load_pf, load_char, load_out, out_reg_shift;
26 wire clk_i;
27 wire [7:0] ms_hcount;
28 wire new_block, dma_block, char_block;
29 wire [1:0] dma_pf_width;
30 wire [7:0] ir;
31 wire shift_reg_shift;
32 reg load_pf, load_char;
33 reg load_out;
34 wire out_reg_shift;
36 reg load_pf_0, load_char_0;
37 reg [3:0] pf_byte_mod;
38 reg [1:0] pf_pixel_mod;
40 always @ (ir)
41 case (ir[3:0])
42 'h2: begin
43 pf_byte_mod = 3;
44 pf_pixel_mod = 0;
45 end
46 'h3: begin
47 pf_byte_mod = 3;
48 pf_pixel_mod = 0;
49 end
50 'h4: begin
51 pf_byte_mod = 3;
52 pf_pixel_mod = 0;
53 end
54 'h5: begin
55 pf_byte_mod = 3;
56 pf_pixel_mod = 0;
57 end
58 'h6: begin
59 pf_byte_mod = 7;
60 pf_pixel_mod = 0;
61 end
62 'h7: begin
63 pf_byte_mod = 7;
64 pf_pixel_mod = 0;
65 end
66 'h8: begin
67 pf_byte_mod = 15;
68 pf_pixel_mod = 3;
69 end
70 'h9: begin
71 pf_byte_mod = 15;
72 pf_pixel_mod = 1;
73 end
74 'ha: begin
75 pf_byte_mod = 7;
76 pf_pixel_mod = 1;
77 end
78 'hb: begin
79 pf_byte_mod = 7;
80 pf_pixel_mod = 0;
81 end
82 'hc: begin
83 pf_byte_mod = 7;
84 pf_pixel_mod = 0;
85 end
86 'hd: begin
87 pf_byte_mod = 3;
88 pf_pixel_mod = 0;
89 end
90 'he: begin
91 pf_byte_mod = 3;
92 pf_pixel_mod = 0;
93 end
94 'hf: begin
95 pf_byte_mod = 3;
96 pf_pixel_mod = 0;
97 end
98 default: begin
99 pf_byte_mod = 3;
100 pf_pixel_mod = 0;
102 endcase
104 assign shift_reg_shift = (ms_hcount >= 3) && (ms_hcount < 192 + 3) &&
105 (ms_hcount[1:0] == 3);
107 assign out_reg_shift = ((ms_hcount[1:0] & pf_pixel_mod) ==
108 (2'd2 & pf_pixel_mod));
110 always @ (new_block or dma_block or dma_pf_width or ms_hcount or
111 pf_byte_mod or ir) begin
112 load_pf_0 = 0;
113 if (new_block && dma_block) begin
114 if (dma_pf_width == 1 && !ir[4])
115 load_pf_0 = ((ms_hcount & pf_byte_mod) == (3 & pf_byte_mod)) &&
116 (ms_hcount >= 32 + 3) && (ms_hcount < 160 + 3);
117 else if (dma_pf_width == (ir[4] ? 1 : 2))
118 load_pf_0 = ((ms_hcount & pf_byte_mod) == (3 & pf_byte_mod)) &&
119 (ms_hcount >= 16 + 3) && (ms_hcount < 176 + 3);
120 else if (dma_pf_width == 3 || (ir[4] && dma_pf_width == 2))
121 load_pf_0 = ((ms_hcount & pf_byte_mod) == (3 & pf_byte_mod)) &&
122 (ms_hcount >= 3) && (ms_hcount < 192 + 3);
126 always @ (dma_block or dma_pf_width or ms_hcount or pf_byte_mod) begin
127 load_char_0 = 0;
128 if (dma_block)
129 case (dma_pf_width)
130 1: load_char_0 = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
131 (ms_hcount >= 32 + 9 && ms_hcount < 160 + 9);
132 2: load_char_0 = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
133 (ms_hcount >= 16 + 9 && ms_hcount < 176 + 9);
134 3: load_char_0 = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
135 (ms_hcount >= 9 && ms_hcount < 192 + 9);
136 endcase
139 always @ (dma_block or dma_pf_width or ms_hcount or pf_byte_mod) begin
140 load_out = 0;
141 if (dma_block)
142 case (dma_pf_width)
143 1: load_out = ((ms_hcount & pf_byte_mod) == (12 & pf_byte_mod)) &&
144 (ms_hcount >= 32 + 12 && ms_hcount < 160 + 12);
145 2: load_out = ((ms_hcount & pf_byte_mod) == (12 & pf_byte_mod)) &&
146 (ms_hcount >= 16 + 12 && ms_hcount < 176 + 12);
147 3: load_out = ((ms_hcount & pf_byte_mod) == (12 & pf_byte_mod)) &&
148 (ms_hcount >= 12 && ms_hcount < 192 + 12);
149 endcase
152 always @ (posedge clk_i) begin
153 load_pf <= load_pf_0;
154 load_char <= load_char_0 && char_block;
156 endmodule
158 module antic_shift_reg(clk_i, shift, load, in, out);
159 input clk_i;
160 input shift;
161 input load;
162 input in;
164 output out;
166 wire clk_i;
167 wire shift;
168 wire load;
169 wire [7:0] in;
170 wire [7:0] out;
172 reg [7:0] shift_reg [0:47];
174 integer i;
176 assign out = shift_reg[1];
178 always @ (posedge clk_i) begin
179 if (shift)
180 for (i = 0; i < 47; i = i + 1)
181 shift_reg[i + 1] <= shift_reg[i];
182 if (load)
183 shift_reg[0] <= in;
184 else if (shift)
185 shift_reg[0] <= shift_reg[47];
187 endmodule
189 module antic(rst_i, clk_i,
190 adr_i, adr_o,
191 slavedat_i, masterdat_i,
192 dat_o,
193 we_i,
194 stb_i, stb_o,
195 ack_i, ack_o,
196 cyc_o,
197 clk2_i,
198 nmi,
199 antic_out);
200 input rst_i;
201 input clk_i;
202 input adr_i;
203 input slavedat_i;
204 input masterdat_i;
205 input we_i;
206 input stb_i;
207 input ack_i;
208 input clk2_i;
210 output adr_o;
211 output dat_o;
212 output stb_o;
213 output ack_o;
214 output cyc_o;
215 output nmi;
216 output antic_out;
218 wire rst_i, clk_i;
219 wire [3:0] adr_i;
220 wire [7:0] slavedat_i;
221 wire [7:0] masterdat_i;
222 wire we_i;
223 wire stb_i;
224 wire ack_i;
225 wire clk2_i;
227 reg [15:0] adr_o;
228 reg [7:0] dat_o;
229 wire stb_o;
230 wire ack_o;
231 wire cyc_o;
232 wire nmi;
233 reg [2:0] antic_out;
235 reg [1:0] dma_pf_width;
236 reg dma_mis_en;
237 reg dma_ply_en;
238 reg dma_pm_1res;
239 reg dma_instr_en;
241 reg [6:0] chbase;
242 reg [2:0] chactl;
243 reg [5:0] pmbase;
244 reg [3:0] hscrol;
245 reg [3:0] vscrol;
247 wire nmireq_dli, nmireq_vbi;
248 reg nmist_dli, nmist_vbi;
249 reg nmien_dli, nmien_vbi;
251 reg [15:0] dlist_ctr;
252 reg [7:0] dlist_ctr_tmp;
253 wire dl_load;
255 reg [15:0] memscan_ctr;
257 reg [7:0] hcount;
258 reg [8:0] vcount;
259 reg [3:0] dcount;
260 reg [7:0] ms_hcount;
262 reg [7:0] ir;
263 reg new_block;
264 reg [3:0] maxline;
265 wire dli;
266 wire wait_vblank;
267 wire dma_block;
268 reg char_block;
269 reg one_bit_pixel;
271 reg wsync;
273 wire load_instr;
274 wire load_dlptrl;
275 wire load_dlptrh;
276 wire load_memscanl;
277 wire load_memscanh;
278 wire load_mis;
279 wire load_ply;
280 wire load_pf;
281 wire load_char;
283 wire [1:0] dma_ply_num;
285 wire load_out_p, load_out;
287 wire hblank, vblank, vsync;
288 reg dwin;
290 wire shift_reg_shift;
291 wire [7:0] shift_reg_out;
292 reg [7:0] char_data, out_reg;
293 wire out_reg_shift;
294 reg [1:0] char_color_p, char_color;
296 assign ack_o = stb_i;
298 // Read registers.
299 always @ (adr_i or vcount or nmist_dli or nmist_vbi)
300 case (adr_i)
301 'hb:
302 dat_o = vcount[8:1];
303 'hf:
304 dat_o = {nmist_dli, nmist_vbi, 6'b0};
305 default:
306 dat_o = 'hff;
307 endcase
309 // DMACTL
310 always @ (posedge clk_i)
311 if (stb_i && we_i && adr_i == 'h0) begin
312 dma_pf_width <= slavedat_i[1:0];
313 dma_mis_en <= slavedat_i[2];
314 dma_ply_en <= slavedat_i[3];
315 dma_pm_1res <= slavedat_i[4];
316 dma_instr_en <= slavedat_i[5];
319 // CHACTL
320 always @ (posedge clk_i)
321 if (stb_i && we_i && adr_i == 'h1)
322 chactl <= slavedat_i[2:0];
324 // DLISTL/H
325 always @ (posedge clk_i)
326 if (stb_i && we_i && adr_i == 'h2)
327 dlist_ctr[7:0] <= slavedat_i;
328 else if (stb_i && we_i && adr_i == 'h3)
329 dlist_ctr[15:8] <= slavedat_i;
330 else if (dl_load) begin
331 if (!load_dlptrh)
332 dlist_ctr[9:0] <= dlist_ctr[9:0] + 1;
333 else begin
334 dlist_ctr[15:8] <= masterdat_i;
335 dlist_ctr[7:0] <= dlist_ctr_tmp;
337 if (load_dlptrl)
338 dlist_ctr_tmp <= masterdat_i;
341 // HSCROL
342 always @ (posedge clk_i)
343 if (stb_i && we_i && adr_i == 'h4)
344 hscrol <= slavedat_i[3:0];
346 // VSCROL
347 always @ (posedge clk_i)
348 if (stb_i && we_i && adr_i == 'h5)
349 vscrol <= slavedat_i[3:0];
351 // PMBASE
352 always @ (posedge clk_i)
353 if (stb_i && we_i && adr_i == 'h7)
354 pmbase <= slavedat_i[7:2];
356 // CHBASE
357 always @ (posedge clk_i)
358 if (stb_i && we_i && adr_i == 'h9)
359 chbase <= slavedat_i[7:1];
361 // WSYNC
362 always @ (posedge clk_i)
363 if (rst_i || hcount == 206)
364 wsync <= 0;
365 else if (stb_i && we_i && adr_i == 'ha)
366 wsync <= 1;
368 // NMIEN
369 always @ (posedge clk_i)
370 if (rst_i) begin
371 nmien_vbi <= 0;
372 nmien_dli <= 0;
373 end else if (stb_i && we_i && adr_i == 'he) begin
374 nmien_vbi <= slavedat_i[6];
375 nmien_dli <= slavedat_i[7];
378 // HCOUNT
379 always @ (posedge clk2_i)
380 if (rst_i && !clk_i)
381 hcount <= 0;
382 else if (hcount == 227)
383 hcount <= 0;
384 else
385 hcount <= hcount + 1;
387 // VCOUNT
388 always @ (posedge clk2_i)
389 if (rst_i && !clk_i)
390 vcount <= 0;
391 else if (hcount == 227)
392 if (vcount == 311)
393 vcount <= 0;
394 else
395 vcount <= vcount + 1;
397 // Display list interrupt.
398 assign nmireq_dli = (hcount == 16 && dcount == maxline && dli &&
399 nmien_dli && !vblank && !wait_vblank);
401 // Vertical blank interrupt.
402 assign nmireq_vbi = (hcount == 16 && vcount == 240 && nmien_vbi);
404 always @ (posedge clk_i)
405 if (rst_i) begin
406 nmist_vbi <= 0;
407 nmist_dli <= 0;
408 end else if (nmireq_vbi) begin
409 nmist_vbi <= 1;
410 nmist_dli <= 0;
411 end else if (nmireq_dli) begin
412 nmist_vbi <= 0;
413 nmist_dli <= 1;
414 end else if (stb_i && we_i && adr_i =='hf) begin
415 nmist_vbi <= 0;
416 nmist_dli <= 0;
419 assign nmi = nmireq_dli | nmireq_vbi;
421 always @ (posedge clk2_i)
422 if (hcount == 227)
423 if (dma_instr_en &&
424 (vcount == 7 ||
425 (dcount == maxline && !wait_vblank && !vblank && dma_instr_en)))
426 new_block <= 1;
427 else
428 new_block <= 0;
430 assign load_instr = new_block && (hcount == 2);
432 // DCOUNT
433 always @ (posedge clk2_i)
434 if (vcount == 0)
435 dcount <= 0;
436 else if (hcount == 0)
437 if (new_block)
438 dcount <= 0; // TODO: vscroll
439 else
440 dcount <= dcount + 1;
442 // Memory Scan Counter.
443 always @ (posedge clk_i)
444 if (load_pf)
445 memscan_ctr[11:0] <= memscan_ctr[11:0] + 1;
446 else if (load_memscanl)
447 memscan_ctr[7:0] <= masterdat_i;
448 else if (load_memscanh)
449 memscan_ctr[15:8] <= masterdat_i;
451 // Instruction register.
452 always @ (posedge clk_i)
453 if (load_instr)
454 ir <= masterdat_i;
455 else if (vcount == 0)
456 ir <= 0;
458 // Instruction decoder.
459 always @ (ir) begin
460 maxline = 0;
461 char_block = 0;
462 one_bit_pixel = 0;
463 case (ir[3:0])
464 'h0: maxline = ir[6:4];
465 'h1: maxline = 0;
466 'h2: begin
467 maxline = 7;
468 char_block = 1;
469 one_bit_pixel = 0;
471 'h3: begin
472 maxline = 9;
473 char_block = 1;
474 one_bit_pixel = 0;
476 'h4: begin
477 maxline = 7;
478 char_block = 1;
479 one_bit_pixel = 0;
481 'h5: begin
482 maxline = 15;
483 char_block = 1;
484 one_bit_pixel = 0;
486 'h6: begin
487 maxline = 7;
488 char_block = 1;
489 one_bit_pixel = 1;
491 'h7: begin
492 maxline = 15;
493 char_block = 1;
494 one_bit_pixel = 1;
496 'h8: begin
497 maxline = 7;
498 char_block = 0;
499 one_bit_pixel = 0;
501 'h9: begin
502 maxline = 3;
503 char_block = 0;
504 one_bit_pixel = 1;
506 'ha: begin
507 maxline = 3;
508 char_block = 0;
509 one_bit_pixel = 0;
511 'hb: begin
512 maxline = 1;
513 char_block = 0;
514 one_bit_pixel = 1;
516 'hc: begin
517 maxline = 0;
518 char_block = 0;
519 one_bit_pixel = 1;
521 'hd: begin
522 maxline = 1;
523 char_block = 0;
524 one_bit_pixel = 0;
526 'he: begin
527 maxline = 0;
528 char_block = 0;
529 one_bit_pixel = 0;
531 'hf: begin
532 maxline = 0;
533 char_block = 0;
534 one_bit_pixel = 0;
536 endcase
539 assign dli = ir[7];
540 assign wait_vblank = (ir == 'h41);
541 assign dma_block = (ir[3:0] != 0 && ir[3:0] != 1);
543 assign load_dlptrl = new_block && (ir[3:0] == 1) && (hcount == 12);
544 assign load_dlptrh = new_block && (ir[3:0] == 1) && (hcount == 14);
546 assign load_memscanl = new_block && dma_block && ir[6] && (hcount == 12);
547 assign load_memscanh = new_block && dma_block && ir[6] && (hcount == 14);
549 assign load_mis = !vblank && dma_mis_en && (hcount == 0);
550 assign load_ply = !vblank && dma_ply_en &&
551 (hcount == 4 || hcount == 6 ||
552 hcount == 8 || hcount == 10);
553 assign dma_ply_num = (hcount >> 1) - 2;
555 assign dl_load = load_instr || load_memscanh || load_memscanl ||
556 load_dlptrh || load_dlptrl;
558 always @ (posedge clk2_i)
559 if (hcount == 16 + (ir[4] ? (hscrol & ~1) : 0))
560 ms_hcount <= 0;
561 else
562 ms_hcount <= ms_hcount + 1;
564 antic_ms_hcount_seq u_ms_hcount_seq(.clk_i(clk_i),
565 .ms_hcount(ms_hcount),
566 .new_block(new_block),
567 .dma_block(dma_block),
568 .char_block(char_block),
569 .dma_pf_width(dma_pf_width),
570 .ir(ir),
571 .shift_reg_shift(shift_reg_shift),
572 .load_pf(load_pf),
573 .load_char(load_char),
574 .load_out(load_out),
575 .out_reg_shift(out_reg_shift));
577 always @ (hcount or dma_pf_width or dma_instr_en or vblank) begin
578 if (!dma_instr_en || vblank)
579 dwin = 0;
580 else
581 case (dma_pf_width)
582 0: dwin = 0;
583 1: dwin = (hcount >= 64 && hcount < 192);
584 2: dwin = (hcount >= 48 && hcount < 208);
585 3: dwin = (hcount >= 44 && hcount < 220);
586 endcase
589 assign hblank = (hcount < 34 || hcount >= 222);
590 assign vblank = (vcount < 8 || vcount >= 240);
592 // TODO: lines here are approximate.
593 assign vsync = (vcount >= 300 && vcount < 303);
595 always @ (posedge clk_i)
596 if (load_char) begin
597 // TODO: change name out_reg_p na char_data
598 char_data <= masterdat_i;
599 char_color_p <= shift_reg_out[7:6];
602 always @ (posedge clk2_i)
603 if (load_out) begin
604 out_reg <= char_block ? char_data : shift_reg_out;
605 char_color <= char_color_p;
607 else if (out_reg_shift)
608 if (one_bit_pixel)
609 out_reg <= {out_reg[6:0], 1'b0};
610 else
611 out_reg <= {out_reg[5:0], 2'b00};
613 always @ (vsync or vblank or hblank or dwin or ir or out_reg or
614 char_color) begin
615 if (vsync)
616 antic_out = 3'b001;
617 else if (hblank || vblank)
618 if (ir[3:0] == 2 || ir[3:0] == 3 || ir[3:0] == 'hf)
619 antic_out = 3'b011;
620 else
621 antic_out = 3'b010;
622 else if (dwin)
623 if (ir[3:0] == 2 || ir[3:0] == 3)
624 if (char_color[1])
625 antic_out = {1'b1,
626 (out_reg[7:6] & ~{2{chactl[0]}}) ^ {2{chactl[1]}}};
627 else
628 antic_out = {1'b1, out_reg[7:6]};
629 else if (ir[3:0] == 'hf)
630 antic_out = {1'b1, out_reg[7:6]};
631 else if (ir[3:0] == 4 || ir[3:0] == 5)
632 case (out_reg[7:6])
633 0: antic_out = 3'b000;
634 1: antic_out = 3'b100;
635 2: antic_out = 3'b101;
636 3: antic_out = char_color[1] ? 3'b111 : 3'b110;
637 endcase
638 else if (ir[3:0] == 6 || ir[3:0] == 7)
639 if (out_reg[7])
640 antic_out = {1'b1, char_color};
641 else
642 antic_out = 3'b000;
643 else if (ir[3:0] == 8 || ir[3:0] == 'ha || ir[3:0] == 'hd ||
644 ir[3:0] == 'he)
645 case (out_reg[7:6])
646 0: antic_out = 3'b000;
647 1: antic_out = 3'b100;
648 2: antic_out = 3'b101;
649 3: antic_out = 3'b110;
650 endcase
651 else if (ir[3:0] == 9 || ir[3:0] == 'hb || ir[3:0] == 'hc)
652 antic_out = out_reg[7] ? 3'b100 : 3'b000;
653 else
654 antic_out = 3'b000;
655 else
656 antic_out = 3'b000;
659 always @ (dl_load or dlist_ctr or load_mis or load_ply or
660 pmbase or vcount or dma_ply_num or
661 load_pf or memscan_ctr or
662 load_char or chbase or shift_reg_out or dcount) begin
663 if (dl_load)
664 adr_o = dlist_ctr;
665 else if (load_mis)
666 adr_o = dma_pm_1res ?
667 {pmbase[5:1], 3'b011, vcount[7:0]} :
668 {pmbase[5:0], 3'b011, vcount[7:1]};
669 else if (load_ply)
670 adr_o = dma_pm_1res ?
671 {pmbase[5:1], 1'b1, dma_ply_num, vcount[7:0]} :
672 {pmbase[5:0], 1'b1, dma_ply_num, vcount[7:1]};
673 else if (load_pf)
674 adr_o = memscan_ctr;
675 else if (load_char)
676 case (ir[3:0])
677 2: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
678 3: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
679 4: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
680 5: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[3:1]};
681 6: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[2:0]};
682 7: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[3:1]};
683 endcase
684 else
685 adr_o = 0; // TODO: load some pointer by default
688 assign stb_o = dl_load || load_mis || load_ply || load_pf || load_char ||
689 wsync;
690 assign cyc_o = stb_o;
692 antic_shift_reg u_shift_reg(.clk_i(clk_i),
693 .shift(shift_reg_shift),
694 .load(load_pf),
695 .in(masterdat_i),
696 .out(shift_reg_out));
697 endmodule