Factor out ms_hcount sequencer into a module
[AtosmChip.git] / antic.v
blob1eeb103dcd28e6d69de74ec0279239f497ed4e98
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(ms_hcount,
19 new_block, dma_block, dma_pf_width, ir,
20 shift_reg_shift, load_pf, load_out);
21 input ms_hcount;
22 input new_block, dma_block, dma_pf_width, ir;
23 output shift_reg_shift, load_pf, load_out;
25 wire [7:0] ms_hcount;
26 wire new_block, dma_block;
27 wire [1:0] dma_pf_width;
28 wire [7:0] ir;
29 wire shift_reg_shift;
30 reg load_pf, load_out;
32 reg [3:0] pf_byte_mod;
34 always @ (ir)
35 case (ir[3:0])
36 'h2: pf_byte_mod = 3;
37 'h3: pf_byte_mod = 3;
38 'h4: pf_byte_mod = 3;
39 'h5: pf_byte_mod = 3;
40 'h6: pf_byte_mod = 7;
41 'h7: pf_byte_mod = 7;
42 'h8: pf_byte_mod = 15;
43 'h9: pf_byte_mod = 15;
44 'ha: pf_byte_mod = 7;
45 'hb: pf_byte_mod = 7;
46 'hc: pf_byte_mod = 7;
47 'hd: pf_byte_mod = 3;
48 'he: pf_byte_mod = 3;
49 'hf: pf_byte_mod = 3;
50 default: pf_byte_mod = 3;
51 endcase
53 assign shift_reg_shift = (ms_hcount >= 3) && (ms_hcount < 195) &&
54 (ms_hcount[1:0] == 3);
56 always @ (new_block or dma_block or dma_pf_width or ms_hcount or
57 pf_byte_mod or ir) begin
58 load_pf = 0;
59 if (new_block && dma_block) begin
60 if (dma_pf_width == 1 && !ir[4])
61 load_pf = ((ms_hcount & pf_byte_mod) == (3 & pf_byte_mod)) &&
62 (ms_hcount >= 35) && (ms_hcount < 163);
63 else if (dma_pf_width == (ir[4] ? 1 : 2))
64 load_pf = ((ms_hcount & pf_byte_mod) == (3 & pf_byte_mod)) &&
65 (ms_hcount >= 19) && (ms_hcount < 179);
66 else if (dma_pf_width == 3 || (ir[4] && dma_pf_width == 2))
67 load_pf = ((ms_hcount & pf_byte_mod) == (3 & pf_byte_mod)) &&
68 (ms_hcount >= 3) && (ms_hcount < 195);
69 end
70 end
72 always @ (dma_block or dma_pf_width or ms_hcount or pf_byte_mod) begin
73 load_out = 0;
74 if (dma_block)
75 case (dma_pf_width)
76 1: load_out = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
77 (ms_hcount >= 41 && ms_hcount < 169);
78 2: load_out = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
79 (ms_hcount >= 25 && ms_hcount < 185);
80 3: load_out = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
81 (ms_hcount >= 9 && ms_hcount < 201);
82 endcase
83 end
84 endmodule
86 module antic_shift_reg(clk_i, shift, load, in, out);
87 input clk_i;
88 input shift;
89 input load;
90 input in;
92 output out;
94 wire clk_i;
95 wire shift;
96 wire load;
97 wire [7:0] in;
98 wire [7:0] out;
100 reg [7:0] shift_reg [0:47];
102 integer i;
104 assign out = shift_reg[1];
106 always @ (posedge clk_i) begin
107 if (shift)
108 for (i = 0; i < 47; i = i + 1)
109 shift_reg[i + 1] <= shift_reg[i];
110 if (load)
111 shift_reg[0] <= in;
112 else if (shift)
113 shift_reg[0] <= shift_reg[47];
115 endmodule
117 module antic(rst_i, clk_i,
118 adr_i, adr_o,
119 slavedat_i, masterdat_i,
120 dat_o,
121 we_i,
122 stb_i, stb_o,
123 ack_i, ack_o,
124 cyc_o,
125 clk2_i,
126 nmi,
127 antic_out);
128 input rst_i;
129 input clk_i;
130 input adr_i;
131 input slavedat_i;
132 input masterdat_i;
133 input we_i;
134 input stb_i;
135 input ack_i;
136 input clk2_i;
138 output adr_o;
139 output dat_o;
140 output stb_o;
141 output ack_o;
142 output cyc_o;
143 output nmi;
144 output antic_out;
146 wire rst_i, clk_i;
147 wire [3:0] adr_i;
148 wire [7:0] slavedat_i;
149 wire [7:0] masterdat_i;
150 wire we_i;
151 wire stb_i;
152 wire ack_i;
153 wire clk2_i;
155 reg [15:0] adr_o;
156 reg [7:0] dat_o;
157 wire stb_o;
158 wire ack_o;
159 wire cyc_o;
160 wire nmi;
161 reg [2:0] antic_out;
163 reg [1:0] dma_pf_width;
164 reg dma_mis_en;
165 reg dma_ply_en;
166 reg dma_pm_1res;
167 reg dma_instr_en;
169 reg [6:0] chbase;
170 reg [2:0] chactl;
171 reg [5:0] pmbase;
172 reg [3:0] hscrol;
173 reg [3:0] vscrol;
175 wire nmireq_dli, nmireq_vbi;
176 reg nmist_dli, nmist_vbi;
177 reg nmien_dli, nmien_vbi;
179 reg [15:0] dlist_ctr;
180 reg [7:0] dlist_ctr_tmp;
181 wire dl_load;
183 reg [15:0] memscan_ctr;
185 reg [7:0] hcount;
186 reg [8:0] vcount;
187 reg [3:0] dcount;
188 reg [7:0] ms_hcount;
190 reg [7:0] ir;
191 reg new_block;
192 reg [3:0] maxline;
193 wire dli;
194 wire wait_vblank;
195 wire dma_block;
196 reg char_block;
197 reg one_bit_pixel;
198 reg [1:0] pf_pixel_mod;
200 reg wsync;
202 wire load_instr;
203 wire load_dlptrl;
204 wire load_dlptrh;
205 wire load_memscanl;
206 wire load_memscanh;
207 wire load_mis;
208 wire load_ply;
209 wire load_pf;
210 wire load_char;
212 wire [1:0] dma_ply_num;
214 wire load_out;
216 wire hblank, vblank, vsync;
217 reg dwin;
219 wire shift_reg_shift;
220 wire [7:0] shift_reg_out;
221 reg [7:0] out_reg;
222 reg [1:0] char_color;
224 assign ack_o = stb_i;
226 // Read registers.
227 always @ (adr_i or vcount or nmist_dli or nmist_vbi)
228 case (adr_i)
229 'hb:
230 dat_o = vcount[8:1];
231 'hf:
232 dat_o = {nmist_dli, nmist_vbi, 6'b0};
233 default:
234 dat_o = 'hff;
235 endcase
237 // DMACTL
238 always @ (posedge clk_i)
239 if (stb_i && we_i && adr_i == 'h0) begin
240 dma_pf_width <= slavedat_i[1:0];
241 dma_mis_en <= slavedat_i[2];
242 dma_ply_en <= slavedat_i[3];
243 dma_pm_1res <= slavedat_i[4];
244 dma_instr_en <= slavedat_i[5];
247 // CHACTL
248 always @ (posedge clk_i)
249 if (stb_i && we_i && adr_i == 'h1)
250 chactl <= slavedat_i[2:0];
252 // DLISTL/H
253 always @ (posedge clk_i)
254 if (stb_i && we_i && adr_i == 'h2)
255 dlist_ctr[7:0] <= slavedat_i;
256 else if (stb_i && we_i && adr_i == 'h3)
257 dlist_ctr[15:8] <= slavedat_i;
258 else if (dl_load) begin
259 if (!load_dlptrh)
260 dlist_ctr[9:0] <= dlist_ctr[9:0] + 1;
261 else begin
262 dlist_ctr[15:8] <= masterdat_i;
263 dlist_ctr[7:0] <= dlist_ctr_tmp;
265 if (load_dlptrl)
266 dlist_ctr_tmp <= masterdat_i;
269 // HSCROL
270 always @ (posedge clk_i)
271 if (stb_i && we_i && adr_i == 'h4)
272 hscrol <= slavedat_i[3:0];
274 // VSCROL
275 always @ (posedge clk_i)
276 if (stb_i && we_i && adr_i == 'h5)
277 vscrol <= slavedat_i[3:0];
279 // PMBASE
280 always @ (posedge clk_i)
281 if (stb_i && we_i && adr_i == 'h7)
282 pmbase <= slavedat_i[7:2];
284 // CHBASE
285 always @ (posedge clk_i)
286 if (stb_i && we_i && adr_i == 'h9)
287 chbase <= slavedat_i[7:1];
289 // WSYNC
290 always @ (posedge clk_i)
291 if (rst_i || hcount == 206)
292 wsync <= 0;
293 else if (stb_i && we_i && adr_i == 'ha)
294 wsync <= 1;
296 // NMIEN
297 always @ (posedge clk_i)
298 if (rst_i) begin
299 nmien_vbi <= 0;
300 nmien_dli <= 0;
301 end else if (stb_i && we_i && adr_i == 'he) begin
302 nmien_vbi <= slavedat_i[6];
303 nmien_dli <= slavedat_i[7];
306 // HCOUNT
307 always @ (posedge clk2_i)
308 if (rst_i && !clk_i)
309 hcount <= 0;
310 else if (hcount == 227)
311 hcount <= 0;
312 else
313 hcount <= hcount + 1;
315 // VCOUNT
316 always @ (posedge clk2_i)
317 if (rst_i && !clk_i)
318 vcount <= 0;
319 else if (hcount == 227)
320 if (vcount == 311)
321 vcount <= 0;
322 else
323 vcount <= vcount + 1;
325 // Display list interrupt.
326 assign nmireq_dli = (hcount == 16 && dcount == maxline && dli &&
327 nmien_dli && !vblank && !wait_vblank);
329 // Vertical blank interrupt.
330 assign nmireq_vbi = (hcount == 16 && vcount == 240 && nmien_vbi);
332 always @ (posedge clk_i)
333 if (rst_i) begin
334 nmist_vbi <= 0;
335 nmist_dli <= 0;
336 end else if (nmireq_vbi) begin
337 nmist_vbi <= 1;
338 nmist_dli <= 0;
339 end else if (nmireq_dli) begin
340 nmist_vbi <= 0;
341 nmist_dli <= 1;
342 end else if (stb_i && we_i && adr_i =='hf) begin
343 nmist_vbi <= 0;
344 nmist_dli <= 0;
347 assign nmi = nmireq_dli | nmireq_vbi;
349 always @ (posedge clk2_i)
350 if (hcount == 227)
351 if (dma_instr_en &&
352 (vcount == 7 ||
353 (dcount == maxline && !wait_vblank && !vblank && dma_instr_en)))
354 new_block <= 1;
355 else
356 new_block <= 0;
358 assign load_instr = new_block && (hcount == 2);
360 // DCOUNT
361 always @ (posedge clk2_i)
362 if (vcount == 0)
363 dcount <= 0;
364 else if (hcount == 0)
365 if (new_block)
366 dcount <= 0; // TODO: vscroll
367 else
368 dcount <= dcount + 1;
370 // Memory Scan Counter.
371 always @ (posedge clk_i)
372 if (load_pf)
373 memscan_ctr[11:0] <= memscan_ctr[11:0] + 1;
374 else if (load_memscanl)
375 memscan_ctr[7:0] <= masterdat_i;
376 else if (load_memscanh)
377 memscan_ctr[15:8] <= masterdat_i;
379 // Instruction register.
380 always @ (posedge clk_i)
381 if (load_instr)
382 ir <= masterdat_i;
383 else if (vcount == 0)
384 ir <= 0;
386 // Instruction decoder.
387 always @ (ir) begin
388 maxline = 0;
389 char_block = 0;
390 one_bit_pixel = 0;
391 pf_pixel_mod = 0;
392 case (ir[3:0])
393 'h0: maxline = ir[6:4];
394 'h1: maxline = 0;
395 'h2: begin
396 maxline = 7;
397 char_block = 1;
398 one_bit_pixel = 0;
399 pf_pixel_mod = 0;
401 'h3: begin
402 maxline = 9;
403 char_block = 1;
404 one_bit_pixel = 0;
405 pf_pixel_mod = 0;
407 'h4: begin
408 maxline = 7;
409 char_block = 1;
410 one_bit_pixel = 0;
411 pf_pixel_mod = 0;
413 'h5: begin
414 maxline = 15;
415 char_block = 1;
416 one_bit_pixel = 0;
417 pf_pixel_mod = 0;
419 'h6: begin
420 maxline = 7;
421 char_block = 1;
422 one_bit_pixel = 1;
423 pf_pixel_mod = 0;
425 'h7: begin
426 maxline = 15;
427 char_block = 1;
428 one_bit_pixel = 1;
429 pf_pixel_mod = 0;
431 'h8: begin
432 maxline = 7;
433 char_block = 0;
434 one_bit_pixel = 0;
435 pf_pixel_mod = 3;
437 'h9: begin
438 maxline = 3;
439 char_block = 0;
440 one_bit_pixel = 1;
441 pf_pixel_mod = 1;
443 'ha: begin
444 maxline = 3;
445 char_block = 0;
446 one_bit_pixel = 0;
447 pf_pixel_mod = 1;
449 'hb: begin
450 maxline = 1;
451 char_block = 0;
452 one_bit_pixel = 1;
453 pf_pixel_mod = 0;
455 'hc: begin
456 maxline = 0;
457 char_block = 0;
458 one_bit_pixel = 1;
459 pf_pixel_mod = 0;
461 'hd: begin
462 maxline = 1;
463 char_block = 0;
464 one_bit_pixel = 0;
465 pf_pixel_mod = 0;
467 'he: begin
468 maxline = 0;
469 char_block = 0;
470 one_bit_pixel = 0;
471 pf_pixel_mod = 0;
473 'hf: begin
474 maxline = 0;
475 char_block = 0;
476 one_bit_pixel = 0;
477 pf_pixel_mod = 0;
479 endcase
482 assign dli = ir[7];
483 assign wait_vblank = (ir == 'h41);
484 assign dma_block = (ir[3:0] != 0 && ir[3:0] != 1);
486 assign load_dlptrl = new_block && (ir[3:0] == 1) && (hcount == 12);
487 assign load_dlptrh = new_block && (ir[3:0] == 1) && (hcount == 14);
489 assign load_memscanl = new_block && dma_block && ir[6] && (hcount == 12);
490 assign load_memscanh = new_block && dma_block && ir[6] && (hcount == 14);
492 assign load_mis = !vblank && dma_mis_en && (hcount == 0);
493 assign load_ply = !vblank && dma_ply_en &&
494 (hcount == 4 || hcount == 6 ||
495 hcount == 8 || hcount == 10);
496 assign dma_ply_num = (hcount >> 1) - 2;
498 assign dl_load = load_instr || load_memscanh || load_memscanl ||
499 load_dlptrh || load_dlptrl;
501 always @ (posedge clk2_i)
502 if (hcount == 16 + (ir[4] ? (hscrol & ~1) : 0))
503 ms_hcount <= 0;
504 else
505 ms_hcount <= ms_hcount + 1;
507 antic_ms_hcount_seq u_ms_hcount_seq(.ms_hcount(ms_hcount),
508 .new_block(new_block),
509 .dma_block(dma_block),
510 .dma_pf_width(dma_pf_width),
511 .ir(ir),
512 .shift_reg_shift(shift_reg_shift),
513 .load_pf(load_pf),
514 .load_out(load_out));
516 always @ (hcount or dma_pf_width or dma_instr_en or vblank) begin
517 if (!dma_instr_en || vblank)
518 dwin = 0;
519 else
520 case (dma_pf_width)
521 0: dwin = 0;
522 1: dwin = (hcount >= 64 && hcount < 192);
523 2: dwin = (hcount >= 48 && hcount < 208);
524 3: dwin = (hcount >= 44 && hcount < 220);
525 endcase
528 assign hblank = (hcount < 34 || hcount >= 222);
529 assign vblank = (vcount < 8 || vcount >= 240);
531 // TODO: lines here are approximate.
532 assign vsync = (vcount >= 300 && vcount < 303);
534 assign load_char = load_out && char_block;
536 always @ (posedge clk2_i)
537 if (load_out)
538 if (char_block) begin
539 out_reg <= masterdat_i;
540 char_color <= shift_reg_out[7:6];
541 end else
542 out_reg <= shift_reg_out;
543 else if ((hcount & pf_pixel_mod) == (3 & pf_pixel_mod))
544 if (one_bit_pixel)
545 out_reg <= {out_reg[6:0], 1'b0};
546 else
547 out_reg <= {out_reg[5:0], 2'b00};
549 always @ (vsync or vblank or hblank or dwin or ir or out_reg or
550 char_color) begin
551 if (vsync)
552 antic_out = 3'b001;
553 else if (hblank || vblank)
554 if (ir[3:0] == 2 || ir[3:0] == 3 || ir[3:0] == 'hf)
555 antic_out = 3'b011;
556 else
557 antic_out = 3'b010;
558 else if (dwin)
559 if (ir[3:0] == 2 || ir[3:0] == 3)
560 if (char_color[1])
561 antic_out = {1'b1,
562 (out_reg[7:6] & ~{2{chactl[0]}}) ^ {2{chactl[1]}}};
563 else
564 antic_out = {1'b1, out_reg[7:6]};
565 else if (ir[3:0] == 'hf)
566 antic_out = {1'b1, out_reg[7:6]};
567 else if (ir[3:0] == 4 || ir[3:0] == 5)
568 case (out_reg[7:6])
569 0: antic_out = 3'b000;
570 1: antic_out = 3'b100;
571 2: antic_out = 3'b101;
572 3: antic_out = char_color[1] ? 3'b111 : 3'b110;
573 endcase
574 else if (ir[3:0] == 6 || ir[3:0] == 7)
575 if (out_reg[7])
576 antic_out = {1'b1, char_color};
577 else
578 antic_out = 3'b000;
579 else if (ir[3:0] == 8 || ir[3:0] == 'ha || ir[3:0] == 'hd ||
580 ir[3:0] == 'he)
581 case (out_reg[7:6])
582 0: antic_out = 3'b000;
583 1: antic_out = 3'b100;
584 2: antic_out = 3'b101;
585 3: antic_out = 3'b110;
586 endcase
587 else if (ir[3:0] == 9 || ir[3:0] == 'hb || ir[3:0] == 'hc)
588 antic_out = out_reg[7] ? 3'b100 : 3'b000;
589 else
590 antic_out = 3'b000;
591 else
592 antic_out = 3'b000;
595 always @ (dl_load or dlist_ctr or load_mis or load_ply or
596 pmbase or vcount or dma_ply_num or
597 load_pf or memscan_ctr or
598 load_char or chbase or shift_reg_out or dcount) begin
599 if (dl_load)
600 adr_o = dlist_ctr;
601 else if (load_mis)
602 adr_o = dma_pm_1res ?
603 {pmbase[5:1], 3'b011, vcount[7:0]} :
604 {pmbase[5:0], 3'b011, vcount[7:1]};
605 else if (load_ply)
606 adr_o = dma_pm_1res ?
607 {pmbase[5:1], 1'b1, dma_ply_num, vcount[7:0]} :
608 {pmbase[5:0], 1'b1, dma_ply_num, vcount[7:1]};
609 else if (load_pf)
610 adr_o = memscan_ctr;
611 else if (load_char)
612 case (ir[3:0])
613 2: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
614 3: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
615 4: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
616 5: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[3:1]};
617 6: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[2:0]};
618 7: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[3:1]};
619 endcase
620 else
621 adr_o = 0; // TODO: load some pointer by default
624 assign stb_o = dl_load || load_mis || load_ply || load_pf || load_char ||
625 wsync;
626 assign cyc_o = stb_o;
628 antic_shift_reg u_shift_reg(.clk_i(clk_i),
629 .shift(shift_reg_shift),
630 .load(load_pf),
631 .in(masterdat_i),
632 .out(shift_reg_out));
633 endmodule