module accel_width_conv # (
  parameter DATA_IN_WIDTH  = 128,
  parameter DATA_OUT_WIDTH = 8,
  parameter STRB_OUT_WIDTH = DATA_OUT_WIDTH/8,
  // TUSER is offset of last valid byte
  parameter USER_WIDTH     = $clog2(DATA_IN_WIDTH/8)
) (
  input  wire                      clk,
  input  wire                      rst,

  // Read data input
  input  wire [DATA_IN_WIDTH-1:0]  s_axis_tdata,
  input  wire [USER_WIDTH-1:0]     s_axis_tuser,
  input  wire                      s_axis_tlast,
  input  wire                      s_axis_tvalid,
  output wire                      s_axis_tready,

  // Read data output
  output reg  [DATA_OUT_WIDTH-1:0] m_axis_tdata,
  output reg  [STRB_OUT_WIDTH-1:0] m_axis_tkeep,
  output reg                       m_axis_tlast,
  output reg                       m_axis_tvalid,
  input  wire                      m_axis_tready
);

    localparam SKIP_BITS = $clog2(DATA_OUT_WIDTH/8);
    localparam PTR_WIDTH = USER_WIDTH-SKIP_BITS;

    reg  [PTR_WIDTH-1:0]      rd_ptr;
    wire [STRB_OUT_WIDTH-1:0] strobe;

    // Detecting last chunk and setting strobe
    wire last_chunk = (rd_ptr==s_axis_tuser[USER_WIDTH-1:SKIP_BITS]);
    if (SKIP_BITS==0)
      assign strobe = 1'b1;
    else
      assign strobe = ~({{STRB_OUT_WIDTH-1{1'b1}},1'b0} << s_axis_tuser[SKIP_BITS-1:0]);

    // out_ready works with accel always asserting tready or
    // accepting tvalid in same cycle
    wire out_ready  = !m_axis_tvalid || m_axis_tready;
    assign s_axis_tready = out_ready && last_chunk;

    always @ (posedge clk) begin
      // Since data is coming from a FIFO, tvalid drop without
      // tready assertion means there was a stop signal and
      // rd_ptr needs to be reset. In normal mode and no
      // tvalid it keeps the rd_ptr to be zero.
      if (!s_axis_tvalid)
        rd_ptr <= {PTR_WIDTH{1'b0}};
      else if (out_ready) begin
        if (last_chunk)
          rd_ptr <= {PTR_WIDTH{1'b0}};
        else
          rd_ptr <= rd_ptr + 1;
      end

      if (rst)
        rd_ptr <= {PTR_WIDTH{1'b0}};
    end

    // Register the outputs
    always @ (posedge clk) begin
      m_axis_tdata   <= s_axis_tdata[rd_ptr*DATA_OUT_WIDTH+:DATA_OUT_WIDTH];
      m_axis_tkeep   <= (s_axis_tlast && last_chunk) ?
                         strobe : {STRB_OUT_WIDTH{1'b1}};
      m_axis_tlast   <= s_axis_tlast && last_chunk;
      m_axis_tvalid  <= s_axis_tvalid;
    end

endmodule