data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v
1: b'%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.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/noc_arq/source/rtl/verilog,data/full_repos/permissive/463204869/noc_parameter.vh\n             data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog,data/full_repos/permissive/463204869/noc_parameter.vh.v\n             data/full_repos/permissive/463204869/units/noc_arq/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/noc_arq/source/rtl/verilog/noc_arq_tx.v:4: syntax error, unexpected \',\', expecting \'[\'\n    ,parameter ARQ_TX_BUFFER_ADDR_WIDTH = 8\n    ^\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:5: syntax error, unexpected \')\', expecting \';\'\n)(\n^\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:7: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                        reset_q_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:10: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                        mod_wrreq_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:11: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire  [NOC_HEADER_SIZE-1:0] mod_header_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:12: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire [NOC_PAYLOAD_SIZE-1:0] mod_payload_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:13: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                        mod_stall_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:14: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output reg                         noc_wrreq_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:15: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg   [NOC_HEADER_SIZE-1:0] noc_header_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:16: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output reg  [NOC_PAYLOAD_SIZE-1:0] noc_payload_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:17: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  wire                        noc_stall_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:20: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                        ack_wrreq_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:21: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire  [NOC_HEADER_SIZE-1:0] ack_header_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:22: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire [NOC_PAYLOAD_SIZE-1:0] ack_payload_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:23: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                        ack_stall_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:25: syntax error, unexpected input, expecting IDENTIFIER or do or final\n    input  wire                  [1:0] arq_enable_i,\n    ^~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:28: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                 [31:0] arq_tx_bvt_mod_wr_ptr_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:29: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                 [31:0] arq_tx_bvt_ack_wr_ptr_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:30: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                 [31:0] arq_tx_bvt_occ_ptr_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:31: syntax error, unexpected output, expecting IDENTIFIER or do or final\n    output wire                 [31:0] arq_tx_bvt_rd_ptr_o\n    ^~~~~~\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:32: syntax error, unexpected \')\', expecting \',\' or \';\'\n);\n^\n%Error: data/full_repos/permissive/463204869/units/noc_arq/source/rtl/verilog/noc_arq_tx.v:163: syntax error, unexpected IDENTIFIER\n    mem_tp_wrap #(\n    ^~~~~~~~~~~\n%Error: Exiting due to 23 error(s)\n'
module noc_arq_tx #(
    `include "noc_parameter.vh"
    ,parameter ARQ_TX_BUFFER_ADDR_WIDTH = 8
)(
    input  wire                        clk_i,
    input  wire                        reset_q_i,


    input  wire                        mod_wrreq_i,
    input  wire  [NOC_HEADER_SIZE-1:0] mod_header_i,
    input  wire [NOC_PAYLOAD_SIZE-1:0] mod_payload_i,
    output wire                        mod_stall_o,
    output reg                         noc_wrreq_o,
    output reg   [NOC_HEADER_SIZE-1:0] noc_header_o,
    output reg  [NOC_PAYLOAD_SIZE-1:0] noc_payload_o,
    input  wire                        noc_stall_i,


    input  wire                        ack_wrreq_i,
    input  wire  [NOC_HEADER_SIZE-1:0] ack_header_i,
    input  wire [NOC_PAYLOAD_SIZE-1:0] ack_payload_i,
    output wire                        ack_stall_o,

    input  wire                  [1:0] arq_enable_i,


    output wire                 [31:0] arq_tx_bvt_mod_wr_ptr_o,
    output wire                 [31:0] arq_tx_bvt_ack_wr_ptr_o,
    output wire                 [31:0] arq_tx_bvt_occ_ptr_o,
    output wire                 [31:0] arq_tx_bvt_rd_ptr_o
);


    localparam PTR_ADDR_WIDTH = ARQ_TX_BUFFER_ADDR_WIDTH + 1;
    localparam BVT_DATA_SIZE = 2*ARQ_TX_BUFFER_ADDR_WIDTH + NOC_MODID_SIZE + NOC_CHIPID_SIZE + NOC_ADDR_SIZE;
    localparam ARQ_TX_BUFFER_DEPTH = 1 << ARQ_TX_BUFFER_ADDR_WIDTH;
    localparam ACK_FIFO_DATA_SIZE = NOC_MODID_SIZE + NOC_CHIPID_SIZE + NOC_ADDR_SIZE + 1;


    localparam S_TXB_WRITE_FILL_BUF = 1'b0;
    localparam S_TXB_WRITE_SET_BVT  = 1'b1;
    reg txb_write_state, next_txb_write_state;


    localparam S_TXB_READ_IDLE   = 2'h0;
    localparam S_TXB_READ_SEND   = 2'h1;
    localparam S_TXB_READ_RESEND = 2'h2;
    localparam S_TXB_READ_FINISH = 2'h3;
    reg [1:0] txb_read_state, next_txb_read_state;


    localparam S_ACK_IDLE         = 3'h0;
    localparam S_ACK_CHECK        = 3'h1;
    localparam S_ACK_INCR_OCC_PTR = 3'h2;
    localparam S_ACK_UPDATE_BVT   = 3'h3;
    localparam S_ACK_RESEND_START = 3'h4;
    localparam S_ACK_RESEND       = 3'h5;
    reg [2:0] ack_state, next_ack_state;



    reg            [PTR_ADDR_WIDTH-1:0] r_txb_wr_ptr, rin_txb_wr_ptr;
    reg            [PTR_ADDR_WIDTH-1:0] r_txb_occ_ptr, rin_txb_occ_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_txb_mod_rd_ptr, rin_txb_mod_rd_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_txb_resend_rd_ptr, rin_txb_resend_rd_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] txb_rd_ptr;
    reg                                 r_txb_write_active, rin_txb_write_active;

    reg                         r_txb_rdata_fromreg, rin_txb_rdata_fromreg;
    reg                         r_txb_arq_out, rin_txb_arq_out;
    reg   [NOC_HEADER_SIZE-1:0] r_txb_header_out, rin_txb_header_out;
    reg  [NOC_PAYLOAD_SIZE-1:0] r_txb_payload_out, rin_txb_payload_out;

    reg txb_wr_en;
    reg r_txb_rd_en, rin_txb_rd_en;
    reg txb_arq_out;


    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_mod_wr_ptr, rin_bvt_mod_wr_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_ack_wr_ptr, rin_bvt_ack_wr_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_occ_ptr, rin_bvt_occ_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_rd_ptr, rin_bvt_rd_ptr;

    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_wdata_pos, rin_bvt_wdata_pos;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_wdata_length, rin_bvt_wdata_length;
    reg            [NOC_MODID_SIZE-1:0] r_bvt_wdata_modid, rin_bvt_wdata_modid;
    reg           [NOC_CHIPID_SIZE-1:0] r_bvt_wdata_chipid, rin_bvt_wdata_chipid;
    reg             [NOC_ADDR_SIZE-1:0] r_bvt_wdata_addr, rin_bvt_wdata_addr;


    reg [ARQ_TX_BUFFER_DEPTH-1:0] r_bvt_valid_entry, rin_bvt_valid_entry;


    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_resend_pos, rin_resend_pos;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_resend_length, rin_resend_length;


    reg                                 bvt_wr_en;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] bvt_wr_ptr;
    reg             [BVT_DATA_SIZE-1:0] bvt_wdata;
    reg                                 bvt_rd_en;

    wire [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] bvt_rdata_pos;
    wire [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] bvt_rdata_length;
    wire           [NOC_MODID_SIZE-1:0] bvt_rdata_modid;
    wire          [NOC_CHIPID_SIZE-1:0] bvt_rdata_chipid;
    wire            [NOC_ADDR_SIZE-1:0] bvt_rdata_addr;



    reg r_forward, rin_forward;
    reg r_mod_burst;
    reg r_noc_stall;


    wire                       mod_burst = mod_header_i[NOC_HEADER_SIZE-1];
    wire                       mod_arq = mod_header_i[2*NOC_MODID_SIZE+2*NOC_CHIPID_SIZE+NOC_BSEL_SIZE +: NOC_ARQ_SIZE];
    wire  [NOC_MODID_SIZE-1:0] mod_trg_modid = mod_header_i[NOC_MODID_SIZE+NOC_CHIPID_SIZE-1 : NOC_CHIPID_SIZE];
    wire [NOC_CHIPID_SIZE-1:0] mod_trg_chipid = mod_header_i[NOC_CHIPID_SIZE-1:0];
    wire   [NOC_ADDR_SIZE-1:0] mod_addr = mod_payload_i[NOC_ADDR_SIZE+NOC_DATA_SIZE-1 : NOC_DATA_SIZE];


    wire  [NOC_HEADER_SIZE-1:0] txb_header_out;
    wire [NOC_PAYLOAD_SIZE-1:0] txb_payload_out;


    wire txb_full = (r_txb_wr_ptr[ARQ_TX_BUFFER_ADDR_WIDTH-1:0] == r_txb_occ_ptr[ARQ_TX_BUFFER_ADDR_WIDTH-1:0]) &&
                            (r_txb_wr_ptr[ARQ_TX_BUFFER_ADDR_WIDTH] != r_txb_occ_ptr[ARQ_TX_BUFFER_ADDR_WIDTH]);


    wire txb_data_avail = (r_txb_wr_ptr[ARQ_TX_BUFFER_ADDR_WIDTH-1:0] != r_txb_mod_rd_ptr) &&
                            !(r_txb_write_active && (r_txb_mod_rd_ptr == r_bvt_wdata_pos));

    wire txb_read_active = (txb_read_state != S_TXB_READ_IDLE);

    wire [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] resend_end_ptr = r_resend_pos + r_resend_length;

    wire [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] bvt_rd_ptr_decr = r_bvt_rd_ptr - 1;

    wire [ARQ_TX_BUFFER_DEPTH-1:0] ptr_to_bit_mask = 1 << bvt_wr_ptr;


    wire  [NOC_MODID_SIZE-1:0] ack_src_modid = ack_header_i[NOC_MODID_SIZE+2*NOC_CHIPID_SIZE +: NOC_MODID_SIZE];
    wire [NOC_CHIPID_SIZE-1:0] ack_src_chipid = ack_header_i[NOC_MODID_SIZE+NOC_CHIPID_SIZE +: NOC_CHIPID_SIZE];
    wire   [NOC_ADDR_SIZE-1:0] ack_addr = ack_payload_i[NOC_ADDR_SIZE+NOC_DATA_SIZE-1 : NOC_DATA_SIZE];


    wire ack_type = ack_payload_i[0];


    reg                        ack_fifo_pop;
    wire                       ack_fifo_empty;
    wire  [NOC_MODID_SIZE-1:0] ack_fifo_src_modid;
    wire [NOC_CHIPID_SIZE-1:0] ack_fifo_src_chipid;
    wire   [NOC_ADDR_SIZE-1:0] ack_fifo_addr;
    wire                       ack_fifo_type;





    mem_tp_wrap #(
        .MEM_TYPE      ("auto"),
        .MEM_DATAWIDTH (NOC_HEADER_SIZE+NOC_PAYLOAD_SIZE),
        .MEM_ADDRWIDTH (ARQ_TX_BUFFER_ADDR_WIDTH)
    ) arq_tx_buffer (
        .clk     (clk_i),
        .reset   (~reset_q_i),

        .ena     (txb_wr_en),
        .wea     ({((NOC_HEADER_SIZE+NOC_PAYLOAD_SIZE+7)/8){1'b1}}),
        .addra   (r_txb_wr_ptr[ARQ_TX_BUFFER_ADDR_WIDTH-1:0]),
        .dina    ({mod_header_i, mod_payload_i}),

        .enb     (rin_txb_rd_en),
        .addrb   (txb_rd_ptr),
        .doutb   ({txb_header_out, txb_payload_out})
    );



    mem_tp_wrap #(
        .MEM_TYPE      ("auto"),
        .MEM_DATAWIDTH (BVT_DATA_SIZE),
        .MEM_ADDRWIDTH (ARQ_TX_BUFFER_ADDR_WIDTH)
    ) arq_bvt (
        .clk     (clk_i),
        .reset   (~reset_q_i),

        .ena     (bvt_wr_en),
        .wea     ({((BVT_DATA_SIZE+7)/8){1'b1}}),
        .addra   (bvt_wr_ptr),
        .dina    (bvt_wdata),

        .enb     (bvt_rd_en),
        .addrb   (r_bvt_rd_ptr),
        .doutb   ({bvt_rdata_pos, bvt_rdata_length, bvt_rdata_modid, bvt_rdata_chipid, bvt_rdata_addr})
    );



    sync_fifo #(
        .DATA_WIDTH (ACK_FIFO_DATA_SIZE),
        .ADDR_WIDTH (3)
    ) ack_fifo (
        .clk_i		(clk_i),
        .resetn_i	(reset_q_i),

        .wr_en_i	(ack_wrreq_i),
        .wdata_i	({ack_src_modid, ack_src_chipid, ack_addr, ack_type}),
        .wfull_o	(ack_stall_o),

        .rd_en_i	(ack_fifo_pop),
        .rdata_o	({ack_fifo_src_modid, ack_fifo_src_chipid, ack_fifo_addr, ack_fifo_type}),
        .rempty_o	(ack_fifo_empty)
    );



    always @(posedge clk_i or negedge reset_q_i) begin
        if (reset_q_i == 1'b0) begin
            txb_write_state <= S_TXB_WRITE_FILL_BUF;
            txb_read_state <= S_TXB_READ_IDLE;
            ack_state <= S_ACK_IDLE;

            r_txb_wr_ptr <= {PTR_ADDR_WIDTH{1'b0}};
            r_txb_occ_ptr <= {PTR_ADDR_WIDTH{1'b0}};
            r_txb_mod_rd_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_txb_resend_rd_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_txb_rd_en <= 1'b0;
            r_txb_write_active <= 1'b0;

            r_txb_rdata_fromreg <= 1'b0;
            r_txb_arq_out <= 1'b0;
            r_txb_header_out <= {NOC_HEADER_SIZE{1'b0}};
            r_txb_payload_out <= {NOC_PAYLOAD_SIZE{1'b0}};

            r_bvt_mod_wr_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_ack_wr_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_occ_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_rd_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};

            r_bvt_wdata_pos <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_wdata_length <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_wdata_modid <= {NOC_MODID_SIZE{1'b0}};
            r_bvt_wdata_chipid <= {NOC_CHIPID_SIZE{1'b0}};
            r_bvt_wdata_addr <= {NOC_ADDR_SIZE{1'b0}};

            r_bvt_valid_entry <= {ARQ_TX_BUFFER_DEPTH{1'b0}};

            r_resend_pos <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_resend_length <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};

            r_forward <= 1'b0;
            r_mod_burst <= 1'b0;
            r_noc_stall <= 1'b0;
        end
        else begin
            txb_write_state <= next_txb_write_state;
            txb_read_state <= next_txb_read_state;
            ack_state <= next_ack_state;

            r_txb_wr_ptr <= rin_txb_wr_ptr;
            r_txb_mod_rd_ptr <= rin_txb_mod_rd_ptr;
            r_txb_resend_rd_ptr <= rin_txb_resend_rd_ptr;
            r_txb_occ_ptr <= rin_txb_occ_ptr;
            r_txb_rd_en <= rin_txb_rd_en;
            r_txb_write_active <= rin_txb_write_active;

            r_txb_rdata_fromreg <= rin_txb_rdata_fromreg;
            r_txb_arq_out <= rin_txb_arq_out;
            r_txb_header_out <= rin_txb_header_out;
            r_txb_payload_out <= rin_txb_payload_out;

            r_bvt_mod_wr_ptr <= rin_bvt_mod_wr_ptr;
            r_bvt_ack_wr_ptr <= rin_bvt_ack_wr_ptr;
            r_bvt_occ_ptr <= rin_bvt_occ_ptr;
            r_bvt_rd_ptr <= rin_bvt_rd_ptr;

            r_bvt_wdata_pos <= rin_bvt_wdata_pos;
            r_bvt_wdata_length <= rin_bvt_wdata_length;
            r_bvt_wdata_modid <= rin_bvt_wdata_modid;
            r_bvt_wdata_chipid <= rin_bvt_wdata_chipid;
            r_bvt_wdata_addr <= rin_bvt_wdata_addr;

            r_bvt_valid_entry <= rin_bvt_valid_entry;

            r_resend_pos <= rin_resend_pos;
            r_resend_length <= rin_resend_length;

            r_forward <= rin_forward;
            r_mod_burst <= (mod_wrreq_i && !mod_stall_o) ? mod_burst : r_mod_burst;
            r_noc_stall <= noc_stall_i;
        end
    end





    always @* begin
        next_txb_write_state = txb_write_state;

        rin_txb_write_active = r_txb_write_active;

        txb_wr_en = 1'b0;
        rin_txb_wr_ptr = r_txb_wr_ptr;

        rin_bvt_mod_wr_ptr = r_bvt_mod_wr_ptr;

        rin_bvt_wdata_pos = r_bvt_wdata_pos;
        rin_bvt_wdata_length = r_bvt_wdata_length;
        rin_bvt_wdata_modid = r_bvt_wdata_modid;
        rin_bvt_wdata_chipid = r_bvt_wdata_chipid;
        rin_bvt_wdata_addr = r_bvt_wdata_addr;

        case(txb_write_state)
            S_TXB_WRITE_FILL_BUF: begin
                if (mod_wrreq_i && !rin_forward && !txb_full) begin

                    rin_txb_write_active = 1'b1;

                    txb_wr_en = 1'b1;
                    rin_txb_wr_ptr = r_txb_wr_ptr + 1;

                    if (!r_mod_burst) begin

                        rin_bvt_wdata_pos = r_txb_wr_ptr;
                        rin_bvt_wdata_modid = mod_trg_modid;
                        rin_bvt_wdata_chipid = mod_trg_chipid;
                        rin_bvt_wdata_addr = mod_addr;


                        if (mod_burst) begin
                            rin_bvt_wdata_length = mod_payload_i[ARQ_TX_BUFFER_ADDR_WIDTH-1:0] + 1;
                        end


                        else begin
                            rin_bvt_wdata_length = 1;
                        end
                    end


                    if (!mod_burst) begin
                        next_txb_write_state = S_TXB_WRITE_SET_BVT;
                    end
                end
            end

            S_TXB_WRITE_SET_BVT: begin
                rin_txb_write_active = 1'b0;


                if (ack_state != S_ACK_UPDATE_BVT) begin
                    rin_bvt_mod_wr_ptr = r_bvt_mod_wr_ptr + 1;
                    next_txb_write_state = S_TXB_WRITE_FILL_BUF;
                end
            end
        endcase
    end



    always @* begin
        rin_forward = 1'b0;

        if (!r_mod_burst) begin


            case(arq_enable_i)
                NOC_ARQ_ENABLE_OFF: begin
                    rin_forward = 1'b1;
                end
                NOC_ARQ_ENABLE_ON: begin
                    rin_forward = 1'b0;
                end
                default: begin


                    if (mod_arq) begin
                        rin_forward = 1'b0;
                    end else begin
                        rin_forward = 1'b1;
                    end
                end
            endcase
        end


        else if (r_forward) begin
            rin_forward = r_forward;
        end
    end



    always @* begin
        next_txb_read_state = txb_read_state;

        rin_txb_rd_en = 1'b0;
        rin_txb_mod_rd_ptr = r_txb_mod_rd_ptr;
        rin_txb_resend_rd_ptr = r_txb_resend_rd_ptr;
        txb_rd_ptr = {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};

        case(txb_read_state)

            S_TXB_READ_IDLE: begin

                if (ack_state == S_ACK_RESEND_START) begin
                    rin_txb_resend_rd_ptr = r_resend_pos;
                    next_txb_read_state = S_TXB_READ_RESEND;
                end


                else if (txb_data_avail) begin
                    next_txb_read_state = S_TXB_READ_SEND;
                end
            end


            S_TXB_READ_SEND: begin
                txb_rd_ptr = r_txb_mod_rd_ptr;

                if (!noc_stall_i) begin
                    if (txb_data_avail) begin
                        rin_txb_rd_en = 1'b1;
                        rin_txb_mod_rd_ptr = r_txb_mod_rd_ptr + 1;
                    end


                    else begin
                        next_txb_read_state = S_TXB_READ_FINISH;
                    end
                end
                else begin
                    rin_txb_rd_en = r_txb_rd_en;
                end
            end


            S_TXB_READ_RESEND: begin
                txb_rd_ptr = r_txb_resend_rd_ptr;

                if (!noc_stall_i) begin
                    if (r_txb_resend_rd_ptr != resend_end_ptr) begin
                        rin_txb_rd_en = 1'b1;
                        rin_txb_resend_rd_ptr = r_txb_resend_rd_ptr + 1;
                    end


                    else begin
                        next_txb_read_state = S_TXB_READ_FINISH;
                    end
                end
                else begin
                    rin_txb_rd_en = r_txb_rd_en;
                end
            end

            S_TXB_READ_FINISH: begin
                next_txb_read_state = S_TXB_READ_IDLE;
            end
        endcase
    end



    always @* begin
        rin_txb_rdata_fromreg = r_txb_rdata_fromreg;
        rin_txb_arq_out = r_txb_arq_out;
        rin_txb_header_out = r_txb_header_out;
        rin_txb_payload_out = r_txb_payload_out;

        if (r_txb_rd_en && noc_stall_i && !r_noc_stall) begin
            rin_txb_rdata_fromreg = 1'b1;
            rin_txb_arq_out = txb_arq_out;
            rin_txb_header_out = txb_header_out;
            rin_txb_payload_out = txb_payload_out;
        end
        else if (!noc_stall_i) begin
            rin_txb_rdata_fromreg = 1'b0;
        end
    end


    always @* begin

        case(arq_enable_i)
            NOC_ARQ_ENABLE_OFF: begin
                txb_arq_out = 1'b0;
            end
            NOC_ARQ_ENABLE_ON: begin
                txb_arq_out = 1'b1;
            end
            default: begin
                txb_arq_out = txb_header_out[NOC_HEADER_SIZE-NOC_BURST_SIZE-1];
            end
        endcase


        noc_wrreq_o = r_txb_rd_en;
        noc_header_o = r_txb_rdata_fromreg ?
                        {r_txb_header_out[NOC_HEADER_SIZE-1], r_txb_arq_out, r_txb_header_out[NOC_HEADER_SIZE-NOC_BURST_SIZE-NOC_ARQ_SIZE-1:0]} :
                        {txb_header_out[NOC_HEADER_SIZE-1], txb_arq_out, txb_header_out[NOC_HEADER_SIZE-NOC_BURST_SIZE-NOC_ARQ_SIZE-1:0]};
        noc_payload_o = r_txb_rdata_fromreg ? r_txb_payload_out : txb_payload_out;
        



        if (rin_forward && !txb_read_active) begin
            noc_wrreq_o = mod_wrreq_i;
            noc_header_o = {mod_header_i[NOC_HEADER_SIZE-1], 1'b0, mod_header_i[NOC_HEADER_SIZE-NOC_BURST_SIZE-NOC_ARQ_SIZE-1:0]};
            noc_payload_o = mod_payload_i;
        end
    end

    assign mod_stall_o = rin_forward ? (noc_stall_i || txb_read_active) : (txb_full || (txb_write_state == S_TXB_WRITE_SET_BVT));




    always @* begin
        next_ack_state = ack_state;

        rin_txb_occ_ptr = r_txb_occ_ptr;

        bvt_rd_en = 1'b0;
        rin_bvt_ack_wr_ptr = r_bvt_ack_wr_ptr;
        rin_bvt_occ_ptr = r_bvt_occ_ptr;
        rin_bvt_rd_ptr = r_bvt_rd_ptr;

        rin_resend_pos = r_resend_pos;
        rin_resend_length = r_resend_length;

        ack_fifo_pop = 1'b0;


        case(ack_state)

            S_ACK_IDLE: begin
                if (!ack_fifo_empty) begin
                    bvt_rd_en = 1'b1;
                    rin_bvt_rd_ptr = r_bvt_rd_ptr + 1;
                    next_ack_state = S_ACK_CHECK;
                end
            end

            S_ACK_CHECK: begin
                bvt_rd_en = 1'b1;
                rin_bvt_rd_ptr = r_bvt_rd_ptr + 1;


                if (r_bvt_valid_entry[bvt_rd_ptr_decr] &&
                    (ack_fifo_src_modid == bvt_rdata_modid) &&
                    (ack_fifo_src_chipid == bvt_rdata_chipid) &&
                    (ack_fifo_addr == bvt_rdata_addr)) begin
                    ack_fifo_pop = 1'b1;


                    if (ack_fifo_type) begin


                        if (r_bvt_occ_ptr == bvt_rd_ptr_decr) begin
                            rin_bvt_occ_ptr = r_bvt_occ_ptr + 1;
                            rin_txb_occ_ptr = r_txb_occ_ptr + bvt_rdata_length;

                            next_ack_state = S_ACK_INCR_OCC_PTR;
                        end
                        else begin
                            next_ack_state = S_ACK_UPDATE_BVT;
                        end


                        rin_bvt_ack_wr_ptr = bvt_rd_ptr_decr;
                    end


                    else begin
                        rin_resend_pos = bvt_rdata_pos;
                        rin_resend_length = bvt_rdata_length;
                        next_ack_state = S_ACK_RESEND_START;
                    end
                end



                else if (r_bvt_rd_ptr == r_bvt_mod_wr_ptr) begin
                    rin_bvt_rd_ptr = r_bvt_occ_ptr;
                end
            end



            S_ACK_INCR_OCC_PTR: begin
                bvt_rd_en = 1'b1;
                rin_bvt_rd_ptr = r_bvt_rd_ptr + 1;
                
                if (r_bvt_valid_entry[bvt_rd_ptr_decr] || (r_bvt_occ_ptr == r_bvt_mod_wr_ptr)) begin
                    next_ack_state = S_ACK_UPDATE_BVT;
                end
                else begin

                    rin_bvt_occ_ptr = r_bvt_occ_ptr + 1;
                    rin_txb_occ_ptr = r_txb_occ_ptr + bvt_rdata_length;
                end
            end


            S_ACK_UPDATE_BVT: begin


                rin_bvt_rd_ptr = r_bvt_occ_ptr;
                next_ack_state = S_ACK_IDLE;
            end



            S_ACK_RESEND_START: begin
                if (!txb_read_active) begin
                    next_ack_state = S_ACK_RESEND;
                end
            end


            S_ACK_RESEND: begin
                if (!txb_read_active) begin


                    rin_bvt_rd_ptr = r_bvt_occ_ptr;
                    next_ack_state = S_ACK_IDLE;
                end
            end

            default: next_ack_state = S_ACK_IDLE;
        endcase
    end



    always @* begin
        bvt_wr_en = 1'b0;
        bvt_wr_ptr = {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
        bvt_wdata = {BVT_DATA_SIZE{1'b0}};

        rin_bvt_valid_entry = r_bvt_valid_entry;



        if (ack_state == S_ACK_UPDATE_BVT) begin

            bvt_wr_ptr = r_bvt_ack_wr_ptr;


            rin_bvt_valid_entry = r_bvt_valid_entry ^ ptr_to_bit_mask;
        end


        else if (txb_write_state == S_TXB_WRITE_SET_BVT) begin
            bvt_wr_en = 1'b1;
            bvt_wr_ptr = r_bvt_mod_wr_ptr;
            bvt_wdata = {r_bvt_wdata_pos, r_bvt_wdata_length, r_bvt_wdata_modid, r_bvt_wdata_chipid, r_bvt_wdata_addr};


            rin_bvt_valid_entry = r_bvt_valid_entry ^ ptr_to_bit_mask;
        end
    end


    assign arq_tx_bvt_mod_wr_ptr_o = {{(32-ARQ_TX_BUFFER_ADDR_WIDTH){1'b0}}, r_bvt_mod_wr_ptr};
    assign arq_tx_bvt_ack_wr_ptr_o = {{(32-ARQ_TX_BUFFER_ADDR_WIDTH){1'b0}}, r_bvt_ack_wr_ptr};
    assign arq_tx_bvt_occ_ptr_o = {{(32-ARQ_TX_BUFFER_ADDR_WIDTH){1'b0}}, r_bvt_occ_ptr};
    assign arq_tx_bvt_rd_ptr_o = {{(32-ARQ_TX_BUFFER_ADDR_WIDTH){1'b0}}, r_bvt_rd_ptr};

endmodule
module noc_arq_tx #(
    `include "noc_parameter.vh"
    ,parameter ARQ_TX_BUFFER_ADDR_WIDTH = 8
)(
    input  wire                        clk_i,
    input  wire                        reset_q_i,


    input  wire                        mod_wrreq_i,
    input  wire  [NOC_HEADER_SIZE-1:0] mod_header_i,
    input  wire [NOC_PAYLOAD_SIZE-1:0] mod_payload_i,
    output wire                        mod_stall_o,
    output reg                         noc_wrreq_o,
    output reg   [NOC_HEADER_SIZE-1:0] noc_header_o,
    output reg  [NOC_PAYLOAD_SIZE-1:0] noc_payload_o,
    input  wire                        noc_stall_i,


    input  wire                        ack_wrreq_i,
    input  wire  [NOC_HEADER_SIZE-1:0] ack_header_i,
    input  wire [NOC_PAYLOAD_SIZE-1:0] ack_payload_i,
    output wire                        ack_stall_o,

    input  wire                  [1:0] arq_enable_i,


    output wire                 [31:0] arq_tx_bvt_mod_wr_ptr_o,
    output wire                 [31:0] arq_tx_bvt_ack_wr_ptr_o,
    output wire                 [31:0] arq_tx_bvt_occ_ptr_o,
    output wire                 [31:0] arq_tx_bvt_rd_ptr_o
);



    localparam PTR_ADDR_WIDTH = ARQ_TX_BUFFER_ADDR_WIDTH + 1;
    localparam BVT_DATA_SIZE = 2*ARQ_TX_BUFFER_ADDR_WIDTH + NOC_MODID_SIZE + NOC_CHIPID_SIZE + NOC_ADDR_SIZE;
    localparam ARQ_TX_BUFFER_DEPTH = 1 << ARQ_TX_BUFFER_ADDR_WIDTH;
    localparam ACK_FIFO_DATA_SIZE = NOC_MODID_SIZE + NOC_CHIPID_SIZE + NOC_ADDR_SIZE + 1;


    localparam S_TXB_WRITE_FILL_BUF = 1'b0;
    localparam S_TXB_WRITE_SET_BVT  = 1'b1;
    reg txb_write_state, next_txb_write_state;


    localparam S_TXB_READ_IDLE   = 2'h0;
    localparam S_TXB_READ_SEND   = 2'h1;
    localparam S_TXB_READ_RESEND = 2'h2;
    localparam S_TXB_READ_FINISH = 2'h3;
    reg [1:0] txb_read_state, next_txb_read_state;


    localparam S_ACK_IDLE         = 3'h0;
    localparam S_ACK_CHECK        = 3'h1;
    localparam S_ACK_INCR_OCC_PTR = 3'h2;
    localparam S_ACK_UPDATE_BVT   = 3'h3;
    localparam S_ACK_RESEND_START = 3'h4;
    localparam S_ACK_RESEND       = 3'h5;
    reg [2:0] ack_state, next_ack_state;



    reg            [PTR_ADDR_WIDTH-1:0] r_txb_wr_ptr, rin_txb_wr_ptr;
    reg            [PTR_ADDR_WIDTH-1:0] r_txb_occ_ptr, rin_txb_occ_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_txb_mod_rd_ptr, rin_txb_mod_rd_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_txb_resend_rd_ptr, rin_txb_resend_rd_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] txb_rd_ptr;
    reg                                 r_txb_write_active, rin_txb_write_active;

    reg                         r_txb_rdata_fromreg, rin_txb_rdata_fromreg;
    reg                         r_txb_arq_out, rin_txb_arq_out;
    reg   [NOC_HEADER_SIZE-1:0] r_txb_header_out, rin_txb_header_out;
    reg  [NOC_PAYLOAD_SIZE-1:0] r_txb_payload_out, rin_txb_payload_out;

    reg txb_wr_en;
    reg r_txb_rd_en, rin_txb_rd_en;
    reg txb_arq_out;


    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_mod_wr_ptr, rin_bvt_mod_wr_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_ack_wr_ptr, rin_bvt_ack_wr_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_occ_ptr, rin_bvt_occ_ptr;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_rd_ptr, rin_bvt_rd_ptr;

    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_wdata_pos, rin_bvt_wdata_pos;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_bvt_wdata_length, rin_bvt_wdata_length;
    reg            [NOC_MODID_SIZE-1:0] r_bvt_wdata_modid, rin_bvt_wdata_modid;
    reg           [NOC_CHIPID_SIZE-1:0] r_bvt_wdata_chipid, rin_bvt_wdata_chipid;
    reg             [NOC_ADDR_SIZE-1:0] r_bvt_wdata_addr, rin_bvt_wdata_addr;


    reg [ARQ_TX_BUFFER_DEPTH-1:0] r_bvt_valid_entry, rin_bvt_valid_entry;


    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_resend_pos, rin_resend_pos;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] r_resend_length, rin_resend_length;


    reg                                 bvt_wr_en;
    reg  [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] bvt_wr_ptr;
    reg             [BVT_DATA_SIZE-1:0] bvt_wdata;
    reg                                 bvt_rd_en;

    wire [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] bvt_rdata_pos;
    wire [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] bvt_rdata_length;
    wire           [NOC_MODID_SIZE-1:0] bvt_rdata_modid;
    wire          [NOC_CHIPID_SIZE-1:0] bvt_rdata_chipid;
    wire            [NOC_ADDR_SIZE-1:0] bvt_rdata_addr;



    reg r_forward, rin_forward;
    reg r_mod_burst;
    reg r_noc_stall;


    wire                       mod_burst = mod_header_i[NOC_HEADER_SIZE-1];
    wire                       mod_arq = mod_header_i[2*NOC_MODID_SIZE+2*NOC_CHIPID_SIZE+NOC_BSEL_SIZE +: NOC_ARQ_SIZE];
    wire  [NOC_MODID_SIZE-1:0] mod_trg_modid = mod_header_i[NOC_MODID_SIZE+NOC_CHIPID_SIZE-1 : NOC_CHIPID_SIZE];
    wire [NOC_CHIPID_SIZE-1:0] mod_trg_chipid = mod_header_i[NOC_CHIPID_SIZE-1:0];
    wire   [NOC_ADDR_SIZE-1:0] mod_addr = mod_payload_i[NOC_ADDR_SIZE+NOC_DATA_SIZE-1 : NOC_DATA_SIZE];


    wire  [NOC_HEADER_SIZE-1:0] txb_header_out;
    wire [NOC_PAYLOAD_SIZE-1:0] txb_payload_out;


    wire txb_full = (r_txb_wr_ptr[ARQ_TX_BUFFER_ADDR_WIDTH-1:0] == r_txb_occ_ptr[ARQ_TX_BUFFER_ADDR_WIDTH-1:0]) &&
                            (r_txb_wr_ptr[ARQ_TX_BUFFER_ADDR_WIDTH] != r_txb_occ_ptr[ARQ_TX_BUFFER_ADDR_WIDTH]);


    wire txb_data_avail = (r_txb_wr_ptr[ARQ_TX_BUFFER_ADDR_WIDTH-1:0] != r_txb_mod_rd_ptr) &&
                            !(r_txb_write_active && (r_txb_mod_rd_ptr == r_bvt_wdata_pos));

    wire txb_read_active = (txb_read_state != S_TXB_READ_IDLE);

    wire [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] resend_end_ptr = r_resend_pos + r_resend_length;

    wire [ARQ_TX_BUFFER_ADDR_WIDTH-1:0] bvt_rd_ptr_decr = r_bvt_rd_ptr - 1;

    wire [ARQ_TX_BUFFER_DEPTH-1:0] ptr_to_bit_mask = 1 << bvt_wr_ptr;


    wire  [NOC_MODID_SIZE-1:0] ack_src_modid = ack_header_i[NOC_MODID_SIZE+2*NOC_CHIPID_SIZE +: NOC_MODID_SIZE];
    wire [NOC_CHIPID_SIZE-1:0] ack_src_chipid = ack_header_i[NOC_MODID_SIZE+NOC_CHIPID_SIZE +: NOC_CHIPID_SIZE];
    wire   [NOC_ADDR_SIZE-1:0] ack_addr = ack_payload_i[NOC_ADDR_SIZE+NOC_DATA_SIZE-1 : NOC_DATA_SIZE];


    wire ack_type = ack_payload_i[0];


    reg                        ack_fifo_pop;
    wire                       ack_fifo_empty;
    wire  [NOC_MODID_SIZE-1:0] ack_fifo_src_modid;
    wire [NOC_CHIPID_SIZE-1:0] ack_fifo_src_chipid;
    wire   [NOC_ADDR_SIZE-1:0] ack_fifo_addr;
    wire                       ack_fifo_type;





    mem_tp_wrap #(
        .MEM_TYPE      ("auto"),
        .MEM_DATAWIDTH (NOC_HEADER_SIZE+NOC_PAYLOAD_SIZE),
        .MEM_ADDRWIDTH (ARQ_TX_BUFFER_ADDR_WIDTH)
    ) arq_tx_buffer (
        .clk     (clk_i),
        .reset   (~reset_q_i),

        .ena     (txb_wr_en),
        .wea     ({((NOC_HEADER_SIZE+NOC_PAYLOAD_SIZE+7)/8){1'b1}}),
        .addra   (r_txb_wr_ptr[ARQ_TX_BUFFER_ADDR_WIDTH-1:0]),
        .dina    ({mod_header_i, mod_payload_i}),

        .enb     (rin_txb_rd_en),
        .addrb   (txb_rd_ptr),
        .doutb   ({txb_header_out, txb_payload_out})
    );



    mem_tp_wrap #(
        .MEM_TYPE      ("auto"),
        .MEM_DATAWIDTH (BVT_DATA_SIZE),
        .MEM_ADDRWIDTH (ARQ_TX_BUFFER_ADDR_WIDTH)
    ) arq_bvt (
        .clk     (clk_i),
        .reset   (~reset_q_i),

        .ena     (bvt_wr_en),
        .wea     ({((BVT_DATA_SIZE+7)/8){1'b1}}),
        .addra   (bvt_wr_ptr),
        .dina    (bvt_wdata),

        .enb     (bvt_rd_en),
        .addrb   (r_bvt_rd_ptr),
        .doutb   ({bvt_rdata_pos, bvt_rdata_length, bvt_rdata_modid, bvt_rdata_chipid, bvt_rdata_addr})
    );



    sync_fifo #(
        .DATA_WIDTH (ACK_FIFO_DATA_SIZE),
        .ADDR_WIDTH (3)
    ) ack_fifo (
        .clk_i		(clk_i),
        .resetn_i	(reset_q_i),

        .wr_en_i	(ack_wrreq_i),
        .wdata_i	({ack_src_modid, ack_src_chipid, ack_addr, ack_type}),
        .wfull_o	(ack_stall_o),

        .rd_en_i	(ack_fifo_pop),
        .rdata_o	({ack_fifo_src_modid, ack_fifo_src_chipid, ack_fifo_addr, ack_fifo_type}),
        .rempty_o	(ack_fifo_empty)
    );



    always @(posedge clk_i or negedge reset_q_i) begin
        if (reset_q_i == 1'b0) begin
            txb_write_state <= S_TXB_WRITE_FILL_BUF;
            txb_read_state <= S_TXB_READ_IDLE;
            ack_state <= S_ACK_IDLE;

            r_txb_wr_ptr <= {PTR_ADDR_WIDTH{1'b0}};
            r_txb_occ_ptr <= {PTR_ADDR_WIDTH{1'b0}};
            r_txb_mod_rd_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_txb_resend_rd_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_txb_rd_en <= 1'b0;
            r_txb_write_active <= 1'b0;

            r_txb_rdata_fromreg <= 1'b0;
            r_txb_arq_out <= 1'b0;
            r_txb_header_out <= {NOC_HEADER_SIZE{1'b0}};
            r_txb_payload_out <= {NOC_PAYLOAD_SIZE{1'b0}};

            r_bvt_mod_wr_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_ack_wr_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_occ_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_rd_ptr <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};

            r_bvt_wdata_pos <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_wdata_length <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_bvt_wdata_modid <= {NOC_MODID_SIZE{1'b0}};
            r_bvt_wdata_chipid <= {NOC_CHIPID_SIZE{1'b0}};
            r_bvt_wdata_addr <= {NOC_ADDR_SIZE{1'b0}};

            r_bvt_valid_entry <= {ARQ_TX_BUFFER_DEPTH{1'b0}};

            r_resend_pos <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
            r_resend_length <= {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};

            r_forward <= 1'b0;
            r_mod_burst <= 1'b0;
            r_noc_stall <= 1'b0;
        end
        else begin
            txb_write_state <= next_txb_write_state;
            txb_read_state <= next_txb_read_state;
            ack_state <= next_ack_state;

            r_txb_wr_ptr <= rin_txb_wr_ptr;
            r_txb_mod_rd_ptr <= rin_txb_mod_rd_ptr;
            r_txb_resend_rd_ptr <= rin_txb_resend_rd_ptr;
            r_txb_occ_ptr <= rin_txb_occ_ptr;
            r_txb_rd_en <= rin_txb_rd_en;
            r_txb_write_active <= rin_txb_write_active;

            r_txb_rdata_fromreg <= rin_txb_rdata_fromreg;
            r_txb_arq_out <= rin_txb_arq_out;
            r_txb_header_out <= rin_txb_header_out;
            r_txb_payload_out <= rin_txb_payload_out;

            r_bvt_mod_wr_ptr <= rin_bvt_mod_wr_ptr;
            r_bvt_ack_wr_ptr <= rin_bvt_ack_wr_ptr;
            r_bvt_occ_ptr <= rin_bvt_occ_ptr;
            r_bvt_rd_ptr <= rin_bvt_rd_ptr;

            r_bvt_wdata_pos <= rin_bvt_wdata_pos;
            r_bvt_wdata_length <= rin_bvt_wdata_length;
            r_bvt_wdata_modid <= rin_bvt_wdata_modid;
            r_bvt_wdata_chipid <= rin_bvt_wdata_chipid;
            r_bvt_wdata_addr <= rin_bvt_wdata_addr;

            r_bvt_valid_entry <= rin_bvt_valid_entry;

            r_resend_pos <= rin_resend_pos;
            r_resend_length <= rin_resend_length;

            r_forward <= rin_forward;
            r_mod_burst <= (mod_wrreq_i && !mod_stall_o) ? mod_burst : r_mod_burst;
            r_noc_stall <= noc_stall_i;
        end
    end





    always @* begin
        next_txb_write_state = txb_write_state;

        rin_txb_write_active = r_txb_write_active;

        txb_wr_en = 1'b0;
        rin_txb_wr_ptr = r_txb_wr_ptr;

        rin_bvt_mod_wr_ptr = r_bvt_mod_wr_ptr;

        rin_bvt_wdata_pos = r_bvt_wdata_pos;
        rin_bvt_wdata_length = r_bvt_wdata_length;
        rin_bvt_wdata_modid = r_bvt_wdata_modid;
        rin_bvt_wdata_chipid = r_bvt_wdata_chipid;
        rin_bvt_wdata_addr = r_bvt_wdata_addr;

        case(txb_write_state)
            S_TXB_WRITE_FILL_BUF: begin
                if (mod_wrreq_i && !rin_forward && !txb_full) begin

                    rin_txb_write_active = 1'b1;

                    txb_wr_en = 1'b1;
                    rin_txb_wr_ptr = r_txb_wr_ptr + 1;

                    if (!r_mod_burst) begin

                        rin_bvt_wdata_pos = r_txb_wr_ptr;
                        rin_bvt_wdata_modid = mod_trg_modid;
                        rin_bvt_wdata_chipid = mod_trg_chipid;
                        rin_bvt_wdata_addr = mod_addr;


                        if (mod_burst) begin
                            rin_bvt_wdata_length = mod_payload_i[ARQ_TX_BUFFER_ADDR_WIDTH-1:0] + 1;
                        end


                        else begin
                            rin_bvt_wdata_length = 1;
                        end
                    end


                    if (!mod_burst) begin
                        next_txb_write_state = S_TXB_WRITE_SET_BVT;
                    end
                end
            end

            S_TXB_WRITE_SET_BVT: begin
                rin_txb_write_active = 1'b0;


                if (ack_state != S_ACK_UPDATE_BVT) begin
                    rin_bvt_mod_wr_ptr = r_bvt_mod_wr_ptr + 1;
                    next_txb_write_state = S_TXB_WRITE_FILL_BUF;
                end
            end
        endcase
    end



    always @* begin
        rin_forward = 1'b0;

        if (!r_mod_burst) begin


            case(arq_enable_i)
                NOC_ARQ_ENABLE_OFF: begin
                    rin_forward = 1'b1;
                end
                NOC_ARQ_ENABLE_ON: begin
                    rin_forward = 1'b0;
                end
                default: begin


                    if (mod_arq) begin
                        rin_forward = 1'b0;
                    end else begin
                        rin_forward = 1'b1;
                    end
                end
            endcase
        end


        else if (r_forward) begin
            rin_forward = r_forward;
        end
    end



    always @* begin
        next_txb_read_state = txb_read_state;

        rin_txb_rd_en = 1'b0;
        rin_txb_mod_rd_ptr = r_txb_mod_rd_ptr;
        rin_txb_resend_rd_ptr = r_txb_resend_rd_ptr;
        txb_rd_ptr = {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};

        case(txb_read_state)

            S_TXB_READ_IDLE: begin

                if (ack_state == S_ACK_RESEND_START) begin
                    rin_txb_resend_rd_ptr = r_resend_pos;
                    next_txb_read_state = S_TXB_READ_RESEND;
                end


                else if (txb_data_avail) begin
                    next_txb_read_state = S_TXB_READ_SEND;
                end
            end


            S_TXB_READ_SEND: begin
                txb_rd_ptr = r_txb_mod_rd_ptr;

                if (!noc_stall_i) begin
                    if (txb_data_avail) begin
                        rin_txb_rd_en = 1'b1;
                        rin_txb_mod_rd_ptr = r_txb_mod_rd_ptr + 1;
                    end


                    else begin
                        next_txb_read_state = S_TXB_READ_FINISH;
                    end
                end
                else begin
                    rin_txb_rd_en = r_txb_rd_en;
                end
            end


            S_TXB_READ_RESEND: begin
                txb_rd_ptr = r_txb_resend_rd_ptr;

                if (!noc_stall_i) begin
                    if (r_txb_resend_rd_ptr != resend_end_ptr) begin
                        rin_txb_rd_en = 1'b1;
                        rin_txb_resend_rd_ptr = r_txb_resend_rd_ptr + 1;
                    end


                    else begin
                        next_txb_read_state = S_TXB_READ_FINISH;
                    end
                end
                else begin
                    rin_txb_rd_en = r_txb_rd_en;
                end
            end

            S_TXB_READ_FINISH: begin
                next_txb_read_state = S_TXB_READ_IDLE;
            end
        endcase
    end



    always @* begin
        rin_txb_rdata_fromreg = r_txb_rdata_fromreg;
        rin_txb_arq_out = r_txb_arq_out;
        rin_txb_header_out = r_txb_header_out;
        rin_txb_payload_out = r_txb_payload_out;

        if (r_txb_rd_en && noc_stall_i && !r_noc_stall) begin
            rin_txb_rdata_fromreg = 1'b1;
            rin_txb_arq_out = txb_arq_out;
            rin_txb_header_out = txb_header_out;
            rin_txb_payload_out = txb_payload_out;
        end
        else if (!noc_stall_i) begin
            rin_txb_rdata_fromreg = 1'b0;
        end
    end


    always @* begin

        case(arq_enable_i)
            NOC_ARQ_ENABLE_OFF: begin
                txb_arq_out = 1'b0;
            end
            NOC_ARQ_ENABLE_ON: begin
                txb_arq_out = 1'b1;
            end
            default: begin
                txb_arq_out = txb_header_out[NOC_HEADER_SIZE-NOC_BURST_SIZE-1];
            end
        endcase


        noc_wrreq_o = r_txb_rd_en;
        noc_header_o = r_txb_rdata_fromreg ?
                        {r_txb_header_out[NOC_HEADER_SIZE-1], r_txb_arq_out, r_txb_header_out[NOC_HEADER_SIZE-NOC_BURST_SIZE-NOC_ARQ_SIZE-1:0]} :
                        {txb_header_out[NOC_HEADER_SIZE-1], txb_arq_out, txb_header_out[NOC_HEADER_SIZE-NOC_BURST_SIZE-NOC_ARQ_SIZE-1:0]};
        noc_payload_o = r_txb_rdata_fromreg ? r_txb_payload_out : txb_payload_out;
        



        if (rin_forward && !txb_read_active) begin
            noc_wrreq_o = mod_wrreq_i;
            noc_header_o = {mod_header_i[NOC_HEADER_SIZE-1], 1'b0, mod_header_i[NOC_HEADER_SIZE-NOC_BURST_SIZE-NOC_ARQ_SIZE-1:0]};
            noc_payload_o = mod_payload_i;
        end
    end

    assign mod_stall_o = rin_forward ? (noc_stall_i || txb_read_active) : (txb_full || (txb_write_state == S_TXB_WRITE_SET_BVT));




    always @* begin
        next_ack_state = ack_state;

        rin_txb_occ_ptr = r_txb_occ_ptr;

        bvt_rd_en = 1'b0;
        rin_bvt_ack_wr_ptr = r_bvt_ack_wr_ptr;
        rin_bvt_occ_ptr = r_bvt_occ_ptr;
        rin_bvt_rd_ptr = r_bvt_rd_ptr;

        rin_resend_pos = r_resend_pos;
        rin_resend_length = r_resend_length;

        ack_fifo_pop = 1'b0;


        case(ack_state)

            S_ACK_IDLE: begin
                if (!ack_fifo_empty) begin
                    bvt_rd_en = 1'b1;
                    rin_bvt_rd_ptr = r_bvt_rd_ptr + 1;
                    next_ack_state = S_ACK_CHECK;
                end
            end

            S_ACK_CHECK: begin
                bvt_rd_en = 1'b1;
                rin_bvt_rd_ptr = r_bvt_rd_ptr + 1;


                if (r_bvt_valid_entry[bvt_rd_ptr_decr] &&
                    (ack_fifo_src_modid == bvt_rdata_modid) &&
                    (ack_fifo_src_chipid == bvt_rdata_chipid) &&
                    (ack_fifo_addr == bvt_rdata_addr)) begin
                    ack_fifo_pop = 1'b1;


                    if (ack_fifo_type) begin


                        if (r_bvt_occ_ptr == bvt_rd_ptr_decr) begin
                            rin_bvt_occ_ptr = r_bvt_occ_ptr + 1;
                            rin_txb_occ_ptr = r_txb_occ_ptr + bvt_rdata_length;

                            next_ack_state = S_ACK_INCR_OCC_PTR;
                        end
                        else begin
                            next_ack_state = S_ACK_UPDATE_BVT;
                        end


                        rin_bvt_ack_wr_ptr = bvt_rd_ptr_decr;
                    end


                    else begin
                        rin_resend_pos = bvt_rdata_pos;
                        rin_resend_length = bvt_rdata_length;
                        next_ack_state = S_ACK_RESEND_START;
                    end
                end



                else if (r_bvt_rd_ptr == r_bvt_mod_wr_ptr) begin
                    rin_bvt_rd_ptr = r_bvt_occ_ptr;
                end
            end



            S_ACK_INCR_OCC_PTR: begin
                bvt_rd_en = 1'b1;
                rin_bvt_rd_ptr = r_bvt_rd_ptr + 1;
                
                if (r_bvt_valid_entry[bvt_rd_ptr_decr] || (r_bvt_occ_ptr == r_bvt_mod_wr_ptr)) begin
                    next_ack_state = S_ACK_UPDATE_BVT;
                end
                else begin

                    rin_bvt_occ_ptr = r_bvt_occ_ptr + 1;
                    rin_txb_occ_ptr = r_txb_occ_ptr + bvt_rdata_length;
                end
            end


            S_ACK_UPDATE_BVT: begin


                rin_bvt_rd_ptr = r_bvt_occ_ptr;
                next_ack_state = S_ACK_IDLE;
            end



            S_ACK_RESEND_START: begin
                if (!txb_read_active) begin
                    next_ack_state = S_ACK_RESEND;
                end
            end


            S_ACK_RESEND: begin
                if (!txb_read_active) begin


                    rin_bvt_rd_ptr = r_bvt_occ_ptr;
                    next_ack_state = S_ACK_IDLE;
                end
            end

            default: next_ack_state = S_ACK_IDLE;
        endcase
    end



    always @* begin
        bvt_wr_en = 1'b0;
        bvt_wr_ptr = {ARQ_TX_BUFFER_ADDR_WIDTH{1'b0}};
        bvt_wdata = {BVT_DATA_SIZE{1'b0}};

        rin_bvt_valid_entry = r_bvt_valid_entry;



        if (ack_state == S_ACK_UPDATE_BVT) begin

            bvt_wr_ptr = r_bvt_ack_wr_ptr;


            rin_bvt_valid_entry = r_bvt_valid_entry ^ ptr_to_bit_mask;
        end


        else if (txb_write_state == S_TXB_WRITE_SET_BVT) begin
            bvt_wr_en = 1'b1;
            bvt_wr_ptr = r_bvt_mod_wr_ptr;
            bvt_wdata = {r_bvt_wdata_pos, r_bvt_wdata_length, r_bvt_wdata_modid, r_bvt_wdata_chipid, r_bvt_wdata_addr};


            rin_bvt_valid_entry = r_bvt_valid_entry ^ ptr_to_bit_mask;
        end
    end


    assign arq_tx_bvt_mod_wr_ptr_o = {{(32-ARQ_TX_BUFFER_ADDR_WIDTH){1'b0}}, r_bvt_mod_wr_ptr};
    assign arq_tx_bvt_ack_wr_ptr_o = {{(32-ARQ_TX_BUFFER_ADDR_WIDTH){1'b0}}, r_bvt_ack_wr_ptr};
    assign arq_tx_bvt_occ_ptr_o = {{(32-ARQ_TX_BUFFER_ADDR_WIDTH){1'b0}}, r_bvt_occ_ptr};
    assign arq_tx_bvt_rd_ptr_o = {{(32-ARQ_TX_BUFFER_ADDR_WIDTH){1'b0}}, r_bvt_rd_ptr};

endmodule