OSDN Git Service

merged master
[motonesfpga/motonesfpga.git] / de1_nes / cpu / alu.vhd
index 9270cc6..fb369ec 100644 (file)
@@ -116,11 +116,14 @@ end component;
 --------- signals for address calucuration ----------
 signal al_buf_we_n : std_logic;
 signal ah_buf_we_n : std_logic;
+signal tmp_buf_we_n : std_logic;
 
 signal al_reg_in : std_logic_vector (dsize - 1 downto 0);
 signal ah_reg_in : std_logic_vector (dsize - 1 downto 0);
+signal tmp_reg_in : std_logic_vector (dsize - 1 downto 0);
 signal al_reg : std_logic_vector (dsize - 1 downto 0);
 signal ah_reg : std_logic_vector (dsize - 1 downto 0);
+signal tmp_reg : std_logic_vector (dsize - 1 downto 0);
 
 
 signal a_sel : std_logic_vector (1 downto 0);
@@ -161,6 +164,8 @@ begin
             port map(clk, '1', '1', al_buf_we_n, al_reg_in, al_reg);
     ah_dff : d_flip_flop generic map (dsize) 
             port map(clk, '1', '1', ah_buf_we_n, ah_reg_in, ah_reg);
+    tmp_dff : d_flip_flop generic map (dsize) 
+            port map(clk, '1', '1', tmp_buf_we_n, tmp_reg_in, tmp_reg);
 
     --pcl carry flag set.
     pcl_carry_reg_in <= addr_c when pcl_inc_n = '0' else
@@ -199,13 +204,12 @@ begin
                     pcl_inc_n, pch_inc_n, sp_oe_n, sp_push_n, sp_pop_n,
                     abs_xy_n, pg_next_n, zp_n, zp_xy_n, rel_calc_n, 
                     indir_n, indir_x_n, indir_y_n, 
-                    index_bus, bal, bah, addr_c_in, addr_out, addr_c,
+                    index_bus, bal, bah,
 
                     --for arithmatic operation.
                     arith_en_n,
                     instruction, exec_cycle, int_d_bus, acc_out, 
-                    carry_in, n, z, c, v,
-                    arith_reg, arith_reg_out, alu_out, d_out
+                    carry_in, n, z, c, v
                     )
 
 constant ADDR_ADC    : std_logic_vector (1 downto 0) := "00";
@@ -260,6 +264,7 @@ end procedure;
     ----- address calcuration -----
     -------------------------------
     if (pcl_inc_n = '0') then
+        ea_carry <= '0';
         a_sel <= ADDR_INC;
         addr1 <= bal;
         addr_back <= addr_out;
@@ -280,6 +285,7 @@ end procedure;
         abh <= bah;
 
     elsif (pch_inc_n = '0') then
+        ea_carry <= '0';
         a_sel <= ADDR_INC;
         addr1 <= bah;
         addr_back <= addr_out;
@@ -292,6 +298,7 @@ end procedure;
     elsif (sp_oe_n = '0') then
         --stack operation...
         abh <= "00000001";
+        ea_carry <= '0';
 
         if (sp_push_n /= '0' and sp_pop_n /= '0') then
             abl <= bal;
@@ -323,6 +330,7 @@ end procedure;
             end if;
         end if;
     elsif (zp_n = '0') then
+        ea_carry <= '0';
         if (zp_xy_n <= '0') then
             a_sel <= ADDR_ADC;
             addr1 <= bal;
@@ -404,14 +412,62 @@ end procedure;
         a_sel <= ADDR_INC;
         abl <= addr_out;
 
-        --TODO: must handle page crossing case...
         ea_carry <= addr_c;
 
     elsif (indir_x_n = '0') then
+        if (exec_cycle = T2) then
+            ---input is IAL, but this cycle doesn't do anything....
+            abh <= "00000000";
+            abl <= bal;
+
+            --save base addr.
+            tmp_buf_we_n <= '0';
+            tmp_reg_in <= bal;
+        elsif (exec_cycle = T3) then
+
+            ---add x reg.
+            a_sel <= ADDR_ADC;
+            addr1 <= tmp_reg;
+            addr2 <= index_bus;
+            addr_c_in <= '0';
+
+            --save base addr.
+            tmp_buf_we_n <= '0';
+            tmp_reg_in <= addr_out;
+
+            --output @IAL+x
+            abh <= "00000000";
+            abl <= addr_out;
+
+            ---save BAL.
+            al_buf_we_n <= '0';
+            al_reg_in <= int_d_bus;
+
+        elsif (exec_cycle = T4) then
+            al_buf_we_n <= '1';
+            tmp_buf_we_n <= '1';
+
+            ---increment.
+            a_sel <= ADDR_INC;
+            addr1 <= tmp_reg;
+
+            --output @IAL+x
+            abh <= "00000000";
+            abl <= addr_out;
+
+            ---save BAH.
+            ah_buf_we_n <= '0';
+            ah_reg_in <= int_d_bus;
+        elsif (exec_cycle = T5 or exec_cycle = T0) then
+            ah_buf_we_n <= '1';
+
+            --output ah/al reg.
+            abh <= ah_reg;
+            abl <= al_reg;
+        end if; -- if (exec_cycle = T2) then
 
     elsif (indir_y_n = '0') then
 
