-- 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_package.all;
use work.rtps_config_package.all;
use work.Type2_package.all;

entity Type2_reader_interface is
    port (
        -- SYSTEM
        clk                                 : in std_logic;
        reset                               : in std_logic;
        -- FROM DDS READER
        start_dds                           : out std_logic;
        ack_dds                             : in std_logic;
        opcode_dds                          : out DDS_READER_OPCODE_TYPE;
        instance_state_dds                  : out std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
        view_state_dds                      : out std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
        sample_state_dds                    : out std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0);
        instance_handle_dds                 : out INSTANCE_HANDLE_TYPE;
        max_samples_dds                     : out std_logic_vector(MAX_SAMPLES_WIDTH-1 downto 0);
        get_data_dds                        : out std_logic;
        done_dds                            : in std_logic;
        return_code_dds                     : in std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
        ready_in_dds                        : out std_logic;
        valid_in_dds                        : in std_logic;
        data_in_dds                         : in std_logic_vector(WORD_WIDTH-1 downto 0);
        last_word_in_dds                    : in std_logic;
        -- Sample Info
        sample_info_dds                     : in SAMPLE_INFO_TYPE;
        sample_info_valid_dds               : in std_logic;
        sample_info_ack_dds                 : out std_logic;
        eoc_dds                             : in std_logic;
        -- Communication Status
        status_dds                          : in std_logic_vector(STATUS_KIND_WIDTH-1 downto 0);
        
        -- TO USER ENTITY
        start_user                          : in std_logic;
        ack_user                            : out std_logic;
        opcode_user                         : in DDS_READER_OPCODE_TYPE;
        instance_state_user                 : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
        view_state_user                     : in std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
        sample_state_user                   : in std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0);
        instance_handle_user                : in INSTANCE_HANDLE_TYPE;
        max_samples_user                    : in std_logic_vector(MAX_SAMPLES_WIDTH-1 downto 0);
        get_data_user                       : in std_logic;
        done_user                           : out std_logic;
        return_code_user                    : out std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
        -- Sample Info
        sample_info_user                    : out SAMPLE_INFO_TYPE;
        sample_info_valid_user              : out std_logic;
        sample_info_ack_user                : in std_logic;
        eoc_user                            : out std_logic;
        -- Communication Status
        status_user                         : out std_logic_vector(STATUS_KIND_WIDTH-1 downto 0);
        decode_error                        : out std_logic;
        
        -- ###GENERATED START###
        id                                  : out std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        TestSequence_len                    : out std_logic_vector(TESTSEQUENCE_ADDR_WIDTH-1 downto 0);
        TestSequence_addr                   : in std_logic_vector(TESTSEQUENCE_ADDR_WIDTH-1 downto 0);
        TestSequence_ready                  : out std_logic;
        TestSequence_ren                    : in std_logic;
        TestSequence_valid                  : out std_logic;
        TestSequence_ack                    : in std_logic;
        TestSequence_TestArray_addr         : in std_logic_vector(TESTSEQUENCE_TESTARRAY_ADDR_WIDTH-1 downto 0);
        TestSequence_TestArray_ready        : out std_logic;
        TestSequence_TestArray_ren          : in std_logic;
        TestSequence_TestArray_valid        : out std_logic;
        TestSequence_TestArray_ack          : in std_logic;
        TestSequence_TestArray              : out std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
        TestSequence_TestChar               : out std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
        TestSequence_TestWChar              : out std_logic_vector(CDR_WCHAR_WIDTH-1 downto 0);
        TestSequence_TestLongLong           : out std_logic_vector(CDR_LONG_LONG_WIDTH-1 downto 0);
        TestSequence_TestLongDouble         : out std_logic_vector(CDR_LONG_DOUBLE_WIDTH-1 downto 0);
        TestSequence_TestLongDouble_opt     : out std_logic;
        TestMap_len                         : out std_logic_vector(TESTMAP_ADDR_WIDTH-1 downto 0);
        TestMap_addr                        : in std_logic_vector(TESTMAP_ADDR_WIDTH-1 downto 0);
        TestMap_ready                       : out std_logic;
        TestMap_ren                         : in std_logic;
        TestMap_valid                       : out std_logic;
        TestMap_ack                         : in std_logic;
        TestMap_key                         : out std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
        TestMap_value                       : out std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
        TestEnum                            : out std_logic_vector(TESTENUM_WIDTH-1 downto 0);
        TestUnion_opt                       : out std_logic;
        TestUnion_d                         : out std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
        TestUnion_LongU                     : out std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        TestUnion_OctetU                    : out std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
        TestBitmask                         : out std_logic_vector(TESTBITMASK_WIDTH-1 downto 0);
        TestString_len                      : out std_logic_vector(TESTSTRING_ADDR_WIDTH-1 downto 0);
        TestString_addr                     : in std_logic_vector(TESTSTRING_ADDR_WIDTH-1 downto 0);
        TestString_ready                    : out std_logic;
        TestString_ren                      : in std_logic;
        TestString_valid                    : out std_logic;
        TestString_ack                      : in std_logic;
        TestString                          : out std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
        -- ###GENERATED END###
        valid                               : out std_logic
    );
end entity;

