OSDN Git Service

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