OSDN Git Service

added sp.
[motonesfpga/motonesfpga.git] / simulation / cpu / mos6502.vhd
index a46cb68..9d3058a 100644 (file)
@@ -34,10 +34,30 @@ signal trigger_clk : std_logic;
 
 signal pc : std_logic_vector (asize - 1 downto 0);
 signal instruction : std_logic_vector (dsize - 1 downto 0);
+
+-- SR Flags (bit 7 to bit 0):
+--  7   N   ....    Negative
+--  6   V   ....    Overflow
+--  5   -   ....    ignored
+--  4   B   ....    Break
+--  3   D   ....    Decimal (use BCD for arithmetics)
+--  2   I   ....    Interrupt (IRQ disable)
+--  1   Z   ....    Zero
+--  0   C   ....    Carry
+constant st_N : integer := 7;
+constant st_V : integer := 6;
+constant st_B : integer := 4;
+constant st_D : integer := 3;
+constant st_I : integer := 2;
+constant st_Z : integer := 1;
+constant st_C : integer := 0;
+
 signal status_reg : std_logic_vector (dsize - 1 downto 0);
+
 signal dbus_buffer : std_logic_vector (dsize - 1 downto 0);
 signal reg_x : std_logic_vector (dsize - 1 downto 0);
 signal reg_y : std_logic_vector (dsize - 1 downto 0);
