Initial Commit
This commit is contained in:
124
soc/core/alu.vhd
Normal file
124
soc/core/alu.vhd
Normal file
@@ -0,0 +1,124 @@
|
||||
-- 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;
|
||||
Reference in New Issue
Block a user