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_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;

u_add: entity word.add
    port map (
        clk => clk,
        reset => reset,
        
        task_start => task_start,
        task_state => task_state,
        
        signal_a_read => signal_a_read,
        signal_a_readdata => signal_a_readdata,
        
        signal_b_read => signal_b_read,
        signal_b_readdata => signal_b_readdata,
        
        signal_write => signal_write,
        signal_writedata => signal_writedata
);

        
    
    
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;
    signal state : integer range 0 to 255;
    signal reset : integer range 0 to 7;
    signal start : integer range 0 to 7;
    signal done : integer range 0 to 7;
    signal A : STD_LOGIC_VECTOR(31 downto 0);
    signal B : STD_LOGIC_VECTOR(31 downto 0);
    signal sum : STD_LOGIC_VECTOR(31 downto 0);

begin
    
    u_float_add : entity work.float_add
        port map (
            clk => clk,
            reset => reset,
            start => start,
            done => done,
            A => A,
            B => B,
            sum => sum
        );

    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 - 1 ) 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;

    sync : process ( clk, reset ) is
    begin
        if ( reset = '1' ) then
            current_task_state <= work.task.TASK_IDLE;
            signal_a_read <= 'O';
            signal_b_read <= 'O';
            signal_write <= 'O';
            signal_Writedata <= (others => '0');
            index <= 0;
            state <= 0;
            sum <= 0;
            done <= 0;
            start <= 0;
        elsif ( rising_edge( clk ) ) then
            current_task_state <= next_task_state;
            case next_task_state is
            when work.task.TASK_IDLE =>
                index <= 0;
                signal_write <= '0';
            when work.task.TASK_RUNNING =>
                index <= index + 1;
                --signal_a_read <= '1' ;
                --signal_b_read <= '1' ;
                signal_write <= '1';
                signal_writedata <= ( others => '0' );
            when work.task.TASK_DONE =>
                index <= 0;
                signal_write <= '0';
            end case;
        end if;
    end process sync;

    task_state <= current_task_state;

end architecture rtl;