+signal sp : std_logic_vector (dsize - 1 downto 0);
 
 type dec_status is (reset0, reset1, reset2, reset3, reset4, reset5, 
                     fetch, decode, 
@@ -128,10 +148,12 @@ begin
     --addr(dsize - 1 downto 0) <= internal_abus_l;
 
     main_p : process (rst_n, set_clk, trigger_clk)
+    variable single_inst : boolean;
     begin
         if (rst_n'event and rst_n = '0') then
             d_print("reset negated.");
             cur_status <= reset0;
+            status_reg <= (others => '0');
             pc <= conv_std_logic_vector(16#8000#, asize);
         end if;
 
@@ -197,182 +219,202 @@ begin
             ---instruction consists of aaabbbcc form.
             if cur_status = decode then
                 d_print("inst: " & conv_hex8(conv_integer(instruction)));
-                if instruction (1 downto 0) = "01" then
-                    d_print("cc=01");
-
-                    ---bbb part format
-                    if instruction (4 downto 2) = "000" or 
-                        instruction (4 downto 2) = "001" or 
-                        instruction (4 downto 2) = "010" or 
-                        instruction (4 downto 2) = "011" or 
-                        instruction (4 downto 2) = "100" or 
-                        instruction (4 downto 2) = "101" or 
-                        instruction (4 downto 2) = "110" or 
-                        instruction (4 downto 2) = "111" then
 
-                        if instruction (7 downto 5) = "000" then
-                            d_print("ora");
-                        elsif instruction (7 downto 5) = "001" then
-                            d_print("and");
-                        elsif instruction (7 downto 5) = "010" then
-                            d_print("eor");
-                        elsif instruction (7 downto 5) = "011" then
-                            d_print("adc");
-                        elsif instruction (7 downto 5) = "100" then
-                            d_print("sta");
-                        elsif instruction (7 downto 5) = "101" then
-                            d_print("lda");
-                        elsif instruction (7 downto 5) = "110" then
-                            d_print("cmp");
-                        elsif instruction (7 downto 5) = "111" then
-                            d_print("sbc");
-                        else
-                            assert false 
-                                report ("unknow instruction") severity failure;
+                ---rest of single byte instruction.
+                single_inst := false;
+
+                if instruction = conv_std_logic_vector(16#8a#, dsize) then
+                    single_inst := true;
+                    d_print("txa");
+                elsif instruction = conv_std_logic_vector(16#9a#, dsize) then
+                    single_inst := true;
+                    d_print("txs");
+                    sp <= reg_x;
+                elsif instruction = conv_std_logic_vector(16#aa#, dsize) then
+                    single_inst := true;
+                    d_print("tax");
+                elsif instruction = conv_std_logic_vector(16#ba#, dsize) then
+                    single_inst := true;
+                    d_print("tsx");
+                elsif instruction = conv_std_logic_vector(16#ca#, dsize) then
+                    single_inst := true;
+                    d_print("dex");
+                elsif instruction = conv_std_logic_vector(16#ea#, dsize) then
+                    single_inst := true;
+                    d_print("nop");
+                elsif instruction = conv_std_logic_vector(16#08#, dsize) then
+                    single_inst := true;
+                    d_print("php");
+                elsif instruction = conv_std_logic_vector(16#28#, dsize) then
+                    single_inst := true;
+                    d_print("plp");
+                elsif instruction = conv_std_logic_vector(16#48#, dsize) then
+                    single_inst := true;
+                    d_print("pha");
+                elsif instruction = conv_std_logic_vector(16#68#, dsize) then
+                    single_inst := true;
+                    d_print("pla");
+                elsif instruction = conv_std_logic_vector(16#88#, dsize) then
+                    single_inst := true;
+                    d_print("dey");
+                elsif instruction = conv_std_logic_vector(16#a8#, dsize) then
+                    single_inst := true;
+                    d_print("tay");
+                elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
+                    single_inst := true;
+                    d_print("iny");
+                elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
+                    single_inst := true;
+                    d_print("inx");
+                elsif instruction = conv_std_logic_vector(16#18#, dsize) then
+                    single_inst := true;
+                    d_print("clc");
+                elsif instruction = conv_std_logic_vector(16#38#, dsize) then
+                    single_inst := true;
+                    d_print("sec");
+                elsif instruction = conv_std_logic_vector(16#58#, dsize) then
+                    single_inst := true;
+                    d_print("cli");
+                elsif instruction = conv_std_logic_vector(16#78#, dsize) then
+                    single_inst := true;
+                    d_print("sei");
+                    status_reg(st_I) <= '1';
+                elsif instruction = conv_std_logic_vector(16#98#, dsize) then
+                    single_inst := true;
+                    d_print("tya");
+                elsif instruction = conv_std_logic_vector(16#b8#, dsize) then
+                    single_inst := true;
+                    d_print("clv");
+                elsif instruction = conv_std_logic_vector(16#d8#, dsize) then
+                    single_inst := true;
+                    d_print("cld");
+                elsif instruction = conv_std_logic_vector(16#f8#, dsize) then
+                    single_inst := true;
+                    d_print("sed");
+                end if;
+
+                if single_inst then
+                    cur_status <= fetch;
+                    cur_mode <= ad_imp;
+                    addr <= (others => 'Z');
+                else
+
+                    if instruction (1 downto 0) = "01" then
+                        d_print("cc=01");
+
+                        ---bbb part format
+                        if instruction (4 downto 2) = "000" or 
+                            instruction (4 downto 2) = "001" or 
+                            instruction (4 downto 2) = "010" or 
+                            instruction (4 downto 2) = "011" or 
+                            instruction (4 downto 2) = "100" or 
+                            instruction (4 downto 2) = "101" or 
+                            instruction (4 downto 2) = "110" or 
+                            instruction (4 downto 2) = "111" then
+
+                            if instruction (7 downto 5) = "000" then
+                                d_print("ora");
+                            elsif instruction (7 downto 5) = "001" then
+                                d_print("and");
+                            elsif instruction (7 downto 5) = "010" then
+                                d_print("eor");
+                            elsif instruction (7 downto 5) = "011" then
+                                d_print("adc");
+                            elsif instruction (7 downto 5) = "100" then
+                                d_print("sta");
+                            elsif instruction (7 downto 5) = "101" then
+                                d_print("lda");
+                            elsif instruction (7 downto 5) = "110" then
+                                d_print("cmp");
+                            elsif instruction (7 downto 5) = "111" then
+                                d_print("sbc");
+                            else
+                                assert false 
+                                    report ("unknow instruction") severity failure;
+                            end if;
                         end if;
-                    else
-                        ---else single byte instruction.
-                        cur_status <= fetch;
-                        cur_mode <= ad_imp;
-                        addr <= (others => 'Z');
-                        if instruction = conv_std_logic_vector(16#8a#, dsize) then
-                            d_print("txa");
-                        elsif instruction = conv_std_logic_vector(16#9a#, dsize) then
-                            d_print("txs");
-                        elsif instruction = conv_std_logic_vector(16#aa#, dsize) then
-                            d_print("tax");
-                        elsif instruction = conv_std_logic_vector(16#ba#, dsize) then
-                            d_print("tsx");
-                        elsif instruction = conv_std_logic_vector(16#ca#, dsize) then
-                            d_print("dex");
-                        elsif instruction = conv_std_logic_vector(16#ea#, dsize) then
-                            d_print("nop");
+                    elsif instruction (1 downto 0) = "10" then
+                        d_print("cc=10");
+
+                        if instruction (4 downto 2) = "000" then
+                            cur_mode <= ad_imm;
+                            d_print("immediate");
+                            addr <= pc;
+                            pc <= pc + 1;
+                            cur_status <= exec0;
+                        elsif instruction (4 downto 2) = "001" then
+                            cur_mode <= ad_zp0;
+                        elsif instruction (4 downto 2) = "010" then
+                            cur_mode <= ad_acc;
+                        elsif instruction (4 downto 2) = "011" then
+                            cur_mode <= ad_abs0;
+                        elsif instruction (4 downto 2) = "101" then
+                            cur_mode <= ad_zpx0;
+                        elsif instruction (4 downto 2) = "111" then
+                            cur_mode <= ad_absx0;
                         else
-                            assert false 
-                                report ("unknow instruction") severity failure;
+                            cur_mode <= ad_unknown;
                         end if;
-                    end if;
-                elsif instruction (1 downto 0) = "10" then
-                    d_print("cc=10");
-
-                    if instruction (4 downto 2) = "000" then
-                        cur_mode <= ad_imm;
-                        d_print("immediate");
-                        addr <= pc;
-                        pc <= pc + 1;
-                        cur_status <= exec0;
-                    elsif instruction (4 downto 2) = "001" then
-                        cur_mode <= ad_zp0;
-                    elsif instruction (4 downto 2) = "010" then
-                        cur_mode <= ad_acc;
-                    elsif instruction (4 downto 2) = "011" then
-                        cur_mode <= ad_abs0;
-                    elsif instruction (4 downto 2) = "101" then
-                        cur_mode <= ad_zpx0;
-                    elsif instruction (4 downto 2) = "111" then
-                        cur_mode <= ad_absx0;
-                    else
-                        cur_mode <= ad_unknown;
-                    end if;
-
-                    if instruction (7 downto 5) = "000" then
-                        d_print("asl");
-                    elsif instruction (7 downto 5) = "001" then
-                        d_print("rol");
-                    elsif instruction (7 downto 5) = "010" then
-                        d_print("lsr");
-                    elsif instruction (7 downto 5) = "011" then
-                        d_print("ror");
-                    elsif instruction (7 downto 5) = "100" then
-                        d_print("stx");
-                    elsif instruction (7 downto 5) = "101" then
-                        d_print("ldx");
-                    elsif instruction (7 downto 5) = "110" then
-                        d_print("dec");
-                    elsif instruction (7 downto 5) = "111" then
-                        d_print("inc");
-                    else
-                        assert false 
-                            report ("unknow instruction") severity failure;
-                    end if;
 
-                elsif instruction (1 downto 0) = "00" then
-                    d_print("cc=00 group...");
-
-                    if instruction (4 downto 0) = "10000" then
-                        ---conditional branch instruction..
-                        
-                    ---bbb part format
-                    elsif instruction (4 downto 2) = "000" or 
-                        instruction (4 downto 2) = "001" or 
-                        instruction (4 downto 2) = "011" or 
-                        instruction (4 downto 2) = "101" or 
-                        instruction (4 downto 2) = "111" then
-
-                        if instruction (7 downto 5) = "001" then
-                            d_print("bit");
+                        if instruction (7 downto 5) = "000" then
+                            d_print("asl");
+                        elsif instruction (7 downto 5) = "001" then
+                            d_print("rol");
                         elsif instruction (7 downto 5) = "010" then
-                            d_print("jmp");
+                            d_print("lsr");
                         elsif instruction (7 downto 5) = "011" then
-                            d_print("jmp");
+                            d_print("ror");
                         elsif instruction (7 downto 5) = "100" then
-                            d_print("sty");
+                            d_print("stx");
                         elsif instruction (7 downto 5) = "101" then
-                            d_print("ldy");
+                            d_print("ldx");
                         elsif instruction (7 downto 5) = "110" then
-                            d_print("cpy");
+                            d_print("dec");
                         elsif instruction (7 downto 5) = "111" then
-                            d_print("cpx");
+                            d_print("inc");
                         else
                             assert false 
                                 report ("unknow instruction") severity failure;
                         end if;
-                        
-                    else
-                        ---else single byte instruction.
-                        cur_status <= fetch;
-                        cur_mode <= ad_imp;
-                        addr <= (others => 'Z');
-                        if instruction = conv_std_logic_vector(16#08#, dsize) then
-                            d_print("php");
-                        elsif instruction = conv_std_logic_vector(16#28#, dsize) then
-                            d_print("plp");
-                        elsif instruction = conv_std_logic_vector(16#48#, dsize) then
-                            d_print("pha");
-                        elsif instruction = conv_std_logic_vector(16#68#, dsize) then
-                            d_print("pla");
-                        elsif instruction = conv_std_logic_vector(16#88#, dsize) then
-                            d_print("dey");
-                        elsif instruction = conv_std_logic_vector(16#a8#, dsize) then
-                            d_print("tay");
-                        elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
-                            d_print("iny");
-                        elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
-                            d_print("inx");
-                        elsif instruction = conv_std_logic_vector(16#18#, dsize) then
-                            d_print("clc");
-                        elsif instruction = conv_std_logic_vector(16#38#, dsize) then
-                            d_print("sec");
-                        elsif instruction = conv_std_logic_vector(16#58#, dsize) then
-                            d_print("cli");
-                        elsif instruction = conv_std_logic_vector(16#78#, dsize) then
-                            d_print("sei");
-                        elsif instruction = conv_std_logic_vector(16#98#, dsize) then
-                            d_print("tya");
-                        elsif instruction = conv_std_logic_vector(16#b8#, dsize) then
-                            d_print("clv");
-                        elsif instruction = conv_std_logic_vector(16#d8#, dsize) then
-                            d_print("cld");
-                        elsif instruction = conv_std_logic_vector(16#f8#, dsize) then
-                            d_print("sed");
-                        else
-                            assert false 
-                                report ("unknow instruction") severity failure;
-                        end if;
-                    end if;
-                end if;
-            end if;
-        end if;
+
+                    elsif instruction (1 downto 0) = "00" then
+                        d_print("cc=00 group...");
+
+                        if instruction (4 downto 0) = "10000" then
+                            ---conditional branch instruction..
+                            
+                        ---bbb part format
+                        elsif instruction (4 downto 2) = "000" or 
+                            instruction (4 downto 2) = "001" or 
+                            instruction (4 downto 2) = "011" or 
+                            instruction (4 downto 2) = "101" or 
+                            instruction (4 downto 2) = "111" then
+
+                            if instruction (7 downto 5) = "001" then
+                                d_print("bit");
+                            elsif instruction (7 downto 5) = "010" then
+                                d_print("jmp");
+                            elsif instruction (7 downto 5) = "011" then
+                                d_print("jmp");
+                            elsif instruction (7 downto 5) = "100" then
+                                d_print("sty");
+                            elsif instruction (7 downto 5) = "101" then
+                                d_print("ldy");
+                            elsif instruction (7 downto 5) = "110" then
+                                d_print("cpy");
+                            elsif instruction (7 downto 5) = "111" then
+                                d_print("cpx");
+                            else
+                                assert false 
+                                    report ("unknow instruction") severity failure;
+                            end if;
+                        end if; --if instruction (4 downto 0) = "10000"
+                    end if; --if instruction (1 downto 0) = "01"
+
+                end if; --if single_inst
+
+            end if; --if cur_status = decode 
+        end if; --if (set_clk'event and set_clk = '1') 
 
         if (trigger_clk'event and trigger_clk = '1') then
             --d_print("_");