-- 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_writer_interface is
    generic (
        LITTLE_ENDIAN   : std_logic := '0'
    );
    port (
        -- SYSTEM
        clk                                 : in std_logic;
        reset                               : in std_logic;
        -- FROM DDS WRITER
        start_dds                           : out std_logic;
        ack_dds                             : in std_logic;
        opcode_dds                          : out DDS_WRITER_OPCODE_TYPE;
        instance_handle_in_dds              : out INSTANCE_HANDLE_TYPE;
        source_ts_dds                       : out TIME_TYPE;
        max_wait_dds                        : out DURATION_TYPE;
        done_dds                            : in std_logic;
        return_code_dds                     : in std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
        instance_handle_out_dds             : in INSTANCE_HANDLE_TYPE;
        ready_out_dds                       : in std_logic;
        valid_out_dds                       : out std_logic;
        data_out_dds                        : out std_logic_vector(WORD_WIDTH-1 downto 0);
        last_word_out_dds                   : out std_logic;
        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;
        -- 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_WRITER_OPCODE_TYPE;
        instance_handle_in_user             : in INSTANCE_HANDLE_TYPE;
        source_ts_user                      : in TIME_TYPE;
        max_wait_user                       : in DURATION_TYPE;
        done_user                           : out std_logic;
        return_code_user                    : out std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
        instance_handle_out_user            : out INSTANCE_HANDLE_TYPE;
        -- Communication Status
        status_user                         : out std_logic_vector(STATUS_KIND_WIDTH-1 downto 0);
        
        -- ###GENERATED START###
        id                                  : in std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        TestSequence_len                    : in 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_wen                    : 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_wen          : in std_logic;
        TestSequence_TestArray_valid        : out std_logic;
        TestSequence_TestArray_ack          : in std_logic;
        TestSequence_TestArray_r            : out std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
        TestSequence_TestArray_w            : in std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
        TestSequence_TestChar_r             : out std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
        TestSequence_TestChar_w             : in std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
        TestSequence_TestWChar_r            : out std_logic_vector(CDR_WCHAR_WIDTH-1 downto 0);
        TestSequence_TestWChar_w            : in std_logic_vector(CDR_WCHAR_WIDTH-1 downto 0);
        TestSequence_TestLongLong_r         : out std_logic_vector(CDR_LONG_LONG_WIDTH-1 downto 0);
        TestSequence_TestLongLong_w         : in std_logic_vector(CDR_LONG_LONG_WIDTH-1 downto 0);
        TestSequence_TestLongDouble_r       : out std_logic_vector(CDR_LONG_DOUBLE_WIDTH-1 downto 0);
        TestSequence_TestLongDouble_w       : in std_logic_vector(CDR_LONG_DOUBLE_WIDTH-1 downto 0);
        TestSequence_TestLongDouble_opt_r   : out std_logic;
        TestSequence_TestLongDouble_opt_w   : in std_logic;
        TestMap_len                         : in 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_wen                         : in std_logic;
        TestMap_valid                       : out std_logic;
        TestMap_ack                         : in std_logic;
        TestMap_key_r                       : out std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
        TestMap_key_w                       : in std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
        TestMap_value_r                     : out std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
        TestMap_value_w                     : in std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
        TestEnum                            : in std_logic_vector(TESTENUM_WIDTH-1 downto 0);
        TestUnion_opt                       : in std_logic;
        TestUnion_d                         : in std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
        TestUnion_LongU                     : in std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        TestUnion_OctetU                    : in std_logic_vector(CDR_OCTET_WIDTH-1 downto 0);
        TestBitmask                         : in std_logic_vector(TESTBITMASK_WIDTH-1 downto 0);
        TestString_len                      : in 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_wen                      : in std_logic;
        TestString_valid                    : out std_logic;
        TestString_ack                      : in std_logic;
        TestString_r                        : out std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
        TestString_w                        : in std_logic_vector(CDR_CHAR_WIDTH-1 downto 0);
        -- ###GENERATED END###
        
        encode_done                         : out std_logic
    );
end entity;

