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

Subversion Repositories igor

[/] [igor/] [trunk/] [processor/] [pl/] [alu.vhd] - Rev 4

Compare with Previous | Blame | View Log

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
use work.leval2_package.all;
 
entity alu is
	port (
		in_a		: in std_logic_vector(OBJECT_SIZE-1 downto 0);
		in_b		: in std_logic_vector(OBJECT_SIZE-1 downto 0);
		funct		: in std_logic_vector(ALU_FUNCT_SIZE-1 downto 0);
		status	: out std_logic_vector(STATUS_REG_BITS-1 downto 0);
		output	: out std_logic_vector(OBJECT_SIZE-1 downto 0));
end entity alu;
 
architecture rtl of alu is
 
	signal mul_res : std_logic_vector(DATUM_SIZE*2-3 downto 0);
 
	signal type_a : std_logic_vector(INSTR_TYPE_BITS-1 downto 0);
	signal gc_flag_a : std_logic;
	signal datum_a : std_logic_vector(DATUM_SIZE-1 downto 0);
	signal type_b : std_logic_vector(INSTR_TYPE_BITS-1 downto 0);
	signal gc_flag_b : std_logic;
	signal datum_b : std_logic_vector(DATUM_SIZE-1 downto 0);
	signal type_r : std_logic_vector(INSTR_TYPE_BITS-1 downto 0);
	signal gc_flag_r : std_logic;
	signal datum_r : std_logic_vector(DATUM_SIZE-1 downto 0);
 
begin
 
	-- Decode inputs
	type_a <= in_a(OBJECT_SIZE-1 downto 27);
	gc_flag_a <= in_a(26);
	datum_a <= in_a(25 downto 0);
	type_b <= in_b(OBJECT_SIZE-1 downto 27);
	gc_flag_b <= in_b(26);
	datum_b <= in_b(25 downto 0);
 
	-- SET STATUS FLAGS
	-- Overflow
	status(OVERFLOW) <= '0' when (mul_res(49 downto 25) = (mul_res(49 downto 25) xor mul_res(49 downto 25))) else '1';
	-- negative
	status(NEG) <= datum_r(25);
	-- zero
	status(ZERO) <= '1' when datum_r = (datum_r xor datum_r) else '0';
	-- type error
	status(TYP) <= '0' when type_a = type_b else '1';
	-- io-error
	status(IO) <= '0';
	--unused
	status(1) <= '0';
	status(6) <= '0';
	status(7) <= '0';
 
	mul_res <= (datum_a(24 downto 0) * datum_b(24 downto 0));
 
	-- set output to result
	output <= type_r & gc_flag_r & datum_r;
 
	process(funct, type_a, type_b, gc_flag_a, gc_flag_b, datum_a, datum_b, mul_res)
	begin
		type_r <= (others => '0');
		gc_flag_r <= '0';
		datum_r  <= (others => '0');
		case funct is
			when ALU_ADD =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= datum_a + datum_b;
 
			when ALU_SUB =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= datum_a - datum_b;
 
			when ALU_MUL =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r(24 downto 0) <= mul_res(24 downto 0);
				datum_r(25) <= datum_a(25) xor datum_b(25);
 
 
			when ALU_AND =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= datum_a and datum_b;
 
			when ALU_OR =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= datum_a or datum_b;
 
			when ALU_XOR =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= datum_a xor datum_b;
 
			when ALU_GET_TYPE =>
				type_r <= DT_INT;
				gc_flag_r <= '0';
				datum_r(INSTR_TYPE_BITS - 1 downto 0) <= type_b;
				datum_r(DATUM_SIZE - 1 downto INSTR_TYPE_BITS) <= (others => '0');
 
			when ALU_SET_TYPE =>
				type_r <= datum_b(INSTR_TYPE_BITS-1 downto 0);
				gc_flag_r <= '0';
				datum_r <= datum_a;
 
			when ALU_SET_DATUM =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= datum_b;
 
			when ALU_SET_GC =>
				type_r <= type_a;
				gc_flag_r <= datum_b(0);
				datum_r <= datum_a;
 
			when ALU_GET_GC =>
				type_r <= DT_INT;
				gc_flag_r <= '0';
				datum_r(0) <= gc_flag_b;
				datum_r(DATUM_SIZE - 1 downto 1) <= (others => '0');
 
			when ALU_CPY =>
				type_r <= type_b;
				gc_flag_r <= gc_flag_b;
				datum_r <= datum_b;
 
			-- shift right
			when ALU_SR =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= std_logic_vector(shift_right(unsigned(datum_a), 
					to_integer(unsigned(datum_b))));
 
			-- shift left
			when ALU_SL =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= std_logic_vector(shift_left(unsigned(datum_a), 
					to_integer(unsigned(datum_b))));
 
			when ALU_CMP_DATUM =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= datum_a - datum_b;
 
			when ALU_CMP_TYPE =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= "000000000000000000000" & (type_a - type_b);
 
			when ALU_CMP_TYPE_IMM =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= "000000000000000000000" & (type_a - datum_b(INSTR_TYPE_BITS - 1 downto 0));
 
			when ALU_CMP_GC =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= "0000000000000000000000000"&(gc_flag_a xor gc_flag_b);
 
			when ALU_CMP_GC_IMM =>
				type_r <= type_a;
				gc_flag_r <= gc_flag_a;
				datum_r <= "0000000000000000000000000"&(gc_flag_a xor datum_b(0));
 
			when ALU_CMP =>
				if type_a = type_b and
					datum_a = datum_b then -- we have equivalent objects
					datum_r <= (others => '0');
				else
					datum_r(DATUM_SIZE-1 downto DATUM_SIZE-4) <= "1111";
					datum_r(DATUM_SIZE-5 downto 0) <= (others => '0'); -- not same
				end if;
 
			when others =>
				type_r <= (others => '0');
				gc_flag_r <= '0';
				datum_r  <= (others => '0');
 
		end case;
	end process;
end rtl;
 

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.