Add ms_hcount (hcount for memscan)
[AtosmChip.git] / antic.v
blob3d6f944d4e2525f5801fa8ad50630a29dd6c07f0
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_shift_reg(clk_i, shift, load, in, out);
19 input clk_i;
20 input shift;
21 input load;
22 input in;
24 output out;
26 wire clk_i;
27 wire shift;
28 wire load;
29 wire [7:0] in;
30 wire [7:0] out;
32 reg [7:0] shift_reg [0:47];
34 integer i;
36 assign out = shift_reg[1];
38 always @ (posedge clk_i) begin
39 if (shift)
40 for (i = 0; i < 47; i = i + 1)
41 shift_reg[i + 1] <= shift_reg[i];
42 if (load)
43 shift_reg[0] <= in;
44 else if (shift)
45 shift_reg[0] <= shift_reg[47];
46 end
47 endmodule
49 module antic(rst_i, clk_i,
50 adr_i, adr_o,
51 slavedat_i, masterdat_i,
52 dat_o,
53 we_i,
54 stb_i, stb_o,
55 ack_i, ack_o,
56 cyc_o,
57 clk2_i,
58 nmi,
59 antic_out);
60 input rst_i;
61 input clk_i;
62 input adr_i;
63 input slavedat_i;
64 input masterdat_i;
65 input we_i;
66 input stb_i;
67 input ack_i;
68 input clk2_i;
70 output adr_o;
71 output dat_o;
72 output stb_o;
73 output ack_o;
74 output cyc_o;
75 output nmi;
76 output antic_out;
78 wire rst_i, clk_i;
79 wire [3:0] adr_i;
80 wire [7:0] slavedat_i;
81 wire [7:0] masterdat_i;
82 wire we_i;
83 wire stb_i;
84 wire ack_i;
85 wire clk2_i;
87 reg [15:0] adr_o;
88 reg [7:0] dat_o;
89 wire stb_o;
90 wire ack_o;
91 wire cyc_o;
92 wire nmi;
93 reg [2:0] antic_out;
95 reg [1:0] dma_pf_width;
96 reg dma_mis_en;
97 reg dma_ply_en;
98 reg dma_pm_1res;
99 reg dma_instr_en;
101 reg [6:0] chbase;
102 reg [2:0] chactl;
103 reg [5:0] pmbase;
104 reg [3:0] hscrol;
105 reg [3:0] vscrol;
107 wire nmireq_dli, nmireq_vbi;
108 reg nmist_dli, nmist_vbi;
109 reg nmien_dli, nmien_vbi;
111 reg [15:0] dlist_ctr;
112 reg [7:0] dlist_ctr_tmp;
113 wire dl_load;
115 reg [15:0] memscan_ctr;
117 reg [7:0] hcount;
118 reg [8:0] vcount;
119 reg [3:0] dcount;
120 reg [7:0] ms_hcount;
122 reg [7:0] ir;
123 reg new_block;
124 reg [3:0] maxline;
125 wire dli;
126 wire wait_vblank;
127 wire dma_block;
128 reg char_block;
129 reg one_bit_pixel;
130 reg [1:0] pf_pixel_mod;
131 reg [3:0] pf_byte_mod;
133 reg wsync;
135 wire load_instr;
136 wire load_dlptrl;
137 wire load_dlptrh;
138 wire load_memscanl;
139 wire load_memscanh;
140 wire load_mis;
141 wire load_ply;
142 reg load_pf;
143 wire load_char;
145 wire [1:0] dma_ply_num;
147 reg load_out;
149 wire hblank, vblank, vsync;
150 reg dwin;
152 wire shift_reg_shift;
153 wire [7:0] shift_reg_out;
154 reg [7:0] out_reg;
155 reg [1:0] char_color;
157 assign ack_o = stb_i;
159 // Read registers.
160 always @ (adr_i or vcount or nmist_dli or nmist_vbi)
161 case (adr_i)
162 'hb:
163 dat_o = vcount[8:1];
164 'hf:
165 dat_o = {nmist_dli, nmist_vbi, 6'b0};
166 default:
167 dat_o = 'hff;
168 endcase
170 // DMACTL
171 always @ (posedge clk_i)
172 if (stb_i && we_i && adr_i == 'h0) begin
173 dma_pf_width <= slavedat_i[1:0];
174 dma_mis_en <= slavedat_i[2];
175 dma_ply_en <= slavedat_i[3];
176 dma_pm_1res <= slavedat_i[4];
177 dma_instr_en <= slavedat_i[5];
180 // CHACTL
181 always @ (posedge clk_i)
182 if (stb_i && we_i && adr_i == 'h1)
183 chactl <= slavedat_i[2:0];
185 // DLISTL/H
186 always @ (posedge clk_i)
187 if (stb_i && we_i && adr_i == 'h2)
188 dlist_ctr[7:0] <= slavedat_i;
189 else if (stb_i && we_i && adr_i == 'h3)
190 dlist_ctr[15:8] <= slavedat_i;
191 else if (dl_load) begin
192 if (!load_dlptrh)
193 dlist_ctr[9:0] <= dlist_ctr[9:0] + 1;
194 else begin
195 dlist_ctr[15:8] <= masterdat_i;
196 dlist_ctr[7:0] <= dlist_ctr_tmp;
198 if (load_dlptrl)
199 dlist_ctr_tmp <= masterdat_i;
202 // HSCROL
203 always @ (posedge clk_i)
204 if (stb_i && we_i && adr_i == 'h4)
205 hscrol <= slavedat_i[3:0];
207 // VSCROL
208 always @ (posedge clk_i)
209 if (stb_i && we_i && adr_i == 'h5)
210 vscrol <= slavedat_i[3:0];
212 // PMBASE
213 always @ (posedge clk_i)
214 if (stb_i && we_i && adr_i == 'h7)
215 pmbase <= slavedat_i[7:2];
217 // CHBASE
218 always @ (posedge clk_i)
219 if (stb_i && we_i && adr_i == 'h9)
220 chbase <= slavedat_i[7:1];
222 // WSYNC
223 always @ (posedge clk_i)
224 if (rst_i || hcount == 206)
225 wsync <= 0;
226 else if (stb_i && we_i && adr_i == 'ha)
227 wsync <= 1;
229 // NMIEN
230 always @ (posedge clk_i)
231 if (rst_i) begin
232 nmien_vbi <= 0;
233 nmien_dli <= 0;
234 end else if (stb_i && we_i && adr_i == 'he) begin
235 nmien_vbi <= slavedat_i[6];
236 nmien_dli <= slavedat_i[7];
239 // HCOUNT
240 always @ (posedge clk2_i)
241 if (rst_i && !clk_i)
242 hcount <= 0;
243 else if (hcount == 227)
244 hcount <= 0;
245 else
246 hcount <= hcount + 1;
248 // VCOUNT
249 always @ (posedge clk2_i)
250 if (rst_i && !clk_i)
251 vcount <= 0;
252 else if (hcount == 227)
253 if (vcount == 311)
254 vcount <= 0;
255 else
256 vcount <= vcount + 1;
258 // Display list interrupt.
259 assign nmireq_dli = (hcount == 16 && dcount == maxline && dli &&
260 nmien_dli && !vblank && !wait_vblank);
262 // Vertical blank interrupt.
263 assign nmireq_vbi = (hcount == 16 && vcount == 240 && nmien_vbi);
265 always @ (posedge clk_i)
266 if (rst_i) begin
267 nmist_vbi <= 0;
268 nmist_dli <= 0;
269 end else if (nmireq_vbi) begin
270 nmist_vbi <= 1;
271 nmist_dli <= 0;
272 end else if (nmireq_dli) begin
273 nmist_vbi <= 0;
274 nmist_dli <= 1;
275 end else if (stb_i && we_i && adr_i =='hf) begin
276 nmist_vbi <= 0;
277 nmist_dli <= 0;
280 assign nmi = nmireq_dli | nmireq_vbi;
282 always @ (posedge clk2_i)
283 if (hcount == 227)
284 if (dma_instr_en &&
285 (vcount == 7 ||
286 (dcount == maxline && !wait_vblank && !vblank && dma_instr_en)))
287 new_block <= 1;
288 else
289 new_block <= 0;
291 assign load_instr = new_block && (hcount == 2);
293 // DCOUNT
294 always @ (posedge clk2_i)
295 if (vcount == 0)
296 dcount <= 0;
297 else if (hcount == 0)
298 if (new_block)
299 dcount <= 0; // TODO: vscroll
300 else
301 dcount <= dcount + 1;
303 // Memory Scan Counter.
304 always @ (posedge clk_i)
305 if (load_pf)
306 memscan_ctr[11:0] <= memscan_ctr[11:0] + 1;
307 else if (load_memscanl)
308 memscan_ctr[7:0] <= masterdat_i;
309 else if (load_memscanh)
310 memscan_ctr[15:8] <= masterdat_i;
312 // Instruction register.
313 always @ (posedge clk_i)
314 if (load_instr)
315 ir <= masterdat_i;
316 else if (vcount == 0)
317 ir <= 0;
319 // Instruction decoder.
320 always @ (ir) begin
321 maxline = 0;
322 char_block = 0;
323 one_bit_pixel = 0;
324 pf_pixel_mod = 0;
325 pf_byte_mod = 3;
326 case (ir[3:0])
327 'h0: maxline = ir[6:4];
328 'h1: maxline = 0;
329 'h2: begin
330 maxline = 7;
331 char_block = 1;
332 one_bit_pixel = 0;
333 pf_pixel_mod = 0;
334 pf_byte_mod = 3;
336 'h3: begin
337 maxline = 9;
338 char_block = 1;
339 one_bit_pixel = 0;
340 pf_pixel_mod = 0;
341 pf_byte_mod = 3;
343 'h4: begin
344 maxline = 7;
345 char_block = 1;
346 one_bit_pixel = 0;
347 pf_pixel_mod = 0;
348 pf_byte_mod = 3;
350 'h5: begin
351 maxline = 15;
352 char_block = 1;
353 one_bit_pixel = 0;
354 pf_pixel_mod = 0;
355 pf_byte_mod = 3;
357 'h6: begin
358 maxline = 7;
359 char_block = 1;
360 one_bit_pixel = 1;
361 pf_pixel_mod = 0;
362 pf_byte_mod = 7;
364 'h7: begin
365 maxline = 15;
366 char_block = 1;
367 one_bit_pixel = 1;
368 pf_pixel_mod = 0;
369 pf_byte_mod = 7;
371 'h8: begin
372 maxline = 7;
373 char_block = 0;
374 one_bit_pixel = 0;
375 pf_pixel_mod = 3;
376 pf_byte_mod = 15;
378 'h9: begin
379 maxline = 3;
380 char_block = 0;
381 one_bit_pixel = 1;
382 pf_pixel_mod = 1;
383 pf_byte_mod = 15;
385 'ha: begin
386 maxline = 3;
387 char_block = 0;
388 one_bit_pixel = 0;
389 pf_pixel_mod = 1;
390 pf_byte_mod = 7;
392 'hb: begin
393 maxline = 1;
394 char_block = 0;
395 one_bit_pixel = 1;
396 pf_pixel_mod = 0;
397 pf_byte_mod = 7;
399 'hc: begin
400 maxline = 0;
401 char_block = 0;
402 one_bit_pixel = 1;
403 pf_pixel_mod = 0;
404 pf_byte_mod = 7;
406 'hd: begin
407 maxline = 1;
408 char_block = 0;
409 one_bit_pixel = 0;
410 pf_pixel_mod = 0;
411 pf_byte_mod = 3;
413 'he: begin
414 maxline = 0;
415 char_block = 0;
416 one_bit_pixel = 0;
417 pf_pixel_mod = 0;
418 pf_byte_mod = 3;
420 'hf: begin
421 maxline = 0;
422 char_block = 0;
423 one_bit_pixel = 0;
424 pf_pixel_mod = 0;
425 pf_byte_mod = 3;
427 endcase
430 assign dli = ir[7];
431 assign wait_vblank = (ir == 'h41);
432 assign dma_block = (ir[3:0] != 0 && ir[3:0] != 1);
434 assign load_dlptrl = new_block && (ir[3:0] == 1) && (hcount == 12);
435 assign load_dlptrh = new_block && (ir[3:0] == 1) && (hcount == 14);
437 assign load_memscanl = new_block && dma_block && ir[6] && (hcount == 12);
438 assign load_memscanh = new_block && dma_block && ir[6] && (hcount == 14);
440 assign load_mis = !vblank && dma_mis_en && (hcount == 0);
441 assign load_ply = !vblank && dma_ply_en &&
442 (hcount == 4 || hcount == 6 ||
443 hcount == 8 || hcount == 10);
444 assign dma_ply_num = (hcount >> 1) - 2;
446 assign dl_load = load_instr || load_memscanh || load_memscanl ||
447 load_dlptrh || load_dlptrl;
449 always @ (posedge clk2_i)
450 if (hcount == 16 + (ir[4] ? (hscrol & ~1) : 0))
451 ms_hcount <= 0;
452 else
453 ms_hcount <= ms_hcount + 1;
455 assign shift_reg_shift = (ms_hcount >= 3) && (ms_hcount < 195) &&
456 (ms_hcount[1:0] == 3);
458 always @ (new_block or dma_block or dma_pf_width or ms_hcount or
459 pf_byte_mod or ir) begin
460 load_pf = 0;
461 if (new_block && dma_block) begin
462 if (dma_pf_width == 1 && !ir[4])
463 load_pf = ((ms_hcount & pf_byte_mod) == (3 & pf_byte_mod)) &&
464 (ms_hcount >= 35) && (ms_hcount < 163);
465 else if (dma_pf_width == (ir[4] ? 1 : 2))
466 load_pf = ((ms_hcount & pf_byte_mod) == (3 & pf_byte_mod)) &&
467 (ms_hcount >= 19) && (ms_hcount < 179);
468 else if (dma_pf_width == 3 || (ir[4] && dma_pf_width == 2))
469 load_pf = ((ms_hcount & pf_byte_mod) == (3 & pf_byte_mod)) &&
470 (ms_hcount >= 3) && (ms_hcount < 195);
474 always @ (dma_block or dma_pf_width or ms_hcount or pf_byte_mod) begin
475 load_out = 0;
476 if (dma_block)
477 case (dma_pf_width)
478 1: load_out = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
479 (ms_hcount >= 41 && hcount < 169);
480 2: load_out = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
481 (ms_hcount >= 25 && ms_hcount < 185);
482 3: load_out = ((ms_hcount & pf_byte_mod) == (9 & pf_byte_mod)) &&
483 (ms_hcount >= 9 && ms_hcount < 201);
484 endcase
487 always @ (hcount or dma_pf_width or dma_instr_en or vblank) begin
488 if (!dma_instr_en || vblank)
489 dwin = 0;
490 else
491 case (dma_pf_width)
492 0: dwin = 0;
493 1: dwin = (hcount >= 64 && hcount < 192);
494 2: dwin = (hcount >= 48 && hcount < 208);
495 3: dwin = (hcount >= 44 && hcount < 220);
496 endcase
499 assign hblank = (hcount < 34 || hcount >= 222);
500 assign vblank = (vcount < 8 || vcount >= 240);
502 // TODO: lines here are approximate.
503 assign vsync = (vcount >= 300 && vcount < 303);
505 assign load_char = load_out && char_block;
507 always @ (posedge clk2_i)
508 if (load_out)
509 if (char_block) begin
510 out_reg <= masterdat_i;
511 char_color <= shift_reg_out[7:6];
512 end else
513 out_reg <= shift_reg_out;
514 else if ((hcount & pf_pixel_mod) == (3 & pf_pixel_mod))
515 if (one_bit_pixel)
516 out_reg <= {out_reg[6:0], 1'b0};
517 else
518 out_reg <= {out_reg[5:0], 2'b00};
520 always @ (vsync or vblank or hblank or dwin or ir or out_reg or
521 char_color) begin
522 if (vsync)
523 antic_out = 3'b001;
524 else if (hblank || vblank)
525 if (ir[3:0] == 2 || ir[3:0] == 3 || ir[3:0] == 'hf)
526 antic_out = 3'b011;
527 else
528 antic_out = 3'b010;
529 else if (dwin)
530 if (ir[3:0] == 2 || ir[3:0] == 3)
531 if (char_color[1])
532 antic_out = {1'b1,
533 (out_reg[7:6] & ~{2{chactl[0]}}) ^ {2{chactl[1]}}};
534 else
535 antic_out = {1'b1, out_reg[7:6]};
536 else if (ir[3:0] == 'hf)
537 antic_out = {1'b1, out_reg[7:6]};
538 else if (ir[3:0] == 4 || ir[3:0] == 5)
539 case (out_reg[7:6])
540 0: antic_out = 3'b000;
541 1: antic_out = 3'b100;
542 2: antic_out = 3'b101;
543 3: antic_out = char_color[1] ? 3'b111 : 3'b110;
544 endcase
545 else if (ir[3:0] == 6 || ir[3:0] == 7)
546 if (out_reg[7])
547 antic_out = {1'b1, char_color};
548 else
549 antic_out = 3'b000;
550 else if (ir[3:0] == 8 || ir[3:0] == 'ha || ir[3:0] == 'hd ||
551 ir[3:0] == 'he)
552 case (out_reg[7:6])
553 0: antic_out = 3'b000;
554 1: antic_out = 3'b100;
555 2: antic_out = 3'b101;
556 3: antic_out = 3'b110;
557 endcase
558 else if (ir[3:0] == 9 || ir[3:0] == 'hb || ir[3:0] == 'hc)
559 antic_out = out_reg[7] ? 3'b100 : 3'b000;
560 else
561 antic_out = 3'b000;
562 else
563 antic_out = 3'b000;
566 always @ (dl_load or dlist_ctr or load_mis or load_ply or
567 pmbase or vcount or dma_ply_num or
568 load_pf or memscan_ctr or
569 load_char or chbase or shift_reg_out or dcount) begin
570 if (dl_load)
571 adr_o = dlist_ctr;
572 else if (load_mis)
573 adr_o = dma_pm_1res ?
574 {pmbase[5:1], 3'b011, vcount[7:0]} :
575 {pmbase[5:0], 3'b011, vcount[7:1]};
576 else if (load_ply)
577 adr_o = dma_pm_1res ?
578 {pmbase[5:1], 1'b1, dma_ply_num, vcount[7:0]} :
579 {pmbase[5:0], 1'b1, dma_ply_num, vcount[7:1]};
580 else if (load_pf)
581 adr_o = memscan_ctr;
582 else if (load_char)
583 case (ir[3:0])
584 2: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
585 3: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
586 4: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
587 5: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[3:1]};
588 6: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[2:0]};
589 7: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[3:1]};
590 endcase
591 else
592 adr_o = 0; // TODO: load some pointer by default
595 assign stb_o = dl_load || load_mis || load_ply || load_pf || load_char ||
596 wsync;
597 assign cyc_o = stb_o;
599 antic_shift_reg u_shift_reg(.clk_i(clk_i),
600 .shift(shift_reg_shift),
601 .load(load_pf),
602 .in(masterdat_i),
603 .out(shift_reg_out));
604 endmodule