2 // Copyright (C) 2008 Tomasz Malesinski <tmal@mimuw.edu.pl>
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.
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
,
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
;
28 wire new_block
, dma_block
, char_block
;
29 wire [1:0] dma_pf_width
;
32 reg load_pf
, load_char
;
36 reg load_pf_0
, load_char_0
;
37 reg [3:0] pf_byte_mod
;
38 reg [1:0] pf_pixel_mod
;
106 assign shift_reg_shift
= (ms_hcount
>= 3) && (ms_hcount
< 192 + 3) &&
107 (ms_hcount
[1:0] == 3);
109 assign out_reg_shift
= ((ms_hcount
[1:0] & pf_pixel_mod
) ==
110 (2'd2 & pf_pixel_mod
));
112 always @ (new_block
or dma_block
or dma_pf_width
or ms_hcount
or
113 pf_byte_mod
or ir
) begin
114 pf_cyc
= char_block ?
3 : 7;
116 if (new_block
&& dma_block
) begin
117 if (dma_pf_width
== 1 && !ir
[4])
118 load_pf_0
= ((ms_hcount
& pf_byte_mod
) == (pf_cyc
& pf_byte_mod
)) &&
119 (ms_hcount
>= 32 + pf_cyc
) &&
120 (ms_hcount
< 160 + pf_cyc
);
121 else if (dma_pf_width
== (ir
[4] ?
1 : 2))
122 load_pf_0
= ((ms_hcount
& pf_byte_mod
) == (pf_cyc
& pf_byte_mod
)) &&
123 (ms_hcount
>= 16 + pf_cyc
) &&
124 (ms_hcount
< 176 + pf_cyc
);
125 else if (dma_pf_width
== 3 ||
(ir
[4] && dma_pf_width
== 2))
126 load_pf_0
= ((ms_hcount
& pf_byte_mod
) == (pf_cyc
& pf_byte_mod
)) &&
127 (ms_hcount
>= pf_cyc
) && (ms_hcount
< 192 + pf_cyc
);
131 always @ (char_block
or dma_block
or dma_pf_width
or ms_hcount
or
134 if (char_block
&& dma_block
) begin
135 if (dma_pf_width
== 1 && !ir
[4])
136 load_char_0
= ((ms_hcount
& pf_byte_mod
) == (9 & pf_byte_mod
)) &&
137 (ms_hcount
>= 32 + 9 && ms_hcount
< 160 + 9);
138 else if (dma_pf_width
== (ir
[4] ?
1 : 2))
139 load_char_0
= ((ms_hcount
& pf_byte_mod
) == (9 & pf_byte_mod
)) &&
140 (ms_hcount
>= 16 + 9 && ms_hcount
< 176 + 9);
141 else if (dma_pf_width
== 3 ||
(ir
[4] && dma_pf_width
== 2))
142 load_char_0
= ((ms_hcount
& pf_byte_mod
) == (9 & pf_byte_mod
)) &&
143 (ms_hcount
>= 9 && ms_hcount
< 192 + 9);
147 assign load_out
= ((ms_hcount
[3:0] & pf_byte_mod
) == (4'd14 & pf_byte_mod
));
149 always @ (posedge clk_i
) begin
150 load_pf
<= load_pf_0
;
151 load_char
<= load_char_0
;
155 module antic_shift_reg(clk_i
, shift
, load
, in
, out
);
169 reg [7:0] shift_reg
[0:47];
173 assign out
= shift_reg
[1];
175 always @ (posedge clk_i
) begin
177 for (i
= 0; i
< 47; i
= i
+ 1)
178 shift_reg
[i
+ 1] <= shift_reg
[i
];
182 shift_reg
[0] <= shift_reg
[47];
186 module antic(rst_i
, clk_i
,
188 slavedat_i
, masterdat_i
,
217 wire [7:0] slavedat_i
;
218 wire [7:0] masterdat_i
;
230 reg [2:0] pf_antic_out
, pf_antic_out_d
;
233 reg [1:0] dma_pf_width
;
245 wire nmireq_dli
, nmireq_vbi
;
246 reg nmist_dli
, nmist_vbi
;
247 reg nmien_dli
, nmien_vbi
;
249 reg [15:0] dlist_ctr
;
250 reg [7:0] dlist_ctr_tmp
;
253 reg [15:0] memscan_ctr
;
258 wire [3:0] chr_dcount
;
287 wire [1:0] dma_ply_num
;
289 wire load_out_p
, load_out
;
291 wire hblank
, vblank
, vsync
;
294 wire shift_reg_shift
;
295 wire [7:0] shift_reg_out
;
297 reg [7:0] char_data
, out_reg
;
299 reg [1:0] char_color_p
, char_color
;
301 assign ack_o
= stb_i
;
304 always @ (adr_i
or vcount
or nmist_dli
or nmist_vbi
)
309 dat_o
= {nmist_dli
, nmist_vbi
, 6'b0};
315 always @ (posedge clk_i
)
316 if (stb_i
&& we_i
&& adr_i
== 'h0
) begin
317 dma_pf_width
<= slavedat_i
[1:0];
318 dma_mis_en
<= slavedat_i
[2];
319 dma_ply_en
<= slavedat_i
[3];
320 dma_pm_1res
<= slavedat_i
[4];
321 dma_instr_en
<= slavedat_i
[5];
325 always @ (posedge clk_i
)
326 if (stb_i
&& we_i
&& adr_i
== 'h1
)
327 chactl
<= slavedat_i
[2:0];
330 always @ (posedge clk_i
)
331 if (stb_i
&& we_i
&& adr_i
== 'h2
)
332 dlist_ctr
[7:0] <= slavedat_i
;
333 else if (stb_i
&& we_i
&& adr_i
== 'h3
)
334 dlist_ctr
[15:8] <= slavedat_i
;
335 else if (dl_load
) begin
337 dlist_ctr
[9:0] <= dlist_ctr
[9:0] + 1;
339 dlist_ctr
[15:8] <= masterdat_i
;
340 dlist_ctr
[7:0] <= dlist_ctr_tmp
;
343 dlist_ctr_tmp
<= masterdat_i
;
347 always @ (posedge clk_i
)
348 if (stb_i
&& we_i
&& adr_i
== 'h4
)
349 hscrol
<= slavedat_i
[3:0];
352 always @ (posedge clk_i
)
353 if (stb_i
&& we_i
&& adr_i
== 'h5
)
354 vscrol
<= slavedat_i
[3:0];
357 always @ (posedge clk_i
)
358 if (stb_i
&& we_i
&& adr_i
== 'h7
)
359 pmbase
<= slavedat_i
[7:2];
362 always @ (posedge clk_i
)
363 if (stb_i
&& we_i
&& adr_i
== 'h9
)
364 chbase
<= slavedat_i
[7:1];
367 always @ (posedge clk_i
)
368 if (rst_i || hcount
== 206)
370 else if (stb_i
&& we_i
&& adr_i
== 'ha
)
374 always @ (posedge clk_i
)
378 end else if (stb_i
&& we_i
&& adr_i
== 'he
) begin
379 nmien_vbi
<= slavedat_i
[6];
380 nmien_dli
<= slavedat_i
[7];
384 always @ (posedge clk2_i
)
387 else if (hcount
== 227)
390 hcount
<= hcount
+ 1;
393 always @ (posedge clk2_i
)
396 else if (hcount
== 227)
400 vcount
<= vcount
+ 1;
402 // Display list interrupt.
403 assign nmireq_dli
= (hcount
== 16 && dcount
== maxline
&& dli
&&
404 nmien_dli
&& !vblank
&& !wait_vblank
);
406 // Vertical blank interrupt.
407 assign nmireq_vbi
= (hcount
== 16 && vcount
== 240 && nmien_vbi
);
409 always @ (posedge clk_i
)
413 end else if (nmireq_vbi
) begin
416 end else if (nmireq_dli
) begin
419 end else if (stb_i
&& we_i
&& adr_i
=='hf
) begin
424 assign nmi
= nmireq_dli | nmireq_vbi
;
426 always @ (posedge clk2_i
)
430 (dcount
== ((last_vscrol_en
&& !vscrol_en
) ? vscrol
: maxline
) &&
431 !wait_vblank
&& !vblank
&& dma_instr_en
)))
436 assign load_instr
= new_block
&& (hcount
== 2);
438 assign vscrol_en
= dma_block
&& ir
[5];
440 always @ (posedge clk2_i
)
441 if (hcount
== 0 && new_block
)
442 last_vscrol_en
<= vscrol_en
;
445 always @ (posedge clk2_i
)
448 else if (hcount
== 6)
450 dcount
<= (!last_vscrol_en
&& vscrol_en
) ? vscrol
: 0;
452 dcount
<= dcount
+ 1;
454 // Memory Scan Counter.
455 always @ (posedge clk_i
)
457 memscan_ctr
[11:0] <= memscan_ctr
[11:0] + 1;
458 else if (load_memscanl
)
459 memscan_ctr
[7:0] <= masterdat_i
;
460 else if (load_memscanh
)
461 memscan_ctr
[15:8] <= masterdat_i
;
463 // Instruction register.
464 always @ (posedge clk_i
)
467 else if (vcount
== 0)
470 // Instruction decoder.
476 'h0
: maxline
= ir
[6:4];
552 assign wait_vblank
= (ir
== 'h41
);
553 assign dma_block
= (ir
[3:0] != 0 && ir
[3:0] != 1);
555 assign load_dlptrl
= new_block
&& (ir
[3:0] == 1) && (hcount
== 12);
556 assign load_dlptrh
= new_block
&& (ir
[3:0] == 1) && (hcount
== 14);
558 assign load_memscanl
= new_block
&& dma_block
&& ir
[6] && (hcount
== 12);
559 assign load_memscanh
= new_block
&& dma_block
&& ir
[6] && (hcount
== 14);
561 assign load_mis
= !vblank
&& dma_mis_en
&& (hcount
== 0);
562 assign load_ply
= !vblank
&& dma_ply_en
&&
563 (hcount
== 4 || hcount
== 6 ||
564 hcount
== 8 || hcount
== 10);
565 assign dma_ply_num
= (hcount
>> 1) - 2;
567 assign dl_load
= load_instr || load_memscanh || load_memscanl ||
568 load_dlptrh || load_dlptrl
;
570 always @ (posedge clk2_i
)
571 if (hcount
== 16 + (ir
[4] ?
(hscrol
& ~1) : 0))
574 ms_hcount
<= ms_hcount
+ 1;
576 antic_ms_hcount_seq
u_ms_hcount_seq(.
clk_i(clk_i
),
577 .
ms_hcount(ms_hcount
),
578 .
new_block(new_block
),
579 .
dma_block(dma_block
),
580 .
char_block(char_block
),
581 .
dma_pf_width(dma_pf_width
),
583 .
shift_reg_shift(shift_reg_shift
),
585 .
load_char(load_char
),
587 .
out_reg_shift(out_reg_shift
));
589 always @ (hcount
or dma_pf_width
or dma_instr_en
or vblank
) begin
590 if (!dma_instr_en || vblank
)
595 1: dwin
= (hcount
>= 64 && hcount
< 192);
596 2: dwin
= (hcount
>= 48 && hcount
< 208);
597 3: dwin
= (hcount
>= 44 && hcount
< 220);
601 assign hblank
= (hcount
< 34 || hcount
>= 222);
602 assign vblank
= (vcount
< 8 || vcount
>= 240);
604 // TODO: lines here are approximate.
605 assign vsync
= (vcount
>= 300 && vcount
< 303);
607 assign char_blank
= (ir
[3:0] == 3) &&
608 (((chr_dcount
== 0 || chr_dcount
== 1) &&
609 shift_reg_out
[6:5] == 2'b11) ||
610 ((chr_dcount
== 8 || chr_dcount
== 9) &&
611 shift_reg_out
[6:5] != 2'b11));
613 always @ (posedge clk_i
)
615 char_data
<= char_blank ?
0 : masterdat_i
;
616 char_color_p
<= shift_reg_out
[7:6];
619 always @ (posedge clk2_i
)
621 out_reg
<= char_block ? char_data
: shift_reg_out
;
622 char_color
<= char_color_p
;
624 else if (out_reg_shift
)
626 out_reg
<= {out_reg
[6:0], 1'b0};
628 out_reg
<= {out_reg
[5:0], 2'b00};
630 always @ (ir
or out_reg
or char_color
or chactl
)
631 if (ir
[3:0] == 2 || ir
[3:0] == 3)
633 pf_antic_out
= {1'b1,
634 (out_reg
[7:6] & ~{2{chactl
[0]}}) ^
{2{chactl
[1]}}};
636 pf_antic_out
= {1'b1, out_reg
[7:6]};
637 else if (ir
[3:0] == 'hf
)
638 pf_antic_out
= {1'b1, out_reg
[7:6]};
639 else if (ir
[3:0] == 4 || ir
[3:0] == 5)
641 0: pf_antic_out
= 3'b000;
642 1: pf_antic_out
= 3'b100;
643 2: pf_antic_out
= 3'b101;
644 3: pf_antic_out
= char_color
[1] ?
3'b111 : 3'b110;
646 else if (ir
[3:0] == 6 || ir
[3:0] == 7)
648 pf_antic_out
= {1'b1, char_color
};
650 pf_antic_out
= 3'b000;
651 else if (ir
[3:0] == 8 || ir
[3:0] == 'ha || ir
[3:0] == 'hd ||
654 0: pf_antic_out
= 3'b000;
655 1: pf_antic_out
= 3'b100;
656 2: pf_antic_out
= 3'b101;
657 3: pf_antic_out
= 3'b110;
659 else if (ir
[3:0] == 9 || ir
[3:0] == 'hb || ir
[3:0] == 'hc
)
660 pf_antic_out
= out_reg
[7] ?
3'b100 : 3'b000;
662 pf_antic_out
= 3'b000;
664 always @ (posedge clk2_i
)
665 pf_antic_out_d
<= pf_antic_out
;
667 always @ (vsync
or vblank
or hblank
or dwin
or ir
or pf_antic_out
or
668 pf_antic_out_d
) begin
671 else if (hblank || vblank
)
672 if (ir
[3:0] == 2 || ir
[3:0] == 3 || ir
[3:0] == 'hf
)
677 antic_out
= (dma_block
&& ir
[4] && hscrol
[0]) ?
678 pf_antic_out_d
: pf_antic_out
;
683 always @ (posedge clk_i
)
684 if (hcount
>= 50 && hcount
<= 82 && (hcount
& 7) == 2)
686 else if (refresh_ack
)
689 assign chr_dcount
= dcount ^
{4{chactl
[2]}};
691 always @ (dl_load
or dlist_ctr
or load_mis
or load_ply
or
692 pmbase
or vcount
or dma_ply_num
or
693 load_pf
or memscan_ctr
or
694 load_char
or chbase
or shift_reg_out
or chr_dcount
or
700 adr_o
= dma_pm_1res ?
701 {pmbase
[5:1], 3'b011, vcount
[7:0]} :
702 {pmbase
[5:0], 3'b011, vcount
[7:1]};
704 adr_o
= dma_pm_1res ?
705 {pmbase
[5:1], 1'b1, dma_ply_num
, vcount
[7:0]} :
706 {pmbase
[5:0], 1'b1, dma_ply_num
, vcount
[7:1]};
711 2: adr_o
= {chbase
[6:1], shift_reg_out
[6:0], chr_dcount
[2:0]};
712 3: adr_o
= {chbase
[6:1], shift_reg_out
[6:0], chr_dcount
[2:0]};
713 4: adr_o
= {chbase
[6:1], shift_reg_out
[6:0], chr_dcount
[2:0]};
714 5: adr_o
= {chbase
[6:1], shift_reg_out
[6:0], chr_dcount
[3:1]};
715 6: adr_o
= {chbase
[6:0], shift_reg_out
[5:0], chr_dcount
[2:0]};
716 7: adr_o
= {chbase
[6:0], shift_reg_out
[5:0], chr_dcount
[3:1]};
718 else if (refresh_req
) begin
725 assign stb_o
= dl_load || load_mis || load_ply || load_pf || load_char ||
726 wsync || refresh_req
;
727 assign cyc_o
= stb_o
;
729 antic_shift_reg
u_shift_reg(.
clk_i(clk_i
),
730 .
shift(shift_reg_shift
),
733 .
out(shift_reg_out
));