library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.std_logic_unsigned.all;

LIBRARY altera;
USE altera.altera_primitives_components.all;

entity Qsys_ALU is
port (
clk :
in std_logic;
reset_n :
in std_logic; -- reset asserted low
avs_s1_address :
in std_logic_vector(2 downto 0);
avs_s1_write :
in std_logic;
avs_s1_writedata :
in std_logic_vector(31 downto 0);
avs_s1_read :
in std_logic;
avs_s1_readdata :
out std_logic_vector(31 downto 0);
switches :
in std_logic_vector(3 downto 0);
pushbutton :
in std_logic;
LEDs :
out std_logic_vector(7 downto 0)
);
end Qsys_ALU;

architecture Qsys_ALU_arch of Qsys_ALU is

signal reg0: std_logic_vector(31 downto 0);
signal reg1: std_logic_vector(31 downto 0);
signal reg2: std_logic_vector(31 downto 0);
signal reg3: std_logic_vector(31 downto 0);
signal reg4: std_logic_vector(31 downto 0);
signal reg5: std_logic_vector(31 downto 0);
signal LED_reg: std_logic_vector(7 downto 0);

shared variable temp_33: signed(31 downto 0);
shared variable temp_64: signed(63 downto 0);
shared variable temp_32: std_logic_vector(31 downto 0);
shared variable temp_32_dos: std_logic_vector(31 downto 0);
shared variable led_32: std_logic_vector(31 downto 0);
shared variable temp_shift: signed(31 downto 0);
shared variable temp_int: integer;
shared variable temp_hold: signed(63 downto 0);
shared variable temp_hold_32: signed(31 downto 0);

constant highbound : integer := ((2**31)-1);
constant lowbound : integer := (-1*(2**31)+1);

shared variable check: std_logic;

shared variable reg0_sig: std_logic_vector(31 downto 0);
shared variable reg1_sig: std_logic_vector(31 downto 0);

begin
                
                bus_logic:
process(clk)
                
begin
                
if rising_edge(clk) then
                
                        
if avs_s1_read = '1' then
                                
                        
if avs_s1_address = "000" then
                                avs_s1_readdata <= reg0;
                        
elsif avs_s1_address = "001" then
                                avs_s1_readdata <= reg1;
                        
elsif avs_s1_address = "010" then
                                avs_s1_readdata <= reg2;
                        
elsif avs_s1_address = "011" then
                                avs_s1_readdata <= reg3;
                        
elsif avs_s1_address = "100" then
                                avs_s1_readdata <= reg4;
                        
elsif avs_s1_address = "101" then
                                avs_s1_readdata <= reg5;
                        
end if;
                        
                        
                        
elsif avs_s1_write = '1' then
                        
                        
if avs_s1_address = "000" then
                                reg0 <= avs_s1_writedata;
                        
elsif avs_s1_address = "001" then
                                reg1 <= avs_s1_writedata;
                        
elsif avs_s1_address = "010" then
                                reg2 <= avs_s1_writedata;
                        
end if;
                        
                        
elsif check = '1' then
                                reg0 <= reg0_sig;
                                reg1 <= reg1_sig;
                                
                        
end if;
                
                
end if;
                
                
end process;
                
                LED_logic:
process(clk,reset_n,switches)
                
begin
                
if(reset_n = '0') then
                LEDs <=
"01010101";
                
elsif(rising_edge(clk)) then
                
                        
-- Switches 3 and 2
                        
if(switches(3 downto 2) = "00") then
                        led_32 :=
std_logic_vector(reg0);
                        
elsif(switches(3 downto 2) = "01") then
                        led_32 :=
std_logic_vector(reg1);
                        
elsif(switches(3 downto 2) = "10") then
                        led_32 :=
std_logic_vector(reg3);
                        
elsif(switches(3 downto 2) = "11") then
                        led_32 :=
std_logic_vector(reg4);
                        
end if;
                        
                        
-- Swtiches 1 and 2
                        
