⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t80_alu.vhd

📁 DE1-FPGA-Board
💻 VHD
字号:
---- Z80 compatible microprocessor core---- Version : 0247---- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)---- All rights reserved---- Redistribution and use in source and synthezised forms, with or without-- modification, are permitted provided that the following conditions are met:---- Redistributions of source code must retain the above copyright notice,-- this list of conditions and the following disclaimer.---- Redistributions in synthesized form must reproduce the above copyright-- notice, this list of conditions and the following disclaimer in the-- documentation and/or other materials provided with the distribution.---- Neither the name of the author nor the names of other contributors may-- be used to endorse or promote products derived from this software without-- specific prior written permission.---- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE-- POSSIBILITY OF SUCH DAMAGE.---- Please report bugs to the author, but before you do so, please-- make sure that this is not a derivative work and that-- 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/---- Limitations :---- File history :----	0214 : Fixed mostly flags, only the block instructions now fail the zex regression test----	0238 : Fixed zero flag for 16 bit SBC and ADC----	0240 : Added GB operations----	0242 : Cleanup----	0247 : Cleanup--library IEEE;use IEEE.std_logic_1164.all;use IEEE.numeric_std.all;entity T80_ALU is	generic(		Mode : integer := 0;		Flag_C : integer := 0;		Flag_N : integer := 1;		Flag_P : integer := 2;		Flag_X : integer := 3;		Flag_H : integer := 4;		Flag_Y : integer := 5;		Flag_Z : integer := 6;		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)	);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);	begin		if Sub = '1' then			B_i := not unsigned(B);		else			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	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;	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;	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);		variable DAA_Q : unsigned(8 downto 0);	begin		Q_t := "--------";		F_Out <= F_In;		DAA_Q := "---------";		case ALU_Op is		when "0000" | "0001" |  "0010" | "0011" | "0100" | "0101" | "0110" | "0111" =>			F_Out(Flag_N) <= '0';			F_Out(Flag_C) <= '0';			case ALU_OP(2 downto 0) is			when "000" | "001" => -- ADD, ADC				Q_t := Q_v;				F_Out(Flag_C) <= Carry_v;				F_Out(Flag_H) <= HalfCarry_v;				F_Out(Flag_P) <= OverFlow_v;			when "010" | "011" | "111" => -- SUB, SBC, CP				Q_t := Q_v;				F_Out(Flag_N) <= '1';				F_Out(Flag_C) <= not Carry_v;				F_Out(Flag_H) <= not HalfCarry_v;				F_Out(Flag_P) <= OverFlow_v;			when "100" => -- AND				Q_t(7 downto 0) := BusA and BusB;				F_Out(Flag_H) <= '1';			when "101" => -- XOR				Q_t(7 downto 0) := BusA xor BusB;				F_Out(Flag_H) <= '0';			when others => -- OR "110"				Q_t(7 downto 0) := BusA or BusB;				F_Out(Flag_H) <= '0';			end case;			if ALU_Op(2 downto 0) = "111" then -- CP				F_Out(Flag_X) <= BusB(3);				F_Out(Flag_Y) <= BusB(5);			else				F_Out(Flag_X) <= Q_t(3);				F_Out(Flag_Y) <= Q_t(5);			end if;			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				end if;			else				F_Out(Flag_Z) <= '0';			end if;			F_Out(Flag_S) <= Q_t(7);			case ALU_Op(2 downto 0) is			when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP			when others =>				F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor					Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));			end case;			if Arith16 = '1' then				F_Out(Flag_S) <= F_In(Flag_S);				F_Out(Flag_Z) <= F_In(Flag_Z);				F_Out(Flag_P) <= F_In(Flag_P);			end if;		when "1100" =>			-- DAA			F_Out(Flag_H) <= F_In(Flag_H);			F_Out(Flag_C) <= F_In(Flag_C);			DAA_Q(7 downto 0) := unsigned(BusA);			DAA_Q(8) := '0';			if F_In(Flag_N) = '0' then				-- After addition				-- Alow > 9 or H = 1				if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then					if (DAA_Q(3 downto 0) > 9) then						F_Out(Flag_H) <= '1';					else						F_Out(Flag_H) <= '0';					end if;					DAA_Q := DAA_Q + 6;				end if;				-- new Ahigh > 9 or C = 1				if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then					DAA_Q := DAA_Q + 96; -- 0x60				end if;			else				-- After subtraction				if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then					if DAA_Q(3 downto 0) > 5 then						F_Out(Flag_H) <= '0';					end if;					DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6;				end if;				if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then					DAA_Q := DAA_Q - 352; -- 0x160				end if;			end if;			F_Out(Flag_X) <= DAA_Q(3);			F_Out(Flag_Y) <= DAA_Q(5);			F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8);			Q_t := std_logic_vector(DAA_Q(7 downto 0));			if DAA_Q(7 downto 0) = "00000000" then				F_Out(Flag_Z) <= '1';			else				F_Out(Flag_Z) <= '0';			end if;			F_Out(Flag_S) <= DAA_Q(7);			F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor				DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7));		when "1101" | "1110" =>			-- RLD, RRD			Q_t(7 downto 4) := BusA(7 downto 4);			if ALU_Op(0) = '1' then				Q_t(3 downto 0) := BusB(7 downto 4);			else				Q_t(3 downto 0) := BusB(3 downto 0);			end if;			F_Out(Flag_H) <= '0';			F_Out(Flag_N) <= '0';			F_Out(Flag_X) <= Q_t(3);			F_Out(Flag_Y) <= Q_t(5);			if Q_t(7 downto 0) = "00000000" then				F_Out(Flag_Z) <= '1';			else				F_Out(Flag_Z) <= '0';			end if;			F_Out(Flag_S) <= Q_t(7);			F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor				Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));		when "1001" =>			-- BIT			Q_t(7 downto 0) := BusB and BitMask;			F_Out(Flag_S) <= Q_t(7);			if Q_t(7 downto 0) = "00000000" then				F_Out(Flag_Z) <= '1';				F_Out(Flag_P) <= '1';			else				F_Out(Flag_Z) <= '0';				F_Out(Flag_P) <= '0';			end if;			F_Out(Flag_H) <= '1';			F_Out(Flag_N) <= '0';			F_Out(Flag_X) <= '0';			F_Out(Flag_Y) <= '0';			if IR(2 downto 0) /= "110" then				F_Out(Flag_X) <= BusB(3);				F_Out(Flag_Y) <= BusB(5);			end if;		when "1010" =>			-- SET			Q_t(7 downto 0) := BusB or BitMask;		when "1011" =>			-- RES			Q_t(7 downto 0) := BusB and not BitMask;		when "1000" =>			-- ROT			case IR(5 downto 3) is			when "000" => -- RLC				Q_t(7 downto 1) := BusA(6 downto 0);				Q_t(0) := BusA(7);				F_Out(Flag_C) <= BusA(7);			when "010" => -- RL				Q_t(7 downto 1) := BusA(6 downto 0);				Q_t(0) := F_In(Flag_C);				F_Out(Flag_C) <= BusA(7);			when "001" => -- RRC				Q_t(6 downto 0) := BusA(7 downto 1);				Q_t(7) := BusA(0);				F_Out(Flag_C) <= BusA(0);			when "011" => -- RR				Q_t(6 downto 0) := BusA(7 downto 1);				Q_t(7) := F_In(Flag_C);				F_Out(Flag_C) <= BusA(0);			when "100" => -- SLA				Q_t(7 downto 1) := BusA(6 downto 0);				Q_t(0) := '0';				F_Out(Flag_C) <= BusA(7);			when "110" => -- SLL (Undocumented) / SWAP				if Mode = 3 then					Q_t(7 downto 4) := BusA(3 downto 0);					Q_t(3 downto 0) := BusA(7 downto 4);					F_Out(Flag_C) <= '0';				else					Q_t(7 downto 1) := BusA(6 downto 0);					Q_t(0) := '1';					F_Out(Flag_C) <= BusA(7);				end if;			when "101" => -- SRA				Q_t(6 downto 0) := BusA(7 downto 1);				Q_t(7) := BusA(7);				F_Out(Flag_C) <= BusA(0);			when others => -- SRL				Q_t(6 downto 0) := BusA(7 downto 1);				Q_t(7) := '0';				F_Out(Flag_C) <= BusA(0);			end case;			F_Out(Flag_H) <= '0';			F_Out(Flag_N) <= '0';			F_Out(Flag_X) <= Q_t(3);			F_Out(Flag_Y) <= Q_t(5);			F_Out(Flag_S) <= Q_t(7);			if Q_t(7 downto 0) = "00000000" then				F_Out(Flag_Z) <= '1';			else				F_Out(Flag_Z) <= '0';			end if;			F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor				Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));			if ISet = "00" then				F_Out(Flag_P) <= F_In(Flag_P);				F_Out(Flag_S) <= F_In(Flag_S);				F_Out(Flag_Z) <= F_In(Flag_Z);			end if;		when others =>			null;		end case;		Q <= Q_t;	end process;end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -