library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

library work;
    use work.reg32.all;
    use work.task.all;

entity add is
    port (
        clk : in std_logic;
        reset : in std_logic;

        task_start : in std_logic;
        task_state : out work.task.State;
					
        signal_a_read : out std_logic;				--signal_read wird als Bestätigung gesetzt, dass die Daten gelesen wurden, d.h. bei der nächsten rising edge werden die nächsten Daten angelegt.
        signal_a_readdata : in std_logic_vector( 31 downto 0 );

        signal_b_read : out std_logic;
        signal_b_readdata : in std_logic_vector( 31 downto 0 );

        signal_write : out std_logic;
        signal_writedata : out std_logic_vector( 31 downto 0 )
    );
end entity add;

architecture rtl of add is
    signal current_task_state : work.task.State;
    signal next_task_state : work.task.State;
    signal index : integer range 0 to work.task.STREAM_LEN;

	--hier noch einige Signale anlegen
	signal done_flag  : std_logic;
	signal start_flag : std_logic;

	--Zustände für die Zustandsmaschine für die Berechnung
	type CalcState is (
		CALC_IDLE,
		CALC_ADD,
		CALC_STORE_RESULT
	);

	--Signale für die Zustandsmaschine für die Berechnung
	signal current_calc_state : CalcState;
	signal next_calc_state : CalcState;

	signal ergebnis : signed( 31 downto 0);	--das hier vielleicht zu std_logic_vector oder float
	signal ergebnis_valid : std_logic;

begin

	u_float_add : entity work.float_add --Das hier ist der IP Core !!!
	port map(
		clk =>		clk,
		reset =>	reset,
		start =>	start_flag,
		done =>		done_flag,
		A =>		signal_a_readdata,
		B =>		signal_b_readdata,
		sum =>		signal_writedata
	);

    --task_state_transitions wird nicht geaendert
    --Übergangsschaltnetz der Zustandsmaschine zu Steuerung der Tasks
    task_state_transitions : process ( current_task_state, task_start, index ) is
    begin
        next_task_state <= current_task_state;
        case current_task_state is
            when work.task.TASK_IDLE =>
                if ( task_start = '1' ) then
                    next_task_state <= work.task.TASK_RUNNING;
                end if;
            when work.task.TASK_RUNNING =>
                if ( index = work.task.STREAM_LEN  ) then
                    next_task_state <= work.task.TASK_DONE;
                end if;
            when work.task.TASK_DONE =>
                if ( task_start = '1' ) then
                    next_task_state <= work.task.TASK_RUNNING;
                end if;
        end case;
    end process task_state_transitions;

	
	--Übergangsschaltnetz der Zustandsmaschine für die Berechnung ###Fertig
	calc_state_transitions: process (all) is
	begin
		next_calc_state <= current_calc_state; 
		case current_calc_state is
			when CALC_IDLE=>
				if (current_task_state= work.task.TASK_RUNNING) then 
					next_calc_state <= CALC_ADD;
				end if;
			when CALC_ADD =>
				if (done_flag = '1') then
					next_calc_state <= CALC_STORE_RESULT;
				end if;
			when CALC_STORE_RESULT =>
				next_calc_state <= CALC_IDLE;
		end case;
	end process calc_state_transitions;


	--Zustandsspeicher und Ausgangsschaltnetz zu der Steuerung der Tasks 
	task_sync : process (clk, reset) is
	begin
		if (reset = '1') then
			current_task_state <= work.task.TASK_IDLE;
			
		elsif (rising_edge( clk)) then
			current_task_state <= next_task_state; 
			case next_task_state is
				when work.task. TASK_IDLE => null;
				when work.task. TASK_RUNNING => null; 
				when work.task. TASK_DONE => null;
			end case;
		end if;
	end process task_sync;

	--Zustandsspeicher und Ausgangsschaltnetz zu Berechnung 
	sync : process (clk, reset) is
	begin
		if (reset = '1') then
			index <= 0;
			current_calc_state <= CALC_IDLE;
			ergebnis <= (others => '0'); 
			ergebnis_valid <= '0';
			signal_write <= '0';
			--signal_writedata <= (others => '0'); 
			signal_a_read <= '0';
			signal_b_read <= '0';
		elsif (rising_edge( clk)) then
			current_calc_state <= next_calc_state; 
			ergebnis_valid <= '0';
			case next_calc_state is 
				when CALC_IDLE =>
					start_flag <= '0';
					signal_a_read <= '0';	--Daten wurden noch nicht verwendet.
					signal_b_read <= '0';
					signal_write <= '0';
				when CALC_ADD => 				--hier Berechnung mit IP Core?
					start_flag <= '1';
				when CALC_STORE_RESULT =>
					start_flag <= '0';
					index <= index + 1;
					signal_write <= '1';
					--signal_writedata <= std_logic_vector( ergebnis ); --Ergebnis schreiben, ergebnis direkt aus IP Core anschliessen
					--mitteilen, dass die Daten gelesen wurden und jetzt neue Daten angelegt werden sollen
					signal_a_read <= '1';	
					signal_b_read <= '1';
			end case;
		end if;
	end process sync;
	task_state <= current_task_state;

end architecture rtl;
