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

Subversion Repositories tinyvliw8

[/] [tinyvliw8/] [trunk/] [src/] [vhdl/] [proc/] [alu.vhd] - Rev 4

Go to most recent revision | Compare with Previous | Blame | View Log

-----------------------------------------------------------------
-- Project: Aeternitas
-- Author:  Oliver Stecklina <stecklina@ihp-microelectronics.com
-- Date:    13.11.2013 
-- File:    alu.vhd
-- Design:  AeternitasSWUR
-----------------------------------------------------------------
-- Description : Arithmetic unit of IHPvliw8 processor
-----------------------------------------------------------------
-- $Log$
-----------------------------------------------------------------
 
library ieee;
 
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
 
entity vliwProc_alu is
	port (
		state      : in std_logic_vector(3 downto 0);
 
		enable_n   : in std_logic;
 
		opcode     : in std_logic_vector(2 downto 0);
		as         : in std_logic_vector(1 downto 0);
		dstRegIn   : in std_logic_vector(2 downto 0);
		dataIn     : in std_logic_vector(7 downto 0);
 
		reg0       : in std_logic_vector(7 downto 0);
		reg1       : in std_logic_vector(7 downto 0);
		reg2       : in std_logic_vector(7 downto 0);
		reg3       : in std_logic_vector(7 downto 0);
		reg4       : in std_logic_vector(7 downto 0);
		reg5       : in std_logic_vector(7 downto 0);
		reg6       : in std_logic_vector(7 downto 0);
		reg7       : in std_logic_vector(7 downto 0);
 
		cIn        : in  std_logic;
		cOut       : out std_logic;
		zOut       : out std_logic;
 
		dstRegEn_n : out std_logic;
		dstRegOut  : out std_logic_vector(2 downto 0);
		dataOut    : out std_logic_vector(7 downto 0);
 
		rst_n      : in  std_logic
	);
end vliwProc_alu;
 
architecture behavior of vliwProc_alu is
 
	signal cIn_s      : std_logic;
	signal as_s       : std_logic_vector(1 downto 0);
	signal opcode_s   : std_logic_vector(2 downto 0);
	signal dstRegIn_s : std_logic_vector(2 downto 0);
 
	signal cShift_s : std_logic;
	signal cAdd_s   : std_logic;
 
	signal shift_s  : std_logic;
	signal logic_s  : std_logic;
	signal arith_s  : std_logic;
 
	signal dataOut_s : std_logic_vector(7 downto 0);
 
	signal op0_s    : std_logic_vector(7 downto 0);
	signal op1_s    : std_logic_vector(7 downto 0);
 
	signal aluEn_s  : std_logic;
 
	signal rst_n_s  : std_logic;
 
