);\r
end component;\r
\r
-component ppu_render\r
- port ( \r
- signal dbg_ppu_clk : out std_logic;\r
- signal dbg_nes_x : out std_logic_vector (8 downto 0);\r
- signal dbg_nes_y : out std_logic_vector (8 downto 0);\r
- signal dbg_disp_nt, dbg_disp_attr : out std_logic_vector (7 downto 0);\r
- signal dbg_disp_ptn_h, dbg_disp_ptn_l : out std_logic_vector (15 downto 0);\r
- signal dbg_plt_ce_rn_wn : out std_logic_vector (2 downto 0);\r
- signal dbg_plt_addr : out std_logic_vector (4 downto 0);\r
- signal dbg_plt_data : out std_logic_vector (7 downto 0);\r
- signal dbg_p_oam_ce_rn_wn : out std_logic_vector (2 downto 0);\r
- signal dbg_p_oam_addr : out std_logic_vector (7 downto 0);\r
- signal dbg_p_oam_data : out std_logic_vector (7 downto 0);\r
- signal dbg_s_oam_ce_rn_wn : out std_logic_vector (2 downto 0);\r
- signal dbg_s_oam_addr : out std_logic_vector (4 downto 0);\r
- signal dbg_s_oam_data : out std_logic_vector (7 downto 0);\r
- \r
- ppu_clk : in std_logic;\r
- mem_clk : in std_logic;\r
- rst_n : in std_logic;\r
- rd_n : out std_logic;\r
- wr_n : out std_logic;\r
- ale : out std_logic;\r
- vram_ad : inout std_logic_vector (7 downto 0);\r
- vram_a : out std_logic_vector (13 downto 8);\r
- cur_x : in std_logic_vector (8 downto 0);\r
- cur_y : in std_logic_vector (8 downto 0);\r
- r : out std_logic_vector (3 downto 0);\r
- g : out std_logic_vector (3 downto 0);\r
- b : out std_logic_vector (3 downto 0);\r
- ppu_ctrl : in std_logic_vector (7 downto 0);\r
- ppu_mask : in std_logic_vector (7 downto 0);\r
- read_status : in std_logic;\r
- ppu_status : out std_logic_vector (7 downto 0);\r
- ppu_scroll_x : in std_logic_vector (7 downto 0);\r
- ppu_scroll_y : in std_logic_vector (7 downto 0);\r
- \r
- r_nw : in std_logic;\r
- oam_bus_ce_n : in std_logic;\r
- plt_bus_ce_n : in std_logic;\r
- oam_plt_addr : in std_logic_vector (7 downto 0);\r
- oam_plt_data : inout std_logic_vector (7 downto 0);\r
- v_bus_busy_n : out std_logic\r
- );\r
-end component;\r
-\r
---------- screen constant -----------\r
-constant VGA_W : integer := 640;\r
-constant VGA_H : integer := 480;\r
-constant VGA_W_MAX : integer := 800;\r
-constant VGA_H_MAX : integer := 525;\r
-constant H_SP : integer := 95;\r
-constant H_BP : integer := 48;\r
-constant H_FP : integer := 15;\r
-constant V_SP : integer := 2;\r
-constant V_BP : integer := 33;\r
-constant V_FP : integer := 10;\r
-\r
---------- signal declaration -----------\r
-signal vga_x : std_logic_vector (9 downto 0);\r
-signal vga_y : std_logic_vector (9 downto 0);\r
-signal x_res_n : std_logic;\r
-signal y_res_n : std_logic;\r
-signal y_en_n : std_logic;\r
-signal cnt_clk : std_logic;\r
-\r
-signal emu_ppu_clk : std_logic;\r
-signal emu_ppu_clk_n : std_logic;\r
-signal count5_res_n : std_logic;\r
-signal count5 : std_logic_vector(2 downto 0);\r
-signal nes_x : std_logic_vector (8 downto 0);\r
-signal nes_y : std_logic_vector (8 downto 0);\r
-\r
----DE1 base clock 50 MHz\r
----motones sim project uses following clock.\r
---cpu clock = base clock / 24 = 2.08 MHz (480 ns / cycle)\r
---ppu clock = base clock / 8\r
---vga clock = base clock / 2\r
---sdram clock = 135 MHz\r
-\r
-begin\r
- dbg_vga_x <= vga_x;\r
- dbg_vga_y <= vga_y;\r
- dbg_vga_clk <= vga_clk;\r
- \r
- cnt_clk <= not vga_clk;\r
- \r
- --vga position counter\r
- x_inst : counter_register generic map (10, 1)\r
- port map (cnt_clk , x_res_n, '0', '1', (others => '0'), vga_x);\r
- y_inst : counter_register generic map (10, 1)\r
- port map (cnt_clk , y_res_n, y_en_n, '1', (others => '0'), vga_y);\r
- vga_out_p : process (rst_n, vga_clk)\r
- begin\r
- if (rst_n = '0') then\r
- h_sync_n <= '0';\r
- v_sync_n <= '0';\r
- x_res_n <= '0';\r
- y_res_n <= '0';\r
- elsif (rising_edge(vga_clk)) then\r
- --xmax = 799\r
- if (vga_x = conv_std_logic_vector(VGA_W_MAX, 10)) then\r
- x_res_n <= '0';\r
- y_en_n <= '0';\r
- --ymax=524\r
- if (vga_y = conv_std_logic_vector(VGA_H_MAX, 10)) then\r
- y_res_n <= '0';\r
- else\r
- y_res_n <= '1';\r
- end if;\r
- else\r
- x_res_n <= '1';\r
- y_en_n <= '1';\r
- y_res_n <= '1';\r
- end if;\r
-\r
- --sync signal assert.\r
- if (vga_x >= conv_std_logic_vector((VGA_W + H_FP) , 10) and \r
- vga_x < conv_std_logic_vector((VGA_W + H_FP + H_SP) , 10)) then\r
- h_sync_n <= '0';\r
- else\r
- h_sync_n <= '1';\r
- end if;\r
-\r
- if (vga_y >= conv_std_logic_vector((VGA_H + V_FP) , 10) and \r
- vga_y < conv_std_logic_vector((VGA_H + V_FP + V_SP) , 10)) then\r
- v_sync_n <= '0';\r
- else\r
- v_sync_n <= '1';\r
- end if;\r
-\r
- end if;\r
- end process;\r
-\r
- --emulate ppu clock that is synchronized with vga clock\r
- count5_inst : counter_register generic map (3, 1)\r
- port map (cnt_clk, count5_res_n, '0', '1', (others => '0'), count5);\r
- nes_x_inst : counter_register generic map (9, 1)\r
- port map (emu_ppu_clk , x_res_n, '0', '1', (others => '0'), nes_x);\r
- nes_y <= vga_y(9 downto 1);\r
-\r
- res_p : process (rst_n, vga_clk)\r
- begin\r
- if (rst_n = '0') then\r
- count5_res_n <= '0';\r
- elsif (rising_edge(vga_clk)) then\r
- if (vga_x = conv_std_logic_vector(VGA_W_MAX, 10)) then\r
- count5_res_n <= '0';\r
- elsif (count5 = "100") then\r
- count5_res_n <= '0';\r
- else\r
- count5_res_n <= '1';\r
- end if;\r
- end if;\r
- end process;\r
-\r
- emu_clk_p : process (rst_n, mem_clk)\r
- begin\r
- if (rst_n = '0') then\r
- emu_ppu_clk <= '0';\r
- elsif (rising_edge(mem_clk)) then\r
- if (vga_x < conv_std_logic_vector(765, 10) ) then\r
- if (count5 = "001" or count5 = "011") then\r
- emu_ppu_clk <= '0';\r
- else\r
- emu_ppu_clk <= '1';\r
- end if;\r
- else\r
- emu_ppu_clk <= not emu_ppu_clk;\r
- end if;\r
- end if;\r
- end process;\r
-\r
- ---emulated ppu clock adjustment.\r
- emu_ppu_clk_n <= not emu_ppu_clk;\r
- ppu_render_inst : ppu_render\r
- port map (\r
- dbg_emu_ppu_clk ,\r
- dbg_nes_x ,\r
- dbg_nes_y ,\r
- dbg_disp_nt, dbg_disp_attr ,\r
- dbg_disp_ptn_h, dbg_disp_ptn_l ,\r
- dbg_plt_ce_rn_wn ,\r
- dbg_plt_addr ,\r
- dbg_plt_data ,\r
- dbg_p_oam_ce_rn_wn ,\r
- dbg_p_oam_addr ,\r
- dbg_p_oam_data ,\r
- dbg_s_oam_ce_rn_wn ,\r
- dbg_s_oam_addr ,\r
- dbg_s_oam_data ,\r
- \r
- emu_ppu_clk_n ,\r
- mem_clk ,\r
- rst_n ,\r
- rd_n ,\r
- wr_n ,\r
- ale ,\r
- vram_ad ,\r
- vram_a ,\r
- nes_x ,\r
- nes_y ,\r
- r ,\r
- g ,\r
- b ,\r
- ppu_ctrl ,\r
- ppu_mask ,\r
- read_status ,\r
- ppu_status ,\r
- ppu_scroll_x ,\r
- ppu_scroll_y ,\r
- r_nw ,\r
- oam_bus_ce_n ,\r
- plt_bus_ce_n ,\r
- oam_plt_addr ,\r
- oam_plt_data ,\r
- v_bus_busy_n \r
- );\r
-\r
-end rtl;\r
-\r
-\r
-\r
----------------------------------------------------------------\r
----------------------------------------------------------------\r
------------------------- PPU VGA Renderer ---------------------\r
----------------------------------------------------------------\r
----------------------------------------------------------------\r
-\r
-library ieee;\r
-use ieee.std_logic_1164.all;\r
-use ieee.std_logic_arith.conv_std_logic_vector;\r
-use ieee.std_logic_unsigned.all;\r
-use work.motonesfpga_common.all;\r
-\r
-entity ppu_render is \r
- port ( \r
- signal dbg_ppu_clk : out std_logic;\r
- signal dbg_nes_x : out std_logic_vector (8 downto 0);\r
- signal dbg_nes_y : out std_logic_vector (8 downto 0);\r
- signal dbg_disp_nt, dbg_disp_attr : out std_logic_vector (7 downto 0);\r
- signal dbg_disp_ptn_h, dbg_disp_ptn_l : out std_logic_vector (15 downto 0);\r
- signal dbg_plt_ce_rn_wn : out std_logic_vector (2 downto 0);\r
- signal dbg_plt_addr : out std_logic_vector (4 downto 0);\r
- signal dbg_plt_data : out std_logic_vector (7 downto 0);\r
- signal dbg_p_oam_ce_rn_wn : out std_logic_vector (2 downto 0);\r
- signal dbg_p_oam_addr : out std_logic_vector (7 downto 0);\r
- signal dbg_p_oam_data : out std_logic_vector (7 downto 0);\r
- signal dbg_s_oam_ce_rn_wn : out std_logic_vector (2 downto 0);\r
- signal dbg_s_oam_addr : out std_logic_vector (4 downto 0);\r
- signal dbg_s_oam_data : out std_logic_vector (7 downto 0);\r
- \r
- ppu_clk : in std_logic;\r
- mem_clk : in std_logic;\r
- rst_n : in std_logic;\r
-\r
- rd_n : out std_logic;\r
- wr_n : out std_logic;\r
- ale : out std_logic;\r
- vram_ad : inout std_logic_vector (7 downto 0);\r
- vram_a : out std_logic_vector (13 downto 8);\r
-\r
- --current drawing position 340 x 261\r
- cur_x : in std_logic_vector (8 downto 0);\r
- cur_y : in std_logic_vector (8 downto 0);\r
- r : out std_logic_vector (3 downto 0);\r
- g : out std_logic_vector (3 downto 0);\r
- b : out std_logic_vector (3 downto 0);\r
-\r
- ppu_ctrl : in std_logic_vector (7 downto 0);\r
- ppu_mask : in std_logic_vector (7 downto 0);\r
- read_status : in std_logic;\r
- ppu_status : out std_logic_vector (7 downto 0);\r
- ppu_scroll_x : in std_logic_vector (7 downto 0);\r
- ppu_scroll_y : in std_logic_vector (7 downto 0);\r
-\r
- r_nw : in std_logic;\r
- oam_bus_ce_n : in std_logic;\r
- plt_bus_ce_n : in std_logic;\r
- oam_plt_addr : in std_logic_vector (7 downto 0);\r
- oam_plt_data : inout std_logic_vector (7 downto 0);\r
- v_bus_busy_n : out std_logic\r
- );\r
-end ppu_render;\r
-\r
-architecture rtl of ppu_render is\r
-\r
-component counter_register\r
- generic (\r
- dsize : integer := 8;\r
- inc : integer := 1\r
- );\r
- port ( clk : in std_logic;\r
- rst_n : in std_logic;\r
- ce_n : in std_logic;\r
- we_n : in std_logic;\r
- d : in std_logic_vector(dsize - 1 downto 0);\r
- q : out std_logic_vector(dsize - 1 downto 0)\r
- );\r
-end component;\r
-\r
component shift_register\r
generic (\r
dsize : integer := 8;\r
);\r
end component;\r
\r
+--------- VGA screen constant -----------\r
+constant VGA_W : integer := 640;\r
+constant VGA_H : integer := 480;\r
+constant VGA_W_MAX : integer := 800;\r
+constant VGA_H_MAX : integer := 525;\r
+constant H_SP : integer := 95;\r
+constant H_BP : integer := 48;\r
+constant H_FP : integer := 15;\r
+constant V_SP : integer := 2;\r
+constant V_BP : integer := 33;\r
+constant V_FP : integer := 10;\r
+\r
--nes screen size is emulated to align with the vga timing...\r
constant X_SIZE : integer := 9;\r
constant dsize : integer := 8;\r
constant asize : integer := 14;\r
-constant HSCAN_MAX : integer := 341;\r
-constant VSCAN_MAX : integer := 262;\r
-constant HSCAN : integer := 257;\r
+constant HSCAN : integer := 256;\r
constant VSCAN : integer := 240;\r
-constant HSCAN_NEXT_START : integer := 320;\r
-constant HSCAN_NEXT_EXTRA : integer := 336;\r
+constant HSCAN_NEXT_START : integer := 377;\r
+constant VSCAN_NEXT_START : integer := 262;\r
+constant HSCAN_SPR_MAX : integer := 321;\r
+constant HSCAN_OAM_EVA_START : integer := 64;\r
\r
\r
constant PPUBNA : integer := 1; --base name address\r
constant ST_SP0 : integer := 6; --sprite 0 hits\r
constant ST_VBL : integer := 7; --vblank\r
\r
-subtype nes_color_data is std_logic_vector (11 downto 0);\r
-type nes_color_array is array (0 to 63) of nes_color_data;\r
---ref: http://hlc6502.web.fc2.com/NesPal2.htm\r
-constant nes_color_palette : nes_color_array := (\r
- conv_std_logic_vector(16#777#, 12), \r
- conv_std_logic_vector(16#20b#, 12), \r
- conv_std_logic_vector(16#20b#, 12), \r
- conv_std_logic_vector(16#61a#, 12), \r
- conv_std_logic_vector(16#927#, 12), \r
- conv_std_logic_vector(16#b13#, 12), \r
- conv_std_logic_vector(16#a30#, 12), \r
- conv_std_logic_vector(16#740#, 12), \r
- conv_std_logic_vector(16#450#, 12), \r
- conv_std_logic_vector(16#360#, 12), \r
- conv_std_logic_vector(16#360#, 12), \r
- conv_std_logic_vector(16#364#, 12), \r
- conv_std_logic_vector(16#358#, 12), \r
- conv_std_logic_vector(16#000#, 12), \r
- conv_std_logic_vector(16#000#, 12), \r
- conv_std_logic_vector(16#000#, 12),\r
- conv_std_logic_vector(16#bbb#, 12), \r
- conv_std_logic_vector(16#46f#, 12), \r
- conv_std_logic_vector(16#44f#, 12), \r
- conv_std_logic_vector(16#94f#, 12), \r
- conv_std_logic_vector(16#d4c#, 12), \r
- conv_std_logic_vector(16#d46#, 12), \r
- conv_std_logic_vector(16#e50#, 12), \r
- conv_std_logic_vector(16#c70#, 12), \r
- conv_std_logic_vector(16#880#, 12), \r
- conv_std_logic_vector(16#5a0#, 12), \r
- conv_std_logic_vector(16#4a1#, 12), \r
- conv_std_logic_vector(16#4a6#, 12), \r
- conv_std_logic_vector(16#49c#, 12), \r
- conv_std_logic_vector(16#000#, 12), \r
- conv_std_logic_vector(16#000#, 12), \r
- conv_std_logic_vector(16#000#, 12),\r
- conv_std_logic_vector(16#fff#, 12), \r
- conv_std_logic_vector(16#6af#, 12), \r
- conv_std_logic_vector(16#58f#, 12), \r
- conv_std_logic_vector(16#a7f#, 12), \r
- conv_std_logic_vector(16#f6f#, 12), \r
- conv_std_logic_vector(16#f6b#, 12), \r
- conv_std_logic_vector(16#f73#, 12), \r
- conv_std_logic_vector(16#fa0#, 12), \r
- conv_std_logic_vector(16#ed2#, 12), \r
- conv_std_logic_vector(16#9e0#, 12), \r
- conv_std_logic_vector(16#7f4#, 12), \r
- conv_std_logic_vector(16#7e9#, 12), \r
- conv_std_logic_vector(16#6de#, 12), \r
- conv_std_logic_vector(16#777#, 12), \r
- conv_std_logic_vector(16#000#, 12), \r
- conv_std_logic_vector(16#000#, 12),\r
- conv_std_logic_vector(16#fff#, 12), \r
- conv_std_logic_vector(16#9df#, 12), \r
- conv_std_logic_vector(16#abf#, 12), \r
- conv_std_logic_vector(16#cbf#, 12), \r
- conv_std_logic_vector(16#ebf#, 12), \r
- conv_std_logic_vector(16#fbe#, 12), \r
- conv_std_logic_vector(16#fcb#, 12), \r
- conv_std_logic_vector(16#fda#, 12), \r
- conv_std_logic_vector(16#ff9#, 12), \r
- conv_std_logic_vector(16#cf8#, 12), \r
- conv_std_logic_vector(16#afa#, 12), \r
- conv_std_logic_vector(16#afc#, 12), \r
- conv_std_logic_vector(16#aff#, 12), \r
- conv_std_logic_vector(16#aaa#, 12), \r
- conv_std_logic_vector(16#000#, 12), \r
- conv_std_logic_vector(16#000#, 12)\r
- );\r
+--------- signal declaration -----------\r
+signal vga_x : std_logic_vector (9 downto 0);\r
+signal vga_y : std_logic_vector (9 downto 0);\r
+signal x_res_n : std_logic;\r
+signal y_res_n : std_logic;\r
+signal y_en_n : std_logic;\r
+signal vga_clk_n : std_logic;\r
+\r
+signal emu_ppu_clk : std_logic;\r
+signal emu_ppu_clk_n : std_logic;\r
+signal count1 : std_logic_vector (0 downto 0);\r
+signal nes_x : std_logic_vector (8 downto 0);\r
+signal nes_y : std_logic_vector (8 downto 0);\r
\r
-signal ppu_clk_n : std_logic;\r
\r
---timing adjust\r
-signal bg_io_cnt : std_logic_vector(0 downto 0);\r
-signal spr_io_cnt : std_logic_vector(0 downto 0);\r
+------- 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
-signal cnt_x_res_n : std_logic;\r
-signal bg_cnt_res_n : std_logic;\r
-\r
--bg prefetch position (scroll + 16 cycle ahead of current pos)\r
--511 x 239 (or 255 x 479)\r
signal prf_x : std_logic_vector(X_SIZE - 1 downto 0);\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
constant EV_STAT_CP3 : std_logic_vector (2 downto 0) := "011";\r
constant EV_STAT_PRE_COMP : std_logic_vector (2 downto 0) := "100";\r
\r
-----------sprite registers.\r
-type oam_pin_array is array (0 to 7) of std_logic;\r
-type oam_reg_array is array (0 to 7) of std_logic_vector (dsize - 1 downto 0);\r
+----------sprite registers.\r
+type oam_pin_array is array (0 to 7) of std_logic;\r
+type oam_reg_array is array (0 to 7) of std_logic_vector (dsize - 1 downto 0);\r
+\r
+signal spr_x_we_n : oam_pin_array;\r
+signal spr_x_ce_n : oam_pin_array;\r
+signal spr_attr_we_n : oam_pin_array;\r
+signal spr_ptn_l_we_n : oam_pin_array;\r
+signal spr_ptn_h_we_n : oam_pin_array;\r
+signal spr_ptn_ce_n : oam_pin_array;\r
+\r
+signal spr_x_cnt : oam_reg_array;\r
+signal spr_attr : oam_reg_array;\r
+signal spr_ptn_l : oam_reg_array;\r
+signal spr_ptn_h : oam_reg_array;\r
+\r
+signal spr_y_we_n : std_logic;\r
+signal spr_tile_we_n : std_logic;\r
+signal spr_y_tmp : std_logic_vector (dsize - 1 downto 0);\r
+signal spr_tile_tmp : std_logic_vector (dsize - 1 downto 0);\r
+signal spr_ptn_in : std_logic_vector (dsize - 1 downto 0);\r
+\r
+signal sprite0_evaluated : std_logic;\r
+signal sprite0_displayed : std_logic;\r
+\r
+\r
+subtype nes_color_data is std_logic_vector (11 downto 0);\r
+type nes_color_array is array (0 to 63) of nes_color_data;\r
+--ref: http://hlc6502.web.fc2.com/NesPal2.htm\r
+constant nes_color_palette : nes_color_array := (\r
+ conv_std_logic_vector(16#777#, 12), \r
+ conv_std_logic_vector(16#20b#, 12), \r
+ conv_std_logic_vector(16#20b#, 12), \r
+ conv_std_logic_vector(16#61a#, 12), \r
+ conv_std_logic_vector(16#927#, 12), \r
+ conv_std_logic_vector(16#b13#, 12), \r
+ conv_std_logic_vector(16#a30#, 12), \r
+ conv_std_logic_vector(16#740#, 12), \r
+ conv_std_logic_vector(16#450#, 12), \r
+ conv_std_logic_vector(16#360#, 12), \r
+ conv_std_logic_vector(16#360#, 12), \r
+ conv_std_logic_vector(16#364#, 12), \r
+ conv_std_logic_vector(16#358#, 12), \r
+ conv_std_logic_vector(16#000#, 12), \r
+ conv_std_logic_vector(16#000#, 12), \r
+ conv_std_logic_vector(16#000#, 12),\r
+ conv_std_logic_vector(16#bbb#, 12), \r
+ conv_std_logic_vector(16#46f#, 12), \r
+ conv_std_logic_vector(16#44f#, 12), \r
+ conv_std_logic_vector(16#94f#, 12), \r
+ conv_std_logic_vector(16#d4c#, 12), \r
+ conv_std_logic_vector(16#d46#, 12), \r
+ conv_std_logic_vector(16#e50#, 12), \r
+ conv_std_logic_vector(16#c70#, 12), \r
+ conv_std_logic_vector(16#880#, 12), \r
+ conv_std_logic_vector(16#5a0#, 12), \r
+ conv_std_logic_vector(16#4a1#, 12), \r
+ conv_std_logic_vector(16#4a6#, 12), \r
+ conv_std_logic_vector(16#49c#, 12), \r
+ conv_std_logic_vector(16#000#, 12), \r
+ conv_std_logic_vector(16#000#, 12), \r
+ conv_std_logic_vector(16#000#, 12),\r
+ conv_std_logic_vector(16#fff#, 12), \r
+ conv_std_logic_vector(16#6af#, 12), \r
+ conv_std_logic_vector(16#58f#, 12), \r
+ conv_std_logic_vector(16#a7f#, 12), \r
+ conv_std_logic_vector(16#f6f#, 12), \r
+ conv_std_logic_vector(16#f6b#, 12), \r
+ conv_std_logic_vector(16#f73#, 12), \r
+ conv_std_logic_vector(16#fa0#, 12), \r
+ conv_std_logic_vector(16#ed2#, 12), \r
+ conv_std_logic_vector(16#9e0#, 12), \r
+ conv_std_logic_vector(16#7f4#, 12), \r
+ conv_std_logic_vector(16#7e9#, 12), \r
+ conv_std_logic_vector(16#6de#, 12), \r
+ conv_std_logic_vector(16#777#, 12), \r
+ conv_std_logic_vector(16#000#, 12), \r
+ conv_std_logic_vector(16#000#, 12),\r
+ conv_std_logic_vector(16#fff#, 12), \r
+ conv_std_logic_vector(16#9df#, 12), \r
+ conv_std_logic_vector(16#abf#, 12), \r
+ conv_std_logic_vector(16#cbf#, 12), \r
+ conv_std_logic_vector(16#ebf#, 12), \r
+ conv_std_logic_vector(16#fbe#, 12), \r
+ conv_std_logic_vector(16#fcb#, 12), \r
+ conv_std_logic_vector(16#fda#, 12), \r
+ conv_std_logic_vector(16#ff9#, 12), \r
+ conv_std_logic_vector(16#cf8#, 12), \r
+ conv_std_logic_vector(16#afa#, 12), \r
+ conv_std_logic_vector(16#afc#, 12), \r
+ conv_std_logic_vector(16#aff#, 12), \r
+ conv_std_logic_vector(16#aaa#, 12), \r
+ conv_std_logic_vector(16#000#, 12), \r
+ conv_std_logic_vector(16#000#, 12)\r
+ );\r
+\r
+---DE1 base clock 50 MHz\r
+---motones sim project uses following clock.\r
+--cpu clock = base clock / 24 = 2.08 MHz (480 ns / cycle)\r
+--ppu clock = base clock / 8\r
+--vga clock = base clock / 2\r
+\r
+begin\r
+ dbg_vga_x <= vga_x;\r
+ dbg_vga_y <= vga_y;\r
+ dbg_vga_clk <= vga_clk;\r
+ dbg_emu_ppu_clk <= emu_ppu_clk;\r
+\r
+ vga_clk_n <= not vga_clk;\r
+ \r
+ --vga position counter\r
+ vga_x_inst : counter_register generic map (10, 1)\r
+ port map (vga_clk, x_res_n, '0', '1', (others => '0'), vga_x);\r
+ vga_y_inst : counter_register generic map (10, 1)\r
+ port map (vga_clk, y_res_n, y_en_n, '1', (others => '0'), vga_y);\r
+ vga_out_p : process (rst_n, vga_clk)\r
+ begin\r
+ if (rst_n = '0') then\r
+ h_sync_n <= '0';\r
+ v_sync_n <= '0';\r
+ x_res_n <= '0';\r
+ y_res_n <= '0';\r
+ elsif (rising_edge(vga_clk)) then\r
+ --xmax = 799\r
+ if (vga_x = conv_std_logic_vector(VGA_W_MAX, 10)) then\r
+ x_res_n <= '0';\r
+ y_en_n <= '0';\r
+ --ymax=524\r
+ if (vga_y = conv_std_logic_vector(VGA_H_MAX, 10)) then\r
+ y_res_n <= '0';\r
+ else\r
+ y_res_n <= '1';\r
+ end if;\r
+ else\r
+ x_res_n <= '1';\r
+ y_en_n <= '1';\r
+ y_res_n <= '1';\r
+ end if;\r
\r
-signal spr_x_we_n : oam_pin_array;\r
-signal spr_x_ce_n : oam_pin_array;\r
-signal spr_attr_we_n : oam_pin_array;\r
-signal spr_ptn_l_we_n : oam_pin_array;\r
-signal spr_ptn_h_we_n : oam_pin_array;\r
-signal spr_ptn_ce_n : oam_pin_array;\r
+ --sync signal assert.\r
+ if (vga_x >= conv_std_logic_vector((VGA_W + H_FP) , 10) and \r
+ vga_x < conv_std_logic_vector((VGA_W + H_FP + H_SP) , 10)) then\r
+ h_sync_n <= '0';\r
+ else\r
+ h_sync_n <= '1';\r
+ end if;\r
\r
-signal spr_x_cnt : oam_reg_array;\r
-signal spr_attr : oam_reg_array;\r
-signal spr_ptn_l : oam_reg_array;\r
-signal spr_ptn_h : oam_reg_array;\r
+ if (vga_y >= conv_std_logic_vector((VGA_H + V_FP) , 10) and \r
+ vga_y < conv_std_logic_vector((VGA_H + V_FP + V_SP) , 10)) then\r
+ v_sync_n <= '0';\r
+ else\r
+ v_sync_n <= '1';\r
+ end if;\r
\r
-signal spr_y_we_n : std_logic;\r
-signal spr_tile_we_n : std_logic;\r
-signal spr_y_tmp : std_logic_vector (dsize - 1 downto 0);\r
-signal spr_tile_tmp : std_logic_vector (dsize - 1 downto 0);\r
-signal spr_ptn_in : std_logic_vector (dsize - 1 downto 0);\r
+ end if;\r
+ end process;\r
\r
+ --nes position counter\r
+ count1_inst : counter_register generic map (1, 1)\r
+ port map (vga_clk , rst_n, '0', '1', (others => '0'), count1);\r
+ emu_ppu_clk <= not count1(0);\r
+ emu_ppu_clk_n <= count1(0);\r
+ nes_x <= vga_x(9 downto 1);\r
+ nes_y <= vga_y(9 downto 1);\r
\r
-begin\r
- dbg_ppu_clk <= ppu_clk;\r
- dbg_nes_x <= cur_x;\r
- dbg_nes_y <= cur_y;\r
+------------------------------------------------------------------------\r
+------------------------------------------------------------------------\r
+------------------------------------------------------------------------\r
+------------------------------------------------------------------------\r
+------------------------ ppu render instance... ------------------------\r
+------------------------------------------------------------------------\r
+------------------------------------------------------------------------\r
+------------------------------------------------------------------------\r
+------------------------------------------------------------------------\r
+\r
+ dbg_nes_x <= nes_x;\r
+ dbg_nes_y <= nes_y;\r
dbg_disp_nt <= disp_nt;\r
dbg_disp_attr <= disp_attr;\r
dbg_disp_ptn_h <= disp_ptn_h;\r
dbg_p_oam_data <= p_oam_data;\r
dbg_s_oam_ce_rn_wn <= s_oam_ram_ce_n & s_oam_r_n & s_oam_w_n;\r
dbg_s_oam_addr <= s_oam_addr;\r
- dbg_s_oam_data <= p_oam_data;\r
+ dbg_s_oam_data <= s_oam_data;\r
\r
-\r
- ppu_clk_n <= not ppu_clk;\r
-\r
- ale <= bg_io_cnt(0) when ppu_mask(PPUSBG) = '1' and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
- (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or\r
- cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
- spr_io_cnt(0) when ppu_mask(PPUSSP) = '1' and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
- (cur_x > conv_std_logic_vector(256, X_SIZE) and \r
- cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\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
+ 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
-\r
- rd_n <= bg_io_cnt(0) when ppu_mask(PPUSBG) = '1' and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
- (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or\r
- cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
- spr_io_cnt(0) when ppu_mask(PPUSSP) = '1' and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
- (cur_x > conv_std_logic_vector(256, X_SIZE) and \r
- cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
+ rd_n <= \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 <= '1' when (ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else\r
+ wr_n <= \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 <= not bg_io_cnt(0) when ppu_mask(PPUSBG) = '1' and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
- (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or\r
- cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\r
- not spr_io_cnt(0) when ppu_mask(PPUSSP) = '1' and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
- (cur_x > conv_std_logic_vector(256, X_SIZE) and \r
- cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) else\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
- ah_oe_n <= '0' when (ppu_mask(PPUSBG) = '1' or ppu_mask(PPUSSP) = '1') and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) else\r
- '1';\r
+ ah_oe_n <= \r
+ '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
- bg_io_cnt_inst : counter_register generic map (1, 1)\r
- port map (ppu_clk, bg_cnt_res_n, '0', '1', (others => '0'), bg_io_cnt);\r
- spr_io_cnt_inst : counter_register generic map (1, 1)\r
- port map (ppu_clk, cnt_x_res_n, '0', '1', (others => '0'), spr_io_cnt);\r
-\r
- ---bg prefetch x pos is 16 + scroll cycle ahead of current pos.\r
- prf_x <= cur_x + ppu_scroll_x + "000010000" \r
- when cur_x < conv_std_logic_vector(HSCAN, X_SIZE) else\r
- cur_x + ppu_scroll_x + "010111011"; -- +16 -341\r
-\r
- prf_y <= cur_y + ppu_scroll_y\r
- when cur_x < conv_std_logic_vector(HSCAN, X_SIZE) and\r
- cur_y + ppu_scroll_y <\r
- conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE) else\r
- cur_y + ppu_scroll_y + "000000001" \r
- when cur_y + ppu_scroll_y <\r
- conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE) else\r
- "000000000"; \r
-\r
- nt_inst : d_flip_flop generic map(dsize)\r
- port map (ppu_clk_n, rst_n, '1', nt_we_n, vram_ad, disp_nt);\r
-\r
- at_inst : d_flip_flop generic map(dsize)\r
- port map (ppu_clk_n, rst_n, '1', attr_we_n, vram_ad, attr_val);\r
-\r
- disp_at_inst : shift_register generic map(dsize, 2)\r
- port map (ppu_clk_n, rst_n, attr_ce_n, disp_attr_we_n, attr_val, disp_attr);\r
-\r
- --chr rom data's bit is stored in opposite direction.\r
- --reverse bit when loading...\r
- ptn_l_in <= (vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) & \r
- vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7));\r
- ptn_h_in <= (vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) & \r
- vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7)) & \r
- disp_ptn_h (dsize downto 1);\r
-\r
- ptn_l_inst : d_flip_flop generic map(dsize)\r
- port map (ppu_clk_n, rst_n, '1', ptn_l_we_n, ptn_l_in, ptn_l_val);\r
-\r
- disp_ptn_l_in <= ptn_l_val & disp_ptn_l (dsize downto 1);\r
- disp_ptn_l_inst : shift_register generic map(dsize * 2, 1)\r
- port map (ppu_clk_n, rst_n, '0', ptn_h_we_n, disp_ptn_l_in, disp_ptn_l);\r
-\r
- ptn_h_inst : shift_register generic map(dsize * 2, 1)\r
- port map (ppu_clk_n, rst_n, '0', ptn_h_we_n, ptn_h_in, disp_ptn_h);\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
+ 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
+ -----------------------------------------\r
+ p_oam_ram_ce_n_in <= \r
+ '0' when oam_bus_ce_n = '0' else\r
+ '0' when 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)) and\r
+ nes_x > conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE) and \r
+ nes_x <= conv_std_logic_vector(HSCAN, X_SIZE) else\r
+ '1';\r
+ p_oam_addr <= oam_plt_addr when oam_bus_ce_n = '0' else\r
+ p_oam_addr_in when 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)) and\r
+ nes_x > conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE) and \r
+ nes_x <= conv_std_logic_vector(HSCAN, X_SIZE) else\r
+ (others => 'Z');\r
+ p_oam_r_n <= not r_nw when oam_bus_ce_n = '0' else\r
+ '0' when 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)) and\r
+ nes_x > conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE) and \r
+ nes_x <= conv_std_logic_vector(HSCAN, X_SIZE) else\r
+ '1';\r
+ p_oam_w_n <= r_nw when oam_bus_ce_n = '0' else\r
+ '1';\r
+ oam_d_buf_w : tri_state_buffer generic map (dsize)\r
+ port map (p_oam_w_n, oam_plt_data, p_oam_data);\r
+ oam_d_buf_r : tri_state_buffer generic map (dsize)\r
+ port map (p_oam_r_n, p_oam_data, oam_plt_data);\r
+\r
+ p_oam_ram_ctl : ram_ctrl\r
+ port map (mem_clk, p_oam_ram_ce_n_in, p_oam_r_n, p_oam_w_n, p_oam_ram_ce_n);\r
+ primary_oam_inst : ram generic map (dsize, dsize)\r
+ port map (mem_clk, p_oam_ram_ce_n, p_oam_r_n, p_oam_w_n, p_oam_addr, p_oam_data);\r
+\r
+ -----------------------------------------\r
+ ---secondary oam implementation\r
+ -----------------------------------------\r
+ --primary oam copy count\r
+ p_oam_cnt_inst : counter_register generic map (dsize, 4)\r
+ port map (emu_ppu_clk_n, p_oam_cnt_res_n, p_oam_cnt_ce_n, '1', (others => '0'), p_oam_cnt);\r
+ --primary oam copy count\r
+ s_oam_cnt_inst : counter_register generic map (5, 1)\r
+ port map (emu_ppu_clk_n, p_oam_cnt_res_n, s_oam_cnt_ce_n, '1', (others => '0'), s_oam_cnt);\r
+ --secondary oam pattern index.\r
+ s_oam_addr_cpy_inst : counter_register generic map (5, 1)\r
+ port map (emu_ppu_clk_n, p_oam_cnt_res_n, s_oam_addr_cpy_ce_n, \r
+ '1', (others => '0'), s_oam_addr_cpy);\r
+\r
+ s_oam_ram_ce_n_in <= \r
+ --enabled on clear only.\r
+ '0' when ppu_mask(PPUSSP) = '1' and nes_x(0) = '0' and\r
+ nes_x <= conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE) else\r
+ --enabled on copy only.\r
+ '0' when ppu_mask(PPUSSP) = '1' and nes_x(0) = '0' and\r
+ nes_x > conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE) and\r
+ nes_x <= conv_std_logic_vector(HSCAN, X_SIZE) else\r
+ --enabled all the time for reference.\r
+ '0' when ppu_mask(PPUSSP) = '1' and\r
+ nes_x > conv_std_logic_vector(HSCAN, X_SIZE) and\r
+ nes_x <= conv_std_logic_vector(HSCAN_SPR_MAX, X_SIZE) and\r
+ s_oam_addr_cpy_n = '0' else\r
+ '1';\r
+\r
+ s_oam_ram_ctl : ram_ctrl\r
+ port map (mem_clk, s_oam_ram_ce_n_in, s_oam_r_n, s_oam_w_n, s_oam_ram_ce_n);\r
+ secondary_oam_inst : ram generic map (5, dsize)\r
+ port map (mem_clk, s_oam_ram_ce_n, s_oam_r_n, s_oam_w_n, s_oam_addr, s_oam_data);\r
+\r
+ --sprite y tmp val\r
+ spr_y_inst : d_flip_flop generic map(dsize)\r
+ port map (emu_ppu_clk_n, p_oam_cnt_res_n, '1', spr_y_we_n, s_oam_data, spr_y_tmp);\r
+ --sprite pattern tmp val\r
+ spr_tile_inst : d_flip_flop generic map(dsize)\r
+ port map (emu_ppu_clk_n, p_oam_cnt_res_n, '1', spr_tile_we_n, s_oam_data, spr_tile_tmp);\r
+\r
+\r
+ --reverse bit when NOT SPRHFL is set (.nes file format bit endian).\r
+ spr_ptn_in <= vram_ad when spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRHFL) = '1' else\r
+ (vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) & \r
+ vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7));\r
+ --oam array instances...\r
+ spr_inst : for i in 0 to 7 generate\r
+ spr_x_inst : counter_register generic map(dsize, 16#ff#)\r
+ port map (emu_ppu_clk_n, rst_n, spr_x_ce_n(i), spr_x_we_n(i), s_oam_data, spr_x_cnt(i));\r
+\r
+ spr_attr_inst : d_flip_flop generic map(dsize)\r
+ port map (emu_ppu_clk_n, rst_n, '1', spr_attr_we_n(i), s_oam_data, spr_attr(i));\r
+\r
+ spr_ptn_l_inst : shift_register generic map(dsize, 1)\r
+ port map (emu_ppu_clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_l_we_n(i), spr_ptn_in, spr_ptn_l(i));\r
+\r
+ spr_ptn_h_inst : shift_register generic map(dsize, 1)\r
+ port map (emu_ppu_clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_h_we_n(i), spr_ptn_in, spr_ptn_h(i));\r
+ end generate;\r
+\r
+ -----------------------------------------\r
---palette ram\r
+ -----------------------------------------\r
r_n <= not r_nw;\r
\r
- plt_ram_ce_n_in <= ppu_clk when plt_bus_ce_n = '0' and r_nw = '0' else \r
+ plt_ram_ce_n_in <= '0' when plt_bus_ce_n = '0' and r_nw = '0' else \r
'0' when plt_bus_ce_n = '0' and r_nw = '1' else\r
'0' when ppu_mask(PPUSBG) = '1' and \r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and \r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) else\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and \r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) else\r
'1';\r
\r
plt_addr <= oam_plt_addr(4 downto 0) when plt_bus_ce_n = '0' else\r
"1" & spr_attr(0)(1 downto 0) & spr_ptn_h(0)(0) & spr_ptn_l(0)(0)\r
when ppu_mask(PPUSSP) = '1' and\r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
spr_x_cnt(0) = "00000000" and \r
(spr_ptn_h(0)(0) or spr_ptn_l(0)(0)) = '1' else\r
"1" & spr_attr(1)(1 downto 0) & spr_ptn_h(1)(0) & spr_ptn_l(1)(0)\r
when ppu_mask(PPUSSP) = '1' and\r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
spr_x_cnt(1) = "00000000" and \r
(spr_ptn_h(1)(0) or spr_ptn_l(1)(0)) = '1' else\r
"1" & spr_attr(2)(1 downto 0) & spr_ptn_h(2)(0) & spr_ptn_l(2)(0)\r
when ppu_mask(PPUSSP) = '1' and \r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
spr_x_cnt(2) = "00000000" and\r
(spr_ptn_h(2)(0) or spr_ptn_l(2)(0)) = '1' else\r
"1" & spr_attr(3)(1 downto 0) & spr_ptn_h(3)(0) & spr_ptn_l(3)(0)\r
when ppu_mask(PPUSSP) = '1' and\r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
spr_x_cnt(3) = "00000000" and\r
(spr_ptn_h(3)(0) or spr_ptn_l(3)(0)) = '1' else\r
"1" & spr_attr(4)(1 downto 0) & spr_ptn_h(4)(0) & spr_ptn_l(4)(0)\r
when ppu_mask(PPUSSP) = '1' and\r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
spr_x_cnt(4) = "00000000" and\r
(spr_ptn_h(4)(0) or spr_ptn_l(4)(0)) = '1' else\r
"1" & spr_attr(5)(1 downto 0) & spr_ptn_h(5)(0) & spr_ptn_l(5)(0)\r
when ppu_mask(PPUSSP) = '1' and\r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
spr_x_cnt(5) = "00000000" and\r
(spr_ptn_h(5)(0) or spr_ptn_l(5)(0)) = '1' else\r
"1" & spr_attr(6)(1 downto 0) & spr_ptn_h(6)(0) & spr_ptn_l(6)(0)\r
when ppu_mask(PPUSSP) = '1' and\r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
spr_x_cnt(6) = "00000000" and\r
(spr_ptn_h(6)(0) or spr_ptn_l(6)(0)) = '1' else\r
"1" & spr_attr(7)(1 downto 0) & spr_ptn_h(7)(0) & spr_ptn_l(7)(0)\r
when ppu_mask(PPUSSP) = '1' and\r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) and\r
spr_x_cnt(7) = "00000000" and\r
(spr_ptn_h(7)(0) or spr_ptn_l(7)(0)) = '1' else\r
"0" & disp_attr(1 downto 0) & disp_ptn_h(0) & disp_ptn_l(0) \r
- when ppu_mask(PPUSBG) = '1' and cur_y(4) = '0' and\r
+ when ppu_mask(PPUSBG) = '1' and nes_y(4) = '0' and\r
((disp_ptn_h(0) or disp_ptn_l(0)) = '1') and\r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) else\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) else\r
"0" & disp_attr(5 downto 4) & disp_ptn_h(0) & disp_ptn_l(0)\r
- when ppu_mask(PPUSBG) = '1' and cur_y(4) = '1' and\r
+ when ppu_mask(PPUSBG) = '1' and nes_y(4) = '1' and\r
((disp_ptn_h(0) or disp_ptn_l(0)) = '1') and\r
- (cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE)) else\r
+ (nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE)) else\r
---else: no output color >> universal bg color output.\r
--0x3f00 is the universal bg palette.\r
(others => '0'); \r
palette_inst : palette_ram generic map (5, dsize)\r
port map (mem_clk, plt_ram_ce_n, plt_r_n, plt_w_n, plt_addr, plt_data);\r
\r
- ---primary oam\r
- p_oam_ram_ce_n_in <= ppu_clk when oam_bus_ce_n = '0' and r_nw = '0' else\r
- '0' when oam_bus_ce_n = '0' and r_nw = '1' else\r
- '0' when ppu_mask(PPUSSP) = '1' and\r
- cur_x > conv_std_logic_vector(64, X_SIZE) and\r
- cur_x <= conv_std_logic_vector(256, X_SIZE) and\r
- p_oam_cnt_wrap_n = '1' else\r
- '1';\r
- p_oam_addr <= oam_plt_addr when oam_bus_ce_n = '0' else\r
- p_oam_addr_in when ppu_mask(PPUSSP) = '1' and \r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
- cur_x > conv_std_logic_vector(64, X_SIZE) and \r
- cur_x <= conv_std_logic_vector(256, X_SIZE) else\r
- (others => 'Z');\r
- p_oam_r_n <= not r_nw when oam_bus_ce_n = '0' else\r
- '0' when ppu_mask(PPUSSP) = '1' and \r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE)) and\r
- cur_x > conv_std_logic_vector(64, X_SIZE) and \r
- cur_x <= conv_std_logic_vector(256, X_SIZE) else\r
- '1';\r
- p_oam_w_n <= r_nw when oam_bus_ce_n = '0' else\r
- '1';\r
- oam_d_buf_w : tri_state_buffer generic map (dsize)\r
- port map (p_oam_w_n, oam_plt_data, p_oam_data);\r
- oam_d_buf_r : tri_state_buffer generic map (dsize)\r
- port map (p_oam_r_n, p_oam_data, oam_plt_data);\r
-\r
- p_oam_ram_ctl : ram_ctrl\r
- port map (mem_clk, p_oam_ram_ce_n_in, p_oam_r_n, p_oam_w_n, p_oam_ram_ce_n);\r
- primary_oam_inst : ram generic map (dsize, dsize)\r
- port map (mem_clk, p_oam_ram_ce_n, p_oam_r_n, p_oam_w_n, p_oam_addr, p_oam_data);\r
-\r
- ---secondary oam\r
- p_oam_cnt_inst : counter_register generic map (dsize, 4)\r
- port map (ppu_clk_n, p_oam_cnt_res_n, p_oam_cnt_ce_n, '1', (others => '0'), p_oam_cnt);\r
- s_oam_cnt_inst : counter_register generic map (5, 1)\r
- port map (ppu_clk_n, p_oam_cnt_res_n, s_oam_cnt_ce_n, '1', (others => '0'), s_oam_cnt);\r
- s_oam_addr_cpy_inst : counter_register generic map (5, 1)\r
- port map (ppu_clk_n, p_oam_cnt_res_n, s_oam_addr_cpy_ce_n, \r
- '1', (others => '0'), s_oam_addr_cpy);\r
-\r
- s_oam_ram_ce_n_in <= ppu_clk when ppu_mask(PPUSSP) = '1' and cur_x(0) = '1' and\r
- cur_x > "000000001" and\r
- cur_x <= conv_std_logic_vector(64, X_SIZE) else\r
- ppu_clk when ppu_mask(PPUSSP) = '1' and cur_x(0) = '1' and\r
- cur_x > conv_std_logic_vector(64, X_SIZE) and\r
- cur_x <= conv_std_logic_vector(256, X_SIZE) and\r
- p_oam_cnt_wrap_n = '1' else\r
- '0' when ppu_mask(PPUSSP) = '1' and\r
- cur_x > conv_std_logic_vector(256, X_SIZE) and\r
- cur_x <= conv_std_logic_vector(320, X_SIZE) and\r
- s_oam_addr_cpy_n = '0' else\r
- '1';\r
-\r
- s_oam_ram_ctl : ram_ctrl\r
- port map (mem_clk, s_oam_ram_ce_n_in, s_oam_r_n, s_oam_w_n, s_oam_ram_ce_n);\r
- secondary_oam_inst : ram generic map (5, dsize)\r
- port map (mem_clk, s_oam_ram_ce_n, s_oam_r_n, s_oam_w_n, s_oam_addr, s_oam_data);\r
-\r
- spr_y_inst : d_flip_flop generic map(dsize)\r
- port map (ppu_clk_n, p_oam_cnt_res_n, '1', spr_y_we_n, s_oam_data, spr_y_tmp);\r
- spr_tile_inst : d_flip_flop generic map(dsize)\r
- port map (ppu_clk_n, p_oam_cnt_res_n, '1', spr_tile_we_n, s_oam_data, spr_tile_tmp);\r
-\r
-\r
- --reverse bit when NOT SPRHFL is set (.nes file format bit endian).\r
- spr_ptn_in <= vram_ad when spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRHFL) = '1' else\r
- (vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) & \r
- vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7));\r
- --array instances...\r
- spr_inst : for i in 0 to 7 generate\r
- spr_x_inst : counter_register generic map(dsize, 16#ff#)\r
- port map (ppu_clk_n, rst_n, spr_x_ce_n(i), spr_x_we_n(i), s_oam_data, spr_x_cnt(i));\r
-\r
- spr_attr_inst : d_flip_flop generic map(dsize)\r
- port map (ppu_clk_n, rst_n, '1', spr_attr_we_n(i), s_oam_data, spr_attr(i));\r
-\r
- spr_ptn_l_inst : shift_register generic map(dsize, 1)\r
- port map (ppu_clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_l_we_n(i), spr_ptn_in, spr_ptn_l(i));\r
-\r
- spr_ptn_h_inst : shift_register generic map(dsize, 1)\r
- port map (ppu_clk_n, rst_n, spr_ptn_ce_n(i), spr_ptn_h_we_n(i), spr_ptn_in, spr_ptn_h(i));\r
- end generate;\r
-\r
- pos_p : process (rst_n, ppu_clk)\r
- begin\r
- if (rst_n = '0') then\r
- cnt_x_res_n <= '0';\r
- bg_cnt_res_n <= '0';\r
- elsif (ppu_clk'event and ppu_clk = '0') then\r
- if (cur_x = conv_std_logic_vector(HSCAN_MAX - 1, X_SIZE)) then\r
- --x pos reset.\r
- cnt_x_res_n <= '0';\r
- else\r
- cnt_x_res_n <= '1';\r
- end if;\r
-\r
- if (ppu_scroll_x(0) = '0' and cur_x = conv_std_logic_vector(HSCAN, X_SIZE)) then\r
- bg_cnt_res_n <= '0';\r
- elsif (ppu_scroll_x(0) = '1' and cur_x = conv_std_logic_vector(HSCAN - 1, X_SIZE)) then\r
- bg_cnt_res_n <= '0';\r
- else\r
- bg_cnt_res_n <= '1';\r
- end if;\r
- end if; --if (rst_n = '0') then\r
- end process;\r
-\r
- clk_p : process (rst_n, ppu_clk, read_status)\r
-\r
-procedure output_rgb is\r
-variable pl_addr : integer;\r
-variable pl_index : integer;\r
-variable dot_output : boolean;\r
-begin\r
- dot_output := false;\r
-\r
- --first show sprite.\r
- if (ppu_mask(PPUSSP) = '1') then\r
- for i in 0 to 7 loop\r
- if (spr_x_cnt(i) = "00000000") then\r
- if ((spr_ptn_h(i)(0) or spr_ptn_l(i)(0)) = '1') then\r
- dot_output := true;\r
- exit;\r
- end if;\r
- end if;\r
- end loop;\r
- end if;\r
-\r
- if (dot_output = true and ppu_mask(PPUSBG) = '1' and \r
- (disp_ptn_h(0) or disp_ptn_l(0)) = '1') then\r
- --raise sprite 0 hit.\r
- ppu_status(ST_SP0) <= '1';\r
- end if;\r
-\r
- --first color in the palette is transparent color.\r
- if (ppu_mask(PPUSBG) = '1' and dot_output = false and \r
- (disp_ptn_h(0) or disp_ptn_l(0)) = '1') then\r
- dot_output := true;\r
- end if;\r
-\r
- --if or if not bg/sprite is shown, output color anyway \r
- --sinse universal bg color is included..\r
- pl_index := conv_integer(plt_data(5 downto 0));\r
- b <= nes_color_palette(pl_index) (11 downto 8);\r
- g <= nes_color_palette(pl_index) (7 downto 4);\r
- r <= nes_color_palette(pl_index) (3 downto 0);\r
-end;\r
-procedure stop_rgb is\r
-begin\r
- b <= (others => '0');\r
- g <= (others => '0');\r
- r <= (others => '0');\r
-end;\r
-\r
+ -----------------------------------------\r
+ ---sprite main process\r
+ -----------------------------------------\r
+ spr_main_p : process (rst_n, emu_ppu_clk)\r
begin\r
if (rst_n = '0') then\r
- nt_we_n <= '1';\r
- ppu_status <= (others => '0');\r
+ s_oam_addr <= (others => 'Z');\r
s_oam_data <= (others => 'Z');\r
- stop_rgb;\r
- else\r
-\r
- if (ppu_clk'event and ppu_clk = '1') then\r
-\r
- --fetch bg pattern and display.\r
- if (ppu_mask(PPUSBG) = '1' and \r
- (cur_x <= conv_std_logic_vector(HSCAN, X_SIZE) or\r
- cur_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE))) then\r
- --visible area bg image\r
-\r
- d_print("*");\r
- d_print("cur_x: " & conv_hex16(conv_integer(cur_x)));\r
- d_print("cur_y: " & conv_hex16(conv_integer(cur_y)));\r
-\r
- ----fetch next tile byte.\r
- if (prf_x (2 downto 0) = "001") then\r
- --vram addr is incremented every 8 cycle.\r
- --name table at 0x2000\r
- vram_addr(9 downto 0) \r
- <= prf_y(dsize - 1 downto 3) \r
- & prf_x(dsize - 1 downto 3);\r
- vram_addr(asize - 1 downto 10) <= "10" & ppu_ctrl(PPUBNA downto 0) \r
- + ("000" & prf_x(dsize));\r
- ----fetch attr table byte.\r
- elsif (prf_x (4 downto 0) = "00011") then\r
- --attribute table is loaded every 32 cycle.\r
- --attr table at 0x23c0\r
- vram_addr(dsize - 1 downto 0) <= "11000000" +\r
- ("00" & prf_y(7 downto 5) & prf_x(7 downto 5));\r
- vram_addr(asize - 1 downto dsize) <= "10" &\r
- ppu_ctrl(PPUBNA downto 0) & "11"\r
- + ("000" & prf_x(dsize) & "00");\r
- ----fetch pattern table low byte.\r
- elsif (prf_x (2 downto 0) = "101") then\r
- --vram addr is incremented every 8 cycle.\r
- vram_addr <= "0" & ppu_ctrl(PPUBPA) & \r
- disp_nt(dsize - 1 downto 0) \r
- & "0" & prf_y(2 downto 0);\r
- ----fetch pattern table high byte.\r
- elsif (prf_x (2 downto 0) = "111") then\r
- --vram addr is incremented every 8 cycle.\r
- vram_addr <= "0" & ppu_ctrl(PPUBPA) & \r
- disp_nt(dsize - 1 downto 0) \r
- & "0" & prf_y(2 downto 0) + "00000000001000";\r
- end if;\r
-\r
- ----fetch next tile byte.\r
- if (prf_x (2 downto 0) = "010") then\r
- nt_we_n <= '0';\r
- else\r
- nt_we_n <= '1';\r
- end if;\r
-\r
- ----fetch attr table byte.\r
- if (prf_x (4 downto 0) = "00100") then\r
- attr_we_n <= '0';\r
- else\r
- attr_we_n <= '1';\r
- end if;\r
- if (prf_x (4 downto 0) = "10000") then\r
- disp_attr_we_n <= '0';\r
- else\r
- disp_attr_we_n <= '1';\r
- end if;\r
- ---attribute is shifted every 16 bit.\r
- if (prf_x (3 downto 0) = "0000") then\r
- attr_ce_n <= '0';\r
- else\r
- attr_ce_n <= '1';\r
- end if;\r
\r
- ----fetch pattern table low byte.\r
- if (prf_x (2 downto 0) = "110") then\r
- ptn_l_we_n <= '0';\r
- else\r
- ptn_l_we_n <= '1';\r
- end if;\r
+ s_oam_r_n <= '1';\r
+ s_oam_w_n <= '1';\r
+ p_oam_cnt_res_n <= '1';\r
+ p_oam_cnt_ce_n <= '1';\r
+ s_oam_cnt_ce_n <= '1';\r
+ oam_ev_status <= EV_STAT_COMP;\r
+ p_oam_addr_in <= (others => 'Z');\r
+\r
+ s_oam_addr_cpy_n <= '1';\r
+ spr_y_we_n <= '1';\r
+ spr_tile_we_n <= '1';\r
+ spr_x_we_n <= (others => '1');\r
+ spr_attr_we_n <= (others => '1');\r
+ spr_ptn_l_we_n <= (others => '1');\r
+ spr_ptn_h_we_n <= (others => '1');\r
+ s_oam_addr_cpy_ce_n <= '1';\r
+ spr_x_ce_n <= (others => '1');\r
+ spr_ptn_ce_n <= (others => '1');\r
+\r
+ sprite0_evaluated <= '0';\r
+ sprite0_displayed <= '0';\r
\r
- ----fetch pattern table high byte.\r
- if (prf_x (2 downto 0) = "000") then\r
- ptn_h_we_n <= '0';\r
- else\r
- ptn_h_we_n <= '1';\r
- end if;\r
+ else\r
\r
- end if;--if (ppu_mask(PPUSBG) = '1') and\r
+ if (rising_edge(emu_ppu_clk)) then\r
\r
--fetch sprite and display.\r
if (ppu_mask(PPUSSP) = '1' and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
- cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE))) then\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
+ nes_y = conv_std_logic_vector(VSCAN_NEXT_START, X_SIZE))) then\r
--secondary oam clear\r
- if (cur_x /= "000000000" and cur_x <= conv_std_logic_vector(64, X_SIZE)) then\r
- if (cur_x(0) = '0') then\r
- --write secondary oam on even cycle\r
- s_oam_r_n <= '1';\r
- s_oam_w_n <= '0';\r
- s_oam_addr <= cur_x(5 downto 1);\r
- s_oam_data <= (others => '1');\r
+ if (nes_x <= conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE)) then\r
+ if (nes_x(0) = '1') then\r
+ --odd cycle is set address.\r
+ --even cycle is write data.\r
+ s_oam_addr <= nes_x(5 downto 1);\r
end if;\r
+ s_oam_r_n <= '1';\r
+ s_oam_w_n <= '0';\r
+ s_oam_data <= (others => '1');\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
- elsif (cur_x > conv_std_logic_vector(64, X_SIZE) and \r
- cur_x <= conv_std_logic_vector(256, X_SIZE)) then\r
+ elsif (nes_x > conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE) and \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
- --old secondary sprite entry.\r
- if (p_oam_cnt = "00000000" and cur_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 (cur_x(0) = '1') then\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
- 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 (cur_y < "000000110" and p_oam_data <= cur_y + "000000001") or \r
- (cur_y >= "000000110" and p_oam_data <= cur_y + "000000001" and \r
- p_oam_data >= cur_y - "000000110") then\r
- oam_ev_status <= EV_STAT_CP1;\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
+ 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
- --copy remaining oam entry.\r
- p_oam_cnt_ce_n <= '1';\r
- else\r
- --goto next entry\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 (cur_x(0) = '1') then\r
+ end if;--if (nes_x(0) = '1') then\r
\r
--prepare for next step\r
s_oam_addr_cpy_n <= '1';\r
spr_ptn_h_we_n <= "11111111";\r
\r
--sprite pattern fetch\r
- elsif (cur_x > conv_std_logic_vector(256, X_SIZE) and \r
- cur_x <= conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) then\r
+ elsif (nes_x > conv_std_logic_vector(HSCAN, X_SIZE) and \r
+ nes_x <= conv_std_logic_vector(HSCAN_SPR_MAX, X_SIZE)) then\r
\r
s_oam_addr_cpy_n <= '0';\r
s_oam_r_n <= '0';\r
s_oam_addr <= s_oam_addr_cpy;\r
\r
----fetch y-cordinate from secondary oam\r
- if (cur_x (2 downto 0) = "001" ) then\r
+ if (nes_x (2 downto 0) = "001" ) then\r
s_oam_addr_cpy_ce_n <= '0';\r
spr_y_we_n <= '0';\r
else\r
end if;\r
\r
----fetch tile number\r
- if (cur_x (2 downto 0) = "010" ) then\r
+ if (nes_x (2 downto 0) = "010" ) then\r
spr_tile_we_n <= '0';\r
else\r
spr_tile_we_n <= '1';\r
end if;\r
\r
----fetch attribute\r
- if (cur_x (2 downto 0) = "011" ) then\r
+ if (nes_x (2 downto 0) = "011" ) then\r
spr_attr_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '0';\r
else\r
spr_attr_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '1';\r
- end if;--if (cur_x (2 downto 0) = "010" ) then\r
+ end if;--if (nes_x (2 downto 0) = "010" ) then\r
\r
----fetch x-cordinate\r
- if (cur_x (2 downto 0) = "100" ) then\r
+ if (nes_x (2 downto 0) = "100" ) then\r
s_oam_addr_cpy_ce_n <= '1';\r
spr_x_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '0';\r
else\r
end if;\r
\r
----fetch pattern table low byte.\r
- if (cur_x (2 downto 0) = "101" ) then\r
+ if (nes_x (2 downto 0) = "101" ) then\r
if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL) = '0') then\r
vram_addr <= "0" & ppu_ctrl(PPUSPA) & \r
spr_tile_tmp(dsize - 1 downto 0) & "0" & \r
- (cur_y(2 downto 0) + "001" - spr_y_tmp(2 downto 0));\r
+ (nes_y(2 downto 0) + "001" - spr_y_tmp(2 downto 0));\r
else\r
--flip sprite vertically.\r
vram_addr <= "0" & ppu_ctrl(PPUSPA) & \r
spr_tile_tmp(dsize - 1 downto 0) & "0" & \r
- (spr_y_tmp(2 downto 0) - cur_y(2 downto 0) - "010");\r
+ (spr_y_tmp(2 downto 0) - nes_y(2 downto 0) - "010");\r
end if;\r
end if;\r
\r
- if (cur_x (2 downto 0) = "110" ) then\r
+ if (nes_x (2 downto 0) = "110" ) then\r
spr_ptn_l_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '0';\r
else\r
spr_ptn_l_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '1';\r
end if;\r
\r
----fetch pattern table high byte.\r
- if (cur_x (2 downto 0) = "111" ) then\r
+ if (nes_x (2 downto 0) = "111" ) then\r
if (spr_attr(conv_integer(s_oam_addr_cpy(4 downto 2)))(SPRVFL) = '0') then\r
vram_addr <= "0" & ppu_ctrl(PPUSPA) & \r
spr_tile_tmp(dsize - 1 downto 0) & "0" & \r
- (cur_y(2 downto 0) + "001" - spr_y_tmp(2 downto 0))\r
+ (nes_y(2 downto 0) + "001" - spr_y_tmp(2 downto 0))\r
+ "00000000001000";\r
else\r
--flip sprite vertically.\r
vram_addr <= "0" & ppu_ctrl(PPUSPA) & \r
spr_tile_tmp(dsize - 1 downto 0) & "0" & \r
- (spr_y_tmp(2 downto 0) - cur_y(2 downto 0) - "010")\r
+ (spr_y_tmp(2 downto 0) - nes_y(2 downto 0) - "010")\r
+ "00000000001000";\r
end if;\r
end if;\r
\r
- if (cur_x (2 downto 0) = "000") then\r
+ if (nes_x (2 downto 0) = "000") then\r
spr_ptn_h_we_n(conv_integer(s_oam_addr_cpy(4 downto 2))) <= '0';\r
s_oam_addr_cpy_ce_n <= '0';\r
else\r
spr_ptn_h_we_n(conv_integer(s_oam_addr_cpy(4 downto 2) - "001")) <= '1';\r
end if;\r
+ \r
+ --check sprite 0 is used in the next line.\r
+ if (sprite0_evaluated = '1') then\r
+ sprite0_displayed <= '1';\r
+ end if;\r
\r
- elsif (cur_x > conv_std_logic_vector(320, X_SIZE)) then\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 (cur_x /= "000000000" and cur_x <= conv_std_logic_vector(64, X_SIZE))\r
+ end if;--if (nes_x <= conv_std_logic_vector(HSCAN_OAM_EVA_START, X_SIZE))\r
\r
--display sprite.\r
- if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE))) then\r
+ if ((nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE))) then\r
--start counter.\r
- if (cur_x = "000000000") then\r
+ if (nes_x = "000000000") then\r
spr_x_ce_n <= "00000000";\r
end if;\r
\r
else\r
spr_x_ce_n <= "11111111";\r
spr_ptn_ce_n <= "11111111";\r
- end if; --if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) \r
- end if; --if (ppu_mask(PPUSSP) = '1') then\r
+ end if; --if ((nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) \r
+ else\r
+ --sprite evaluation are cleared during the blank line.\r
+ sprite0_evaluated <= '0';\r
+ sprite0_displayed <= '0';\r
+ end if; --if (ppu_mask(PPUSSP) = '1') \r
+ --(nes_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
+ --nes_y = conv_std_logic_vector(VSCAN_NEXT_START, X_SIZE))) then\r
+ \r
+ end if; --if (rising_edge(emu_ppu_clk)) then\r
\r
+ end if;--if (rst_n = '0') then\r
+ end process;\r
+\r
+\r
+ output_p : process (rst_n, emu_ppu_clk)\r
+\r
+procedure output_rgb is\r
+variable pl_addr : integer;\r
+variable pl_index : integer;\r
+begin\r
+ if (rst_n = '0') then\r
+ b <= (others => '0');\r
+ g <= (others => '0');\r
+ r <= (others => '0');\r
+ else\r
+ if ((nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE))) then\r
+ --if or if not bg/sprite is shown, output color anyway \r
+ --sinse universal bg color is included..\r
+ pl_index := conv_integer(plt_data(5 downto 0));\r
+ b <= nes_color_palette(pl_index) (11 downto 8);\r
+ g <= nes_color_palette(pl_index) (7 downto 4);\r
+ r <= nes_color_palette(pl_index) (3 downto 0);\r
+ else\r
+ b <= (others => '0');\r
+ g <= (others => '0');\r
+ r <= (others => '0');\r
+ end if;\r
+ end if;\r
+end;\r
+\r
+procedure set_sp0_hit is\r
+begin\r
+ if (rst_n = '0') then\r
+ ppu_status(ST_SP0) <= '0';\r
+ else\r
+ if ((nes_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
+ (nes_y < conv_std_logic_vector(VSCAN, X_SIZE))) then\r
+ if (sprite0_displayed = '1' \r
+ and (ppu_mask(PPUSSP) = '1' and (spr_x_cnt(0) & (spr_ptn_h(0)(0) or spr_ptn_l(0)(0)) = "000000001"))\r
+ and (ppu_mask(PPUSBG) = '1' and ((disp_ptn_h(0) or disp_ptn_l(0)) = '1'))\r
+ ) then\r
+ --raise sprite 0 hit.\r
+ ppu_status(ST_SP0) <= '1';\r
+ end if;\r
+ else\r
+ ppu_status(ST_SP0) <= '0';\r
+ end if;\r
+ end if;\r
+end;\r
+\r
+ begin\r
+ if (rst_n = '0') then\r
+ ppu_status <= (others => '0');\r
+ else\r
+\r
+ if (rising_edge(emu_ppu_clk)) then\r
--output visible area only.\r
- if ((cur_x < conv_std_logic_vector(HSCAN, X_SIZE)) and\r
- (cur_y < conv_std_logic_vector(VSCAN, X_SIZE))) then\r
- --output image.\r
- output_rgb;\r
- else\r
- stop_rgb;\r
- end if;\r
+ output_rgb;\r
\r
--flag operation\r
- if ((cur_x = conv_std_logic_vector(1, X_SIZE)) and\r
- (cur_y = conv_std_logic_vector(VSCAN + 1, X_SIZE))) then\r
+ --TODO: sprite overflow is not inplemented!\r
+ ppu_status(ST_SOF) <= '0';\r
+ set_sp0_hit;\r
+\r
+ if ((nes_y > conv_std_logic_vector(VSCAN, X_SIZE))) then\r
--vblank start\r
ppu_status(ST_VBL) <= '1';\r
- elsif ((cur_x = conv_std_logic_vector(1, X_SIZE)) and\r
- (cur_y = conv_std_logic_vector(VSCAN_MAX - 1, X_SIZE))) then\r
- ppu_status(ST_SP0) <= '0';\r
+ else\r
--vblank end\r
ppu_status(ST_VBL) <= '0';\r
- --TODO: sprite overflow is not inplemented!\r
- ppu_status(ST_SOF) <= '0';\r
end if;\r
- end if; --if (clk'event and clk = '1') then\r
-\r
+ \r
-- if (read_status'event and read_status = '1') then\r
-- --reading ppu status clears vblank bit.\r
-- ppu_status(ST_VBL) <= '0';\r
-- end if;\r
\r
+ end if; --if (rising_edge(emu_ppu_clk)) then\r
end if;--if (rst_n = '0') then\r
end process;\r
\r
+-- ---bg prefetch x pos is 16 + scroll cycle ahead of current pos.\r
+-- prf_x <= nes_x + ppu_scroll_x + "000010000" \r
+-- when nes_x < conv_std_logic_vector(HSCAN, X_SIZE) else\r
+-- nes_x + ppu_scroll_x + "010111011"; -- +16 -341\r
+--\r
+-- prf_y <= nes_y + ppu_scroll_y\r
+-- when nes_x < conv_std_logic_vector(HSCAN, X_SIZE) and\r
+-- nes_y < conv_std_logic_vector(VSCAN, X_SIZE) else\r
+-- nes_y + ppu_scroll_y + "000000001" \r
+-- when nes_y < conv_std_logic_vector(VSCAN_NEXT_START, X_SIZE) else\r
+-- "000000000"; \r
+--\r
+-- nt_inst : d_flip_flop generic map(dsize)\r
+-- port map (ppu_clk_n, rst_n, '1', nt_we_n, vram_ad, disp_nt);\r
+--\r
+-- at_inst : d_flip_flop generic map(dsize)\r
+-- port map (ppu_clk_n, rst_n, '1', attr_we_n, vram_ad, attr_val);\r
+--\r
+-- disp_at_inst : shift_register generic map(dsize, 2)\r
+-- port map (ppu_clk_n, rst_n, attr_ce_n, disp_attr_we_n, attr_val, disp_attr);\r
+--\r
+-- --chr rom data's bit is stored in opposite direction.\r
+-- --reverse bit when loading...\r
+-- ptn_l_in <= (vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) & \r
+-- vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7));\r
+-- ptn_h_in <= (vram_ad(0) & vram_ad(1) & vram_ad(2) & vram_ad(3) & \r
+-- vram_ad(4) & vram_ad(5) & vram_ad(6) & vram_ad(7)) & \r
+-- disp_ptn_h (dsize downto 1);\r
+--\r
+-- ptn_l_inst : d_flip_flop generic map(dsize)\r
+-- port map (ppu_clk_n, rst_n, '1', ptn_l_we_n, ptn_l_in, ptn_l_val);\r
+--\r
+-- disp_ptn_l_in <= ptn_l_val & disp_ptn_l (dsize downto 1);\r
+-- disp_ptn_l_inst : shift_register generic map(dsize * 2, 1)\r
+-- port map (ppu_clk_n, rst_n, '0', ptn_h_we_n, disp_ptn_l_in, disp_ptn_l);\r
+--\r
+-- ptn_h_inst : shift_register generic map(dsize * 2, 1)\r
+-- port map (ppu_clk_n, rst_n, '0', ptn_h_we_n, ptn_h_in, disp_ptn_h);\r
+--\r
+\r
+\r
+\r
+\r
+-- nt_we_n <= '1';\r
+\r
+-- --fetch bg pattern and display.\r
+-- if (ppu_mask(PPUSBG) = '1' and \r
+-- (nes_x <= conv_std_logic_vector(HSCAN, X_SIZE) or\r
+-- nes_x > conv_std_logic_vector(HSCAN_NEXT_START, X_SIZE)) and\r
+-- (nes_y < conv_std_logic_vector(VSCAN, X_SIZE) or \r
+-- nes_y = conv_std_logic_vector(VSCAN_NEXT_START, X_SIZE))) then\r
+-- --visible area bg image\r
+--\r
+-- d_print("*");\r
+-- d_print("nes_x: " & conv_hex16(conv_integer(nes_x)));\r
+-- d_print("nes_y: " & conv_hex16(conv_integer(nes_y)));\r
+--\r
+-- ----fetch next tile byte.\r
+-- if (prf_x (2 downto 0) = "001") then\r
+-- --vram addr is incremented every 8 cycle.\r
+-- --name table at 0x2000\r
+-- vram_addr(9 downto 0) \r
+-- <= prf_y(dsize - 1 downto 3) \r
+-- & prf_x(dsize - 1 downto 3);\r
+-- vram_addr(asize - 1 downto 10) <= "10" & ppu_ctrl(PPUBNA downto 0) \r
+-- + ("000" & prf_x(dsize));\r
+-- ----fetch attr table byte.\r
+-- elsif (prf_x (4 downto 0) = "00011") then\r
+-- --attribute table is loaded every 32 cycle.\r
+-- --attr table at 0x23c0\r
+-- vram_addr(dsize - 1 downto 0) <= "11000000" +\r
+-- ("00" & prf_y(7 downto 5) & prf_x(7 downto 5));\r
+-- vram_addr(asize - 1 downto dsize) <= "10" &\r
+-- ppu_ctrl(PPUBNA downto 0) & "11"\r
+-- + ("000" & prf_x(dsize) & "00");\r
+-- ----fetch pattern table low byte.\r
+-- elsif (prf_x (2 downto 0) = "101") then\r
+-- --vram addr is incremented every 8 cycle.\r
+-- vram_addr <= "0" & ppu_ctrl(PPUBPA) & \r
+-- disp_nt(dsize - 1 downto 0) \r
+-- & "0" & prf_y(2 downto 0);\r
+-- ----fetch pattern table high byte.\r
+-- elsif (prf_x (2 downto 0) = "111") then\r
+-- --vram addr is incremented every 8 cycle.\r
+-- vram_addr <= "0" & ppu_ctrl(PPUBPA) & \r
+-- disp_nt(dsize - 1 downto 0) \r
+-- & "0" & prf_y(2 downto 0) + "00000000001000";\r
+-- end if;\r
+--\r
+-- ----fetch next tile byte.\r
+-- if (prf_x (2 downto 0) = "010") then\r
+-- nt_we_n <= '0';\r
+-- else\r
+-- nt_we_n <= '1';\r
+-- end if;\r
+--\r
+-- ----fetch attr table byte.\r
+-- if (prf_x (4 downto 0) = "00100") then\r
+-- attr_we_n <= '0';\r
+-- else\r
+-- attr_we_n <= '1';\r
+-- end if;\r
+-- if (prf_x (4 downto 0) = "10000") then\r
+-- disp_attr_we_n <= '0';\r
+-- else\r
+-- disp_attr_we_n <= '1';\r
+-- end if;\r
+-- ---attribute is shifted every 16 bit.\r
+-- if (prf_x (3 downto 0) = "0000") then\r
+-- attr_ce_n <= '0';\r
+-- else\r
+-- attr_ce_n <= '1';\r
+-- end if;\r
+--\r
+-- ----fetch pattern table low byte.\r
+-- if (prf_x (2 downto 0) = "110") then\r
+-- ptn_l_we_n <= '0';\r
+-- else\r
+-- ptn_l_we_n <= '1';\r
+-- end if;\r
+--\r
+-- ----fetch pattern table high byte.\r
+-- if (prf_x (2 downto 0) = "000") then\r
+-- ptn_h_we_n <= '0';\r
+-- else\r
+-- ptn_h_we_n <= '1';\r
+-- end if;\r
+--\r
+-- else\r
+-- nt_we_n <= '1';\r
+-- attr_we_n <= '1';\r
+-- disp_attr_we_n <= '1';\r
+-- attr_ce_n <= '1';\r
+-- ptn_l_we_n <= '1';\r
+-- ptn_h_we_n <= '1';\r
+-- end if;--if (ppu_mask(PPUSBG) = '1') and\r
+\r
end rtl;\r
\r