update T80 ip
[fpga-games] / galaxian / t80_ip / T80_ALU.vhd
index 86fddce7dd7b846baa48650f1167b367f45022d7..95c98dab9753aaf7a9a8ad54c49ffc2cad10be4e 100644 (file)
@@ -1,3 +1,13 @@
+-- ****
+-- T80(b) core. In an effort to merge and maintain bug fixes ....
+--
+--
+-- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle
+-- Ver 300 started tidyup
+-- MikeJ March 2005
+-- Latest version from www.fpgaarcade.com (original www.opencores.org)
+--
+-- ****
 --
 -- Z80 compatible microprocessor core
 --
 -- you have the latest version of this file.
 --
 -- The latest version of this file can be found at:
---     http://www.opencores.org/cvsweb.shtml/t80/
+--      http://www.opencores.org/cvsweb.shtml/t80/
 --
 -- Limitations :
 --
 -- File history :
 --
---     0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
+--      0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
 --
---     0238 : Fixed zero flag for 16 bit SBC and ADC
+--      0238 : Fixed zero flag for 16 bit SBC and ADC
 --
---     0240 : Added GB operations
+--      0240 : Added GB operations
 --
---     0242 : Cleanup
+--      0242 : Cleanup
 --
---     0247 : Cleanup
+--      0247 : Cleanup
 --
 
 library IEEE;
@@ -72,66 +82,77 @@ entity T80_ALU is
                Flag_S : integer := 7
        );
        port(
-               Arith16         : in std_logic;
-               Z16                     : in std_logic;
-               ALU_Op          : in std_logic_vector(3 downto 0);
-               IR                      : in std_logic_vector(5 downto 0);
-               ISet            : in std_logic_vector(1 downto 0);
-               BusA            : in std_logic_vector(7 downto 0);
-               BusB            : in std_logic_vector(7 downto 0);
-               F_In            : in std_logic_vector(7 downto 0);
-               Q                       : out std_logic_vector(7 downto 0);
-               F_Out           : out std_logic_vector(7 downto 0)
+               Arith16         : in  std_logic;
+               Z16             : in  std_logic;
+               ALU_Op          : in  std_logic_vector(3 downto 0);
+               IR              : in  std_logic_vector(5 downto 0);
+               ISet            : in  std_logic_vector(1 downto 0);
+               BusA            : in  std_logic_vector(7 downto 0);
+               BusB            : in  std_logic_vector(7 downto 0);
+               F_In            : in  std_logic_vector(7 downto 0);
+               Q               : out std_logic_vector(7 downto 0);
+               F_Out           : out std_logic_vector(7 downto 0)
        );
 end T80_ALU;
 
 architecture rtl of T80_ALU is
 
-       procedure AddSub(A : std_logic_vector;
-                                       B : std_logic_vector;
-                                       Sub : std_logic;
-                                       Carry_In : std_logic;
-                                       signal Res : out std_logic_vector;
-                                       signal Carry : out std_logic) is
-               variable B_i            : unsigned(A'length - 1 downto 0);
-               variable Res_i          : unsigned(A'length + 1 downto 0);
+       procedure AddSub(A        : std_logic_vector;
+                                        B        : std_logic_vector;
+                                        Sub      : std_logic;
+                                        Carry_In : std_logic;
+                         signal Res      : out std_logic_vector;
+                         signal Carry    : out std_logic) is
+
+               variable B_i          : unsigned(A'length - 1 downto 0);
+               variable Res_i        : unsigned(A'length + 1 downto 0);
        begin
                if Sub = '1' then
                        B_i := not unsigned(B);
                else
-                       B_i := unsigned(B);
+                       B_i :=     unsigned(B);
                end if;
+
                Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1");
                Carry <= Res_i(A'length + 1);
                Res <= std_logic_vector(Res_i(A'length downto 1));
        end;
 
        -- AddSub variables (temporary signals)
-       signal  UseCarry                : std_logic;
-       signal  Carry7_v                : std_logic;
-       signal  Overflow_v              : std_logic;
-       signal  HalfCarry_v             : std_logic;
-       signal  Carry_v                 : std_logic;
-       signal  Q_v                             : std_logic_vector(7 downto 0);
+       signal UseCarry                : std_logic;
+       signal Carry7_v                : std_logic;
+       signal Overflow_v              : std_logic;
+       signal HalfCarry_v             : std_logic;
+       signal Carry_v                 : std_logic;
+       signal Q_v                     : std_logic_vector(7 downto 0);
 
-       signal  BitMask                 : std_logic_vector(7 downto 0);
+       signal BitMask                 : std_logic_vector(7 downto 0);
 
 begin
 
        with IR(5 downto 3) select BitMask <= "00000001" when "000",
-                                                                       "00000010" when "001",
-                                                                       "00000100" when "010",
-                                                                       "00001000" when "011",
-                                                                       "00010000" when "100",
-                                                                       "00100000" when "101",
-                                                                       "01000000" when "110",
-                                                                       "10000000" when others;
+                                                                                 "00000010" when "001",
+                                                                                 "00000100" when "010",
+                                                                                 "00001000" when "011",
+                                                                                 "00010000" when "100",
+                                                                                 "00100000" when "101",
+                                                                                 "01000000" when "110",
+                                                                                 "10000000" when others;
 
        UseCarry <= not ALU_Op(2) and ALU_Op(0);
        AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v);
        AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v);
        AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v);
-       OverFlow_v <= Carry_v xor Carry7_v;
+
+       -- bug fix - parity flag is just parity for 8080, also overflow for Z80
+       process (Carry_v, Carry7_v, Q_v)
+       begin
+               if(Mode=2) then
+                       OverFlow_v <= not (Q_v(0) xor Q_v(1) xor Q_v(2) xor Q_v(3) xor
+                                          Q_v(4) xor Q_v(5) xor Q_v(6) xor Q_v(7));  else
+                       OverFlow_v <= Carry_v xor Carry7_v;
+               end if;
+       end process;
 
        process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
                variable Q_t : std_logic_vector(7 downto 0);
@@ -176,7 +197,7 @@ begin
                        if Q_t(7 downto 0) = "00000000" then
                                F_Out(Flag_Z) <= '1';
                                if Z16 = '1' then
-                                       F_Out(Flag_Z) <= F_In(Flag_Z);  -- 16 bit ADC,SBC
+                                       F_Out(Flag_Z) <= F_In(Flag_Z);      -- 16 bit ADC,SBC
                                end if;
                        else
                                F_Out(Flag_Z) <= '0';
@@ -347,5 +368,4 @@ begin
                end case;
                Q <= Q_t;
        end process;
-
 end;
Impressum, Datenschutz