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_shift_reg(clk_i
, shift
, load
, in
, out
);
32 reg [7:0] shift_reg
[0:47];
36 assign out
= shift_reg
[1];
38 always @ (posedge clk_i
) begin
40 for (i
= 0; i
< 47; i
= i
+ 1)
41 shift_reg
[i
+ 1] <= shift_reg
[i
];
45 shift_reg
[0] <= shift_reg
[47];
49 module antic(rst_i
, clk_i
,
51 slavedat_i
, masterdat_i
,
80 wire [7:0] slavedat_i
;
81 wire [7:0] masterdat_i
;
95 reg [1:0] dma_pf_width
;
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
;
115 reg [15:0] memscan_ctr
;
129 reg [1:0] pf_pixel_mod
;
130 reg [3:0] pf_byte_mod
;
144 wire [1:0] dma_ply_num
;
148 wire hblank
, vblank
, vsync
;
151 wire shift_reg_shift
;
152 wire [7:0] shift_reg_out
;
154 reg [1:0] char_color
;
156 assign ack_o
= stb_i
;
159 always @ (adr_i
or vcount
or nmist_dli
or nmist_vbi
)
164 dat_o
= {nmist_dli
, nmist_vbi
, 6'b0};
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];
180 always @ (posedge clk_i
)
181 if (stb_i
&& we_i
&& adr_i
== 'h1
)
182 chactl
<= slavedat_i
[2:0];
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
192 dlist_ctr
[9:0] <= dlist_ctr
[9:0] + 1;
194 dlist_ctr
[15:8] <= masterdat_i
;
195 dlist_ctr
[7:0] <= dlist_ctr_tmp
;
198 dlist_ctr_tmp
<= masterdat_i
;
202 always @ (posedge clk_i
)
203 if (stb_i
&& we_i
&& adr_i
== 'h4
)
204 hscrol
<= slavedat_i
[3:0];
207 always @ (posedge clk_i
)
208 if (stb_i
&& we_i
&& adr_i
== 'h5
)
209 vscrol
<= slavedat_i
[3:0];
212 always @ (posedge clk_i
)
213 if (stb_i
&& we_i
&& adr_i
== 'h7
)
214 pmbase
<= slavedat_i
[7:2];
217 always @ (posedge clk_i
)
218 if (stb_i
&& we_i
&& adr_i
== 'h9
)
219 chbase
<= slavedat_i
[7:1];
222 always @ (posedge clk_i
)
223 if (rst_i || hcount
== 206)
225 else if (stb_i
&& we_i
&& adr_i
== 'ha
)
229 always @ (posedge clk_i
)
233 end else if (stb_i
&& we_i
&& adr_i
== 'he
) begin
234 nmien_vbi
<= slavedat_i
[6];
235 nmien_dli
<= slavedat_i
[7];
239 always @ (posedge clk2_i
)
242 else if (hcount
== 227)
245 hcount
<= hcount
+ 1;
248 always @ (posedge clk2_i
)
251 else if (hcount
== 227)
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
)
268 end else if (nmireq_vbi
) begin
271 end else if (nmireq_dli
) begin
274 end else if (stb_i
&& we_i
&& adr_i
=='hf
) begin
279 assign nmi
= nmireq_dli | nmireq_vbi
;
281 always @ (posedge clk2_i
)
285 (dcount
== maxline
&& !wait_vblank
&& !vblank
&& dma_instr_en
)))
290 assign load_instr
= new_block
&& (hcount
== 2);
293 always @ (posedge clk2_i
)
296 else if (hcount
== 0)
298 dcount
<= 0; // TODO: vscroll
300 dcount
<= dcount
+ 1;
302 // Memory Scan Counter.
303 always @ (posedge clk_i
)
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
)
315 else if (vcount
== 0)
318 // Instruction decoder.
326 'h0
: maxline
= ir
[6:4];
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) &&
453 always @ (hcount
or dma_pf_width
or new_block
) begin
456 if (new_block
&& dma_block
)
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);
467 always @ (hcount
or dma_pf_width
or new_block
) begin
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);
481 always @ (hcount
or dma_pf_width
or dma_instr_en
or vblank
) begin
482 if (!dma_instr_en || vblank
)
487 1: dwin
= (hcount
>= 64 && hcount
< 192);
488 2: dwin
= (hcount
>= 48 && hcount
< 208);
489 3: dwin
= (hcount
>= 44 && hcount
< 220);
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
)
503 if (char_block
) begin
504 out_reg
<= masterdat_i
;
505 char_color
<= shift_reg_out
[7:6];
507 out_reg
<= shift_reg_out
;
508 else if ((hcount
& pf_pixel_mod
) == (3 & pf_pixel_mod
))
510 out_reg
<= {out_reg
[6:0], 1'b0};
512 out_reg
<= {out_reg
[5:0], 2'b00};
514 always @ (vsync
or vblank
or hblank
or dwin
or ir
or out_reg
or
518 else if (hblank || vblank
)
519 if (ir
[3:0] == 2 || ir
[3:0] == 3 || ir
[3:0] == 'hf
)
524 if (ir
[3:0] == 2 || ir
[3:0] == 3 || ir
[3:0] == 'hf
)
526 antic_out
= {1'b1, out_reg
[7:6]};
527 else if (ir
[3:0] == 4 || ir
[3:0] == 5)
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;
534 else if (ir
[3:0] == 6 || ir
[3:0] == 7)
536 antic_out
= {1'b1, char_color
};
539 else if (ir
[3:0] == 8 || ir
[3:0] == 'ha || ir
[3:0] == 'hd ||
542 0: antic_out
= 3'b000;
543 1: antic_out
= 3'b100;
544 2: antic_out
= 3'b101;
545 3: antic_out
= 3'b110;
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;
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
562 adr_o
= dma_pm_1res ?
563 {pmbase
[5:1], 3'b011, vcount
[7:0]} :
564 {pmbase
[5:0], 3'b011, vcount
[7:1]};
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]};
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]};
581 adr_o
= 0; // TODO: load some pointer by default
584 assign stb_o
= dl_load || load_mis || load_ply || load_pf || load_char ||
586 assign cyc_o
= stb_o
;
588 antic_shift_reg
u_shift_reg(.
clk_i(clk_i
),
589 .
shift(shift_reg_shift
),
592 .
out(shift_reg_out
));