--- Code for LSU EE 4702 Spring 2001

--- Binary Full Adder (BFA) and Testbench

library ieee;
use ieee.std_logic_1164.all;

 --- BFA Interface Declaration.  Two architectures (implementations) follow.

entity bfa is
  port( a, b, ci: in std_logic;
        s, co: out std_logic );
end bfa;

 --- Architecture 1.

architecture bfa_c of bfa is
begin
  s <= a xor b xor ci;
  co <= ( a and b ) or ( a and ci ) or ( b and ci );
end bfa_c;
  
 --- Architecture 2.

architecture bfa_s of bfa is
begin
  p:process(a,b,ci)
  begin
    s <= reject 1 ns inertial    a xor b xor ci   after 3 ns;
    co <= transport ( a and b ) or ( a and ci ) or ( b and ci ) after 2 ns;
  end process p;
end bfa_s;



 --- BFA Testbench

-- Note: libraries must be re-declared for each entity.

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

entity atest is end;

-- Testbench, instantiating bfa the hard way.

architecture atest1 of atest is

  component some_bfa
    port(a,b,ci: in std_logic;
         s, co: out std_logic);
  end component;

  signal a, b, cin, s, cout: std_logic := '0';

  for bfa1:some_bfa use entity work.bfa(bfa_c);

  -- Iterator for bfa inputs.
  signal i: std_logic_vector ( 2 downto 0 ) := b"000";
  -- Better way of setting inputs to i.
--  alias a: std_logic is i(0);
--  alias b: std_logic is i(1);
--  alias cin: std_logic is i(2);

begin

  bfa1:some_bfa port map(a=>a, b=>b, ci=>cin, s=>s, co=>cout);

  -- Connect BFA inputs to i.  Lines execute whenever referenced
  -- bit in i changes.
  a <= i(0);
  b <= i(1);
  cin <= i(2);

  -- Iterate over values of i then exit.
  process
  begin

    while true loop
      exit when i = -1;  -- i is interpreted as signed.
      wait for 5 ns;
      i <= i + 1;
    end loop;

    -- Stop the simulation.
    assert false
      report "Done with tests."
      severity failure;
    
  end process;

  -- Check the outputs whenever anything changes.
  process
    variable sum_tb, sum_mod: std_logic_vector ( 1 downto 0 );
  begin

    wait on a, b, cin, s, cout;
    wait for 1 ns;

    sum_tb := ('0'&a) + b + cin;
    sum_mod := cout & s;

    assert sum_tb = sum_mod
      report "Wrong output "
      severity failure;
    
  end process;

end atest1;

 --- Testbench, instantiating bfa the easier way.

architecture atest2 of atest is
  -- Wires connecting to bfa.
  signal a, b, cin, s, cout: std_logic := '0';

  -- Iterator for bfa inputs, initialized to zero.
  signal i: std_logic_vector ( 2 downto 0 ) := b"000";

begin

  bfa1:entity work.bfa(bfa_c) port map(a, b, cin, s, cout);

  -- Connect BFA inputs to i.  Lines execute whenever referenced
  -- bit in i changes.
  a <= i(0);
  b <= i(1);
  cin <= i(2);

  -- Iterate over values of i then exit.
  -- Line executes whenever i changes.
  i <= i + 1 after 5 ns;
  
  process
  begin

    wait until i = b"111";  -- Wait for 7.
    wait until i = b"000";  -- Wait for zero. (Had to wait for 7 first.)
    
    -- Stop the simulation.
    assert false
      report "Done with tests."
      severity failure;
    
  end process;

  -- Check the outputs whenever anything changes.
  process
    variable sum_tb, sum_mod: std_logic_vector ( 1 downto 0 );
  begin

    wait on a, b, cin, s, cout;
    wait for 1 ns;

    sum_tb := ('0'&a) + b + cin;
    sum_mod := cout & s;

    assert sum_tb = sum_mod
      report "Wrong output "
      severity failure;
    
  end process;

end atest2;