module NV_NVDLA_SDP_MRDMA_ig (
   nvdla_core_clk
  ,nvdla_core_rstn
  ,op_load
  ,ig2cq_pd
  ,ig2cq_pvld
  ,ig2cq_prdy
  ,dma_rd_req_ram_type
  ,dma_rd_req_pd
  ,dma_rd_req_vld
  ,dma_rd_req_rdy
  ,reg2dp_batch_number
  ,reg2dp_channel
  ,reg2dp_height
  ,reg2dp_width
  ,reg2dp_in_precision
  ,reg2dp_proc_precision
  ,reg2dp_src_base_addr_high
  ,reg2dp_src_base_addr_low
  ,reg2dp_src_line_stride
  ,reg2dp_src_ram_type
  ,reg2dp_src_surface_stride
  ,reg2dp_perf_dma_en
  ,dp2reg_mrdma_stall
  );
input nvdla_core_clk;
input nvdla_core_rstn;
input op_load;
output [13:0] ig2cq_pd;
output ig2cq_pvld;
input ig2cq_prdy;
output dma_rd_req_ram_type;
output dma_rd_req_vld;
input dma_rd_req_rdy;
output [47 -1:0] dma_rd_req_pd;
input reg2dp_src_ram_type;
input [4:0] reg2dp_batch_number;
input [12:0] reg2dp_channel;
input [12:0] reg2dp_height;
input [12:0] reg2dp_width;
input [1:0] reg2dp_in_precision;
input [1:0] reg2dp_proc_precision;
input [31:0] reg2dp_src_base_addr_high;
input [31-3:0] reg2dp_src_base_addr_low;
input [31-3:0] reg2dp_src_line_stride;
input [31-3:0] reg2dp_src_surface_stride;
input reg2dp_perf_dma_en;
output [31:0] dp2reg_mrdma_stall;
reg cmd_process;
wire cmd_accept;
wire cmd_done;
wire [14:0] ig2eg_size;
wire ig2eg_cube_end;
wire cfg_di_int16;
wire cfg_di_int8;
wire cfg_do_int8;
wire cfg_mode_1x1_pack;
wire cfg_mode_multi_batch;
wire [31-3:0] cfg_line_stride;
wire [31-3:0] cfg_surf_stride;
wire [32 -3 -1:0] cfg_base_addr;
reg [32 -3 -1:0] base_addr_elem;
reg [32 -3 -1:0] base_addr_line;
reg [32 -3 -1:0] base_addr_surf;
reg [32 -3 -1:0] base_addr_width;
reg mon_base_addr_surf_c;
reg mon_base_addr_width_c;
reg mon_base_addr_elem_c;
reg mon_base_addr_line_c;
reg [4:0] count_b;
reg [13-3:0] count_c;
reg [12:0] count_h;
reg count_e;
reg [9:0] count_w;
wire is_batch_end;
wire is_cube_end;
wire is_elem_end;
wire is_last_b;
wire is_last_c;
wire is_last_e;
wire is_last_h;
wire is_last_w;
wire is_line_end;
wire is_surf_end;
wire [13-3:0] mode_1x1_req_size;
reg [14:0] dma_req_size;
wire [32 -3 -1:0] req_addr;
wire [32 -1:0] dma_req_addr;
wire [4:0] size_of_batch;
wire size_of_elem;
wire [9:0] size_of_width;
reg [13-3:0] size_of_surf;
reg mrdma_rd_stall_cnt_cen;
wire mrdma_rd_stall_cnt_clr;
wire mrdma_rd_stall_cnt_inc;
reg stl_adv;
reg [31:0] stl_cnt_cur;
reg [33:0] stl_cnt_dec;
reg [33:0] stl_cnt_ext;
reg [33:0] stl_cnt_inc;
reg [33:0] stl_cnt_mod;
reg [33:0] stl_cnt_new;
reg [33:0] stl_cnt_nxt;
reg [31:0] dp2reg_mrdma_stall;
wire dp2reg_mrdma_stall_dec;
assign cmd_done = cmd_accept & is_cube_end;
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    cmd_process <= 1'b0;
  end else begin
    if (op_load) begin
        cmd_process <= 1'b1;
    end else if (cmd_done) begin
        cmd_process <= 1'b0;
    end
  end
