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

library work;
    use work.reg32.all;
    use work.avalon_slave.all;
    use work.test_utility.all;
    use work.test_avalon_slave.all;
    use work.task.all;
    use work.crc_data.all;
    use work.fft_data.all;
    use work.test_hardware_task.all;
    use work.test_data_channel_pkg.all;

library std;
    use std.env.all;
    use std.textio.all;

entity test_task_crc is
    generic( CHECK_RESULTS : boolean );
end entity test_task_crc;

architecture test of test_task_crc is

    signal clk : std_logic := '0';
    signal reset : std_logic := '1';

    signal req : work.avalon_slave.Request;
    signal rsp : work.avalon_slave.Response;

    signal data_channel_req : work.avalon_slave.Request;
    signal data_channel_rsp : work.avalon_slave.Response;

    signal signal_read : std_logic;
    signal signal_readdata : std_logic_vector( 31 downto 0 );

    signal signal_write : std_logic;
    signal signal_writedata : std_logic_vector( 31 downto 0 );

    signal data_channel_read : std_logic;
    signal data_channel_readdata : std_logic_vector( 31 downto 0 );

    signal index_output : integer range 0 to 1023;

begin

    dut : entity work.task_crc
        port map (
            clk => clk,
            reset => reset,

            address => req.address,
            read => req.read,
            readdata => rsp.readdata,
            write => req.write,
            writedata => req.writedata,

            signal_read => signal_read,
            signal_readdata => signal_readdata,

            signal_write => signal_write,
            signal_writedata => signal_writedata
        );

    u_data_channel : entity work.data_channel
        port map (
            clk => clk,
            reset => reset,

            ctrl_address => data_channel_req.address,
            ctrl_read => data_channel_req.read,
            ctrl_readdata => data_channel_rsp.readdata,
            ctrl_write => data_channel_req.write,
            ctrl_writedata => data_channel_req.writedata,

            hw_sink_write => signal_write,
            hw_sink_writedata => signal_writedata,

            hw_source_read => data_channel_read,
            hw_source_readdata => data_channel_readdata
        );

    clk <= not clk after 10 ns;

    reset_release : process is
    begin
         wait for 35 ns;
         reset <= '0';
         wait;
    end process reset_release;

    p_number_input_sample: process ( clk, reset ) is
    begin
        if ( reset = '1' ) then
            index_output <= 1;
            signal_readdata <= to_std_logic_vector( to_float( work.fft_data.expected( 0 ) ) );
        elsif ( rising_edge( clk ) ) then
            if signal_read = '1' then
               if index_output /= 1023 then
               index_output <= index_output + 1;
               end if;
             signal_readdata <= to_std_logic_vector( to_float( work.fft_data.expected( index_output ) ) );
            end if;
        end if;
    end process p_number_input_sample;

    stimulus: process is
        variable data_channel_config : std_logic_vector( 31 downto 0 ) := x"00000001";
        variable expected_crc_value : std_logic_vector( 31 downto 0 ) := work.crc_data.expected;
    begin
        wait until falling_edge( reset );

        work.test_data_channel_pkg.write_and_assert_config( clk => clk,
            req => data_channel_req,
            rsp => data_channel_rsp,
            config => data_channel_config );

        test_execute( clk => clk, req => req, rsp => rsp,
            write => signal_write, writedata => signal_writedata );

        std.textio.write( std.textio.OUTPUT, "    test_crc_value ... " );

        assert_read_sw_source_eq( clk => clk,
            req => data_channel_req, rsp => data_channel_rsp,
            expected => expected_crc_value );

        std.textio.write( std.textio.OUTPUT, TEST_OK );

        finish;
    end process stimulus;
end architecture test;

