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(ms_hcount
,
19 new_block
, dma_block
, dma_pf_width
, ir
,
20 shift_reg_shift
, load_pf
, load_out
);
22 input new_block
, dma_block
, dma_pf_width
, ir
;
23 output shift_reg_shift
, load_pf
, load_out
;
26 wire new_block
, dma_block
;
27 wire [1:0] dma_pf_width
;
30 reg load_pf
, load_out
;
32 reg [3:0] pf_byte_mod
;
42 'h8
: pf_byte_mod
= 15;
43 'h9
: pf_byte_mod
= 15;
50 default: pf_byte_mod
= 3;
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
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);
72 always @ (dma_block
or dma_pf_width
or ms_hcount
or pf_byte_mod
) begin
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);
86 module antic_shift_reg(clk_i
, shift
, load
, in
, out
);
100 reg [7:0] shift_reg
[0:47];
104 assign out
= shift_reg
[1];
106 always @ (posedge clk_i
) begin
108 for (i
= 0; i
< 47; i
= i
+ 1)
109 shift_reg
[i
+ 1] <= shift_reg
[i
];
113 shift_reg
[0] <= shift_reg
[47];
117 module antic(rst_i
, clk_i
,
119 slavedat_i
, masterdat_i
,
148 wire [7:0] slavedat_i
;
149 wire [7:0] masterdat_i
;
163 reg [1:0] dma_pf_width
;
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
;
183 reg [15:0] memscan_ctr
;
198 reg [1:0] pf_pixel_mod
;
212 wire [1:0] dma_ply_num
;
216 wire hblank
, vblank
, vsync
;
219 wire shift_reg_shift
;
220 wire [7:0] shift_reg_out
;
222 reg [1:0] char_color
;
224 assign ack_o
= stb_i
;
227 always @ (adr_i
or vcount
or nmist_dli
or nmist_vbi
)
232 dat_o
= {nmist_dli
, nmist_vbi
, 6'b0};
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];
248 always @ (posedge clk_i
)
249 if (stb_i
&& we_i
&& adr_i
== 'h1
)
250 chactl
<= slavedat_i
[2:0];
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
260 dlist_ctr
[9:0] <= dlist_ctr
[9:0] + 1;
262 dlist_ctr
[15:8] <= masterdat_i
;
263 dlist_ctr
[7:0] <= dlist_ctr_tmp
;
266 dlist_ctr_tmp
<= masterdat_i
;
270 always @ (posedge clk_i
)
271 if (stb_i
&& we_i
&& adr_i
== 'h4
)
272 hscrol
<= slavedat_i
[3:0];
275 always @ (posedge clk_i
)
276 if (stb_i
&& we_i
&& adr_i
== 'h5
)
277 vscrol
<= slavedat_i
[3:0];
280 always @ (posedge clk_i
)
281 if (stb_i
&& we_i
&& adr_i
== 'h7
)
282 pmbase
<= slavedat_i
[7:2];
285 always @ (posedge clk_i
)
286 if (stb_i
&& we_i
&& adr_i
== 'h9
)
287 chbase
<= slavedat_i
[7:1];
290 always @ (posedge clk_i
)
291 if (rst_i || hcount
== 206)
293 else if (stb_i
&& we_i
&& adr_i
== 'ha
)
297 always @ (posedge clk_i
)
301 end else if (stb_i
&& we_i
&& adr_i
== 'he
) begin
302 nmien_vbi
<= slavedat_i
[6];
303 nmien_dli
<= slavedat_i
[7];
307 always @ (posedge clk2_i
)
310 else if (hcount
== 227)
313 hcount
<= hcount
+ 1;
316 always @ (posedge clk2_i
)
319 else if (hcount
== 227)
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
)
336 end else if (nmireq_vbi
) begin
339 end else if (nmireq_dli
) begin
342 end else if (stb_i
&& we_i
&& adr_i
=='hf
) begin
347 assign nmi
= nmireq_dli | nmireq_vbi
;
349 always @ (posedge clk2_i
)
353 (dcount
== maxline
&& !wait_vblank
&& !vblank
&& dma_instr_en
)))
358 assign load_instr
= new_block
&& (hcount
== 2);
361 always @ (posedge clk2_i
)
364 else if (hcount
== 0)
366 dcount
<= 0; // TODO: vscroll
368 dcount
<= dcount
+ 1;
370 // Memory Scan Counter.
371 always @ (posedge clk_i
)
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
)
383 else if (vcount
== 0)
386 // Instruction decoder.
393 'h0
: maxline
= ir
[6:4];
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))
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
),
512 .
shift_reg_shift(shift_reg_shift
),
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
)
522 1: dwin
= (hcount
>= 64 && hcount
< 192);
523 2: dwin
= (hcount
>= 48 && hcount
< 208);
524 3: dwin
= (hcount
>= 44 && hcount
< 220);
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
)
538 if (char_block
) begin
539 out_reg
<= masterdat_i
;
540 char_color
<= shift_reg_out
[7:6];
542 out_reg
<= shift_reg_out
;
543 else if ((hcount
& pf_pixel_mod
) == (3 & pf_pixel_mod
))
545 out_reg
<= {out_reg
[6:0], 1'b0};
547 out_reg
<= {out_reg
[5:0], 2'b00};
549 always @ (vsync
or vblank
or hblank
or dwin
or ir
or out_reg
or
553 else if (hblank || vblank
)
554 if (ir
[3:0] == 2 || ir
[3:0] == 3 || ir
[3:0] == 'hf
)
559 if (ir
[3:0] == 2 || ir
[3:0] == 3)
562 (out_reg
[7:6] & ~{2{chactl
[0]}}) ^
{2{chactl
[1]}}};
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)
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;
574 else if (ir
[3:0] == 6 || ir
[3:0] == 7)
576 antic_out
= {1'b1, char_color
};
579 else if (ir
[3:0] == 8 || ir
[3:0] == 'ha || ir
[3:0] == 'hd ||
582 0: antic_out
= 3'b000;
583 1: antic_out
= 3'b100;
584 2: antic_out
= 3'b101;
585 3: antic_out
= 3'b110;
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;
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
602 adr_o
= dma_pm_1res ?
603 {pmbase
[5:1], 3'b011, vcount
[7:0]} :
604 {pmbase
[5:0], 3'b011, vcount
[7:1]};
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]};
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]};
621 adr_o
= 0; // TODO: load some pointer by default
624 assign stb_o
= dl_load || load_mis || load_ply || load_pf || load_char ||
626 assign cyc_o
= stb_o
;
628 antic_shift_reg
u_shift_reg(.
clk_i(clk_i
),
629 .
shift(shift_reg_shift
),
632 .
out(shift_reg_out
));