if(switches(1 downto 0) = "00") then
                        LEDs <= led_32(7
downto 0);
                        
elsif(switches(1 downto 0) = "01") then
                        LEDs <= led_32(15
downto 8);
                        
elsif(switches(1 downto 0) = "10") then
                        LEDs <= led_32(23
downto 16);
                        
elsif(switches(1 downto 0) = "11") then
                        LEDs <= led_32(31
downto 24);
                        
end if;
                
end if;
                
                
end process;
                
                ALU_logic:
process(reg2)
                
begin
                
if(rising_edge(clk)) then
                
                        check :=
'0';
                        
                        
-- Nop
                        
if(reg2(2 downto 0) = "000") then
                                
-- Do nothing
                                
                                reg3 <= (
others => '0');
                                reg4 <= (
others => '0');
                                reg5 <= (
others => '0');
                        
                        
-- Add
                        
elsif(reg2(2 downto 0) = "001") then
                        
                                temp_int := to_integer(
signed(reg0)+signed(reg1));
                                
-- Z flag
                                
if(temp_int = 0) then
                                reg5(0) <=
'1';
                                
else
                                reg5(0) <=
'0';
                                
end if;
                                
                                
-- N flag
                                
if(temp_int < 0) then
                                reg5(1) <=
'1';
                                
else
                                reg5(1) <=
'0';
                                
end if;
                                
                                
-- F flag and write to result
                                
                                
-- Handle positive overflow
                                
                                
if(temp_int > highbound) then
                                reg5(2) <=
'1';
                                temp_hold := to_signed(temp_int,64);
                                reg3 <=
std_logic_vector(temp_hold(31 downto 0));
                                reg4 <=
std_logic_vector(temp_hold(63 downto 32));
                                
                                
-- Handle negative overflow and sign extend
                                
elsif(temp_int < lowbound) then
                                reg5(2) <=
'1';
                                temp_64 := to_signed(temp_int,64);
                                reg3 <=
std_logic_vector(temp_64(31 downto 0));
                                reg4 <=
std_logic_vector(temp_64(63 downto 32));
                                
                                
else
                                temp_hold_32 := to_signed(temp_int,32);
                                reg5(2) <=
'0';
                                reg3 <=
std_logic_vector(temp_hold_32(31 downto 0));
                                reg4 <= (
others => '0');
                                
end if;
                                
                        
-- Subtract
                        
elsif(reg2(2 downto 0) = "010") then
                        
                                temp_int := to_integer(
signed(reg0)-signed(reg1));
                                
-- Z flag
                                
if(temp_int = 0) then
                                reg5(0) <=
'1';
                                
else
                                reg5(0) <=
'0';
                                
end if;
                                
                                
-- N flag
                                
if(temp_int < 0) then
                                reg5(1) <=
'1';
                                
else
                                reg5(1) <=
'0';
                                
end if;
                                
                                
-- F flag and write to result
                                
                                
-- Handle positive overflow
                                
                                
if(temp_int > highbound) then
                                reg5(2) <=
'1';
                                temp_hold := to_signed(temp_int,64);
                                reg3 <=
std_logic_vector(temp_hold(31 downto 0));
                                reg4 <=
std_logic_vector(temp_hold(63 downto 32));
                                
                                
-- Handle negative overflow and sign extend
                                
elsif(temp_int < lowbound) then
                                reg5(2) <=
'1';
                                temp_64 := to_signed(temp_int,64);
                                reg3 <=
std_logic_vector(temp_64(31 downto 0));
                                reg4 <=
std_logic_vector(temp_64(63 downto 32));
                                
                                
else
                                temp_hold_32 := to_signed(temp_int,32);
                                reg5(2) <=
'0';
                                reg3 <=
std_logic_vector(temp_hold_32(31 downto 0));
                                reg4 <= (
others => '0');
                                
end if;
                                
                        
-- Multiply
                        
elsif(reg2(2 downto 0) = "011") then
                                temp_64 :=
signed(reg0) * signed(reg1);
                                
                                
-- Z flag
                                
