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

entity data_channel is
    generic (
        DEPTH : positive := 1024
    );
    port (
        clk : in std_logic;
        reset : in std_logic;

        ctrl_address : in std_logic_vector( 3 downto 0 );
        ctrl_read : in std_logic;
        ctrl_readdata : out std_logic_vector( 31 downto 0 );
        ctrl_write : in std_logic;
        ctrl_writedata : in std_logic_vector( 31 downto 0 );

        hw_sink_write : in std_logic;
        hw_sink_writedata : in std_logic_vector( 31 downto 0 );

        hw_source_read : in std_logic;
        hw_source_readdata : out std_logic_vector( 31 downto 0 )
    );
end entity data_channel;

architecture struct of data_channel is

    signal sink_config : std_logic;
    signal source_config : std_logic;

    signal clear : std_logic;
    signal empty : std_logic;
    signal full : std_logic;
    signal level : std_logic_vector( 9 downto 0 );

    signal ctrl_sink_write : std_logic;
    signal ctrl_sink_writedata : std_logic_vector( 31 downto 0 );

    signal ctrl_source_read : std_logic;
    signal ctrl_source_readdata : std_logic_vector( 31 downto 0 );

    signal sink_write : std_logic;
    signal sink_writedata : std_logic_vector( 31 downto 0 );

    signal source_read : std_logic;
    signal source_readdata : std_logic_vector( 31 downto 0 );

begin

    u_control : entity work.data_channel_control
        port map (
            clk => clk,
            reset => reset,

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

            sink_config => sink_config,
            source_config => source_config,

            clear => clear,
            empty => empty,
            full => full,
            level => level,

            sink_write => ctrl_sink_write,
            sink_writedata => ctrl_sink_writedata,

            source_read => ctrl_source_read,
            source_readdata => ctrl_source_readdata
        );

    u_data_sink_mux : entity work.data_sink_mux
        port map (
            sel => sink_config,

            sw_write => ctrl_sink_write,
            sw_writedata => ctrl_sink_writedata,

            hw_write => hw_sink_write,
            hw_writedata => hw_sink_writedata,

            write => sink_write,
            writedata => sink_writedata
        );

    u_fifo : entity work.fifo
        generic map (
            DEPTH => DEPTH
        )
        port map (
            aclr => reset,
            clock => clk,
            sclr => clear,
            data => sink_writedata,
            rdreq => source_read,
            wrreq => sink_write,
            empty => empty,
            full => full,
            q => source_readdata,
            usedw => level
        );

    u_data_source_mux : entity work.data_source_mux
        port map (
            sel => source_config,

            sw_read => ctrl_source_read,
            sw_readdata => ctrl_source_readdata,

            hw_read => hw_source_read,
            hw_readdata => hw_source_readdata,

            read => source_read,
            readdata => source_readdata
        );

end architecture;
