-- altera vhdl_input_version vhdl_2008
-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html)

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

use work.rtps_config_package.all;

entity Avalon_MM_wrapper is
    generic (
        DATA_WIDTH      : integer := 32
    );
    port (
        -- SYSTEM
        clk         : in std_logic;
        reset       : in std_logic;
        -- AVALON MM INTERFACE
        address     : in std_logic_vector(1 downto 0);
        read        : in std_logic;
        write       : in std_logic;
        readdata    : out std_logic_vector(DATA_WIDTH-1 downto 0);
        writedata   : in std_logic_vector(DATA_WIDTH-1 downto 0);
        waitrequest : out std_logic;
        -- RTPS INPUT
        full_ri     : in std_logic;
        write_ri    : out std_logic;
        data_ri     : out std_logic_vector(DATA_WIDTH-1 downto 0);
        -- RTPS OUTPUT
        empty_ro    : in std_logic;
        read_ro     : out std_logic;
        data_ro     : in std_logic_vector(DATA_WIDTH-1 downto 0)
    );
end entity;

architecture arch of Avalon_MM_wrapper is
    
    --*****SIGNAl DECLARATION*****
    
    
begin

    main_prc : process(all)
    begin
        -- DEFAULT
        waitrequest <= '0';
        write_ri    <= '0';
        read_ro     <= '0';
        readdata    <= (others => '0');
        data_ri     <= (others => '0');
        
        if (reset = '1') then
            -- NOTE: To avoid system lockup, an agent device should assert waitrequest when in reset.
            waitrequest <= '1';
        else
            if (write = '1') then
                case (to_integer(unsigned(address))) is
                    when 2 =>
                        -- NOTE: Avalon-MM interface specification requires little endian ordering. [Embedded Design Handbook, Chapter 11, ED51012-1.1]
                        data_ri <= endian_swap('1', writedata);
                        if (full_ri = '1') then
                            -- Stall Avalon MM
                            waitrequest <= '1';
                        else
                            write_ri    <= '1';
                        end if;
                    when others =>
                        null;
                end case;
            elsif (read = '1') then
                case (to_integer(unsigned(address))) is
                    when 0 =>
                        readdata(0) <= not empty_ro;
                    when 1 =>
                        -- NOTE: Avalon-MM interface specification requires little endian ordering. [Embedded Design Handbook, Chapter 11, ED51012-1.1]
                        readdata    <= endian_swap('1',data_ro);
                        if (empty_ro = '1') then
                            -- Stall Avalon MM
                            waitrequest <= '1';
                        else
                            read_ro <= '1';
                        end if;
                    when others =>
                        null;
                end case;
            end if;
        end if;
    end process;
    
end architecture;
