OSDN Git Service

771537570044719455a9b26d65eba9a20807ce1b
[motonesfpga/motonesfpga.git] / de1_nes / ppu / vga_ppu.vhd
1 -------------------------------------------------------------\r
2 -------------------------------------------------------------\r
3 ------------------- PPU VGA Output Control ------------------\r
4 -------------------------------------------------------------\r
5 -------------------------------------------------------------\r
6 \r
7 library ieee;\r
8 use ieee.std_logic_1164.all;\r
9 use ieee.std_logic_unsigned.conv_integer;\r
10 use ieee.std_logic_arith.conv_std_logic_vector;\r
11 use ieee.std_logic_unsigned.all;\r
12 use work.motonesfpga_common.all;\r
13 \r
14 entity vga_ppu_render is \r
15     port (  \r
16     signal dbg_vga_clk                      : out std_logic;\r
17     signal dbg_nes_x                        : out std_logic_vector (8 downto 0);\r
18     signal dbg_vga_x                        : out std_logic_vector (9 downto 0);\r
19     signal dbg_nes_y                        : out std_logic_vector (8 downto 0);\r
20     signal dbg_vga_y                        : out std_logic_vector (9 downto 0);\r
21     signal dbg_disp_nt, dbg_disp_attr       : out std_logic_vector (7 downto 0);\r
22     signal dbg_disp_ptn_h, dbg_disp_ptn_l   : out std_logic_vector (15 downto 0);\r
23     signal dbg_plt_ce_rn_wn                 : out std_logic_vector (2 downto 0);\r
24     signal dbg_plt_addr                     : out std_logic_vector (4 downto 0);\r
25     signal dbg_plt_data                     : out std_logic_vector (7 downto 0);\r
26     signal dbg_p_oam_ce_rn_wn               : out std_logic_vector (2 downto 0);\r
27     signal dbg_p_oam_addr                   : out std_logic_vector (7 downto 0);\r
28     signal dbg_p_oam_data                   : out std_logic_vector (7 downto 0);\r
29     signal dbg_s_oam_ce_rn_wn               : out std_logic_vector (2 downto 0);\r
30     signal dbg_s_oam_addr                   : out std_logic_vector (4 downto 0);\r
31     signal dbg_s_oam_data                   : out std_logic_vector (7 downto 0);\r
32     signal dbg_emu_ppu_clk                  : out std_logic;\r
33 \r
34             vga_clk     : in std_logic;\r
35             mem_clk     : in std_logic;\r
36             rst_n       : in std_logic;\r
37 \r
38             --vram i/f\r
39             rd_n        : out std_logic;\r
40             wr_n        : out std_logic;\r
41             ale         : out std_logic;\r
42             vram_ad     : inout  std_logic_vector (7 downto 0);\r
43             vram_a      : out std_logic_vector (13 downto 8);\r
44 \r
45             --vga output\r
46             h_sync_n    : out std_logic;\r
47             v_sync_n    : out std_logic;\r
48             r           : out std_logic_vector (3 downto 0);\r
49             g           : out std_logic_vector (3 downto 0);\r
50             b           : out std_logic_vector (3 downto 0);\r
51 \r
52             --upper ppu i/f\r
53             ppu_ctrl        : in std_logic_vector (7 downto 0);\r
54             ppu_mask        : in std_logic_vector (7 downto 0);\r
55             read_status     : in std_logic;\r
56             ppu_status      : out std_logic_vector (7 downto 0);\r
57             ppu_scroll_x    : in std_logic_vector (7 downto 0);\r
58             ppu_scroll_y    : in std_logic_vector (7 downto 0);\r
59 \r
60             --ppu internal ram access\r
61             r_nw            : in std_logic;\r
62             oam_bus_ce_n    : in std_logic;\r
63             plt_bus_ce_n    : in std_logic;\r
64             oam_plt_addr    : in std_logic_vector (7 downto 0);\r
65             oam_plt_data    : inout std_logic_vector (7 downto 0);\r
66             v_bus_busy_n    : out std_logic\r
67     );\r
68 end vga_ppu_render;\r
69 \r
70 architecture rtl of vga_ppu_render is\r
71 \r
72 component counter_register\r
73     generic (\r
74         dsize       : integer := 8;\r
75         inc         : integer := 1\r
76     );\r
77     port (  clk         : in std_logic;\r
78             rst_n       : in std_logic;\r
79             ce_n        : in std_logic;\r
80             we_n        : in std_logic;\r
81             d           : in std_logic_vector(dsize - 1 downto 0);\r
82             q           : out std_logic_vector(dsize - 1 downto 0)\r
83     );\r
84 end component;\r
85 \r
86 component ppu_render\r
87     port (  \r
88     signal dbg_ppu_clk                      : out std_logic;\r
89     signal dbg_nes_x                        : out std_logic_vector (8 downto 0);\r
90     signal dbg_nes_y                        : out std_logic_vector (8 downto 0);\r
91     signal dbg_disp_nt, dbg_disp_attr       : out std_logic_vector (7 downto 0);\r
92     signal dbg_disp_ptn_h, dbg_disp_ptn_l   : out std_logic_vector (15 downto 0);\r
93     signal dbg_plt_ce_rn_wn                 : out std_logic_vector (2 downto 0);\r
94     signal dbg_plt_addr                     : out std_logic_vector (4 downto 0);\r
95     signal dbg_plt_data                     : out std_logic_vector (7 downto 0);\r
96     signal dbg_p_oam_ce_rn_wn               : out std_logic_vector (2 downto 0);\r
97     signal dbg_p_oam_addr                   : out std_logic_vector (7 downto 0);\r
98     signal dbg_p_oam_data                   : out std_logic_vector (7 downto 0);\r
99     signal dbg_s_oam_ce_rn_wn               : out std_logic_vector (2 downto 0);\r
100     signal dbg_s_oam_addr                   : out std_logic_vector (4 downto 0);\r
101     signal dbg_s_oam_data                   : out std_logic_vector (7 downto 0);\r
102     \r
103             ppu_clk     : in std_logic;\r
104             mem_clk     : in std_logic;\r
105             rst_n       : in std_logic;\r
106             rd_n        : out std_logic;\r
107             wr_n        : out std_logic;\r
108             ale         : out std_logic;\r
109             vram_ad     : inout std_logic_vector (7 downto 0);\r
110             vram_a      : out std_logic_vector (13 downto 8);\r
111             cur_x       : in std_logic_vector (8 downto 0);\r
112             cur_y       : in std_logic_vector (8 downto 0);\r
113             r           : out std_logic_vector (3 downto 0);\r
114             g           : out std_logic_vector (3 downto 0);\r
115             b           : out std_logic_vector (3 downto 0);\r
116             ppu_ctrl        : in std_logic_vector (7 downto 0);\r
117             ppu_mask        : in std_logic_vector (7 downto 0);\r
118             read_status     : in std_logic;\r
119             ppu_status      : out std_logic_vector (7 downto 0);\r
120             ppu_scroll_x    : in std_logic_vector (7 downto 0);\r
121             ppu_scroll_y    : in std_logic_vector (7 downto 0);\r
122             \r
123             r_nw            : in std_logic;\r
124             oam_bus_ce_n    : in std_logic;\r
125             plt_bus_ce_n    : in std_logic;\r
126             oam_plt_addr    : in std_logic_vector (7 downto 0);\r
127             oam_plt_data    : inout std_logic_vector (7 downto 0);\r
128             v_bus_busy_n    : out std_logic\r
129     );\r
130 end component;\r
131 \r
132 --------- screen constant -----------\r
133 constant VGA_W          : integer := 640;\r
134 constant VGA_H          : integer := 480;\r
135 constant VGA_W_MAX      : integer := 800;\r
136 constant VGA_H_MAX      : integer := 525;\r
137 constant H_SP           : integer := 95;\r
138 constant H_BP           : integer := 48;\r
139 constant H_FP           : integer := 15;\r
140 constant V_SP           : integer := 2;\r
141 constant V_BP           : integer := 33;\r
142 constant V_FP           : integer := 10;\r
143 \r
144 --------- signal declaration -----------\r
145 signal vga_x        : std_logic_vector (9 downto 0);\r
146 signal vga_y        : std_logic_vector (9 downto 0);\r
147 signal x_res_n      : std_logic;\r
148 signal y_res_n      : std_logic;\r
149 signal y_en_n       : std_logic;\r
150 signal cnt_clk      : std_logic;\r
151 \r
152 signal emu_ppu_clk      : std_logic;\r
153 signal emu_ppu_clk_n    : std_logic;\r
154 signal count5_res_n     : std_logic;\r
155 signal count5           : std_logic_vector(2 downto 0);\r
156 signal nes_x        : std_logic_vector (8 downto 0);\r
157 signal nes_y        : std_logic_vector (8 downto 0);\r
158 \r
159 ---DE1 base clock 50 MHz\r
160 ---motones sim project uses following clock.\r
161 --cpu clock = base clock / 24 = 2.08 MHz (480 ns / cycle)\r
162 --ppu clock = base clock / 8\r
163 --vga clock = base clock / 2\r
164 --sdram clock = 135 MHz\r
165 \r
166 begin\r
167     dbg_vga_x <= vga_x;\r
168     dbg_vga_y <= vga_y;\r
169     dbg_vga_clk <= vga_clk;\r
170     \r
171     cnt_clk <= not vga_clk;\r
172     \r
173     --vga position counter\r
174     x_inst : counter_register generic map (10, 1)\r
175             port map (cnt_clk , x_res_n, '0', '1', (others => '0'), vga_x);\r
176     y_inst : counter_register generic map (10, 1)\r
177             port map (cnt_clk , y_res_n, y_en_n, '1', (others => '0'), vga_y);\r
178     vga_out_p : process (rst_n, vga_clk)\r
179     begin\r
180         if (rst_n = '0') then\r
181             h_sync_n <= '0';\r
182             v_sync_n <= '0';\r
183             x_res_n <= '0';\r
184             y_res_n <= '0';\r
185         elsif (rising_edge(vga_clk)) then\r
186             --xmax = 799\r
187             if (vga_x = conv_std_logic_vector(VGA_W_MAX, 10)) then\r
188                 x_res_n <= '0';\r
189                 y_en_n <= '0';\r
190                 --ymax=524\r
191                 if (vga_y = conv_std_logic_vector(VGA_H_MAX, 10)) then\r
192                     y_res_n <= '0';\r
193                 else\r
194                     y_res_n <= '1';\r
195                 end if;\r
196             else\r
197                 x_res_n <= '1';\r
198                 y_en_n <= '1';\r
199                 y_res_n <= '1';\r
200             end if;\r
201 \r
202             --sync signal assert.\r
203             if (vga_x >= conv_std_logic_vector((VGA_W + H_FP) , 10) and \r
204                 vga_x < conv_std_logic_vector((VGA_W + H_FP + H_SP) , 10)) then\r
205                 h_sync_n <= '0';\r
206             else\r
207                 h_sync_n <= '1';\r
208             end if;\r
209 \r
210             if (vga_y >= conv_std_logic_vector((VGA_H + V_FP) , 10) and \r
211                 vga_y < conv_std_logic_vector((VGA_H + V_FP + V_SP) , 10)) then\r
212                 v_sync_n <= '0';\r
213             else\r
214                 v_sync_n <= '1';\r
215             end if;\r
216 \r
217         end if;\r
218     end process;\r
219 \r
220     --emulate ppu clock that is synchronized with vga clock\r
221     count5_inst : counter_register generic map (3, 1)\r
222             port map (cnt_clk, count5_res_n, '0', '1', (others => '0'), count5);\r
223     nes_x_inst : counter_register generic map (9, 1)\r
224             port map (emu_ppu_clk , x_res_n, '0', '1', (others => '0'), nes_x);\r
225     nes_y <= vga_y(9 downto 1);\r
226 \r
227     res_p : process (rst_n, vga_clk)\r
228     begin\r
229         if (rst_n = '0') then\r
230             count5_res_n <= '0';\r
231         elsif (rising_edge(vga_clk)) then\r
232             if (vga_x = conv_std_logic_vector(VGA_W_MAX, 10)) then\r
233                 count5_res_n <= '0';\r
234             elsif (count5 = "100") then\r
235                 count5_res_n <= '0';\r
236             else\r
237                 count5_res_n <= '1';\r
238             end if;\r
239         end if;\r
240     end process;\r
241 \r
242     emu_clk_p : process (rst_n, mem_clk)\r
243     begin\r
244         if (rst_n = '0') then\r
245             emu_ppu_clk <= '0';\r
246         elsif (rising_edge(mem_clk)) then\r
247             if (vga_x < conv_std_logic_vector(765, 10) ) then\r
248                 if (count5 = "001" or count5 = "011") then\r
249                     emu_ppu_clk <= '0';\r
250                 else\r
251                     emu_ppu_clk <= '1';\r
252                 end if;\r
253             else\r
254                 emu_ppu_clk <= not emu_ppu_clk;\r
255             end if;\r
256         end if;\r
257     end process;\r
258 \r
259     ---emulated ppu clock adjustment.\r
260     emu_ppu_clk_n <= not emu_ppu_clk;\r
261     ppu_render_inst : ppu_render\r
262         port map (\r
263         dbg_emu_ppu_clk                      ,\r
264         dbg_nes_x                        ,\r
265         dbg_nes_y                        ,\r
266         dbg_disp_nt, dbg_disp_attr       ,\r
267         dbg_disp_ptn_h, dbg_disp_ptn_l   ,\r
268         dbg_plt_ce_rn_wn                 ,\r
269         dbg_plt_addr                    ,\r
270         dbg_plt_data                    ,\r
271         dbg_p_oam_ce_rn_wn              ,\r
272         dbg_p_oam_addr                  ,\r
273         dbg_p_oam_data                  ,\r
274         dbg_s_oam_ce_rn_wn              ,\r
275         dbg_s_oam_addr                  ,\r
276         dbg_s_oam_data                  ,\r
277         \r
278                 emu_ppu_clk_n ,\r
279                 mem_clk     ,\r
280                 rst_n       ,\r
281                 rd_n        ,\r
282                 wr_n        ,\r
283                 ale         ,\r
284                 vram_ad     ,\r
285                 vram_a      ,\r
286                 nes_x       ,\r
287                 nes_y       ,\r
288                 r           ,\r
289                 g           ,\r
290                 b           ,\r
291                 ppu_ctrl        ,\r
292                 ppu_mask        ,\r
293                 read_status     ,\r
294                 ppu_status      ,\r
295                 ppu_scroll_x    ,\r
296                 ppu_scroll_y    ,\r
297                 r_nw            ,\r
298                 oam_bus_ce_n    ,\r
299                 plt_bus_ce_n    ,\r
300                 oam_plt_addr    ,\r
301                 oam_plt_data    ,\r
302                 v_bus_busy_n    \r
303         );\r
304 \r
305 end rtl;\r
306 \r
307 \r
308 \r
309 ---------------------------------------------------------------\r
310 ---------------------------------------------------------------\r
311 ------------------------ PPU VGA Renderer ---------------------\r
312 ---------------------------------------------------------------\r
313 ---------------------------------------------------------------\r
314 \r
315 library ieee;\r
316 use ieee.std_logic_1164.all;\r
317 use ieee.std_logic_arith.conv_std_logic_vector;\r
318 use ieee.std_logic_unsigned.all;\r
319 use work.motonesfpga_common.all;\r
320 \r
321 entity ppu_render is \r
322     port (  \r
323     signal dbg_ppu_clk                      : out std_logic;\r
324     signal dbg_nes_x                        : out std_logic_vector (8 downto 0);\r
325     signal dbg_nes_y                        : out std_logic_vector (8 downto 0);\r
326     signal dbg_disp_nt, dbg_disp_attr       : out std_logic_vector (7 downto 0);\r
327     signal dbg_disp_ptn_h, dbg_disp_ptn_l   : out std_logic_vector (15 downto 0);\r
328     signal dbg_plt_ce_rn_wn                 : out std_logic_vector (2 downto 0);\r
329     signal dbg_plt_addr                     : out std_logic_vector (4 downto 0);\r
330     signal dbg_plt_data                     : out std_logic_vector (7 downto 0);\r
331     signal dbg_p_oam_ce_rn_wn               : out std_logic_vector (2 downto 0);\r
332     signal dbg_p_oam_addr                   : out std_logic_vector (7 downto 0);\r
333     signal dbg_p_oam_data                   : out std_logic_vector (7 downto 0);\r
334     signal dbg_s_oam_ce_rn_wn               : out std_logic_vector (2 downto 0);\r
335     signal dbg_s_oam_addr                   : out std_logic_vector (4 downto 0);\r
336     signal dbg_s_oam_data                   : out std_logic_vector (7 downto 0);\r
337     \r
338             ppu_clk     : in std_logic;\r
339             mem_clk     : in std_logic;\r
340             rst_n       : in std_logic;\r
341 \r
342             rd_n        : out std_logic;\r
343             wr_n        : out std_logic;\r
344             ale         : out std_logic;\r
345             vram_ad     : inout std_logic_vector (7 downto 0);\r
346             vram_a      : out std_logic_vector (13 downto 8);\r
347 \r
348             --current drawing position 340 x 261\r
349             cur_x       : in std_logic_vector (8 downto 0);\r
350             cur_y       : in std_logic_vector (8 downto 0);\r
351             r           : out std_logic_vector (3 downto 0);\r
352             g           : out std_logic_vector (3 downto 0);\r
353             b           : out std_logic_vector (3 downto 0);\r
354 \r
355             ppu_ctrl        : in std_logic_vector (7 downto 0);\r
356             ppu_mask        : in std_logic_vector (7 downto 0);\r
357             read_status     : in std_logic;\r
358             ppu_status      : out std_logic_vector (7 downto 0);\r
359             ppu_scroll_x    : in std_logic_vector (7 downto 0);\r
360             ppu_scroll_y    : in std_logic_vector (7 downto 0);\r
361 \r
362             r_nw            : in std_logic;\r
363             oam_bus_ce_n    : in std_logic;\r
364             plt_bus_ce_n    : in std_logic;\r
365             oam_plt_addr    : in std_logic_vector (7 downto 0);\r
366             oam_plt_data    : inout std_logic_vector (7 downto 0);\r
367             v_bus_busy_n    : out std_logic\r
368     );\r
369 end ppu_render;\r
370 \r
371 architecture rtl of ppu_render is\r
372 \r
373 component counter_register\r
374     generic (\r
375         dsize       : integer := 8;\r
376         inc         : integer := 1\r
377     );\r
378     port (  clk         : in std_logic;\r
379             rst_n       : in std_logic;\r
380             ce_n        : in std_logic;\r
381             we_n        : in std_logic;\r
382             d           : in std_logic_vector(dsize - 1 downto 0);\r
383             q           : out std_logic_vector(dsize - 1 downto 0)\r
384     );\r
385 end component;\r
386 \r
387 component shift_register\r
388     generic (\r
389         dsize : integer := 8;\r
390         shift : integer := 1\r
391     );\r
392     port (  clk         : in std_logic;\r
393             rst_n       : in std_logic;\r
394             ce_n        : in std_logic;\r
395             we_n        : in std_logic;\r
396             d           : in std_logic_vector(dsize - 1 downto 0);\r
397             q           : out std_logic_vector(dsize - 1 downto 0)\r
398     );\r
399 end component;\r
400 \r
401 component d_flip_flop\r
402     generic (\r
403             dsize : integer := 8\r
404             );\r
405     port (  \r
406             clk     : in std_logic;\r
407             res_n   : in std_logic;\r
408             set_n   : in std_logic;\r
409             we_n    : in std_logic;\r
410             d       : in std_logic_vector (dsize - 1 downto 0);\r
411             q       : out std_logic_vector (dsize - 1 downto 0)\r
412         );\r
413 end component;\r
414 \r
415 component tri_state_buffer\r
416     generic (\r
417             dsize : integer := 8\r
418             );\r
419     port (  \r
420             oe_n    : in std_logic;\r
421             d       : in std_logic_vector (dsize - 1 downto 0);\r
422             q       : out std_logic_vector (dsize - 1 downto 0)\r
423         );\r
424 end component;\r
425 \r
426 component ram\r
427     generic (abus_size : integer := 16; dbus_size : integer := 8);\r
428     port (  \r
429             clk               : in std_logic;\r
430             ce_n, oe_n, we_n  : in std_logic;   --select pin active low.\r
431             addr              : in std_logic_vector (abus_size - 1 downto 0);\r
432             d_io              : inout std_logic_vector (dbus_size - 1 downto 0)\r
433     );\r
434 end component;\r
435 \r
436 component palette_ram\r
437     generic (abus_size : integer := 16; dbus_size : integer := 8);\r
438     port (  \r
439             clk               : in std_logic;\r
440             ce_n, oe_n, we_n  : in std_logic;   --select pin active low.\r
441             addr              : in std_logic_vector (abus_size - 1 downto 0);\r
442             d_io              : inout std_logic_vector (dbus_size - 1 downto 0)\r
443     );\r
444 end component;\r
445 \r
446 component ram_ctrl\r
447     port (  \r
448             clk              : in std_logic;\r
449             ce_n, oe_n, we_n : in std_logic;\r
450             sync_ce_n        : out std_logic\r
451         );\r
452 end component;\r
453 \r
454 --nes screen size is emulated to align with the vga timing...\r
455 constant X_SIZE       : integer := 9;\r
456 constant dsize        : integer := 8;\r
457 constant asize        : integer := 14;\r
458 constant HSCAN_MAX    : integer := 341;\r
459 constant VSCAN_MAX    : integer := 262;\r
460 constant HSCAN        : integer := 257;\r
461 constant VSCAN        : integer := 240;\r
462 constant HSCAN_NEXT_START    : integer := 320;\r
463 constant HSCAN_NEXT_EXTRA    : integer := 336;\r
464 \r
465 \r
466 constant PPUBNA    : integer := 1;  --base name address\r
467 constant PPUVAI    : integer := 2;  --vram address increment\r
468 constant PPUSPA    : integer := 3;  --sprite pattern table address\r
469 constant PPUBPA    : integer := 4;  --background pattern table address\r
470 constant PPUSPS    : integer := 5;  --sprite size\r
471 constant PPUMS     : integer := 6;  --ppu master/slave\r
472 constant PPUNEN    : integer := 7;  --nmi enable\r
473 \r
474 constant PPUGS     : integer := 0;  --grayscale\r
475 constant PPUSBL    : integer := 1;  --show 8 left most bg pixel\r
476 constant PPUSSL    : integer := 2;  --show 8 left most sprite pixel\r
477 constant PPUSBG    : integer := 3;  --show bg\r
478 constant PPUSSP    : integer := 4;  --show sprie\r
479 constant PPUIR     : integer := 5;  --intensify red\r
480 constant PPUIG     : integer := 6;  --intensify green\r
481 constant PPUIB     : integer := 7;  --intensify blue\r
482 \r
483 constant SPRHFL     : integer := 6;  --flip sprigte horizontally\r
484 constant SPRVFL     : integer := 7;  --flip sprigte vertically\r
485 \r
486 constant ST_SOF     : integer := 5;  --sprite overflow\r
487 constant ST_SP0     : integer := 6;  --sprite 0 hits\r
488 constant ST_VBL     : integer := 7;  --vblank\r
489 \r
490 subtype nes_color_data  is std_logic_vector (11 downto 0);\r
491 type nes_color_array    is array (0 to 63) of nes_color_data;\r
492 --ref: http://hlc6502.web.fc2.com/NesPal2.htm\r
493 constant nes_color_palette : nes_color_array := (\r
494         conv_std_logic_vector(16#777#, 12), \r
495         conv_std_logic_vector(16#20b#, 12), \r
496         conv_std_logic_vector(16#20b#, 12), \r
497         conv_std_logic_vector(16#61a#, 12), \r
498         conv_std_logic_vector(16#927#, 12), \r
499         conv_std_logic_vector(16#b13#, 12), \r
500         conv_std_logic_vector(16#a30#, 12), \r
501         conv_std_logic_vector(16#740#, 12), \r
502         conv_std_logic_vector(16#450#, 12), \r
503         conv_std_logic_vector(16#360#, 12), \r
504         conv_std_logic_vector(16#360#, 12), \r
505         conv_std_logic_vector(16#364#, 12), \r
506         conv_std_logic_vector(16#358#, 12), \r
507         conv_std_logic_vector(16#000#, 12), \r
508         conv_std_logic_vector(16#000#, 12), \r
509         conv_std_logic_vector(16#000#, 12),\r
510         conv_std_logic_vector(16#bbb#, 12), \r
511         conv_std_logic_vector(16#46f#, 12), \r
512         conv_std_logic_vector(16#44f#, 12), \r
513         conv_std_logic_vector(16#94f#, 12), \r
514         conv_std_logic_vector(16#d4c#, 12), \r
515         conv_std_logic_vector(16#d46#, 12), \r
516         conv_std_logic_vector(16#e50#, 12), \r
517         conv_std_logic_vector(16#c70#, 12), \r
518         conv_std_logic_vector(16#880#, 12), \r
519         conv_std_logic_vector(16#5a0#, 12), \r
520         conv_std_logic_vector(16#4a1#, 12), \r
521         conv_std_logic_vector(16#4a6#, 12), \r
522         conv_std_logic_vector(16#49c#, 12), \r
523         conv_std_logic_vector(16#000#, 12), \r
524         conv_std_logic_vector(16#000#, 12), \r
525         conv_std_logic_vector(16#000#, 12),\r
526         conv_std_logic_vector(16#fff#, 12), \r
527         conv_std_logic_vector(16#6af#, 12), \r
528         conv_std_logic_vector(16#58f#, 12), \r
529         conv_std_logic_vector(16#a7f#, 12), \r
530         conv_std_logic_vector(16#f6f#, 12), \r
531         conv_std_logic_vector(16#f6b#, 12), \r
532         conv_std_logic_vector(16#f73#, 12), \r
533         conv_std_logic_vector(16#fa0#, 12), \r
534         conv_std_logic_vector(16#ed2#, 12), \r
535         conv_std_logic_vector(16#9e0#, 12), \r
536         conv_std_logic_vector(16#7f4#, 12), \r
537         conv_std_logic_vector(16#7e9#, 12), \r
538         conv_std_logic_vector(16#6de#, 12), \r
539         conv_std_logic_vector(16#777#, 12), \r
540         conv_std_logic_vector(16#000#, 12), \r
541         conv_std_logic_vector(16#000#, 12),\r
542         conv_std_logic_vector(16#fff#, 12), \r
543         conv_std_logic_vector(16#9df#, 12), \r
544         conv_std_logic_vector(16#abf#, 12), \r
545         conv_std_logic_vector(16#cbf#, 12), \r
546         conv_std_logic_vector(16#ebf#, 12), \r
547         conv_std_logic_vector(16#fbe#, 12), \r
548         conv_std_logic_vector(16#fcb#, 12), \r
549         conv_std_logic_vector(16#fda#, 12), \r
550         conv_std_logic_vector(16#ff9#, 12), \r
551         conv_std_logic_vector(16#cf8#, 12), \r
552         conv_std_logic_vector(16#afa#, 12), \r
553         conv_std_logic_vector(16#afc#, 12), \r
554         conv_std_logic_vector(16#aff#, 12), \r
555         conv_std_logic_vector(16#aaa#, 12), \r
556         conv_std_logic_vector(16#000#, 12), \r
557         conv_std_logic_vector(16#000#, 12)\r
558         );\r
559 \r
560 signal ppu_clk_n        : std_logic;\r
561 \r
562 --timing adjust\r
563 signal bg_io_cnt        : std_logic_vector(0 downto 0);\r
564 signal spr_io_cnt       : std_logic_vector(0 downto 0);\r
565 \r
566 --vram i/o\r
567 signal io_oe_n          : std_logic;\r
568 signal ah_oe_n          : std_logic;\r
569 \r
570 signal cnt_x_res_n   : std_logic;\r
571 signal bg_cnt_res_n  : std_logic;\r
572 \r
573 --bg prefetch position (scroll + 16 cycle ahead of current pos)\r
574 --511 x 239 (or 255 x 479)\r
575 signal prf_x            : std_logic_vector(X_SIZE - 1 downto 0);\r
576 signal prf_y            : std_logic_vector(X_SIZE - 1 downto 0);\r
577 \r
578 signal nt_we_n          : std_logic;\r
579 signal disp_nt          : std_logic_vector (dsize - 1 downto 0);\r
580 \r
581 signal attr_ce_n        : std_logic;\r
582 signal attr_we_n        : std_logic;\r
583 signal attr_val         : std_logic_vector (dsize - 1 downto 0);\r
584 signal disp_attr_we_n   : std_logic;\r
585 signal disp_attr        : std_logic_vector (dsize - 1 downto 0);\r
586 \r
587 signal ptn_l_we_n       : std_logic;\r
588 signal ptn_l_in         : std_logic_vector (dsize - 1 downto 0);\r
589 signal ptn_l_val        : std_logic_vector (dsize - 1 downto 0);\r
590 signal disp_ptn_l_in    : std_logic_vector (dsize * 2 - 1 downto 0);\r
591 signal disp_ptn_l       : std_logic_vector (dsize * 2 - 1 downto 0);\r
592 \r
593 signal ptn_h_we_n       : std_logic;\r
594 signal ptn_h_in         : std_logic_vector (dsize * 2 - 1 downto 0);\r
595 signal disp_ptn_h       : std_logic_vector (dsize * 2 - 1 downto 0);\r
596 \r
597 --signals for palette / oam access from cpu\r
598 signal r_n              : std_logic;\r
599 signal vram_addr        : std_logic_vector (asize - 1 downto 0);\r
600 \r
601 --palette\r
602 signal plt_ram_ce_n_in  : std_logic;\r
603 signal plt_ram_ce_n     : std_logic;\r
604 signal plt_r_n          : std_logic;\r
605 signal plt_w_n          : std_logic;\r
606 signal plt_addr         : std_logic_vector (4 downto 0);\r
607 signal plt_data         : std_logic_vector (dsize - 1 downto 0);\r
608 \r
609 --primari / secondary oam\r
610 signal p_oam_ram_ce_n_in    : std_logic;\r
611 signal p_oam_ram_ce_n       : std_logic;\r
612 signal p_oam_r_n            : std_logic;\r
613 signal p_oam_w_n            : std_logic;\r
614 signal p_oam_addr           : std_logic_vector (dsize - 1 downto 0);\r
615 signal p_oam_data           : std_logic_vector (dsize - 1 downto 0);\r
616 \r
617 signal s_oam_ram_ce_n_in    : std_logic;\r
618 signal s_oam_ram_ce_n       : std_logic;\r
619 signal s_oam_r_n            : std_logic;\r
620 signal s_oam_w_n            : std_logic;\r
621 signal s_oam_addr_cpy_ce_n  : std_logic;\r
622 signal s_oam_addr_cpy_n     : std_logic;\r
623 signal s_oam_addr           : std_logic_vector (4 downto 0);\r
624 signal s_oam_addr_cpy       : std_logic_vector (4 downto 0);\r
625 signal s_oam_data           : std_logic_vector (dsize - 1 downto 0);\r
626 \r
627 signal p_oam_cnt_res_n  : std_logic;\r
628 signal p_oam_cnt_ce_n   : std_logic;\r
629 signal p_oam_cnt_wrap_n : std_logic;\r
630 signal p_oam_cnt        : std_logic_vector (dsize - 1 downto 0);\r
631 signal p_oam_addr_in    : std_logic_vector (dsize - 1 downto 0);\r
632 signal oam_ev_status    : std_logic_vector (2 downto 0);\r
633 \r
634 signal s_oam_cnt_ce_n   : std_logic;\r
635 signal s_oam_cnt        : std_logic_vector (4 downto 0);\r
636 \r
637 --oam evaluation status\r
638 constant EV_STAT_COMP       : std_logic_vector (2 downto 0) := "000";\r
639 constant EV_STAT_CP1        : std_logic_vector (2 downto 0) := "001";\r
640 constant EV_STAT_CP2        : std_logic_vector (2 downto 0) := "010";\r
641 constant EV_STAT_CP3        : std_logic_vector (2 downto 0) := "011";\r
642 constant EV_STAT_PRE_COMP   : std_logic_vector (2 downto 0) := "100";\r
643 \r
644 ----------sprite registers.\r
645 type oam_pin_array    is array (0 to 7) of std_logic;\r
646 type oam_reg_array    is array (0 to 7) of std_logic_vector (dsize - 1 downto 0);\r
647 \r
648 signal spr_x_we_n       : oam_pin_array;\r
649 signal spr_x_ce_n       : oam_pin_array;\r
650 signal spr_attr_we_n    : oam_pin_array;\r
651 signal spr_ptn_l_we_n   : oam_pin_array;\r
652 signal spr_ptn_h_we_n   : oam_pin_array;\r
653 signal spr_ptn_ce_n     : oam_pin_array;\r
654 \r
655 signal spr_x_cnt        : oam_reg_array;\r
656 signal spr_attr         : oam_reg_array;\r
657 signal spr_ptn_l        : oam_reg_array;\r
658 signal spr_ptn_h        : oam_reg_array;\r
659 \r
660 signal spr_y_we_n       : std_logic;\r
661 signal spr_tile_we_n    : std_logic;\r
662 signal spr_y_tmp        : std_logic_vector (dsize - 1 downto 0);\r
663 signal spr_tile_tmp     : std_logic_vector (dsize - 1 downto 0);\r
664 signal spr_ptn_in       : std_logic_vector (dsize - 1 downto 0);\r
665 \r
666 \r
667 begin\r
668     dbg_ppu_clk <= ppu_clk;\r
669     dbg_nes_x <= cur_x;\r
670     dbg_nes_y <= cur_y;\r
671     dbg_disp_nt <= disp_nt;\r
672     dbg_disp_attr <= disp_attr;\r
673     dbg_disp_ptn_h <= disp_ptn_h;\r
674     dbg_disp_ptn_l <= disp_ptn_l;\r
675     dbg_plt_addr <= plt_addr;\r
676     dbg_plt_data <= plt_data;\r
677     dbg_plt_ce_rn_wn               <= plt_ram_ce_n & plt_r_n & plt_w_n;\r
678     dbg_p_oam_ce_rn_wn               <= p_oam_ram_ce_n & p_oam_r_n & p_oam_w_n;\r
679     dbg_p_oam_addr                   <= p_oam_addr;\r
680     dbg_p_oam_data                   <= p_oam_data;\r
681     dbg_s_oam_ce_rn_wn               <= s_oam_ram_ce_n & s_oam_r_n & s_oam_w_n;\r
682     dbg_s_oam_addr                   <= s_oam_addr;\r
683     dbg_s_oam_data                   <= p_oam_data;\r
684 \r
685 \r
686     ppu_clk_n <= not ppu_clk;\r
687 \r
688     ale <= bg_io_cnt(0) when ppu_mask(PPUSBG) = '1' and\r
689                 (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
690                 cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
691                 (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or\r
692                 cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
693            spr_io_cnt(0) when ppu_mask(PPUSSP) = '1' and\r
694                 (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
695                 cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
696                 (cur_x > conv_std_logic_vector(256, X_SIZE) and \r
697                 cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
698            'Z';\r
699 \r
700     rd_n <= bg_io_cnt(0) when ppu_mask(PPUSBG) = '1' and\r
701                 (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
702                 cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
703                 (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or\r
704                 cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
705            spr_io_cnt(0) when ppu_mask(PPUSSP) = '1' and\r
706                 (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
707                 cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
708                 (cur_x > conv_std_logic_vector(256, X_SIZE) and \r
709                 cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
710             'Z';\r
711     wr_n <= '1' when (ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and\r
712                 (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
713                 cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else\r
714             'Z';\r
715     io_oe_n <= not bg_io_cnt(0) when ppu_mask(PPUSBG) = '1' and\r
716                 (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
717                 cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
718                 (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or\r
719                 cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
720            not spr_io_cnt(0) when ppu_mask(PPUSSP) = '1' and\r
721                 (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
722                 cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
723                 (cur_x > conv_std_logic_vector(256, X_SIZE) and \r
724                 cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
725                '1';\r
726     ah_oe_n <= '0' when (ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and\r
727                 (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
728                 cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else\r
729               '1';\r
730     v_bus_busy_n <= ah_oe_n;\r
731 \r
732     bg_io_cnt_inst : counter_register generic map (1, 1)\r
733             port map (ppu_clk, bg_cnt_res_n, '0', '1', (others => '0'), bg_io_cnt);\r
734     spr_io_cnt_inst : counter_register generic map (1, 1)\r
735             port map (ppu_clk, cnt_x_res_n, '0', '1', (others => '0'), spr_io_cnt);\r
736 \r
737     ---bg prefetch x pos is 16 + scroll cycle ahead of current pos.\r
738     prf_x <= cur_x + ppu_scroll_x + "000010000" \r
739                     when cur_x < conv_std_logic_vector(HSCAN, X_SIZE) else\r
740              cur_x + ppu_scroll_x + "010111011"; -- +16 -341\r
741 \r
742     prf_y <= cur_y + ppu_scroll_y\r
743                     when cur_x < conv_std_logic_vector(HSCAN, X_SIZE) and\r
744                          cur_y + ppu_scroll_y <\r
745                             conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE) else\r
746              cur_y + ppu_scroll_y + "000000001" \r
747                     when cur_y + ppu_scroll_y <\r
748                             conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE) else\r
749              "000000000"; \r
750 \r
751     nt_inst : d_flip_flop generic map(dsize)\r
752             port map (ppu_clk_n, rst_n, '1', nt_we_n, vram_ad, disp_nt);\r
753 \r
754     at_inst : d_flip_flop generic map(dsize)\r
755             port map (ppu_clk_n, rst_n, '1', attr_we_n, vram_ad, attr_val);\r
756 \r
757     disp_at_inst : shift_register generic map(dsize, 2)\r
758             port map (ppu_clk_n, rst_n, attr_ce_n, disp_attr_we_n, attr_val, disp_attr);\r
759 \r
760     --chr rom data's bit is stored in opposite direction.\r
761     --reverse bit when loading...\r
762     ptn_l_in <= (vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) & \r
763                  vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7));\r
764     ptn_h_in <= (vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) & \r
765                  vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7)) & \r
766                 disp_ptn_h (dsize downto 1);\r
767 \r
768     ptn_l_inst : d_flip_flop generic map(dsize)\r
769             port map (ppu_clk_n, rst_n, '1', ptn_l_we_n, ptn_l_in, ptn_l_val);\r
770 \r
771     disp_ptn_l_in <= ptn_l_val & disp_ptn_l (dsize downto 1);\r
772     disp_ptn_l_inst : shift_register generic map(dsize * 2, 1)\r
773             port map (ppu_clk_n, rst_n, '0', ptn_h_we_n, disp_ptn_l_in, disp_ptn_l);\r
774 \r
775     ptn_h_inst : shift_register generic map(dsize * 2, 1)\r
776             port map (ppu_clk_n, rst_n, '0', ptn_h_we_n, ptn_h_in, disp_ptn_h);\r
777 \r
778     --vram i/o\r
779     vram_io_buf : tri_state_buffer generic map (dsize)\r
780             port map (io_oe_n, vram_addr(dsize - 1 downto 0), vram_ad);\r
781 \r
782     vram_a_buf : tri_state_buffer generic map (6)\r
783             port map (ah_oe_n, vram_addr(asize - 1 downto dsize), vram_a);\r
784 \r
785     ---palette ram\r
786     r_n <= not r_nw;\r
787 \r
788     plt_ram_ce_n_in <= ppu_clk when plt_bus_ce_n = '0' and r_nw = '0' else \r
789                     '0' when plt_bus_ce_n = '0' and r_nw = '1' else\r
790                     '0' when ppu_mask(PPUSBG) = '1' and \r
791                             (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and \r
792                             (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) else\r
793                     '1';\r
794 \r
795     plt_addr <= oam_plt_addr(4 downto 0) when plt_bus_ce_n = '0' else\r
796                 "1" & spr_attr(0)(1 downto 0) & spr_ptn_h(0)(0) & spr_ptn_l(0)(0)\r
797                     when ppu_mask(PPUSSP) = '1' and\r
798                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
799                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
800                         spr_x_cnt(0) = "00000000" and \r
801                         (spr_ptn_h(0)(0) or spr_ptn_l(0)(0)) = '1' else\r
802                 "1" & spr_attr(1)(1 downto 0) & spr_ptn_h(1)(0) & spr_ptn_l(1)(0)\r
803                     when ppu_mask(PPUSSP) = '1' and\r
804                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
805                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
806                         spr_x_cnt(1) = "00000000" and \r
807                         (spr_ptn_h(1)(0) or spr_ptn_l(1)(0)) = '1' else\r
808                 "1" & spr_attr(2)(1 downto 0) & spr_ptn_h(2)(0) & spr_ptn_l(2)(0)\r
809                     when ppu_mask(PPUSSP) = '1' and \r
810                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
811                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
812                         spr_x_cnt(2) = "00000000" and\r
813                         (spr_ptn_h(2)(0) or spr_ptn_l(2)(0)) = '1' else\r
814                 "1" & spr_attr(3)(1 downto 0) & spr_ptn_h(3)(0) & spr_ptn_l(3)(0)\r
815                     when ppu_mask(PPUSSP) = '1' and\r
816                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
817                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
818                         spr_x_cnt(3) = "00000000" and\r
819                         (spr_ptn_h(3)(0) or spr_ptn_l(3)(0)) = '1' else\r
820                 "1" & spr_attr(4)(1 downto 0) & spr_ptn_h(4)(0) & spr_ptn_l(4)(0)\r
821                     when ppu_mask(PPUSSP) = '1' and\r
822                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
823                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
824                         spr_x_cnt(4) = "00000000" and\r
825                         (spr_ptn_h(4)(0) or spr_ptn_l(4)(0)) = '1' else\r
826                 "1" & spr_attr(5)(1 downto 0) & spr_ptn_h(5)(0) & spr_ptn_l(5)(0)\r
827                     when ppu_mask(PPUSSP) = '1' and\r
828                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
829                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
830                         spr_x_cnt(5) = "00000000" and\r
831                         (spr_ptn_h(5)(0) or spr_ptn_l(5)(0)) = '1' else\r
832                 "1" & spr_attr(6)(1 downto 0) & spr_ptn_h(6)(0) & spr_ptn_l(6)(0)\r
833                     when ppu_mask(PPUSSP) = '1' and\r
834                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
835                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
836                         spr_x_cnt(6) = "00000000" and\r
837                         (spr_ptn_h(6)(0) or spr_ptn_l(6)(0)) = '1' else\r
838                 "1" & spr_attr(7)(1 downto 0) & spr_ptn_h(7)(0) & spr_ptn_l(7)(0)\r
839                     when ppu_mask(PPUSSP) = '1' and\r
840                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
841                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
842                         spr_x_cnt(7) = "00000000" and\r
843                         (spr_ptn_h(7)(0) or spr_ptn_l(7)(0)) = '1' else\r
844                 "0" & disp_attr(1 downto 0) & disp_ptn_h(0) & disp_ptn_l(0) \r
845                     when ppu_mask(PPUSBG) = '1' and cur_y(4) = '0' and\r
846                         ((disp_ptn_h(0) or disp_ptn_l(0)) = '1') and\r
847                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
848                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) else\r
849                 "0" & disp_attr(5 downto 4) & disp_ptn_h(0) & disp_ptn_l(0)\r
850                     when ppu_mask(PPUSBG) = '1' and cur_y(4) = '1' and\r
851                         ((disp_ptn_h(0) or disp_ptn_l(0)) = '1') and\r
852                         (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
853                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) else\r
854                 ---else: no output color >> universal bg color output.\r
855                 --0x3f00 is the universal bg palette.\r
856                 (others => '0');    \r
857 \r
858     plt_r_n <= not r_nw when plt_bus_ce_n = '0' else\r
859                 '0' when ppu_mask(PPUSBG) = '1' else\r
860                 '1';\r
861     plt_w_n <= r_nw when plt_bus_ce_n = '0' else\r
862                 '1';\r
863     plt_d_buf_w : tri_state_buffer generic map (dsize)\r
864             port map (plt_w_n, oam_plt_data, plt_data);\r
865     plt_d_buf_r : tri_state_buffer generic map (dsize)\r
866             port map (plt_r_n, plt_data, oam_plt_data);\r
867     plt_ram_ctl : ram_ctrl\r
868             port map (mem_clk, plt_ram_ce_n_in, plt_r_n, plt_w_n, plt_ram_ce_n);\r
869     palette_inst : palette_ram generic map (5, dsize)\r
870             port map (mem_clk, plt_ram_ce_n, plt_r_n, plt_w_n, plt_addr, plt_data);\r
871 \r
872     ---primary oam\r
873     p_oam_ram_ce_n_in <= ppu_clk when oam_bus_ce_n = '0' and r_nw = '0' else\r
874                     '0' when oam_bus_ce_n = '0' and r_nw = '1' else\r
875                     '0' when ppu_mask(PPUSSP) = '1' and\r
876                              cur_x > conv_std_logic_vector(64, X_SIZE) and\r
877                              cur_x <= conv_std_logic_vector(256, X_SIZE) and\r
878                              p_oam_cnt_wrap_n = '1' else\r
879                     '1';\r
880     p_oam_addr <= oam_plt_addr when oam_bus_ce_n = '0' else\r
881                 p_oam_addr_in when ppu_mask(PPUSSP) = '1' and \r
882                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
883                         cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
884                          cur_x > conv_std_logic_vector(64, X_SIZE) and \r
885                          cur_x <= conv_std_logic_vector(256, X_SIZE) else\r
886                 (others => 'Z');\r
887     p_oam_r_n <= not r_nw when oam_bus_ce_n = '0' else\r
888                 '0' when ppu_mask(PPUSSP) = '1' and \r
889                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
890                         cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
891                          cur_x > conv_std_logic_vector(64, X_SIZE) and \r
892                          cur_x <= conv_std_logic_vector(256, X_SIZE) else\r
893                 '1';\r
894     p_oam_w_n <= r_nw when oam_bus_ce_n = '0' else\r
895                 '1';\r
896     oam_d_buf_w : tri_state_buffer generic map (dsize)\r
897             port map (p_oam_w_n, oam_plt_data, p_oam_data);\r
898     oam_d_buf_r : tri_state_buffer generic map (dsize)\r
899             port map (p_oam_r_n, p_oam_data, oam_plt_data);\r
900 \r
901     p_oam_ram_ctl : ram_ctrl\r
902             port map (mem_clk, p_oam_ram_ce_n_in, p_oam_r_n, p_oam_w_n, p_oam_ram_ce_n);\r
903     primary_oam_inst : ram generic map (dsize, dsize)\r
904             port map (mem_clk, p_oam_ram_ce_n, p_oam_r_n, p_oam_w_n, p_oam_addr, p_oam_data);\r
905 \r
906     ---secondary oam\r
907     p_oam_cnt_inst : counter_register generic map (dsize, 4)\r
908             port map (ppu_clk_n, p_oam_cnt_res_n, p_oam_cnt_ce_n, '1', (others => '0'), p_oam_cnt);\r
909     s_oam_cnt_inst : counter_register generic map (5, 1)\r
910             port map (ppu_clk_n, p_oam_cnt_res_n, s_oam_cnt_ce_n, '1', (others => '0'), s_oam_cnt);\r
911     s_oam_addr_cpy_inst : counter_register generic map (5, 1)\r
912             port map (ppu_clk_n, p_oam_cnt_res_n, s_oam_addr_cpy_ce_n, \r
913                     '1', (others => '0'), s_oam_addr_cpy);\r
914 \r
915     s_oam_ram_ce_n_in <= ppu_clk when ppu_mask(PPUSSP) = '1' and cur_x(0) = '1' and\r
916                                 cur_x > "000000001" and\r
917                                 cur_x <= conv_std_logic_vector(64, X_SIZE) else\r
918                       ppu_clk when ppu_mask(PPUSSP) = '1' and cur_x(0) = '1' and\r
919                                 cur_x > conv_std_logic_vector(64, X_SIZE) and\r
920                                 cur_x <= conv_std_logic_vector(256, X_SIZE) and\r
921                                 p_oam_cnt_wrap_n = '1' else\r
922                       '0' when ppu_mask(PPUSSP) = '1' and\r
923                                 cur_x > conv_std_logic_vector(256, X_SIZE) and\r
924                                 cur_x <= conv_std_logic_vector(320, X_SIZE) and\r
925                                 s_oam_addr_cpy_n = '0' else\r
926                       '1';\r
927 \r
928     s_oam_ram_ctl : ram_ctrl\r
929             port map (mem_clk, s_oam_ram_ce_n_in, s_oam_r_n, s_oam_w_n, s_oam_ram_ce_n);\r
930     secondary_oam_inst : ram generic map (5, dsize)\r
931             port map (mem_clk, s_oam_ram_ce_n, s_oam_r_n, s_oam_w_n, s_oam_addr, s_oam_data);\r
932 \r
933     spr_y_inst : d_flip_flop generic map(dsize)\r
934             port map (ppu_clk_n, p_oam_cnt_res_n, '1', spr_y_we_n, s_oam_data, spr_y_tmp);\r
935     spr_tile_inst : d_flip_flop generic map(dsize)\r
936             port map (ppu_clk_n, p_oam_cnt_res_n, '1', spr_tile_we_n, s_oam_data, spr_tile_tmp);\r
937 \r
938 \r
939    --reverse bit when NOT SPRHFL is set (.nes file format bit endian).\r
940    spr_ptn_in <= vram_ad when spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRHFL) = '1' else\r
941                 (vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) & \r
942                  vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7));\r
943     --array instances...\r
944     spr_inst : for i in 0 to 7 generate\r
945         spr_x_inst : counter_register generic map(dsize, 16#ff#)\r
946                 port map (ppu_clk_n, rst_n, spr_x_ce_n(i), spr_x_we_n(i), s_oam_data, spr_x_cnt(i));\r
947 \r
948         spr_attr_inst : d_flip_flop generic map(dsize)\r
949                 port map (ppu_clk_n, rst_n, '1', spr_attr_we_n(i), s_oam_data, spr_attr(i));\r
950 \r
951         spr_ptn_l_inst : shift_register generic map(dsize, 1)\r
952                 port map (ppu_clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_l_we_n(i), spr_ptn_in, spr_ptn_l(i));\r
953 \r
954         spr_ptn_h_inst : shift_register generic map(dsize, 1)\r
955                 port map (ppu_clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_h_we_n(i), spr_ptn_in, spr_ptn_h(i));\r
956     end generate;\r
957 \r
958     pos_p : process (rst_n, ppu_clk)\r
959     begin\r
960         if (rst_n = '0') then\r
961             cnt_x_res_n <= '0';\r
962             bg_cnt_res_n <= '0';\r
963         elsif (ppu_clk'event and ppu_clk = '0') then\r
964             if (cur_x = conv_std_logic_vector(HSCAN_MAX - 1, X_SIZE)) then\r
965                 --x pos reset.\r
966                 cnt_x_res_n <= '0';\r
967             else\r
968                 cnt_x_res_n <= '1';\r
969             end if;\r
970 \r
971             if (ppu_scroll_x(0) = '0' and cur_x = conv_std_logic_vector(HSCAN, X_SIZE)) then\r
972                 bg_cnt_res_n <= '0';\r
973             elsif (ppu_scroll_x(0) = '1' and cur_x = conv_std_logic_vector(HSCAN - 1, X_SIZE)) then\r
974                 bg_cnt_res_n <= '0';\r
975             else\r
976                 bg_cnt_res_n <= '1';\r
977             end if;\r
978         end if; --if (rst_n = '0') then\r
979     end process;\r
980 \r
981     clk_p : process (rst_n, ppu_clk, read_status)\r
982 \r
983 procedure output_rgb is\r
984 variable pl_addr : integer;\r
985 variable pl_index : integer;\r
986 variable dot_output : boolean;\r
987 begin\r
988     dot_output := false;\r
989 \r
990     --first show sprite.\r
991     if (ppu_mask(PPUSSP) = '1') then\r
992         for i in 0 to 7 loop\r
993             if (spr_x_cnt(i) = "00000000") then\r
994                 if ((spr_ptn_h(i)(0) or spr_ptn_l(i)(0)) = '1') then\r
995                     dot_output := true;\r
996                     exit;\r
997                 end if;\r
998             end if;\r
999         end loop;\r
1000     end if;\r
1001 \r
1002     if (dot_output = true and ppu_mask(PPUSBG) = '1' and \r
1003             (disp_ptn_h(0) or disp_ptn_l(0)) = '1') then\r
1004         --raise sprite 0 hit.\r
1005         ppu_status(ST_SP0) <= '1';\r
1006     end if;\r
1007 \r
1008     --first color in the palette is transparent color.\r
1009     if (ppu_mask(PPUSBG) = '1' and dot_output = false and \r
1010             (disp_ptn_h(0) or disp_ptn_l(0)) = '1') then\r
1011         dot_output := true;\r
1012     end if;\r
1013 \r
1014     --if or if not bg/sprite is shown, output color anyway \r
1015     --sinse universal bg color is included..\r
1016     pl_index := conv_integer(plt_data(5 downto 0));\r
1017     b <= nes_color_palette(pl_index) (11 downto 8);\r
1018     g <= nes_color_palette(pl_index) (7 downto 4);\r
1019     r <= nes_color_palette(pl_index) (3 downto 0);\r
1020 end;\r
1021 procedure stop_rgb is\r
1022 begin\r
1023     b <= (others => '0');\r
1024     g <= (others => '0');\r
1025     r <= (others => '0');\r
1026 end;\r
1027 \r
1028     begin\r
1029         if (rst_n = '0') then\r
1030             nt_we_n <= '1';\r
1031             ppu_status <= (others => '0');\r
1032             s_oam_data <= (others => 'Z');\r
1033             stop_rgb;\r
1034         else\r
1035 \r
1036             if (ppu_clk'event and ppu_clk = '1') then\r
1037 \r
1038                 --fetch bg pattern and display.\r
1039                 if (ppu_mask(PPUSBG) = '1' and \r
1040                         (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or\r
1041                         cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) and\r
1042                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
1043                         cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE))) then\r
1044                     --visible area bg image\r
1045 \r
1046                     d_print("*");\r
1047                     d_print("cur_x: " & conv_hex16(conv_integer(cur_x)));\r
1048                     d_print("cur_y: " & conv_hex16(conv_integer(cur_y)));\r
1049 \r
1050                     ----fetch next tile byte.\r
1051                     if (prf_x (2 downto 0) = "001") then\r
1052                         --vram addr is incremented every 8 cycle.\r
1053                         --name table at 0x2000\r
1054                         vram_addr(9 downto 0) \r
1055                             <= prf_y(dsize - 1 downto 3) \r
1056                                 & prf_x(dsize - 1 downto 3);\r
1057                         vram_addr(asize - 1 downto 10) <= "10" & ppu_ctrl(PPUBNA downto 0) \r
1058                                                         + ("000" & prf_x(dsize));\r
1059                     ----fetch attr table byte.\r
1060                     elsif (prf_x (4 downto 0) = "00011") then\r
1061                         --attribute table is loaded every 32 cycle.\r
1062                         --attr table at 0x23c0\r
1063                         vram_addr(dsize - 1 downto 0) <= "11000000" +\r
1064                                 ("00" & prf_y(7 downto 5) & prf_x(7 downto 5));\r
1065                         vram_addr(asize - 1 downto dsize) <= "10" &\r
1066                                 ppu_ctrl(PPUBNA downto 0) & "11"\r
1067                                     + ("000" & prf_x(dsize) & "00");\r
1068                     ----fetch pattern table low byte.\r
1069                     elsif (prf_x (2 downto 0) = "101") then\r
1070                          --vram addr is incremented every 8 cycle.\r
1071                          vram_addr <= "0" & ppu_ctrl(PPUBPA) & \r
1072                                               disp_nt(dsize - 1 downto 0) \r
1073                                                     & "0"  & prf_y(2  downto 0);\r
1074                     ----fetch pattern table high byte.\r
1075                     elsif (prf_x (2 downto 0) = "111") then\r
1076                          --vram addr is incremented every 8 cycle.\r
1077                          vram_addr <= "0" & ppu_ctrl(PPUBPA) & \r
1078                                               disp_nt(dsize - 1 downto 0) \r
1079                                                     & "0"  & prf_y(2 downto 0) + "00000000001000";\r
1080                     end if;\r
1081 \r
1082                     ----fetch next tile byte.\r
1083                     if (prf_x (2 downto 0) = "010") then\r
1084                         nt_we_n <= '0';\r
1085                     else\r
1086                         nt_we_n <= '1';\r
1087                     end if;\r
1088 \r
1089                     ----fetch attr table byte.\r
1090                     if (prf_x (4 downto 0) = "00100") then\r
1091                         attr_we_n <= '0';\r
1092                     else\r
1093                         attr_we_n <= '1';\r
1094                     end if;\r
1095                     if (prf_x (4 downto 0) = "10000") then\r
1096                         disp_attr_we_n <= '0';\r
1097                     else\r
1098                         disp_attr_we_n <= '1';\r
1099                     end if;\r
1100                     ---attribute is shifted every 16 bit.\r
1101                     if (prf_x (3 downto 0) = "0000") then\r
1102                         attr_ce_n <= '0';\r
1103                     else\r
1104                         attr_ce_n <= '1';\r
1105                     end if;\r
1106 \r
1107                     ----fetch pattern table low byte.\r
1108                     if (prf_x (2 downto 0) = "110") then\r
1109                          ptn_l_we_n <= '0';\r
1110                     else\r
1111                          ptn_l_we_n <= '1';\r
1112                     end if;\r
1113 \r
1114                     ----fetch pattern table high byte.\r
1115                     if (prf_x (2 downto 0) = "000") then\r
1116                          ptn_h_we_n <= '0';\r
1117                     else\r
1118                          ptn_h_we_n <= '1';\r
1119                     end if;\r
1120 \r
1121                 else\r
1122                     nt_we_n <= '1';\r
1123                     attr_we_n <= '1';\r
1124                     disp_attr_we_n <= '1';\r
1125                     attr_ce_n <= '1';\r
1126                     ptn_l_we_n <= '1';\r
1127                     ptn_h_we_n <= '1';\r
1128                 end if;--if (ppu_mask(PPUSBG) = '1') and\r
1129 \r
1130                 --fetch sprite and display.\r
1131                 if (ppu_mask(PPUSSP) = '1' and\r
1132                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
1133                         cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE))) then\r
1134                     --secondary oam clear\r
1135                     if (cur_x /= "000000000" and cur_x <= conv_std_logic_vector(64, X_SIZE)) then\r
1136                         if (cur_x(0) = '0') then\r
1137                             --write secondary oam on even cycle\r
1138                             s_oam_r_n <= '1';\r
1139                             s_oam_w_n <= '0';\r
1140                             s_oam_addr <= cur_x(5 downto 1);\r
1141                             s_oam_data <= (others => '1');\r
1142                         end if;\r
1143                         p_oam_cnt_res_n <= '0';\r
1144                         p_oam_cnt_ce_n <= '1';\r
1145                         s_oam_cnt_ce_n <= '1';\r
1146                         p_oam_cnt_wrap_n <= '1';\r
1147                         oam_ev_status <= EV_STAT_COMP;\r
1148 \r
1149                     --sprite evaluation and secondary oam copy.\r
1150                     elsif (cur_x > conv_std_logic_vector(64, X_SIZE) and \r
1151                             cur_x <= conv_std_logic_vector(256, X_SIZE)) then\r
1152                         p_oam_cnt_res_n <= '1';\r
1153 \r
1154                         --TODO: sprite evaluation is simplified!!\r
1155                         --not complying the original NES spec at\r
1156                         --http://wiki.nesdev.com/w/index.php/PPU_sprite_evaluation\r
1157                         --e.g., when overflow happens, it just ignore subsequent entry.\r
1158                         --old secondary sprite entry.\r
1159                         if (p_oam_cnt = "00000000" and cur_x > conv_std_logic_vector(192, X_SIZE)) then\r
1160                             p_oam_cnt_wrap_n <= '0';\r
1161                         end if;\r
1162 \r
1163                         --odd cycle copy from primary oam\r
1164                         if (cur_x(0) = '1') then\r
1165                             if (oam_ev_status = EV_STAT_COMP) then\r
1166                                 p_oam_addr_in <= p_oam_cnt;\r
1167                                 p_oam_cnt_ce_n <= '1';\r
1168                                 s_oam_cnt_ce_n <= '1';\r
1169                             elsif (oam_ev_status = EV_STAT_CP1) then\r
1170                                 p_oam_addr_in <= p_oam_cnt + "00000001";\r
1171                                 s_oam_cnt_ce_n <= '1';\r
1172 \r
1173                             elsif (oam_ev_status = EV_STAT_CP2) then\r
1174                                 p_oam_addr_in <= p_oam_cnt + "00000010";\r
1175                                 s_oam_cnt_ce_n <= '1';\r
1176 \r
1177                             elsif (oam_ev_status = EV_STAT_CP3) then\r
1178                                 oam_ev_status <= EV_STAT_PRE_COMP;\r
1179                                 p_oam_addr_in <= p_oam_cnt + "00000011";\r
1180                                 s_oam_cnt_ce_n <= '1';\r
1181                             end if;\r
1182                         else\r
1183                         --even cycle copy to secondary oam (if y is in range.)\r
1184                             s_oam_r_n <= '1';\r
1185                             s_oam_w_n <= '0';\r
1186                             s_oam_addr <= s_oam_cnt;\r
1187                             s_oam_data <= p_oam_data;\r
1188 \r
1189                             if (oam_ev_status = EV_STAT_COMP) then\r
1190                                 --check y range.\r
1191                                 if (cur_y < "000000110" and p_oam_data <= cur_y + "000000001") or \r
1192                                     (cur_y >= "000000110" and p_oam_data <= cur_y + "000000001" and \r
1193                                              p_oam_data >= cur_y - "000000110") then\r
1194                                     oam_ev_status <= EV_STAT_CP1;\r
1195                                     s_oam_cnt_ce_n <= '0';\r
1196                                     --copy remaining oam entry.\r
1197                                     p_oam_cnt_ce_n <= '1';\r
1198                                 else\r
1199                                     --goto next entry\r
1200                                     p_oam_cnt_ce_n <= '0';\r
1201                                 end if;\r
1202                             elsif (oam_ev_status = EV_STAT_CP1) then\r
1203                                 s_oam_cnt_ce_n <= '0';\r
1204                                 oam_ev_status <= EV_STAT_CP2;\r
1205                             elsif (oam_ev_status = EV_STAT_CP2) then\r
1206                                 s_oam_cnt_ce_n <= '0';\r
1207                                 oam_ev_status <= EV_STAT_CP3;\r
1208                             elsif (oam_ev_status = EV_STAT_CP3) then\r
1209                                 s_oam_cnt_ce_n <= '0';\r
1210                             elsif (oam_ev_status = EV_STAT_PRE_COMP) then\r
1211                                 oam_ev_status <= EV_STAT_COMP;\r
1212                                 s_oam_cnt_ce_n <= '0';\r
1213                                 p_oam_cnt_ce_n <= '0';\r
1214                             end if;\r
1215                         end if;--if (cur_x(0) = '1') then\r
1216 \r
1217                         --prepare for next step\r
1218                         s_oam_addr_cpy_n <= '1';\r
1219                         spr_y_we_n <= '1';\r
1220                         spr_tile_we_n <= '1';\r
1221                         spr_x_we_n <= "11111111";\r
1222                         spr_attr_we_n <= "11111111";\r
1223                         spr_ptn_l_we_n <= "11111111";\r
1224                         spr_ptn_h_we_n <= "11111111";\r
1225 \r
1226                     --sprite pattern fetch\r
1227                     elsif (cur_x > conv_std_logic_vector(256, X_SIZE) and \r
1228                             cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) then\r
1229 \r
1230                         s_oam_addr_cpy_n <= '0';\r
1231                         s_oam_r_n <= '0';\r
1232                         s_oam_w_n <= '1';\r
1233                         s_oam_addr <= s_oam_addr_cpy;\r
1234 \r
1235                         ----fetch y-cordinate from secondary oam\r
1236                         if (cur_x (2 downto 0) = "001" ) then\r
1237                             s_oam_addr_cpy_ce_n <= '0';\r
1238                             spr_y_we_n <= '0';\r
1239                         else\r
1240                             spr_y_we_n <= '1';\r
1241                         end if;\r
1242 \r
1243                         ----fetch tile number\r
1244                         if (cur_x (2 downto 0) = "010" ) then\r
1245                             spr_tile_we_n <= '0';\r
1246                         else\r
1247                             spr_tile_we_n <= '1';\r
1248                         end if;\r
1249 \r
1250                         ----fetch attribute\r
1251                         if (cur_x (2 downto 0) = "011" ) then\r
1252                             spr_attr_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '0';\r
1253                         else\r
1254                             spr_attr_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '1';\r
1255                         end if;--if (cur_x (2 downto 0) = "010" ) then\r
1256 \r
1257                         ----fetch x-cordinate\r
1258                         if (cur_x (2 downto 0) = "100" ) then\r
1259                             s_oam_addr_cpy_ce_n <= '1';\r
1260                             spr_x_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '0';\r
1261                         else\r
1262                             spr_x_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '1';\r
1263                         end if;\r
1264 \r
1265                         ----fetch pattern table low byte.\r
1266                         if (cur_x (2 downto 0) = "101" ) then\r
1267                             if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL) = '0') then\r
1268                                 vram_addr <= "0" & ppu_ctrl(PPUSPA) & \r
1269                                             spr_tile_tmp(dsize - 1 downto 0) & "0" & \r
1270                                             (cur_y(2 downto 0) + "001" - spr_y_tmp(2 downto 0));\r
1271                             else\r
1272                                 --flip sprite vertically.\r
1273                                 vram_addr <= "0" & ppu_ctrl(PPUSPA) & \r
1274                                             spr_tile_tmp(dsize - 1 downto 0) & "0" & \r
1275                                             (spr_y_tmp(2 downto 0) - cur_y(2 downto 0) - "010");\r
1276                             end if;\r
1277                         end if;\r
1278 \r
1279                         if (cur_x (2 downto 0) = "110" ) then\r
1280                             spr_ptn_l_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '0';\r
1281                         else\r
1282                             spr_ptn_l_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '1';\r
1283                         end if;\r
1284 \r
1285                         ----fetch pattern table high byte.\r
1286                         if (cur_x (2 downto 0) = "111" ) then\r
1287                             if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL) = '0') then\r
1288                                 vram_addr <= "0" & ppu_ctrl(PPUSPA) & \r
1289                                             spr_tile_tmp(dsize - 1 downto 0) & "0" & \r
1290                                             (cur_y(2 downto 0) + "001" - spr_y_tmp(2 downto 0))\r
1291                                                 + "00000000001000";\r
1292                             else\r
1293                                 --flip sprite vertically.\r
1294                                 vram_addr <= "0" & ppu_ctrl(PPUSPA) & \r
1295                                             spr_tile_tmp(dsize - 1 downto 0) & "0"  & \r
1296                                             (spr_y_tmp(2 downto 0) - cur_y(2 downto 0) - "010")\r
1297                                                 + "00000000001000";\r
1298                             end if;\r
1299                         end if;\r
1300 \r
1301                         if (cur_x (2 downto 0) = "000") then\r
1302                             spr_ptn_h_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '0';\r
1303                             s_oam_addr_cpy_ce_n <= '0';\r
1304                         else\r
1305                             spr_ptn_h_we_n(conv_integer(s_oam_addr_cpy(4 downto 2) - "001")) <= '1';\r
1306                         end if;\r
1307 \r
1308                     elsif (cur_x > conv_std_logic_vector(320, X_SIZE)) then\r
1309                         --clear last write enable.\r
1310                         spr_ptn_h_we_n <= "11111111";\r
1311                     end if;--if (cur_x /= "000000000" and cur_x <= conv_std_logic_vector(64, X_SIZE))\r
1312 \r
1313                     --display sprite.\r
1314                     if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
1315                         (cur_y < conv_std_logic_vector(VSCAN, X_SIZE))) then\r
1316                         --start counter.\r
1317                         if (cur_x = "000000000") then\r
1318                             spr_x_ce_n <= "00000000";\r
1319                         end if;\r
1320 \r
1321                         for i in 0 to 7 loop\r
1322                             if (spr_x_cnt(i) = "00000000") then\r
1323                                 --active sprite, start shifting..\r
1324                                 spr_x_ce_n(i) <= '1';\r
1325                                 spr_ptn_ce_n(i) <= '0';\r
1326                             end if;\r
1327                         end loop;\r
1328                     else\r
1329                         spr_x_ce_n <= "11111111";\r
1330                         spr_ptn_ce_n <= "11111111";\r
1331                     end if; --if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) \r
1332                 end if; --if (ppu_mask(PPUSSP) = '1') then\r
1333 \r
1334                 --output visible area only.\r
1335                 if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
1336                     (cur_y < conv_std_logic_vector(VSCAN, X_SIZE))) then\r
1337                     --output image.\r
1338                     output_rgb;\r
1339                 else\r
1340                     stop_rgb;\r
1341                 end if;\r
1342 \r
1343                 --flag operation\r
1344                 if ((cur_x = conv_std_logic_vector(1, X_SIZE)) and\r
1345                     (cur_y = conv_std_logic_vector(VSCAN + 1, X_SIZE))) then\r
1346                     --vblank start\r
1347                     ppu_status(ST_VBL) <= '1';\r
1348                 elsif ((cur_x = conv_std_logic_vector(1, X_SIZE)) and\r
1349                     (cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE))) then\r
1350                     ppu_status(ST_SP0) <= '0';\r
1351                     --vblank end\r
1352                     ppu_status(ST_VBL) <= '0';\r
1353                     --TODO: sprite overflow is not inplemented!\r
1354                     ppu_status(ST_SOF) <= '0';\r
1355                 end if;\r
1356             end if; --if (clk'event and clk = '1') then\r
1357 \r
1358 --            if (read_status'event and read_status = '1') then\r
1359 --                --reading ppu status clears vblank bit.\r
1360 --                ppu_status(ST_VBL) <= '0';\r
1361 --            end if;\r
1362 \r
1363         end if;--if (rst_n = '0') then\r
1364     end process;\r
1365 \r
1366 end rtl;\r
1367 \r