--! Use ieee library for std_logic types.
library ieee;
    use ieee.std_logic_1164.all;

--! Use the niosII library for all processor system components
library niosII;

--! Use the pll_200 library for the PLL 200 MHz clock generation
library pll_main;

entity signal_processing is
    port
    (
        clk_input : in  std_logic;
        reset_n : in  std_logic;

        --! Push button key_0 used to start a single execution of the signal
        --! processing.
        key_start : in  std_logic;

        leds     : out std_logic_vector( 7 downto 0 )
    );
end entity signal_processing;

architecture struct of signal_processing is

    --! input clock synchronous reset
    signal sync_reset : std_logic;

    --! main clock for the NiosII system
    signal clk_main : std_logic;
    --! main clock from PLL is locked and the system reset can be released.
    signal locked_main : std_logic;
    --! main clock synchronous reset
    signal sync_reset_main : std_logic;
    signal sync_reset_main_n : std_logic;

    signal sw_leds : std_logic_vector( 7 downto 0 );
    signal hw_leds : std_logic_vector( 7 downto 0 );

    signal hardware_task_0_address : std_logic_vector(3 downto 0);
    signal hardware_task_0_read : std_logic;
    signal hardware_task_0_readdata : std_logic_vector(31 downto 0);
    signal hardware_task_0_write : std_logic;
    signal hardware_task_0_writedata : std_logic_vector(31 downto 0);

    signal hardware_task_1_address : std_logic_vector(3 downto 0);
    signal hardware_task_1_read : std_logic;
    signal hardware_task_1_readdata : std_logic_vector(31 downto 0);
    signal hardware_task_1_write : std_logic;
    signal hardware_task_1_writedata : std_logic_vector(31 downto 0);

    signal hardware_task_2_address : std_logic_vector(3 downto 0);
    signal hardware_task_2_read : std_logic;
    signal hardware_task_2_readdata : std_logic_vector(31 downto 0);
    signal hardware_task_2_write : std_logic;
    signal hardware_task_2_writedata : std_logic_vector(31 downto 0);

    signal hardware_task_3_address : std_logic_vector(3 downto 0);
    signal hardware_task_3_read : std_logic;
    signal hardware_task_3_readdata : std_logic_vector(31 downto 0);
    signal hardware_task_3_write : std_logic;
    signal hardware_task_3_writedata : std_logic_vector(31 downto 0);

    signal hardware_task_4_address : std_logic_vector(3 downto 0);
    signal hardware_task_4_read : std_logic;
    signal hardware_task_4_readdata : std_logic_vector(31 downto 0);
    signal hardware_task_4_write : std_logic;
    signal hardware_task_4_writedata : std_logic_vector(31 downto 0);

    signal hardware_task_5_address : std_logic_vector(3 downto 0);
    signal hardware_task_5_read : std_logic;
    signal hardware_task_5_readdata : std_logic_vector(31 downto 0);
    signal hardware_task_5_write : std_logic;
    signal hardware_task_5_writedata : std_logic_vector(31 downto 0);

    signal hardware_task_6_address : std_logic_vector(3 downto 0);
    signal hardware_task_6_read : std_logic;
    signal hardware_task_6_readdata : std_logic_vector(31 downto 0);
    signal hardware_task_6_write : std_logic;
    signal hardware_task_6_writedata : std_logic_vector(31 downto 0);

    signal data_channel_0_hw_sink_write : std_logic;
    signal data_channel_0_hw_sink_writedata : std_logic_vector(31 downto 0);
    signal data_channel_0_hw_source_read : std_logic;
    signal data_channel_0_hw_source_readdata : std_logic_vector(31 downto 0);

    signal data_channel_1_hw_sink_write : std_logic;
    signal data_channel_1_hw_sink_writedata : std_logic_vector(31 downto 0);
    signal data_channel_1_hw_source_read : std_logic;
    signal data_channel_1_hw_source_readdata : std_logic_vector(31 downto 0);

    signal data_channel_2_hw_sink_write : std_logic;
    signal data_channel_2_hw_sink_writedata : std_logic_vector(31 downto 0);
    signal data_channel_2_hw_source_read : std_logic;
    signal data_channel_2_hw_source_readdata : std_logic_vector(31 downto 0);

    signal data_channel_3_hw_sink_write : std_logic;
    signal data_channel_3_hw_sink_writedata : std_logic_vector(31 downto 0);
    signal data_channel_3_hw_source_read : std_logic;
    signal data_channel_3_hw_source_readdata : std_logic_vector(31 downto 0);

    signal data_channel_4_hw_sink_write : std_logic;
    signal data_channel_4_hw_sink_writedata : std_logic_vector(31 downto 0);
    signal data_channel_4_hw_source_read : std_logic;
    signal data_channel_4_hw_source_readdata : std_logic_vector(31 downto 0);

    signal data_channel_5_hw_sink_write : std_logic;
    signal data_channel_5_hw_sink_writedata : std_logic_vector(31 downto 0);
    signal data_channel_5_hw_source_read : std_logic;
    signal data_channel_5_hw_source_readdata : std_logic_vector(31 downto 0);

    signal data_channel_6_hw_sink_write : std_logic;
    signal data_channel_6_hw_sink_writedata : std_logic_vector(31 downto 0);
    signal data_channel_6_hw_source_read : std_logic;
    signal data_channel_6_hw_source_readdata : std_logic_vector(31 downto 0);
