data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v
1: b'%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:3: Cannot find include file: noc_parameter.vh\n    `include "noc_parameter.vh" \n             ^~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog,data/full_repos/permissive/463204869/noc_parameter.vh\n             data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog,data/full_repos/permissive/463204869/noc_parameter.vh.v\n             data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog,data/full_repos/permissive/463204869/noc_parameter.vh.sv\n             noc_parameter.vh\n             noc_parameter.vh.v\n             noc_parameter.vh.sv\n             obj_dir/noc_parameter.vh\n             obj_dir/noc_parameter.vh.v\n             obj_dir/noc_parameter.vh.sv\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:4: Cannot find include file: tcu_parameter.vh\n    ,`include "tcu_parameter.vh" \n              ^~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:75: Cannot find include file: tcu_functions.v\n    `include "tcu_functions.v" \n             ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:4: syntax error, unexpected \',\', expecting \'[\'\n    , \n    ^\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:6: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter TCU_ENABLE_DRAM            = 0,\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:7: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter TCU_ENABLE_LOG             = 0,\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:8: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter [31:0] TIMEOUT_RECV_CYCLES = 0\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:9: syntax error, unexpected \')\', expecting \';\'\n)(\n^\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:11: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                                reset_n_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:15: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output reg                                 rm_reg_en_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:16: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg         [TCU_REG_DATA_SIZE-1:0] rm_reg_wben_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:17: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output wire        [TCU_REG_ADDR_SIZE-1:0] rm_reg_addr_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:18: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire        [TCU_REG_DATA_SIZE-1:0] rm_reg_wdata_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:19: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire        [TCU_REG_DATA_SIZE-1:0] rm_reg_rdata_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:20: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                                rm_reg_stall_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:24: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                          [2:0] rm_mem_en_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:25: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire        [TCU_MEM_BSEL_SIZE-1:0] rm_mem_wben_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:26: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire        [TCU_MEM_ADDR_SIZE-1:0] rm_mem_addr_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:27: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire        [TCU_MEM_DATA_SIZE-1:0] rm_mem_wdata_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:28: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                                rm_mem_wdata_infifo_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:29: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output reg                                 rm_mem_wabort_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:30: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  wire                                rm_mem_stall_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:34: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output reg                                 noc_fifo_pop_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:35: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  wire                                noc_wrreq_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:36: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                                noc_burst_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:37: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire            [NOC_BSEL_SIZE-1:0] noc_bsel_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:38: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                                noc_stall_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:39: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                                noc_wrreq_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:40: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire            [NOC_DATA_SIZE-1:0] noc_data_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:41: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire            [NOC_ADDR_SIZE-1:0] noc_addr_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:42: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire          [NOC_CHIPID_SIZE-1:0] noc_chipid_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:43: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire           [NOC_MODID_SIZE-1:0] noc_modid_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:47: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                                rm_start_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:48: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire              [TCU_EP_SIZE-1:0] rm_recvep_i,    \n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:49: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                        [127:0] rm_header_i,    \n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:50: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                         [31:0] rm_cur_vpe_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:51: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                                rm_active_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:52: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                                rm_cur_vpe_active_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:53: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                                rm_crd_update_active_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:54: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output reg                                 rm_done_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:58: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg                                 rm_core_req_push_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:59: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg  [TCU_CORE_REQ_FORMSG_SIZE-1:0] rm_core_req_data_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:60: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  wire                                rm_core_req_stall_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:64: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire        [TCU_LOG_DATA_SIZE-1:0] tcu_log_rm_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:68: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                                tcu_features_virt_pes_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:72: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire          [NOC_CHIPID_SIZE-1:0] home_chipid_i\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:73: syntax error, unexpected \')\', expecting \',\' or \';\'\n);\n^\n%Error: data/full_repos/permissive/463204869/units/tcu/source/rtl/verilog/tcu_ctrl_recv_msg.v:203: syntax error, unexpected always\n    always @(posedge clk_i) begin\n    ^~~~~~\n%Error: Exiting due to 48 error(s)\n'
module tcu_ctrl_recv_msg #(
    `include "noc_parameter.vh"
    ,`include "tcu_parameter.vh"
    ,parameter TCU_ENABLE_VIRT_PES       = 0,
    parameter TCU_ENABLE_DRAM            = 0,
    parameter TCU_ENABLE_LOG             = 0,
    parameter [31:0] TIMEOUT_RECV_CYCLES = 0
)(
    input  wire                                clk_i,
    input  wire                                reset_n_i,



    output reg                                 rm_reg_en_o,
    output reg         [TCU_REG_DATA_SIZE-1:0] rm_reg_wben_o,
    output wire        [TCU_REG_ADDR_SIZE-1:0] rm_reg_addr_o,
    output wire        [TCU_REG_DATA_SIZE-1:0] rm_reg_wdata_o,
    input  wire        [TCU_REG_DATA_SIZE-1:0] rm_reg_rdata_i,
    input  wire                                rm_reg_stall_i,



    output wire                          [2:0] rm_mem_en_o,
    output wire        [TCU_MEM_BSEL_SIZE-1:0] rm_mem_wben_o,
    output wire        [TCU_MEM_ADDR_SIZE-1:0] rm_mem_addr_o,
    output wire        [TCU_MEM_DATA_SIZE-1:0] rm_mem_wdata_o,
    input  wire                                rm_mem_wdata_infifo_i,
    output reg                                 rm_mem_wabort_o,
    input  wire                                rm_mem_stall_i,



    output reg                                 noc_fifo_pop_o,
    input  wire                                noc_wrreq_i,
    input  wire                                noc_burst_i,
    input  wire            [NOC_BSEL_SIZE-1:0] noc_bsel_i,
    input  wire                                noc_stall_i,
    output wire                                noc_wrreq_o,
    output wire            [NOC_DATA_SIZE-1:0] noc_data_o,
    output wire            [NOC_ADDR_SIZE-1:0] noc_addr_o,
    output wire          [NOC_CHIPID_SIZE-1:0] noc_chipid_o,
    output wire           [NOC_MODID_SIZE-1:0] noc_modid_o,



    input  wire                                rm_start_i,
    input  wire              [TCU_EP_SIZE-1:0] rm_recvep_i,
    input  wire                        [127:0] rm_header_i,
    input  wire                         [31:0] rm_cur_vpe_i,
    output wire                                rm_active_o,
    output wire                                rm_cur_vpe_active_o,
    output wire                                rm_crd_update_active_o,
    output reg                                 rm_done_o,



    output reg                                 rm_core_req_push_o,
    output reg  [TCU_CORE_REQ_FORMSG_SIZE-1:0] rm_core_req_data_o,
    input  wire                                rm_core_req_stall_i,



    output wire        [TCU_LOG_DATA_SIZE-1:0] tcu_log_rm_o,



    input  wire                                tcu_features_virt_pes_i,



    input  wire          [NOC_CHIPID_SIZE-1:0] home_chipid_i
);

    `include "tcu_functions.v"


    localparam CTRL_RM_STATES_SIZE          = 5;
    localparam S_CTRL_RM_IDLE               = 5'h00;
    localparam S_CTRL_RM_READ_EP1           = 5'h01;
    localparam S_CTRL_RM_READ_EP2           = 5'h02;
    localparam S_CTRL_RM_READ_EP3           = 5'h03;
    localparam S_CTRL_RM_READ_EP4           = 5'h04;
    localparam S_CTRL_RM_TAKE_HD            = 5'h05;
    localparam S_CTRL_RM_CHECK_EP           = 5'h06;
    localparam S_CTRL_RM_FIND_SLOT          = 5'h07;
    localparam S_CTRL_RM_WRITE_PREPARE_MEM1 = 6'h08;
    localparam S_CTRL_RM_WRITE_PREPARE_MEM2 = 6'h09;
    localparam S_CTRL_RM_WRITE_MEM_HD       = 5'h0A;
    localparam S_CTRL_RM_WRITE_MEM_PL1      = 5'h0B;
    localparam S_CTRL_RM_WRITE_MEM_PL2      = 5'h0C;
    localparam S_CTRL_RM_UPDATE_EP3         = 5'h0D;
    localparam S_CTRL_RM_UPDATE_EP4         = 5'h0E;
    localparam S_CTRL_RM_CREATE_REPLYEP1    = 5'h0F;
    localparam S_CTRL_RM_CREATE_REPLYEP2    = 5'h10;
    localparam S_CTRL_RM_CREATE_REPLYEP3    = 5'h11;
    localparam S_CTRL_RM_CREATE_REPLYEP4    = 5'h12;
    localparam S_CTRL_RM_READ_SEP1          = 5'h13;
    localparam S_CTRL_RM_READ_SEP2          = 5'h14;
    localparam S_CTRL_RM_READ_SEP3          = 5'h15;
    localparam S_CTRL_RM_UPDATE_SEP1        = 5'h16;
    localparam S_CTRL_RM_UPDATE_SEP2        = 5'h17;
    localparam S_CTRL_RM_CHECK_VPE          = 5'h18;
    localparam S_CTRL_RM_UPDATE_VPE         = 5'h19;
    localparam S_CTRL_RM_WAIT_DRAM          = 5'h1A;
    localparam S_CTRL_RM_ERROR              = 5'h1B;
    localparam S_CTRL_RM_FINISH             = 5'h1F;

    reg [CTRL_RM_STATES_SIZE-1:0] ctrl_rm_state, next_ctrl_rm_state;




    reg [63:0] r_rep_0, rin_rep_0;
    reg [63:0] r_rep_1, rin_rep_1;
    reg [63:0] r_rep_2, rin_rep_2;

    reg [63:0] r_sep_0, rin_sep_0;


    reg [63:0] r_hd_0, rin_hd_0;
    reg [63:0] r_hd_1, rin_hd_1;


    reg [31:0] r_laddr, rin_laddr;
    reg [15:0] r_size, rin_size;

    reg                   [2:0] r_mem_en, rin_mem_en;
    reg [TCU_MEM_BSEL_SIZE-1:0] r_mem_wben, rin_mem_wben;
    reg [TCU_MEM_ADDR_SIZE-1:0] r_mem_addr;

    reg [TCU_REG_DATA_SIZE-1:0] r_reg_wben, rin_reg_wben;
    reg [TCU_REG_ADDR_SIZE-1:0] r_reg_addr, rin_reg_addr;
    reg [TCU_REG_DATA_SIZE-1:0] r_reg_wdata, rin_reg_wdata;


    reg r_rm_reg_rdata_avail, rin_rm_reg_rdata_avail;


    reg [TCU_ERROR_SIZE-1:0] r_rm_error, rin_rm_error;


    reg [TCU_EP_SIZE-1:0] r_recvep, rin_recvep;
    reg [31:0] r_recvep_baseaddr, rin_recvep_baseaddr;


    reg [TCU_SLOT_SIZE-1:0] r_tmp_wpos, rin_tmp_wpos;


    reg [31:0] r_rm_timeout, rin_rm_timeout;



    wire [TCU_EP_TYPE_SIZE-1:0] rep_type     = r_rep_0[TCU_EP_TYPE_SIZE-1 : 0];
    wire   [TCU_VPEID_SIZE-1:0] rep_vpeid    = r_rep_0[TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_EP_TYPE_SIZE];
    wire      [TCU_EP_SIZE-1:0] rep_rpleps   = r_rep_0[TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire    [TCU_SLOT_SIZE-1:0] rep_slots    = r_rep_0[TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire    [TCU_SLOT_SIZE-1:0] rep_slotsize = r_rep_0[2*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire    [TCU_SLOT_SIZE-1:0] rep_wpos     = r_rep_0[3*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : 2*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire    [TCU_SLOT_SIZE-1:0] rep_rpos     = r_rep_0[4*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : 3*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire                 [63:0] rep_buffer   = r_rep_1;
    wire                 [31:0] rep_occupied = r_rep_2[31:0];
    wire                 [31:0] rep_unread   = r_rep_2[63:32];

    wire      [TCU_CRD_SIZE-1:0] sep_curcrd      = r_sep_0[TCU_CRD_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire [TCU_REG_DATA_SIZE-1:0] sep_curcrd_incr = sep_curcrd + 'd1;



    wire [TCU_HD_FLAG_SIZE-1:0] hd_flags      = r_hd_0[TCU_HD_FLAG_SIZE-1 : 0];
    wire   [TCU_RSIZE_SIZE-1:0] hd_replysize  = r_hd_0[TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE-1 : TCU_HD_FLAG_SIZE];
    wire    [TCU_PEID_SIZE-1:0] hd_sendpe     = r_hd_0[TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE-1 : TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE];
    wire  [TCU_CHIPID_SIZE-1:0] hd_sendchip   = r_hd_0[TCU_CHIPID_SIZE+TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE-1 : TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE];
    wire  [TCU_MSGLEN_SIZE-1:0] hd_length     = r_hd_0[TCU_MSGLEN_SIZE+TCU_CHIPID_SIZE+TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE-1 : TCU_CHIPID_SIZE+TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE];
    wire      [TCU_EP_SIZE-1:0] hd_sendep     = r_hd_0[TCU_EP_SIZE+32-1 : 32];
    wire      [TCU_EP_SIZE-1:0] hd_recvep     = r_hd_0[2*TCU_EP_SIZE+32-1 : TCU_EP_SIZE+32];
    wire                 [31:0] hd_replylabel = r_hd_1[31:0];
    wire                 [31:0] hd_label      = r_hd_1[63:32];



    wire [31:0] recvep_addr   = TCU_REGADDR_EP_START + rm_recvep_i*TCU_EP_REG_SIZE;
    wire [31:0] hdrecvep_addr = TCU_REGADDR_EP_START + hd_recvep*TCU_EP_REG_SIZE;
    wire [31:0] rplep_addr    = TCU_REGADDR_EP_START + (rep_rpleps+r_tmp_wpos)*TCU_EP_REG_SIZE;

    wire     [TCU_SLOT_SIZE-1:0] tmp_pos_incr = r_tmp_wpos + 1'b1;
    wire [TCU_REG_DATA_SIZE-1:0] set_bit_wpos = 32'h1 << r_tmp_wpos;


    wire [TCU_SLOT_SIZE-1:0] max_slot = (rep_slots > 'h5) ? 'd32 : {{(TCU_SLOT_SIZE-1){1'b0}}, 1'b1} << rep_slots[2:0];


    wire [4:0] wben_count_ones = count_ones8(rin_mem_wben[7:0]) + count_ones8(rin_mem_wben[15:8]);


    wire [TCU_REG_DATA_SIZE-1:0] cur_vpe_msgs_incr = rm_cur_vpe_i[TCU_VPE_MSGS_SIZE+TCU_VPEID_SIZE-1:TCU_VPEID_SIZE] + 'd1;


    wire [TCU_SLOT_SIZE-1:0] reply_msg_sz = hd_replysize;



    always @(posedge clk_i) begin
        if (reset_n_i == 1'b0) begin
            ctrl_rm_state <= S_CTRL_RM_IDLE;

            r_laddr <= 32'h0;
            r_size <= 16'h0;

            r_rm_reg_rdata_avail <= 1'b0;
            r_rm_error <= TCU_ERROR_NONE;

            r_mem_en <= 3'h0;
            r_mem_wben <= {TCU_MEM_BSEL_SIZE{1'b0}};
            r_mem_addr <= {TCU_MEM_ADDR_SIZE{1'b0}};

            r_reg_wben <= {TCU_REG_DATA_SIZE{1'b0}};
            r_reg_addr <= {TCU_REG_ADDR_SIZE{1'b0}};
            r_reg_wdata <= {TCU_REG_DATA_SIZE{1'b0}};

            r_recvep <= {TCU_EP_SIZE{1'b0}};
            r_recvep_baseaddr <= 32'h0;

            r_hd_0 <= 64'h0;
            r_hd_1 <= 64'h0;

            r_rep_0 <= 64'h0;
            r_rep_1 <= 64'h0;
            r_rep_2 <= 64'h0;

            r_sep_0 <= 64'h0;

            r_tmp_wpos <= {TCU_SLOT_SIZE{1'b0}};

            r_rm_timeout <= 32'h0;
        end
        else begin
            ctrl_rm_state <= next_ctrl_rm_state;
            
            r_laddr <= rin_laddr;
            r_size <= rin_size;

            r_rm_reg_rdata_avail <= rin_rm_reg_rdata_avail;
            r_rm_error <= rin_rm_error;

            r_mem_en <= rin_mem_en;
            r_mem_wben <= rin_mem_wben;
            r_mem_addr <= r_laddr;

            r_reg_wben <= rin_reg_wben;
            r_reg_addr <= rin_reg_addr;
            r_reg_wdata <= rin_reg_wdata;

            r_recvep <= rin_recvep;
            r_recvep_baseaddr <= rin_recvep_baseaddr;

            r_hd_0 <= rin_hd_0;
            r_hd_1 <= rin_hd_1;
            
            r_rep_0 <= rin_rep_0;
            r_rep_1 <= rin_rep_1;
            r_rep_2 <= rin_rep_2;

            r_sep_0 <= rin_sep_0;

            r_tmp_wpos <= rin_tmp_wpos;

            r_rm_timeout <= rin_rm_timeout;
        end
    end






    always @* begin
        next_ctrl_rm_state = ctrl_rm_state;

        rin_laddr = r_laddr;
        rin_size = r_size;

        noc_fifo_pop_o = 1'b0;

        rin_rm_reg_rdata_avail = 1'b0;
        rin_rm_error = r_rm_error;

        rm_done_o = 1'b0;

        rin_tmp_wpos = r_tmp_wpos;

        rin_recvep = r_recvep;
        rin_recvep_baseaddr = r_recvep_baseaddr;

        rin_reg_wben = r_reg_wben;
        rin_reg_addr = r_reg_addr;
        rin_reg_wdata = r_reg_wdata;

        rin_hd_0 = r_hd_0;
        rin_hd_1 = r_hd_1;
            
        rin_rep_0 = r_rep_0;
        rin_rep_1 = r_rep_1;
        rin_rep_2 = r_rep_2;

        rin_sep_0 = r_sep_0;

        rm_core_req_push_o = 1'b0;
        rm_core_req_data_o = {TCU_CORE_REQ_FORMSG_SIZE{1'b0}};

        rin_rm_timeout = 32'h0;

        rm_mem_wabort_o = 1'b0;


        case (ctrl_rm_state)



            S_CTRL_RM_IDLE: begin
                if (rm_start_i) begin

                    rin_recvep = rm_recvep_i;
                    rin_recvep_baseaddr = recvep_addr;
                    rin_reg_addr = recvep_addr;

                    next_ctrl_rm_state = S_CTRL_RM_READ_EP1;
                    rin_rm_error = TCU_ERROR_NONE;
                end
            end



            S_CTRL_RM_READ_EP1: begin
                if (!rm_reg_stall_i) begin
                    rin_reg_addr = r_reg_addr + 'h8;
                    rin_rm_reg_rdata_avail = 1'b1;
                    next_ctrl_rm_state = S_CTRL_RM_READ_EP2;
                end
            end

            S_CTRL_RM_READ_EP2: begin
                if (r_rm_reg_rdata_avail) begin
                    rin_rep_0 = rm_reg_rdata_i;
                end

                if (!rm_reg_stall_i) begin
                    rin_reg_addr = r_reg_addr + 'h8;
                    rin_rm_reg_rdata_avail = 1'b1;
                    next_ctrl_rm_state = S_CTRL_RM_READ_EP3;
                end
            end

            S_CTRL_RM_READ_EP3: begin


                rin_tmp_wpos = rep_wpos;

                if (r_rm_reg_rdata_avail) begin
                    rin_rep_1 = rm_reg_rdata_i;
                end

                if (!rm_reg_stall_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_READ_EP4;
                end
            end

            S_CTRL_RM_READ_EP4: begin

                rin_rep_2 = rm_reg_rdata_i;
                next_ctrl_rm_state = S_CTRL_RM_TAKE_HD;
            end


            S_CTRL_RM_TAKE_HD: begin
                if (noc_wrreq_i) begin

                    rin_hd_0 = rm_header_i[63:0];
                    rin_hd_1 = rm_header_i[127:64];
                    next_ctrl_rm_state = S_CTRL_RM_CHECK_EP;
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rin_rm_error = TCU_ERROR_TIMEOUT_NOC;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end



            S_CTRL_RM_CHECK_EP: begin

                if (rep_type == TCU_EP_TYPE_RECEIVE) begin


                    if ((hd_length+TCU_HD_REG_SIZE) <= (32'h1 << rep_slotsize)) begin


                        if ((rep_rpleps == {TCU_EP_SIZE{1'b1}}) ||
                            ((rep_rpleps + (32'h1 << rep_slots)) <= TCU_EP_REG_COUNT)) begin
                            next_ctrl_rm_state = S_CTRL_RM_FIND_SLOT;
                        end
                        else begin
                            rin_rm_error = TCU_ERROR_RECV_INV_RPL_EPS;
                            next_ctrl_rm_state = S_CTRL_RM_FINISH;
                        end
                    end
                    else begin
                        rin_rm_error = TCU_ERROR_RECV_OUT_OF_BOUNDS;
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
                else begin
                    rin_rm_error = TCU_ERROR_RECV_GONE;
                    next_ctrl_rm_state = S_CTRL_RM_FINISH;
                end
            end



            S_CTRL_RM_FIND_SLOT: begin

                if (r_tmp_wpos < max_slot) begin
                    if (!rep_occupied[r_tmp_wpos]) begin
                        rin_tmp_wpos = r_tmp_wpos;


                        rin_laddr = rep_buffer[31:0] + (r_tmp_wpos<<rep_slotsize);
                        rin_size = hd_length + TCU_HD_REG_SIZE;

                        next_ctrl_rm_state = S_CTRL_RM_WRITE_PREPARE_MEM1;
                    end


                    else if (tmp_pos_incr != rep_wpos) begin
                        rin_tmp_wpos = tmp_pos_incr;
                        next_ctrl_rm_state = S_CTRL_RM_FIND_SLOT;
                    end


                    else begin
                        rin_rm_error = TCU_ERROR_RECV_NO_SPACE;
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
                else begin

                    rin_tmp_wpos = 'h0;
                    next_ctrl_rm_state = S_CTRL_RM_FIND_SLOT;
                end
            end



            S_CTRL_RM_WRITE_PREPARE_MEM1: begin
                if (noc_wrreq_i) begin

                    rin_reg_wben = {{{TCU_REG_DATA_SIZE-TCU_SLOT_SIZE}{1'b0}}, {TCU_SLOT_SIZE{1'b1}}} << (2*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE);
                    rin_reg_addr = r_recvep_baseaddr;
                    rin_reg_wdata = {{(TCU_REG_DATA_SIZE-TCU_SLOT_SIZE){1'b0}}, tmp_pos_incr} << (2*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE);


                    if (TCU_ENABLE_DRAM && noc_burst_i && (r_size > 'd16)) begin
                        next_ctrl_rm_state = S_CTRL_RM_WRITE_PREPARE_MEM2;
                    end


                    else begin
                        next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_HD;
                    end
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rin_rm_error = TCU_ERROR_TIMEOUT_NOC;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end


            S_CTRL_RM_WRITE_PREPARE_MEM2: begin
                if (!rm_mem_stall_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_HD;
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end




            S_CTRL_RM_WRITE_MEM_HD: begin
                if (noc_wrreq_i) begin
                    if (!rm_mem_stall_i) begin
                        noc_fifo_pop_o = 1'b1;


                        if (noc_bsel_i == {NOC_BSEL_SIZE{1'b0}}) begin
                            rm_mem_wabort_o = 1'b1;
                            rin_rm_error = TCU_ERROR_ABORT;
                            next_ctrl_rm_state = S_CTRL_RM_FINISH;
                        end
                        else begin
                            rin_laddr = r_laddr + 'd16;
                            rin_size = r_size - (5'd16 - r_laddr[3:0]);


                            if (noc_burst_i) begin
                                next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_PL1;
                            end



                            else if (rin_size > 'd0) begin
                                next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_PL2;
                            end


                            else begin
                                next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP3;
                            end
                        end
                    end


                    else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                        rin_rm_timeout = r_rm_timeout + 32'd1;
                        if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                            rm_mem_wabort_o = 1'b1;
                            rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                            next_ctrl_rm_state = S_CTRL_RM_ERROR;
                        end
                    end
                end
            end


            S_CTRL_RM_WRITE_MEM_PL1: begin
                if (noc_wrreq_i && !rm_mem_stall_i) begin
                    noc_fifo_pop_o = 1'b1;


                    if (noc_bsel_i == {NOC_BSEL_SIZE{1'b0}}) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_ABORT;
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                    else begin
                        rin_size = r_size - wben_count_ones;
                        rin_laddr = r_laddr + 'd16;


                        if (noc_burst_i) begin

                            if (r_size > 'd16) begin
                                next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_PL1;
                            end
                            else begin
                                rin_rm_error = TCU_ERROR_CRITICAL;
                                next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP3;
                            end
                        end


                        else begin


                            if (r_size > 'd16) begin
                                next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_PL2;
                            end


                            else begin
                                rin_size = 'd0;
                                next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP3;
                            end
                        end
                    end
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = noc_wrreq_i ? TCU_ERROR_TIMEOUT_MEM : TCU_ERROR_TIMEOUT_NOC;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end


            S_CTRL_RM_WRITE_MEM_PL2: begin
                if (!rm_mem_stall_i) begin
                    rin_size = 'd0;
                    next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP3;
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end




            S_CTRL_RM_UPDATE_EP3: begin
                if (!rm_reg_stall_i) begin
                    rin_reg_wben = (set_bit_wpos<<32) | set_bit_wpos;
                    rin_reg_addr = r_recvep_baseaddr + 'h10;
                    rin_reg_wdata = (set_bit_wpos<<32) | set_bit_wpos;
                    next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP4;
                end
            end

            S_CTRL_RM_UPDATE_EP4: begin

                if (!rm_reg_stall_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_CREATE_REPLYEP1;
                end
            end




            S_CTRL_RM_CREATE_REPLYEP1: begin

                if (((hd_flags & TCU_HD_FLAG_REPLY) == {TCU_HD_FLAG_SIZE{1'b0}}) &&
                    (rep_rpleps != {TCU_EP_SIZE{1'b1}}) &&
                    (hd_recvep != {TCU_EP_SIZE{1'b1}})) begin
                    rin_reg_wben = {(1+TCU_EP_SIZE+TCU_SLOT_SIZE+2*TCU_CRD_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE){1'b1}};
                    rin_reg_addr = rplep_addr;
                    rin_reg_wdata = {1'b1,
                                     hd_sendep,
                                     reply_msg_sz,
                                     {{(TCU_CRD_SIZE-1){1'b0}}, 1'b1},
                                     {{(TCU_CRD_SIZE-1){1'b0}}, 1'b1},
                                     rep_vpeid,
                                     TCU_EP_TYPE_SEND};
                    next_ctrl_rm_state = S_CTRL_RM_CREATE_REPLYEP2;
                end else begin
                    next_ctrl_rm_state = S_CTRL_RM_READ_SEP1;
                end
            end

            S_CTRL_RM_CREATE_REPLYEP2: begin
                if (!rm_reg_stall_i) begin
                    rin_reg_wben = {(TCU_PEID_SIZE+TCU_EP_SIZE){1'b1}};
                    rin_reg_addr = r_reg_addr + 'd8;
                    rin_reg_wdata = {hd_sendchip, hd_sendpe, hd_recvep};
                    next_ctrl_rm_state = S_CTRL_RM_CREATE_REPLYEP3;
                end
            end

            S_CTRL_RM_CREATE_REPLYEP3: begin
                if (!rm_reg_stall_i) begin
                    rin_reg_wben = {32{1'b1}};
                    rin_reg_addr = r_reg_addr + 'd8;
                    rin_reg_wdata = hd_replylabel;
                    next_ctrl_rm_state = S_CTRL_RM_CREATE_REPLYEP4;
                end
            end

            S_CTRL_RM_CREATE_REPLYEP4: begin
                if (!rm_reg_stall_i) begin
                    if (TCU_ENABLE_VIRT_PES && tcu_features_virt_pes_i) begin
                        next_ctrl_rm_state = S_CTRL_RM_CHECK_VPE;
                    end
                    else if (TCU_ENABLE_DRAM) begin
                        next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                    end else begin
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
            end



            S_CTRL_RM_READ_SEP1: begin
                if (!rm_reg_stall_i) begin

                    if (((hd_flags & TCU_HD_FLAG_REPLY) != {TCU_HD_FLAG_SIZE{1'b0}}) && (hd_recvep != {TCU_EP_SIZE{1'b1}})) begin
                        rin_reg_addr = hdrecvep_addr;
                        next_ctrl_rm_state = S_CTRL_RM_READ_SEP2;
                    end
                    else if (TCU_ENABLE_VIRT_PES && tcu_features_virt_pes_i) begin
                        next_ctrl_rm_state = S_CTRL_RM_CHECK_VPE;
                    end
                    else if (TCU_ENABLE_DRAM) begin
                        next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                    end
                    else begin
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
            end

            S_CTRL_RM_READ_SEP2: begin

                if (!rm_reg_stall_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_READ_SEP3;
                end
            end

            S_CTRL_RM_READ_SEP3: begin
                rin_sep_0 = rm_reg_rdata_i;
                next_ctrl_rm_state = S_CTRL_RM_UPDATE_SEP1;
            end

            S_CTRL_RM_UPDATE_SEP1: begin
                rin_reg_wben = {{(TCU_REG_DATA_SIZE-TCU_CRD_SIZE){1'b0}}, {TCU_CRD_SIZE{1'b1}}} << (TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE);
                rin_reg_addr = hdrecvep_addr;
                rin_reg_wdata = sep_curcrd_incr << (TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE);
                next_ctrl_rm_state = S_CTRL_RM_UPDATE_SEP2;
            end

            S_CTRL_RM_UPDATE_SEP2: begin
                if (!rm_reg_stall_i) begin
                    if (TCU_ENABLE_VIRT_PES && tcu_features_virt_pes_i) begin
                        next_ctrl_rm_state = S_CTRL_RM_CHECK_VPE;
                    end
                    else if (TCU_ENABLE_DRAM) begin
                        next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                    end
                    else begin
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
            end



            S_CTRL_RM_CHECK_VPE: begin
                if (TCU_ENABLE_VIRT_PES) begin
                    if (rep_vpeid == rm_cur_vpe_i[TCU_VPEID_SIZE-1:0]) begin

                        rin_reg_wben = {{(TCU_REG_DATA_SIZE-TCU_VPE_MSGS_SIZE){1'b0}}, {TCU_VPE_MSGS_SIZE{1'b1}}} << TCU_VPEID_SIZE;
                        rin_reg_addr = TCU_REGADDR_CUR_VPE;
                        rin_reg_wdata = cur_vpe_msgs_incr << TCU_VPEID_SIZE;
                        next_ctrl_rm_state = S_CTRL_RM_UPDATE_VPE;
                    end


                    else begin
                        rm_core_req_push_o = 1'b1;
                        rm_core_req_data_o = {rep_vpeid, r_recvep};

                        if (!rm_core_req_stall_i) begin
                            if (TCU_ENABLE_DRAM) begin
                                next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                            end else begin
                                next_ctrl_rm_state = S_CTRL_RM_FINISH;
                            end
                        end
                    end
                end
            end

            S_CTRL_RM_UPDATE_VPE: begin
                if (TCU_ENABLE_VIRT_PES) begin
                    if (!rm_reg_stall_i) begin
                        if (TCU_ENABLE_DRAM) begin
                            next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                        end else begin
                            next_ctrl_rm_state = S_CTRL_RM_FINISH;
                        end
                    end
                end
            end



            S_CTRL_RM_WAIT_DRAM: begin
                if (!rm_mem_wdata_infifo_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_FINISH;
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end



            S_CTRL_RM_ERROR: begin
                if (!noc_stall_i && !rm_mem_stall_i) begin
                    rm_done_o = 1'b1;
                    next_ctrl_rm_state = S_CTRL_RM_IDLE;
                end
            end


            S_CTRL_RM_FINISH: begin
                if (!noc_stall_i && !rm_mem_stall_i) begin
                    rm_done_o = 1'b1;
                    next_ctrl_rm_state = S_CTRL_RM_IDLE;
                end


                else if (rm_mem_stall_i && (TIMEOUT_RECV_CYCLES != 32'h0)) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end

            default: next_ctrl_rm_state = S_CTRL_RM_IDLE;

        endcase
    end







    always @* begin
        rm_reg_en_o = 1'b0;
        rm_reg_wben_o = {TCU_REG_DATA_SIZE{1'b0}};

        if (!rm_reg_stall_i) begin
            if ((ctrl_rm_state == S_CTRL_RM_READ_EP1) ||
                (ctrl_rm_state == S_CTRL_RM_READ_EP2) ||
                (ctrl_rm_state == S_CTRL_RM_READ_EP3) ||
                (ctrl_rm_state == S_CTRL_RM_READ_SEP2)) begin
                rm_reg_en_o = 1'b1;
            end
            else if ((ctrl_rm_state == S_CTRL_RM_UPDATE_EP3) ||
                     (ctrl_rm_state == S_CTRL_RM_UPDATE_EP4) ||
                     (ctrl_rm_state == S_CTRL_RM_CREATE_REPLYEP2) ||
                     (ctrl_rm_state == S_CTRL_RM_CREATE_REPLYEP3) ||
                     (ctrl_rm_state == S_CTRL_RM_CREATE_REPLYEP4) ||
                     (ctrl_rm_state == S_CTRL_RM_UPDATE_SEP2)) begin
                rm_reg_en_o = 1'b1;
                rm_reg_wben_o = r_reg_wben;
            end
            else if (TCU_ENABLE_VIRT_PES && (ctrl_rm_state == S_CTRL_RM_UPDATE_VPE)) begin
                rm_reg_en_o = 1'b1;
                rm_reg_wben_o = r_reg_wben;
            end
        end
    end





    always @* begin



        rin_mem_en = 3'b000;
        rin_mem_wben = r_mem_wben;

        if (!rm_mem_stall_i) begin


            if (ctrl_rm_state == S_CTRL_RM_WRITE_PREPARE_MEM2) begin
                rin_mem_en = 3'b100;
                rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}};
            end


            else if (noc_wrreq_i && (ctrl_rm_state == S_CTRL_RM_WRITE_MEM_HD)) begin
                rin_mem_en = 3'b001;
                rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}} << r_laddr[3:0];
            end


            else if (noc_wrreq_i && (ctrl_rm_state == S_CTRL_RM_WRITE_MEM_PL1) && !rm_mem_wabort_o) begin
                if (r_laddr[3:0] == 4'h0) begin
                    rin_mem_en = 3'b001;
                end else begin
                    rin_mem_en = 3'b010;
                end

                if (noc_burst_i) begin
                    rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}};
                end
                else if (r_size >= 'd16) begin
                    rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}};
                end
                else begin
                    rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}} >> (5'd16 - r_size[3:0]);
                end
            end


            else if (ctrl_rm_state == S_CTRL_RM_WRITE_MEM_PL2) begin
                rin_mem_en = 3'b010;
                rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}} >> (5'd16 - r_size[3:0]);
            end
        end
    end

    assign rm_reg_addr_o = r_reg_addr;
    assign rm_reg_wdata_o = r_reg_wdata;

    assign rm_active_o = (ctrl_rm_state != S_CTRL_RM_IDLE);
    assign rm_cur_vpe_active_o = (ctrl_rm_state == S_CTRL_RM_CHECK_VPE) || (ctrl_rm_state == S_CTRL_RM_UPDATE_VPE);
    assign rm_crd_update_active_o = (ctrl_rm_state == S_CTRL_RM_READ_SEP1) ||
                                    (ctrl_rm_state == S_CTRL_RM_READ_SEP2) ||
                                    (ctrl_rm_state == S_CTRL_RM_READ_SEP3) ||
                                    (ctrl_rm_state == S_CTRL_RM_UPDATE_SEP1) ||
                                    (ctrl_rm_state == S_CTRL_RM_UPDATE_SEP2);


    assign rm_mem_en_o = r_mem_en;
    assign rm_mem_wben_o = r_mem_wben;
    assign rm_mem_addr_o = r_mem_addr;
    assign rm_mem_wdata_o = r_size;


    assign noc_wrreq_o = rm_done_o;
    assign noc_chipid_o = hd_sendchip;
    assign noc_modid_o = hd_sendpe;
    assign noc_addr_o = hd_label;
    assign noc_data_o = r_rm_error;

    generate
    assign tcu_log_rm_o = TCU_ENABLE_LOG ?
                            (rm_done_o ? {set_bit_wpos, rep_unread, rep_occupied, TCU_LOG_RECV_FINISH} : TCU_LOG_NONE) :
                            TCU_LOG_NONE;
    endgenerate


endmodule
module tcu_ctrl_recv_msg #(
    `include "noc_parameter.vh"
    ,`include "tcu_parameter.vh"
    ,parameter TCU_ENABLE_VIRT_PES       = 0,
    parameter TCU_ENABLE_DRAM            = 0,
    parameter TCU_ENABLE_LOG             = 0,
    parameter [31:0] TIMEOUT_RECV_CYCLES = 0
)(
    input  wire                                clk_i,
    input  wire                                reset_n_i,



    output reg                                 rm_reg_en_o,
    output reg         [TCU_REG_DATA_SIZE-1:0] rm_reg_wben_o,
    output wire        [TCU_REG_ADDR_SIZE-1:0] rm_reg_addr_o,
    output wire        [TCU_REG_DATA_SIZE-1:0] rm_reg_wdata_o,
    input  wire        [TCU_REG_DATA_SIZE-1:0] rm_reg_rdata_i,
    input  wire                                rm_reg_stall_i,



    output wire                          [2:0] rm_mem_en_o,
    output wire        [TCU_MEM_BSEL_SIZE-1:0] rm_mem_wben_o,
    output wire        [TCU_MEM_ADDR_SIZE-1:0] rm_mem_addr_o,
    output wire        [TCU_MEM_DATA_SIZE-1:0] rm_mem_wdata_o,
    input  wire                                rm_mem_wdata_infifo_i,
    output reg                                 rm_mem_wabort_o,
    input  wire                                rm_mem_stall_i,



    output reg                                 noc_fifo_pop_o,
    input  wire                                noc_wrreq_i,
    input  wire                                noc_burst_i,
    input  wire            [NOC_BSEL_SIZE-1:0] noc_bsel_i,
    input  wire                                noc_stall_i,
    output wire                                noc_wrreq_o,
    output wire            [NOC_DATA_SIZE-1:0] noc_data_o,
    output wire            [NOC_ADDR_SIZE-1:0] noc_addr_o,
    output wire          [NOC_CHIPID_SIZE-1:0] noc_chipid_o,
    output wire           [NOC_MODID_SIZE-1:0] noc_modid_o,



    input  wire                                rm_start_i,
    input  wire              [TCU_EP_SIZE-1:0] rm_recvep_i,
    input  wire                        [127:0] rm_header_i,
    input  wire                         [31:0] rm_cur_vpe_i,
    output wire                                rm_active_o,
    output wire                                rm_cur_vpe_active_o,
    output wire                                rm_crd_update_active_o,
    output reg                                 rm_done_o,



    output reg                                 rm_core_req_push_o,
    output reg  [TCU_CORE_REQ_FORMSG_SIZE-1:0] rm_core_req_data_o,
    input  wire                                rm_core_req_stall_i,



    output wire        [TCU_LOG_DATA_SIZE-1:0] tcu_log_rm_o,



    input  wire                                tcu_features_virt_pes_i,



    input  wire          [NOC_CHIPID_SIZE-1:0] home_chipid_i
);


    `include "tcu_functions.v"


    localparam CTRL_RM_STATES_SIZE          = 5;
    localparam S_CTRL_RM_IDLE               = 5'h00;
    localparam S_CTRL_RM_READ_EP1           = 5'h01;
    localparam S_CTRL_RM_READ_EP2           = 5'h02;
    localparam S_CTRL_RM_READ_EP3           = 5'h03;
    localparam S_CTRL_RM_READ_EP4           = 5'h04;
    localparam S_CTRL_RM_TAKE_HD            = 5'h05;
    localparam S_CTRL_RM_CHECK_EP           = 5'h06;
    localparam S_CTRL_RM_FIND_SLOT          = 5'h07;
    localparam S_CTRL_RM_WRITE_PREPARE_MEM1 = 6'h08;
    localparam S_CTRL_RM_WRITE_PREPARE_MEM2 = 6'h09;
    localparam S_CTRL_RM_WRITE_MEM_HD       = 5'h0A;
    localparam S_CTRL_RM_WRITE_MEM_PL1      = 5'h0B;
    localparam S_CTRL_RM_WRITE_MEM_PL2      = 5'h0C;
    localparam S_CTRL_RM_UPDATE_EP3         = 5'h0D;
    localparam S_CTRL_RM_UPDATE_EP4         = 5'h0E;
    localparam S_CTRL_RM_CREATE_REPLYEP1    = 5'h0F;
    localparam S_CTRL_RM_CREATE_REPLYEP2    = 5'h10;
    localparam S_CTRL_RM_CREATE_REPLYEP3    = 5'h11;
    localparam S_CTRL_RM_CREATE_REPLYEP4    = 5'h12;
    localparam S_CTRL_RM_READ_SEP1          = 5'h13;
    localparam S_CTRL_RM_READ_SEP2          = 5'h14;
    localparam S_CTRL_RM_READ_SEP3          = 5'h15;
    localparam S_CTRL_RM_UPDATE_SEP1        = 5'h16;
    localparam S_CTRL_RM_UPDATE_SEP2        = 5'h17;
    localparam S_CTRL_RM_CHECK_VPE          = 5'h18;
    localparam S_CTRL_RM_UPDATE_VPE         = 5'h19;
    localparam S_CTRL_RM_WAIT_DRAM          = 5'h1A;
    localparam S_CTRL_RM_ERROR              = 5'h1B;
    localparam S_CTRL_RM_FINISH             = 5'h1F;

    reg [CTRL_RM_STATES_SIZE-1:0] ctrl_rm_state, next_ctrl_rm_state;




    reg [63:0] r_rep_0, rin_rep_0;
    reg [63:0] r_rep_1, rin_rep_1;
    reg [63:0] r_rep_2, rin_rep_2;

    reg [63:0] r_sep_0, rin_sep_0;


    reg [63:0] r_hd_0, rin_hd_0;
    reg [63:0] r_hd_1, rin_hd_1;


    reg [31:0] r_laddr, rin_laddr;
    reg [15:0] r_size, rin_size;

    reg                   [2:0] r_mem_en, rin_mem_en;
    reg [TCU_MEM_BSEL_SIZE-1:0] r_mem_wben, rin_mem_wben;
    reg [TCU_MEM_ADDR_SIZE-1:0] r_mem_addr;

    reg [TCU_REG_DATA_SIZE-1:0] r_reg_wben, rin_reg_wben;
    reg [TCU_REG_ADDR_SIZE-1:0] r_reg_addr, rin_reg_addr;
    reg [TCU_REG_DATA_SIZE-1:0] r_reg_wdata, rin_reg_wdata;


    reg r_rm_reg_rdata_avail, rin_rm_reg_rdata_avail;


    reg [TCU_ERROR_SIZE-1:0] r_rm_error, rin_rm_error;


    reg [TCU_EP_SIZE-1:0] r_recvep, rin_recvep;
    reg [31:0] r_recvep_baseaddr, rin_recvep_baseaddr;


    reg [TCU_SLOT_SIZE-1:0] r_tmp_wpos, rin_tmp_wpos;


    reg [31:0] r_rm_timeout, rin_rm_timeout;



    wire [TCU_EP_TYPE_SIZE-1:0] rep_type     = r_rep_0[TCU_EP_TYPE_SIZE-1 : 0];
    wire   [TCU_VPEID_SIZE-1:0] rep_vpeid    = r_rep_0[TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_EP_TYPE_SIZE];
    wire      [TCU_EP_SIZE-1:0] rep_rpleps   = r_rep_0[TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire    [TCU_SLOT_SIZE-1:0] rep_slots    = r_rep_0[TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire    [TCU_SLOT_SIZE-1:0] rep_slotsize = r_rep_0[2*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire    [TCU_SLOT_SIZE-1:0] rep_wpos     = r_rep_0[3*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : 2*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire    [TCU_SLOT_SIZE-1:0] rep_rpos     = r_rep_0[4*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : 3*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire                 [63:0] rep_buffer   = r_rep_1;
    wire                 [31:0] rep_occupied = r_rep_2[31:0];
    wire                 [31:0] rep_unread   = r_rep_2[63:32];

    wire      [TCU_CRD_SIZE-1:0] sep_curcrd      = r_sep_0[TCU_CRD_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE-1 : TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE];
    wire [TCU_REG_DATA_SIZE-1:0] sep_curcrd_incr = sep_curcrd + 'd1;



    wire [TCU_HD_FLAG_SIZE-1:0] hd_flags      = r_hd_0[TCU_HD_FLAG_SIZE-1 : 0];
    wire   [TCU_RSIZE_SIZE-1:0] hd_replysize  = r_hd_0[TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE-1 : TCU_HD_FLAG_SIZE];
    wire    [TCU_PEID_SIZE-1:0] hd_sendpe     = r_hd_0[TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE-1 : TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE];
    wire  [TCU_CHIPID_SIZE-1:0] hd_sendchip   = r_hd_0[TCU_CHIPID_SIZE+TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE-1 : TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE];
    wire  [TCU_MSGLEN_SIZE-1:0] hd_length     = r_hd_0[TCU_MSGLEN_SIZE+TCU_CHIPID_SIZE+TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE-1 : TCU_CHIPID_SIZE+TCU_PEID_SIZE+TCU_RSIZE_SIZE+TCU_HD_FLAG_SIZE];
    wire      [TCU_EP_SIZE-1:0] hd_sendep     = r_hd_0[TCU_EP_SIZE+32-1 : 32];
    wire      [TCU_EP_SIZE-1:0] hd_recvep     = r_hd_0[2*TCU_EP_SIZE+32-1 : TCU_EP_SIZE+32];
    wire                 [31:0] hd_replylabel = r_hd_1[31:0];
    wire                 [31:0] hd_label      = r_hd_1[63:32];



    wire [31:0] recvep_addr   = TCU_REGADDR_EP_START + rm_recvep_i*TCU_EP_REG_SIZE;
    wire [31:0] hdrecvep_addr = TCU_REGADDR_EP_START + hd_recvep*TCU_EP_REG_SIZE;
    wire [31:0] rplep_addr    = TCU_REGADDR_EP_START + (rep_rpleps+r_tmp_wpos)*TCU_EP_REG_SIZE;

    wire     [TCU_SLOT_SIZE-1:0] tmp_pos_incr = r_tmp_wpos + 1'b1;
    wire [TCU_REG_DATA_SIZE-1:0] set_bit_wpos = 32'h1 << r_tmp_wpos;


    wire [TCU_SLOT_SIZE-1:0] max_slot = (rep_slots > 'h5) ? 'd32 : {{(TCU_SLOT_SIZE-1){1'b0}}, 1'b1} << rep_slots[2:0];


    wire [4:0] wben_count_ones = count_ones8(rin_mem_wben[7:0]) + count_ones8(rin_mem_wben[15:8]);


    wire [TCU_REG_DATA_SIZE-1:0] cur_vpe_msgs_incr = rm_cur_vpe_i[TCU_VPE_MSGS_SIZE+TCU_VPEID_SIZE-1:TCU_VPEID_SIZE] + 'd1;


    wire [TCU_SLOT_SIZE-1:0] reply_msg_sz = hd_replysize;



    always @(posedge clk_i) begin
        if (reset_n_i == 1'b0) begin
            ctrl_rm_state <= S_CTRL_RM_IDLE;

            r_laddr <= 32'h0;
            r_size <= 16'h0;

            r_rm_reg_rdata_avail <= 1'b0;
            r_rm_error <= TCU_ERROR_NONE;

            r_mem_en <= 3'h0;
            r_mem_wben <= {TCU_MEM_BSEL_SIZE{1'b0}};
            r_mem_addr <= {TCU_MEM_ADDR_SIZE{1'b0}};

            r_reg_wben <= {TCU_REG_DATA_SIZE{1'b0}};
            r_reg_addr <= {TCU_REG_ADDR_SIZE{1'b0}};
            r_reg_wdata <= {TCU_REG_DATA_SIZE{1'b0}};

            r_recvep <= {TCU_EP_SIZE{1'b0}};
            r_recvep_baseaddr <= 32'h0;

            r_hd_0 <= 64'h0;
            r_hd_1 <= 64'h0;

            r_rep_0 <= 64'h0;
            r_rep_1 <= 64'h0;
            r_rep_2 <= 64'h0;

            r_sep_0 <= 64'h0;

            r_tmp_wpos <= {TCU_SLOT_SIZE{1'b0}};

            r_rm_timeout <= 32'h0;
        end
        else begin
            ctrl_rm_state <= next_ctrl_rm_state;
            
            r_laddr <= rin_laddr;
            r_size <= rin_size;

            r_rm_reg_rdata_avail <= rin_rm_reg_rdata_avail;
            r_rm_error <= rin_rm_error;

            r_mem_en <= rin_mem_en;
            r_mem_wben <= rin_mem_wben;
            r_mem_addr <= r_laddr;

            r_reg_wben <= rin_reg_wben;
            r_reg_addr <= rin_reg_addr;
            r_reg_wdata <= rin_reg_wdata;

            r_recvep <= rin_recvep;
            r_recvep_baseaddr <= rin_recvep_baseaddr;

            r_hd_0 <= rin_hd_0;
            r_hd_1 <= rin_hd_1;
            
            r_rep_0 <= rin_rep_0;
            r_rep_1 <= rin_rep_1;
            r_rep_2 <= rin_rep_2;

            r_sep_0 <= rin_sep_0;

            r_tmp_wpos <= rin_tmp_wpos;

            r_rm_timeout <= rin_rm_timeout;
        end
    end






    always @* begin
        next_ctrl_rm_state = ctrl_rm_state;

        rin_laddr = r_laddr;
        rin_size = r_size;

        noc_fifo_pop_o = 1'b0;

        rin_rm_reg_rdata_avail = 1'b0;
        rin_rm_error = r_rm_error;

        rm_done_o = 1'b0;

        rin_tmp_wpos = r_tmp_wpos;

        rin_recvep = r_recvep;
        rin_recvep_baseaddr = r_recvep_baseaddr;

        rin_reg_wben = r_reg_wben;
        rin_reg_addr = r_reg_addr;
        rin_reg_wdata = r_reg_wdata;

        rin_hd_0 = r_hd_0;
        rin_hd_1 = r_hd_1;
            
        rin_rep_0 = r_rep_0;
        rin_rep_1 = r_rep_1;
        rin_rep_2 = r_rep_2;

        rin_sep_0 = r_sep_0;

        rm_core_req_push_o = 1'b0;
        rm_core_req_data_o = {TCU_CORE_REQ_FORMSG_SIZE{1'b0}};

        rin_rm_timeout = 32'h0;

        rm_mem_wabort_o = 1'b0;


        case (ctrl_rm_state)



            S_CTRL_RM_IDLE: begin
                if (rm_start_i) begin

                    rin_recvep = rm_recvep_i;
                    rin_recvep_baseaddr = recvep_addr;
                    rin_reg_addr = recvep_addr;

                    next_ctrl_rm_state = S_CTRL_RM_READ_EP1;
                    rin_rm_error = TCU_ERROR_NONE;
                end
            end



            S_CTRL_RM_READ_EP1: begin
                if (!rm_reg_stall_i) begin
                    rin_reg_addr = r_reg_addr + 'h8;
                    rin_rm_reg_rdata_avail = 1'b1;
                    next_ctrl_rm_state = S_CTRL_RM_READ_EP2;
                end
            end

            S_CTRL_RM_READ_EP2: begin
                if (r_rm_reg_rdata_avail) begin
                    rin_rep_0 = rm_reg_rdata_i;
                end

                if (!rm_reg_stall_i) begin
                    rin_reg_addr = r_reg_addr + 'h8;
                    rin_rm_reg_rdata_avail = 1'b1;
                    next_ctrl_rm_state = S_CTRL_RM_READ_EP3;
                end
            end

            S_CTRL_RM_READ_EP3: begin


                rin_tmp_wpos = rep_wpos;

                if (r_rm_reg_rdata_avail) begin
                    rin_rep_1 = rm_reg_rdata_i;
                end

                if (!rm_reg_stall_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_READ_EP4;
                end
            end

            S_CTRL_RM_READ_EP4: begin

                rin_rep_2 = rm_reg_rdata_i;
                next_ctrl_rm_state = S_CTRL_RM_TAKE_HD;
            end


            S_CTRL_RM_TAKE_HD: begin
                if (noc_wrreq_i) begin

                    rin_hd_0 = rm_header_i[63:0];
                    rin_hd_1 = rm_header_i[127:64];
                    next_ctrl_rm_state = S_CTRL_RM_CHECK_EP;
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rin_rm_error = TCU_ERROR_TIMEOUT_NOC;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end



            S_CTRL_RM_CHECK_EP: begin

                if (rep_type == TCU_EP_TYPE_RECEIVE) begin


                    if ((hd_length+TCU_HD_REG_SIZE) <= (32'h1 << rep_slotsize)) begin


                        if ((rep_rpleps == {TCU_EP_SIZE{1'b1}}) ||
                            ((rep_rpleps + (32'h1 << rep_slots)) <= TCU_EP_REG_COUNT)) begin
                            next_ctrl_rm_state = S_CTRL_RM_FIND_SLOT;
                        end
                        else begin
                            rin_rm_error = TCU_ERROR_RECV_INV_RPL_EPS;
                            next_ctrl_rm_state = S_CTRL_RM_FINISH;
                        end
                    end
                    else begin
                        rin_rm_error = TCU_ERROR_RECV_OUT_OF_BOUNDS;
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
                else begin
                    rin_rm_error = TCU_ERROR_RECV_GONE;
                    next_ctrl_rm_state = S_CTRL_RM_FINISH;
                end
            end



            S_CTRL_RM_FIND_SLOT: begin

                if (r_tmp_wpos < max_slot) begin
                    if (!rep_occupied[r_tmp_wpos]) begin
                        rin_tmp_wpos = r_tmp_wpos;


                        rin_laddr = rep_buffer[31:0] + (r_tmp_wpos<<rep_slotsize);
                        rin_size = hd_length + TCU_HD_REG_SIZE;

                        next_ctrl_rm_state = S_CTRL_RM_WRITE_PREPARE_MEM1;
                    end


                    else if (tmp_pos_incr != rep_wpos) begin
                        rin_tmp_wpos = tmp_pos_incr;
                        next_ctrl_rm_state = S_CTRL_RM_FIND_SLOT;
                    end


                    else begin
                        rin_rm_error = TCU_ERROR_RECV_NO_SPACE;
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
                else begin

                    rin_tmp_wpos = 'h0;
                    next_ctrl_rm_state = S_CTRL_RM_FIND_SLOT;
                end
            end



            S_CTRL_RM_WRITE_PREPARE_MEM1: begin
                if (noc_wrreq_i) begin

                    rin_reg_wben = {{{TCU_REG_DATA_SIZE-TCU_SLOT_SIZE}{1'b0}}, {TCU_SLOT_SIZE{1'b1}}} << (2*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE);
                    rin_reg_addr = r_recvep_baseaddr;
                    rin_reg_wdata = {{(TCU_REG_DATA_SIZE-TCU_SLOT_SIZE){1'b0}}, tmp_pos_incr} << (2*TCU_SLOT_SIZE+TCU_EP_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE);


                    if (TCU_ENABLE_DRAM && noc_burst_i && (r_size > 'd16)) begin
                        next_ctrl_rm_state = S_CTRL_RM_WRITE_PREPARE_MEM2;
                    end


                    else begin
                        next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_HD;
                    end
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rin_rm_error = TCU_ERROR_TIMEOUT_NOC;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end


            S_CTRL_RM_WRITE_PREPARE_MEM2: begin
                if (!rm_mem_stall_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_HD;
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end




            S_CTRL_RM_WRITE_MEM_HD: begin
                if (noc_wrreq_i) begin
                    if (!rm_mem_stall_i) begin
                        noc_fifo_pop_o = 1'b1;


                        if (noc_bsel_i == {NOC_BSEL_SIZE{1'b0}}) begin
                            rm_mem_wabort_o = 1'b1;
                            rin_rm_error = TCU_ERROR_ABORT;
                            next_ctrl_rm_state = S_CTRL_RM_FINISH;
                        end
                        else begin
                            rin_laddr = r_laddr + 'd16;
                            rin_size = r_size - (5'd16 - r_laddr[3:0]);


                            if (noc_burst_i) begin
                                next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_PL1;
                            end



                            else if (rin_size > 'd0) begin
                                next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_PL2;
                            end


                            else begin
                                next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP3;
                            end
                        end
                    end


                    else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                        rin_rm_timeout = r_rm_timeout + 32'd1;
                        if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                            rm_mem_wabort_o = 1'b1;
                            rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                            next_ctrl_rm_state = S_CTRL_RM_ERROR;
                        end
                    end
                end
            end


            S_CTRL_RM_WRITE_MEM_PL1: begin
                if (noc_wrreq_i && !rm_mem_stall_i) begin
                    noc_fifo_pop_o = 1'b1;


                    if (noc_bsel_i == {NOC_BSEL_SIZE{1'b0}}) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_ABORT;
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                    else begin
                        rin_size = r_size - wben_count_ones;
                        rin_laddr = r_laddr + 'd16;


                        if (noc_burst_i) begin

                            if (r_size > 'd16) begin
                                next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_PL1;
                            end
                            else begin
                                rin_rm_error = TCU_ERROR_CRITICAL;
                                next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP3;
                            end
                        end


                        else begin


                            if (r_size > 'd16) begin
                                next_ctrl_rm_state = S_CTRL_RM_WRITE_MEM_PL2;
                            end


                            else begin
                                rin_size = 'd0;
                                next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP3;
                            end
                        end
                    end
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = noc_wrreq_i ? TCU_ERROR_TIMEOUT_MEM : TCU_ERROR_TIMEOUT_NOC;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end


            S_CTRL_RM_WRITE_MEM_PL2: begin
                if (!rm_mem_stall_i) begin
                    rin_size = 'd0;
                    next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP3;
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end




            S_CTRL_RM_UPDATE_EP3: begin
                if (!rm_reg_stall_i) begin
                    rin_reg_wben = (set_bit_wpos<<32) | set_bit_wpos;
                    rin_reg_addr = r_recvep_baseaddr + 'h10;
                    rin_reg_wdata = (set_bit_wpos<<32) | set_bit_wpos;
                    next_ctrl_rm_state = S_CTRL_RM_UPDATE_EP4;
                end
            end

            S_CTRL_RM_UPDATE_EP4: begin

                if (!rm_reg_stall_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_CREATE_REPLYEP1;
                end
            end




            S_CTRL_RM_CREATE_REPLYEP1: begin

                if (((hd_flags & TCU_HD_FLAG_REPLY) == {TCU_HD_FLAG_SIZE{1'b0}}) &&
                    (rep_rpleps != {TCU_EP_SIZE{1'b1}}) &&
                    (hd_recvep != {TCU_EP_SIZE{1'b1}})) begin
                    rin_reg_wben = {(1+TCU_EP_SIZE+TCU_SLOT_SIZE+2*TCU_CRD_SIZE+TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE){1'b1}};
                    rin_reg_addr = rplep_addr;
                    rin_reg_wdata = {1'b1,
                                     hd_sendep,
                                     reply_msg_sz,
                                     {{(TCU_CRD_SIZE-1){1'b0}}, 1'b1},
                                     {{(TCU_CRD_SIZE-1){1'b0}}, 1'b1},
                                     rep_vpeid,
                                     TCU_EP_TYPE_SEND};
                    next_ctrl_rm_state = S_CTRL_RM_CREATE_REPLYEP2;
                end else begin
                    next_ctrl_rm_state = S_CTRL_RM_READ_SEP1;
                end
            end

            S_CTRL_RM_CREATE_REPLYEP2: begin
                if (!rm_reg_stall_i) begin
                    rin_reg_wben = {(TCU_PEID_SIZE+TCU_EP_SIZE){1'b1}};
                    rin_reg_addr = r_reg_addr + 'd8;
                    rin_reg_wdata = {hd_sendchip, hd_sendpe, hd_recvep};
                    next_ctrl_rm_state = S_CTRL_RM_CREATE_REPLYEP3;
                end
            end

            S_CTRL_RM_CREATE_REPLYEP3: begin
                if (!rm_reg_stall_i) begin
                    rin_reg_wben = {32{1'b1}};
                    rin_reg_addr = r_reg_addr + 'd8;
                    rin_reg_wdata = hd_replylabel;
                    next_ctrl_rm_state = S_CTRL_RM_CREATE_REPLYEP4;
                end
            end

            S_CTRL_RM_CREATE_REPLYEP4: begin
                if (!rm_reg_stall_i) begin
                    if (TCU_ENABLE_VIRT_PES && tcu_features_virt_pes_i) begin
                        next_ctrl_rm_state = S_CTRL_RM_CHECK_VPE;
                    end
                    else if (TCU_ENABLE_DRAM) begin
                        next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                    end else begin
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
            end



            S_CTRL_RM_READ_SEP1: begin
                if (!rm_reg_stall_i) begin

                    if (((hd_flags & TCU_HD_FLAG_REPLY) != {TCU_HD_FLAG_SIZE{1'b0}}) && (hd_recvep != {TCU_EP_SIZE{1'b1}})) begin
                        rin_reg_addr = hdrecvep_addr;
                        next_ctrl_rm_state = S_CTRL_RM_READ_SEP2;
                    end
                    else if (TCU_ENABLE_VIRT_PES && tcu_features_virt_pes_i) begin
                        next_ctrl_rm_state = S_CTRL_RM_CHECK_VPE;
                    end
                    else if (TCU_ENABLE_DRAM) begin
                        next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                    end
                    else begin
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
            end

            S_CTRL_RM_READ_SEP2: begin

                if (!rm_reg_stall_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_READ_SEP3;
                end
            end

            S_CTRL_RM_READ_SEP3: begin
                rin_sep_0 = rm_reg_rdata_i;
                next_ctrl_rm_state = S_CTRL_RM_UPDATE_SEP1;
            end

            S_CTRL_RM_UPDATE_SEP1: begin
                rin_reg_wben = {{(TCU_REG_DATA_SIZE-TCU_CRD_SIZE){1'b0}}, {TCU_CRD_SIZE{1'b1}}} << (TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE);
                rin_reg_addr = hdrecvep_addr;
                rin_reg_wdata = sep_curcrd_incr << (TCU_VPEID_SIZE+TCU_EP_TYPE_SIZE);
                next_ctrl_rm_state = S_CTRL_RM_UPDATE_SEP2;
            end

            S_CTRL_RM_UPDATE_SEP2: begin
                if (!rm_reg_stall_i) begin
                    if (TCU_ENABLE_VIRT_PES && tcu_features_virt_pes_i) begin
                        next_ctrl_rm_state = S_CTRL_RM_CHECK_VPE;
                    end
                    else if (TCU_ENABLE_DRAM) begin
                        next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                    end
                    else begin
                        next_ctrl_rm_state = S_CTRL_RM_FINISH;
                    end
                end
            end



            S_CTRL_RM_CHECK_VPE: begin
                if (TCU_ENABLE_VIRT_PES) begin
                    if (rep_vpeid == rm_cur_vpe_i[TCU_VPEID_SIZE-1:0]) begin

                        rin_reg_wben = {{(TCU_REG_DATA_SIZE-TCU_VPE_MSGS_SIZE){1'b0}}, {TCU_VPE_MSGS_SIZE{1'b1}}} << TCU_VPEID_SIZE;
                        rin_reg_addr = TCU_REGADDR_CUR_VPE;
                        rin_reg_wdata = cur_vpe_msgs_incr << TCU_VPEID_SIZE;
                        next_ctrl_rm_state = S_CTRL_RM_UPDATE_VPE;
                    end


                    else begin
                        rm_core_req_push_o = 1'b1;
                        rm_core_req_data_o = {rep_vpeid, r_recvep};

                        if (!rm_core_req_stall_i) begin
                            if (TCU_ENABLE_DRAM) begin
                                next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                            end else begin
                                next_ctrl_rm_state = S_CTRL_RM_FINISH;
                            end
                        end
                    end
                end
            end

            S_CTRL_RM_UPDATE_VPE: begin
                if (TCU_ENABLE_VIRT_PES) begin
                    if (!rm_reg_stall_i) begin
                        if (TCU_ENABLE_DRAM) begin
                            next_ctrl_rm_state = S_CTRL_RM_WAIT_DRAM;
                        end else begin
                            next_ctrl_rm_state = S_CTRL_RM_FINISH;
                        end
                    end
                end
            end



            S_CTRL_RM_WAIT_DRAM: begin
                if (!rm_mem_wdata_infifo_i) begin
                    next_ctrl_rm_state = S_CTRL_RM_FINISH;
                end


                else if (TIMEOUT_RECV_CYCLES != 32'h0) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end



            S_CTRL_RM_ERROR: begin
                if (!noc_stall_i && !rm_mem_stall_i) begin
                    rm_done_o = 1'b1;
                    next_ctrl_rm_state = S_CTRL_RM_IDLE;
                end
            end


            S_CTRL_RM_FINISH: begin
                if (!noc_stall_i && !rm_mem_stall_i) begin
                    rm_done_o = 1'b1;
                    next_ctrl_rm_state = S_CTRL_RM_IDLE;
                end


                else if (rm_mem_stall_i && (TIMEOUT_RECV_CYCLES != 32'h0)) begin
                    rin_rm_timeout = r_rm_timeout + 32'd1;
                    if (r_rm_timeout > TIMEOUT_RECV_CYCLES) begin
                        rm_mem_wabort_o = 1'b1;
                        rin_rm_error = TCU_ERROR_TIMEOUT_MEM;
                        next_ctrl_rm_state = S_CTRL_RM_ERROR;
                    end
                end
            end

            default: next_ctrl_rm_state = S_CTRL_RM_IDLE;

        endcase
    end







    always @* begin
        rm_reg_en_o = 1'b0;
        rm_reg_wben_o = {TCU_REG_DATA_SIZE{1'b0}};

        if (!rm_reg_stall_i) begin
            if ((ctrl_rm_state == S_CTRL_RM_READ_EP1) ||
                (ctrl_rm_state == S_CTRL_RM_READ_EP2) ||
                (ctrl_rm_state == S_CTRL_RM_READ_EP3) ||
                (ctrl_rm_state == S_CTRL_RM_READ_SEP2)) begin
                rm_reg_en_o = 1'b1;
            end
            else if ((ctrl_rm_state == S_CTRL_RM_UPDATE_EP3) ||
                     (ctrl_rm_state == S_CTRL_RM_UPDATE_EP4) ||
                     (ctrl_rm_state == S_CTRL_RM_CREATE_REPLYEP2) ||
                     (ctrl_rm_state == S_CTRL_RM_CREATE_REPLYEP3) ||
                     (ctrl_rm_state == S_CTRL_RM_CREATE_REPLYEP4) ||
                     (ctrl_rm_state == S_CTRL_RM_UPDATE_SEP2)) begin
                rm_reg_en_o = 1'b1;
                rm_reg_wben_o = r_reg_wben;
            end
            else if (TCU_ENABLE_VIRT_PES && (ctrl_rm_state == S_CTRL_RM_UPDATE_VPE)) begin
                rm_reg_en_o = 1'b1;
                rm_reg_wben_o = r_reg_wben;
            end
        end
    end





    always @* begin



        rin_mem_en = 3'b000;
        rin_mem_wben = r_mem_wben;

        if (!rm_mem_stall_i) begin


            if (ctrl_rm_state == S_CTRL_RM_WRITE_PREPARE_MEM2) begin
                rin_mem_en = 3'b100;
                rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}};
            end


            else if (noc_wrreq_i && (ctrl_rm_state == S_CTRL_RM_WRITE_MEM_HD)) begin
                rin_mem_en = 3'b001;
                rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}} << r_laddr[3:0];
            end


            else if (noc_wrreq_i && (ctrl_rm_state == S_CTRL_RM_WRITE_MEM_PL1) && !rm_mem_wabort_o) begin
                if (r_laddr[3:0] == 4'h0) begin
                    rin_mem_en = 3'b001;
                end else begin
                    rin_mem_en = 3'b010;
                end

                if (noc_burst_i) begin
                    rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}};
                end
                else if (r_size >= 'd16) begin
                    rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}};
                end
                else begin
                    rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}} >> (5'd16 - r_size[3:0]);
                end
            end


            else if (ctrl_rm_state == S_CTRL_RM_WRITE_MEM_PL2) begin
                rin_mem_en = 3'b010;
                rin_mem_wben = {TCU_MEM_BSEL_SIZE{1'b1}} >> (5'd16 - r_size[3:0]);
            end
        end
    end

    assign rm_reg_addr_o = r_reg_addr;
    assign rm_reg_wdata_o = r_reg_wdata;

    assign rm_active_o = (ctrl_rm_state != S_CTRL_RM_IDLE);
    assign rm_cur_vpe_active_o = (ctrl_rm_state == S_CTRL_RM_CHECK_VPE) || (ctrl_rm_state == S_CTRL_RM_UPDATE_VPE);
    assign rm_crd_update_active_o = (ctrl_rm_state == S_CTRL_RM_READ_SEP1) ||
                                    (ctrl_rm_state == S_CTRL_RM_READ_SEP2) ||
                                    (ctrl_rm_state == S_CTRL_RM_READ_SEP3) ||
                                    (ctrl_rm_state == S_CTRL_RM_UPDATE_SEP1) ||
                                    (ctrl_rm_state == S_CTRL_RM_UPDATE_SEP2);


    assign rm_mem_en_o = r_mem_en;
    assign rm_mem_wben_o = r_mem_wben;
    assign rm_mem_addr_o = r_mem_addr;
    assign rm_mem_wdata_o = r_size;


    assign noc_wrreq_o = rm_done_o;
    assign noc_chipid_o = hd_sendchip;
    assign noc_modid_o = hd_sendpe;
    assign noc_addr_o = hd_label;
    assign noc_data_o = r_rm_error;

    generate
    assign tcu_log_rm_o = TCU_ENABLE_LOG ?
                            (rm_done_o ? {set_bit_wpos, rep_unread, rep_occupied, TCU_LOG_RECV_FINISH} : TCU_LOG_NONE) :
                            TCU_LOG_NONE;
    endgenerate


endmodule