library ieee; use ieee.std_logic_1164.all; entity mos6502 is generic ( dsize : integer := 8; asize : integer :=16 ); port ( signal dbg_instruction : out std_logic_vector(7 downto 0); signal dbg_int_d_bus : out std_logic_vector(7 downto 0); signal dbg_exec_cycle : out std_logic_vector (5 downto 0); signal dbg_ea_carry : out std_logic; -- signal dbg_index_bus : out std_logic_vector(7 downto 0); -- signal dbg_acc_bus : out std_logic_vector(7 downto 0); signal dbg_status : out std_logic_vector(7 downto 0); signal dbg_pcl, dbg_pch, dbg_sp, dbg_x, dbg_y, dbg_acc : out std_logic_vector(7 downto 0); signal dbg_dec_oe_n : out std_logic; signal dbg_dec_val : out std_logic_vector (7 downto 0); signal dbg_int_dbus : out std_logic_vector (7 downto 0); -- signal dbg_status_val : out std_logic_vector (7 downto 0); signal dbg_stat_we_n : out std_logic; signal dbg_idl_h, dbg_idl_l, dbg_dbb_r, dbg_dbb_w : out std_logic_vector (7 downto 0); cpu_clk : in std_logic; --phi0 input pin. dl_cpu_clk : in std_logic; --phi1 delayed clock. rdy : in std_logic; rst_n : in std_logic; irq_n : in std_logic; nmi_n : in std_logic; r_nw : out std_logic; addr : out std_logic_vector ( asize - 1 downto 0); d_io : inout std_logic_vector ( dsize - 1 downto 0) ); end mos6502; architecture rtl of mos6502 is begin --set ppu value... set_ppu_p : process (cpu_clk, rst_n) use ieee.std_logic_arith.conv_std_logic_vector; variable init_step_cnt, plt_step_cnt, nt_step_cnt, spr_step_cnt, dma_step_cnt, scl_step_cnt, enable_ppu_step_cnt, nmi_step_cnt : integer; variable init_done : std_logic; variable global_step_cnt : integer; constant cpu_io_multi : integer := 3; --io happens every 4 cpu cycle. variable i, j : integer; variable ch : integer := 16#41# ; variable nmi_oam_x : integer range 0 to 255; variable nmi_scl_y : integer range 0 to 255; variable ref_cnt : integer range 0 to 120; procedure io_out (ad: in integer; dt : in integer) is begin r_nw <= '0'; addr <= conv_std_logic_vector(ad, 16); d_io <= conv_std_logic_vector(dt, 8); end; procedure io_brk is begin addr <= (others => 'Z'); d_io <= (others => 'Z'); r_nw <= 'Z'; end; procedure io_read (ad: in integer) is begin r_nw <= '1'; addr <= conv_std_logic_vector(ad, 16); d_io <= (others => 'Z'); end; begin if (rst_n = '0') then r_nw <= 'Z'; addr <= (others => 'Z'); d_io <= (others => 'Z'); init_done := '0'; global_step_cnt := 0; init_step_cnt := 0; plt_step_cnt := 0; nt_step_cnt := 0; spr_step_cnt := 0; dma_step_cnt := 0; scl_step_cnt := 0; enable_ppu_step_cnt := 0; nmi_step_cnt := 0; nmi_oam_x := 0; nmi_scl_y := 200; ref_cnt := 0; elsif (rising_edge(cpu_clk)) then if (rdy = '1') then if (init_done = '0') then if (global_step_cnt = 0) then --step0.0 = init ppu. if (init_step_cnt = 0 * cpu_io_multi) then --PPUCTRL=01 for test... io_out(16#2000#, 16#01#); elsif (init_step_cnt = 1 * cpu_io_multi) then --PPUMASK=02 io_out(16#2001#, 16#02#); elsif (init_step_cnt = 2 * cpu_io_multi) then --PPUCTRL=00 io_out(16#2000#, 16#00#); elsif (init_step_cnt = 3 * cpu_io_multi) then --PPUMASK=00 io_out(16#2001#, 16#00#); elsif (init_step_cnt = 4 * cpu_io_multi) then --ppuaddr io_out(16#2006#, 16#02#); elsif (init_step_cnt = 5 * cpu_io_multi) then io_out(16#2006#, 16#40#); elsif (init_step_cnt = 6 * cpu_io_multi) then --scroll io_out(16#2005#, 16#21#); elsif (init_step_cnt = 7 * cpu_io_multi) then io_out(16#2005#, 16#5#); else io_brk; if (init_step_cnt > 8 * cpu_io_multi) then global_step_cnt := global_step_cnt + 1; end if; end if; init_step_cnt := init_step_cnt + 1; elsif (global_step_cnt = 1) then --step0.1 = palette set. --palettes: --;;;bg palette -- .byte $0f, $00, $10, $20 -- .byte $0f, $04, $14, $24 -- .byte $0f, $08, $18, $28 -- .byte $0f, $0c, $1c, $2c --;;;spr palette -- .byte $0f, $00, $10, $20 -- .byte $0f, $06, $16, $26 -- .byte $0f, $08, $18, $28 -- .byte $0f, $0a, $1a, $2a if (plt_step_cnt = 0 * cpu_io_multi) then --set vram addr 3f00 io_out(16#2006#, 16#3f#); elsif (plt_step_cnt = 1 * cpu_io_multi) then io_out(16#2006#, 16#00#); elsif (plt_step_cnt = 2 * cpu_io_multi) then --set palette bg data io_out(16#2007#, 16#11#); elsif (plt_step_cnt = 3 * cpu_io_multi) then io_out(16#2007#, 16#01#); elsif (plt_step_cnt = 4 * cpu_io_multi) then io_out(16#2007#, 16#03#); elsif (plt_step_cnt = 5 * cpu_io_multi) then io_out(16#2007#, 16#13#); elsif (plt_step_cnt = 6 * cpu_io_multi) then io_out(16#2007#, 16#0f#); elsif (plt_step_cnt = 7 * cpu_io_multi) then io_out(16#2007#, 16#04#); elsif (plt_step_cnt = 8 * cpu_io_multi) then io_out(16#2007#, 16#14#); elsif (plt_step_cnt = 9 * cpu_io_multi) then io_out(16#2007#, 16#24#); elsif (plt_step_cnt = 10 * cpu_io_multi) then io_out(16#2007#, 16#0f#); elsif (plt_step_cnt = 11 * cpu_io_multi) then io_out(16#2007#, 16#08#); elsif (plt_step_cnt = 12 * cpu_io_multi) then io_out(16#2007#, 16#18#); elsif (plt_step_cnt = 13 * cpu_io_multi) then io_out(16#2007#, 16#28#); elsif (plt_step_cnt = 14 * cpu_io_multi) then io_out(16#2007#, 16#05#); elsif (plt_step_cnt = 15 * cpu_io_multi) then io_out(16#2007#, 16#0c#); elsif (plt_step_cnt = 16 * cpu_io_multi) then io_out(16#2007#, 16#1c#); elsif (plt_step_cnt = 17 * cpu_io_multi) then io_out(16#2007#, 16#2c#); elsif (plt_step_cnt = 18 * cpu_io_multi) then --below is sprite pallete io_out(16#2007#, 16#00#); elsif (plt_step_cnt = 19 * cpu_io_multi) then io_out(16#2007#, 16#24#); elsif (plt_step_cnt = 20 * cpu_io_multi) then io_out(16#2007#, 16#1b#); elsif (plt_step_cnt = 21 * cpu_io_multi) then io_out(16#2007#, 16#11#); elsif (plt_step_cnt = 22 * cpu_io_multi) then io_out(16#2007#, 16#00#); elsif (plt_step_cnt = 23 * cpu_io_multi) then io_out(16#2007#, 16#32#); elsif (plt_step_cnt = 24 * cpu_io_multi) then io_out(16#2007#, 16#16#); elsif (plt_step_cnt = 25 * cpu_io_multi) then io_out(16#2007#, 16#20#); elsif (plt_step_cnt = 26 * cpu_io_multi) then io_out(16#2007#, 16#00#); elsif (plt_step_cnt = 27 * cpu_io_multi) then io_out(16#2007#, 16#26#); elsif (plt_step_cnt = 28 * cpu_io_multi) then io_out(16#2007#, 16#01#); elsif (plt_step_cnt = 29 * cpu_io_multi) then io_out(16#2007#, 16#31#); else io_brk; if (plt_step_cnt > 30 * cpu_io_multi) then global_step_cnt := global_step_cnt + 1; end if; end if; plt_step_cnt := plt_step_cnt + 1; elsif (global_step_cnt = 2) then --step1 = name table set. if (nt_step_cnt = 0 * cpu_io_multi) then --set vram addr 2005 (first row, 6th col) io_out(16#2006#, 16#20#); elsif (nt_step_cnt = 1 * cpu_io_multi) then io_out(16#2006#, 16#03#); elsif (nt_step_cnt = 2 * cpu_io_multi) then --set name tbl data --0x44, 45, 45 = DEE io_out(16#2007#, 16#44#); elsif (nt_step_cnt = 3 * cpu_io_multi) then io_out(16#2007#, 16#45#); elsif (nt_step_cnt = 4 * cpu_io_multi) then io_out(16#2007#, 16#45#); elsif (nt_step_cnt = 5 * cpu_io_multi) then io_out(16#2006#, 16#20#); elsif (nt_step_cnt = 6 * cpu_io_multi) then io_out(16#2006#, 16#2a#); elsif (nt_step_cnt = 7 * cpu_io_multi) then io_out(16#2007#, 16#44#); elsif (nt_step_cnt = 8 * cpu_io_multi) then io_out(16#2006#, 16#24#); elsif (nt_step_cnt = 9 * cpu_io_multi) then io_out(16#2006#, 16#43#); elsif (nt_step_cnt = 10 * cpu_io_multi) then io_out(16#2007#, 16#6d#); elsif (nt_step_cnt = 11 * cpu_io_multi) then io_out(16#2007#, 16#6f#); elsif (nt_step_cnt = 12 * cpu_io_multi) then io_out(16#2007#, 16#74#); elsif (nt_step_cnt = 13 * cpu_io_multi) then io_out(16#2007#, 16#6f#); elsif (nt_step_cnt = 14 * cpu_io_multi) then io_out(16#2006#, 16#2e#); elsif (nt_step_cnt = 15 * cpu_io_multi) then io_out(16#2006#, 16#93#); elsif (nt_step_cnt = 16 * cpu_io_multi) then io_out(16#2007#, 16#59#); elsif (nt_step_cnt = 17 * cpu_io_multi) then io_out(16#2007#, 16#00#); else io_brk; if (nt_step_cnt > 4 * cpu_io_multi) then global_step_cnt := global_step_cnt + 1; end if; end if; nt_step_cnt := nt_step_cnt + 1; elsif (global_step_cnt = 3) then --step2 = sprite set. if (spr_step_cnt = 0) then --set sprite addr=00 (first sprite) io_out(16#2003#, 16#00#); elsif (spr_step_cnt = 1 * cpu_io_multi) then --set sprite data: y=02 io_out(16#2004#, 16#05#); elsif (spr_step_cnt = 2 * cpu_io_multi) then --tile=0x4d (ascii 'O') io_out(16#2004#, 16#4f#); elsif (spr_step_cnt = 3 * cpu_io_multi) then --set sprite attr=01 (palette 01) io_out(16#2004#, 16#01#); elsif (spr_step_cnt = 4 * cpu_io_multi) then --set sprite data: x=60 io_out(16#2004#, 16#3c#); elsif (spr_step_cnt = 5 * cpu_io_multi) then --set sprite data: y=50 io_out(16#2004#, 1); elsif (spr_step_cnt = 6 * cpu_io_multi) then --tile=0x4f (ascii 'M') io_out(16#2004#, 16#4d#); elsif (spr_step_cnt = 7 * cpu_io_multi) then --set sprite attr=02 io_out(16#2004#, 16#02#); elsif (spr_step_cnt = 8 * cpu_io_multi) then --set sprite data: x=100 io_out(16#2004#, 16#64#); elsif (spr_step_cnt = 9 * cpu_io_multi) then --set sprite data: y=60 io_out(16#2004#, 60); elsif (spr_step_cnt = 10 * cpu_io_multi) then --tile=0x4d (ascii 'P') io_out(16#2004#, 16#50#); elsif (spr_step_cnt = 11 * cpu_io_multi) then --set sprite attr=01 io_out(16#2004#, 16#01#); elsif (spr_step_cnt = 12 * cpu_io_multi) then --set sprite data: x=33 io_out(16#2004#, 16#21#); elsif (spr_step_cnt = 13 * cpu_io_multi) then --set sprite data: y=61 io_out(16#2004#, 16#3d#); elsif (spr_step_cnt = 14 * cpu_io_multi) then --tile=0x4d (ascii 'Q') io_out(16#2004#, 16#51#); elsif (spr_step_cnt = 15 * cpu_io_multi) then --set sprite attr=02 io_out(16#2004#, 16#02#); elsif (spr_step_cnt = 16 * cpu_io_multi) then --set sprite data: x=45 io_out(16#2004#, 45); else io_brk; if (spr_step_cnt > 8 * cpu_io_multi) then global_step_cnt := global_step_cnt + 2; end if; end if; spr_step_cnt := spr_step_cnt + 1; elsif (global_step_cnt = 4) then --step3 = dma set. for i in 0 to 64 loop j := i * 4; if (ch = 16#5b#) then ch := 16#41#; else ch := 16#41# + i; end if; --if (i < 64) then if (i < 10) then --set dma value on the ram. if (dma_step_cnt = (0 + j) * cpu_io_multi) then io_out(16#0200# + j, i); elsif (dma_step_cnt = (1 + j) * cpu_io_multi) then io_out(16#0201# + j, ch); elsif (dma_step_cnt = (2 + j) * cpu_io_multi) then io_out(16#0202# + j, 16#01#); elsif (dma_step_cnt = (3 + j) * cpu_io_multi) then io_out(16#0203# + j, j); elsif (dma_step_cnt = (0 + j) * cpu_io_multi + 1) or (dma_step_cnt = (1 + j) * cpu_io_multi + 1) or (dma_step_cnt = (2 + j) * cpu_io_multi + 1) or (dma_step_cnt = (3 + j) * cpu_io_multi + 1) then io_brk; end if; else if (dma_step_cnt = (0 + j) * cpu_io_multi) then --start dma io_out(16#4014#, 16#02#); elsif (dma_step_cnt = (0 + j) * cpu_io_multi + 1) then io_brk; elsif (dma_step_cnt = (0 + j) * cpu_io_multi + 2) then io_brk; global_step_cnt := global_step_cnt + 1; end if; end if; end loop; dma_step_cnt := dma_step_cnt + 1; elsif (global_step_cnt = 5) then --step4 = scroll test and ppu reg read test. if (scl_step_cnt = 0) then --x scroll pos=123 io_out(16#2005#, 11); elsif (scl_step_cnt = 1 * cpu_io_multi) then --y scroll pos=100 io_out(16#2005#, 0); elsif (scl_step_cnt = 2 * cpu_io_multi) then --read status reg. io_read(16#2002#); elsif (scl_step_cnt = 3 * cpu_io_multi) then --read vram nt0. io_out(16#2006#, 16#20#); elsif (scl_step_cnt = 4 * cpu_io_multi) then io_out(16#2006#, 16#03#); elsif (scl_step_cnt = 5 * cpu_io_multi) then io_read(16#2007#); elsif (scl_step_cnt = 6 * cpu_io_multi) then --pattern tbl. io_out(16#2006#, 16#04#); elsif (scl_step_cnt = 7 * cpu_io_multi) then io_out(16#2006#, 16#d1#); elsif (scl_step_cnt = 8 * cpu_io_multi) then io_read(16#2007#); elsif (scl_step_cnt = 9 * cpu_io_multi) then --attr tbl. io_out(16#2006#, 16#23#); elsif (scl_step_cnt = 10 * cpu_io_multi) then io_out(16#2006#, 16#c0#); elsif (scl_step_cnt = 11 * cpu_io_multi) then --set attr first. io_out(16#2007#, 16#5a#); elsif (scl_step_cnt = 12 * cpu_io_multi) then io_out(16#2006#, 16#23#); elsif (scl_step_cnt = 13 * cpu_io_multi) then io_out(16#2006#, 16#c0#); elsif (scl_step_cnt = 14 * cpu_io_multi) then io_read(16#2007#); elsif (scl_step_cnt = 15 * cpu_io_multi) then --read palette tbl. io_out(16#2006#, 16#3f#); elsif (scl_step_cnt = 16 * cpu_io_multi) then io_out(16#2006#, 16#11#); elsif (scl_step_cnt = 17 * cpu_io_multi) then io_read(16#2007#); else io_brk; if (scl_step_cnt > 17 * cpu_io_multi) then global_step_cnt := global_step_cnt + 1; end if; end if; scl_step_cnt := scl_step_cnt + 1; elsif (global_step_cnt = 6) then --final step = enable ppu. if (enable_ppu_step_cnt = 0 * cpu_io_multi) then --show bg --PPUMASK=1e (show bg and sprite) --PPUMASK=0e (show bg only) io_out(16#2001#, 16#1e#); elsif (enable_ppu_step_cnt = 1 * cpu_io_multi) then --enable nmi --PPUCTRL=80 io_out(16#2000#, 16#80#); else io_brk; if (enable_ppu_step_cnt > 1 * cpu_io_multi) then global_step_cnt := global_step_cnt + 1; end if; end if; enable_ppu_step_cnt := enable_ppu_step_cnt + 1; elsif (global_step_cnt = 7) then ----nmi tests..... if (nmi_n = '0') then if (nmi_step_cnt = 0 * cpu_io_multi) then --set sprite addr=00 (first sprite) io_out(16#2003#, 16#03#); elsif (nmi_step_cnt = 1 * cpu_io_multi) then --set sprite data: x=100 io_out(16#2004#, nmi_oam_x); elsif (nmi_step_cnt = 2 * cpu_io_multi) then --scroll x=0 -- io_out(16#2005#, nmi_scl_y); io_brk; elsif (nmi_step_cnt = 3 * cpu_io_multi) then --scroll y++ -- io_out(16#2005#, nmi_scl_y); io_brk; elsif (nmi_step_cnt = 4 * cpu_io_multi) then --set sprite addr=00 (first sprite) io_out(16#2003#, 16#04#); elsif (nmi_step_cnt = 5 * cpu_io_multi) then --set sprite data: x=100 io_out(16#2004#, nmi_oam_x); else if (ref_cnt = 0) then nmi_oam_x := nmi_oam_x + 1; end if; if (nmi_step_cnt mod 10 = 0) then nmi_scl_y := nmi_scl_y + 1; end if; io_brk; if (nmi_step_cnt > 5 * cpu_io_multi) then ref_cnt := ref_cnt + 1; global_step_cnt := global_step_cnt + 1; end if; end if; nmi_step_cnt := nmi_step_cnt + 1; end if; elsif (global_step_cnt = 8) then ----back to nmi tests..... if (nmi_n = '1') then nmi_step_cnt := 0; global_step_cnt := global_step_cnt - 1; end if; else io_brk; init_done := '1'; end if; end if;--if (init_done = '0') then else r_nw <= 'Z'; addr <= (others => 'Z'); d_io <= (others => 'Z'); end if;--if (rdy = '1') then end if; --if (rst_n = '0') then end process; end rtl; -----------dummy prg rom library ieee; use ieee.std_logic_1164.all; entity prg_rom is generic (abus_size : integer := 15; dbus_size : integer := 8); port ( clk : in std_logic; ce_n : in std_logic; --active low. addr : in std_logic_vector (abus_size - 1 downto 0); data : out std_logic_vector (dbus_size - 1 downto 0) ); end prg_rom; architecture rtl of prg_rom is begin data <= (others => 'Z'); end rtl;