OSDN Git Service

relative addressing mode and branch inst (bne) supported.
authorastoria-d <astoria-d@mail.goo.ne.jp>
Fri, 14 Jun 2013 06:03:17 +0000 (15:03 +0900)
committerastoria-d <astoria-d@mail.goo.ne.jp>
Fri, 14 Jun 2013 06:03:17 +0000 (15:03 +0900)
simulation/cpu/cpu_registers.vhd
simulation/cpu/decoder.vhd
simulation/cpu/mos6502.vhd

index 152ee28..fba8f56 100644 (file)
@@ -16,13 +16,17 @@ entity pc is
     port (  
             clk             : in std_logic;
             res_n           : in std_logic;
+            pc_type         : in std_logic;     --'0' pcl, '1' pch
             dbus_we_n       : in std_logic;
             abus_we_n       : in std_logic;
             dbus_oe_n       : in std_logic;
             abus_oe_n       : in std_logic;
             addr_inc_n      : in std_logic;
-            add_carry       : in std_logic;
-            inc_carry       : out std_logic;
+            addr_dec_n      : in std_logic;
+            add_carry       : out std_logic;
+            rel_we_n        : in std_logic;
+            rel_calc_n      : in std_logic;
+            rel_prev        : out std_logic;
             int_d_bus       : inout std_logic_vector (dsize - 1 downto 0);
             int_a_bus       : inout std_logic_vector (dsize - 1 downto 0)
         );
@@ -30,43 +34,95 @@ end pc;
 
 architecture rtl of pc is
 
+component dff
+    generic (
+            dsize : integer := 8
+            );
+    port (  
+            clk         : in std_logic;
+            we_n    : in std_logic;
+            oe_n    : in std_logic;
+            d       : in std_logic_vector (dsize - 1 downto 0);
+            q       : out std_logic_vector (dsize - 1 downto 0)
+        );
+end component;
+
 signal val : std_logic_vector (dsize - 1 downto 0);
+signal rel : std_logic_vector (dsize - 1 downto 0);
 
 begin
-    int_a_bus <= (val + add_carry) when 
-                    (abus_oe_n = '0' and add_carry = '1') else
-                  val when 
-                    (abus_oe_n = '0' and add_carry /= '1') else
+                ---increment & page moved case.
+    int_a_bus <= val + 1 when (abus_oe_n = '0' 
+                                and pc_type = '1' and addr_inc_n = '0') else
+                val when (abus_oe_n = '0') else
                 (others => 'Z');
-    int_d_bus <= (val + add_carry) when 
-                    (dbus_oe_n = '0' and add_carry = '1') else
-                  val when 
-                    (dbus_oe_n = '0' and add_carry /= '1') else
+
+                ---increment & page moved case.
+    int_d_bus <= val + 1 when (dbus_oe_n = '0' 
+                                and pc_type = '1' and addr_inc_n = '0') else
+                val when (dbus_oe_n = '0') else
                 (others => 'Z');
 
     set_p : process (clk, res_n)
     variable add_val : std_logic_vector(dsize downto 0);