architecture arch of Type2_writer_interface is
    
    --*****TYPE DECLARATION*****
    -- FSM states. Explained below in detail
    type STAGE_TYPE is (IDLE,WRITE_PAYLOAD_HEADER,PUSH,ALIGN_STREAM,ENCODE_PAYLOAD);
    -- ###GENERATED START###
    type ENCODE_STAGE_TYPE is (WRITE_ID,WRITE_TESTSEQUENCE_LENGTH,WRITE_TESTSEQUENCE_TESTARRAY,WRITE_TESTSEQUENCE_TESTCHAR,WRITE_TESTSEQUENCE_TESTWCHAR,WRITE_TESTSEQUENCE_TESTLONGLONG,WRITE_TESTSEQUENCE_TESTLONGDOUBLE,WRITE_TESTMAP_LENGTH,WRITE_TESTMAP_KEY,WRITE_TESTMAP_VALUE,WRITE_TESTENUM,WRITE_TESTUNION_D,WRITE_TESTUNION_LONGU,WRITE_TESTUNION_OCTETU,WRITE_TESTBITMASK,WRITE_TESTSTRING_LENGTH,WRITE_TESTSTRING);
    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 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_out_latch, data_out_latch_next : std_logic_vector(WORD_WIDTH-1 downto 0);
    signal abort_mem : std_logic;
    signal finalize_payload, finalize_payload_next : std_logic;
    signal encode_stage, encode_stage_next : ENCODE_STAGE_TYPE;
    
    -- ###GENERATED START###
    signal TestSequence_cnt, TestSequence_cnt_next : natural range 0 to TESTSEQUENCE_MAX_DEPTH-1;
    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 TestString_cnt, TestString_cnt_next : natural range 0 to TESTSTRING_MAX_DEPTH-1;
    -- 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###
    
    
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_handle_in_dds      <= instance_handle_in_user;
    source_ts_dds               <= source_ts_user;
    max_wait_dds                <= max_wait_user;
    done_user                   <= done_dds;
    return_code_user            <= return_code_dds;
    instance_handle_out_user    <= instance_handle_out_dds;
    status_user                 <= status_dds;
    
    -- ###GENERATED START###
    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_r                <= 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_r                 <= TestSequence_TestChar_mem_data_out;
    TestSequence_TestWChar_r                <= TestSequence_TestWChar_mem_data_out;
    TestSequence_TestLongLong_r             <= TestSequence_TestLongLong_mem_data_out;
    TestSequence_TestLongDouble_r           <= TestSequence_TestLongDouble_mem_data_out(CDR_LONG_DOUBLE_WIDTH-1 downto 0);
    TestSequence_TestLongDouble_opt_r       <= TestSequence_TestLongDouble_mem_data_out(CDR_LONG_DOUBLE_WIDTH);
    TestMap_valid                           <= TestMap_key_mem_valid_out and TestMap_value_mem_valid_out;
    TestMap_key_r                           <= TestMap_key_mem_data_out;
    TestMap_value_r                         <= TestMap_value_mem_data_out;
    TestString_valid                        <= TestString_mem_valid_out;
    TestString_r                            <= TestString_mem_data_out;
    TestSequence_TestChar_mem_data_in       <= TestSequence_TestChar_w;
    TestSequence_TestWChar_mem_data_in      <= TestSequence_TestWChar_w;
    TestSequence_TestLongLong_mem_data_in   <= TestSequence_TestLongLong_w;
    TestSequence_TestLongDouble_mem_data_in <= TestSequence_TestLongDouble_opt_w & TestSequence_TestLongDouble_w;
    TestSequence_TestArray_mem_data_in      <= (others => TestSequence_TestArray_w);
    TestMap_key_mem_data_in                 <= TestMap_key_w;
    TestMap_value_mem_data_in               <= TestMap_value_w;
    TestString_mem_data_in                  <= TestString_w;
    -- ###GENERATED END###
    
    main_prc : process (all)
    begin
        -- DEFAULT
        stage_next                  <= stage;
        encode_stage_next           <= encode_stage;
        cnt_next                    <= cnt;
        align_offset_next           <= align_offset;
        align_op_next               <= align_op;
        target_align_next           <= target_align;
        data_out_latch_next         <= data_out_latch;
        finalize_payload_next       <= finalize_payload;
        abort_mem                   <= '0';
        encode_done                 <= '0';
        ready_in_dds                <= '0';
        valid_out_dds               <= '0';
        last_word_out_dds           <= '0';
        data_out_dds                <= (others => '0');
        -- ###GENERATED START###
        TestSequence_cnt_next                       <= TestSequence_cnt;
        TestSequence_TestArray_cnt_next             <= TestSequence_TestArray_cnt;
        TestSequence_addr_latch_next                <= TestSequence_addr_latch;
        TestMap_cnt_next                            <= TestMap_cnt;
        TestString_cnt_next                         <= TestString_cnt;
        TestSequence_TestChar_mem_addr              <= (others => '0');
        TestSequence_TestChar_mem_read              <= '0';
        TestSequence_TestChar_mem_valid_in          <= '0';
        TestSequence_TestChar_mem_ready_out         <= '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_TestLongLong_mem_addr          <= (others => '0');
        TestSequence_TestLongLong_mem_read          <= '0';
        TestSequence_TestLongLong_mem_valid_in      <= '0';
        TestSequence_TestLongLong_mem_ready_out     <= '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_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');
        TestMap_key_mem_addr                        <= (others => '0');
        TestMap_key_mem_read                        <= '0';
        TestMap_key_mem_valid_in                    <= '0';
        TestMap_key_mem_ready_out                   <= '0';
        TestMap_value_mem_addr                      <= (others => '0');
        TestMap_value_mem_read                      <= '0';
        TestMap_value_mem_valid_in                  <= '0';
        TestMap_value_mem_ready_out                 <= '0';
        TestString_mem_addr                         <= (others => '0');
        TestString_mem_read                         <= '0';
        TestString_mem_valid_in                     <= '0';
        TestString_mem_ready_out                    <= '0';
        TestSequence_ready                          <= '0';
        TestSequence_TestArray_ready                <= '0';
        TestMap_ready                               <= '0';
        TestString_ready                            <= '0';
        -- ###GENERATED END###
        
        case (stage) is
            when IDLE =>
                -- User Requests Payload
                if (start_user = '1' and ack_dds = '1') then
                    case (opcode_user) is
                        when REGISTER_INSTANCE =>
                            stage_next  <= WRITE_PAYLOAD_HEADER;
                            -- RESET
                            abort_mem   <= '1';
                        when UNREGISTER_INSTANCE =>
                            stage_next  <= WRITE_PAYLOAD_HEADER;
                            -- RESET
                            abort_mem   <= '1';
                        when LOOKUP_INSTANCE =>
                            stage_next  <= WRITE_PAYLOAD_HEADER;
                            -- RESET
                            abort_mem   <= '1';
                        when WRITE =>
                            stage_next  <= WRITE_PAYLOAD_HEADER;
                            -- RESET
                            abort_mem   <= '1';
                        when DISPOSE =>
                            stage_next  <= WRITE_PAYLOAD_HEADER;
                            -- RESET
                            abort_mem   <= '1';
                        when others =>
                            null;
                    end case;
                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 or TestSequence_wen;
                    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 or TestSequence_wen;
                    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 or TestSequence_wen;
                    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 or TestSequence_wen;
                    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 or TestSequence_TestArray_wen;
                    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 or TestMap_wen;
                    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 or TestMap_wen;
                    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 or TestString_wen;
                    TestString_mem_ready_out    <= TestString_ack;
                    -- ###GENERATED END###
                end if;
            when WRITE_PAYLOAD_HEADER =>
                valid_out_dds   <= '1';
                if (LITTLE_ENDIAN = '0') then
                    data_out_dds    <= CDR_BE & x"0000";
                else
                    data_out_dds    <= CDR_LE & x"0000";
                end if;
                -- Output Guard
                if (ready_out_dds = '1') then
                    stage_next          <= ENCODE_PAYLOAD;
                    -- Reset 
                    align_offset_next   <= (others => '0');
                    data_out_latch_next <= (others => '0');
                    -- ###GENERATED START###
                    encode_stage_next   <= WRITE_ID;
                    -- ###GENERATED END###
                end if;
            when PUSH =>
                -- Mark Last Word
                if (finalize_payload = '1') then
                    last_word_out_dds   <= '1';
                end if;
                
                valid_out_dds   <= '1';
                data_out_dds    <= data_out_latch;
                -- Output Guard
                if (ready_out_dds = '1') then
                    -- NOTE: Ensures all padding is zero.
                    data_out_latch_next <= (others => '0');
                    -- Alignment Operation in process
                    if (align_op = '1') then
                        stage_next      <= ALIGN_STREAM;
                        -- Reset
                        align_op_next   <= '0';
                    -- DONE
                    elsif (finalize_payload = '1') then
                        finalize_payload_next   <= '0';
                        stage_next              <= IDLE;
                    else
                        stage_next  <= ENCODE_PAYLOAD;
                    end if;
                end if;
            when ALIGN_STREAM =>
                -- Target Stream Alignment reached
                if (check_align(align_offset, target_align)) then
                    -- DONE
                    stage_next  <= ENCODE_PAYLOAD;
                else
                    align_offset_next   <= align_offset + 1;
                    -- Need to push Word
                    if (align_offset(1 downto 0) = "11") then
                        align_op_next   <= '1';
                        stage_next      <= PUSH;
                    end if;
                end if;
            when ENCODE_PAYLOAD =>
                case (encode_stage) is
                    -- ###GENERATED START###
                    when WRITE_ID =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            data_out_latch_next <= endian_swap(LITTLE_ENDIAN,id);
                            align_offset_next   <= align_offset + 4;
                            stage_next          <= PUSH;
                            -- Next Member
                            encode_stage_next    <= WRITE_TESTSEQUENCE_LENGTH;
                        end if;
                    when WRITE_TESTSEQUENCE_LENGTH =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            data_out_latch_next <= endian_swap(LITTLE_ENDIAN, std_logic_vector(resize(unsigned(TestSequence_len),WORD_WIDTH)));
                            align_offset_next   <= align_offset + 4;
                            stage_next          <= PUSH;
                            
                            -- Empty Sequence
                            if (unsigned(TestSequence_len) = 0) then
                                -- Next Member
                                encode_stage_next    <= WRITE_TESTMAP_LENGTH;
                            else
                                encode_stage_next       <= WRITE_TESTSEQUENCE_TESTARRAY;
                                cnt_next                <= 0;
                                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 WRITE_TESTSEQUENCE_TESTARRAY =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else                            
                            case (cnt) is
                                -- GET
                                when 0 =>
                                    TestSequence_TestArray_mem_addr(TestSequence_cnt)       <= std_logic_vector(to_unsigned(TestSequence_TestArray_cnt,TESTSEQUENCE_TESTARRAY_ADDR_WIDTH));
                                    TestSequence_TestArray_mem_valid_in(TestSequence_cnt)   <= '1';
                                    TestSequence_TestArray_mem_read(TestSequence_cnt)       <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestArray_mem_ready_in(TestSequence_cnt) = '1') then
                                        cnt_next    <= cnt + 1;
                                    end if;
                                -- WRITE
                                when 1 =>
                                    TestSequence_TestArray_mem_ready_out(TestSequence_cnt)  <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestArray_mem_valid_out(TestSequence_cnt) = '1') then
                                        data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, TestSequence_TestArray_mem_data_out(TestSequence_cnt)), to_integer(align_offset(1 downto 0)), TRUE);
                                        align_offset_next   <= align_offset + 1;
                                        cnt_next            <= 0;
                                        
                                        -- All Elements processed
                                        if (TestSequence_TestArray_cnt = TESTSEQUENCE_TESTARRAY_MAX_DEPTH-1) then
                                            encode_stage_next   <= WRITE_TESTSEQUENCE_TESTCHAR;
                                            cnt_next            <= 0;
                                        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  <= PUSH;
                                        end if;
                                    end if;
                                when others => 
                            end case;
                        end if;
                    when WRITE_TESTSEQUENCE_TESTCHAR =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else
                            case (cnt) is
                                -- GET
                                when 0 =>
                                    TestSequence_TestChar_mem_addr      <= std_logic_vector(to_unsigned(TestSequence_cnt,TESTSEQUENCE_ADDR_WIDTH));
                                    TestSequence_TestChar_mem_valid_in  <= '1';
                                    TestSequence_TestChar_mem_read      <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestChar_mem_ready_in = '1') then
                                        cnt_next    <= cnt + 1;
                                    end if;
                                -- WRITE
                                when 1 =>
                                    TestSequence_TestChar_mem_ready_out <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestChar_mem_valid_out = '1') then
                                        data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, TestSequence_TestChar_mem_data_out), to_integer(align_offset(1 downto 0)), TRUE);
                                        align_offset_next   <= align_offset + 1;
                                        
                                        encode_stage_next   <= WRITE_TESTSEQUENCE_TESTWCHAR;
                                        cnt_next            <= 0;
                                        
                                        -- DES: Needed for ALIGN_1
                                        -- Need to fetch next Word
                                        if(align_offset(1 downto 0) = "11") then
                                            stage_next  <= PUSH;
                                        end if;
                                    end if;
                                when others => 
                            end case;
                        end if;
                    when WRITE_TESTSEQUENCE_TESTWCHAR =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_2)) then
                            target_align_next   <= ALIGN_2;
                            stage_next          <= ALIGN_STREAM;
                        else
                            case (cnt) is
                                -- GET
                                when 0 =>
                                    TestSequence_TestWChar_mem_addr      <= std_logic_vector(to_unsigned(TestSequence_cnt,TESTSEQUENCE_ADDR_WIDTH));
                                    TestSequence_TestWChar_mem_valid_in  <= '1';
                                    TestSequence_TestWChar_mem_read      <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestWChar_mem_ready_in = '1') then
                                        cnt_next    <= cnt + 1;
                                    end if;
                                -- WRITE
                                when 1 =>
                                    TestSequence_TestWChar_mem_ready_out <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestWChar_mem_valid_out = '1') then
                                        data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, TestSequence_TestWChar_mem_data_out), to_integer(align_offset(1 downto 1)), TRUE);
                                        align_offset_next   <= align_offset + 2;
                                        
                                        encode_stage_next   <= WRITE_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  <= PUSH;
                                        end if;
                                    end if;
                                when others => 
                            end case;
                        end if;
                    when WRITE_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
                                -- GET
                                when 0 =>
                                    TestSequence_TestLongLong_mem_addr      <= std_logic_vector(to_unsigned(TestSequence_cnt,TESTSEQUENCE_ADDR_WIDTH));
                                    TestSequence_TestLongLong_mem_valid_in  <= '1';
                                    TestSequence_TestLongLong_mem_read      <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongLong_mem_ready_in = '1') then
                                        cnt_next    <= cnt + 1;
                                    end if;
                                -- WRITE 1/2
                                when 1 =>
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongLong_mem_valid_out = '1') then
                                        data_out_latch_next <= get_sub_vector(endian_swap(LITTLE_ENDIAN, TestSequence_TestLongLong_mem_data_out), 0, WORD_WIDTH, TRUE);
                                        stage_next          <= PUSH;
                                        cnt_next            <= cnt + 1;
                                    end if;
                                -- WRITE 2/2
                                when 2 =>
                                    TestSequence_TestLongLong_mem_ready_out <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongLong_mem_valid_out = '1') then
                                        data_out_latch_next <= get_sub_vector(endian_swap(LITTLE_ENDIAN, TestSequence_TestLongLong_mem_data_out), 1, WORD_WIDTH, TRUE);
                                        stage_next          <= PUSH;
                                        align_offset_next   <= align_offset + 8;
                                        encode_stage_next   <= WRITE_TESTSEQUENCE_TESTLONGDOUBLE;
                                        cnt_next            <= 0;
                                    end if;
                                when others => 
                            end case;
                        end if;
                    when WRITE_TESTSEQUENCE_TESTLONGDOUBLE =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            case (cnt) is
                                -- GET
                                when 0 =>
                                    TestSequence_TestLongDouble_mem_addr        <= std_logic_vector(to_unsigned(TestSequence_cnt,TESTSEQUENCE_ADDR_WIDTH));
                                    TestSequence_TestLongDouble_mem_valid_in    <= '1';
                                    TestSequence_TestLongDouble_mem_read        <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongDouble_mem_ready_in = '1') then
                                        cnt_next    <= cnt + 1;
                                    end if;
                                -- OPTIONAL HEADER
                                when 1 =>
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongDouble_mem_valid_out = '1') then
                                        -- Optional Available
                                        if (TestSequence_TestLongDouble_mem_data_out(CDR_LONG_DOUBLE_WIDTH) = '1') then
                                            -- Member ID 4, Length 16
                                            data_out_latch_next <= x"0004" & x"0010";
                                            
                                            cnt_next    <= cnt + 1;
                                        else
                                            -- Member ID 4, Length 0
                                            data_out_latch_next <= x"0004" & x"0000";
                                            
                                            -- All Elements processed
                                            if (TestSequence_cnt = unsigned(TestSequence_len)-1) then
                                                -- Next Member
                                                encode_stage_next    <= WRITE_TESTMAP_LENGTH;
                                            else
                                                TestSequence_cnt_next           <= TestSequence_cnt + 1;
                                                encode_stage_next               <= WRITE_TESTSEQUENCE_TESTARRAY;
                                                TestSequence_TestArray_cnt_next <= 0;
                                                cnt_next                        <= 0;
                                            end if;
                                            -- "Comsume" input word
                                            TestSequence_TestLongDouble_mem_ready_out <= '1';
                                        end if;
                                        -- Reset Alignment
                                        align_offset_next   <= (others => '0');
                                        stage_next          <= PUSH;
                                    end if;
                                -- WRITE 1/4
                                when 2 =>
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongDouble_mem_valid_out = '1') then
                                        data_out_latch_next <= get_sub_vector(endian_swap(LITTLE_ENDIAN, TestSequence_TestLongDouble_mem_data_out(CDR_LONG_DOUBLE_WIDTH-1 downto 0)), 0, WORD_WIDTH, TRUE);
                                        stage_next          <= PUSH;
                                        cnt_next            <= cnt + 1;
                                    end if;
                                -- WRITE 2/4
                                when 3 =>
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongDouble_mem_valid_out = '1') then
                                        data_out_latch_next <= get_sub_vector(endian_swap(LITTLE_ENDIAN, TestSequence_TestLongDouble_mem_data_out(CDR_LONG_DOUBLE_WIDTH-1 downto 0)), 1, WORD_WIDTH, TRUE);
                                        stage_next          <= PUSH;
                                        cnt_next            <= cnt + 1;
                                    end if;
                                -- WRITE 3/4
                                when 4 =>
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongDouble_mem_valid_out = '1') then
                                        data_out_latch_next <= get_sub_vector(endian_swap(LITTLE_ENDIAN, TestSequence_TestLongDouble_mem_data_out(CDR_LONG_DOUBLE_WIDTH-1 downto 0)), 2, WORD_WIDTH, TRUE);
                                        stage_next          <= PUSH;
                                        cnt_next            <= cnt + 1;
                                    end if;
                                -- WRITE 4/4
                                when 5 =>
                                    TestSequence_TestLongDouble_mem_ready_out <= '1';
                                    -- Memory Operation Guard
                                    if (TestSequence_TestLongDouble_mem_valid_out = '1') then
                                        data_out_latch_next <= get_sub_vector(endian_swap(LITTLE_ENDIAN, TestSequence_TestLongDouble_mem_data_out(CDR_LONG_DOUBLE_WIDTH-1 downto 0)), 3, WORD_WIDTH, TRUE);
                                        stage_next          <= PUSH;
                                        align_offset_next   <= align_offset + 16;
                                        
                                        -- All Elements processed
                                        if (TestSequence_cnt = unsigned(TestSequence_len)-1) then
                                            -- Next Member
                                            encode_stage_next    <= WRITE_TESTMAP_LENGTH;
                                        else
                                            TestSequence_cnt_next           <= TestSequence_cnt + 1;
                                            encode_stage_next               <= WRITE_TESTSEQUENCE_TESTARRAY;
                                            TestSequence_TestArray_cnt_next <= 0;
                                            cnt_next                        <= 0;
                                        end if;
                                    end if;
                                when others => 
                            end case;
                        end if;
                    when WRITE_TESTMAP_LENGTH =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            data_out_latch_next <= endian_swap(LITTLE_ENDIAN, std_logic_vector(resize(unsigned(TestMap_len),WORD_WIDTH)));
                            align_offset_next   <= align_offset + 4;
                            stage_next          <= PUSH;
                            
                            -- Empty Sequence
                            if (unsigned(TestMap_len) = 0) then
                                -- Next Member
                                encode_stage_next    <= WRITE_TESTENUM;
                            else
                                encode_stage_next   <= WRITE_TESTMAP_KEY;
                                cnt_next            <= 0;
                                TestMap_cnt_next    <= 0;
                            end if;
                        end if;
                    when WRITE_TESTMAP_KEY =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else
                            case (cnt) is
                                -- GET
                                when 0 =>
                                    TestMap_key_mem_addr        <= std_logic_vector(to_unsigned(TestMap_cnt,TESTMAP_ADDR_WIDTH));
                                    TestMap_key_mem_valid_in    <= '1';
                                    TestMap_key_mem_read        <= '1';
                                    -- Memory Operation Guard
                                    if (TestMap_key_mem_ready_in = '1') then
                                        cnt_next    <= cnt + 1;
                                    end if;
                                -- WRITE
                                when 1 =>
                                    TestMap_key_mem_ready_out   <= '1';
                                    -- Memory Operation Guard
                                    if (TestMap_key_mem_valid_out = '1') then
                                        data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, TestMap_key_mem_data_out), to_integer(align_offset(1 downto 0)), TRUE);
                                        align_offset_next   <= align_offset + 1;
                                        
                                        encode_stage_next   <= WRITE_TESTMAP_VALUE;
                                        cnt_next            <= 0;    
                                        
                                        -- DES: Needed for ALIGN_1
                                        -- Need to fetch next Word
                                        if(align_offset(1 downto 0) = "11") then
                                            stage_next  <= PUSH;
                                        end if;
                                    end if;
                                when others => 
                            end case;
                        end if;
                    when WRITE_TESTMAP_VALUE =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_2)) then
                            target_align_next   <= ALIGN_2;
                            stage_next          <= ALIGN_STREAM;
                        else
                            case (cnt) is
                                -- GET
                                when 0 =>
                                    TestMap_value_mem_addr      <= std_logic_vector(to_unsigned(TestMap_cnt,TESTMAP_ADDR_WIDTH));
                                    TestMap_value_mem_valid_in  <= '1';
                                    TestMap_value_mem_read      <= '1';
                                    -- Memory Operation Guard
                                    if (TestMap_value_mem_ready_in = '1') then
                                        cnt_next    <= cnt + 1;
                                    end if;
                                -- WRITE
                                when 1 =>
                                    TestMap_value_mem_ready_out <= '1';
                                    -- Memory Operation Guard
                                    if (TestMap_value_mem_valid_out = '1') then
                                        data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, TestMap_value_mem_data_out), to_integer(align_offset(1 downto 1)), TRUE);
                                        align_offset_next   <= align_offset + 2;
                                        
                                        -- All Elements processed
                                        if (TestMap_cnt = unsigned(TestMap_len)-1) then
                                            -- Next Member
                                            encode_stage_next    <= WRITE_TESTENUM;
                                        else
                                            TestMap_cnt_next    <= TestMap_cnt + 1;
                                            encode_stage_next   <= WRITE_TESTMAP_KEY;
                                            cnt_next            <= 0;
                                        end if;
                                        
                                        -- Need to fetch next Word
                                        if(align_offset(1 downto 1) = "1") then
                                            stage_next  <= PUSH;
                                        end if;
                                    end if;
                                when others => 
                            end case;
                        end if;
                    when WRITE_TESTENUM =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else
                            data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, std_logic_vector(resize(unsigned(TestEnum),TESTENUM_CDR_WIDTH))), to_integer(align_offset(1 downto 0)), TRUE);
                            align_offset_next   <= align_offset + 1;
                            
                            -- Next Member
                            encode_stage_next   <= WRITE_TESTUNION_D;
                            cnt_next            <= 0;
                            
                            -- Need to fetch next Word
                            if(align_offset(1 downto 0) = "11") then
                                stage_next  <= PUSH;
                            end if;
                        end if;
                    when WRITE_TESTUNION_D =>
                        -- 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 HEADER
                                when 0 =>
                                    -- Optional Available
                                    if (TestUnion_opt = '1') then
                                        case (TestUnion_d) is
                                            when TESTUNION_LONGU_D =>
                                                -- Member ID 4, Length 8
                                                data_out_latch_next <= x"0004" & x"0008";
                                            when others =>
                                                -- Member ID 4, Length 2
                                                data_out_latch_next <= x"0004" & x"0002";
                                        end case;
                                        cnt_next            <= cnt + 1;
                                    else
                                        -- Member ID 4, Length 0
                                        data_out_latch_next <= x"0004" & x"0000";
                                        
                                        encode_stage_next    <= WRITE_TESTBITMASK;
                                    end if;
                                    
                                    -- Reset Alignment
                                    align_offset_next   <= (others => '0');
                                    stage_next          <= PUSH;
                                -- WRITE Discriminator
                                when 1 =>
                                    data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, TestUnion_d), to_integer(align_offset(1 downto 0)), TRUE);
                                    align_offset_next   <= align_offset + 1;
                                    
                                    case (TestUnion_d) is
                                        when TESTUNION_LONGU_D =>
                                            -- Member ID 4, Length 16
                                            encode_stage_next    <= WRITE_TESTUNION_LONGU;
                                        when others =>
                                            encode_stage_next    <= WRITE_TESTUNION_OCTETU;
                                    end case;
                                    
                                    -- Need to fetch next Word
                                    if(align_offset(1 downto 0) = "11") then
                                        stage_next  <= PUSH;
                                    end if;
                                when others => 
                            end case;
                        end if;
                    when WRITE_TESTUNION_LONGU =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            data_out_latch_next <= endian_swap(LITTLE_ENDIAN, TestUnion_LongU);
                            align_offset_next   <= align_offset + 4;
                            
                            -- Next Member
                            encode_stage_next    <= WRITE_TESTBITMASK;
                            stage_next          <= PUSH;
                        end if;
                    when WRITE_TESTUNION_OCTETU =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else
                            data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, TestUnion_OctetU), to_integer(align_offset(1 downto 0)), TRUE);
                            align_offset_next   <= align_offset + 1;
                            
                            -- Next Member
                            encode_stage_next    <= WRITE_TESTBITMASK;
                            
                            -- Need to fetch next Word
                            if(align_offset(1 downto 0) = "11") then
                                stage_next  <= PUSH;
                            end if;
                        end if;
                    when WRITE_TESTBITMASK =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_2)) then
                            target_align_next   <= ALIGN_2;
                            stage_next          <= ALIGN_STREAM;
                        else
                            data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, std_logic_vector(resize(unsigned(TestBitmask),TESTBITMASK_CDR_WIDTH))), to_integer(align_offset(1 downto 1)), TRUE);
                            align_offset_next   <= align_offset + 2;
                            
                            -- Next Member
                            encode_stage_next    <= WRITE_TESTSTRING_LENGTH;
                            
                            -- Need to fetch next Word
                            if(align_offset(1 downto 1) = "1") then
                                stage_next  <= PUSH;
                            end if;
                        end if;
                    when WRITE_TESTSTRING_LENGTH =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_4)) then
                            target_align_next   <= ALIGN_4;
                            stage_next          <= ALIGN_STREAM;
                        else
                            data_out_latch_next <= endian_swap(LITTLE_ENDIAN, std_logic_vector(resize(unsigned(TestString_len),WORD_WIDTH)));
                            align_offset_next   <= align_offset + 4;
                            stage_next          <= PUSH;
                            
                            -- Empty Sequence
                            if (unsigned(TestString_len) = 0) then
                                -- DONE
                                stage_next              <= PUSH;
                                finalize_payload_next   <= '1';
                                encode_done             <= '1';
                            else
                                encode_stage_next   <= WRITE_TESTSTRING;
                                cnt_next            <= 0;
                                TestString_cnt_next <= 0;
                            end if;
                        end if;
                    when WRITE_TESTSTRING =>
                        -- ALIGN GUARD
                        if (not check_align(align_offset, ALIGN_1)) then
                            target_align_next   <= ALIGN_1;
                            stage_next          <= ALIGN_STREAM;
                        else                            
                            case (cnt) is
                                -- GET
                                when 0 =>
                                    TestString_mem_addr     <= std_logic_vector(to_unsigned(TestString_cnt,TESTSTRING_ADDR_WIDTH));
                                    TestString_mem_valid_in <= '1';
                                    TestString_mem_read     <= '1';
                                    -- Memory Operation Guard
                                    if (TestString_mem_ready_in = '1') then
                                        cnt_next    <= cnt + 1;
                                    end if;
                                -- WRITE
                                when 1 =>
                                    TestString_mem_ready_out    <= '1';
                                    -- Memory Operation Guard
                                    if (TestString_mem_valid_out = '1') then
                                        data_out_latch_next <= write_sub_vector(data_out_latch, endian_swap(LITTLE_ENDIAN, TestString_mem_data_out), to_integer(align_offset(1 downto 0)), TRUE);
                                        align_offset_next   <= align_offset + 1;
                                        cnt_next            <= 0;
                                        
                                        -- All Elements processed
                                        if (TestString_cnt = unsigned(TestString_len)-1) then
                                            -- DONE
                                            stage_next              <= PUSH;
                                            finalize_payload_next   <= '1';
                                            encode_done             <= '1';
                                        else
                                            TestString_cnt_next <= TestString_cnt + 1;
                                        end if;
                                        
                                        -- Need to fetch next Word
                                        if(align_offset(1 downto 0) = "11") then
                                            stage_next  <= PUSH;
                                        end if;
                                    end if;
                                when others => 
                            end case;
                        end if;
                    -- ###GENERATED END###
                    when others =>
                        null;
                end case;
            when others =>
                null;
        end case;
    end process;
    
    sync_prc : process(clk)
    begin
        if rising_edge(clk) then
            if (reset = '1') then
                stage               <= IDLE;
                encode_stage        <= WRITE_ID;
                target_align        <= ALIGN_1;
                cnt                 <= 0;
                finalize_payload    <= '0';
                align_op            <= '0';
                align_offset        <= (others => '0');
                data_out_latch      <= (others => '0');
                -- ###GENERATED START###
                TestSequence_cnt            <= 0;
                TestSequence_TestArray_cnt  <= 0;
                TestMap_cnt                 <= 0;
                TestString_cnt              <= 0;
                TestSequence_addr_latch     <= (others => '0');
                -- ###GENERATED END###
            else
                stage               <= stage_next;
                encode_stage        <= encode_stage_next;
                target_align        <= target_align_next;
                cnt                 <= cnt_next;
                finalize_payload    <= finalize_payload_next;
                align_op            <= align_op_next;
                align_offset        <= align_offset_next;
                data_out_latch      <= data_out_latch_next;
                -- ###GENERATED START###
                TestSequence_cnt            <= TestSequence_cnt_next;
                TestSequence_TestArray_cnt  <= TestSequence_TestArray_cnt_next;
                TestMap_cnt                 <= TestMap_cnt_next;
                TestString_cnt              <= TestString_cnt_next;
                TestSequence_addr_latch     <= TestSequence_addr_latch_next;
                -- ###GENERATED END###
            end if;
        end if;
    end process;
    
end architecture;