OpenCores
URL https://opencores.org/ocsvn/ax8/ax8/trunk

Subversion Repositories ax8

[/] [ax8/] [trunk/] [rtl/] [vhdl/] [AX_ALU.vhd] - Rev 31

Compare with Previous | Blame | View Log

--
-- AT90Sxxxx compatible microcontroller core
--
-- Version : 0221
--
-- 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/t51/
--
-- Limitations :
--
-- File history :
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.AX_Pack.all;
 
entity AX_ALU is
	generic(
		TriState	: boolean := false
	);
	port(
		Clk			: in std_logic;
		ROM_Data	: in std_logic_vector(15 downto 0);
		A			: in std_logic_vector(7 downto 0);
		B			: in std_logic_vector(7 downto 0);
		Q			: out std_logic_vector(7 downto 0);
		SREG		: in std_logic_vector(7 downto 0);
		PassB		: in std_logic;
		Skip		: in std_logic;
		Do_Other	: out std_logic;
		Z_Skip		: out std_logic;
		Status_D	: out std_logic_vector(6 downto 0);
		Status_Wr	: out std_logic_vector(6 downto 0)	-- T,H,S,V,N,Z,C
	);
end AX_ALU;
 
architecture rtl of AX_ALU is
 
	signal	Do_NEG			: std_logic;
	signal	Do_ADD			: std_logic;
	signal	Do_SUB			: std_logic;
	signal	Do_DEC			: std_logic;
	signal	Do_INC			: std_logic;
	signal	Do_AND			: std_logic;
	signal	Do_OR			: std_logic;
	signal	Do_XOR			: std_logic;
	signal	Do_COM			: std_logic;
	signal	Do_SWAP			: std_logic;
	signal	Do_BLD			: std_logic;
	signal	Do_BST			: std_logic;
	signal	Do_ROR			: std_logic;
	signal	Do_ASR			: std_logic;
	signal	Do_LSR			: std_logic;
	signal	Do_PASSB		: std_logic;
	signal	Do_SBRC			: std_logic;
	signal	Do_SBRS			: std_logic;
	signal	Use_Carry		: std_logic;
 
	signal	Bit_Pattern		: std_logic_vector(7 downto 0);
	signal	Bit_Test		: std_logic_vector(7 downto 0);
 
	signal	Q_i				: std_logic_vector(7 downto 0);
	signal	Q_L				: std_logic_vector(7 downto 0);
	signal	Q_C				: std_logic_vector(7 downto 0);
	signal	Q_S				: std_logic_vector(7 downto 0);
	signal	Q_R				: std_logic_vector(7 downto 0);
	signal	Q_B				: std_logic_vector(7 downto 0);
 
	-- AddSub intermediate signals
	signal	Carry7_v		: std_logic;
	signal	Overflow_v		: std_logic;
	signal	Overflow_t		: std_logic;
	signal	HalfCarry_v		: std_logic;
	signal	Carry_v			: std_logic;
	signal	Q_v				: std_logic_vector(7 downto 0);
	signal	AAS				: std_logic_vector(7 downto 0);
	signal	BAS				: std_logic_vector(7 downto 0);
 