begin
 
	rst_n_s <= rst_n;
 
	enable_p : process(rst_n_s, state(2))
	begin
		if (rst_n_s = '0') then
			aluEn_s <= '0';
		else
			if (state(2)'event and state(2) = '1') then
				if (enable_n = '0') then
					aluEn_s <= '1';
				else
					aluEn_s <= '0';
				end if;
			end if;
		end if;
	end process;
 
	commitIn_proc : process(rst_n_s, state(2))
		variable shift_v : std_logic;
		variable logic_v : std_logic;
		variable arith_v : std_logic;
 
		variable op0_v : unsigned(8 downto 0);
		variable op1_v : unsigned(8 downto 0);
	begin
		if (rst_n_s = '0') then
			cIn_s <= '0';
 
			as_s       <= (others => '0');
			opcode_s   <= (others => '0');
			dstRegIn_s <= (others => '0');
 
			op0_v := (others => '0');
			op1_v := (others => '0');
 
			shift_v := '0';
			logic_v := '0';
			arith_v := '0';
 
			cAdd_s <= '0';
		else
			if (state(2)'event and state(2) = '1') then
				shift_v := '0';
				logic_v := '0';
				arith_v := '0';
 
			if (enable_n = '0') then
				cIn_s    <= cIn;
 
				as_s     <= as;
				opcode_s <= opcode;
				dstRegIn_s <= dstRegIn;
 
				case opcode IS
					when "010" => arith_v := '1';
				   when "011" => shift_v := '1';
				   when "100" => logic_v := '1';
				   when "101" => logic_v := '1';
				   when "110" => logic_v := '1';
					WHEN others => null;
				end case;
 
				if (shift_v = '1') then
					if (as(0) = '0' or as(1) = '0') then
						CASE dataIn(2 downto 0) IS
							WHEN "000" => op0_v := unsigned('0' & reg0);
							WHEN "001" => op0_v := unsigned('0' & reg1);
							WHEN "010" => op0_v := unsigned('0' & reg2);
							WHEN "011" => op0_v := unsigned('0' & reg3);
							WHEN "100" => op0_v := unsigned('0' & reg4);
							WHEN "101" => op0_v := unsigned('0' & reg5);
							WHEN "110" => op0_v := unsigned('0' & reg6);
							WHEN "111" => op0_v := unsigned('0' & reg7);
							WHEN others => null;
						END CASE;
 
						op1_v := unsigned('0' & dataIn);
					else -- mov Rx, #NUM
						op0_v := unsigned('0' & dataIn);
					end if;
				elsif (logic_v = '1') then
					if (as(0) = '0') then
						if (dataIn(7) = '0') then
							case dataIn(6 downto 4) is
								when "000" => op0_v := unsigned('0' & reg0);
								when "001" => op0_v := unsigned('0' & reg1);
								when "010" => op0_v := unsigned('0' & reg2);
								when "011" => op0_v := unsigned('0' & reg3);
								when "100" => op0_v := unsigned('0' & reg4);
								when "101" => op0_v := unsigned('0' & reg5);
								when "110" => op0_v := unsigned('0' & reg6);
								when "111" => op0_v := unsigned('0' & reg7);
								when others => null;
							end case;
						else
							case dataIn(6 downto 4) is
								when "000" => op0_v := unsigned(not('0' & reg0));
								when "001" => op0_v := unsigned(not('0' & reg1));
								when "010" => op0_v := unsigned(not('0' & reg2));
								when "011" => op0_v := unsigned(not('0' & reg3));
								when "100" => op0_v := unsigned(not('0' & reg4));
								when "101" => op0_v := unsigned(not('0' & reg5));
								when "110" => op0_v := unsigned(not('0' & reg6));
								when "111" => op0_v := unsigned(not('0' & reg7));
								when others => null;
							end case;
						end if;
 
						if (dataIn(3) = '0') then
							case dataIn(2 downto 0) is
								when "000" => op1_v := unsigned('0' & reg0);
								when "001" => op1_v := unsigned('0' & reg1);
								when "010" => op1_v := unsigned('0' & reg2);
								when "011" => op1_v := unsigned('0' & reg3);
								when "100" => op1_v := unsigned('0' & reg4);
								when "101" => op1_v := unsigned('0' & reg5);
								when "110" => op1_v := unsigned('0' & reg6);
								when "111" => op1_v := unsigned('0' & reg7);
								when others => null;
							end case;
						else
							case dataIn(2 downto 0) is
								when "000" => op1_v := unsigned(not('0' & reg0));
								when "001" => op1_v := unsigned(not('0' & reg1));
								when "010" => op1_v := unsigned(not('0' & reg2));
								when "011" => op1_v := unsigned(not('0' & reg3));
								when "100" => op1_v := unsigned(not('0' & reg4));
								when "101" => op1_v := unsigned(not('0' & reg5));
								when "110" => op1_v := unsigned(not('0' & reg6));
								when "111" => op1_v := unsigned(not('0' & reg7));
								when others => null;
							end case;
						end if;
					else
						CASE dstRegIn IS
							WHEN "000" => op0_v := unsigned('0' & reg0);
							WHEN "001" => op0_v := unsigned('0' & reg1);
							WHEN "010" => op0_v := unsigned('0' & reg2);
							WHEN "011" => op0_v := unsigned('0' & reg3);
							WHEN "100" => op0_v := unsigned('0' & reg4);
							WHEN "101" => op0_v := unsigned('0' & reg5);
							WHEN "110" => op0_v := unsigned('0' & reg6);
							WHEN "111" => op0_v := unsigned('0' & reg7);
							WHEN others => null;
						END CASE;
 
						op1_v := unsigned('0' & dataIn);
					end if;
				elsif (arith_v = '1') then
					if (as(0) = '0') then
						if (dataIn(7) = '0') then
							case dataIn(6 downto 4) is
								when "000" => op0_v := unsigned('0' & reg0);
								when "001" => op0_v := unsigned('0' & reg1);
								when "010" => op0_v := unsigned('0' & reg2);
								when "011" => op0_v := unsigned('0' & reg3);
								when "100" => op0_v := unsigned('0' & reg4);
								when "101" => op0_v := unsigned('0' & reg5);
								when "110" => op0_v := unsigned('0' & reg6);
								when "111" => op0_v := unsigned('0' & reg7);
								when others => null;
							end case;
						else
							case dataIn(6 downto 4) is
								when "000" => op0_v := unsigned(not('0' & reg0));
								when "001" => op0_v := unsigned(not('0' & reg1));
								when "010" => op0_v := unsigned(not('0' & reg2));
								when "011" => op0_v := unsigned(not('0' & reg3));
								when "100" => op0_v := unsigned(not('0' & reg4));
								when "101" => op0_v := unsigned(not('0' & reg5));
								when "110" => op0_v := unsigned(not('0' & reg6));
								when "111" => op0_v := unsigned(not('0' & reg7));
								when others => null;
							end case;
 
							op0_v := op0_v + 1;
						end if;
 
						if (dataIn(3) = '0') then
							case dataIn(2 downto 0) is
								when "000" => op1_v := unsigned('0' & reg0);
								when "001" => op1_v := unsigned('0' & reg1);
								when "010" => op1_v := unsigned('0' & reg2);
								when "011" => op1_v := unsigned('0' & reg3);
								when "100" => op1_v := unsigned('0' & reg4);
								when "101" => op1_v := unsigned('0' & reg5);
								when "110" => op1_v := unsigned('0' & reg6);
								when "111" => op1_v := unsigned('0' & reg7);
								when others => null;
							end case;
						else
							-- two's complement
							case dataIn(2 downto 0) is
								when "000" => op1_v := unsigned(not('0' & reg0));
								when "001" => op1_v := unsigned(not('0' & reg1));
								when "010" => op1_v := unsigned(not('0' & reg2));
								when "011" => op1_v := unsigned(not('0' & reg3));
								when "100" => op1_v := unsigned(not('0' & reg4));
								when "101" => op1_v := unsigned(not('0' & reg5));
								when "110" => op1_v := unsigned(not('0' & reg6));
								when "111" => op1_v := unsigned(not('0' & reg7));
								when others => null;
							end case;
 
							op1_v := op1_v + 1;
						end if;
					else
						CASE dstRegIn IS
							WHEN "000" => op0_v := unsigned('0' & reg0);
							WHEN "001" => op0_v := unsigned('0' & reg1);
							WHEN "010" => op0_v := unsigned('0' & reg2);
							WHEN "011" => op0_v := unsigned('0' & reg3);
							WHEN "100" => op0_v := unsigned('0' & reg4);
							WHEN "101" => op0_v := unsigned('0' & reg5);
							WHEN "110" => op0_v := unsigned('0' & reg6);
							WHEN "111" => op0_v := unsigned('0' & reg7);
							WHEN others => null;
						END CASE;
 
						op1_v := unsigned('0' & dataIn);
					end if;
 
					-- addition
					op0_v := op0_v + op1_v;
 
					-- carry add
					if (as(1) = '1' and cIn = '1') then
						op0_v := op0_v + 1;
					end if;
 
					cAdd_s <= std_logic(op0_v(8));
				end if;
				end if;
			end if;
		end if;
 
		shift_s <= std_logic(shift_v);
		logic_s <= std_logic(logic_v);
		arith_s <= std_logic(arith_v);
 
		op0_s <= std_logic_vector(op0_v(7 downto 0));
		op1_s <= std_logic_vector(op1_v(7 downto 0));
	end process;
 
	cShift_s <= op0_s(7) when as_s(0) = '0' and as(1) = '0' else   -- shift left
	            op0_s(0) when as_s(0) = '0' and as(1) = '1' else   -- shift right
					'0';
 
	dataOut_s <= op0_s(6 downto 0) & '0'      when shift_s = '1' and as_s = "00" and op1_s(3) = '0' else
	             op0_s(6 downto 0) & cIn_s    when shift_s = '1' and as_s = "00" and op1_s(3) = '1' else
			  	    op0_s(7) & op0_s(7 downto 1) when shift_s = '1' and as_s = "01" and op1_s(3) = '0' else
					 cIn_s & op0_s(7 downto 1)    when shift_s = '1' and as_s = "01" and op1_s(3) = '1' else
				    not(op0_s)                   when shift_s = '1' and as_s = "10" and op1_s(3) = '1' else
					 op0_s                        when shift_s = '1' and as_s(0) = '1' else
				    op0_s and op1_s      when logic_s = '1' and opcode_s = "100" and as_s(1) = '0' else
				    not(op0_s and op1_s) when logic_s = '1' and opcode_s = "100" and as_s(1) = '1' else
				    op0_s or op1_s       when logic_s = '1' and opcode_s = "101" and as_s(1) = '0' else
				    not(op0_s or op1_s)  when logic_s = '1' and opcode_s = "101" and as_s(1) = '1' else
				    op0_s xor op1_s      when logic_s = '1' and opcode_s = "110" and as_s(1) = '0' else
				    not(op0_s xor op1_s) when logic_s = '1' and opcode_s = "110" and as_s(1) = '1' else
					 op0_s when arith_s = '1' else
				    (others => '0');
 
	cOut <= cAdd_s   when aluEn_s = '1' and arith_s = '1' else                   -- arithmetic operations
  	        cShift_s when aluEn_s = '1' and shift_s = '1' and as_s(0) = '0' else -- shift
			  '0';
 
	dataOut <= dataOut_s  when aluEn_s = '1' else
	           (others => '0');
	zOut <= '1' when aluEn_s = '1' and dataOut_s = "00000000" else
	        '0';
 
	dstRegEn_n <= '0' when aluEn_s = '1' else
	              '1';
	dstRegOut <= dstRegIn_s when aluEn_s = '1' else
	             (others => '0');
 
end behavior;
 

Go to most recent revision | 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.