OSDN Git Service

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