X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/fpga-games/blobdiff_plain/0840cca68ecfa59ea10e60db9c02dbbd081215e7..be8a9b96554636d47b7d5113b4c4aab3b6ebb8e3:/galaxian/t80_ip/T80_ALU.vhd diff --git a/galaxian/t80_ip/T80_ALU.vhd b/galaxian/t80_ip/T80_ALU.vhd index 86fddce..95c98da 100644 --- a/galaxian/t80_ip/T80_ALU.vhd +++ b/galaxian/t80_ip/T80_ALU.vhd @@ -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 -- @@ -38,21 +48,21 @@ -- 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;