OSDN Git Service

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