module axi_mcb_wrap_cmd #
(
///////////////////////////////////////////////////////////////////////////////
// Parameter Definitions
///////////////////////////////////////////////////////////////////////////////
                    // Width of AxADDR
                    // Range: 32.
  parameter integer C_AXI_ADDR_WIDTH            = 32, 
                    // Width of cmd_byte_addr
                    // Range: 30
  parameter integer C_MCB_ADDR_WIDTH            = 30,
                    // Width of AXI xDATA and MCB xx_data
                    // Range: 32, 64, 128.
  parameter integer C_DATA_WIDTH                = 32,
                    // Register CMD_BL_SECOND for better timing.  Does not add
                    // any latency.
  parameter integer C_PL_CMD_BL_SECOND        = 1
)
(
///////////////////////////////////////////////////////////////////////////////
// Port Declarations     
///////////////////////////////////////////////////////////////////////////////
  input  wire                                 clk           , 
  input  wire                                 reset         , 
  input  wire [C_AXI_ADDR_WIDTH-1:0]          axaddr        , 
  input  wire [7:0]                           axlen         , 
  input  wire [2:0]                           axsize        , 
  // axhandshake = axvalid & axready
  input  wire                                 axhandshake   , 
  output wire [5:0]                           cmd_bl        , 
  output wire [C_MCB_ADDR_WIDTH-1:0]          cmd_byte_addr , 

  // Connections to/from fsm module
  // signal to increment to the next mcb transaction 
  input  wire                                 next_cmd      , 
  // signal to the fsm there is another transaction required
  output wire                                 next_pending 

);
////////////////////////////////////////////////////////////////////////////////
// Wire and register declarations
////////////////////////////////////////////////////////////////////////////////
reg                         sel_first;
wire [C_MCB_ADDR_WIDTH-1:0] axaddr_i;
wire [3:0]                  axlen_i;
wire [C_MCB_ADDR_WIDTH-1:0] wrap_boundary_axaddr;
wire [3:0]                  axaddr_offset;
wire [3:0]                  cmd_bl_i;
wire [3:0]                  cmd_bl_first;
wire [3:0]                  cmd_bl_second;
wire [3:0]                  cmd_bl_second_i;
wire [3:0]                  cmd_bl_second_ns;
wire                        next_pending_ns;
reg                         next_pending_r;

////////////////////////////////////////////////////////////////////////////////
// BEGIN RTL
////////////////////////////////////////////////////////////////////////////////
assign cmd_byte_addr = (sel_first) ? axaddr_i : wrap_boundary_axaddr;
assign axaddr_i = axaddr[0 +: C_MCB_ADDR_WIDTH];
assign axlen_i = axlen[3:0];
// Mask bits based on transaction length to get wrap boundary low address
assign wrap_boundary_axaddr = axaddr_i & ~(axlen_i << axsize);

// Offset used to calculate the length of each transaction
assign axaddr_offset = axaddr_i[axsize +: 4] & axlen_i;
// burst length will never exceed 16 beats, add zeros to msb
assign cmd_bl = {2'b0, cmd_bl_i};
assign cmd_bl_i = (sel_first) ? cmd_bl_first : cmd_bl_second;
// Equations for calculating the number of beats.
assign cmd_bl_first = axlen_i & ~axaddr_offset;
assign cmd_bl_second    = cmd_bl_second_i;
assign cmd_bl_second_ns = axaddr_offset - 1'b1;

generate
if (C_PL_CMD_BL_SECOND) begin : PL_CMD_BL_SECOND
  reg  [3:0]                  cmd_bl_second_r;

  always @(posedge clk) begin
    cmd_bl_second_r <= cmd_bl_second_ns;
  end

  assign cmd_bl_second_i = cmd_bl_second_r;
end else begin : NO_PL_CMD_BL_SECOND
  assign cmd_bl_second_i = cmd_bl_second_ns;
end
endgenerate

assign next_pending_ns = ((axaddr_offset > 4'b0000) & sel_first) & ~next_cmd;

always @(posedge clk) begin
  next_pending_r <= next_pending_ns;
end
// Assign output
assign next_pending = next_pending_r;

// Indicates if we are on the first transaction of a mcb translation with more
// than 1 transaction.
always @(posedge clk) begin
  if (reset | axhandshake) begin
    sel_first <= 1'b1;
  end else if (next_cmd) begin
    sel_first <= 1'b0;
  end
end

endmodule