module NV_NVDLA_SDP_cmux (
   nvdla_core_clk //|< i
  ,nvdla_core_rstn //|< i
  ,cacc2sdp_pd //|< i
  ,cacc2sdp_valid //|< i
  ,op_en_load //|< i
  ,reg2dp_flying_mode //|< i
  ,reg2dp_nan_to_zero //|< i
  ,reg2dp_proc_precision //|< i
  ,sdp_cmux2dp_ready //|< i
  ,sdp_mrdma2cmux_pd //|< i
  ,sdp_mrdma2cmux_valid //|< i
  ,cacc2sdp_ready //|> o
  ,sdp_cmux2dp_pd //|> o
  ,sdp_cmux2dp_valid //|> o
  ,sdp_mrdma2cmux_ready //|> o
  );
//
// NV_NVDLA_SDP_cmux_ports.v
//
input nvdla_core_clk;
input nvdla_core_rstn;
input cacc2sdp_valid; /* data valid */
output cacc2sdp_ready; /* data return handshake */
input [32*16 +1:0] cacc2sdp_pd;
input sdp_mrdma2cmux_valid; /* data valid */
output sdp_mrdma2cmux_ready; /* data return handshake */
input [32*16 +1:0] sdp_mrdma2cmux_pd;
output sdp_cmux2dp_valid;
input sdp_cmux2dp_ready;
output [32*16 -1:0] sdp_cmux2dp_pd;
input reg2dp_flying_mode;
input reg2dp_nan_to_zero;
input [1:0] reg2dp_proc_precision;
input op_en_load;
reg cfg_flying_mode_on;
reg cfg_proc_precision;
reg cmux_in_en;
wire cacc_rdy;
wire cacc_vld;
wire [32*16 +1:0] cacc_pd;
wire [32*16 +1:0] cmux_pd;
wire cmux_pd_batch_end;
wire cmux_pd_layer_end;
wire cmux_pd_flush_batch_end_NC;
wire [32*16 -1:0] cmux_pd_flush_data;
wire cmux2dp_prdy;
wire cmux2dp_pvld;
wire [32*16 -1:0] cmux2dp_pd;
//=======================
// CFG
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    cfg_flying_mode_on <= 1'b0;
  end else begin
  cfg_flying_mode_on <= reg2dp_flying_mode == 1'h1;
  end
end
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    cfg_proc_precision <= 1'b0;
  end else begin
  cfg_proc_precision <= reg2dp_proc_precision == 2'h2;
  end
end
NV_NVDLA_SDP_CMUX_pipe_p1 pipe_p1 (
   .nvdla_core_clk (nvdla_core_clk) //|< i
  ,.nvdla_core_rstn (nvdla_core_rstn) //|< i
  ,.cacc2sdp_pd (cacc2sdp_pd[32*16 +1:0]) //|< i
  ,.cacc2sdp_valid (cacc2sdp_valid) //|< i
  ,.cacc_rdy (cacc_rdy) //|< w
  ,.cacc2sdp_ready (cacc2sdp_ready) //|> o
  ,.cacc_pd (cacc_pd[32*16 +1:0]) //|> w
  ,.cacc_vld (cacc_vld) //|> w
  );
assign cmux2dp_pvld = cmux_in_en & ((cfg_flying_mode_on) ? cacc_vld : sdp_mrdma2cmux_valid);
assign cacc_rdy = cmux_in_en & cfg_flying_mode_on & cmux2dp_prdy;
assign sdp_mrdma2cmux_ready = cmux_in_en & (!cfg_flying_mode_on) & cmux2dp_prdy;
//===========================================
// Layer Switch
//===========================================
assign cmux_pd = (cfg_flying_mode_on) ? cacc_pd : sdp_mrdma2cmux_pd;
assign cmux_pd_batch_end = cmux_pd[32*16];
assign cmux_pd_layer_end = cmux_pd[32*16 +1];
assign cmux_pd_flush_batch_end_NC = cmux_pd_batch_end;
always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin
  if (!nvdla_core_rstn) begin
    cmux_in_en <= 1'b0;
  end else begin
    if (op_en_load) begin
       cmux_in_en <= 1'b1;
    end else if (cmux_pd_layer_end && cmux2dp_pvld && cmux2dp_prdy) begin
       cmux_in_en <= 1'b0;
    end
  end
end
assign cmux2dp_pd[32*16 -1:0] = cmux_pd[32*16 -1:0];
NV_NVDLA_SDP_CMUX_pipe_p2 pipe_p2 (
   .nvdla_core_clk (nvdla_core_clk) //|< i
  ,.nvdla_core_rstn (nvdla_core_rstn) //|< i
  ,.cmux2dp_pd (cmux2dp_pd[32*16 -1:0]) //|< w
  ,.cmux2dp_pvld (cmux2dp_pvld) //|< w
  ,.sdp_cmux2dp_ready (sdp_cmux2dp_ready) //|< i
  ,.cmux2dp_prdy (cmux2dp_prdy) //|> w
  ,.sdp_cmux2dp_pd (sdp_cmux2dp_pd[32*16 -1:0]) //|> o
  ,.sdp_cmux2dp_valid (sdp_cmux2dp_valid) //|> o
  );
endmodule // NV_NVDLA_SDP_cmux