architecture arch of Type2_reader_interface is
    
    --*****TYPE DECLARATION*****
    -- FSM states. Explained below in detail
    type STAGE_TYPE is (IDLE,GET_PAYLOAD_HEADER,FETCH,ALIGN_STREAM,SKIP_PAYLOAD,DECODE_PAYLOAD);
    -- ###GENERATED START###
    type DECODE_STAGE_TYPE is (GET_ID,GET_TESTSEQUENCE_LENGTH,GET_TESTSEQUENCE_TESTARRAY,GET_TESTSEQUENCE_TESTCHAR,GET_TESTSEQUENCE_TESTWCHAR,GET_TESTSEQUENCE_TESTLONGLONG,GET_TESTSEQUENCE_TESTLONGDOUBLE,GET_TESTMAP_LENGTH,GET_TESTMAP_KEY,GET_TESTMAP_VALUE,GET_TESTENUM,GET_TESTUNION_D,GET_TESTUNION_LONGU,GET_TESTUNION_OCTETU,GET_TESTBITMASK,GET_TESTSTRING_LENGTH,GET_TESTSTRING,GET_OPTIONAL_HEADER);
    type TESTSEQUENCE_TESTARRAY_ADDR_TYPE is array (0 to TESTSEQUENCE_MAX_DEPTH-1) of std_logic_vector(TESTSEQUENCE_TESTARRAY_ADDR_WIDTH-1 downto 0);
    type TESTSEQUENCE_TESTARRAY_DATA_TYPE is array (0 to TESTSEQUENCE_MAX_DEPTH-1) of std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
    -- ###GENERATED END###
    
    -- *MAIN PROCESS*
    signal stage, stage_next : STAGE_TYPE;
    signal cnt, cnt_next : natural range 0 to 5;
    signal endian_flag, endian_flag_next : std_logic;
    signal last_word_in_latch, last_word_in_latch_next : std_logic;
    signal decode_error_latch, decode_error_latch_next : std_logic;
    signal align_offset, align_offset_next  : unsigned(MAX_ALIGN_OFFSET_WIDTH-1 downto 0);
    signal align_op, align_op_next : std_logic;
    signal target_align, target_align_next : ALIGN_TYPE;
    signal data_in_latch, data_in_latch_next : std_logic_vector(WORD_WIDTH-1 downto 0);
    signal optional, optional_next : std_logic;
    signal abort_mem : std_logic;
    signal ready_in_dds_sig : std_logic;
    signal valid_latch, valid_latch_next : std_logic;
    signal decode_stage, decode_stage_next : DECODE_STAGE_TYPE;
    signal return_stage, return_stage_next : DECODE_STAGE_TYPE;
    -- ###GENERATED START###
    signal dw_latch, dw_latch_next : std_logic_vector(CDR_LONG_LONG_WIDTH-1 downto 0);
    signal qw_latch, qw_latch_next : std_logic_vector(CDR_LONG_DOUBLE_WIDTH-1 downto 0);
    signal id_latch, id_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
    signal TestSequence_cnt, TestSequence_cnt_next : natural range 0 to TESTSEQUENCE_MAX_DEPTH-1;
    signal TestSequence_len_latch, TestSequence_len_latch_next : unsigned(TESTSEQUENCE_ADDR_WIDTH-1 downto 0);
    signal TestSequence_addr_latch, TestSequence_addr_latch_next : std_logic_vector(TESTSEQUENCE_ADDR_WIDTH-1 downto 0);
    signal TestSequence_TestArray_cnt, TestSequence_TestArray_cnt_next : natural range 0 to TESTSEQUENCE_TESTARRAY_MAX_DEPTH-1;
    signal TestMap_cnt, TestMap_cnt_next : natural range 0 to TESTMAP_MAX_DEPTH-1;
    signal TestMap_len_latch, TestMap_len_latch_next : unsigned(TESTMAP_ADDR_WIDTH-1 downto 0);
    signal TestString_cnt, TestString_cnt_next : natural range 0 to TESTSTRING_MAX_DEPTH-1;
    signal TestString_len_latch, TestString_len_latch_next : unsigned(TESTSTRING_ADDR_WIDTH-1 downto 0);
    signal TestEnum_latch, TestEnum_latch_next : std_logic_vector(TESTENUM_WIDTH-1 downto 0);
    signal TestUnion_opt_latch, TestUnion_opt_latch_next : std_logic;
    signal TestUnion_d_latch, TestUnion_d_latch_next : std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
    signal TestUnion_LongU_latch, TestUnion_LongU_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
    signal TestUnion_OctetU_latch, TestUnion_OctetU_latch_next : std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
    signal TestBitmask_latch, TestBitmask_latch_next : std_logic_vector(TESTBITMASK_WIDTH-1 downto 0);
    -- TestSequence_TestChar_mem SIGNALS
    signal TestSequence_TestChar_mem_addr : std_logic_vector(TESTSEQUENCE_ADDR_WIDTH-1 downto 0);
    signal TestSequence_TestChar_mem_read, TestSequence_TestChar_mem_ready_in, TestSequence_TestChar_mem_ready_out, TestSequence_TestChar_mem_valid_in, TestSequence_TestChar_mem_valid_out : std_logic;
    signal TestSequence_TestChar_mem_data_in, TestSequence_TestChar_mem_data_out : std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
    -- TestSequence_TestWChar_mem SIGNALS
    signal TestSequence_TestWChar_mem_addr : std_logic_vector(TESTSEQUENCE_ADDR_WIDTH-1 downto 0);
    signal TestSequence_TestWChar_mem_read, TestSequence_TestWChar_mem_ready_in, TestSequence_TestWChar_mem_ready_out, TestSequence_TestWChar_mem_valid_in, TestSequence_TestWChar_mem_valid_out : std_logic;
    signal TestSequence_TestWChar_mem_data_in, TestSequence_TestWChar_mem_data_out : std_logic_vector(CDR_WCHAR_WIDTH-1 downto 0);
    -- TestSequence_TestLongLong_mem SIGNALS
    signal TestSequence_TestLongLong_mem_addr : std_logic_vector(TESTSEQUENCE_ADDR_WIDTH-1 downto 0);
    signal TestSequence_TestLongLong_mem_read, TestSequence_TestLongLong_mem_ready_in, TestSequence_TestLongLong_mem_ready_out, TestSequence_TestLongLong_mem_valid_in, TestSequence_TestLongLong_mem_valid_out : std_logic;
    signal TestSequence_TestLongLong_mem_data_in, TestSequence_TestLongLong_mem_data_out : std_logic_vector(CDR_LONG_LONG_WIDTH-1 downto 0);
    -- TestSequence_TestLongDouble_mem SIGNALS
    signal TestSequence_TestLongDouble_mem_addr : std_logic_vector(TESTSEQUENCE_ADDR_WIDTH-1 downto 0);
    signal TestSequence_TestLongDouble_mem_read, TestSequence_TestLongDouble_mem_ready_in, TestSequence_TestLongDouble_mem_ready_out, TestSequence_TestLongDouble_mem_valid_in, TestSequence_TestLongDouble_mem_valid_out : std_logic;
    signal TestSequence_TestLongDouble_mem_data_in, TestSequence_TestLongDouble_mem_data_out : std_logic_vector(CDR_LONG_DOUBLE_WIDTH+1-1 downto 0);
    -- TestSequence_TestArray_mem SIGNALS
    signal TestSequence_TestArray_mem_addr : TESTSEQUENCE_TESTARRAY_ADDR_TYPE;
    signal TestSequence_TestArray_mem_read, TestSequence_TestArray_mem_ready_in, TestSequence_TestArray_mem_ready_out, TestSequence_TestArray_mem_valid_in, TestSequence_TestArray_mem_valid_out : std_logic_vector(0 to TESTSEQUENCE_TESTARRAY_MAX_DEPTH-1);
    signal TestSequence_TestArray_mem_data_in, TestSequence_TestArray_mem_data_out : TESTSEQUENCE_TESTARRAY_DATA_TYPE;
    -- TestMap_key_mem SIGNALS
    signal TestMap_key_mem_addr : std_logic_vector(TESTMAP_ADDR_WIDTH-1 downto 0);
    signal TestMap_key_mem_read, TestMap_key_mem_ready_in, TestMap_key_mem_ready_out, TestMap_key_mem_valid_in, TestMap_key_mem_valid_out : std_logic;
    signal TestMap_key_mem_data_in, TestMap_key_mem_data_out : std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
    -- TestMap_value_mem SIGNALS
    signal TestMap_value_mem_addr : std_logic_vector(TESTMAP_ADDR_WIDTH-1 downto 0);
    signal TestMap_value_mem_read, TestMap_value_mem_ready_in, TestMap_value_mem_ready_out, TestMap_value_mem_valid_in, TestMap_value_mem_valid_out : std_logic;
    signal TestMap_value_mem_data_in, TestMap_value_mem_data_out : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
    -- TestString_mem SIGNALS
    signal TestString_mem_addr : std_logic_vector(TESTSTRING_ADDR_WIDTH-1 downto 0);
    signal TestString_mem_read, TestString_mem_ready_in, TestString_mem_ready_out, TestString_mem_valid_in, TestString_mem_valid_out : std_logic;
    signal TestString_mem_data_in, TestString_mem_data_out : std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
    -- ###GENERATED END###
    
    --*****ALIAS DECLARATION*****
    alias representation_id         : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) is data_in_dds(WORD_WIDTH-1 downto WORD_WIDTH-PAYLOAD_REPRESENTATION_ID_WIDTH);
    alias representation_options    : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) is data_in_dds(PAYLOAD_REPRESENTATION_OPTIONS_WIDTH-1 downto 0);
    alias parameter_id              : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) is data_in_latch(WORD_WIDTH-1 downto WORD_WIDTH-PARAMETER_ID_WIDTH);
    alias parameter_length          : std_logic_vector(PARAMETER_LENGTH_WIDTH-1 downto 0) is data_in_latch(PARAMETER_LENGTH_WIDTH-1 downto 0);
    
    
