signal cnt_x_en_n : std_logic;
signal cnt_x_res_n : std_logic;
+signal scrl_x_res_n : std_logic;
signal cnt_y_en_n : std_logic;
signal cnt_y_res_n : std_logic;
signal cur_x : std_logic_vector(X_SIZE - 1 downto 0);
signal cur_y : std_logic_vector(X_SIZE - 1 downto 0);
-signal next_x : std_logic_vector(X_SIZE - 1 downto 0);
-signal next_y : std_logic_vector(X_SIZE - 1 downto 0);
-signal scrl_x : std_logic_vector(X_SIZE - 1 downto 0);
-signal scrl_y : std_logic_vector(X_SIZE - 1 downto 0);
+--prefetch position 512 x 240
+signal prf_x : std_logic_vector(X_SIZE - 1 downto 0);
+signal prf_y : std_logic_vector(X_SIZE - 1 downto 0);
signal nt_we_n : std_logic;
signal disp_nt : std_logic_vector (dsize - 1 downto 0);
cnt_x_en_n <= '0';
- vram_io <= io_cnt(0) when ppu_scroll_x(0) = '0' else
- not io_cnt(0);
+ vram_io <= not io_cnt(0) when ppu_scroll_x(0) = '0' else
+ io_cnt(0);
ale <= vram_io when ppu_mask(PPUSBG) = '1' and
(cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or
cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else
v_bus_busy_n <= d_oe_n;
io_cnt_inst : counter_register generic map (1, 1)
- port map (clk, cnt_x_res_n, '0', '1', (others => '0'), io_cnt);
-
- --take scroll position into account
- scrl_x <= cur_x + ppu_scroll_x
- when cur_x + ppu_scroll_x <= "101010100" else
- cur_x + ppu_scroll_x + "010101011"; -- << +511-340 = 171.
-
- scrl_y <= cur_y + ppu_scroll_y
- when cur_y + ppu_scroll_y <= "100000101" else
- cur_y + ppu_scroll_y + "011111010"; -- << +511-261 = 251.
-
- ---x pos is 8 cycle ahead of current pos.
- next_x <= scrl_x + "000010000"
- when scrl_x < conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE) else
- scrl_x + "011000000";
- next_y <= cur_y
- when cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) else
+ port map (clk, scrl_x_res_n, '0', '1', (others => '0'), io_cnt);
+
+ ---x pos is 16 + scroll cycle ahead of current pos.
+ prf_x <= cur_x + ppu_scroll_x + "000010000"
+ when cur_x < conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE) else
+ cur_x + ppu_scroll_x + "010111011"; -- +16 -341
+ prf_y <= cur_y + ppu_scroll_y
+ when prf_x <= conv_std_logic_vector(HSCAN, X_SIZE) and prf_x > cur_x else
"000000000"
- when cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE) else
- cur_y + "000000001";
+ when cur_y + ppu_scroll_y =
+ conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE) else
+ cur_y + ppu_scroll_y + "000000001";
--current x,y pos
cur_x_inst : counter_register generic map (X_SIZE, 1)
vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7)) &
disp_ptn_h (dsize downto 1);
- ptn_en_n <= '1' when scrl_x = conv_std_logic_vector(0, X_SIZE) else
- '0' when scrl_x <= conv_std_logic_vector(HSCAN_NEXT_EXTRA, X_SIZE) else
+ ptn_en_n <= '1' when prf_x = conv_std_logic_vector(0, X_SIZE) else
+ '0' when prf_x <= conv_std_logic_vector(HSCAN_NEXT_EXTRA, X_SIZE) else
'1';
ptn_l_inst : d_flip_flop generic map(dsize)
--reverse bit when NOT SPRHFL is set (.nes file format bit endian).
- spr_ptn_in <= vram_ad when spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRHFL) = '1' else
+ spr_ptn_in <= vram_ad
+ when spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRHFL) = '1' else
(vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) &
vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7));
--array instances...
spr_inst : for i in 0 to 7 generate
spr_x_inst : counter_register generic map(dsize, 16#ff#)
- port map (clk_n, rst_n, spr_x_ce_n(i), spr_x_we_n(i), s_oam_data, spr_x_cnt(i));
+ port map (clk_n, rst_n, spr_x_ce_n(i), spr_x_we_n(i),
+ s_oam_data, spr_x_cnt(i));
spr_attr_inst : d_flip_flop generic map(dsize)
port map (clk_n, rst_n, '1', spr_attr_we_n(i), s_oam_data, spr_attr(i));
spr_ptn_l_inst : shift_register generic map(dsize, 1)
- port map (clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_l_we_n(i), spr_ptn_in, spr_ptn_l(i));
+ port map (clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_l_we_n(i),
+ spr_ptn_in, spr_ptn_l(i));
spr_ptn_h_inst : shift_register generic map(dsize, 1)
- port map (clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_h_we_n(i), spr_ptn_in, spr_ptn_h(i));
+ port map (clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_h_we_n(i),
+ spr_ptn_in, spr_ptn_h(i));
end generate;
clk_p : process (rst_n, clk, read_status)
begin
if (rst_n = '0') then
cnt_x_res_n <= '0';
+ scrl_x_res_n <= '0';
cnt_y_res_n <= '0';
nt_we_n <= '1';
cnt_x_res_n <= '1';
cnt_y_res_n <= '1';
end if;
+
+ if (clk = '0' and
+ prf_x = conv_std_logic_vector(HSCAN_MAX - 1, X_SIZE)) then
+ scrl_x_res_n <= '0';
+ else
+ scrl_x_res_n <= '1';
+ end if;
end if; --if (clk'event) then
if (clk'event and clk = '1') then
d_print("cur_x: " & conv_hex16(conv_integer(cur_x)));
d_print("cur_y: " & conv_hex16(conv_integer(cur_y)));
+ --visible area bg image
+ if ((cur_x <= conv_std_logic_vector(HSCAN, X_SIZE)) or
+ cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) then
+
----fetch next tile byte.
- if (scrl_x (2 downto 0) = "001" ) then
+ if (prf_x (2 downto 0) = "001" ) then
--vram addr is incremented every 8 cycle.
--name table at 0x2000
vram_addr(9 downto 0)
- <= next_y(dsize - 1 downto 3)
- & next_x(dsize - 1 downto 3);
- vram_addr(asize - 1 downto 10) <= "10" & ppu_ctrl(PPUBNA downto 0);
+ <= prf_y(dsize - 1 downto 3)
+ & prf_x(dsize - 1 downto 3);
+ vram_addr(asize - 1 downto 10) <= "10" & ppu_ctrl(PPUBNA downto 0)
+ + ("000" & prf_x(dsize));
end if;
- if (scrl_x (2 downto 0) = "010" ) then
+ if (prf_x (2 downto 0) = "010" ) then
nt_we_n <= '0';
else
nt_we_n <= '1';
end if;
----fetch attr table byte.
- if (scrl_x (4 downto 0) = "11011" or
- scrl_x = conv_std_logic_vector(HSCAN_NEXT_START + 3, X_SIZE)) then
+ if (prf_x (4 downto 0) = "11011" or
+ prf_x = conv_std_logic_vector(HSCAN_NEXT_START + 3, X_SIZE)) then
--attribute table is loaded every 32 cycle.
--attr table at 0x23c0
vram_addr(dsize - 1 downto 0) <= "11000000" +
- ("00" & next_y(7 downto 5) & next_x(7 downto 5));
+ ("00" & prf_y(7 downto 5) & prf_x(7 downto 5));
vram_addr(asize - 1 downto dsize) <= "10" &
- ppu_ctrl(PPUBNA downto 0) & "11";
- end if;--if (scrl_x (2 downto 0) = "010" ) then
- if (scrl_x (4 downto 0) = "11100" or
- scrl_x = conv_std_logic_vector(HSCAN_NEXT_START + 4, X_SIZE)) then
+ ppu_ctrl(PPUBNA downto 0) & "11"
+ + ("000" & prf_x(dsize));
+ end if;--if (prf_x (2 downto 0) = "010" ) then
+ if (prf_x (4 downto 0) = "11100" or
+ prf_x = conv_std_logic_vector(HSCAN_NEXT_START + 4, X_SIZE)) then
attr_we_n <= '0';
else
attr_we_n <= '1';
end if;
- if (scrl_x (4 downto 0) = "00000" ) then
+ if (prf_x (4 downto 0) = "00000" ) then
disp_attr_we_n <= '0';
else
disp_attr_we_n <= '1';
end if;
---attribute is shifted every 16 bit.
- if (scrl_x (3 downto 0) = "0000" ) then
+ if (prf_x (3 downto 0) = "0000" ) then
attr_ce_n <= '0';
else
attr_ce_n <= '1';
end if;
- --visible area bg image
- if ((cur_x <= conv_std_logic_vector(HSCAN, X_SIZE)) or
- cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) then
-
----fetch pattern table low byte.
- if (scrl_x (2 downto 0) = "101" ) then
+ if (prf_x (2 downto 0) = "101" ) then
--vram addr is incremented every 8 cycle.
vram_addr <= "0" & ppu_ctrl(PPUBPA) &
disp_nt(dsize - 1 downto 0)
- & "0" & next_y(2 downto 0);
- end if;--if (scrl_x (2 downto 0) = "100" ) then
- if (scrl_x (2 downto 0) = "110" ) then
+ & "0" & prf_y(2 downto 0);
+ end if;--if (prf_x (2 downto 0) = "100" ) then
+ if (prf_x (2 downto 0) = "110" ) then
ptn_l_we_n <= '0';
else
ptn_l_we_n <= '1';
end if;
----fetch pattern table high byte.
- if (scrl_x (2 downto 0) = "111" ) then
+ if (prf_x (2 downto 0) = "111" ) then
--vram addr is incremented every 8 cycle.
vram_addr <= "0" & ppu_ctrl(PPUBPA) &
disp_nt(dsize - 1 downto 0)
- & "0" & next_y(2 downto 0) + "00000000001000";
- end if; --if (scrl_x (2 downto 0) = "110" ) then
- if (scrl_x (2 downto 0) = "000" and scrl_x /= "000000000") then
+ & "0" & prf_y(2 downto 0) + "00000000001000";
+ end if; --if (prf_x (2 downto 0) = "110" ) then
+ if (prf_x (2 downto 0) = "000" and prf_x /= "000000000") then
ptn_h_we_n <= '0';
else
ptn_h_we_n <= '1';
- end if;--if (scrl_x (2 downto 0) = "001" ) then
+ end if;--if (prf_x (2 downto 0) = "001" ) then
end if; --if (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE)) and
end if;--if (ppu_mask(PPUSBG) = '1') then
(cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or
cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE))) then
--secondary oam clear
- if (cur_x /= "000000000" and cur_x <= conv_std_logic_vector(64, X_SIZE)) then
+ if (cur_x /= "000000000" and
+ cur_x <= conv_std_logic_vector(64, X_SIZE)) then
if (cur_x(0) = '0') then
--write secondary oam on even cycle
s_oam_r_n <= '1';
--http://wiki.nesdev.com/w/index.php/PPU_sprite_evaluation
--e.g., when overflow happens, it just ignore subsequent entry.
--old secondary sprite entry.
- if (p_oam_cnt = "00000000" and cur_x > conv_std_logic_vector(192, X_SIZE)) then
+ if (p_oam_cnt = "00000000" and
+ cur_x > conv_std_logic_vector(192, X_SIZE)) then
p_oam_cnt_wrap_n <= '0';
end if;
if (oam_ev_status = EV_STAT_COMP) then
--check y range.
- if (cur_y < "000000110" and oam_data <= cur_y + "000000001") or
- (cur_y >= "000000110" and oam_data <= cur_y + "000000001" and
+ if (cur_y < "000000110" and
+ oam_data <= cur_y + "000000001") or
+ (cur_y >= "000000110" and
+ oam_data <= cur_y + "000000001" and
oam_data >= cur_y - "000000110") then
oam_ev_status <= EV_STAT_CP1;
s_oam_cnt_ce_n <= '0';
----fetch pattern table low byte.
if (cur_x (2 downto 0) = "101" ) then
- if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL) = '0') then
+ if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL)
+ = '0') then
vram_addr <= "0" & ppu_ctrl(PPUSPA) &
spr_tile_tmp(dsize - 1 downto 0) & "0" &
- (next_y(2 downto 0) - spr_y_tmp(2 downto 0));
+ (prf_y(2 downto 0) - spr_y_tmp(2 downto 0));
else
--flip sprite vertically.
vram_addr <= "0" & ppu_ctrl(PPUSPA) &
- spr_tile_tmp(dsize - 1 downto 0) & "0" &
- (spr_y_tmp(2 downto 0) - next_y(2 downto 0) - "001");
+ spr_tile_tmp(dsize - 1 downto 0) & "0" &
+ (spr_y_tmp(2 downto 0) - prf_y(2 downto 0) - "001");
end if;
end if;
----fetch pattern table high byte.
if (cur_x (2 downto 0) = "111" ) then
- if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL) = '0') then
+ if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL)
+ = '0') then
vram_addr <= "0" & ppu_ctrl(PPUSPA) &
spr_tile_tmp(dsize - 1 downto 0) & "0" &
- (next_y(2 downto 0) - spr_y_tmp(2 downto 0))
+ (prf_y(2 downto 0) - spr_y_tmp(2 downto 0))
+ "00000000001000";
else
--flip sprite vertically.
vram_addr <= "0" & ppu_ctrl(PPUSPA) &
spr_tile_tmp(dsize - 1 downto 0) & "0" &
- (spr_y_tmp(2 downto 0) - next_y(2 downto 0))
+ (spr_y_tmp(2 downto 0) - prf_y(2 downto 0))
+ "00000000000111";
end if;
end if;
spr_ptn_h_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '0';
s_oam_addr_cpy_ce_n <= '0';
else
- spr_ptn_h_we_n(conv_integer(s_oam_addr_cpy(4 downto 2) - "001")) <= '1';
+ spr_ptn_h_we_n(conv_integer(s_oam_addr_cpy(4 downto 2) - "001"))
+ <= '1';
end if;
elsif (cur_x > conv_std_logic_vector(320, X_SIZE)) then
--clear last write enable.
spr_ptn_h_we_n <= "11111111";
- end if;--if (cur_x /= "000000000" and cur_x <= conv_std_logic_vector(64, X_SIZE))
+ end if;--if (cur_x /= "000000000" and
+ --cur_x <= conv_std_logic_vector(64, X_SIZE))
--display sprite.
if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and