if(temp_64 = 0) then
                                reg5(0) <=
'1';
                                
else
                                reg5(0) <=
'0';
                                
end if;
                                
                                
-- N flag
                                
if(temp_64 < 0) then
                                reg5(1) <=
'1';
                                
else
                                reg5(1) <=
'0';
                                
end if;
                                
                                
-- F flag and write to result
                                
                                
-- Handle positive overflow
                                
                                
if(temp_64 > highbound) then
                                reg5(2) <=
'1';
                                reg3 <=
std_logic_vector(temp_64(31 downto 0));
                                reg4 <=
std_logic_vector(temp_64(63 downto 32));
                                
                                
-- Handle negative overflow and sign extend
                                
elsif(temp_64 < lowbound) then
                                reg5(2) <=
'1';
                                reg3 <=
std_logic_vector(temp_64(31 downto 0));
                                reg4 <=
std_logic_vector(temp_64(63 downto 32));
                                
                                
else
                                temp_int := to_integer(temp_64);
                                temp_hold_32 := to_signed(temp_int,32);
                                reg5(2) <=
'0';
                                reg3 <=
std_logic_vector(temp_hold_32(31 downto 0));
                                reg4 <= (
others => '0');
                                
end if;
                                
                                
                        
-- Decrement B
                        
elsif(reg2(2 downto 0) = "100") then        
                                temp_int := to_integer(
signed(reg1) - 1);
                                
                                
-- Z flag
                                
if(temp_33 = 0) then
                                reg5(0) <=
'1';
                                
else
                                reg5(0) <=
'0';
                                
end if;
                                
                                
-- N flag
                                
if(temp_33 < 0) then
                                reg5(1) <=
'1';
                                
else
                                reg5(1) <=
'0';
                                
end if;
                                
                                
-- F flag
                                
if(temp_int < lowbound) then
                                reg5(2) <=
'1';
                                temp_64 := to_signed(temp_int,64);
                                reg3 <=
std_logic_vector(temp_64(31 downto 0));
                                reg4 <=
std_logic_vector(temp_64(63 downto 32));
                                
else
                                reg5(2) <=
'0';
                                reg3 <=
std_logic_vector(to_signed(temp_int,32));
                                reg4 <= (
others => '0');
                                
end if;
                        
                        
-- Move A
                        
elsif(reg2(2 downto 0) = "101") then
                                        reg3 <= reg0;
                                        
                                
-- Z flag
                                
if(signed(reg0) = 0) then
                                reg5(0) <=
'1';
                                
else
                                reg5(0) <=
'0';
                                
end if;
                                
                                
-- N flag
                                
if(signed(reg0) < 0) then
                                reg5(1) <=
'1';
                                
else
                                reg5(1) <=
'0';
                                
end if;
                                
                                
-- F flag
                                reg5(2) <=
'0';
                                
                        
-- Swap
                        
elsif(reg2(2 downto 0) = "101") then
                                temp_32 := reg0;
                                temp_32_dos := reg1;
                                
                                check :=
'1';
                                reg0_sig := temp_32_dos;
                                reg1_sig := temp_32;
                                
                                reg5(0) <=
'0';
                                reg5(1) <=
'0';
                                reg5(2) <=
'0';
                        
                        
-- Logical shift left A
                        
elsif(reg2(2 downto 0) = "110") then
                                temp_shift := shift_left(
signed(reg0),1);
                                
                                
-- Z flag
                                
if(temp_shift = 0) then
                                reg5(0) <=
'1';
                                
else
                                reg5(0) <=
'0';
                                
end if;
                                
                                
-- N flag
                                
if(temp_shift < 0) then
                                reg5(1) <=
'1';
                                
else
                                reg5(1) <=
'0';
                                
end if;
                                
                                
-- F flag
                                reg5(2) <=
'0';
                                
                                
-- Write result
                                reg3 <=
std_logic_vector(temp_shift);
                                reg4 <= (
others => '0');
                                
                
end if;                
                
end if;
                
end process;
                


end architecture;