+    variable dec_val : std_logic_vector(dsize downto 0);
     begin
         if (clk'event and clk = '1') then
+
             if (addr_inc_n = '0' and abus_we_n = '0') then
                 --case increment & address set
                 --for jmp op, abs xy not page crossing case.
                 add_val := ('0' & int_a_bus) + 1;
-                inc_carry <= add_val(dsize);
                 val <= add_val(dsize - 1 downto 0);
+                add_carry <= add_val(dsize);
+                rel_prev <= '0';
             elsif (addr_inc_n = '0') then
                 add_val := ('0' & val) + 1;
-                inc_carry <= add_val(dsize);
+                val <= add_val(dsize - 1 downto 0);
+                add_carry <= add_val(dsize);
+                rel_prev <= '0';
+            elsif (addr_dec_n = '0') then
+                dec_val := ('0' & val) - 1;
+                val <= dec_val(dsize - 1 downto 0);
+                add_carry <= '0';
+                rel_prev <= '0';
+            elsif (rel_calc_n = '0') then
+                add_val := ('0' & val) + ('0' & rel);
+                --relative addressing mode is signed operation.
+                if (rel(7) = '0') then
+                    --add positive
+                    add_carry <= add_val(dsize);
+                    rel_prev <= '1';
+                else
+                    --add negative
+                    add_carry <= '0';
+                    if (add_val(7) = '1') then
+                        --negative value > goto preveous page.
+                        rel_prev <= '1';
+                    else
+                        rel_prev <= '0';
+                    end if;
+                end if;
                 val <= add_val(dsize - 1 downto 0);
             elsif (abus_we_n = '0') then
                 val <= int_a_bus;
+                add_carry <= '0';
+                rel_prev <= '0';
             elsif (dbus_we_n = '0') then
                 val <= int_d_bus;
+                add_carry <= '0';
+                rel_prev <= '0';
+            else
+                rel_prev <= '0';
+                add_carry <= '0';
             end if;
         elsif (res_n'event and res_n = '0') then
             val <= conv_std_logic_vector(reset_addr, dsize);
         end if;
     end process;
+
+    rel_dff : dff generic map (dsize) 
+                    port map(clk, rel_we_n, '0', int_d_bus, rel);
 end rtl;
 
 ----------------------------------------
index 9a72e04..c51098b 100644 (file)
@@ -17,15 +17,18 @@ entity decoder is
             status_reg      : inout std_logic_vector (dsize - 1 downto 0);
             inst_we_n       : out std_logic;
             ad_oe_n         : out std_logic;
+            pcl_inc_n       : out std_logic;
             pcl_d_we_n      : out std_logic;
             pcl_a_we_n      : out std_logic;
             pcl_d_oe_n      : out std_logic;
             pcl_a_oe_n      : out std_logic;
+            pcl_rel_we_n    : out std_logic;
+            pcl_rel_calc_n  : out std_logic;
             pch_d_we_n      : out std_logic;
             pch_a_we_n      : out std_logic;
             pch_d_oe_n      : out std_logic;
             pch_a_oe_n      : out std_logic;
-            pc_inc_n        : out std_logic;
+            rel_pg_crs_n    : in std_logic;
             dbuf_int_oe_n   : out std_logic;
             dl_al_we_n      : out std_logic;
             dl_ah_we_n      : out std_logic;
@@ -186,7 +189,7 @@ begin
     pcl_a_oe_n <= '0';
     pch_a_oe_n <= '0';
     inst_we_n <= '0';
-    pc_inc_n <= '0';
+    pcl_inc_n <= '0';
 
     --disable the last opration pins.
     x_oe_n <= '1';
@@ -200,6 +203,8 @@ begin
     dbuf_int_oe_n <= '1';
     pch_d_we_n <= '1';
     pcl_a_we_n <= '1';
+    pcl_rel_we_n <= '1';
+    pcl_rel_calc_n <= '1';
     dl_al_we_n <= '1';
     dl_al_oe_n <= '1';
     dl_ah_oe_n <= '1';
@@ -224,7 +229,7 @@ procedure single_inst is
 begin
     pcl_a_oe_n <= '1';
     pch_a_oe_n <= '1';
-    pc_inc_n <= '1';
+    pcl_inc_n <= '1';
     next_cycle <= T0;
 end  procedure;
 
@@ -233,7 +238,7 @@ begin
     d_print("immediate");
     pcl_a_oe_n <= '0';
     pch_a_oe_n <= '0';
-    pc_inc_n <= '0';
+    pcl_inc_n <= '0';
     --send data from data bus buffer.
     --receiver is instruction dependent.
     dbuf_int_oe_n <= '0';
@@ -285,7 +290,7 @@ begin
     --fetch next opcode (abs low).
     pcl_a_oe_n <= '0';
     pch_a_oe_n <= '0';
-    pc_inc_n <= '0';
+    pcl_inc_n <= '0';
     --latch abs low data.
     dbuf_int_oe_n <= '0';
     dl_al_we_n <= '0';
@@ -298,7 +303,7 @@ begin
     dl_al_we_n <= '1';
 
     --latch abs hi data.
-    pc_inc_n <= '0';
+    pcl_inc_n <= '0';
     pcl_a_oe_n <= '0';
     pch_a_oe_n <= '0';
     dbuf_int_oe_n <= '0';
@@ -309,7 +314,7 @@ end  procedure;
 procedure abs_latch_out is
 begin
     --d_print("abs 4");
-    pc_inc_n <= '1';
+    pcl_inc_n <= '1';
     pcl_a_oe_n <= '1';
     pch_a_oe_n <= '1';
     dl_ah_we_n <= '1';
@@ -1040,7 +1045,7 @@ end  procedure;
                         --fetch opcode.
                         pcl_a_oe_n <= '0';
                         pch_a_oe_n <= '0';
-                        pc_inc_n <= '0';
+                        pcl_inc_n <= '0';
                         dbuf_int_oe_n <= '0';
                         --latch adl
                         dl_al_we_n <= '0';
@@ -1049,7 +1054,7 @@ end  procedure;
                         d_print("jsr 3");
                         pcl_a_oe_n <= '1';
                         pch_a_oe_n <= '1';
-                        pc_inc_n <= '1';
+                        pcl_inc_n <= '1';
                         dbuf_int_oe_n <= '1';
                         dl_al_we_n <= '1';
 
@@ -1118,7 +1123,7 @@ end  procedure;
                         --fetch next opcode (abs low).
                         pcl_a_oe_n <= '0';
                         pch_a_oe_n <= '0';
-                        pc_inc_n <= '0';
+                        pcl_inc_n <= '0';
                         --latch abs low data.
                         dbuf_int_oe_n <= '0';
                         dl_al_we_n <= '0';
@@ -1148,7 +1153,7 @@ end  procedure;
                         pcl_a_we_n <= '0';
                         pch_a_we_n <= '0';
                         inst_we_n <= '0';
-                        pc_inc_n <= '0';
+                        pcl_inc_n <= '0';
                         next_cycle <= T1;
                     end if;
 
@@ -1163,7 +1168,7 @@ end  procedure;
                     if exec_cycle = T1 then
                         pcl_a_oe_n <= '1';
                         pch_a_oe_n <= '1';
-                        pc_inc_n <= '1';
+                        pcl_inc_n <= '1';
 
                         --pop stack (decrement only)
                         sp_pop_n <= '0';
@@ -1206,7 +1211,7 @@ end  procedure;
                         d_print("rts 6");
 
                         --increment pc.
-                        pc_inc_n <= '0';
+                        pcl_inc_n <= '0';
                         next_cycle <= T0;
                     end if; --if exec_cycle = T1 then
 
@@ -1223,6 +1228,49 @@ end  procedure;
                     d_print("bmi");
                 elsif instruction = conv_std_logic_vector(16#d0#, dsize) then
                     d_print("bne");
+                    if exec_cycle = T1 then
+                        stat_dec_oe_n <= '0';
+                        pcl_inc_n <= '0';
+                        if status_reg(st_Z) /= '1' then
+                            d_print("get rel");
+
+                            pcl_a_oe_n <= '0';
+                            pch_a_oe_n <= '0';
+                            dbuf_int_oe_n <= '0';
+                            --latch rel value.
+                            pcl_rel_we_n <= '0';
+                            next_cycle <= T2;
+                        else
+                            d_print("no branch");
+                            next_cycle <= T0;
+                        end if;
+                    elsif exec_cycle = T2 then
+                        d_print("rel ea");
+                        pcl_inc_n <= '1';
+                        pcl_a_oe_n <= '0';
+                        pch_a_oe_n <= '0';
+                        dbuf_int_oe_n <= '1';
+                        pcl_rel_we_n <= '1';
+
+                        --calcurate relative addr.
+                        pcl_rel_calc_n <= '0';
+                        next_cycle <= T3;
+                    elsif exec_cycle = T3 then
+                        --pcl_a_oe_n <= '0';
+                        --pch_a_oe_n <= '0';
+                        pcl_rel_calc_n <= '1';
+
+                        if rel_pg_crs_n = '0' then
+                        --page crossed. start from fetch.
+                            next_cycle <= T0;
+                        else
+                            --no page boundary. 
+                            --fetch cycle is done.
+                            fetch_inst;
+                            next_cycle <= T1;
+                        end if;
+                    end if;
+
                 elsif instruction = conv_std_logic_vector(16#10#, dsize) then
                     d_print("bpl");
                 elsif instruction = conv_std_logic_vector(16#50#, dsize) then
@@ -1241,11 +1289,13 @@ end  procedure;
                 pcl_a_we_n <= '1';
                 pcl_d_oe_n <= '1';
                 pcl_a_oe_n <= '1';
+                pcl_rel_we_n <= '1';
+                pcl_rel_calc_n <= '1';
                 pch_d_we_n <= '1';
                 pch_a_we_n <= '1';
                 pch_d_oe_n <= '1';
                 pch_a_oe_n <= '1';
-                pc_inc_n <= '1';
+                pcl_inc_n <= '1';
                 inst_we_n <= '1';
                 dbuf_int_oe_n <= '1';
                 dl_al_we_n <= '1';
index 442faa3..7b2a6df 100644 (file)
@@ -29,13 +29,17 @@ architecture rtl of mos6502 is
         port (  
                 clk             : in std_logic;
                 res_n           : in std_logic;
+                pc_type         : in std_logic;
                 dbus_we_n       : in std_logic;
                 abus_we_n       : in std_logic;
                 dbus_oe_n       : in std_logic;
                 abus_oe_n       : in std_logic;
                 addr_inc_n      : in std_logic;
-                add_carry       : in std_logic;
-                inc_carry       : out std_logic;
+                addr_dec_n      : in std_logic;
+                add_carry       : out std_logic;
+                rel_we_n        : in std_logic;
+                rel_calc_n      : in std_logic;
+                rel_prev        : out std_logic;
                 int_d_bus       : inout std_logic_vector (dsize - 1 downto 0);
                 int_a_bus       : inout std_logic_vector (dsize - 1 downto 0)
             );
@@ -55,15 +59,18 @@ architecture rtl of mos6502 is
                 status_reg      : inout std_logic_vector (dsize - 1 downto 0);
                 inst_we_n       : out std_logic;
                 ad_oe_n         : out std_logic;
+                pcl_inc_n       : out std_logic;
                 pcl_d_we_n      : out std_logic;
                 pcl_a_we_n      : out std_logic;
                 pcl_d_oe_n      : out std_logic;
                 pcl_a_oe_n      : out std_logic;
+                pcl_rel_we_n    : out std_logic;
+                pcl_rel_calc_n  : out std_logic;
                 pch_d_we_n      : out std_logic;
                 pch_a_we_n      : out std_logic;
                 pch_d_oe_n      : out std_logic;
                 pch_a_oe_n      : out std_logic;
-                pc_inc_n        : out std_logic;
+                rel_pg_crs_n    : in std_logic;
                 dbuf_int_oe_n   : out std_logic;
                 dl_al_we_n      : out std_logic;
                 dl_ah_we_n      : out std_logic;
@@ -250,18 +257,23 @@ architecture rtl of mos6502 is
     signal set_clk : std_logic;
     signal trigger_clk : std_logic;
 
+    signal pcl_inc_n : std_logic;
     signal pcl_d_we_n : std_logic;
     signal pcl_a_we_n : std_logic;
     signal pcl_d_oe_n : std_logic;
     signal pcl_a_oe_n : std_logic;
+    signal pcl_rel_we_n : std_logic;
+    signal pcl_rel_calc_n : std_logic;
     signal pch_d_we_n : std_logic;
     signal pch_a_we_n : std_logic;
     signal pch_d_oe_n : std_logic;
     signal pch_a_oe_n : std_logic;
-    signal pc_inc_n : std_logic;
     signal pc_cry : std_logic;
     signal pc_cry_n : std_logic;
     signal dum_terminate : std_logic := 'Z';
+    signal pc_rel_prev : std_logic;
+    signal pc_rel_prev_n : std_logic;
+    signal rel_pg_crs_n : std_logic;
 
     signal inst_we_n : std_logic;
     signal dbuf_r_nw : std_logic;
@@ -345,15 +357,18 @@ begin
                     status_reg, 
                     inst_we_n, 
                     ad_oe_n, 
+                    pcl_inc_n, 
                     pcl_d_we_n, 
                     pcl_a_we_n, 
                     pcl_d_oe_n, 
                     pcl_a_oe_n,
+                    pcl_rel_we_n,
+                    pcl_rel_calc_n,
                     pch_d_we_n, 
                     pch_a_we_n, 
                     pch_d_oe_n, 
                     pch_a_oe_n,
-                    pc_inc_n, 
+                    rel_pg_crs_n,
                     dbuf_int_oe_n, 
                     dl_al_we_n, 
                     dl_ah_we_n, 
@@ -414,13 +429,17 @@ begin
                     internal_dbus, ea_base_l, ea_base_h);
 
     pc_l : pc generic map (dsize, 16#00#) 
-            port map(trigger_clk, rst_n, 
+            port map(trigger_clk, rst_n, '0', 
                     pcl_d_we_n, pcl_a_we_n, pcl_d_oe_n, pcl_a_oe_n, 
-                    pc_inc_n, '0', pc_cry, internal_dbus, internal_abus_l);
+                    pcl_inc_n, '1', pc_cry, 
+                    pcl_rel_we_n, pcl_rel_calc_n, pc_rel_prev,  
+                    internal_dbus, internal_abus_l);
     pc_h : pc generic map (dsize, 16#80#) 
-            port map(trigger_clk, rst_n, 
+            port map(trigger_clk, rst_n, '1', 
                     pch_d_we_n, pch_a_we_n, pch_d_oe_n, pch_a_oe_n, 
-                    pc_cry_n, pc_cry, dum_terminate, internal_dbus, internal_abus_h);
+                    pc_cry_n, pc_rel_prev_n, dum_terminate, 
+                    '1', '1', dum_terminate, 
+                    internal_dbus, internal_abus_h);
 
     instruction_register : dff generic map (dsize) 
             port map(trigger_clk, inst_we_n, '0', d_io, instruction);
@@ -458,9 +477,14 @@ begin
     phi2 <= not input_clk;
     set_clk <= input_clk;
     trigger_clk <= not input_clk;
+
     pc_cry_n <= not pc_cry;
+    pc_rel_prev_n <= not pc_rel_prev;
     r_nw <= dbuf_r_nw;
 
+    --branch instruction page crossed?
+    rel_pg_crs_n <= pc_cry nand pc_rel_prev;
+
     --adh output is controlled by decoder.
     adh_buffer : tsb generic map (dsize)
             port map (ad_oe_n, internal_abus_h, addr(asize - 1 downto dsize));