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

architecture arch of key_hash_generator is
    
    type STAGE_TYPE is (IDLE, GEN_CHECKSUM, FINALIZE);
    
    signal stage, stage_next : STAGE_TYPE;
    signal checksum, checksum_next : std_logic_vector(127 downto 0);
    signal done_sig, done_sig_next : std_logic;
    
begin
    
    done        <= done_sig;
    key_hash    <= checksum;
    
    checksum_prc : process(all)
    begin
        -- DEFAULT
        stage_next      <= stage;
        checksum_next   <= checksum;
        done_sig_next   <= '0';
        ack             <= '0';
        ready_in        <= '0';
        
        case (stage) is
            when IDLE =>
                if (start = '1') then
                    ack         <= '1';
                    stage_next  <= GEN_CHECKSUM;
                    -- Reset
                    checksum_next   <= (others => '0');
                end if;
            when GEN_CHECKSUM =>
                ready_in    <= '1';
                -- Input Guard
                if (valid_in = '1') then
                    checksum_next   <= std_logic_vector(unsigned(checksum) + resize(unsigned(data_in),checksum'length));
                    
                    -- Last Word
                    if (last_word_in = '1') then
                        stage_next  <= FINALIZE;
                    end if;
                end if;
            when FINALIZE =>
                checksum_next   <= std_logic_vector(-signed(checksum)); -- Two's Complement
                done_sig_next   <= '1';
                stage_next      <= IDLE;
            when others =>
                null;
        end case;
    end process;
    
    sync_prc : process(clk)
    begin
        if rising_edge(clk) then
            if (reset = '1') then
                stage       <= IDLE;
                done_sig    <= '0';
                checksum    <= (others => '0');
            else
                stage       <= stage_next;
                done_sig    <= done_sig_next;
                checksum    <= checksum_next;
            end if;
        end if;
    end process;
    
end architecture;