begin
    
    -- ###GENERATED START###
    TestSequence_TestChar_mem : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => TESTSEQUENCE_ADDR_WIDTH,
            DATA_WIDTH          => CDR_CHAR_WIDTH,
            MEMORY_DEPTH        => TESTSEQUENCE_MAX_DEPTH,
            MAX_BURST_LENGTH    => 1
        )
        port map (
            clk         => clk,
            reset       => reset or abort_mem,
            addr        => TestSequence_TestChar_mem_addr,
            read        => TestSequence_TestChar_mem_read,
            ready_in    => TestSequence_TestChar_mem_ready_in,
            valid_in    => TestSequence_TestChar_mem_valid_in,
            data_in     => TestSequence_TestChar_mem_data_in,
            ready_out   => TestSequence_TestChar_mem_ready_out,
            valid_out   => TestSequence_TestChar_mem_valid_out,
            data_out    => TestSequence_TestChar_mem_data_out
        );
    
    TestSequence_TestWChar_mem : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => TESTSEQUENCE_ADDR_WIDTH,
            DATA_WIDTH          => CDR_WCHAR_WIDTH,
            MEMORY_DEPTH        => TESTSEQUENCE_MAX_DEPTH,
            MAX_BURST_LENGTH    => 1
        )
        port map (
            clk         => clk,
            reset       => reset or abort_mem,
            addr        => TestSequence_TestWChar_mem_addr,
            read        => TestSequence_TestWChar_mem_read,
            ready_in    => TestSequence_TestWChar_mem_ready_in,
            valid_in    => TestSequence_TestWChar_mem_valid_in,
            data_in     => TestSequence_TestWChar_mem_data_in,
            ready_out   => TestSequence_TestWChar_mem_ready_out,
            valid_out   => TestSequence_TestWChar_mem_valid_out,
            data_out    => TestSequence_TestWChar_mem_data_out
        );
    
    TestSequence_TestLongLong_mem : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => TESTSEQUENCE_ADDR_WIDTH,
            DATA_WIDTH          => CDR_LONG_LONG_WIDTH,
            MEMORY_DEPTH        => TESTSEQUENCE_MAX_DEPTH,
            MAX_BURST_LENGTH    => 1
        )
        port map (
            clk         => clk,
            reset       => reset or abort_mem,
            addr        => TestSequence_TestLongLong_mem_addr,
            read        => TestSequence_TestLongLong_mem_read,
            ready_in    => TestSequence_TestLongLong_mem_ready_in,
            valid_in    => TestSequence_TestLongLong_mem_valid_in,
            data_in     => TestSequence_TestLongLong_mem_data_in,
            ready_out   => TestSequence_TestLongLong_mem_ready_out,
            valid_out   => TestSequence_TestLongLong_mem_valid_out,
            data_out    => TestSequence_TestLongLong_mem_data_out
        );
    
    TestSequence_TestLongDouble_mem : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => TESTSEQUENCE_ADDR_WIDTH,
            DATA_WIDTH          => CDR_LONG_DOUBLE_WIDTH+1,
            MEMORY_DEPTH        => TESTSEQUENCE_MAX_DEPTH,
            MAX_BURST_LENGTH    => 1
        )
        port map (
            clk         => clk,
            reset       => reset or abort_mem,
            addr        => TestSequence_TestLongDouble_mem_addr,
            read        => TestSequence_TestLongDouble_mem_read,
            ready_in    => TestSequence_TestLongDouble_mem_ready_in,
            valid_in    => TestSequence_TestLongDouble_mem_valid_in,
            data_in     => TestSequence_TestLongDouble_mem_data_in,
            ready_out   => TestSequence_TestLongDouble_mem_ready_out,
            valid_out   => TestSequence_TestLongDouble_mem_valid_out,
            data_out    => TestSequence_TestLongDouble_mem_data_out
        );
    
    TestSequence_TestArray_gen : for i in 0 to TESTSEQUENCE_MAX_DEPTH-1 generate
    begin
        TestSequence_TestArray_mem : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => TESTSEQUENCE_TESTARRAY_ADDR_WIDTH,
            DATA_WIDTH          => CDR_OCTET_WIDTH,
            MEMORY_DEPTH        => TESTSEQUENCE_TESTARRAY_MAX_DEPTH,
            MAX_BURST_LENGTH    => 1
        )
        port map (
            clk         => clk,
            reset       => reset or abort_mem,
            addr        => TestSequence_TestArray_mem_addr(i),
            read        => TestSequence_TestArray_mem_read(i),
            ready_in    => TestSequence_TestArray_mem_ready_in(i),
            valid_in    => TestSequence_TestArray_mem_valid_in(i),
            data_in     => TestSequence_TestArray_mem_data_in(i),
            ready_out   => TestSequence_TestArray_mem_ready_out(i),
            valid_out   => TestSequence_TestArray_mem_valid_out(i),
            data_out    => TestSequence_TestArray_mem_data_out(i)
        );
    end generate;
    
    TestMap_key_mem : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => TESTMAP_ADDR_WIDTH,
            DATA_WIDTH          => CDR_OCTET_WIDTH,
            MEMORY_DEPTH        => TESTMAP_MAX_DEPTH,
            MAX_BURST_LENGTH    => 1
        )
        port map (
            clk         => clk,
            reset       => reset or abort_mem,
            addr        => TestMap_key_mem_addr,
            read        => TestMap_key_mem_read,
            ready_in    => TestMap_key_mem_ready_in,
            valid_in    => TestMap_key_mem_valid_in,
            data_in     => TestMap_key_mem_data_in,
            ready_out   => TestMap_key_mem_ready_out,
            valid_out   => TestMap_key_mem_valid_out,
            data_out    => TestMap_key_mem_data_out
        );
    
    TestMap_value_mem : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => TESTMAP_ADDR_WIDTH,
            DATA_WIDTH          => CDR_SHORT_WIDTH,
            MEMORY_DEPTH        => TESTMAP_MAX_DEPTH,
            MAX_BURST_LENGTH    => 1
        )
        port map (
            clk         => clk,
            reset       => reset or abort_mem,
            addr        => TestMap_value_mem_addr,
            read        => TestMap_value_mem_read,
            ready_in    => TestMap_value_mem_ready_in,
            valid_in    => TestMap_value_mem_valid_in,
            data_in     => TestMap_value_mem_data_in,
            ready_out   => TestMap_value_mem_ready_out,
            valid_out   => TestMap_value_mem_valid_out,
            data_out    => TestMap_value_mem_data_out
        );
    
    TestString_mem : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => TESTSTRING_ADDR_WIDTH,
            DATA_WIDTH          => CDR_CHAR_WIDTH,
            MEMORY_DEPTH        => TESTSTRING_MAX_DEPTH,
            MAX_BURST_LENGTH    => 1
        )
        port map (
            clk         => clk,
            reset       => reset or abort_mem,
            addr        => TestString_mem_addr,
            read        => TestString_mem_read,
            ready_in    => TestString_mem_ready_in,
            valid_in    => TestString_mem_valid_in,
            data_in     => TestString_mem_data_in,
            ready_out   => TestString_mem_ready_out,
            valid_out   => TestString_mem_valid_out,
            data_out    => TestString_mem_data_out
        );
    -- ###GENERATED END###
    
    -- PASSTHROUGH
    start_dds                           <= start_user;
    ack_user                            <= ack_dds;
    opcode_dds                          <= opcode_user;
    instance_state_dds                  <= instance_state_user;
    view_state_dds                      <= view_state_user;
    sample_state_dds                    <= sample_state_user;
    instance_handle_dds                 <= instance_handle_user;
    max_samples_dds                     <= max_samples_user;
    get_data_dds                        <= get_data_user;
    done_user                           <= done_dds;
    return_code_user                    <= return_code_dds;
    sample_info_user                    <= sample_info_dds;
    sample_info_valid_user              <= sample_info_valid_dds;
    sample_info_ack_dds                 <= sample_info_ack_user;
    eoc_user                            <= eoc_dds;
    status_user                         <= status_dds;
    
    valid           <= valid_latch;
    decode_error    <= decode_error_latch;
    ready_in_dds    <= ready_in_dds_sig;
    
    -- ###GENERATED START###
    id                                  <= id_latch;
    TestSequence_len                    <= std_logic_vector(TestSequence_len_latch);
    TestSequence_valid                  <= TestSequence_TestChar_mem_valid_out and TestSequence_TestWChar_mem_valid_out and TestSequence_TestLongLong_mem_valid_out and TestSequence_TestLongDouble_mem_valid_out;
    -- NOTE:    We could also solve this with a one-hot mux, but syntesis of a one-hot mux is more complex than a simple index mux.
    --          Alternatively you could just OR all outputs, but that places the restriction that the data_out signal has to be (others => '0') when valid = '0'.
    TestSequence_TestArray              <= TestSequence_TestArray_mem_data_out(to_integer(unsigned(TestSequence_addr_latch)));
    TestSequence_TestArray_valid        <= TestSequence_TestArray_mem_valid_out(to_integer(unsigned(TestSequence_addr_latch)));
    TestSequence_TestChar               <= TestSequence_TestChar_mem_data_out;
    TestSequence_TestWChar              <= TestSequence_TestWChar_mem_data_out;
    TestSequence_TestLongLong           <= TestSequence_TestLongLong_mem_data_out;
    TestSequence_TestLongDouble         <= TestSequence_TestLongDouble_mem_data_out(CDR_LONG_DOUBLE_WIDTH-1 downto 0);
    TestSequence_TestLongDouble_opt     <= TestSequence_TestLongDouble_mem_data_out(CDR_LONG_DOUBLE_WIDTH);
    TestMap_len                         <= std_logic_vector(TestMap_len_latch);
    TestMap_valid                       <= TestMap_key_mem_valid_out and TestMap_value_mem_valid_out;
    TestMap_key                         <= TestMap_key_mem_data_out;
    TestMap_value                       <= TestMap_value_mem_data_out;
    TestEnum                            <= TestEnum_latch;
    TestUnion_opt                       <= TestUnion_opt_latch;
    TestUnion_d                         <= TestUnion_d_latch;
    TestUnion_LongU                     <= TestUnion_LongU_latch;
    TestUnion_OctetU                    <= TestUnion_OctetU_latch;
    TestBitmask                         <= TestBitmask_latch;
    TestString_len                      <= std_logic_vector(TestString_len_latch);
    TestString_valid                    <= TestString_mem_valid_out;
    TestString                          <= TestString_mem_data_out;
    -- ###GENERATED END###
    
    main_prc : process (all)
        variable tmp_length : unsigned(WORD_WIDTH-1 downto 0);
    begin
        -- DEFAULT
        stage_next                  <= stage;
        decode_stage_next           <= decode_stage;
        return_stage_next           <= return_stage;
        cnt_next                    <= cnt;
        endian_flag_next            <= endian_flag;
        last_word_in_latch_next     <= last_word_in_latch;
        decode_error_latch_next     <= decode_error_latch;
        align_offset_next           <= align_offset;
        target_align_next           <= target_align;
        optional_next               <= optional;
        valid_latch_next            <= valid_latch;
        data_in_latch_next          <= data_in_latch;
        align_op_next               <= align_op;
        abort_mem                   <= '0';
        ready_in_dds_sig            <= '0';
        -- ###GENERATED START###
        dw_latch_next                               <= dw_latch;
        qw_latch_next                               <= qw_latch;
        id_latch_next                               <= id_latch;
        TestSequence_len_latch_next                 <= TestSequence_len_latch;
        TestSequence_cnt_next                       <= TestSequence_cnt;
        TestSequence_TestArray_cnt_next             <= TestSequence_TestArray_cnt;
        TestSequence_addr_latch_next                <= TestSequence_addr_latch;
        TestMap_cnt_next                            <= TestMap_cnt;
        TestMap_len_latch_next                      <= TestMap_len_latch;
        TestEnum_latch_next                         <= TestEnum_latch;
        TestUnion_opt_latch_next                    <= TestUnion_opt_latch;
        TestUnion_d_latch_next                      <= TestUnion_d_latch;
        TestUnion_LongU_latch_next                  <= TestUnion_LongU_latch;
        TestUnion_OctetU_latch_next                 <= TestUnion_OctetU_latch;
        TestBitmask_latch_next                      <= TestBitmask_latch;
        TestString_cnt_next                         <= TestString_cnt;
        TestString_len_latch_next                   <= TestString_len_latch;
        TestSequence_TestChar_mem_addr              <= (others => '0');
        TestSequence_TestChar_mem_read              <= '0';
        TestSequence_TestChar_mem_valid_in          <= '0';
        TestSequence_TestChar_mem_ready_out         <= '0';
        TestSequence_TestChar_mem_data_in           <= (others => '0');
        TestSequence_TestWChar_mem_addr             <= (others => '0');
        TestSequence_TestWChar_mem_read             <= '0';
        TestSequence_TestWChar_mem_valid_in         <= '0';
        TestSequence_TestWChar_mem_ready_out        <= '0';
        TestSequence_TestWChar_mem_data_in          <= (others => '0');
        TestSequence_TestLongLong_mem_addr          <= (others => '0');
        TestSequence_TestLongLong_mem_read          <= '0';
        TestSequence_TestLongLong_mem_valid_in      <= '0';
        TestSequence_TestLongLong_mem_ready_out     <= '0';
        TestSequence_TestLongLong_mem_data_in       <= (others => '0');
        TestSequence_TestLongDouble_mem_addr        <= (others => '0');
        TestSequence_TestLongDouble_mem_read        <= '0';
        TestSequence_TestLongDouble_mem_valid_in    <= '0';
        TestSequence_TestLongDouble_mem_ready_out   <= '0';
        TestSequence_TestLongDouble_mem_data_in     <= (others => '0');
        TestSequence_TestArray_mem_addr             <= (others => (others => '0'));
        TestSequence_TestArray_mem_read             <= (others => '0');
        TestSequence_TestArray_mem_valid_in         <= (others => '0');
        TestSequence_TestArray_mem_ready_out        <= (others => '0');
        TestSequence_TestArray_mem_data_in          <= (others => (others => '0'));
        TestMap_key_mem_addr                        <= (others => '0');
        TestMap_key_mem_read                        <= '0';
        TestMap_key_mem_valid_in                    <= '0';
        TestMap_key_mem_ready_out                   <= '0';
        TestMap_key_mem_data_in                     <= (others => '0');
        TestMap_value_mem_addr                      <= (others => '0');
        TestMap_value_mem_read                      <= '0';
        TestMap_value_mem_valid_in                  <= '0';
        TestMap_value_mem_ready_out                 <= '0';
        TestMap_value_mem_data_in                   <= (others => '0');
        TestString_mem_addr                         <= (others => '0');
        TestString_mem_read                         <= '0';
        TestString_mem_valid_in                     <= '0';
        TestString_mem_ready_out                    <= '0';
        TestString_mem_data_in                      <= (others => '0');
        TestSequence_ready                          <= '0';
        TestSequence_TestArray_ready                <= '0';
        TestMap_ready                               <= '0';
        TestString_ready                            <= '0';
        -- ###GENERATED END###
        
        -- Last Word Latch Setter
        if (last_word_in_dds = '1') then
            last_word_in_latch_next <= '1';
        end if;
        
        case (stage) is
            when IDLE =>
                -- User Requests Payload
                if (sample_info_valid_dds = '1' and sample_info_dds.valid_data = '1' and sample_info_ack_user = '1' and get_data_user = '1') then
                    stage_next  <= GET_PAYLOAD_HEADER;
                    -- RESET
                    decode_error_latch_next <= '0';
                    valid_latch_next        <= '0';
                    abort_mem               <= '1';
                else
                    -- ###GENERATED START###
                    TestSequence_ready                          <= TestSequence_TestChar_mem_ready_in and TestSequence_TestWChar_mem_ready_in and TestSequence_TestLongLong_mem_ready_in and TestSequence_TestLongDouble_mem_ready_in;
                    TestSequence_TestChar_mem_addr              <= TestSequence_addr;
                    TestSequence_TestChar_mem_read              <= TestSequence_ren;
                    TestSequence_TestChar_mem_valid_in          <= TestSequence_ren;
                    TestSequence_TestChar_mem_ready_out         <= TestSequence_ack;
                    TestSequence_TestWChar_mem_addr             <= TestSequence_addr;
                    TestSequence_TestWChar_mem_read             <= TestSequence_ren;
                    TestSequence_TestWChar_mem_valid_in         <= TestSequence_ren;
                    TestSequence_TestWChar_mem_ready_out        <= TestSequence_ack;
                    TestSequence_TestLongLong_mem_addr          <= TestSequence_addr;
                    TestSequence_TestLongLong_mem_read          <= TestSequence_ren;
                    TestSequence_TestLongLong_mem_valid_in      <= TestSequence_ren;
                    TestSequence_TestLongLong_mem_ready_out     <= TestSequence_ack;
                    TestSequence_TestLongDouble_mem_addr        <= TestSequence_addr;
                    TestSequence_TestLongDouble_mem_read        <= TestSequence_ren;
                    TestSequence_TestLongDouble_mem_valid_in    <= TestSequence_ren;
                    TestSequence_TestLongDouble_mem_ready_out   <= TestSequence_ack;
                    TestSequence_TestArray_ready                <= TestSequence_TestArray_mem_ready_in(to_integer(unsigned(TestSequence_addr)));
                    TestSequence_TestArray_mem_addr(to_integer(unsigned(TestSequence_addr)))        <= TestSequence_TestArray_addr;
                    TestSequence_TestArray_mem_read(to_integer(unsigned(TestSequence_addr)))        <= TestSequence_TestArray_ren;
                    TestSequence_TestArray_mem_valid_in(to_integer(unsigned(TestSequence_addr)))    <= TestSequence_TestArray_ren;
                    TestSequence_TestArray_mem_ready_out                                            <= (others => TestSequence_TestArray_ack);
                    -- Latch Address for output
                    if (TestSequence_TestArray_ren = '1') then
                        TestSequence_addr_latch_next    <= TestSequence_addr;
                    end if;
                    TestMap_ready               <= TestMap_key_mem_ready_in and TestMap_value_mem_ready_in;
                    TestMap_key_mem_addr        <= TestMap_addr;
                    TestMap_key_mem_read        <= TestMap_ren;
                    TestMap_key_mem_valid_in    <= TestMap_ren;
                    TestMap_key_mem_ready_out   <= TestMap_ack;
                    TestMap_value_mem_addr      <= TestMap_addr;
                    TestMap_value_mem_read      <= TestMap_ren;
                    TestMap_value_mem_valid_in  <= TestMap_ren;
                    TestMap_value_mem_ready_out <= TestMap_ack;
                    TestString_ready            <= TestString_mem_ready_in;
                    TestString_mem_addr         <= TestString_addr;
                    TestString_mem_read         <= TestString_ren;
                    TestString_mem_valid_in     <= TestString_ren;
                    TestString_mem_ready_out    <= TestString_ack;
                    -- ###GENERATED END###
                end if;
            when GET_PAYLOAD_HEADER =>
                -- TODO: Latch Offset from Options Field?
                
                ready_in_dds_sig    <= '1';
                -- Input Guard
                if (valid_in_dds = '1') then
                    case (representation_id) is
                        when CDR_BE =>
                            endian_flag_next    <= '0';
                            stage_next          <= FETCH;
                            -- Alignment Reset 
                            align_offset_next   <= (others => '0');
                            -- ###GENERATED START###
                            decode_stage_next   <= GET_ID;
                            -- ###GENERATED END###
                            -- Initial Fetch
                        when CDR_LE =>
                            endian_flag_next    <= '1';
                            stage_next          <= FETCH;
                            -- Alignment Reset 
                            align_offset_next   <= (others => '0');
                            -- ###GENERATED START###
                            decode_stage_next   <= GET_ID;
                            -- ###GENERATED END###
                        when others =>
                            -- Unknown Payload Encoding
                            stage_next              <= SKIP_PAYLOAD;
                            decode_error_latch_next <= '1';
                    end case;
                end if;
            when FETCH =>
                ready_in_dds_sig    <= '1';
                -- Input Guard
                if (valid_in_dds = '1') then
                    data_in_latch_next  <= data_in_dds;
                    -- Alignment Operation in progress
                    if (align_op = '1') then
                        stage_next      <= ALIGN_STREAM;
                        -- Reset
                        align_op_next   <= '0';
                    else
                        stage_next  <= DECODE_PAYLOAD;
                    end if;
                end if;
            when ALIGN_STREAM =>
                -- Target Stream Alignment reached
                if (check_align(align_offset, target_align)) then
                    -- DONE
                    stage_next  <= DECODE_PAYLOAD;
                else
                    align_offset_next   <= align_offset + 1;
                    -- Need to fetch new Input Word
                    if (align_offset(1 downto 0) = "11") then
                        align_op_next   <= '1';
                        stage_next      <= FETCH;
                    end if;
                end if;
            when SKIP_PAYLOAD =>
                if (last_word_in_latch = '0') then
                    -- Skip Read
                    ready_in_dds_sig    <= '1';
                else
                    stage_next  <= IDLE;
                    
                    -- If no Decode Error, mark output as valid
                    if (decode_error_latch = '0') then
                        valid_latch_next    <= '1';
                    end if;
                    
                    -- Reset
                    last_word_in_latch_next <= '0';
                end if;
            when DECODE_PAYLOAD =>
                case (decode_stage) is
                    -- ###GENERATED START###
                    when GET_ID =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            id_latch_next       <= endian_swap(endian_flag, data_in_latch);
                            align_offset_next   <= align_offset + 4;
                            stage_next          <= FETCH;
                            -- Next Member
                            decode_stage_next    <= GET_TESTSEQUENCE_LENGTH;
                        end if;
                    when GET_TESTSEQUENCE_LENGTH =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            tmp_length          := unsigned(endian_swap(endian_flag, data_in_latch));
                            align_offset_next   <= align_offset + 4;
                            stage_next          <= FETCH;
                            
                            -- Empty Sequence
                            if (tmp_length = 0) then
                                -- Next Member
                                decode_stage_next    <= GET_TESTMAP_LENGTH;
                            else
                                decode_stage_next               <= GET_TESTSEQUENCE_TESTARRAY;
                                if (tmp_length > TESTSEQUENCE_MAX_DEPTH) then
                                    TestSequence_len_latch_next     <= to_unsigned(TESTSEQUENCE_MAX_DEPTH, TestSequence_len_latch_next'length);
                                else
                                    TestSequence_len_latch_next     <= resize(tmp_length, TestSequence_len_latch_next'length);
                                end if;
                                TestSequence_cnt_next           <= 0;
                                -- DES: For array types the _cnt has to be initialized in the previous member stage
                                TestSequence_TestArray_cnt_next <= 0;
                            end if;
                        end if;
                    when GET_TESTSEQUENCE_TESTARRAY =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else                            
                            TestSequence_TestArray_mem_addr(TestSequence_cnt)       <= std_logic_vector(to_unsigned(TestSequence_TestArray_cnt,TESTSEQUENCE_TESTARRAY_ADDR_WIDTH));
                            TestSequence_TestArray_mem_data_in(TestSequence_cnt)    <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 0)), CDR_OCTET_WIDTH, TRUE));
                            TestSequence_TestArray_mem_valid_in(TestSequence_cnt)   <= '1';
                            -- Memory Operation Guard
                            if (TestSequence_TestArray_mem_ready_in(TestSequence_cnt) = '1') then
                                align_offset_next   <= align_offset + 1;
                                
                                -- All Elements processed
                                if (TestSequence_TestArray_cnt = TESTSEQUENCE_TESTARRAY_MAX_DEPTH-1) then
                                    decode_stage_next    <= GET_TESTSEQUENCE_TESTCHAR;
                                else
                                    TestSequence_TestArray_cnt_next <= TestSequence_TestArray_cnt + 1;
                                end if;
                                
                                -- DES: Needed for ALIGN_1
                                -- Need to fetch next Word
                                if(align_offset(1 downto 0) = "11") then
                                    stage_next  <= FETCH;
                                end if;
                            end if;
                        end if;
                    when GET_TESTSEQUENCE_TESTCHAR =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else
                            TestSequence_TestChar_mem_addr      <= std_logic_vector(to_unsigned(TestSequence_cnt,TESTSEQUENCE_ADDR_WIDTH));
                            TestSequence_TestChar_mem_data_in   <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 0)), CDR_CHAR_WIDTH, TRUE));
                            TestSequence_TestChar_mem_valid_in  <= '1';
                            
                            -- Memory Operation Guard
                            if (TestSequence_TestChar_mem_ready_in = '1') then
                                align_offset_next   <= align_offset + 1;
                                decode_stage_next    <= GET_TESTSEQUENCE_TESTWCHAR;
                                
                                -- Need to fetch next Word
                                if(align_offset(1 downto 0) = "11") then
                                    stage_next  <= FETCH;
                                end if;
                            end if;
                        end if;
                    when GET_TESTSEQUENCE_TESTWCHAR =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_2)) then
                            target_align_next   <= ALIGN_2;
                            stage_next          <= ALIGN_STREAM;
                        else
                            TestSequence_TestWChar_mem_addr     <= std_logic_vector(to_unsigned(TestSequence_cnt,TESTSEQUENCE_ADDR_WIDTH));
                            TestSequence_TestWChar_mem_data_in  <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 1)), CDR_WCHAR_WIDTH, TRUE));
                            TestSequence_TestWChar_mem_valid_in <= '1';
                            
                            -- Memory Operation Guard
                            if (TestSequence_TestWChar_mem_ready_in = '1') then
                                align_offset_next   <= align_offset + 2;
                                decode_stage_next   <= GET_TESTSEQUENCE_TESTLONGLONG;
                                cnt_next            <= 0;
                                
                                -- DES: Needed for ALIGN_2
                                -- Need to fetch next Word
                                if(align_offset(1 downto 1) = "1") then
                                    stage_next  <= FETCH;
                                end if;
                            end if;
                        end if;
                    when GET_TESTSEQUENCE_TESTLONGLONG =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_8)) then
                            target_align_next   <= ALIGN_8;
                            stage_next          <= ALIGN_STREAM;
                        else
                            case (cnt) is
                                -- Double Word 1/2
                                when 0 =>
                                    dw_latch_next   <= write_sub_vector(dw_latch, data_in_latch, 0, TRUE);
                                    stage_next      <= FETCH;
                                    cnt_next        <= cnt + 1;
                                -- Double Word 2/2
                                when 1 =>
                                    dw_latch_next   <= write_sub_vector(dw_latch, data_in_latch, 1, TRUE);
                                    cnt_next        <= cnt + 1;
                                -- Push Double Word
                                when 2 =>
                                    TestSequence_TestLongLong_mem_addr      <= std_logic_vector(to_unsigned(TestSequence_cnt,TESTSEQUENCE_ADDR_WIDTH));
                                    TestSequence_TestLongLong_mem_data_in   <= endian_swap(endian_flag, dw_latch);
                                    TestSequence_TestLongLong_mem_valid_in  <= '1';
                                    
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongLong_mem_ready_in = '1') then
                                        align_offset_next   <= align_offset + 8;
                                        stage_next          <= FETCH;
                                        decode_stage_next   <= GET_OPTIONAL_HEADER;
                                        return_stage_next   <= GET_TESTSEQUENCE_TESTLONGDOUBLE;
                                        cnt_next            <= 0;
                                    end if;
                                when others =>
                                    null;
                            end case;
                        end if;
                    when GET_TESTSEQUENCE_TESTLONGDOUBLE =>
                        -- Optional Omitted
                        if (optional = '0') then
                            -- Mark Optional as Invalid
                            TestSequence_TestLongDouble_mem_addr        <= std_logic_vector(to_unsigned(TestSequence_cnt,TESTSEQUENCE_ADDR_WIDTH));
                            TestSequence_TestLongDouble_mem_data_in(CDR_LONG_DOUBLE_WIDTH)  <= '0';
                            TestSequence_TestLongDouble_mem_valid_in    <= '1';
                            -- Memory Operation Guard
                            if (TestSequence_TestLongLong_mem_ready_in = '1') then
                                -- All Elements processed
                                if (TestSequence_cnt = TestSequence_len_latch-1) then
                                    -- Next Member
                                    decode_stage_next    <= GET_TESTMAP_LENGTH;
                                else
                                    TestSequence_cnt_next           <= TestSequence_cnt + 1;
                                    decode_stage_next               <= GET_TESTSEQUENCE_TESTARRAY;
                                    TestSequence_TestArray_cnt_next <= 0;
                                end if;
                            end if;
                        -- ALIGN GUARD
                        elsif (not check_align(align_offset, ALIGN_8)) then
                            target_align_next   <= ALIGN_8;
                            stage_next          <= ALIGN_STREAM;
                        else
                            case (cnt) is
                                -- Quad Word 1/4
                                when 0 =>
                                    qw_latch_next   <= write_sub_vector(qw_latch, data_in_latch, 0, TRUE);
                                    stage_next      <= FETCH;
                                    cnt_next        <= cnt + 1;
                                -- Quad Word 2/4
                                when 1 =>
                                    qw_latch_next   <= write_sub_vector(qw_latch, data_in_latch, 1, TRUE);
                                    stage_next      <= FETCH;
                                    cnt_next        <= cnt + 1;
                                -- Quad Word 3/4
                                when 2 =>
                                    qw_latch_next   <= write_sub_vector(qw_latch, data_in_latch, 2, TRUE);
                                    stage_next      <= FETCH;
                                    cnt_next        <= cnt + 1;
                                -- Quad Word 4/4
                                when 3 =>
                                    qw_latch_next   <= write_sub_vector(qw_latch, data_in_latch, 3, TRUE);
                                    cnt_next        <= cnt + 1;
                                -- Push Quad Word
                                when 4 =>
                                    TestSequence_TestLongDouble_mem_addr        <= std_logic_vector(to_unsigned(TestSequence_cnt,TESTSEQUENCE_ADDR_WIDTH));
                                    TestSequence_TestLongDouble_mem_data_in     <= "1" & endian_swap(endian_flag, qw_latch);
                                    TestSequence_TestLongDouble_mem_valid_in    <= '1';
                                    
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongLong_mem_ready_in = '1') then
                                        stage_next          <= FETCH;
                                        align_offset_next   <= align_offset + 16;
                                        
                                        -- All Elements processed
                                        if (TestSequence_cnt = TestSequence_len_latch-1) then
                                            -- Next Member
                                            decode_stage_next    <= GET_TESTMAP_LENGTH;
                                        else
                                            TestSequence_cnt_next           <= TestSequence_cnt + 1;
                                            decode_stage_next               <= GET_TESTSEQUENCE_TESTARRAY;
                                            TestSequence_TestArray_cnt_next <= 0;
                                        end if;
                                    end if;
                                when others =>
                                    null;
                            end case;
                        end if;
                    when GET_TESTMAP_LENGTH =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            tmp_length          := unsigned(endian_swap(endian_flag, data_in_latch));
                            align_offset_next   <= align_offset + 4;
                            stage_next          <= FETCH;
                            
                            -- Empty Sequence
                            if (tmp_length = 0) then
                                -- Next Member
                                decode_stage_next    <= GET_TESTENUM;
                            else
                                if (tmp_length > TESTMAP_MAX_DEPTH) then
                                    TestMap_len_latch_next   <= to_unsigned(TESTMAP_MAX_DEPTH, TestMap_len_latch_next'length);
                                else
                                    TestMap_len_latch_next   <= resize(tmp_length, TestMap_len_latch_next'length);
                                end if;
                                TestMap_cnt_next        <= 0;
                                decode_stage_next        <= GET_TESTMAP_KEY;
                            end if;
                        end if;
                    when GET_TESTMAP_KEY =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else
                            TestMap_key_mem_addr        <= std_logic_vector(to_unsigned(TestMap_cnt,TESTMAP_ADDR_WIDTH));
                            TestMap_key_mem_data_in     <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 0)), CDR_OCTET_WIDTH, TRUE));
                            TestMap_key_mem_valid_in    <= '1';
                            
                            -- Memory Operation Guard
                            if (TestMap_key_mem_ready_in = '1') then
                                align_offset_next   <= align_offset + 1;
                                decode_stage_next   <= GET_TESTMAP_VALUE;
                                
                                -- Need to fetch next Word
                                if(align_offset(1 downto 0) = "11") then
                                    stage_next  <= FETCH;
                                end if;
                            end if;
                        end if;
                    when GET_TESTMAP_VALUE =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_2)) then
                            target_align_next   <= ALIGN_2;
                            stage_next          <= ALIGN_STREAM;
                        else
                            TestMap_value_mem_addr      <= std_logic_vector(to_unsigned(TestMap_cnt,TESTMAP_ADDR_WIDTH));
                            TestMap_value_mem_data_in   <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 1)), CDR_SHORT_WIDTH, TRUE));
                            TestMap_value_mem_valid_in  <= '1';
                            
                            -- Memory Operation Guard
                            if (TestMap_value_mem_ready_in = '1') then
                                align_offset_next   <= align_offset + 2;
                                
                                -- All Elements processed
                                if (TestMap_cnt = TestMap_len_latch-1) then
                                    -- Next Member
                                    decode_stage_next   <= GET_TESTENUM;
                                else
                                    TestMap_cnt_next    <= TestMap_cnt + 1;
                                    decode_stage_next   <= GET_TESTMAP_KEY;
                                end if;
                                
                                -- Need to fetch next Word
                                if(align_offset(1 downto 1) = "1") then
                                    stage_next  <= FETCH;
                                end if;
                            end if;
                        end if;
                    when GET_TESTENUM =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else
                            TestEnum_latch_next <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 0)), CDR_OCTET_WIDTH, TRUE))(TESTENUM_WIDTH-1 downto 0);
                            align_offset_next   <= align_offset + 1;
                            -- Next Member
                            decode_stage_next   <= GET_OPTIONAL_HEADER;
                            return_stage_next   <= GET_TESTUNION_D;
                            cnt_next            <= 0;
                            
                            -- Need to fetch next Word
                            if(align_offset(1 downto 0) = "11") then
                                stage_next  <= FETCH;
                            end if;
                        end if; 
                    when GET_TESTUNION_D =>
                        -- Optional Omitted
                        if (optional = '0') then
                            decode_stage_next            <= GET_TESTBITMASK;
                            TestUnion_opt_latch_next    <= '0';
                        -- ALIGN GUARD
                        elsif (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else
                            align_offset_next   <= align_offset + 1;
                            
                            TestUnion_opt_latch_next    <= '1';
                            TestUnion_d_latch_next      <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 0)), CDR_CHAR_WIDTH, TRUE));
                            
                            case (endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 0)), CDR_CHAR_WIDTH, TRUE))) is
                                when TESTUNION_LONGU_D =>
                                    decode_stage_next   <= GET_TESTUNION_LONGU;
                                when others =>
                                    decode_stage_next   <= GET_TESTUNION_OCTETU;
                            end case;
                            
                            -- Need to fetch next Word
                            if(align_offset(1 downto 0) = "11") then
                                stage_next  <= FETCH;
                            end if;
                        end if;
                    when GET_TESTUNION_LONGU =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            TestUnion_LongU_latch_next          <= endian_swap(endian_flag, data_in_latch);
                            align_offset_next                   <= align_offset + 4;
                            stage_next                          <= FETCH;
                            -- Next Member
                            decode_stage_next    <= GET_TESTBITMASK;
                        end if;
                    when GET_TESTUNION_OCTETU =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else
                            TestUnion_OctetU_latch_next         <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 0)), CDR_OCTET_WIDTH, TRUE));
                            align_offset_next                   <= align_offset + 1;
                            -- Next Member
                            decode_stage_next    <= GET_TESTBITMASK;
                            
                            -- Need to fetch next Word
                            if(align_offset(1 downto 0) = "11") then
                                stage_next  <= FETCH;
                            end if;
                        end if;
                    when GET_TESTBITMASK =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_2)) then
                            target_align_next   <= ALIGN_2;
                            stage_next          <= ALIGN_STREAM;
                        else
                            TestBitmask_latch_next  <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 1)), CDR_SHORT_WIDTH, TRUE))(TESTBITMASK_WIDTH-1 downto 0);
                            align_offset_next       <= align_offset + 2;
                            -- Next Member
                            decode_stage_next    <= GET_TESTSTRING_LENGTH;
                            
                            -- Need to fetch next Word
                            if(align_offset(1 downto 1) = "1") then
                                stage_next  <= FETCH;
                            end if;
                        end if;
                    when GET_TESTSTRING_LENGTH =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            tmp_length          := unsigned(endian_swap(endian_flag, data_in_latch));
                            align_offset_next   <= align_offset + 4;
                            stage_next          <= FETCH;
                            
                            -- Empty Sequence
                            if (tmp_length = 0) then
                                -- DONE
                                stage_next  <= SKIP_PAYLOAD;
                            else
                                if (tmp_length > TESTSTRING_MAX_DEPTH) then
                                    TestString_len_latch_next   <= to_unsigned(TESTSTRING_MAX_DEPTH, TestString_len_latch_next'length);
                                else
                                    TestString_len_latch_next   <= resize(tmp_length, TestString_len_latch_next'length);
                                end if;
                                TestString_cnt_next         <= 0;
                                decode_stage_next           <= GET_TESTSTRING;
                            end if;
                        end if;
                    when GET_TESTSTRING =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else                            
                            TestString_mem_addr     <= std_logic_vector(to_unsigned(TestString_cnt,TESTSTRING_ADDR_WIDTH));
                            TestString_mem_data_in  <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 0)), CDR_CHAR_WIDTH, TRUE));
                            TestString_mem_valid_in <= '1';
                            -- Memory Operation Guard
                            if (TestString_mem_ready_in = '1') then
                                align_offset_next   <= align_offset + 1;
                                
                                -- Need to fetch next Word
                                if(align_offset(1 downto 0) = "11") then
                                    stage_next  <= FETCH;
                                end if;
                                
                                -- All Elements processed
                                if (TestString_cnt = TestString_len_latch-1) then
                                    -- DONE
                                    stage_next  <= SKIP_PAYLOAD;
                                else
                                    TestString_cnt_next <= TestString_cnt + 1;
                                end if;
                            end if;
                        end if;
                    -- ###GENERATED END###
                    when GET_OPTIONAL_HEADER =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            case (cnt) is
                                -- Optional Member Header
                                when 0 =>
                                    -- Extended Parameter Header
                                    if (endian_swap(endian_flag,parameter_id) = PID_EXTENDED) then
                                        cnt_next    <= cnt + 1;
                                        stage_next  <= FETCH;
                                    else
                                        stage_next          <= FETCH;
                                        decode_stage_next   <= return_stage;
                                        cnt_next            <= 0;
                                        -- Alignment Reset 
                                        align_offset_next   <= (others => '0');
                                        
                                        -- Optional omitted
                                        if(endian_swap(endian_flag,parameter_length) = (parameter_length'reverse_range => '0')) then
                                            optional_next   <= '0';
                                        else
                                            optional_next   <= '1';
                                        end if;
                                    end if;
                                -- eMemberHeader 
                                when 1 =>
                                    -- Ignore Parameter ID
                                    cnt_next    <= cnt + 1;
                                    stage_next  <= FETCH;
                                -- Llength
                                when 2 =>
                                    stage_next          <= FETCH;
                                    decode_stage_next    <= return_stage;
                                    cnt_next            <= 0;
                                    -- Alignment Reset 
                                    align_offset_next   <= (others => '0');
                                    
                                    -- Optional omitted
                                    if(endian_swap(endian_flag, data_in_dds) = (data_in_dds'reverse_range => '0')) then
                                        optional_next   <= '0';
                                    else
                                        optional_next   <= '1';
                                    end if;
                                when others =>
                                    null;
                            end case;
                        end if;
                    when others =>
                        null;
                end case;
            when others =>
                null;
        end case;
        
        -- OVERREAD GUARD
        -- Attempted read on empty input
        if (last_word_in_latch = '1' and last_word_in_dds = '0' and ready_in_dds_sig = '1') then
            stage_next              <= SKIP_PAYLOAD;
            decode_error_latch_next <= '1';
        end if;
        
    end process;
    
    sync_prc : process(clk)
    begin
        if rising_edge(clk) then
            if (reset = '1') then
                stage               <= IDLE;
                decode_stage        <= GET_ID;
                return_stage        <= GET_ID;
                target_align        <= ALIGN_1;
                cnt                 <= 0;
                endian_flag         <= '0';
                last_word_in_latch  <= '0';
                decode_error_latch  <= '0';
                optional            <= '0';
                valid_latch         <= '0';
                align_op            <= '0';
                align_offset        <= (others => '0');
                data_in_latch       <= (others => '0');
                dw_latch            <= (others => '0');
                qw_latch            <= (others => '0');
                -- ###GENERATED START###
                id_latch                        <= (others => '0');
                TestSequence_len_latch          <= (others => '0');
                TestSequence_cnt                <= 0;
                TestSequence_TestArray_cnt      <= 0;
                TestSequence_addr_latch         <= (others => '0');
                TestMap_cnt                     <= 0;
                TestMap_len_latch               <= (others => '0');
                TestEnum_latch                  <= (others => '0');
                TestUnion_opt_latch             <= '0';
                TestUnion_d_latch               <= (others => '0');
                TestUnion_LongU_latch           <= (others => '0');
                TestUnion_OctetU_latch          <= (others => '0');
                TestBitmask_latch               <= (others => '0');
                TestString_cnt                  <= 0;
                TestString_len_latch            <= (others => '0');
                -- ###GENERATED END###
            else
                stage               <= stage_next;
                decode_stage        <= decode_stage_next;
                return_stage        <= return_stage_next;
                target_align        <= target_align_next;
                cnt                 <= cnt_next;
                endian_flag         <= endian_flag_next;
                last_word_in_latch  <= last_word_in_latch_next;
                decode_error_latch  <= decode_error_latch_next;
                optional            <= optional_next;
                valid_latch         <= valid_latch_next;
                align_op            <= align_op_next;
                align_offset        <= align_offset_next;
                data_in_latch       <= data_in_latch_next;
                dw_latch            <= dw_latch_next;
                qw_latch            <= qw_latch_next;
                -- ###GENERATED START###
                id_latch                        <= id_latch_next;
                TestSequence_len_latch          <= TestSequence_len_latch_next;
                TestSequence_cnt                <= TestSequence_cnt_next;
                TestSequence_TestArray_cnt      <= TestSequence_TestArray_cnt_next;
                TestSequence_addr_latch         <= TestSequence_addr_latch_next;
                TestMap_cnt                     <= TestMap_cnt_next;
                TestMap_len_latch               <= TestMap_len_latch_next;
                TestEnum_latch                  <= TestEnum_latch_next;
                TestUnion_opt_latch             <= TestUnion_opt_latch_next;
                TestUnion_d_latch               <= TestUnion_d_latch_next;
                TestUnion_LongU_latch           <= TestUnion_LongU_latch_next;
                TestUnion_OctetU_latch          <= TestUnion_OctetU_latch_next;
                TestBitmask_latch               <= TestBitmask_latch_next;
                TestString_cnt                  <= TestString_cnt_next;
                TestString_len_latch            <= TestString_len_latch_next;
                -- ###GENERATED END###
            end if;
        end if;
    end process;
    
end architecture;