125 lines
3.1 KiB
VHDL
125 lines
3.1 KiB
VHDL
-- See the file "LICENSE" for the full license governing this code. --
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
use work.lt16x32_internal.all;
|
|
|
|
-- the ALU offers various two-input arithmetic and logic operations and is fully combinatoric
|
|
entity alu is
|
|
port(
|
|
-- Data Input
|
|
in_a : in signed(reg_width - 1 downto 0);
|
|
in_b : in signed(reg_width - 1 downto 0);
|
|
|
|
-- Truth Flag
|
|
t_out : out std_logic;
|
|
|
|
-- Overflow Flag
|
|
ovf_out : out std_logic;
|
|
|
|
-- Mode of Operation
|
|
mode : in alu_mode_type;
|
|
|
|
-- Data Output
|
|
data_out : out signed(reg_width - 1 downto 0)
|
|
);
|
|
end entity alu;
|
|
|
|
architecture RTL of alu is
|
|
begin
|
|
|
|
-- calculate the result
|
|
calc_out : process(in_a, in_b, mode) is
|
|
-- used to store the result temporarily (e.g. if needed for flag calculation)
|
|
variable result : signed(reg_width - 1 downto 0);
|
|
begin
|
|
-- default outputs
|
|
data_out <= (others => '0');
|
|
ovf_out <= '0';
|
|
t_out <= '0';
|
|
|
|
-- different result for each mode
|
|
case mode is
|
|
-- arithmetic modes
|
|
|
|
when alu_add => -- addition
|
|
result := in_a + in_b;
|
|
|
|
data_out <= result;
|
|
ovf_out <= (in_a(reg_width - 1) AND in_b(reg_width - 1) AND not result(reg_width - 1)) OR (not in_a(reg_width - 1) AND not in_b(reg_width - 1) AND result(reg_width - 1));
|
|
|
|
when alu_sub => -- subtraction
|
|
result := in_a - in_b;
|
|
|
|
data_out <= result;
|
|
ovf_out <= (in_a(reg_width - 1) AND not in_b(reg_width - 1) AND not result(reg_width - 1)) OR (not in_a(reg_width - 1) AND in_b(reg_width - 1) AND result(reg_width - 1));
|
|
|
|
when alu_and => -- bitwise and
|
|
data_out <= in_a and in_b;
|
|
|
|
when alu_or => -- bitwise or
|
|
data_out <= in_a or in_b;
|
|
|
|
when alu_xor => -- bitwise xor
|
|
data_out <= in_a xor in_b;
|
|
|
|
when alu_lsh => -- logic left shift
|
|
data_out <= in_a sll (to_integer(unsigned(in_b(3 downto 0))) + 1);
|
|
|
|
when alu_rsh => -- logic right shift
|
|
data_out <= in_a srl (to_integer(unsigned(in_b(3 downto 0))) + 1);
|
|
|
|
-- compare modes
|
|
when alu_cmp_eq => -- compare for A = B
|
|
if (in_a = in_b) then
|
|
t_out <= '1';
|
|
else
|
|
t_out <= '0';
|
|
end if;
|
|
|
|
when alu_cmp_neq => -- compare for not equal
|
|
if (in_a /= in_b) then
|
|
t_out <= '1';
|
|
else
|
|
t_out <= '0';
|
|
end if;
|
|
|
|
when alu_cmp_ge => -- compare for greater than or equal
|
|
if (in_a >= in_b) then
|
|
t_out <= '1';
|
|
else
|
|
t_out <= '0';
|
|
end if;
|
|
|
|
when alu_cmp_gg => -- compare for greater than
|
|
if (in_a > in_b) then
|
|
t_out <= '1';
|
|
else
|
|
t_out <= '0';
|
|
end if;
|
|
|
|
when alu_cmp_le => -- compare for less than or equal
|
|
if (in_a <= in_b) then
|
|
t_out <= '1';
|
|
else
|
|
t_out <= '0';
|
|
end if;
|
|
|
|
when alu_cmp_ll => -- compare for less than
|
|
if (in_a < in_b) then
|
|
t_out <= '1';
|
|
else
|
|
t_out <= '0';
|
|
end if;
|
|
|
|
when alu_cmp_true => -- always set truth-flag
|
|
t_out <= '1';
|
|
|
|
when alu_cmp_false => -- always reset truth-flag
|
|
t_out <= '0';
|
|
end case;
|
|
end process calc_out;
|
|
|
|
end architecture RTL;
|