Skip to content
Snippets Groups Projects
riscv_adder.vhd 2.99 KiB
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 (
8304_9's avatar
8304_9 committed
    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);

  sign_extend:
  process (all) is
  begin
      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;
8304_9's avatar
8304_9 committed
  for i in 0 to N generate
    half_adder: entity work.half_adder
      port map (
        i_a     => a_ext(i),
8304_9's avatar
8304_9 committed
        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:
8304_9's avatar
8304_9 committed
  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:
8304_9's avatar
8304_9 committed
  -- 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;