begin

    -- Synchronize the external reset to the external clock domain
    u_sync_rst_50: entity work.sync_rst
        port map
        (
            clk => clk_input,
            reset => not reset_n,
            rst_sync => sync_reset
        );

    -- PLL for the main system clock
    u_pll_main: entity pll_main.pll_main
        port map
        (
            refclk   => clk_input,     -- in  std_logic
            rst      => sync_reset,   -- in  std_logic
            outclk_0 => clk_main,    -- out std_logic
            locked   => locked_main  -- out std_logic
        );

    -- Synchronize the main reset to the main clock domain
    u_sync_rst_main: entity work.sync_rst
        port map
        (
            clk => clk_main,
            reset => not locked_main and sync_reset,
            rst_sync => sync_reset_main
        );
    sync_reset_main_n <= not sync_reset_main;

    -- NiosII system
    u_niosII : entity niosii.niosII
        port map
        (
            clk_clk => clk_main,
            reset_reset_n => sync_reset_main_n,

            key_start_export => key_start,
            leds_export => sw_leds,

			data_channel_0_hw_sink_write => data_channel_0_hw_sink_write,
			data_channel_0_hw_sink_writedata => data_channel_0_hw_sink_writedata,
			data_channel_0_hw_source_read => data_channel_0_hw_source_read,
			data_channel_0_hw_source_readdata => data_channel_0_hw_source_readdata,

			data_channel_1_hw_sink_write => data_channel_1_hw_sink_write,
			data_channel_1_hw_sink_writedata => data_channel_1_hw_sink_writedata,
			data_channel_1_hw_source_read => data_channel_1_hw_source_read,
			data_channel_1_hw_source_readdata => data_channel_1_hw_source_readdata,

			data_channel_2_hw_sink_write => data_channel_2_hw_sink_write,
			data_channel_2_hw_sink_writedata => data_channel_2_hw_sink_writedata,
			data_channel_2_hw_source_read => data_channel_2_hw_source_read,
			data_channel_2_hw_source_readdata => data_channel_2_hw_source_readdata,

			data_channel_3_hw_sink_write => data_channel_3_hw_sink_write,
			data_channel_3_hw_sink_writedata => data_channel_3_hw_sink_writedata,
			data_channel_3_hw_source_read => data_channel_3_hw_source_read,
			data_channel_3_hw_source_readdata => data_channel_3_hw_source_readdata,

			data_channel_4_hw_sink_write => data_channel_4_hw_sink_write,
			data_channel_4_hw_sink_writedata => data_channel_4_hw_sink_writedata,
			data_channel_4_hw_source_read => data_channel_4_hw_source_read,
			data_channel_4_hw_source_readdata => data_channel_4_hw_source_readdata,

			data_channel_5_hw_sink_write => data_channel_5_hw_sink_write,
			data_channel_5_hw_sink_writedata => data_channel_5_hw_sink_writedata,
			data_channel_5_hw_source_read => data_channel_5_hw_source_read,
			data_channel_5_hw_source_readdata => data_channel_5_hw_source_readdata,

			data_channel_6_hw_sink_write => data_channel_6_hw_sink_write,
			data_channel_6_hw_sink_writedata => data_channel_6_hw_sink_writedata,
			data_channel_6_hw_source_read => data_channel_6_hw_source_read,
			data_channel_6_hw_source_readdata => data_channel_6_hw_source_readdata,

			hardware_task_0_task_address => hardware_task_0_address,
			hardware_task_0_task_read => hardware_task_0_read,
			hardware_task_0_task_readdata => hardware_task_0_readdata,
			hardware_task_0_task_write     => hardware_task_0_write,
			hardware_task_0_task_writedata => hardware_task_0_writedata,

			hardware_task_1_task_address => hardware_task_1_address,
			hardware_task_1_task_read => hardware_task_1_read,
			hardware_task_1_task_readdata => hardware_task_1_readdata,
			hardware_task_1_task_write     => hardware_task_1_write,
			hardware_task_1_task_writedata => hardware_task_1_writedata,

			hardware_task_2_task_address => hardware_task_2_address,
			hardware_task_2_task_read => hardware_task_2_read,
			hardware_task_2_task_readdata => hardware_task_2_readdata,
			hardware_task_2_task_write     => hardware_task_2_write,
			hardware_task_2_task_writedata => hardware_task_2_writedata,

			hardware_task_3_task_address => hardware_task_3_address,
			hardware_task_3_task_read => hardware_task_3_read,
			hardware_task_3_task_readdata => hardware_task_3_readdata,
			hardware_task_3_task_write     => hardware_task_3_write,
			hardware_task_3_task_writedata => hardware_task_3_writedata,

			hardware_task_4_task_address => hardware_task_4_address,
			hardware_task_4_task_read => hardware_task_4_read,
			hardware_task_4_task_readdata => hardware_task_4_readdata,
			hardware_task_4_task_write     => hardware_task_4_write,
			hardware_task_4_task_writedata => hardware_task_4_writedata,

			hardware_task_5_task_address => hardware_task_5_address,
			hardware_task_5_task_read => hardware_task_5_read,
			hardware_task_5_task_readdata => hardware_task_5_readdata,
			hardware_task_5_task_write     => hardware_task_5_write,
			hardware_task_5_task_writedata => hardware_task_5_writedata,

			hardware_task_6_task_address => hardware_task_6_address,
			hardware_task_6_task_read => hardware_task_6_read,
			hardware_task_6_task_readdata => hardware_task_6_readdata,
			hardware_task_6_task_write     => hardware_task_6_write,
			hardware_task_6_task_writedata => hardware_task_6_writedata
        );

    u_task_sine: entity work.task_sine
        port map (
            clk => clk_main,
            reset => sync_reset_main,

            address => hardware_task_0_address,
            read => hardware_task_0_read,
            readdata => hardware_task_0_readdata,
            write => hardware_task_0_write,
            writedata => hardware_task_0_writedata,

            signal_write => data_channel_0_hw_sink_write ,
            signal_writedata => data_channel_0_hw_sink_writedata
        );

    u_task_cosine: entity work.task_sine
        port map (
            clk => clk_main,
            reset => sync_reset_main,

            address => hardware_task_1_address,
            read => hardware_task_1_read,
            readdata => hardware_task_1_readdata,
            write => hardware_task_1_write,
            writedata => hardware_task_1_writedata,

            signal_write => data_channel_1_hw_sink_write ,
            signal_writedata => data_channel_1_hw_sink_writedata
        );

    u_task_rand: entity work.task_rand
        port map (
            clk => clk_main,
            reset => sync_reset_main,

            address => hardware_task_2_address,
            read => hardware_task_2_read,
            readdata => hardware_task_2_readdata,
            write => hardware_task_2_write,
            writedata => hardware_task_2_writedata,

            signal_write => data_channel_2_hw_sink_write ,
            signal_writedata => data_channel_2_hw_sink_writedata
        );

    u_task_add_sine_cosine: entity work.task_add
        port map (
            clk => clk_main,
            reset => sync_reset_main,

            address => hardware_task_3_address,
            read => hardware_task_3_read,
            readdata => hardware_task_3_readdata,
            write => hardware_task_3_write,
            writedata => hardware_task_3_writedata,

            signal_a_read => data_channel_0_hw_source_read,
            signal_a_readdata => data_channel_0_hw_source_readdata,

            signal_b_read => data_channel_1_hw_source_read,
            signal_b_readdata => data_channel_1_hw_source_readdata,

            signal_write => data_channel_3_hw_sink_write ,
            signal_writedata => data_channel_3_hw_sink_writedata
        );

    u_task_add_rand: entity work.task_add
        port map (
            clk => clk_main,
            reset => sync_reset_main,

            address => hardware_task_4_address,
            read => hardware_task_4_read,
            readdata => hardware_task_4_readdata,
            write => hardware_task_4_write,
            writedata => hardware_task_4_writedata,

            signal_a_read => data_channel_2_hw_source_read,
            signal_a_readdata => data_channel_2_hw_source_readdata,

            signal_b_read => data_channel_3_hw_source_read,
            signal_b_readdata => data_channel_3_hw_source_readdata,

            signal_write => data_channel_4_hw_sink_write ,
            signal_writedata => data_channel_4_hw_sink_writedata
        );

    u_task_fft: entity work.task_fft
        port map (
            clk => clk_main,
            reset => sync_reset_main,

            address => hardware_task_5_address,
            read => hardware_task_5_read,
            readdata => hardware_task_5_readdata,
            write => hardware_task_5_write,
            writedata => hardware_task_5_writedata,

            signal_read => data_channel_4_hw_source_read,
            signal_readdata => data_channel_4_hw_source_readdata,

            signal_write => data_channel_5_hw_sink_write ,
            signal_writedata => data_channel_5_hw_sink_writedata
        );

    u_task_crc: entity work.task_crc
        port map (
            clk => clk_main,
            reset => sync_reset_main,

            address => hardware_task_6_address,
            read => hardware_task_6_read,
            readdata => hardware_task_6_readdata,
            write => hardware_task_6_write,
            writedata => hardware_task_6_writedata,

            signal_read => data_channel_5_hw_source_read,
            signal_readdata => data_channel_5_hw_source_readdata,

            signal_write => data_channel_6_hw_sink_write ,
            signal_writedata => data_channel_6_hw_sink_writedata
        );

    hw_leds <= ( 0 => reset_n, 1 => sync_reset, 2 => locked_main, 3 => sync_reset_main, others => '0' );
    leds <= sw_leds or hw_leds;

end architecture struct;

