-- Copyright 2000 UCR all rights reserved
-- this program may be copy or altered so
-- long as this header stays intake
-- Original design Randy January rjanuary@cs.ucr.edu

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use WORK.SCPU_LIB.all;

entity scpu_alu is
  port (
    reset     : in std_logic;
    alu_sel   : in UNSIGNED (2 downto 0);
    input1    : in UNSIGNED (31 downto 0);
    input2    : in UNSIGNED (31 downto 0);
    output    : out unsigned (31 downto 0);
    interrupt : out std_logic
    );
end scpu_alu;

architecture scpu_alu of scpu_alu is

--***********************************************************************
signal total, sig_input1, sig_input2 : unsigned (32 downto 0);
--***********************************************************************

begin
  process(reset, alu_sel, input1, input2)
    begin
      
--***********************************************************************

      if (reset = '1') then
        output <= "00000000000000000000000000000000";
        interrupt <= '0';
        sig_input1 <= "000000000000000000000000000000000";
        sig_input2 <= "000000000000000000000000000000000";
        total <= "000000000000000000000000000000000";
        
--***********************************************************************
        
      else
        case alu_sel is
          
          --pass
          when "000" => output <= input1;

          --add
          when "001" =>
          output <= input1 + input2;
--             sig_input1(32) <= '0';
--             sig_input2(32) <= '0';
--             sig_input1(31 downto 0) <= input1(31 downto 0);
--             sig_input2(31 downto 0) <= input2(31 downto 0);
--             total <= sig_input1 + sig_input2;
--             --check for overflow 
--             if (total(32) = not total(31)) then
--               interrupt <= '1';  
--             end if;
--             output <= total(31 downto 0);

          --subtract
          when "010" =>
            output <= input1 - input2;
       
--               sig_input1(32) <= '0';      -- set overflow bit to zero
--               sig_input2(32) <= '0';
--               sig_input1(31 downto 0) <= input1(31 downto 0);
--               sig_input2(31 downto 0) <= input2(31 downto 0);

            -- I tried unsuccessfully to use two's complement subtraction
--               for i in 0 to 31 loop
--                 if (sig_input2(i) = '0') then
--                   sig_input2(i) <= '1';
--                 else
--                   sig_input2(i) <= '0';
--                 end if;
--               end loop;
--               sig_input2 <= sig_input2 + 1;
            
--               total <= sig_input1 - sig_input2;
--               --check for overflow 
--               if (total(32) = not total(31)) then
--                 interrupt <= '1';
--                 output <= "--------------------------------";

--               else
--                 output <= total(31 downto 0);
--               end if;
        
              
          --and
          when "011" =>  
           output(31) <= input1(31) and input2(31);
           output(30) <= input1(30) and input2(30);
           output(29) <= input1(29) and input2(29);
           output(28) <= input1(28) and input2(28);
           output(27) <= input1(27) and input2(27);
           output(26) <= input1(26) and input2(26);
           output(25) <= input1(25) and input2(25);
           output(24) <= input1(24) and input2(24);  
           output(23) <= input1(23) and input2(23);
           output(22) <= input1(22) and input2(22);
           output(21) <= input1(21) and input2(21);
           output(20) <= input1(20) and input2(20);
           output(19) <= input1(19) and input2(19);
           output(18) <= input1(18) and input2(18);
           output(17) <= input1(17) and input2(17);
           output(16) <= input1(16) and input2(16);  
           output(15) <= input1(15) and input2(15);
           output(14) <= input1(14) and input2(14);
           output(13) <= input1(13) and input2(13);
           output(12) <= input1(12) and input2(12);
           output(11) <= input1(11) and input2(11);
           output(10) <= input1(10) and input2(10);
           output(9) <= input1(9) and input2(9);
           output(8) <= input1(8) and input2(8);  
           output(7) <= input1(7) and input2(7);
           output(6) <= input1(6) and input2(6);
           output(5) <= input1(5) and input2(5);
           output(4) <= input1(4) and input2(4);
           output(3) <= input1(3) and input2(3);
           output(2) <= input1(2) and input2(2);
           output(1) <= input1(1) and input2(1);
           output(0) <= input1(0) and input2(0);
           
          --XOR
          when "100" =>
          output(31) <= input1(31) XOR input2(31);
          output(30) <= input1(30) XOR input2(30);
          output(29) <= input1(29) XOR input2(29);
          output(28) <= input1(28) XOR input2(28);
          output(27) <= input1(27) XOR input2(27);
          output(26) <= input1(26) XOR input2(26);
          output(25) <= input1(25) XOR input2(25);
          output(24) <= input1(24) XOR input2(24);  
          output(23) <= input1(23) XOR input2(23);
          output(22) <= input1(22) XOR input2(22);
          output(21) <= input1(21) XOR input2(21);
          output(20) <= input1(20) XOR input2(20);
          output(19) <= input1(19) XOR input2(19);
          output(18) <= input1(18) XOR input2(18);
          output(17) <= input1(17) XOR input2(17);
          output(16) <= input1(16) XOR input2(16);  
          output(15) <= input1(15) XOR input2(15);
          output(14) <= input1(14) XOR input2(14);
          output(13) <= input1(13) XOR input2(13);
          output(12) <= input1(12) XOR input2(12);
          output(11) <= input1(11) XOR input2(11);
          output(10) <= input1(10) XOR input2(10);
          output(9) <= input1(9) XOR input2(9);
          output(8) <= input1(8) XOR input2(8);  
          output(7) <= input1(7) XOR input2(7);
          output(6) <= input1(6) XOR input2(6);
          output(5) <= input1(5) XOR input2(5);
          output(4) <= input1(4) XOR input2(4);
          output(3) <= input1(3) XOR input2(3);
          output(2) <= input1(2) XOR input2(2);
          output(1) <= input1(1) XOR input2(1);
          output(0) <= input1(0) XOR input2(0);
          
          -- mult and div were here, they were removed
          
          -- or
          when "110" =>
          output(31) <= input1(31) OR input2(31);
          output(30) <= input1(30) OR input2(30);
          output(29) <= input1(29) OR input2(29);
          output(28) <= input1(28) OR input2(28);
          output(27) <= input1(27) OR input2(27);
          output(26) <= input1(26) OR input2(26);
          output(25) <= input1(25) OR input2(25);
          output(24) <= input1(24) OR input2(24);  
          output(23) <= input1(23) OR input2(23);
          output(22) <= input1(22) OR input2(22);
          output(21) <= input1(21) OR input2(21);
          output(20) <= input1(20) OR input2(20);
          output(19) <= input1(19) OR input2(19);
          output(18) <= input1(18) OR input2(18);
          output(17) <= input1(17) OR input2(17);
          output(16) <= input1(16) OR input2(16);  
          output(15) <= input1(15) OR input2(15);
          output(14) <= input1(14) OR input2(14);
          output(13) <= input1(13) OR input2(13);
          output(12) <= input1(12) OR input2(12);
          output(11) <= input1(11) OR input2(11);
          output(10) <= input1(10) OR input2(10);
          output(9) <= input1(9) OR input2(9);
          output(8) <= input1(8) OR input2(8);  
          output(7) <= input1(7) OR input2(7);
          output(6) <= input1(6) OR input2(6);
          output(5) <= input1(5) OR input2(5);
          output(4) <= input1(4) OR input2(4);
          output(3) <= input1(3) OR input2(3);
          output(2) <= input1(2) OR input2(2);
          output(1) <= input1(1) OR input2(1);
          output(0) <= input1(0) OR input2(0);

          when others => NULL;
                         
        end case;
      end if;
    end process;
end scpu_alu;