-        if (clk = '0') then
         if (exec_cycle = T2) then
             ---input is IAL.
             abh <= "00000000";
@@ -420,22 +476,30 @@ end procedure;
             ---save BAL.
             al_buf_we_n <= '0';
             al_reg_in <= int_d_bus;
+            ea_carry <= '0';
+
+            --get next address (IAL + 1)
+            a_sel <= ADDR_INC;
+            addr1 <= bal;
+            tmp_buf_we_n <= '0';
+            tmp_reg_in <= addr_out;
 
         elsif (exec_cycle = T3) then
             al_buf_we_n <= '1';
+            tmp_buf_we_n <= '1';
 
             abh <= "00000000";
 
             --input is IAL + 1
-            a_sel <= ADDR_INC;
-            addr1 <= bal;
-            abl <= addr_out;
+            abl <= tmp_reg;
 
             ---save BAH.
             ah_buf_we_n <= '0';
             ah_reg_in <= int_d_bus;
+            ea_carry <= addr_c;
 
         elsif (exec_cycle = T4) then
+            ah_buf_we_n <= '1';
 
             ---add y reg.
             a_sel <= ADDR_ADC;
@@ -453,20 +517,34 @@ end procedure;
             ---save the address.
             al_buf_we_n <= '0';
             al_reg_in <= addr_out;
-            ah_buf_we_n <= '0';
-            ah_reg_in <= ah_reg;
-        elsif (exec_cycle = T0 and pg_next_n = '0') then
+            tmp_buf_we_n <= '0';
+            tmp_reg_in <= ah_reg;
+        elsif (exec_cycle = T5 or exec_cycle = T0) then
+            al_buf_we_n <= '1';
+            tmp_buf_we_n <= '1';
+            ea_carry <= '0';
+
+            if (pg_next_n = '0') then
+                a_sel <= ADDR_INC;
+                addr1 <= tmp_reg;
+                ---next page.
+                abh <= addr_out;
+                abl <= al_reg;
+            else
+                abh <= tmp_reg;
+                abl <= al_reg;
+            end if;
+        else
+            al_buf_we_n <= '1';
+            ah_buf_we_n <= '1';
+            tmp_buf_we_n <= '1';
             ea_carry <= '0';
-            a_sel <= ADDR_INC;
-            addr1 <= ah_reg;
-            ---next page.
-            abh <= addr_out;
-            abl <= al_reg;
         end if; -- if (exec_cycle = T2) then
-        end if; --if (clk = '0') then
     else
         al_buf_we_n <= '1';
         ah_buf_we_n <= '1';
+        tmp_buf_we_n <= '1';
+        ea_carry <= '0';
 
         abl <= bal;
         abh <= bah;
@@ -625,17 +703,24 @@ end procedure;
             --011      absolute
             --101      zero page,X
             --111      absolute,X
-            if ((exec_cycle = T3 and instruction (4 downto 2) = "001") or 
+            if ((exec_cycle = T2 and instruction (4 downto 2) = "001") or 
+                (exec_cycle = T3 and instruction (4 downto 2) = "011") or 
+                (exec_cycle = T3 and instruction (4 downto 2) = "101") or 
+                (exec_cycle = T4 and instruction (4 downto 2) = "111")) then
+                arith_buf_we_n <= '0';
+                arith_reg_in <= int_d_bus;
+
+            elsif ((exec_cycle = T3 and instruction (4 downto 2) = "001") or 
                 (exec_cycle = T4 and instruction (4 downto 2) = "011") or 
                 (exec_cycle = T4 and instruction (4 downto 2) = "101") or 
                 (exec_cycle = T5 and instruction (4 downto 2) = "111")) then
                 --first cycle. keep input variable.
                 --d_print("inc first.");
-                arith_buf_we_n <= '0';
+                arith_buf_we_n <= '1';
+
                 arith_buf_oe_n <= '1';
                 d_oe_n <= '1';
 
-                arith_reg_in <= int_d_bus;
                 d1 <= arith_reg;
             else
                 --second cycle read from register, output modified data.