New CPU test
[AtosmChip.git] / antic.v
blobdb1bd5c3bd86a54ee1fc1ff389a6c34082f4a23a
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;
121 reg [7:0] ir;
122 reg new_block;
123 reg [3:0] maxline;
124 wire dli;
125 wire wait_vblank;
126 wire dma_block;
127 reg char_block;
128 reg one_bit_pixel;
129 reg [1:0] pf_pixel_mod;
130 reg [3:0] pf_byte_mod;
132 reg wsync;
134 wire load_instr;
135 wire load_dlptrl;
136 wire load_dlptrh;
137 wire load_memscanl;
138 wire load_memscanh;
139 wire load_mis;
140 wire load_ply;
141 reg load_pf;
142 wire load_char;
144 wire [1:0] dma_ply_num;
146 reg load_out;
148 wire hblank, vblank, vsync;
149 reg dwin;
151 wire shift_reg_shift;
152 wire [7:0] shift_reg_out;
153 reg [7:0] out_reg;
154 reg [1:0] char_color;
156 assign ack_o = stb_i;
158 // Read registers.
159 always @ (adr_i or vcount or nmist_dli or nmist_vbi)
160 case (adr_i)
161 'hb:
162 dat_o = vcount[8:1];
163 'hf:
164 dat_o = {nmist_dli, nmist_vbi, 6'b0};
165 default:
166 dat_o = 'hff;
167 endcase
169 // DMACTL
170 always @ (posedge clk_i)
171 if (stb_i && we_i && adr_i == 'h0) begin
172 dma_pf_width <= slavedat_i[1:0];
173 dma_mis_en <= slavedat_i[2];
174 dma_ply_en <= slavedat_i[3];
175 dma_pm_1res <= slavedat_i[4];
176 dma_instr_en <= slavedat_i[5];
179 // CHACTL
180 always @ (posedge clk_i)
181 if (stb_i && we_i && adr_i == 'h1)
182 chactl <= slavedat_i[2:0];
184 // DLISTL/H
185 always @ (posedge clk_i)
186 if (stb_i && we_i && adr_i == 'h2)
187 dlist_ctr[7:0] <= slavedat_i;
188 else if (stb_i && we_i && adr_i == 'h3)
189 dlist_ctr[15:8] <= slavedat_i;
190 else if (dl_load) begin
191 if (!load_dlptrh)
192 dlist_ctr[9:0] <= dlist_ctr[9:0] + 1;
193 else begin
194 dlist_ctr[15:8] <= masterdat_i;
195 dlist_ctr[7:0] <= dlist_ctr_tmp;
197 if (load_dlptrl)
198 dlist_ctr_tmp <= masterdat_i;
201 // HSCROL
202 always @ (posedge clk_i)
203 if (stb_i && we_i && adr_i == 'h4)
204 hscrol <= slavedat_i[3:0];
206 // VSCROL
207 always @ (posedge clk_i)
208 if (stb_i && we_i && adr_i == 'h5)
209 vscrol <= slavedat_i[3:0];
211 // PMBASE
212 always @ (posedge clk_i)
213 if (stb_i && we_i && adr_i == 'h7)
214 pmbase <= slavedat_i[7:2];
216 // CHBASE
217 always @ (posedge clk_i)
218 if (stb_i && we_i && adr_i == 'h9)
219 chbase <= slavedat_i[7:1];
221 // WSYNC
222 always @ (posedge clk_i)
223 if (rst_i || hcount == 206)
224 wsync <= 0;
225 else if (stb_i && we_i && adr_i == 'ha)
226 wsync <= 1;
228 // NMIEN
229 always @ (posedge clk_i)
230 if (rst_i) begin
231 nmien_vbi <= 0;
232 nmien_dli <= 0;
233 end else if (stb_i && we_i && adr_i == 'he) begin
234 nmien_vbi <= slavedat_i[6];
235 nmien_dli <= slavedat_i[7];
238 // HCOUNT
239 always @ (posedge clk2_i)
240 if (rst_i && !clk_i)
241 hcount <= 0;
242 else if (hcount == 227)
243 hcount <= 0;
244 else
245 hcount <= hcount + 1;
247 // VCOUNT
248 always @ (posedge clk2_i)
249 if (rst_i && !clk_i)
250 vcount <= 0;
251 else if (hcount == 227)
252 if (vcount == 311)
253 vcount <= 0;
254 else
255 vcount <= vcount + 1;
257 // Display list interrupt.
258 assign nmireq_dli = (hcount == 16 && dcount == maxline && dli &&
259 nmien_dli && !vblank && !wait_vblank);
261 // Vertical blank interrupt.
262 assign nmireq_vbi = (hcount == 16 && vcount == 240 && nmien_vbi);
264 always @ (posedge clk_i)
265 if (rst_i) begin
266 nmist_vbi <= 0;
267 nmist_dli <= 0;
268 end else if (nmireq_vbi) begin
269 nmist_vbi <= 1;
270 nmist_dli <= 0;
271 end else if (nmireq_dli) begin
272 nmist_vbi <= 0;
273 nmist_dli <= 1;
274 end else if (stb_i && we_i && adr_i =='hf) begin
275 nmist_vbi <= 0;
276 nmist_dli <= 0;
279 assign nmi = nmireq_dli | nmireq_vbi;
281 always @ (posedge clk2_i)
282 if (hcount == 227)
283 if (dma_instr_en &&
284 (vcount == 7 ||
285 (dcount == maxline && !wait_vblank && !vblank && dma_instr_en)))
286 new_block <= 1;
287 else
288 new_block <= 0;
290 assign load_instr = new_block && (hcount == 2);
292 // DCOUNT
293 always @ (posedge clk2_i)
294 if (vcount == 0)
295 dcount <= 0;
296 else if (hcount == 0)
297 if (new_block)
298 dcount <= 0; // TODO: vscroll
299 else
300 dcount <= dcount + 1;
302 // Memory Scan Counter.
303 always @ (posedge clk_i)
304 if (load_pf)
305 memscan_ctr[11:0] <= memscan_ctr[11:0] + 1;
306 else if (load_memscanl)
307 memscan_ctr[7:0] <= masterdat_i;
308 else if (load_memscanh)
309 memscan_ctr[15:8] <= masterdat_i;
311 // Instruction register.
312 always @ (posedge clk_i)
313 if (load_instr)
314 ir <= masterdat_i;
315 else if (vcount == 0)
316 ir <= 0;
318 // Instruction decoder.
319 always @ (ir) begin
320 maxline = 0;
321 char_block = 0;
322 one_bit_pixel = 0;
323 pf_pixel_mod = 0;
324 pf_byte_mod = 3;
325 case (ir[3:0])
326 'h0: maxline = ir[6:4];
327 'h1: maxline = 0;
328 'h2: begin
329 maxline = 7;
330 char_block = 1;
331 one_bit_pixel = 0;
332 pf_pixel_mod = 0;
333 pf_byte_mod = 3;
335 'h3: begin
336 maxline = 9;
337 char_block = 1;
338 one_bit_pixel = 0;
339 pf_pixel_mod = 0;
340 pf_byte_mod = 3;
342 'h4: begin
343 maxline = 7;
344 char_block = 1;
345 one_bit_pixel = 0;
346 pf_pixel_mod = 0;
347 pf_byte_mod = 3;
349 'h5: begin
350 maxline = 15;
351 char_block = 1;
352 one_bit_pixel = 0;
353 pf_pixel_mod = 0;
354 pf_byte_mod = 3;
356 'h6: begin
357 maxline = 7;
358 char_block = 1;
359 one_bit_pixel = 1;
360 pf_pixel_mod = 0;
361 pf_byte_mod = 7;
363 'h7: begin
364 maxline = 15;
365 char_block = 1;
366 one_bit_pixel = 1;
367 pf_pixel_mod = 0;
368 pf_byte_mod = 7;
370 'h8: begin
371 maxline = 7;
372 char_block = 0;
373 one_bit_pixel = 0;
374 pf_pixel_mod = 3;
375 pf_byte_mod = 15;
377 'h9: begin
378 maxline = 3;
379 char_block = 0;
380 one_bit_pixel = 1;
381 pf_pixel_mod = 1;
382 pf_byte_mod = 15;
384 'ha: begin
385 maxline = 3;
386 char_block = 0;
387 one_bit_pixel = 0;
388 pf_pixel_mod = 1;
389 pf_byte_mod = 7;
391 'hb: begin
392 maxline = 1;
393 char_block = 0;
394 one_bit_pixel = 1;
395 pf_pixel_mod = 0;
396 pf_byte_mod = 7;
398 'hc: begin
399 maxline = 0;
400 char_block = 0;
401 one_bit_pixel = 1;
402 pf_pixel_mod = 0;
403 pf_byte_mod = 7;
405 'hd: begin
406 maxline = 1;
407 char_block = 0;
408 one_bit_pixel = 0;
409 pf_pixel_mod = 0;
410 pf_byte_mod = 3;
412 'he: begin
413 maxline = 0;
414 char_block = 0;
415 one_bit_pixel = 0;
416 pf_pixel_mod = 0;
417 pf_byte_mod = 3;
419 'hf: begin
420 maxline = 0;
421 char_block = 0;
422 one_bit_pixel = 0;
423 pf_pixel_mod = 0;
424 pf_byte_mod = 3;
426 endcase
429 assign dli = ir[7];
430 assign wait_vblank = (ir == 'h41);
431 assign dma_block = (ir[3:0] != 0 && ir[3:0] != 1);
433 assign load_dlptrl = new_block && (ir[3:0] == 1) && (hcount == 12);
434 assign load_dlptrh = new_block && (ir[3:0] == 1) && (hcount == 14);
436 assign load_memscanl = new_block && dma_block && ir[6] && (hcount == 12);
437 assign load_memscanh = new_block && dma_block && ir[6] && (hcount == 14);
439 assign load_mis = !vblank && dma_mis_en && (hcount == 0);
440 assign load_ply = !vblank && dma_ply_en &&
441 (hcount == 4 || hcount == 6 ||
442 hcount == 8 || hcount == 10);
443 assign dma_ply_num = (hcount - 4) >> 1;
445 assign dl_load = load_instr || load_memscanh || load_memscanl ||
446 load_dlptrh || load_dlptrl;
448 // TODO: have (hcount - hscroll) and use it for shift_reg_shift,
449 // load_pf and load_out?
450 assign shift_reg_shift = (hcount >= 20) && (hcount < 212) &&
451 (hcount[1:0] == 0);
453 always @ (hcount or dma_pf_width or new_block) begin
454 load_pf = 0;
455 // TODO: hscroll
456 if (new_block && dma_block)
457 case (dma_pf_width)
458 1: load_pf = ((hcount & pf_byte_mod) == (4 & pf_byte_mod)) &&
459 (hcount >= 52) && (hcount < 180);
460 2: load_pf = ((hcount & pf_byte_mod) == (4 & pf_byte_mod)) &&
461 (hcount >= 36) && (hcount < 196);
462 3: load_pf = ((hcount & pf_byte_mod) == (4 & pf_byte_mod)) &&
463 (hcount >= 20) && (hcount < 212);
464 endcase
467 always @ (hcount or dma_pf_width or new_block) begin
468 load_out = 0;
469 // TODO: hscroll
470 if (dma_block)
471 case (dma_pf_width)
472 1: load_out = ((hcount & pf_byte_mod) == (10 & pf_byte_mod)) &&
473 (hcount >= 58 && hcount < 186);
474 2: load_out = ((hcount & pf_byte_mod) == (10 & pf_byte_mod)) &&
475 (hcount >= 42 && hcount < 202);
476 3: load_out = ((hcount & pf_byte_mod) == (10 & pf_byte_mod)) &&
477 (hcount >= 26 && hcount < 218);
478 endcase
481 always @ (hcount or dma_pf_width or dma_instr_en or vblank) begin
482 if (!dma_instr_en || vblank)
483 dwin = 0;
484 else
485 case (dma_pf_width)
486 0: dwin = 0;
487 1: dwin = (hcount >= 64 && hcount < 192);
488 2: dwin = (hcount >= 48 && hcount < 208);
489 3: dwin = (hcount >= 44 && hcount < 220);
490 endcase
493 assign hblank = (hcount < 34 || hcount >= 222);
494 assign vblank = (vcount < 8 || vcount >= 240);
496 // TODO: lines here are approximate.
497 assign vsync = (vcount >= 300 && vcount < 303);
499 assign load_char = load_out && char_block;
501 always @ (posedge clk2_i)
502 if (load_out)
503 if (char_block) begin
504 out_reg <= masterdat_i;
505 char_color <= shift_reg_out[7:6];
506 end else
507 out_reg <= shift_reg_out;
508 else if ((hcount & pf_pixel_mod) == (3 & pf_pixel_mod))
509 if (one_bit_pixel)
510 out_reg <= {out_reg[6:0], 1'b0};
511 else
512 out_reg <= {out_reg[5:0], 2'b00};
514 always @ (vsync or vblank or hblank or dwin or ir or out_reg or
515 char_color) begin
516 if (vsync)
517 antic_out = 3'b001;
518 else if (hblank || vblank)
519 if (ir[3:0] == 2 || ir[3:0] == 3 || ir[3:0] == 'hf)
520 antic_out = 3'b011;
521 else
522 antic_out = 3'b010;
523 else if (dwin)
524 if (ir[3:0] == 2 || ir[3:0] == 3 || ir[3:0] == 'hf)
525 // TODO: chactl
526 antic_out = {1'b1, out_reg[7:6]};
527 else if (ir[3:0] == 4 || ir[3:0] == 5)
528 case (out_reg[7:6])
529 0: antic_out = 3'b000;
530 1: antic_out = 3'b100;
531 2: antic_out = 3'b101;
532 3: antic_out = char_color[1] ? 3'b111 : 3'b110;
533 endcase
534 else if (ir[3:0] == 6 || ir[3:0] == 7)
535 if (out_reg[7])
536 antic_out = {1'b1, char_color};
537 else
538 antic_out = 3'b000;
539 else if (ir[3:0] == 8 || ir[3:0] == 'ha || ir[3:0] == 'hd ||
540 ir[3:0] == 'he)
541 case (out_reg[7:6])
542 0: antic_out = 3'b000;
543 1: antic_out = 3'b100;
544 2: antic_out = 3'b101;
545 3: antic_out = 3'b110;
546 endcase
547 else if (ir[3:0] == 9 || ir[3:0] == 'hb || ir[3:0] == 'hc)
548 antic_out = out_reg[7] ? 3'b100 : 3'b000;
549 else
550 antic_out = 3'b000;
551 else
552 antic_out = 3'b000;
555 always @ (dl_load or dlist_ctr or load_mis or load_ply or
556 pmbase or vcount or dma_ply_num or
557 load_pf or memscan_ctr or
558 load_char or chbase or shift_reg_out or dcount) begin
559 if (dl_load)
560 adr_o = dlist_ctr;
561 else if (load_mis)
562 adr_o = dma_pm_1res ?
563 {pmbase[5:1], 3'b011, vcount[7:0]} :
564 {pmbase[5:0], 3'b011, vcount[7:1]};
565 else if (load_ply)
566 adr_o = dma_pm_1res ?
567 {pmbase[5:1], 1'b1, dma_ply_num, vcount[7:0]} :
568 {pmbase[5:0], 1'b1, dma_ply_num, vcount[7:1]};
569 else if (load_pf)
570 adr_o = memscan_ctr;
571 else if (load_char)
572 case (ir[3:0])
573 2: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
574 3: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
575 4: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[2:0]};
576 5: adr_o = {chbase[6:1], shift_reg_out[6:0], dcount[3:1]};
577 6: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[2:0]};
578 7: adr_o = {chbase[6:0], shift_reg_out[5:0], dcount[3:1]};
579 endcase
580 else
581 adr_o = 0; // TODO: load some pointer by default
584 assign stb_o = dl_load || load_mis || load_ply || load_pf || load_char ||
585 wsync;
586 assign cyc_o = stb_o;
588 antic_shift_reg u_shift_reg(.clk_i(clk_i),
589 .shift(shift_reg_shift),
590 .load(load_pf),
591 .in(masterdat_i),
592 .out(shift_reg_out));
593 endmodule