begin
 
	Q <= Q_i;
 
	Do_Other <= Do_PASSB;
 
	gNoTri : if not TriState generate
		Q_i <= Q_v when Do_ADD = '1' or Do_SUB = '1' else
			Q_L when Do_AND = '1' or Do_OR = '1' or Do_XOR = '1' else
			Q_C when Do_COM = '1' else
			Q_S when Do_SWAP = '1' else
			Q_R when Do_ASR = '1' or Do_LSR = '1' or Do_ROR = '1' else
			Q_B;
	end generate;
 
	gTri : if TriState generate
		Q_i <= Q_v when Do_ADD = '1' or Do_SUB = '1' else "ZZZZZZZZ";
		Q_i <= Q_L when Do_AND = '1' or Do_OR = '1' or Do_XOR = '1' else "ZZZZZZZZ";
		Q_i <= Q_C when Do_COM = '1' else "ZZZZZZZZ";
		Q_i <= Q_S when Do_SWAP = '1' else "ZZZZZZZZ";
		Q_i <= Q_R when Do_ASR = '1' or Do_LSR = '1' or Do_ROR = '1' else "ZZZZZZZZ";
		Q_i <= Q_B when Do_BLD = '1' else "ZZZZZZZZ";
	end generate;
 
	process (Clk)
	begin
		if Clk'event and Clk = '1' then
			Do_SUB <= '0';
			Do_ADD <= '0';
			Use_Carry <= '0';
			Do_AND <= '0';
			Do_XOR <= '0';
			Do_OR <= '0';
			Do_SWAP <= '0';
			Do_ASR <= '0';
			Do_LSR <= '0';
			Do_ROR <= '0';
			Do_INC <= '0';
			Do_DEC <= '0';
			Do_COM <= '0';
			Do_NEG <= '0';
			Do_BLD <= '0';
			Do_BST <= '0';
			Do_PASSB <= '0';
			Do_SBRC <= '0';
			Do_SBRS <= '0';
			if PassB = '0' then
			if Skip = '0' then
			if ROM_Data(15 downto 10) = "000101" or ROM_Data(15 downto 12) = "0011" or
				ROM_Data(15 downto 10) = "000110" or ROM_Data(15 downto 12) = "0101" or
				ROM_Data(15 downto 12) = "0100" or ROM_Data(15 downto 10) = "000001" or
				ROM_Data(15 downto 10) = "000010" or
				(ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "0001") or
				(ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "1010") then
				-- CP, CPI, SUB, SUBI, SBCI, CPC, SBC, NEG, DEC
				Do_SUB <= '1';
			end if;
			if ROM_Data(15 downto 10) = "000011" or ROM_Data(15 downto 10) = "000111" or
				(ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "0011") then
				-- ADD, ADC, INC
				Do_ADD <= '1';
			end if;
			if ROM_Data(15 downto 12) = "0100" or ROM_Data(15 downto 10) = "000001" or
				ROM_Data(15 downto 10) = "000010" or ROM_Data(15 downto 10) = "000111" then
				-- SBCI, CPC, SBC, ADC
				Use_Carry <= '1';
			end if;
			if ROM_Data(15 downto 10) = "001000" or ROM_Data(15 downto 12) = "0111" then
				-- AND, ANDI
				Do_AND <= '1';
			end if;
			if ROM_Data(15 downto 10) = "001001" then
				-- EOR
				Do_XOR <= '1';
			end if;
			if ROM_Data(15 downto 10) = "001010" or ROM_Data(15 downto 12) = "0110" then
				-- OR, ORI
				Do_OR <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "0010" then
				-- SWAP
				Do_SWAP <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "0101" then
				-- ASR
				Do_ASR <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "0110" then
				-- LSR
				Do_LSR <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "0111" then
				-- ROR
				Do_ROR <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "0011" then
				-- INC
				Do_INC <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "1010" then
				-- DEC
				Do_DEC <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "0000" then
				-- COM
				Do_COM <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1001010" and ROM_Data(3 downto 0) = "0001" then
				-- NEG
				Do_NEG <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1111100" then
				-- BLD
				Do_BLD <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1111101" then
				-- BST
				Do_BST <= '1';
			end if;
			if ROM_Data(15 downto 10) = "001011" or
				ROM_Data(15 downto 12) = "1011" or
				ROM_Data(15 downto 12) = "1110" then
				-- MOV, DidPause, IN, OUT, LDI
				Do_PASSB <= '1';
			end if;
			if ROM_Data(15 downto 9) = "1111110" then
				-- SBRC
				Do_SBRC <= '1';
			else
				Do_SBRC <= '0';
			end if;
			if ROM_Data(15 downto 9) = "1111111" then
				-- SBRS
				Do_SBRS <= '1';
			else
				Do_SBRS <= '0';
			end if;
			end if;
			else
				Do_PASSB <= '1';
			end if;
 
			case ROM_Data(2 downto 0) is
			when "000" =>
				Bit_Pattern <= "00000001";
			when "001" =>
				Bit_Pattern <= "00000010";
			when "010" =>
				Bit_Pattern <= "00000100";
			when "011" =>
				Bit_Pattern <= "00001000";
			when "100" =>
				Bit_Pattern <= "00010000";
			when "101" =>
				Bit_Pattern <= "00100000";
			when "110" =>
				Bit_Pattern <= "01000000";
			when others =>
				Bit_Pattern <= "10000000";
			end case;
		end if;
	end process;
 
	Bit_Test <= Bit_Pattern and A;
 
	Z_Skip <= '1' when ((Bit_Test /= "00000000") and (Do_SBRS = '1')) or
					((Bit_Test = "00000000") and (Do_SBRC = '1')) else '0';
 
	AAS <= "00000000" when Do_NEG = '1' else A;
	BAS <= A when Do_NEG = '1' else "00000001" when Do_DEC = '1' or Do_INC = '1' else B;
	AddSub(AAS(3 downto 0), BAS(3 downto 0), Do_SUB, Do_SUB xor (Use_Carry and SREG(0)), Q_v(3 downto 0), HalfCarry_v);
	AddSub(AAS(6 downto 4), BAS(6 downto 4), Do_SUB, HalfCarry_v, Q_v(6 downto 4), Carry7_v);
	AddSub(AAS(7 downto 7), BAS(7 downto 7), Do_SUB, Carry7_v, Q_v(7 downto 7), Carry_v);
	OverFlow_v <= Carry_v xor Carry7_v;
	Status_D(5) <= HalfCarry_v xor Do_SUB;	-- H
 
	Q_L <= (A and B) when Do_AND = '1' else
		(A or B) when Do_OR = '1' else
		(A xor B);
 
	Q_C <= (not A);
 
	Q_S <= A(3 downto 0) & A(7 downto 4);
 
	Q_R(6 downto 0) <=  A(7 downto 1);
	Q_R(7) <= (A(7) and Do_ASR) or (SREG(0) and Do_ROR);
 
	Q_B <= ((not Bit_Pattern) and A) when SREG(6) = '0' else
			(Bit_Pattern or A);
 
	Status_D(6) <= '1' when (Bit_Pattern and A) /= "00000000" else '0';
 
	Overflow_t <= Overflow_v when Do_SUB = '1' or Do_ADD = '1' else
		Q_i(7) xor A(0) when (Do_ASR or Do_LSR or Do_ROR) = '1' else '0';	-- V
	Status_D(3) <= Overflow_t;
	Status_D(2) <= Q_i(7);	-- N
	Status_D(4) <= Overflow_t xor Q_i(7);	-- SREG(3) xor SREG(2);		-- S
	Status_D(1) <= '1' when Q_i(7 downto 0) = "00000000" and (Do_SUB = '0' or Use_Carry = '0') else
		SREG(1) when Q_i(7 downto 0) = "00000000" and Do_SUB = '1' and Use_Carry = '1' else '0';	-- Z
	Status_D(0) <= ((Carry_v xor Do_SUB) and (Do_ADD or Do_SUB)) or
					(A(0) and (Do_ASR or Do_LSR or Do_ROR)) or Do_COM;
 
	process (Do_SUB, Do_ADD, Do_COM, Do_ASR, Do_LSR, Do_ROR, Do_AND, Do_XOR, Do_OR, Do_INC, Do_DEC, Do_BST)
	begin
		Status_Wr <= "0000000";
		if (Do_COM or Do_ASR or Do_LSR or Do_ROR) = '1' then
			Status_Wr <= "0011111"; -- Z,C,N,V	,S
		end if;
		if (Do_AND or Do_XOR or Do_OR or Do_INC or Do_DEC) = '1' then
			Status_Wr <= "0011110"; -- Z,N,V	,S
		elsif (Do_SUB or Do_ADD) = '1' then
			Status_Wr <= "0111111"; -- Z,C,N,V,H	,S
		end if;
		if Do_BST = '1' then
			Status_Wr <= "1000000"; -- T
		end if;
	end process;
 
end;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.