data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/core/chdr_stream_output.v
 line:50: before: "="
1: b'%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/core/chdr_stream_output.v:75: Cannot find include file: rfnoc_chdr_utils.vh\n  `include "rfnoc_chdr_utils.vh" \n           ^~~~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/core,data/full_repos/permissive/214858095/rfnoc_chdr_utils.vh\n             data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/core,data/full_repos/permissive/214858095/rfnoc_chdr_utils.vh.v\n             data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/core,data/full_repos/permissive/214858095/rfnoc_chdr_utils.vh.sv\n             rfnoc_chdr_utils.vh\n             rfnoc_chdr_utils.vh.v\n             rfnoc_chdr_utils.vh.sv\n             obj_dir/rfnoc_chdr_utils.vh\n             obj_dir/rfnoc_chdr_utils.vh.v\n             obj_dir/rfnoc_chdr_utils.vh.sv\n%Error: data/full_repos/permissive/214858095/FPGA_Exploration/spartan6/B205mini/ISE_Project/lib/rfnoc/core/chdr_stream_output.v:76: Cannot find include file: rfnoc_chdr_internal_utils.vh\n  `include "rfnoc_chdr_internal_utils.vh" \n           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n%Error: Exiting due to 2 error(s)\n'
module chdr_stream_output #(
  parameter CHDR_W = 256,
  parameter MTU    = 10
)(

  input  wire              clk,
  input  wire              rst,

  output wire [CHDR_W-1:0] m_axis_chdr_tdata,
  output wire              m_axis_chdr_tlast,
  output wire              m_axis_chdr_tvalid,
  input  wire              m_axis_chdr_tready,

  input  wire [CHDR_W-1:0] s_axis_data_tdata,
  input  wire              s_axis_data_tlast,
  input  wire              s_axis_data_tvalid,
  output wire              s_axis_data_tready,

  input  wire [CHDR_W-1:0] s_axis_strs_tdata,
  input  wire              s_axis_strs_tlast,
  input  wire              s_axis_strs_tvalid,
  output wire              s_axis_strs_tready,

  input  wire              cfg_start,
  output reg               cfg_pending = 1'b0,
  output reg               cfg_failed = 1'b0,
  input  wire              cfg_lossy_xport,
  input  wire [15:0]       cfg_dst_epid,
  input  wire [15:0]       cfg_this_epid,
  input  wire [39:0]       cfg_fc_freq_bytes,
  input  wire [23:0]       cfg_fc_freq_pkts,
  input  wire [15:0]       cfg_fc_headroom_bytes,
  input  wire [7:0]        cfg_fc_headroom_pkts,

  output reg               fc_enabled     = 1'b0,
  output reg  [39:0]       capacity_bytes = 40'd0,
  output reg  [23:0]       capacity_pkts  = 24'd0,

  output wire              seq_err_stb,
  output reg  [31:0]       seq_err_cnt = 32'd0,
  output wire              data_err_stb,
  output reg  [31:0]       data_err_cnt = 32'd0,
  output wire              route_err_stb,
  output reg  [31:0]       route_err_cnt = 32'd0
);




  `include "rfnoc_chdr_utils.vh"
  `include "rfnoc_chdr_internal_utils.vh"

  localparam CHDR_W_LOG2 = $clog2(CHDR_W);




  reg  [CHDR_W-1:0] chdr_out_tdata;
  reg               chdr_out_tlast, chdr_out_tvalid;
  wire              chdr_out_tready;

  axi_packet_gate #(
    .WIDTH(CHDR_W), .SIZE(MTU), .USE_AS_BUFF(0)
  ) chdr_pkt_gate_i (
    .clk(clk), .reset(rst), .clear(1'b0),
    .i_tdata(chdr_out_tdata), .i_tlast(chdr_out_tlast), .i_terror(1'b0),
    .i_tvalid(chdr_out_tvalid), .i_tready(chdr_out_tready),
    .o_tdata(m_axis_chdr_tdata), .o_tlast(m_axis_chdr_tlast),
    .o_tvalid(m_axis_chdr_tvalid), .o_tready(m_axis_chdr_tready)
  );











  reg [63:0] send_cnt_bytes = 64'd0;
  reg [39:0] send_cnt_pkts  = 40'd0;
  reg [63:0] recv_cnt_bytes = 64'd0;
  reg [39:0] recv_cnt_pkts  = 40'd0;
  reg [39:0] accum_bytes    = 40'd0;
  reg [23:0] accum_pkts     = 24'd0;
  reg [15:0] headroom_bytes = 16'd0;
  reg [ 7:0] headroom_pkts  =  8'd0;
  reg [39:0] adj_cap_bytes  = 40'd0;
  reg [23:0] adj_cap_pkts   = 24'd0;
  reg [63:0] strc_cnt_bytes = 64'd0;


  always @(posedge clk) begin
    if (rst || !fc_enabled) begin
      send_cnt_bytes <= 64'd0;
      send_cnt_pkts  <= 40'd0;
    end else if (chdr_out_tvalid && chdr_out_tready) begin
      send_cnt_bytes <= send_cnt_bytes + (CHDR_W/8);
      if (chdr_out_tlast)
        send_cnt_pkts <= send_cnt_pkts + 40'd1;
    end
  end



  wire signed [64:0] occupied_bytes = 
    $signed({1'b0, send_cnt_bytes}) - $signed({1'b0, recv_cnt_bytes});
  wire signed [40:0] occupied_pkts =
    $signed({1'b0, send_cnt_pkts}) - $signed({1'b0, recv_cnt_pkts});






  reg  [3:0] ok_shreg = 4'b1111;
  always @(posedge clk) begin
    if (rst || !fc_enabled) begin
      ok_shreg <= 4'b1111;
    end else begin
      ok_shreg <= {ok_shreg[2:0], (
        (occupied_bytes[40:0] < $signed({1'b0, adj_cap_bytes})) &&
        (occupied_pkts [24:0] < $signed({1'b0, adj_cap_pkts }))
      )};
    end
  end
  wire ok_to_send = ok_shreg[3];


  reg lossy_xport = 1'b0;
  reg [3:0] fc_resync_req_shreg = 4'h0;
  wire fc_resync_req, fc_resync_ack;

  always @(posedge clk) begin
    if (rst || !fc_enabled || !lossy_xport || fc_resync_ack) begin

      accum_bytes <= 40'd0;
      accum_pkts <= 24'd0;
      fc_resync_req_shreg <= 4'b0000;
    end else begin 
      if (chdr_out_tvalid && chdr_out_tready) begin

        accum_bytes <= accum_bytes + (CHDR_W/8);
        if (chdr_out_tlast)
          accum_pkts <= accum_pkts + 24'd1;
      end

      fc_resync_req_shreg <= {fc_resync_req_shreg[2:0],
        (accum_bytes > capacity_bytes) || (accum_pkts > capacity_pkts)};
    end
  end
  assign fc_resync_req = fc_resync_req_shreg[3];





  wire [3:0] msg_i_tdata,  msg_o_tdata;
  wire       msg_i_tvalid, msg_o_tvalid;
  wire       msg_i_tready, msg_o_tready;

  axi_fifo #(.WIDTH(4), .SIZE(1)) msg_fifo_i (
    .clk(clk), .reset(rst), .clear(1'b0),
    .i_tdata(msg_i_tdata), .i_tvalid(msg_i_tvalid), .i_tready(msg_i_tready),
    .o_tdata(msg_o_tdata), .o_tvalid(msg_o_tvalid), .o_tready(msg_o_tready),
    .space(), .occupied()
  );

  localparam [2:0] ST_STRS_HDR   = 3'd0;
  localparam [2:0] ST_STRS_W0    = 3'd1;
  localparam [2:0] ST_STRS_W1    = 3'd2;
  localparam [2:0] ST_STRS_W2    = 3'd3;
  localparam [2:0] ST_STRS_W3    = 3'd4;
  localparam [2:0] ST_STRS_LATCH = 3'd5;
  localparam [2:0] ST_STRS_DROP  = 3'd6;

  reg [2:0]   strs_state = ST_STRS_HDR;
  reg         strs_too_long = 1'b0;
  reg [15:0]  cached_dst_epid = 16'd0;
  reg [255:0] cached_strs_msg;

  always @(posedge clk) begin
    if (rst) begin
      strs_state <= ST_STRS_HDR;
      strs_too_long <= 1'b0;
    end else begin
      case (strs_state)



        ST_STRS_HDR: begin
          if (s_axis_strs_tvalid) begin

            if (chdr_get_pkt_type(s_axis_strs_tdata[63:0]) == CHDR_PKT_TYPE_STRS)
              strs_state <= ST_STRS_W0;
            else
              strs_state <= ST_STRS_DROP;
            strs_too_long <= 1'b0;
          end
        end







        ST_STRS_W0: begin
          if (s_axis_strs_tvalid) begin
            if (CHDR_W == 64) begin
              cached_strs_msg[63:0] <= s_axis_strs_tdata[63:0];
              strs_state <= !s_axis_strs_tlast ? ST_STRS_W1 : ST_STRS_HDR;
            end else if (CHDR_W == 128) begin
              cached_strs_msg[127:0] <= s_axis_strs_tdata[127:0];
              strs_state <= !s_axis_strs_tlast ? ST_STRS_W1 : ST_STRS_HDR;
            end else begin
              cached_strs_msg[255:0] <= s_axis_strs_tdata[255:0];
              strs_state <= ST_STRS_LATCH;
              strs_too_long <= !s_axis_strs_tlast;
            end
          end
        end




        ST_STRS_W1: begin
          if (s_axis_strs_tvalid) begin
            if (CHDR_W == 64) begin
              cached_strs_msg[127:64] <= s_axis_strs_tdata[63:0];
              strs_state <= !s_axis_strs_tlast ? ST_STRS_W2 : ST_STRS_HDR;
            end else begin
              cached_strs_msg[255:128] <= s_axis_strs_tdata[127:0];
              strs_state <= ST_STRS_LATCH;
              strs_too_long <= !s_axis_strs_tlast;
            end
          end
        end




        ST_STRS_W2: begin
          if (s_axis_strs_tvalid) begin
            cached_strs_msg[191:128] <= s_axis_strs_tdata[63:0];
              strs_state <= !s_axis_strs_tlast ? ST_STRS_W3 : ST_STRS_HDR;
          end
        end




        ST_STRS_W3: begin
          if (s_axis_strs_tvalid) begin
            cached_strs_msg[255:192] <= s_axis_strs_tdata[63:0];
            strs_state <= ST_STRS_LATCH;
            strs_too_long <= !s_axis_strs_tlast;
          end
        end




        ST_STRS_LATCH: begin
          capacity_bytes <= chdr256_strs_get_capacity_bytes(cached_strs_msg);
          capacity_pkts  <= chdr256_strs_get_capacity_pkts(cached_strs_msg);
          recv_cnt_bytes <= chdr256_strs_get_xfercnt_bytes(cached_strs_msg);
          recv_cnt_pkts  <= chdr256_strs_get_xfercnt_pkts(cached_strs_msg);
          adj_cap_bytes  <= chdr256_strs_get_capacity_bytes(cached_strs_msg) - 
                            {24'd0, headroom_bytes[15:(CHDR_W_LOG2-3)], {(CHDR_W_LOG2-3){1'b0}}};
          adj_cap_pkts   <= chdr256_strs_get_capacity_pkts(cached_strs_msg) - 
                            {16'd0, headroom_pkts};
          if (msg_i_tready) begin
            strs_state <= strs_too_long ? ST_STRS_DROP : ST_STRS_HDR;
          end
        end



        ST_STRS_DROP: begin
          if (s_axis_strs_tvalid && s_axis_strs_tlast)
            strs_state <= ST_STRS_HDR;
        end
        default: begin

          strs_state <= ST_STRS_HDR;
        end
      endcase
    end
  end

  assign s_axis_strs_tready = (strs_state != ST_STRS_LATCH);

  assign msg_i_tvalid = (strs_state == ST_STRS_LATCH);
  assign msg_i_tdata = (chdr256_strs_get_src_epid(cached_strs_msg) != cached_dst_epid) ? 
    CHDR_STRS_STATUS_CMDERR : chdr256_strs_get_status(cached_strs_msg);






  localparam [2:0] ST_PASS_DATA = 3'd0;
  localparam [2:0] ST_STRC_HDR  = 3'd1;
  localparam [2:0] ST_STRC_W0   = 3'd2;
  localparam [2:0] ST_STRC_W1   = 3'd3;
  localparam [2:0] ST_STRC_WAIT = 3'd4;
  localparam [2:0] ST_INIT_DLY  = 3'd5;

  reg [2:0]   state = ST_PASS_DATA;
  reg         mid_pkt = 1'b0;
  reg [15:0]  data_seq_num = 16'd0;
  reg [15:0]  strc_seq_num = 16'd0;
  reg [2:0]   cfg_delay = 3'd0;

  reg cfg_fc_freq_bytes_nz;
  reg cfg_fc_freq_pkts_nz;

  always @(posedge clk) begin
    if (rst) begin
      state <= ST_PASS_DATA;
      mid_pkt <= 1'b0;
      data_seq_num <= 16'd0;
      strc_seq_num <= 16'd0;
      cfg_pending <= 1'b0;
      cfg_failed <= 1'b0;
      cfg_fc_freq_bytes_nz <= 1'bX;
      cfg_fc_freq_pkts_nz <= 1'bX;
    end else begin

      cfg_fc_freq_bytes_nz <= (cfg_fc_freq_bytes != 0);
      cfg_fc_freq_pkts_nz  <= (cfg_fc_freq_pkts  != 0);

      case (state)







        ST_PASS_DATA: begin

          if (chdr_out_tvalid && chdr_out_tready) begin
            mid_pkt <= !chdr_out_tlast;
            if (chdr_out_tlast)
              data_seq_num <= data_seq_num + 16'd1;
          end

          if (cfg_start) begin

            cfg_pending <= 1'b1;
            cfg_failed <= 1'b0;

            fc_enabled <= 1'b0;

            lossy_xport <= cfg_lossy_xport;
            cached_dst_epid <= cfg_dst_epid;
            headroom_bytes <= cfg_fc_headroom_bytes;
            headroom_pkts <= cfg_fc_headroom_pkts;
          end


          if (cfg_start || cfg_pending || fc_resync_req) begin
            if (mid_pkt) begin
              if (chdr_out_tvalid && chdr_out_tready && chdr_out_tlast)
                state <= ST_STRC_HDR;
            end else begin
              if (!(chdr_out_tvalid && chdr_out_tready))
                state <= ST_STRC_HDR;
            end
          end
        end




        ST_STRC_HDR: begin
          if (chdr_out_tvalid && chdr_out_tready) begin
            state <= ST_STRC_W0;

            strc_seq_num <= strc_seq_num + 16'd1;
          end

          strc_cnt_bytes <= send_cnt_bytes;
        end




        ST_STRC_W0: begin
          if (chdr_out_tvalid && chdr_out_tready)
            if (CHDR_W < 128)
              state <= ST_STRC_W1;
            else
              state <= fc_resync_req ? ST_PASS_DATA : ST_STRC_WAIT;
        end




        ST_STRC_W1: begin
          if (chdr_out_tvalid && chdr_out_tready)
            state <= fc_resync_req ? ST_PASS_DATA : ST_STRC_WAIT;
        end




        ST_STRC_WAIT: begin

          if (msg_o_tvalid) begin
            if (msg_o_tdata == CHDR_STRS_STATUS_OKAY) begin
              state <= ST_INIT_DLY;
              cfg_delay <= 3'd4;
              data_seq_num <= 16'd0;
              strc_seq_num <= 16'd0;


              fc_enabled <= cfg_fc_freq_bytes_nz || cfg_fc_freq_pkts_nz;
            end else begin
              state <= ST_PASS_DATA;
              cfg_failed <= 1'b1;
              cfg_pending <= 1'b0;
            end
          end
        end




        ST_INIT_DLY: begin
          if (cfg_delay == 3'd0) begin
            state <= ST_PASS_DATA;
            cfg_pending <= 1'b0;
          end else begin
            cfg_delay <= cfg_delay - 3'd1;
          end
        end


        default: begin
          state <= ST_PASS_DATA;
        end
      endcase
    end
  end


  wire [CHDR_W-1:0] data_header;
  assign data_header[63:0] = chdr_set_seq_num(
    chdr_set_dst_epid(s_axis_data_tdata[63:0], cached_dst_epid),
    data_seq_num);
  generate if (CHDR_W > 64)
    assign data_header[CHDR_W-1:64] = s_axis_data_tdata[CHDR_W-1:64];
  endgenerate


  wire [CHDR_W-1:0] strc_header;
  assign strc_header[63:0] = chdr_build_header(
6'd0,1'b0,1'b0, CHDR_PKT_TYPE_STRC, CHDR_NO_MDATA,
    strc_seq_num, 16'd16+(CHDR_W/8), cached_dst_epid);
  generate if (CHDR_W > 64)
    assign strc_header[CHDR_W-1:64] = {(CHDR_W-64){1'b0}};
  endgenerate


  wire [127:0] strc_init_payload = chdr128_strc_build(
    {24'h0, cfg_fc_freq_bytes}, {16'h0, cfg_fc_freq_pkts},
4'h0, CHDR_STRC_OPCODE_INIT, cfg_this_epid);
  wire [127:0] strc_resync_payload = chdr128_strc_build(
    strc_cnt_bytes, send_cnt_pkts,
4'h0, CHDR_STRC_OPCODE_RESYNC, cfg_this_epid);
  wire [127:0] strc_payload = fc_resync_req ? strc_resync_payload : strc_init_payload;

  always @(*) begin
    case (state)
      ST_PASS_DATA: begin
        chdr_out_tdata  = mid_pkt ? s_axis_data_tdata : data_header;
        chdr_out_tlast  = s_axis_data_tlast;
        chdr_out_tvalid = s_axis_data_tvalid && ok_to_send;
      end
      ST_STRC_HDR: begin
        chdr_out_tdata  = strc_header;
        chdr_out_tlast  = 1'b0;
        chdr_out_tvalid = ok_to_send;
      end
      ST_STRC_W0: begin
        chdr_out_tdata  = strc_payload;
        chdr_out_tlast  = (CHDR_W < 128) ? 1'b0 : 1'b1;
        chdr_out_tvalid = ok_to_send;
      end
      ST_STRC_W1: begin

        chdr_out_tdata  = strc_payload[127:64];
        chdr_out_tlast  = 1'b1;
        chdr_out_tvalid = ok_to_send;
      end
      default: begin
        chdr_out_tdata  = {CHDR_W{1'b0}};
        chdr_out_tlast  = 1'b0;
        chdr_out_tvalid = 1'b0;
      end
    endcase
  end
  assign s_axis_data_tready = (state == ST_PASS_DATA) && chdr_out_tready && ok_to_send;




  assign msg_o_tready = msg_o_tvalid && (state == ST_PASS_DATA || state == ST_STRC_WAIT);


  assign fc_resync_ack = fc_resync_req && (state == ST_STRC_W1 || state == ST_STRC_W0) && 
                         chdr_out_tvalid && chdr_out_tready && chdr_out_tlast;





  wire runtime_err_stb = msg_o_tvalid && msg_o_tready && (state == ST_PASS_DATA);
  assign seq_err_stb = runtime_err_stb && (msg_o_tdata == CHDR_STRS_STATUS_SEQERR);
  assign data_err_stb = runtime_err_stb && (msg_o_tdata == CHDR_STRS_STATUS_DATAERR);
  assign route_err_stb = runtime_err_stb && (msg_o_tdata == CHDR_STRS_STATUS_RTERR);

  always @(posedge clk) begin
    if (rst || !fc_enabled) begin
      seq_err_cnt <= 32'd0;
      data_err_cnt <= 32'd0;
      route_err_cnt <= 32'd0;
    end else begin
      if (seq_err_stb)
        seq_err_cnt <= seq_err_cnt + 32'd1;
      if (data_err_stb)
        data_err_cnt <= data_err_cnt + 32'd1;
      if (route_err_stb)
        route_err_cnt <= route_err_cnt + 32'd1;
    end
  end

endmodule
module chdr_stream_output #(
  parameter CHDR_W = 256,
  parameter MTU    = 10
)(

  input  wire              clk,
  input  wire              rst,

  output wire [CHDR_W-1:0] m_axis_chdr_tdata,
  output wire              m_axis_chdr_tlast,
  output wire              m_axis_chdr_tvalid,
  input  wire              m_axis_chdr_tready,

  input  wire [CHDR_W-1:0] s_axis_data_tdata,
  input  wire              s_axis_data_tlast,
  input  wire              s_axis_data_tvalid,
  output wire              s_axis_data_tready,

  input  wire [CHDR_W-1:0] s_axis_strs_tdata,
  input  wire              s_axis_strs_tlast,
  input  wire              s_axis_strs_tvalid,
  output wire              s_axis_strs_tready,

  input  wire              cfg_start,
  output reg               cfg_pending = 1'b0,
  output reg               cfg_failed = 1'b0,
  input  wire              cfg_lossy_xport,
  input  wire [15:0]       cfg_dst_epid,
  input  wire [15:0]       cfg_this_epid,
  input  wire [39:0]       cfg_fc_freq_bytes,
  input  wire [23:0]       cfg_fc_freq_pkts,
  input  wire [15:0]       cfg_fc_headroom_bytes,
  input  wire [7:0]        cfg_fc_headroom_pkts,

  output reg               fc_enabled     = 1'b0,
  output reg  [39:0]       capacity_bytes = 40'd0,
  output reg  [23:0]       capacity_pkts  = 24'd0,

  output wire              seq_err_stb,
  output reg  [31:0]       seq_err_cnt = 32'd0,
  output wire              data_err_stb,
  output reg  [31:0]       data_err_cnt = 32'd0,
  output wire              route_err_stb,
  output reg  [31:0]       route_err_cnt = 32'd0
);





  `include "rfnoc_chdr_utils.vh"
  `include "rfnoc_chdr_internal_utils.vh"

  localparam CHDR_W_LOG2 = $clog2(CHDR_W);




  reg  [CHDR_W-1:0] chdr_out_tdata;
  reg               chdr_out_tlast, chdr_out_tvalid;
  wire              chdr_out_tready;

  axi_packet_gate #(
    .WIDTH(CHDR_W), .SIZE(MTU), .USE_AS_BUFF(0)
  ) chdr_pkt_gate_i (
    .clk(clk), .reset(rst), .clear(1'b0),
    .i_tdata(chdr_out_tdata), .i_tlast(chdr_out_tlast), .i_terror(1'b0),
    .i_tvalid(chdr_out_tvalid), .i_tready(chdr_out_tready),
    .o_tdata(m_axis_chdr_tdata), .o_tlast(m_axis_chdr_tlast),
    .o_tvalid(m_axis_chdr_tvalid), .o_tready(m_axis_chdr_tready)
  );











  reg [63:0] send_cnt_bytes = 64'd0;
  reg [39:0] send_cnt_pkts  = 40'd0;
  reg [63:0] recv_cnt_bytes = 64'd0;
  reg [39:0] recv_cnt_pkts  = 40'd0;
  reg [39:0] accum_bytes    = 40'd0;
  reg [23:0] accum_pkts     = 24'd0;
  reg [15:0] headroom_bytes = 16'd0;
  reg [ 7:0] headroom_pkts  =  8'd0;
  reg [39:0] adj_cap_bytes  = 40'd0;
  reg [23:0] adj_cap_pkts   = 24'd0;
  reg [63:0] strc_cnt_bytes = 64'd0;


  always @(posedge clk) begin
    if (rst || !fc_enabled) begin
      send_cnt_bytes <= 64'd0;
      send_cnt_pkts  <= 40'd0;
    end else if (chdr_out_tvalid && chdr_out_tready) begin
      send_cnt_bytes <= send_cnt_bytes + (CHDR_W/8);
      if (chdr_out_tlast)
        send_cnt_pkts <= send_cnt_pkts + 40'd1;
    end
  end



  wire signed [64:0] occupied_bytes = 
    $signed({1'b0, send_cnt_bytes}) - $signed({1'b0, recv_cnt_bytes});
  wire signed [40:0] occupied_pkts =
    $signed({1'b0, send_cnt_pkts}) - $signed({1'b0, recv_cnt_pkts});






  reg  [3:0] ok_shreg = 4'b1111;
  always @(posedge clk) begin
    if (rst || !fc_enabled) begin
      ok_shreg <= 4'b1111;
    end else begin
      ok_shreg <= {ok_shreg[2:0], (
        (occupied_bytes[40:0] < $signed({1'b0, adj_cap_bytes})) &&
        (occupied_pkts [24:0] < $signed({1'b0, adj_cap_pkts }))
      )};
    end
  end
  wire ok_to_send = ok_shreg[3];


  reg lossy_xport = 1'b0;
  reg [3:0] fc_resync_req_shreg = 4'h0;
  wire fc_resync_req, fc_resync_ack;

  always @(posedge clk) begin
    if (rst || !fc_enabled || !lossy_xport || fc_resync_ack) begin

      accum_bytes <= 40'd0;
      accum_pkts <= 24'd0;
      fc_resync_req_shreg <= 4'b0000;
    end else begin 
      if (chdr_out_tvalid && chdr_out_tready) begin

        accum_bytes <= accum_bytes + (CHDR_W/8);
        if (chdr_out_tlast)
          accum_pkts <= accum_pkts + 24'd1;
      end

      fc_resync_req_shreg <= {fc_resync_req_shreg[2:0],
        (accum_bytes > capacity_bytes) || (accum_pkts > capacity_pkts)};
    end
  end
  assign fc_resync_req = fc_resync_req_shreg[3];





  wire [3:0] msg_i_tdata,  msg_o_tdata;
  wire       msg_i_tvalid, msg_o_tvalid;
  wire       msg_i_tready, msg_o_tready;

  axi_fifo #(.WIDTH(4), .SIZE(1)) msg_fifo_i (
    .clk(clk), .reset(rst), .clear(1'b0),
    .i_tdata(msg_i_tdata), .i_tvalid(msg_i_tvalid), .i_tready(msg_i_tready),
    .o_tdata(msg_o_tdata), .o_tvalid(msg_o_tvalid), .o_tready(msg_o_tready),
    .space(), .occupied()
  );

  localparam [2:0] ST_STRS_HDR   = 3'd0;
  localparam [2:0] ST_STRS_W0    = 3'd1;
  localparam [2:0] ST_STRS_W1    = 3'd2;
  localparam [2:0] ST_STRS_W2    = 3'd3;
  localparam [2:0] ST_STRS_W3    = 3'd4;
  localparam [2:0] ST_STRS_LATCH = 3'd5;
  localparam [2:0] ST_STRS_DROP  = 3'd6;

  reg [2:0]   strs_state = ST_STRS_HDR;
  reg         strs_too_long = 1'b0;
  reg [15:0]  cached_dst_epid = 16'd0;
  reg [255:0] cached_strs_msg;

  always @(posedge clk) begin
    if (rst) begin
      strs_state <= ST_STRS_HDR;
      strs_too_long <= 1'b0;
    end else begin
      case (strs_state)



        ST_STRS_HDR: begin
          if (s_axis_strs_tvalid) begin

            if (chdr_get_pkt_type(s_axis_strs_tdata[63:0]) == CHDR_PKT_TYPE_STRS)
              strs_state <= ST_STRS_W0;
            else
              strs_state <= ST_STRS_DROP;
            strs_too_long <= 1'b0;
          end
        end







        ST_STRS_W0: begin
          if (s_axis_strs_tvalid) begin
            if (CHDR_W == 64) begin
              cached_strs_msg[63:0] <= s_axis_strs_tdata[63:0];
              strs_state <= !s_axis_strs_tlast ? ST_STRS_W1 : ST_STRS_HDR;
            end else if (CHDR_W == 128) begin
              cached_strs_msg[127:0] <= s_axis_strs_tdata[127:0];
              strs_state <= !s_axis_strs_tlast ? ST_STRS_W1 : ST_STRS_HDR;
            end else begin
              cached_strs_msg[255:0] <= s_axis_strs_tdata[255:0];
              strs_state <= ST_STRS_LATCH;
              strs_too_long <= !s_axis_strs_tlast;
            end
          end
        end




        ST_STRS_W1: begin
          if (s_axis_strs_tvalid) begin
            if (CHDR_W == 64) begin
              cached_strs_msg[127:64] <= s_axis_strs_tdata[63:0];
              strs_state <= !s_axis_strs_tlast ? ST_STRS_W2 : ST_STRS_HDR;
            end else begin
              cached_strs_msg[255:128] <= s_axis_strs_tdata[127:0];
              strs_state <= ST_STRS_LATCH;
              strs_too_long <= !s_axis_strs_tlast;
            end
          end
        end




        ST_STRS_W2: begin
          if (s_axis_strs_tvalid) begin
            cached_strs_msg[191:128] <= s_axis_strs_tdata[63:0];
              strs_state <= !s_axis_strs_tlast ? ST_STRS_W3 : ST_STRS_HDR;
          end
        end




        ST_STRS_W3: begin
          if (s_axis_strs_tvalid) begin
            cached_strs_msg[255:192] <= s_axis_strs_tdata[63:0];
            strs_state <= ST_STRS_LATCH;
            strs_too_long <= !s_axis_strs_tlast;
          end
        end




        ST_STRS_LATCH: begin
          capacity_bytes <= chdr256_strs_get_capacity_bytes(cached_strs_msg);
          capacity_pkts  <= chdr256_strs_get_capacity_pkts(cached_strs_msg);
          recv_cnt_bytes <= chdr256_strs_get_xfercnt_bytes(cached_strs_msg);
          recv_cnt_pkts  <= chdr256_strs_get_xfercnt_pkts(cached_strs_msg);
          adj_cap_bytes  <= chdr256_strs_get_capacity_bytes(cached_strs_msg) - 
                            {24'd0, headroom_bytes[15:(CHDR_W_LOG2-3)], {(CHDR_W_LOG2-3){1'b0}}};
          adj_cap_pkts   <= chdr256_strs_get_capacity_pkts(cached_strs_msg) - 
                            {16'd0, headroom_pkts};
          if (msg_i_tready) begin
            strs_state <= strs_too_long ? ST_STRS_DROP : ST_STRS_HDR;
          end
        end



        ST_STRS_DROP: begin
          if (s_axis_strs_tvalid && s_axis_strs_tlast)
            strs_state <= ST_STRS_HDR;
        end
        default: begin

          strs_state <= ST_STRS_HDR;
        end
      endcase
    end
  end

  assign s_axis_strs_tready = (strs_state != ST_STRS_LATCH);

  assign msg_i_tvalid = (strs_state == ST_STRS_LATCH);
  assign msg_i_tdata = (chdr256_strs_get_src_epid(cached_strs_msg) != cached_dst_epid) ? 
    CHDR_STRS_STATUS_CMDERR : chdr256_strs_get_status(cached_strs_msg);






  localparam [2:0] ST_PASS_DATA = 3'd0;
  localparam [2:0] ST_STRC_HDR  = 3'd1;
  localparam [2:0] ST_STRC_W0   = 3'd2;
  localparam [2:0] ST_STRC_W1   = 3'd3;
  localparam [2:0] ST_STRC_WAIT = 3'd4;
  localparam [2:0] ST_INIT_DLY  = 3'd5;

  reg [2:0]   state = ST_PASS_DATA;
  reg         mid_pkt = 1'b0;
  reg [15:0]  data_seq_num = 16'd0;
  reg [15:0]  strc_seq_num = 16'd0;
  reg [2:0]   cfg_delay = 3'd0;

  reg cfg_fc_freq_bytes_nz;
  reg cfg_fc_freq_pkts_nz;

  always @(posedge clk) begin
    if (rst) begin
      state <= ST_PASS_DATA;
      mid_pkt <= 1'b0;
      data_seq_num <= 16'd0;
      strc_seq_num <= 16'd0;
      cfg_pending <= 1'b0;
      cfg_failed <= 1'b0;
      cfg_fc_freq_bytes_nz <= 1'bX;
      cfg_fc_freq_pkts_nz <= 1'bX;
    end else begin

      cfg_fc_freq_bytes_nz <= (cfg_fc_freq_bytes != 0);
      cfg_fc_freq_pkts_nz  <= (cfg_fc_freq_pkts  != 0);

      case (state)







        ST_PASS_DATA: begin

          if (chdr_out_tvalid && chdr_out_tready) begin
            mid_pkt <= !chdr_out_tlast;
            if (chdr_out_tlast)
              data_seq_num <= data_seq_num + 16'd1;
          end

          if (cfg_start) begin

            cfg_pending <= 1'b1;
            cfg_failed <= 1'b0;

            fc_enabled <= 1'b0;

            lossy_xport <= cfg_lossy_xport;
            cached_dst_epid <= cfg_dst_epid;
            headroom_bytes <= cfg_fc_headroom_bytes;
            headroom_pkts <= cfg_fc_headroom_pkts;
          end


          if (cfg_start || cfg_pending || fc_resync_req) begin
            if (mid_pkt) begin
              if (chdr_out_tvalid && chdr_out_tready && chdr_out_tlast)
                state <= ST_STRC_HDR;
            end else begin
              if (!(chdr_out_tvalid && chdr_out_tready))
                state <= ST_STRC_HDR;
            end
          end
        end




        ST_STRC_HDR: begin
          if (chdr_out_tvalid && chdr_out_tready) begin
            state <= ST_STRC_W0;

            strc_seq_num <= strc_seq_num + 16'd1;
          end

          strc_cnt_bytes <= send_cnt_bytes;
        end




        ST_STRC_W0: begin
          if (chdr_out_tvalid && chdr_out_tready)
            if (CHDR_W < 128)
              state <= ST_STRC_W1;
            else
              state <= fc_resync_req ? ST_PASS_DATA : ST_STRC_WAIT;
        end




        ST_STRC_W1: begin
          if (chdr_out_tvalid && chdr_out_tready)
            state <= fc_resync_req ? ST_PASS_DATA : ST_STRC_WAIT;
        end




        ST_STRC_WAIT: begin

          if (msg_o_tvalid) begin
            if (msg_o_tdata == CHDR_STRS_STATUS_OKAY) begin
              state <= ST_INIT_DLY;
              cfg_delay <= 3'd4;
              data_seq_num <= 16'd0;
              strc_seq_num <= 16'd0;


              fc_enabled <= cfg_fc_freq_bytes_nz || cfg_fc_freq_pkts_nz;
            end else begin
              state <= ST_PASS_DATA;
              cfg_failed <= 1'b1;
              cfg_pending <= 1'b0;
            end
          end
        end




        ST_INIT_DLY: begin
          if (cfg_delay == 3'd0) begin
            state <= ST_PASS_DATA;
            cfg_pending <= 1'b0;
          end else begin
            cfg_delay <= cfg_delay - 3'd1;
          end
        end


        default: begin
          state <= ST_PASS_DATA;
        end
      endcase
    end
  end


  wire [CHDR_W-1:0] data_header;
  assign data_header[63:0] = chdr_set_seq_num(
    chdr_set_dst_epid(s_axis_data_tdata[63:0], cached_dst_epid),
    data_seq_num);
  generate if (CHDR_W > 64)
    assign data_header[CHDR_W-1:64] = s_axis_data_tdata[CHDR_W-1:64];
  endgenerate


  wire [CHDR_W-1:0] strc_header;
  assign strc_header[63:0] = chdr_build_header(
6'd0,1'b0,1'b0, CHDR_PKT_TYPE_STRC, CHDR_NO_MDATA,
    strc_seq_num, 16'd16+(CHDR_W/8), cached_dst_epid);
  generate if (CHDR_W > 64)
    assign strc_header[CHDR_W-1:64] = {(CHDR_W-64){1'b0}};
  endgenerate


  wire [127:0] strc_init_payload = chdr128_strc_build(
    {24'h0, cfg_fc_freq_bytes}, {16'h0, cfg_fc_freq_pkts},
4'h0, CHDR_STRC_OPCODE_INIT, cfg_this_epid);
  wire [127:0] strc_resync_payload = chdr128_strc_build(
    strc_cnt_bytes, send_cnt_pkts,
4'h0, CHDR_STRC_OPCODE_RESYNC, cfg_this_epid);
  wire [127:0] strc_payload = fc_resync_req ? strc_resync_payload : strc_init_payload;

  always @(*) begin
    case (state)
      ST_PASS_DATA: begin
        chdr_out_tdata  = mid_pkt ? s_axis_data_tdata : data_header;
        chdr_out_tlast  = s_axis_data_tlast;
        chdr_out_tvalid = s_axis_data_tvalid && ok_to_send;
      end
      ST_STRC_HDR: begin
        chdr_out_tdata  = strc_header;
        chdr_out_tlast  = 1'b0;
        chdr_out_tvalid = ok_to_send;
      end
      ST_STRC_W0: begin
        chdr_out_tdata  = strc_payload;
        chdr_out_tlast  = (CHDR_W < 128) ? 1'b0 : 1'b1;
        chdr_out_tvalid = ok_to_send;
      end
      ST_STRC_W1: begin

        chdr_out_tdata  = strc_payload[127:64];
        chdr_out_tlast  = 1'b1;
        chdr_out_tvalid = ok_to_send;
      end
      default: begin
        chdr_out_tdata  = {CHDR_W{1'b0}};
        chdr_out_tlast  = 1'b0;
        chdr_out_tvalid = 1'b0;
      end
    endcase
  end
  assign s_axis_data_tready = (state == ST_PASS_DATA) && chdr_out_tready && ok_to_send;




  assign msg_o_tready = msg_o_tvalid && (state == ST_PASS_DATA || state == ST_STRC_WAIT);


  assign fc_resync_ack = fc_resync_req && (state == ST_STRC_W1 || state == ST_STRC_W0) && 
                         chdr_out_tvalid && chdr_out_tready && chdr_out_tlast;





  wire runtime_err_stb = msg_o_tvalid && msg_o_tready && (state == ST_PASS_DATA);
  assign seq_err_stb = runtime_err_stb && (msg_o_tdata == CHDR_STRS_STATUS_SEQERR);
  assign data_err_stb = runtime_err_stb && (msg_o_tdata == CHDR_STRS_STATUS_DATAERR);
  assign route_err_stb = runtime_err_stb && (msg_o_tdata == CHDR_STRS_STATUS_RTERR);

  always @(posedge clk) begin
    if (rst || !fc_enabled) begin
      seq_err_cnt <= 32'd0;
      data_err_cnt <= 32'd0;
      route_err_cnt <= 32'd0;
    end else begin
      if (seq_err_stb)
        seq_err_cnt <= seq_err_cnt + 32'd1;
      if (data_err_stb)
        data_err_cnt <= data_err_cnt + 32'd1;
      if (route_err_stb)
        route_err_cnt <= route_err_cnt + 32'd1;
    end
  end

endmodule