pi_ppu_scroll_y : in std_logic_vector (7 downto 0);\r
\r
--vram i/f\r
- po_rd_n : out std_logic;\r
- po_wr_n : out std_logic;\r
+ po_v_ce_n : out std_logic;\r
+ po_v_rd_n : out std_logic;\r
+ po_v_wr_n : out std_logic;\r
po_v_addr : out std_logic_vector (13 downto 0);\r
- io_v_data : in std_logic_vector (7 downto 0);\r
+ pi_v_data : in std_logic_vector (7 downto 0);\r
+\r
+ --plt i/f\r
+ po_plt_ce_n : out std_logic;\r
+ po_plt_rd_n : out std_logic;\r
+ po_plt_wr_n : out std_logic;\r
+ po_plt_addr : out std_logic_vector (4 downto 0);\r
+ pi_plt_data : in std_logic_vector (7 downto 0);\r
\r
--sprite i/f\r
po_spr_ce_n : out std_logic;\r
constant HSCAN_SPR_MAX : integer := 321;\r
constant HSCAN_OAM_EVA_START : integer := 64;\r
\r
+constant PREFETCH_INT : integer := 16;\r
+\r
constant PPUBNA : integer := 1; --base name address\r
constant PPUVAI : integer := 2; --vram address increment\r
constant PPUSPA : integer := 3; --sprite pattern table address\r
conv_std_logic_vector(16#000#, 12)\r
);\r
\r
+function is_bg (\r
+ pm_sbg : in std_logic;\r
+ pm_nes_x : in integer range 0 to VGA_W_MAX - 1;\r
+ pm_nes_y : in integer range 0 to VGA_H_MAX - 1\r
+ )return integer is\r
+begin\r
+ if (pm_sbg = '1'and\r
+ (pm_nes_x <= HSCAN or pm_nes_x >= HSCAN_NEXT_START) and\r
+ (pm_nes_y < VSCAN or pm_nes_y = VSCAN_NEXT_START)) then\r
+ return 1;\r
+ else\r
+ return 0;\r
+ end if;\r
+end;\r
+\r
signal reg_vga_x : integer range 0 to VGA_W_MAX - 1;\r
signal reg_vga_y : integer range 0 to VGA_H_MAX - 1;\r
\r
signal reg_nes_x : integer range 0 to VGA_W_MAX / 2 - 1;\r
signal reg_nes_y : integer range 0 to VGA_W_MAX / 2 - 1;\r
+--prefech is wider by scroll reg size.\r
+signal reg_prf_x : integer range 0 to VGA_W_MAX / 2 + 256 - 1;\r
+signal reg_prf_y : integer range 0 to VGA_W_MAX / 2 + 256 - 1;\r
+\r
+type vac_state is (\r
+ IDLE,\r
+ AD_SET0,\r
+ AD_SET1,\r
+ AD_SET2,\r
+ AD_SET3,\r
+ REG_SET0,\r
+ REG_SET1,\r
+ REG_SET2,\r
+ REG_SET3\r
+ );\r
+\r
+signal reg_v_cur_state : vac_state;\r
+signal reg_v_next_state : vac_state;\r
+\r
+signal reg_v_ce_n : std_logic;\r
+signal reg_v_rd_n : std_logic;\r
+signal reg_v_wr_n : std_logic;\r
+signal reg_v_addr : std_logic_vector (13 downto 0);\r
+signal reg_v_data : std_logic_vector (7 downto 0);\r
+\r
+signal reg_disp_nt : std_logic_vector (7 downto 0);\r
+signal reg_disp_attr : std_logic_vector (7 downto 0);\r
+signal reg_disp_ptn_l : std_logic_vector (15 downto 0);\r
+signal reg_disp_ptn_h : std_logic_vector (15 downto 0);\r
+\r
+signal reg_plt_ce_n : std_logic;\r
+signal reg_plt_rd_n : std_logic;\r
+signal reg_plt_wr_n : std_logic;\r
+signal reg_plt_addr : std_logic_vector (4 downto 0);\r
+signal reg_plt_data : std_logic_vector (7 downto 0);\r
\r
begin\r
\r
reg_vga_y <= 0;\r
reg_nes_x <= 0;\r
reg_nes_y <= 0;\r
+ reg_prf_x <= 0;\r
+ reg_prf_y <= 0;\r
elsif (rising_edge(pi_base_clk)) then\r
-\r
- reg_nes_x <= reg_vga_x / 2;\r
- reg_nes_y <= reg_vga_y / 2;\r
-\r
if ((pi_rnd_en(0) or pi_rnd_en(2))= '1') then\r
if (reg_vga_x = VGA_W_MAX - 1) then\r
reg_vga_x <= 0;\r
+ reg_nes_x <= 0;\r
if (reg_vga_x = VGA_H_MAX - 1) then\r
reg_vga_y <= 0;\r
+ reg_nes_y <= 0;\r
else\r
reg_vga_y <= reg_vga_y + 1;\r
+ reg_nes_y <= (reg_vga_y + 1) / 2;\r
end if;\r
else\r
reg_vga_x <= reg_vga_x + 1;\r
+ reg_nes_x <= (reg_vga_x + 1) / 2;\r
end if;\r
- \r
+\r
--sync signal assert.\r
if (reg_vga_x >= VGA_W + H_FP and reg_vga_x < VGA_W + H_FP + H_SP) then\r
po_h_sync_n <= '0';\r
else\r
po_v_sync_n <= '1';\r
end if;\r
- \r
end if;--if (pi_rnd_en(1) = '1' or pi_rnd_en(3) = '1' ) then\r
+\r
+ --pre-fetch x/y position...\r
+ if (reg_vga_x < HSCAN_NEXT_START * 2) then\r
+ reg_prf_x <= reg_vga_x / 2 + conv_integer(pi_ppu_scroll_x) + PREFETCH_INT;\r
+ else\r
+ reg_prf_x <= reg_vga_x / 2 + conv_integer(pi_ppu_scroll_x)\r
+ - HSCAN_NEXT_START + PREFETCH_INT;\r
+ end if;\r
+\r
+ if (reg_vga_y < VSCAN * 2) then\r
+ if (reg_vga_x < HSCAN_NEXT_START * 2) then\r
+ reg_prf_y <= reg_vga_y / 2 + conv_integer(pi_ppu_scroll_y);\r
+ else\r
+ reg_prf_y <= (reg_vga_y + 1) / 2 + conv_integer(pi_ppu_scroll_y);\r
+ end if;\r
+ else\r
+ reg_prf_y <= 0;\r
+ end if;\r
end if;--if (pi_rst_n = '0') then\r
end process;\r
\r
- po_rd_n <= 'Z';\r
- po_wr_n <= 'Z';\r
- po_v_addr <= (others => 'Z');\r
- \r
+-- --vram access state machine (state transition)...\r
+-- vac_set_stat_p : process (pi_rst_n, pi_base_clk)\r
+-- begin\r
+-- if (pi_rst_n = '0') then\r
+-- reg_v_cur_state <= IDLE;\r
+-- elsif (rising_edge(pi_base_clk)) then\r
+-- reg_v_cur_state <= reg_v_next_state;\r
+-- end if;--if (pi_rst_n = '0') then\r
+-- end process;\r
+--\r
+-- --state change to next.\r
+-- vac_next_stat_p : process (reg_v_cur_state, pi_rnd_en, pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y)\r
+--function bg_process (\r
+-- pm_sbg : in std_logic;\r
+-- pm_nes_x : in integer range 0 to VGA_W_MAX - 1;\r
+-- pm_nes_y : in integer range 0 to VGA_H_MAX - 1\r
+-- )return integer is\r
+--begin\r
+-- if (pm_sbg = '1'and\r
+-- (pm_nes_x <= HSCAN or pm_nes_x >= HSCAN_NEXT_START) and\r
+-- (pm_nes_y < VSCAN or pm_nes_y = VSCAN_NEXT_START)) then\r
+-- return 1;\r
+-- else\r
+-- return 0;\r
+-- end if;\r
+--end;\r
+--\r
+--function is_idle (\r
+-- pm_sbg : in std_logic;\r
+-- pm_nes_x : in integer range 0 to VGA_W_MAX - 1;\r
+-- pm_nes_y : in integer range 0 to VGA_H_MAX - 1\r
+-- )return integer is\r
+--begin\r
+-- if (pm_sbg = '0' or\r
+-- (pm_nes_x > HSCAN and pm_nes_x < HSCAN_NEXT_START) or\r
+-- (pm_nes_y >= VSCAN and pm_nes_y < VSCAN_NEXT_START)) then\r
+-- return 1;\r
+-- else\r
+-- return 0;\r
+-- end if;\r
+--end;\r
+-- begin\r
+-- case reg_v_cur_state is\r
+-- when IDLE =>\r
+-- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+-- pi_rnd_en(3) = '1' and\r
+-- reg_nes_x mod 8 = 0) then\r
+-- --start vram access process.\r
+-- reg_v_next_state <= AD_SET0;\r
+-- else\r
+-- reg_v_next_state <= reg_v_cur_state;\r
+-- end if;\r
+-- when AD_SET0 =>\r
+-- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+-- pi_rnd_en(0) = '1'\r
+-- ) then\r
+-- reg_v_next_state <= AD_SET1;\r
+-- elsif (is_idle(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
+-- ---when nes_x=257, fall to idle\r
+-- reg_v_next_state <= IDLE;\r
+-- else\r
+-- reg_v_next_state <= reg_v_cur_state;\r
+-- end if;\r
+-- when AD_SET1 =>\r
+-- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+-- pi_rnd_en(1) = '1'\r
+-- ) then\r
+-- reg_v_next_state <= AD_SET2;\r
+-- else\r
+-- reg_v_next_state <= reg_v_cur_state;\r
+-- end if;\r
+-- when AD_SET2 =>\r
+-- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+-- pi_rnd_en(2) = '1'\r
+-- ) then\r
+-- reg_v_next_state <= AD_SET3;\r
+-- else\r
+-- reg_v_next_state <= reg_v_cur_state;\r
+-- end if;\r
+-- when AD_SET3 =>\r
+-- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+-- pi_rnd_en(3) = '1'\r
+-- ) then\r
+-- reg_v_next_state <= REG_SET0;\r
+-- else\r
+-- reg_v_next_state <= reg_v_cur_state;\r
+-- end if;\r
+-- when REG_SET0 =>\r
+-- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+-- pi_rnd_en(0) = '1'\r
+-- ) then\r
+-- reg_v_next_state <= REG_SET1;\r
+-- else\r
+-- reg_v_next_state <= reg_v_cur_state;\r
+-- end if;\r
+-- when REG_SET1 =>\r
+-- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+-- pi_rnd_en(1) = '1'\r
+-- ) then\r
+-- reg_v_next_state <= REG_SET2;\r
+-- else\r
+-- reg_v_next_state <= reg_v_cur_state;\r
+-- end if;\r
+-- when REG_SET2 =>\r
+-- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+-- pi_rnd_en(2) = '1'\r
+-- ) then\r
+-- reg_v_next_state <= REG_SET3;\r
+-- else\r
+-- reg_v_next_state <= reg_v_cur_state;\r
+-- end if;\r
+-- when REG_SET3 =>\r
+-- if (bg_process(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1 and\r
+-- pi_rnd_en(3) = '1'\r
+-- ) then\r
+-- reg_v_next_state <= AD_SET0;\r
+-- else\r
+-- reg_v_next_state <= reg_v_cur_state;\r
+-- end if;\r
+-- end case;\r
+-- end process;\r
+--\r
+-- po_v_ce_n <= reg_v_ce_n;\r
+-- po_v_rd_n <= reg_v_rd_n;\r
+-- po_v_wr_n <= reg_v_wr_n;\r
+-- po_v_addr <= reg_v_addr;\r
+--\r
+-- po_plt_ce_n <= reg_plt_ce_n;\r
+-- po_plt_rd_n <= reg_plt_rd_n;\r
+-- po_plt_wr_n <= reg_plt_wr_n;\r
+-- po_plt_addr <= reg_plt_addr;\r
+--\r
+-- --vram r/w selector state machine...\r
+-- vac_main_stat_p : process (reg_v_cur_state)\r
+-- begin\r
+-- case reg_v_cur_state is\r
+-- when IDLE =>\r
+-- reg_v_rd_n <= 'Z';\r
+-- reg_v_wr_n <= 'Z';\r
+-- when AD_SET0 | AD_SET1 | REG_SET2 | REG_SET3 =>\r
+-- reg_v_rd_n <= '1';\r
+-- reg_v_wr_n <= '1';\r
+-- when AD_SET2 | AD_SET3 | REG_SET0 | REG_SET1 =>\r
+-- reg_v_rd_n <= '0';\r
+-- reg_v_wr_n <= '1';\r
+-- end case;\r
+--\r
+-- case reg_v_cur_state is\r
+-- when IDLE =>\r
+-- reg_v_ce_n <= 'Z';\r
+-- reg_plt_ce_n <= 'Z';\r
+-- reg_plt_rd_n <= 'Z';\r
+-- reg_plt_wr_n <= 'Z'; \r
+-- when AD_SET0 | AD_SET1 | REG_SET2 | REG_SET3 | AD_SET2 | AD_SET3 | REG_SET0 | REG_SET1 =>\r
+-- reg_v_ce_n <= '0';\r
+-- reg_plt_ce_n <= '0';\r
+-- reg_plt_rd_n <= '0';\r
+-- reg_plt_wr_n <= '1'; \r
+-- end case;\r
+-- end process;\r
+--\r
+-- --vram address state machine...\r
+-- vaddr_stat_p : process (pi_rst_n, pi_base_clk)\r
+-- begin\r
+-- if (pi_rst_n = '0') then\r
+-- reg_v_addr <= (others => 'Z');\r
+-- reg_v_data <= (others => 'Z');\r
+-- reg_disp_nt <= (others => 'Z');\r
+-- reg_disp_attr <= (others => 'Z');\r
+-- elsif (rising_edge(pi_base_clk)) then\r
+-- reg_v_data <= pi_v_data;\r
+--\r
+-- if (is_bg(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
+-- ----fetch next tile byte.\r
+-- if (reg_prf_x mod 8 = 1) then\r
+-- --vram addr is incremented every 8 cycle.\r
+-- --name table at 0x2000\r
+-- reg_v_addr(9 downto 0)\r
+-- <= conv_std_logic_vector(reg_prf_y, 9)(7 downto 3)\r
+-- & conv_std_logic_vector(reg_prf_x, 9)(7 downto 3);\r
+-- reg_v_addr(13 downto 10) <= "10" & pi_ppu_ctrl(PPUBNA downto 0)\r
+-- + ("000" & conv_std_logic_vector(reg_prf_x, 9)(8));\r
+-- \r
+-- elsif (reg_prf_x mod 8 = 2 and reg_v_cur_state = REG_SET0) then\r
+-- reg_disp_nt <= reg_v_data;\r
+-- \r
+-- ----fetch attr table byte.\r
+-- elsif (reg_prf_x mod 8 = 3) then\r
+-- --attr table at 0x23c0\r
+-- reg_v_addr(7 downto 0) <= "11000000" +\r
+-- ("00" & conv_std_logic_vector(reg_prf_y, 9)(7 downto 5)\r
+-- & conv_std_logic_vector(reg_prf_x, 9)(7 downto 5));\r
+-- reg_v_addr(13 downto 8) <= "10" &\r
+-- pi_ppu_ctrl(PPUBNA downto 0) & "11"\r
+-- + ("000" & conv_std_logic_vector(reg_prf_x, 9)(8) & "00");\r
+-- \r
+-- elsif (reg_prf_x mod 8 = 4 and reg_v_cur_state = REG_SET0) then\r
+-- reg_disp_attr <= reg_v_data;\r
+--\r
+-- ----fetch pattern table low byte.\r
+-- elsif (reg_prf_x mod 8 = 5) then\r
+-- --vram addr is incremented every 8 cycle.\r
+-- reg_v_addr <= "0" & pi_ppu_ctrl(PPUBPA) &\r
+-- reg_disp_nt(7 downto 0)\r
+-- & "0" & conv_std_logic_vector(reg_prf_y, 9)(2 downto 0);\r
+--\r
+-- ----fetch pattern table high byte.\r
+-- elsif (reg_prf_x mod 8 = 7) then\r
+-- --vram addr is incremented every 8 cycle.\r
+-- reg_v_addr <= "0" & pi_ppu_ctrl(PPUBPA) &\r
+-- reg_disp_nt(7 downto 0)\r
+-- & "0" & conv_std_logic_vector(reg_prf_y, 9)(2 downto 0)\r
+-- + "00000000001000";\r
+-- end if;\r
+-- end if;\r
+-- end if;--if (pi_rst_n = '0') then\r
+-- end process;\r
+--\r
+-- --pattern table state machine...\r
+-- bg_ptn_p : process (pi_rst_n, pi_base_clk)\r
+-- begin\r
+-- if (pi_rst_n = '0') then\r
+-- reg_disp_ptn_l <= (others => '0');\r
+-- reg_disp_ptn_h <= (others => '0');\r
+-- elsif (rising_edge(pi_base_clk)) then\r
+--\r
+-- if (is_bg(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
+-- if (reg_v_cur_state = REG_SET0) then\r
+-- if (reg_prf_x mod 8 = 6) then\r
+-- reg_disp_ptn_l <= reg_v_data & reg_disp_ptn_l(7 downto 0);\r
+-- else\r
+-- reg_disp_ptn_l <= "0" & reg_disp_ptn_l(15 downto 1);\r
+-- end if;\r
+--\r
+-- if (reg_prf_x mod 8 = 0) then\r
+-- reg_disp_ptn_h <= reg_v_data & reg_disp_ptn_h(7 downto 0);\r
+-- else\r
+-- reg_disp_ptn_h <= "0" & reg_disp_ptn_h(15 downto 1);\r
+-- end if;\r
+--\r
+-- elsif (reg_v_cur_state = AD_SET0) then\r
+-- reg_disp_ptn_l <= "0" & reg_disp_ptn_l(15 downto 1);\r
+-- reg_disp_ptn_h <= "0" & reg_disp_ptn_h(15 downto 1);\r
+--\r
+-- end if;\r
+-- end if;\r
+-- end if;--if (pi_rst_n = '0') then\r
+-- end process;\r
+--\r
+-- --palette table state machine...\r
+-- plt_ac_p : process (pi_rst_n, pi_base_clk)\r
+-- begin\r
+-- if (pi_rst_n = '0') then\r
+-- reg_plt_addr <= (others => 'Z');\r
+-- reg_plt_data <= (others => 'Z');\r
+-- elsif (rising_edge(pi_base_clk)) then\r
+-- \r
+-- reg_plt_data <= pi_plt_data;\r
+-- \r
+-- if (is_bg(pi_ppu_mask(PPUSBG), reg_nes_x, reg_nes_y) = 1) then\r
+-- if (conv_std_logic_vector(reg_nes_y, 9)(4) = '0'\r
+-- and (reg_disp_ptn_h(0) or reg_disp_ptn_l(0)) = '1') then\r
+-- reg_plt_addr <=\r
+-- "0" & reg_disp_attr(1 downto 0) & reg_disp_ptn_h(0) & reg_disp_ptn_l(0);\r
+-- elsif (conv_std_logic_vector(reg_nes_y, 9)(4) = '1'\r
+-- and (reg_disp_ptn_h(0) or reg_disp_ptn_l(0)) = '1') then\r
+-- reg_plt_addr <=\r
+-- "0" & reg_disp_attr(5 downto 4) & reg_disp_ptn_h(0) & reg_disp_ptn_l(0);\r
+-- else\r
+-- ---else: no output color >> universal bg color output.\r
+-- --0x3f00 is the universal bg palette.\r
+-- reg_plt_addr <= (others => '0');\r
+-- end if;\r
+-- end if;\r
+-- end if;--if (pi_rst_n = '0') then\r
+-- end process;\r
+\r
+ rgb_out_p : process (pi_rst_n, pi_base_clk)\r
+ begin\r
+ if (pi_rst_n = '0') then\r
+ po_b <= (others => '0');\r
+ po_g <= (others => '0');\r
+ po_r <= (others => '0');\r
+ else\r
+ if (rising_edge(pi_base_clk)) then\r
+ if (reg_nes_x < HSCAN and reg_nes_y < VSCAN) then\r
+ --if or if not bg/sprite is shown, output color anyway \r
+ --sinse universal bg color is included..\r
+-- po_b <= nes_color_palette(conv_integer(reg_plt_data(5 downto 0))) (11 downto 8);\r
+-- po_g <= nes_color_palette(conv_integer(reg_plt_data(5 downto 0))) (7 downto 4);\r
+-- po_r <= nes_color_palette(conv_integer(reg_plt_data(5 downto 0))) (3 downto 0);\r
+ po_b <= (others => '0');\r
+ po_g <= (others => '1');\r
+ po_r <= (others => '1');\r
+ else\r
+ po_b <= (others => '0');\r
+ po_g <= (others => '0');\r
+ po_r <= (others => '0');\r
+ end if;\r
+ end if; --if (rising_edge(emu_ppu_clk)) then\r
+ end if;--if (rst_n = '0') then\r
+ end process;--output_p\r
+\r
po_ppu_status <= (others => '0');\r
\r
po_spr_ce_n <= 'Z';\r
po_spr_wr_n <= 'Z';\r
po_spr_addr <= (others => 'Z');\r
\r
- po_r <= (others => 'Z');\r
- po_g <= (others => 'Z');\r
- po_b <= (others => 'Z');\r
end rtl;\r
-\r