end
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass disable_block NoWidthInBasedNum-ML
// spyglass disable_block STARC-2.10.3.2a
// spyglass disable_block STARC05-2.1.3.1
// spyglass disable_block STARC-2.1.4.6
// spyglass disable_block W116
// spyglass disable_block W154
// spyglass disable_block W239
// spyglass disable_block W362
// spyglass disable_block WRN_58
// spyglass disable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
`ifdef ASSERT_ON
`ifdef FV_ASSERT_ON
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef SYNTHESIS
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef ASSERT_OFF_RESET_IS_X
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b0 : nvdla_core_rstn)
`else
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b1 : nvdla_core_rstn)
`endif // ASSERT_OFF_RESET_IS_X
`endif // SYNTHESIS
`endif // FV_ASSERT_ON
// VCS coverage off
  nv_assert_never #(0,0,"SDP-RDMA: get an op-done without starting the op") zzz_assert_never_1x (nvdla_core_clk, `ASSERT_RESET, !cmd_process && cmd_done); // spyglass disable W504 SelfDeterminedExpr-ML 
// VCS coverage on
`undef ASSERT_RESET
`endif // ASSERT_ON
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass enable_block NoWidthInBasedNum-ML
// spyglass enable_block STARC-2.10.3.2a
// spyglass enable_block STARC05-2.1.3.1
// spyglass enable_block STARC-2.1.4.6
// spyglass enable_block W116
// spyglass enable_block W154
// spyglass enable_block W239
// spyglass enable_block W362
// spyglass enable_block WRN_58
// spyglass enable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
//==============
// Address catenate and offset calc
//==============
//==============
// CFG value calculation
//==============
assign cfg_base_addr = reg2dp_src_base_addr_low;
assign cfg_line_stride = {reg2dp_src_line_stride};
assign cfg_surf_stride = {reg2dp_src_surface_stride};
assign cfg_di_int8 = reg2dp_in_precision == 0 ;
assign cfg_di_int16 = reg2dp_in_precision == 1 ;
assign cfg_do_int8 = reg2dp_proc_precision == 0 ;
assign cfg_mode_1x1_pack = (reg2dp_width==0) & (reg2dp_height==0);
assign cfg_mode_multi_batch = reg2dp_batch_number!=0;
//==============
// CHANNEL Direction
// calculate how many 32x8 blocks in channel direction
//==============
always @(
  reg2dp_channel
  or cfg_di_int8
  or cfg_di_int16
  ) begin
    if (cfg_di_int8) begin
        size_of_surf = {1'b0,reg2dp_channel[12:3]};
    end else if (cfg_di_int16) begin
        size_of_surf = reg2dp_channel[12:3 -1];
    end else begin
        size_of_surf = reg2dp_channel[12:3 -1];
    end
end
//=================================================
// Cube Shape
//=================================================
assign is_batch_end = is_last_b;
assign is_elem_end = is_batch_end;
assign is_line_end = is_elem_end ;
assign is_surf_end = is_line_end & ( (cfg_mode_1x1_pack) || (is_last_h) );
assign is_cube_end = is_surf_end & ( (cfg_mode_1x1_pack) || (is_last_c) );
assign is_last_b = 1'b1;
//==============
// CHANNEL Count:
//==============
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    count_c <= {(14-3){1'b0}};
  end else begin
    if (cmd_accept) begin
        if (is_cube_end) begin
            count_c <= 0;
        end else if (is_surf_end) begin
            count_c <= count_c + 1'b1;
        end
    end
  end
end
assign is_last_c = (count_c==size_of_surf);
//==============
// LINE Count:
//==============
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    count_h <= {13{1'b0}};
  end else begin
    if (cmd_accept) begin
        if (is_surf_end) begin
            count_h <= 0;
        end else if (is_line_end) begin
            count_h <= count_h + 1'b1;
        end
    end
  end
end
assign is_last_h = (count_h==reg2dp_height);
//==========================================
// DMA Req : ADDR PREPARE
//==========================================
// LINE
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    base_addr_line <= {(32 -3){1'b0}};
    mon_base_addr_line_c <= 1'b0;
  end else begin
    if (op_load) begin
        base_addr_line <= cfg_base_addr;
    end else if (cmd_accept) begin
        begin
            if (is_surf_end) begin
                {mon_base_addr_line_c,base_addr_line} <= base_addr_surf + cfg_surf_stride;
            end else if (is_line_end) begin
                {mon_base_addr_line_c,base_addr_line} <= base_addr_line + cfg_line_stride;
            end
        end
    end
  end
end
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass disable_block NoWidthInBasedNum-ML
// spyglass disable_block STARC-2.10.3.2a
// spyglass disable_block STARC05-2.1.3.1
// spyglass disable_block STARC-2.1.4.6
// spyglass disable_block W116
// spyglass disable_block W154
// spyglass disable_block W239
// spyglass disable_block W362
// spyglass disable_block WRN_58
// spyglass disable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
`ifdef ASSERT_ON
`ifdef FV_ASSERT_ON
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef SYNTHESIS
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef ASSERT_OFF_RESET_IS_X
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b0 : nvdla_core_rstn)
`else
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b1 : nvdla_core_rstn)
`endif // ASSERT_OFF_RESET_IS_X
`endif // SYNTHESIS
`endif // FV_ASSERT_ON
// VCS coverage off
  nv_assert_never #(0,0,"MRDMA: no overflow is allowed") zzz_assert_never_4x (nvdla_core_clk, `ASSERT_RESET, mon_base_addr_line_c); // spyglass disable W504 SelfDeterminedExpr-ML 
// VCS coverage on
`undef ASSERT_RESET
`endif // ASSERT_ON
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass enable_block NoWidthInBasedNum-ML
// spyglass enable_block STARC-2.10.3.2a
// spyglass enable_block STARC05-2.1.3.1
// spyglass enable_block STARC-2.1.4.6
// spyglass enable_block W116
// spyglass enable_block W154
// spyglass enable_block W239
// spyglass enable_block W362
// spyglass enable_block WRN_58
// spyglass enable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
// SURF
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    base_addr_surf <= {(32 -3){1'b0}};
    mon_base_addr_surf_c <= 1'b0;
  end else begin
    if (op_load) begin
        base_addr_surf <= cfg_base_addr;
    end else if (cmd_accept) begin
        begin
            if (is_surf_end) begin
                {mon_base_addr_surf_c,base_addr_surf} <= base_addr_surf + cfg_surf_stride;
            end
        end
    end
  end
end
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass disable_block NoWidthInBasedNum-ML
// spyglass disable_block STARC-2.10.3.2a
// spyglass disable_block STARC05-2.1.3.1
// spyglass disable_block STARC-2.1.4.6
// spyglass disable_block W116
// spyglass disable_block W154
// spyglass disable_block W239
// spyglass disable_block W362
// spyglass disable_block WRN_58
// spyglass disable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
`ifdef ASSERT_ON
`ifdef FV_ASSERT_ON
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef SYNTHESIS
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef ASSERT_OFF_RESET_IS_X
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b0 : nvdla_core_rstn)
`else
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b1 : nvdla_core_rstn)
`endif // ASSERT_OFF_RESET_IS_X
`endif // SYNTHESIS
`endif // FV_ASSERT_ON
// VCS coverage off
  nv_assert_never #(0,0,"MRDMA: no overflow is allowed") zzz_assert_never_5x (nvdla_core_clk, `ASSERT_RESET, mon_base_addr_surf_c); // spyglass disable W504 SelfDeterminedExpr-ML 
// VCS coverage on
`undef ASSERT_RESET
`endif // ASSERT_ON
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass enable_block NoWidthInBasedNum-ML
// spyglass enable_block STARC-2.10.3.2a
// spyglass enable_block STARC05-2.1.3.1
// spyglass enable_block STARC-2.1.4.6
// spyglass enable_block W116
// spyglass enable_block W154
// spyglass enable_block W239
// spyglass enable_block W362
// spyglass enable_block WRN_58
// spyglass enable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
//==========================================
// DMA Req : Addr : Generation
//==========================================
assign req_addr = base_addr_line;
assign dma_req_addr = {req_addr,{3{1'b0}}};
//==============
// DMA Req : SIZE : Generation
//==============
// in 1x1_pack mode, only send one request out
assign mode_1x1_req_size = size_of_surf;
always @(
  cfg_mode_1x1_pack
  or mode_1x1_req_size
  or reg2dp_width
  ) begin
    if (cfg_mode_1x1_pack) begin
        dma_req_size = {{(3 +1){1'b0}}, mode_1x1_req_size};
    end
    else begin
        dma_req_size = {{2{1'b0}}, reg2dp_width};
    end
end
assign ig2eg_size = dma_req_size;
assign ig2eg_cube_end = is_cube_end;
assign ig2cq_pd[12:0] = ig2eg_size[12:0];
assign ig2cq_pd[13] = ig2eg_cube_end ;
assign ig2cq_pvld = cmd_process & dma_rd_req_rdy;
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass disable_block NoWidthInBasedNum-ML
// spyglass disable_block STARC-2.10.3.2a
// spyglass disable_block STARC05-2.1.3.1
// spyglass disable_block STARC-2.1.4.6
// spyglass disable_block W116
// spyglass disable_block W154
// spyglass disable_block W239
// spyglass disable_block W362
// spyglass disable_block WRN_58
// spyglass disable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
`ifdef ASSERT_ON
`ifdef FV_ASSERT_ON
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef SYNTHESIS
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef ASSERT_OFF_RESET_IS_X
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b0 : nvdla_core_rstn)
`else
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b1 : nvdla_core_rstn)
`endif // ASSERT_OFF_RESET_IS_X
`endif // SYNTHESIS
`endif // FV_ASSERT_ON
// VCS coverage off
  nv_assert_never #(0,0,"SDP-RDMA: CQ and DMA should accept or reject together") zzz_assert_never_6x (nvdla_core_clk, `ASSERT_RESET, (ig2cq_pvld & ig2cq_prdy) ^ (dma_rd_req_vld & dma_rd_req_rdy)); // spyglass disable W504 SelfDeterminedExpr-ML 
// VCS coverage on
`undef ASSERT_RESET
`endif // ASSERT_ON
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass enable_block NoWidthInBasedNum-ML
// spyglass enable_block STARC-2.10.3.2a
// spyglass enable_block STARC05-2.1.3.1
// spyglass enable_block STARC-2.1.4.6
// spyglass enable_block W116
// spyglass enable_block W154
// spyglass enable_block W239
// spyglass enable_block W362
// spyglass enable_block WRN_58
// spyglass enable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
//==============
// DMA Req : PIPE
//==============
// VALID: clamp when when cq is not ready
assign dma_rd_req_vld = cmd_process & ig2cq_prdy;
assign dma_rd_req_pd[32 -1:0] = dma_req_addr[32 -1:0];
assign dma_rd_req_pd[47 -1:32] = dma_req_size[14:0];
assign dma_rd_req_ram_type = reg2dp_src_ram_type;
// Accept
assign cmd_accept = dma_rd_req_vld & dma_rd_req_rdy;
//==============
// PERF STATISTIC
//==============
assign mrdma_rd_stall_cnt_inc = dma_rd_req_vld & !dma_rd_req_rdy;
assign mrdma_rd_stall_cnt_clr = op_load;
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    mrdma_rd_stall_cnt_cen <= 1'b0;
  end else begin
  if ((op_load) == 1'b1) begin
    mrdma_rd_stall_cnt_cen <= reg2dp_perf_dma_en;
//end else if ((op_load) == 1'b0) begin
//end else begin
// mrdma_rd_stall_cnt_cen <= 1'bx;
  end
  end
end
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass disable_block NoWidthInBasedNum-ML
// spyglass disable_block STARC-2.10.3.2a
// spyglass disable_block STARC05-2.1.3.1
// spyglass disable_block STARC-2.1.4.6
// spyglass disable_block W116
// spyglass disable_block W154
// spyglass disable_block W239
// spyglass disable_block W362
// spyglass disable_block WRN_58
// spyglass disable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
`ifdef ASSERT_ON
`ifdef FV_ASSERT_ON
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef SYNTHESIS
`define ASSERT_RESET nvdla_core_rstn
`else
`ifdef ASSERT_OFF_RESET_IS_X
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b0 : nvdla_core_rstn)
`else
`define ASSERT_RESET ((1'bx === nvdla_core_rstn) ? 1'b1 : nvdla_core_rstn)
`endif // ASSERT_OFF_RESET_IS_X
`endif // SYNTHESIS
`endif // FV_ASSERT_ON
`ifndef SYNTHESIS
// VCS coverage off
  nv_assert_no_x #(0,1,0,"No X's allowed on control signals") zzz_assert_no_x_7x (nvdla_core_clk, `ASSERT_RESET, 1'd1, (^(op_load))); // spyglass disable W504 SelfDeterminedExpr-ML 
// VCS coverage on
`endif
`undef ASSERT_RESET
`endif // ASSERT_ON
`ifdef SPYGLASS_ASSERT_ON
`else
// spyglass enable_block NoWidthInBasedNum-ML
// spyglass enable_block STARC-2.10.3.2a
// spyglass enable_block STARC05-2.1.3.1
// spyglass enable_block STARC-2.1.4.6
// spyglass enable_block W116
// spyglass enable_block W154
// spyglass enable_block W239
// spyglass enable_block W362
// spyglass enable_block WRN_58
// spyglass enable_block WRN_61
`endif // SPYGLASS_ASSERT_ON
assign dp2reg_mrdma_stall_dec = 1'b0;
// stl adv logic
always @(
  mrdma_rd_stall_cnt_inc
  or dp2reg_mrdma_stall_dec
  ) begin
  stl_adv = mrdma_rd_stall_cnt_inc ^ dp2reg_mrdma_stall_dec;
end
// stl cnt logic
always @(
  stl_cnt_cur
  or mrdma_rd_stall_cnt_inc
  or dp2reg_mrdma_stall_dec
  or stl_adv
  or mrdma_rd_stall_cnt_clr
  ) begin
  stl_cnt_ext[33:0] = {1'b0, 1'b0, stl_cnt_cur};
  stl_cnt_inc[33:0] = stl_cnt_cur + 1'b1; // spyglass disable W164b
  stl_cnt_dec[33:0] = stl_cnt_cur - 1'b1; // spyglass disable W164b
  stl_cnt_mod[33:0] = (mrdma_rd_stall_cnt_inc && !dp2reg_mrdma_stall_dec)? stl_cnt_inc : (!mrdma_rd_stall_cnt_inc && dp2reg_mrdma_stall_dec)? stl_cnt_dec : stl_cnt_ext;
  stl_cnt_new[33:0] = (stl_adv)? stl_cnt_mod[33:0] : stl_cnt_ext[33:0];
  stl_cnt_nxt[33:0] = (mrdma_rd_stall_cnt_clr)? 34'd0 : stl_cnt_new[33:0];
end
// stl flops
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    stl_cnt_cur[31:0] <= 0;
  end else begin
  if (mrdma_rd_stall_cnt_cen) begin
  stl_cnt_cur[31:0] <= stl_cnt_nxt[31:0];
  end
  end
end
// stl output logic
always @(
  stl_cnt_cur
  ) begin
  dp2reg_mrdma_stall[31:0] = stl_cnt_cur[31:0];
end
//==============
// FUNCTION POINT
//VCS coverage off
`ifndef DISABLE_FUNCPOINT
  `ifdef ENABLE_FUNCPOINT
    reg funcpoint_cover_off;
    initial begin
        if ( $test$plusargs( "cover_off" ) ) begin
            funcpoint_cover_off = 1'b1;
        end else begin
            funcpoint_cover_off = 1'b0;
        end
    end
    property sdp_mrdma_ig__access_CVIF__0_cov;
        disable iff((nvdla_core_rstn !== 1) || funcpoint_cover_off)
        @(posedge nvdla_core_clk)
        ((dma_rd_req_vld) && nvdla_core_rstn) |-> (dma_rd_req_ram_type==0);
    endproperty
// Cover 0 : "dma_rd_req_ram_type==0"
    FUNCPOINT_sdp_mrdma_ig__access_CVIF__0_COV : cover property (sdp_mrdma_ig__access_CVIF__0_cov);
  `endif
`endif
//VCS coverage on
//VCS coverage off
`ifndef DISABLE_FUNCPOINT
  `ifdef ENABLE_FUNCPOINT
    property sdp_mrdma_ig__access_MCIF__1_cov;
        disable iff((nvdla_core_rstn !== 1) || funcpoint_cover_off)
        @(posedge nvdla_core_clk)
        ((dma_rd_req_vld) && nvdla_core_rstn) |-> (dma_rd_req_ram_type==1);
    endproperty
// Cover 1 : "dma_rd_req_ram_type==1"
    FUNCPOINT_sdp_mrdma_ig__access_MCIF__1_COV : cover property (sdp_mrdma_ig__access_MCIF__1_cov);
  `endif
`endif
//VCS coverage on
endmodule // NV_NVDLA_SDP_MRDMA_ig