------------------------------------------------------------------------------- -- 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 -- Date 2021-10-29 ------------------------------------------------------------------------------- -- 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 ( N : positive := 32); 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); begin sign_extend: process (all) is begin if (i_sign = SIGN_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 = ARITH_SUBTRACT else b_ext; gen_half_adders_top: for i in 0 to N generate half_adder: entity work.half_adder port map ( i_a => a_ext(i), i_b => b_operand(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: for i in 0 to N-1 generate 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); end architecture beh;