--- Code for LSU EE 4702 Spring 2001

--- Adder 

library ieee;
use ieee.std_logic_1164.all;

entity adder is
  -- Specify adder width, like a parameter in Verilog.
  generic( w: integer:= 8);
  port( a, b: in std_logic_vector (w-1 downto 0);
        sum : out std_logic_vector (w downto 0));
end adder;

-- Behavioral description of adder.

architecture a1 of adder is

begin
  p:process(a,b)
    variable c: std_logic;  -- Carry bit.
  begin

    c := '0';

    for i in a'reverse_range loop

      sum(i) <= a(i) xor b(i) xor c;
      c := ( a(i) and b(i) ) or ( a(i) and c ) or ( b(i) and c );

    end loop;

    sum(sum'left) <= c;

  end process p;

end a1;
    
-- Structural Description of Hardware
-- Ignores width specification.

architecture a2 of adder is

  signal c: std_logic_vector (7 downto 0);

begin
  b0:entity work.bfa port map(a(0),b(0),'0',sum(0),c(0));
  b1:entity work.bfa port map(a(1),b(1),c(0),sum(1),c(1));
  b2:entity work.bfa port map(a(2),b(2),c(1),sum(2),c(2));
  b3:entity work.bfa port map(a(3),b(3),c(2),sum(3),c(3));
  b4:entity work.bfa port map(a(4),b(4),c(3),sum(4),c(4));
  b5:entity work.bfa port map(a(5),b(5),c(4),sum(5),c(5));
  b6:entity work.bfa port map(a(6),b(6),c(5),sum(6),c(6));
  b7:entity work.bfa port map(a(7),b(7),c(6),sum(7),sum(8));
end a2;

-- Structural Description Using Generate
-- Uses width specification (by basing generates on a and b sizes).

architecture a3 of adder is

  signal c: std_logic_vector (a'left-1 downto 0);

begin
  G1: for i in a'range generate
    MSB: if i = a'left generate
      bfa1:entity work.bfa port map( a(i), b(i), c(i-1), sum(i), sum(i+1) );
    end generate;
    Mid_Bits: if i > a'right and i < a'left generate
      bfa2:entity work.bfa port map( a(i), b(i), c(i-1), sum(i), c(i) );
    end generate;
    LSB: if i = a'right generate
      bfa3:entity work.bfa port map( a(i), b(i), '0', sum(i), c(i) );
    end generate;
    
  end generate;
end a3;


library ieee;
use ieee.std_logic_1164.all;
library Std_DevelopersKit;
use Std_DevelopersKit.Std_Regpak.all;

-- Adder Testbench

entity addertb is end;

architecture a1 of addertb is

  constant width: integer := 4;

  signal a,b:std_logic_vector ( width-1 downto 0 );
  signal sum:std_logic_vector ( width downto 0 );

begin

  adder1:entity work.adder(a3)
    generic map( w => width )
    port map(a, b, sum); 
  
  process
    variable sum_tb:integer;
    
  begin

    for i in 0 to 2**width-1 loop
      for j in 0 to 2**width-1 loop
        a <= to_stdlogicvector(i,a'length);
        b <= to_stdlogicvector(j,b'length);
        sum_tb := i + j;
        wait for 20 ns;
        assert sum_tb = '0' & sum
          report "Wrong output."
          severity failure;
      end loop;
    end loop;

    assert false
      report "Not really a fatal error, only way I know to stop the sim."
      severity failure;
    
  end process;

end architecture a1;