------- render instance ----------------\r
\r
--vram i/o\r
-signal io_oe_n : std_logic;\r
+signal io_cnt_rst_n : std_logic;\r
+signal io_cnt : std_logic_vector(0 downto 0);\r
+signal al_oe_n : std_logic;\r
signal ah_oe_n : std_logic;\r
\r
--bg prefetch position (scroll + 16 cycle ahead of current pos)\r
\r
signal p_oam_cnt_res_n : std_logic;\r
signal p_oam_cnt_ce_n : std_logic;\r
-signal p_oam_cnt_wrap_n : std_logic;\r
signal p_oam_cnt : std_logic_vector (dsize - 1 downto 0);\r
signal p_oam_addr_in : std_logic_vector (dsize - 1 downto 0);\r
signal oam_ev_status : std_logic_vector (2 downto 0);\r
-----------------------------------------\r
---vram access signals\r
-----------------------------------------\r
+ io_cnt_rst_n <= '0' when nes_x = conv_std_logic_vector(VGA_W_MAX / 2, X_SIZE) else \r
+ '1';\r
+ io_cnt_inst : counter_register generic map (1, 1)\r
+ port map (emu_ppu_clk, io_cnt_rst_n, '0', '1', (others => '0'), io_cnt);\r
+\r
ale <= \r
- nes_x(0) when (\r
+ not io_cnt(0) when (\r
((ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and\r
(nes_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
nes_y = conv_std_logic_vector(VSCAN_NEXT_START, X_SIZE)))) else\r
'Z';\r
rd_n <= \r
- nes_x(0) when (\r
+ not io_cnt(0) when (\r
((ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and\r
(nes_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
nes_y = conv_std_logic_vector(VSCAN_NEXT_START, X_SIZE)))) else\r
'Z';\r
wr_n <= \r
- '0' when (\r
+ '1' when (\r
((ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and\r
(nes_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
nes_y = conv_std_logic_vector(VSCAN_NEXT_START, X_SIZE)))) else\r
'Z';\r
- io_oe_n <= \r
- not nes_x(0) when (\r
+ al_oe_n <= \r
+ io_cnt(0) when (\r
((ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and\r
(nes_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
nes_y = conv_std_logic_vector(VSCAN_NEXT_START, X_SIZE)))) else\r
'1';\r
v_bus_busy_n <= ah_oe_n;\r
\r
+ -----------------------------------------\r
+ --vram i/o\r
+ -----------------------------------------\r
+ vram_io_buf : tri_state_buffer generic map (dsize)\r
+ port map (al_oe_n, vram_addr(dsize - 1 downto 0), vram_ad);\r
+\r
+ vram_a_buf : tri_state_buffer generic map (6)\r
+ port map (ah_oe_n, vram_addr(asize - 1 downto dsize), vram_a);\r
\r
-----------------------------------------\r
---primary oam implementation...\r
end generate;\r
\r
-----------------------------------------\r
- --vram i/o\r
- -----------------------------------------\r
- vram_io_buf : tri_state_buffer generic map (dsize)\r
- port map (io_oe_n, vram_addr(dsize - 1 downto 0), vram_ad);\r
-\r
- vram_a_buf : tri_state_buffer generic map (6)\r
- port map (ah_oe_n, vram_addr(asize - 1 downto dsize), vram_a);\r
-\r
- -----------------------------------------\r
---palette ram\r
-----------------------------------------\r
r_n <= not r_nw;\r
p_oam_cnt_res_n <= '1';\r
p_oam_cnt_ce_n <= '1';\r
s_oam_cnt_ce_n <= '1';\r
- p_oam_cnt_wrap_n <= '1';\r
oam_ev_status <= EV_STAT_COMP;\r
p_oam_addr_in <= (others => 'Z');\r
\r
p_oam_cnt_res_n <= '0';\r
p_oam_cnt_ce_n <= '1';\r
s_oam_cnt_ce_n <= '1';\r
- p_oam_cnt_wrap_n <= '1';\r
oam_ev_status <= EV_STAT_COMP;\r
\r
--sprite evaluation and secondary oam copy.\r
nes_x <= conv_std_logic_vector(HSCAN, X_SIZE)) then\r
p_oam_cnt_res_n <= '1';\r
\r
- --TODO: sprite evaluation is simplified!!\r
- --not complying the original NES spec at\r
- --http://wiki.nesdev.com/w/index.php/PPU_sprite_evaluation\r
- --e.g., when overflow happens, it just ignore subsequent entry.\r
- if (p_oam_cnt = "00000000" and nes_x > conv_std_logic_vector(192, X_SIZE)) then\r
- p_oam_cnt_wrap_n <= '0';\r
- end if;\r
-\r
--odd cycle copy from primary oam\r
if (nes_x(0) = '1') then\r
+ s_oam_w_n <= '1';\r
if (oam_ev_status = EV_STAT_COMP) then\r
p_oam_addr_in <= p_oam_cnt;\r
p_oam_cnt_ce_n <= '1';\r
else\r
--even cycle copy to secondary oam (if y is in range.)\r
s_oam_r_n <= '1';\r
- if (p_oam_cnt_wrap_n <= '1') then\r
- s_oam_w_n <= '0';\r
- else\r
- s_oam_w_n <= '1';\r
- end if;\r
- s_oam_addr <= s_oam_cnt;\r
- s_oam_data <= p_oam_data;\r
\r
- if (oam_ev_status = EV_STAT_COMP) then\r
- --check y range.\r
- if (nes_y < "000000110" and p_oam_data <= nes_y + "000000001") or \r
- (nes_y >= "000000110" and p_oam_data <= nes_y + "000000001" and \r
- p_oam_data >= nes_y - "000000110") then\r
- oam_ev_status <= EV_STAT_CP1;\r
- s_oam_cnt_ce_n <= '0';\r
- --copy remaining oam entry.\r
- p_oam_cnt_ce_n <= '1';\r
- \r
- --check sprite 0 is used.\r
- if (p_oam_cnt = "00000000") then\r
- sprite0_evaluated <= '1';\r
+ --TODO: sprite evaluation is simplified!!\r
+ --not complying the original NES spec at\r
+ --http://wiki.nesdev.com/w/index.php/PPU_sprite_evaluation\r
+ --e.g., when overflow happens, it just ignore subsequent entry.\r
+ if (s_oam_cnt = "00000" and nes_x > conv_std_logic_vector(HSCAN_OAM_EVA_START + 2, X_SIZE)) then\r
+ s_oam_cnt_ce_n <= '1';\r
+ s_oam_w_n <= '1';\r
+ s_oam_addr <= (others => 'Z');\r
+ s_oam_data <= (others => 'Z');\r
+ else\r
+ s_oam_w_n <= '0';\r
+ s_oam_addr <= s_oam_cnt;\r
+ s_oam_data <= p_oam_data;\r
+\r
+ if (oam_ev_status = EV_STAT_COMP) then\r
+ --check y range.\r
+ if (nes_y < "000000110" and p_oam_data <= nes_y + "000000001") or \r
+ (nes_y >= "000000110" and p_oam_data <= nes_y + "000000001" and \r
+ p_oam_data >= nes_y - "000000110") then\r
+ oam_ev_status <= EV_STAT_CP1;\r
+ s_oam_cnt_ce_n <= '0';\r
+ --copy remaining oam entry.\r
+ p_oam_cnt_ce_n <= '1';\r
+ \r
+ --check sprite 0 is used.\r
+ if (p_oam_cnt = "00000000") then\r
+ sprite0_evaluated <= '1';\r
+ end if;\r
+ else\r
+ --goto next entry\r
+ p_oam_cnt_ce_n <= '0';\r
end if;\r
- else\r
- --goto next entry\r
+ elsif (oam_ev_status = EV_STAT_CP1) then\r
+ s_oam_cnt_ce_n <= '0';\r
+ oam_ev_status <= EV_STAT_CP2;\r
+ elsif (oam_ev_status = EV_STAT_CP2) then\r
+ s_oam_cnt_ce_n <= '0';\r
+ oam_ev_status <= EV_STAT_CP3;\r
+ elsif (oam_ev_status = EV_STAT_CP3) then\r
+ s_oam_cnt_ce_n <= '0';\r
+ elsif (oam_ev_status = EV_STAT_PRE_COMP) then\r
+ oam_ev_status <= EV_STAT_COMP;\r
+ s_oam_cnt_ce_n <= '0';\r
p_oam_cnt_ce_n <= '0';\r
end if;\r
- elsif (oam_ev_status = EV_STAT_CP1) then\r
- s_oam_cnt_ce_n <= '0';\r
- oam_ev_status <= EV_STAT_CP2;\r
- elsif (oam_ev_status = EV_STAT_CP2) then\r
- s_oam_cnt_ce_n <= '0';\r
- oam_ev_status <= EV_STAT_CP3;\r
- elsif (oam_ev_status = EV_STAT_CP3) then\r
- s_oam_cnt_ce_n <= '0';\r
- elsif (oam_ev_status = EV_STAT_PRE_COMP) then\r
- oam_ev_status <= EV_STAT_COMP;\r
- s_oam_cnt_ce_n <= '0';\r
- p_oam_cnt_ce_n <= '0';\r
end if;\r
end if;--if (nes_x(0) = '1') then\r
\r
elsif (nes_x > conv_std_logic_vector(HSCAN_SPR_MAX, X_SIZE)) then\r
--clear last write enable.\r
spr_ptn_h_we_n <= "11111111";\r
- end if;--if (nes_x /= "000000000" and nes_x <= conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE))\r
+ end if;--if (nes_x <= conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE))\r
\r
--display sprite.\r
if ((nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r