--##############################################################################
|
--##############################################################################
|
--
|
--
|
-- alu
|
-- alu
|
-- The processor ALU
|
-- The processor ALU
|
--
|
--
|
-- Arithmetic and logic unit.
|
-- Arithmetic and logic unit.
|
--
|
--
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
--
|
--
|
-- Versions / Authors
|
-- Versions / Authors
|
-- 1.0 Francois Corthay first implementation
|
-- 1.0 Francois Corthay first implementation
|
--
|
--
|
-- Provided under GNU LGPL licence: <http://www.gnu.org/copyleft/lesser.html>
|
-- Provided under GNU LGPL licence: <http://www.gnu.org/copyleft/lesser.html>
|
--
|
--
|
-- by the electronics group of "HES-SO//Valais Wallis", in Switzerland:
|
-- by the electronics group of "HES-SO//Valais Wallis", in Switzerland:
|
-- <http://www.hevs.ch/en/rad-instituts/institut-systemes-industriels/>.
|
-- <http://www.hevs.ch/en/rad-instituts/institut-systemes-industriels/>.
|
--
|
--
|
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
--
|
--
|
-- Hierarchy
|
-- Hierarchy
|
-- Used by "nanoblaze/nanoProcessor/aluAndRegisters".
|
-- Used by "nanoblaze/nanoProcessor/aluAndRegisters".
|
--
|
--
|
--##############################################################################
|
--##############################################################################
|
|
|
LIBRARY ieee;
|
LIBRARY ieee;
|
USE ieee.std_logic_1164.all;
|
USE ieee.std_logic_1164.all;
|
USE ieee.numeric_std.all;
|
USE ieee.numeric_std.all;
|
|
|
ENTITY alu IS
|
ENTITY alu IS
|
GENERIC(
|
GENERIC(
|
aluCodeBitNb : positive := 5;
|
aluCodeBitNb : positive := 5;
|
dataBitNb : positive := 8
|
dataBitNb : positive := 8
|
);
|
);
|
PORT(
|
PORT(
|
aluCode : IN std_ulogic_vector(aluCodeBitNb-1 DOWNTO 0);
|
aluCode : IN std_ulogic_vector(aluCodeBitNb-1 DOWNTO 0);
|
opA : IN signed(dataBitNb-1 DOWNTO 0);
|
opA : IN signed(dataBitNb-1 DOWNTO 0);
|
opB : IN signed(dataBitNb-1 DOWNTO 0);
|
opB : IN signed(dataBitNb-1 DOWNTO 0);
|
cIn : IN std_ulogic;
|
cIn : IN std_ulogic;
|
aluOut : OUT signed(dataBitNb-1 DOWNTO 0);
|
aluOut : OUT signed(dataBitNb-1 DOWNTO 0);
|
cOut : OUT std_ulogic;
|
cOut : OUT std_ulogic;
|
zero : OUT std_ulogic
|
zero : OUT std_ulogic
|
);
|
);
|
END alu ;
|
END alu ;
|
|
|
--==============================================================================
|
--==============================================================================
|
|
|
ARCHITECTURE RTL OF alu IS
|
ARCHITECTURE RTL OF alu IS
|
|
|
signal aluCodeInt: unsigned(aluCode'range);
|
signal aluCodeInt: unsigned(aluCode'range);
|
signal aArith: signed(opA'high+1 downto 0);
|
signal aArith: signed(opA'high+1 downto 0);
|
signal bArith: signed(opA'high+1 downto 0);
|
signal bArith: signed(opA'high+1 downto 0);
|
signal cInArith: signed(1 downto 0);
|
signal cInArith: signed(1 downto 0);
|
signal cInShift: std_ulogic;
|
signal cInShift: std_ulogic;
|
signal yArith: signed(aluOut'high+1 downto 0);
|
signal yArith: signed(aluOut'high+1 downto 0);
|
signal aluOutInt: signed(aluOut'range);
|
signal aluOutInt: signed(aluOut'range);
|
|
|
BEGIN
|
BEGIN
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- clear aluCode don't care LSB for shifts
|
-- clear aluCode don't care LSB for shifts
|
aluCodeInt(aluCode'high downto 1) <= unsigned(aluCode(aluCode'high downto 1));
|
aluCodeInt(aluCode'high downto 1) <= unsigned(aluCode(aluCode'high downto 1));
|
|
|
cleanupLsb: process(aluCode)
|
cleanupLsb: process(aluCode)
|
begin
|
begin
|
if aluCode(aluCode'high) = '1' then
|
if aluCode(aluCode'high) = '1' then
|
aluCodeInt(0) <= '0';
|
aluCodeInt(0) <= '0';
|
else
|
else
|
aluCodeInt(0) <= aluCode(0);
|
aluCodeInt(0) <= aluCode(0);
|
end if;
|
end if;
|
end process cleanupLsb;
|
end process cleanupLsb;
|
|
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- values for arithmetic operations
|
-- values for arithmetic operations
|
aArith <= signed(resize(unsigned(opA), aArith'length));
|
aArith <= signed(resize(unsigned(opA), aArith'length));
|
bArith <= signed(resize(unsigned(opB), bArith'length));
|
bArith <= signed(resize(unsigned(opB), bArith'length));
|
cInArith(cInArith'high downto 1) <= (others => '0');
|
cInArith <= (0 => cIn, others => '0');
|
cInArith <= '0' & cIn;
|
|
|
|
process(aluCode, cIn, opA)
|
process(aluCode, cIn, opA)
|
begin
|
begin
|
case aluCode(2 downto 1) is
|
case aluCode(2 downto 1) is
|
when "00" => cInShift <= cIn;
|
when "00" => cInShift <= cIn;
|
when "01" => cInShift <= opA(opA'high);
|
when "01" => cInShift <= opA(opA'high);
|
when "10" => cInShift <= opA(opA'low);
|
when "10" => cInShift <= opA(opA'low);
|
when "11" => cInShift <= aluCode(0);
|
when "11" => cInShift <= aluCode(0);
|
when others => cInShift <= '-';
|
when others => cInShift <= '-';
|
end case;
|
end case;
|
end process;
|
end process;
|
|
|
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
-- alu operations
|
-- alu operations
|
aluOperation: process(
|
aluOperation: process(
|
aluCodeInt,
|
aluCodeInt,
|
opA, opB,
|
opA, opB,
|
aArith, bArith, cInArith,
|
aArith, bArith, cInArith,
|
cInShift,
|
cInShift,
|
yArith
|
yArith, aluOutInt
|
)
|
)
|
variable xorAcc: std_ulogic;
|
variable xorAcc: std_ulogic;
|
begin
|
begin
|
yArith <= (others => '-');
|
yArith <= (others => '-');
|
cOut <= '-';
|
cOut <= '-';
|
aluOutInt <= (others => '-');
|
aluOutInt <= (others => '-');
|
case to_integer(aluCodeInt) is
|
case to_integer(aluCodeInt) is
|
when 0 => -- LOAD sX, kk
|
when 0 => -- LOAD sX, kk
|
aluOutInt <= opB;
|
aluOutInt <= opB;
|
when 2 => -- INPUT sX, pp
|
when 2 => -- INPUT sX, pp
|
aluOutInt <= opB;
|
aluOutInt <= opB;
|
when 3 => -- FETCH sX, ss
|
when 3 => -- FETCH sX, ss
|
aluOutInt <= opB;
|
aluOutInt <= opB;
|
when 5 => -- AND sX, kk
|
when 5 => -- AND sX, kk
|
aluOutInt <= opA and opB;
|
aluOutInt <= opA and opB;
|
cOut <= '0';
|
cOut <= '0';
|
when 6 => -- OR sX, kk
|
when 6 => -- OR sX, kk
|
aluOutInt <= opA or opB;
|
aluOutInt <= opA or opB;
|
cOut <= '0';
|
cOut <= '0';
|
when 7 => -- XOR sX, kk
|
when 7 => -- XOR sX, kk
|
aluOutInt <= opA xor opB;
|
aluOutInt <= opA xor opB;
|
cOut <= '0';
|
cOut <= '0';
|
when 9 => -- TEST sX, kk
|
when 9 => -- TEST sX, kk
|
aluOutInt <= opA and opB;
|
aluOutInt <= opA and opB;
|
xorAcc := '0';
|
xorAcc := '0';
|
for index in aluOutInt'range loop
|
for index in aluOutInt'range loop
|
xorAcc := xorAcc xor aluOutInt(index);
|
xorAcc := xorAcc xor aluOutInt(index);
|
end loop;
|
end loop;
|
cOut <= xorAcc;
|
cOut <= xorAcc;
|
when 10 => -- COMPARE sX, kk
|
when 10 => -- COMPARE sX, kk
|
yArith <= aArith - bArith;
|
yArith <= aArith - bArith;
|
aluOutInt <= yArith(aluOut'range);
|
aluOutInt <= yArith(aluOut'range);
|
cOut <= yArith(yArith'high);
|
cOut <= yArith(yArith'high);
|
when 12 => -- ADD sX, kk
|
when 12 => -- ADD sX, kk
|
yArith <= aArith + bArith;
|
yArith <= aArith + bArith;
|
aluOutInt <= yArith(aluOut'range);
|
aluOutInt <= yArith(aluOut'range);
|
cOut <= yArith(yArith'high);
|
cOut <= yArith(yArith'high);
|
when 13 => -- ADDCY sX, kk
|
when 13 => -- ADDCY sX, kk
|
yArith <= (aArith + bArith) + cInArith;
|
yArith <= (aArith + bArith) + cInArith;
|
aluOutInt <= yArith(aluOut'range);
|
aluOutInt <= yArith(aluOut'range);
|
cOut <= yArith(yArith'high);
|
cOut <= yArith(yArith'high);
|
when 14 => -- SUB sX, kk
|
when 14 => -- SUB sX, kk
|
yArith <= aArith - bArith;
|
yArith <= aArith - bArith;
|
aluOutInt <= yArith(aluOut'range);
|
aluOutInt <= yArith(aluOut'range);
|
cOut <= yArith(yArith'high);
|
cOut <= yArith(yArith'high);
|
when 15 => -- SUBCY sX, kk
|
when 15 => -- SUBCY sX, kk
|
yArith <= (aArith - bArith) - cInArith;
|
yArith <= (aArith - bArith) - cInArith;
|
aluOutInt <= yArith(aluOut'range);
|
aluOutInt <= yArith(aluOut'range);
|
cOut <= yArith(yArith'high);
|
cOut <= yArith(yArith'high);
|
when 16 to 23 => -- SL sX
|
when 16 to 23 => -- SL sX
|
aluOutInt <= opA(opA'high-1 downto 0) & cInShift;
|
aluOutInt <= opA(opA'high-1 downto 0) & cInShift;
|
cOut <= opA(opA'high);
|
cOut <= opA(opA'high);
|
when 24 to 31 => -- SR sX
|
when 24 to 31 => -- SR sX
|
aluOutInt <= cInShift & opA(opA'high downto 1);
|
aluOutInt <= cInShift & opA(opA'high downto 1);
|
cOut <= opA(0);
|
cOut <= opA(0);
|
when others =>
|
when others =>
|
aluOutInt <= (others => '-');
|
aluOutInt <= (others => '-');
|
end case;
|
end case;
|
end process aluOperation;
|
end process aluOperation;
|
|
|
aluOut <= aluOutInt;
|
aluOut <= aluOutInt;
|
zero <= '1' when aluOutInt = 0 else '0';
|
zero <= '1' when aluOutInt = 0 else '0';
|
|
|
END ARCHITECTURE RTL;
|
END ARCHITECTURE RTL;
|
|
|