--------------------------------------------------------------------------------------------------------------- -- RISA Project -- Author: A.Greensted -- Module: ALU -- Description: The Snap core's 16bit Arithmetic Logic Unit -- History: --------------------------------------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library CommonLib; use CommonLib.CommonPkg.all; library SnapLib; use SnapLib.SnapPkg.all; entity ALU is port ( opCode : in SNAPTYPE_OPCODE; opA : in std_logic_vector(15 downto 0); opB : in std_logic_vector(15 downto 0); carryBorrowIn : in std_logic; overflowIn : in std_logic; flags : out SNAPTYPE_ALU_FLAGS; dOut : out std_logic_vector(15 downto 0)); end ALU; architecture General of ALU is signal clearOpA : boolean; signal clearOpB : boolean; signal invertOpB : boolean; signal maskOpB : boolean; signal clearCarryIn : boolean; signal invertCarryIn : boolean; signal invertCarryOut : boolean; signal bypassCarry : boolean; signal bypassOverflow : boolean; signal opAProcessed : std_logic_vector(15 downto 0); signal opBProcessed : std_logic_vector(15 downto 0); signal carryInProcessed : std_logic; signal carryOutProcessed : std_logic; signal overflowProcessed : std_logic; type rollDirType is (ROLL_LEFT, ROLL_RIGHT); signal rollDir : rollDirType; type logicSelectType is (AND_SELECT, OR_SELECT, XOR_SELECT); signal logicSelect : logicSelectType; signal rollOut : std_logic_vector(15 downto 0); signal logicOut : std_logic_vector(15 downto 0); signal mathsOut : std_logic_vector(15 downto 0); signal carryOut : std_logic; signal overflowOut : std_logic; signal result : std_logic_vector(15 downto 0); begin -- ProcessOpA ------------------------------------------------------------------------------------------------- -- Process OpA --------------------------------------------------------------------------------------------------------------- -- {{{ ProcessOpA : process(opA, clearOpA) begin if (clearOpA = TRUE) then opAProcessed <= b"0000_0000_0000_0000"; else opAProcessed <= opA; end if; end process; -- }}} -- ProcessOpB ------------------------------------------------------------------------------------------------- -- Process OpB --------------------------------------------------------------------------------------------------------------- -- {{{ ProcessOpB : process(opB, maskOpB, clearOpB, invertOpB) variable tmp : std_logic_vector(15 downto 0); variable shiftAmmount : unsigned(3 downto 0); begin shiftAmmount := unsigned(opB(3 downto 0)); if (maskOpB = TRUE) then tmp := std_logic_vector( uns_0001 sll to_integer(shiftAmmount) ); else tmp := opB; end if; if (clearOpB = TRUE) then tmp := b"0000_0000_0000_0000"; end if; if (invertOpB = TRUE) then tmp := not tmp; end if; opBProcessed <= tmp; end process; -- }}} -- ProcessCarryIn ------------------------------------------------------------------------------------------------- -- Process CarryIn --------------------------------------------------------------------------------------------------------------- -- {{{ ProcessCarryIn : process(carryBorrowIn, clearCarryIn, invertCarryIn) variable tmp : std_logic; begin if (clearCarryIn = TRUE) then tmp := '0'; else tmp := carryBorrowIn; end if; if (invertCarryIn = TRUE) then tmp := not tmp; end if; carryInProcessed <= tmp; end process; -- }}} -- RollUnit --------------------------------------------------------------------------------------------------- -- Performs a barrel roll --------------------------------------------------------------------------------------------------------------- -- {{{ RollUnit : process(opAProcessed, opBProcessed, rollDir) variable ammount : unsigned(3 downto 0); begin ammount := unsigned(opBProcessed(3 downto 0)); case rollDir is when ROLL_LEFT => rollOut <= std_logic_vector( unsigned(opAProcessed) rol to_integer(ammount) ); when ROLL_RIGHT => rollOut <= std_logic_vector( unsigned(opAProcessed) ror to_integer(ammount) ); end case; end process; -- }}} -- LogicUnit -------------------------------------------------------------------------------------------------- -- Performs an add with carry in and out --------------------------------------------------------------------------------------------------------------- -- {{{ LogicUnit : process(opAProcessed, opBProcessed, logicSelect) begin case logicSelect is when AND_SELECT => logicOut <= opAProcessed and opBProcessed; when OR_SELECT => logicOut <= opAProcessed or opBProcessed; when XOR_SELECT => logicOut <= opAProcessed xor opBProcessed; end case; end process; -- }}} -- MathsUnit -------------------------------------------------------------------------------------------------- -- Performs an add with carry in and out --------------------------------------------------------------------------------------------------------------- -- {{{ MathsUnit : process(opAProcessed, opBProcessed, carryInProcessed) variable mathsResult : unsigned(17 downto 0); begin mathsResult := unsigned('0' & opAProcessed & carryInProcessed) + unsigned('0' & opBProcessed & carryInProcessed); mathsOut <= std_logic_vector(mathsResult(16 downto 1)); carryOut <= std_logic(mathsResult(17)); end process; -- }}} -- OverflowUnit ----------------------------------------------------------------------------------------------- -- Calculates overflow from operands and maths result --------------------------------------------------------------------------------------------------------------- -- {{{ OverflowUnit : process(opAProcessed, opBProcessed, mathsOut) begin overflowOut <= (opAProcessed(15) and opBProcessed(15) and not mathsOut(15)) or (not opAProcessed(15) and not opBProcessed(15) and mathsOut(15)); end process; -- }}} -- ProcessCarryOut ------------------------------------------------------------------------------------------------- -- Process CarryOut --------------------------------------------------------------------------------------------------------------- -- {{{ ProcessCarryOut : process(carryOut, invertCarryOut, bypassCarry, carryBorrowIn) variable tmp : std_logic; begin tmp := carryOut; if (invertCarryOut = TRUE) then tmp := not tmp; end if; if (bypassCarry = TRUE) then tmp := carryBorrowIn; end if; carryOutProcessed <= tmp; end process; -- }}} -- ProcessOverflow ------------------------------------------------------------------------------------------------- -- Process Overflow --------------------------------------------------------------------------------------------------------------- -- {{{ ProcessOverflow : process(overflowIn, overflowOut, bypassOverflow) begin if (bypassOverflow = TRUE) then overflowProcessed <= overflowIn; else overflowProcessed <= overflowOut; end if; end process; -- }}} -- OperationSelect -------------------------------------------------------------------------------------------- -- Calculate result depending on opcode --------------------------------------------------------------------------------------------------------------- OperationSelect : process(opCode, rollOut, logicOut, mathsOut) begin -- Defaults clearOpA <= FALSE; maskOpB <= FALSE; clearOpB <= FALSE; invertOpB <= FALSE; clearCarryIn <= FALSE; invertCarryIn <= FALSE; invertCarryOut <= FALSE; bypassCarry <= FALSE; bypassOverflow <= FALSE; rollDir <= ROLL_LEFT; logicSelect <= AND_SELECT; result <= mathsOut; case opCode is when SNAP_OP_ADD => -- 0 clearCarryIn <= TRUE; result <= mathsOut; when SNAP_OP_ADDC => -- 1 result <= mathsOut; when SNAP_OP_SUB => -- 2 invertOpB <= TRUE; clearCarryIn <= TRUE; invertCarryIn <= TRUE; invertCarryOut <= TRUE; result <= mathsOut; when SNAP_OP_SUBC => -- 3 invertOpB <= TRUE; invertCarryIn <= TRUE; invertCarryOut <= TRUE; result <= mathsOut; when SNAP_OP_NEG => -- 4 clearOpA <= TRUE; invertOpB <= TRUE; clearCarryIn <= TRUE; invertCarryIn <= TRUE; invertCarryOut <= TRUE; result <= mathsOut; when SNAP_OP_AND => -- 6 bypassCarry <= TRUE; bypassOverflow <= TRUE; logicSelect <= AND_SELECT; result <= logicOut; when SNAP_OP_OR => -- 7 bypassCarry <= TRUE; bypassOverflow <= TRUE; logicSelect <= OR_SELECT; result <= logicOut; when SNAP_OP_XOR => -- 8 bypassCarry <= TRUE; bypassOverflow <= TRUE; logicSelect <= XOR_SELECT; result <= logicOut; when SNAP_OP_ROL => -- 9 bypassCarry <= TRUE; bypassOverflow <= TRUE; rollDir <= ROLL_LEFT; result <= rollOut; when SNAP_OP_ROR => -- 10 bypassCarry <= TRUE; bypassOverflow <= TRUE; rollDir <= ROLL_RIGHT; result <= rollOut; when SNAP_OP_BS => -- 11 bypassCarry <= TRUE; bypassOverflow <= TRUE; maskOpB <= TRUE; logicSelect <= OR_SELECT; result <= logicOut; when SNAP_OP_BC => -- 12 bypassCarry <= TRUE; bypassOverflow <= TRUE; maskOpB <= TRUE; invertOpB <= TRUE; logicSelect <= AND_SELECT; result <= logicOut; when SNAP_OP_MOV | SNAP_OP_SPECIAL => -- 13, 5 bypassCarry <= TRUE; bypassOverflow <= TRUE; clearOpA <= TRUE; logicSelect <= OR_SELECT; result <= logicOut; when SNAP_OP_LD | SNAP_OP_ST => -- 14, 15 bypassCarry <= TRUE; bypassOverflow <= TRUE; clearOpA <= TRUE; logicSelect <= OR_SELECT; result <= logicOut; end case; end process; -- Outputs ---------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------- flags.zero <= '1' when (result = x"0000") else '0'; flags.negative <= result(15); flags.carryBorrow <= carryOutProcessed; flags.overflow <= overflowProcessed; dOut <= result; end General;