Take hscroll into account when computing load_char_0
[AtosmChip.git] / antic.v
blob296f58d4ad13ce7387ba7fc37e1b887f15fc8f26
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 wire 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 @ (char_block or dma_block or dma_pf_width or ms_hcount or
127 pf_byte_mod) begin
128 load_char_0 = 0;
129 if (char_block && dma_block) begin
130 if (dma_pf_width == 1 && !ir[4])
131 load_char_0 = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
132 (ms_hcount >= 32 + 9 && ms_hcount < 160 + 9);
133 else if (dma_pf_width == (ir[4] ? 1 : 2))
134 load_char_0 = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
135 (ms_hcount >= 16 + 9 && ms_hcount < 176 + 9);
136 else if (dma_pf_width == 3 || (ir[4] && dma_pf_width == 2))
137 load_char_0 = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
138 (ms_hcount >= 9 && ms_hcount < 192 + 9);
142 assign load_out = ((ms_hcount[3:0] & pf_byte_mod) == (4'd12 & pf_byte_mod));
144 always @ (posedge clk_i) begin
145 load_pf <= load_pf_0;
146 load_char <= load_char_0;
148 endmodule
150 module antic_shift_reg(clk_i, shift, load, in, out);
151 input clk_i;
152 input shift;
153 input load;
154 input in;
156 output out;
158 wire clk_i;
159 wire shift;
160 wire load;
161 wire [7:0] in;
162 wire [7:0] out;
164 reg [7:0] shift_reg [0:47];
166 integer i;
168 assign out = shift_reg[1];
170 always @ (posedge clk_i) begin
171 if (shift)
172 for (i = 0; i < 47; i = i + 1)
173 shift_reg[i + 1] <= shift_reg[i];
174 if (load)
175 shift_reg[0] <= in;
176 else if (shift)
177 shift_reg[0] <= shift_reg[47];
179 endmodule
181 module antic(rst_i, clk_i,
182 adr_i, adr_o,
183 slavedat_i, masterdat_i,
184 dat_o,
185 we_i,
186 stb_i, stb_o,
187 ack_i, ack_o,
188 cyc_o,
189 clk2_i,
190 nmi,
191 antic_out);
192 input rst_i;
193 input clk_i;
194 input adr_i;
195 input slavedat_i;
196 input masterdat_i;
197 input we_i;
198 input stb_i;
199 input ack_i;
200 input clk2_i;
202 output adr_o;
203 output dat_o;
204 output stb_o;
205 output ack_o;
206 output cyc_o;
207 output nmi;
208 output antic_out;
210 wire rst_i, clk_i;
211 wire [3:0] adr_i;
212 wire [7:0] slavedat_i;
213 wire [7:0] masterdat_i;
214 wire we_i;
215 wire stb_i;
216 wire ack_i;
217 wire clk2_i;
219 reg [15:0] adr_o;
220 reg [7:0] dat_o;
221 wire stb_o;
222 wire ack_o;
223 wire cyc_o;
224 wire nmi;
225 reg [2:0] antic_out;
227 reg [1:0] dma_pf_width;
228 reg dma_mis_en;
229 reg dma_ply_en;
230 reg dma_pm_1res;
231 reg dma_instr_en;
233 reg [6:0] chbase;
234 reg [2:0] chactl;
235 reg [5:0] pmbase;
236 reg [3:0] hscrol;
237 reg [3:0] vscrol;
239 wire nmireq_dli, nmireq_vbi;
240 reg nmist_dli, nmist_vbi;
241 reg nmien_dli, nmien_vbi;
243 reg [15:0] dlist_ctr;
244 reg [7:0] dlist_ctr_tmp;
245 wire dl_load;
247 reg [15:0] memscan_ctr;
249 reg [7:0] hcount;
250 reg [8:0] vcount;
251 reg [3:0] dcount;
252 reg [7:0] ms_hcount;
254 reg [7:0] ir;
255 reg new_block;
256 reg [3:0] maxline;
257 wire dli;
258 wire wait_vblank;
259 wire dma_block;
260 reg char_block;
261 reg one_bit_pixel;
263 reg wsync;
265 wire load_instr;
266 wire load_dlptrl;
267 wire load_dlptrh;
268 wire load_memscanl;
269 wire load_memscanh;
270 wire load_mis;
271 wire load_ply;
272 wire load_pf;
273 wire load_char;
275 wire [1:0] dma_ply_num;
277 wire load_out_p, load_out;
279 wire hblank, vblank, vsync;
280 reg dwin;
282 wire shift_reg_shift;
283 wire [7:0] shift_reg_out;
284 reg [7:0] char_data, out_reg;
285 wire out_reg_shift;
286 reg [1:0] char_color_p, char_color;
288 assign ack_o = stb_i;
290 // Read registers.
291 always @ (adr_i or vcount or nmist_dli or nmist_vbi)
292 case (adr_i)
293 'hb:
294 dat_o = vcount[8:1];
295 'hf:
296 dat_o = {nmist_dli, nmist_vbi, 6'b0};
297 default:
298 dat_o = 'hff;
299 endcase
301 // DMACTL
302 always @ (posedge clk_i)
303 if (stb_i && we_i && adr_i == 'h0) begin
304 dma_pf_width <= slavedat_i[1:0];
305 dma_mis_en <= slavedat_i[2];
306 dma_ply_en <= slavedat_i[3];
307 dma_pm_1res <= slavedat_i[4];
308 dma_instr_en <= slavedat_i[5];
311 // CHACTL
312 always @ (posedge clk_i)
313 if (stb_i && we_i && adr_i == 'h1)
314 chactl <= slavedat_i[2:0];
316 // DLISTL/H
317 always @ (posedge clk_i)
318 if (stb_i && we_i && adr_i == 'h2)
319 dlist_ctr[7:0] <= slavedat_i;
320 else if (stb_i && we_i && adr_i == 'h3)
321 dlist_ctr[15:8] <= slavedat_i;
322 else if (dl_load) begin
323 if (!load_dlptrh)
324 dlist_ctr[9:0] <= dlist_ctr[9:0] + 1;
325 else begin
326 dlist_ctr[15:8] <= masterdat_i;
327 dlist_ctr[7:0] <= dlist_ctr_tmp;
329 if (load_dlptrl)
330 dlist_ctr_tmp <= masterdat_i;
333 // HSCROL
334 always @ (posedge clk_i)
335 if (stb_i && we_i && adr_i == 'h4)
336 hscrol <= slavedat_i[3:0];
338 // VSCROL
339 always @ (posedge clk_i)
340 if (stb_i && we_i && adr_i == 'h5)
341 vscrol <= slavedat_i[3:0];
343 // PMBASE
344 always @ (posedge clk_i)
345 if (stb_i && we_i && adr_i == 'h7)
346 pmbase <= slavedat_i[7:2];
348 // CHBASE
349 always @ (posedge clk_i)
350 if (stb_i && we_i && adr_i == 'h9)
351 chbase <= slavedat_i[7:1];
353 // WSYNC
354 always @ (posedge clk_i)
355 if (rst_i || hcount == 206)
356 wsync <= 0;
357 else if (stb_i && we_i && adr_i == 'ha)
358 wsync <= 1;
360 // NMIEN
361 always @ (posedge clk_i)
362 if (rst_i) begin
363 nmien_vbi <= 0;
364 nmien_dli <= 0;
365 end else if (stb_i && we_i && adr_i == 'he) begin
366 nmien_vbi <= slavedat_i[6];
367 nmien_dli <= slavedat_i[7];
370 // HCOUNT
371 always @ (posedge clk2_i)
372 if (rst_i && !clk_i)
373 hcount <= 0;
374 else if (hcount == 227)
375 hcount <= 0;
376 else
377 hcount <= hcount + 1;
379 // VCOUNT
380 always @ (posedge clk2_i)
381 if (rst_i && !clk_i)
382 vcount <= 0;
383 else if (hcount == 227)
384 if (vcount == 311)
385 vcount <= 0;
386 else
387 vcount <= vcount + 1;
389 // Display list interrupt.
390 assign nmireq_dli = (hcount == 16 && dcount == maxline && dli &&
391 nmien_dli && !vblank && !wait_vblank);
393 // Vertical blank interrupt.
394 assign nmireq_vbi = (hcount == 16 && vcount == 240 && nmien_vbi);
396 always @ (posedge clk_i)
397 if (rst_i) begin
398 nmist_vbi <= 0;
399 nmist_dli <= 0;
400 end else if (nmireq_vbi) begin
401 nmist_vbi <= 1;
402 nmist_dli <= 0;
403 end else if (nmireq_dli) begin
404 nmist_vbi <= 0;
405 nmist_dli <= 1;
406 end else if (stb_i && we_i && adr_i =='hf) begin
407 nmist_vbi <= 0;
408 nmist_dli <= 0;
411 assign nmi = nmireq_dli | nmireq_vbi;
413 always @ (posedge clk2_i)
414 if (hcount == 227)
415 if (dma_instr_en &&
416 (vcount == 7 ||
417 (dcount == maxline && !wait_vblank && !vblank && dma_instr_en)))
418 new_block <= 1;
419 else
420 new_block <= 0;
422 assign load_instr = new_block && (hcount == 2);
424 // DCOUNT
425 always @ (posedge clk2_i)
426 if (vcount == 0)
427 dcount <= 0;
428 else if (hcount == 0)
429 if (new_block)
430 dcount <= 0; // TODO: vscroll
431 else
432 dcount <= dcount + 1;
434 // Memory Scan Counter.
435 always @ (posedge clk_i)
436 if (load_pf)
437 memscan_ctr[11:0] <= memscan_ctr[11:0] + 1;
438 else if (load_memscanl)
439 memscan_ctr[7:0] <= masterdat_i;
440 else if (load_memscanh)
441 memscan_ctr[15:8] <= masterdat_i;
443 // Instruction register.
444 always @ (posedge clk_i)
445 if (load_instr)
446 ir <= masterdat_i;
447 else if (vcount == 0)
448 ir <= 0;
450 // Instruction decoder.
451 always @ (ir) begin
452 maxline = 0;
453 char_block = 0;
454 one_bit_pixel = 0;
455 case (ir[3:0])
456 'h0: maxline = ir[6:4];
457 'h1: maxline = 0;
458 'h2: begin
459 maxline = 7;
460 char_block = 1;
461 one_bit_pixel = 0;
463 'h3: begin
464 maxline = 9;
465 char_block = 1;
466 one_bit_pixel = 0;
468 'h4: begin
469 maxline = 7;
470 char_block = 1;
471 one_bit_pixel = 0;
473 'h5: begin
474 maxline = 15;
475 char_block = 1;
476 one_bit_pixel = 0;
478 'h6: begin
479 maxline = 7;
480 char_block = 1;
481 one_bit_pixel = 1;
483 'h7: begin
484 maxline = 15;
485 char_block = 1;
486 one_bit_pixel = 1;
488 'h8: begin
489 maxline = 7;
490 char_block = 0;
491 one_bit_pixel = 0;
493 'h9: begin
494 maxline = 3;
495 char_block = 0;
496 one_bit_pixel = 1;
498 'ha: begin
499 maxline = 3;
500 char_block = 0;
501 one_bit_pixel = 0;
503 'hb: begin
504 maxline = 1;
505 char_block = 0;
506 one_bit_pixel = 1;
508 'hc: begin
509 maxline = 0;
510 char_block = 0;
511 one_bit_pixel = 1;
513 'hd: begin
514 maxline = 1;
515 char_block = 0;
516 one_bit_pixel = 0;
518 'he: begin
519 maxline = 0;
520 char_block = 0;
521 one_bit_pixel = 0;
523 'hf: begin
524 maxline = 0;
525 char_block = 0;
526 one_bit_pixel = 0;
528 endcase
531 assign dli = ir[7];
532 assign wait_vblank = (ir == 'h41);
533 assign dma_block = (ir[3:0] != 0 && ir[3:0] != 1);
535 assign load_dlptrl = new_block && (ir[3:0] == 1) && (hcount == 12);
536 assign load_dlptrh = new_block && (ir[3:0] == 1) && (hcount == 14);
538 assign load_memscanl = new_block && dma_block && ir[6] && (hcount == 12);
539 assign load_memscanh = new_block && dma_block && ir[6] && (hcount == 14);
541 assign load_mis = !vblank && dma_mis_en && (hcount == 0);
542 assign load_ply = !vblank && dma_ply_en &&
543 (hcount == 4 || hcount == 6 ||
544 hcount == 8 || hcount == 10);
545 assign dma_ply_num = (hcount >> 1) - 2;
547 assign dl_load = load_instr || load_memscanh || load_memscanl ||
548 load_dlptrh || load_dlptrl;
550 always @ (posedge clk2_i)
551 if (hcount == 16 + (ir[4] ? (hscrol & ~1) : 0))
552 ms_hcount <= 0;
553 else
554 ms_hcount <= ms_hcount + 1;
556 antic_ms_hcount_seq u_ms_hcount_seq(.clk_i(clk_i),
557 .ms_hcount(ms_hcount),
558 .new_block(new_block),
559 .dma_block(dma_block),
560 .char_block(char_block),
561 .dma_pf_width(dma_pf_width),
562 .ir(ir),
563 .shift_reg_shift(shift_reg_shift),
564 .load_pf(load_pf),
565 .load_char(load_char),
566 .load_out(load_out),
567 .out_reg_shift(out_reg_shift));
569 always @ (hcount or dma_pf_width or dma_instr_en or vblank) begin
570 if (!dma_instr_en || vblank)
571 dwin = 0;
572 else
573 case (dma_pf_width)
574 0: dwin = 0;
575 1: dwin = (hcount >= 64 && hcount < 192);
576 2: dwin = (hcount >= 48 && hcount < 208);
577 3: dwin = (hcount >= 44 && hcount < 220);
578 endcase
581 assign hblank = (hcount < 34 || hcount >= 222);
582 assign vblank = (vcount < 8 || vcount >= 240);
584 // TODO: lines here are approximate.
585 assign vsync = (vcount >= 300 && vcount < 303);
587 always @ (posedge clk_i)
588 if (load_char) begin
589 // TODO: change name out_reg_p na char_data
590 char_data <= masterdat_i;
591 char_color_p <= shift_reg_out[7:6];
594 always @ (posedge clk2_i)
595 if (load_out) begin
596 out_reg <= char_block ? char_data : shift_reg_out;
597 char_color <= char_color_p;
599 else if (out_reg_shift)
600 if (one_bit_pixel)
601 out_reg <= {out_reg[6:0], 1'b0};
602 else
603 out_reg <= {out_reg[5:0], 2'b00};
605 always @ (vsync or vblank or hblank or dwin or ir or out_reg or
606 char_color) begin
607 if (vsync)
608 antic_out = 3'b001;
609 else if (hblank || vblank)
610 if (ir[3:0] == 2 || ir[3:0] == 3 || ir[3:0] == 'hf)
611 antic_out = 3'b011;
612 else
613 antic_out = 3'b010;
614 else if (dwin)
615 if (ir[3:0] == 2 || ir[3:0] == 3)
616 if (char_color[1])
617 antic_out = {1'b1,
618 (out_reg[7:6] & ~{2{chactl[0]}}) ^ {2{chactl[1]}}};
619 else
620 antic_out = {1'b1, out_reg[7:6]};
621 else if (ir[3:0] == 'hf)
622 antic_out = {1'b1, out_reg[7:6]};
623 else if (ir[3:0] == 4 || ir[3:0] == 5)
624 case (out_reg[7:6])
625 0: antic_out = 3'b000;
626 1: antic_out = 3'b100;
627 2: antic_out = 3'b101;
628 3: antic_out = char_color[1] ? 3'b111 : 3'b110;
629 endcase
630 else if (ir[3:0] == 6 || ir[3:0] == 7)
631 if (out_reg[7])
632 antic_out = {1'b1, char_color};
633 else
634 antic_out = 3'b000;
635 else if (ir[3:0] == 8 || ir[3:0] == 'ha || ir[3:0] == 'hd ||
636 ir[3:0] == 'he)
637 case (out_reg[7:6])
638 0: antic_out = 3'b000;
639 1: antic_out = 3'b100;
640 2: antic_out = 3'b101;
641 3: antic_out = 3'b110;
642 endcase
643 else if (ir[3:0] == 9 || ir[3:0] == 'hb || ir[3:0] == 'hc)
644 antic_out = out_reg[7] ? 3'b100 : 3'b000;
645 else
646 antic_out = 3'b000;
647 else
648 antic_out = 3'b000;
651 always @ (dl_load or dlist_ctr or load_mis or load_ply or
652 pmbase or vcount or dma_ply_num or
653 load_pf or memscan_ctr or
654 load_char or chbase or shift_reg_out or dcount) begin
655 if (dl_load)
656 adr_o = dlist_ctr;
657 else if (load_mis)
658 adr_o = dma_pm_1res ?
659 {pmbase[5:1], 3'b011, vcount[7:0]} :
660 {pmbase[5:0], 3'b011, vcount[7:1]};
661 else if (load_ply)
662 adr_o = dma_pm_1res ?
663 {pmbase[5:1], 1'b1, dma_ply_num, vcount[7:0]} :
664 {pmbase[5:0], 1'b1, dma_ply_num, vcount[7:1]};
665 else if (load_pf)
666 adr_o = memscan_ctr;
667 else if (load_char)
668 case (ir[3:0])
669 2: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
670 3: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
671 4: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
672 5: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[3:1]};
673 6: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[2:0]};
674 7: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[3:1]};
675 endcase
676 else
677 adr_o = 0; // TODO: load some pointer by default
680 assign stb_o = dl_load || load_mis || load_ply || load_pf || load_char ||
681 wsync;
682 assign cyc_o = stb_o;
684 antic_shift_reg u_shift_reg(.clk_i(clk_i),
685 .shift(shift_reg_shift),
686 .load(load_pf),
687 .in(masterdat_i),
688 .out(shift_reg_out));
689 endmodule