Newer
Older
-------------------------------------------------------------------------------
-- Project ELE8304 : Circuits intégrés à très grande échelle
-------------------------------------------------------------------------------
-- File riscv_adder.vhd
-- Authors Titouan Luard <luardtitouan@gmail.com>
-- Yann Roberge <yann.roberge@polymtl.ca>
-- Lab GRM - Polytechnique Montreal
-------------------------------------------------------------------------------
-- Brief Full adder, supports sign-extension, addition-subtraction,
-- signed and unsigned.
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
library work;
use work.riscv_pkg.all;
entity riscv_adder is
generic (
port (
i_a : in std_logic_vector(N-1 downto 0);
i_b : in std_logic_vector(N-1 downto 0);
i_sign : in std_logic;
i_sub : in std_logic;
o_sum : out std_logic_vector(N downto 0));
end entity riscv_adder;
architecture beh of riscv_adder is
-- Entrées sign-extended
signal a_ext : std_logic_vector(N downto 0);
signal b_ext : std_logic_vector(N downto 0);
-- Complément à deux de B
signal b_compl2 : std_logic_vector(N downto 0);
-- Version de B à utiliser pour le calcul (complément ou pas)
signal b_operand : std_logic_vector(N downto 0);
-- Signaux temporaires
signal temp_sum1 : std_logic_vector(N downto 0);
signal temp_sum2 : std_logic_vector(N-1 downto 0);
signal temp_carry1 : std_logic_vector(N downto 0);
signal temp_carry2 : std_logic_vector(N-1 downto 0);
signal ored_carries : std_logic_vector(N-1 downto 0);
-- Bits de contrôles
constant OP_UNSIGNED : std_logic := '0';
constant OP_SIGNED : std_logic := '1';
constant OP_ADD : std_logic := '0';
constant OP_SUBTRACT : std_logic := '1';
sign_extend:
process (all) is
begin
if (i_sign = OP_UNSIGNED) then
a_ext <= '0' & i_a;
b_ext <= '0' & i_b;
else
a_ext <= i_a(N-1) & i_a;
b_ext <= i_b(N-1) & i_b;
end if;
end process sign_extend;
-- 2's complement
b_compl2 <= std_logic_vector( unsigned(not(b_ext)) + 1 );
-- Addition ou soustraction
b_operand <= b_compl2 when i_sub = OP_SUBTRACT else b_ext;
gen_half_adders_top:
half_adder: entity work.half_adder
port map (
i_a => a_ext(i),
o_sum => temp_sum1(i),
o_carry => temp_carry1(i)
);
end generate;
-- Gestion des retenues
ored_carries <= temp_carry1(N-1 downto 0) or (temp_carry2(N-2 downto 0) & '0');
gen_half_adders_bottom:
half_adder: entity work.half_adder
port map (
i_a => ored_carries(i),
i_b => temp_sum1(i+1),
o_sum => temp_sum2(i), --o_sum(2*i - 1);
o_carry => temp_carry2(i)
);
end generate;
-- Assignation de la somme:
-- Le LSB vient des half-adders du haut
-- Le reste vient des half-adders du bas
o_sum <= temp_sum2 & temp_sum1(0);