data/full_repos/permissive/447681894/pythondata_cpu_marocchino/verilog/rtl/verilog/pfpu_marocchino/pfpu_marocchino_div.v
data/verilator_xmls/2cb91ad2-cdcb-4b03-b687-ce1e1ce57d09.xml
module r4div_fract58
#(
    parameter N      = 58,
    parameter LOG2N2 =  5
)
(

  input              cpu_clk,

  input              pipeline_flush_i,
  input              div_start_i,
  output reg         div_proc_o,
  output reg         div_valid_o,
  input              wb_taking_div_i,

  input              s1o_opc_0_i,
  input              s1o_dbz_i,

  input      [N-1:0] num_i,
  input      [N-1:0] den_i,

  input              s1o_op_fp64_arith_i,

  output reg         dbz_o,
  output     [N-1:0] rem_o,
  output     [N-1:0] qtnt_o
);


  wire zer = s1o_dbz_i | s1o_opc_0_i;


  localparam [LOG2N2-1:0] DIV_COUNT_MAX_D = 5'd28;
  localparam [LOG2N2-1:0] DIV_COUNT_MAX_S = 5'd13;

  reg [LOG2N2-1:0] div_count_r;

  always @(posedge cpu_clk) begin
    if (pipeline_flush_i) begin
      div_valid_o <= 1'b0;
      dbz_o       <= 1'b0;
      div_proc_o  <= 1'b0;
      div_count_r <= {LOG2N2{1'b0}};
    end
    else if (div_start_i) begin
      if (zer) begin
        div_valid_o <= 1'b1;
        dbz_o       <= s1o_dbz_i;
        div_proc_o  <= 1'b0;
        div_count_r <= {LOG2N2{1'b0}};
      end
      else begin
        div_valid_o <= 1'b0;
        dbz_o       <= 1'b0;
        div_proc_o  <= 1'b1;
        div_count_r <= s1o_op_fp64_arith_i ? DIV_COUNT_MAX_D : DIV_COUNT_MAX_S;
      end
    end
    else if (wb_taking_div_i) begin
      div_valid_o <= 1'b0;
      dbz_o       <= 1'b0;
      div_proc_o  <= 1'b0;
      div_count_r <= {LOG2N2{1'b0}};
    end
    else if (div_proc_o) begin
      if (~(|div_count_r)) begin
        div_valid_o <= 1'b1;
        div_proc_o  <= 1'b0;
      end
      else
        div_count_r <= div_count_r + {LOG2N2{1'b1}};
    end
  end


  reg [N-1:0] one_den_r;
  reg   [N:0] three_den_r;

  always @(posedge cpu_clk) begin
    if (div_start_i) begin
      one_den_r   <= den_i;
      three_den_r <= {1'b0, den_i} + {den_i, 1'b0};
    end
  end


  wire   [N:0] four_rem;
  wire   [N:0] nrem;
  reg    [N:0] prem_hi_r;
  wire   [3:0] trunc_rem;


  assign trunc_rem = prem_hi_r[N:N-3];


  reg  [2:0] q_digit;

  wire       lsb_magn_2or3 = ~one_den_r[N-2];

  always @(trunc_rem or lsb_magn_2or3) begin
    (* parallel_case *)
    casez (trunc_rem)
      4'b0000: q_digit = 3'b000;
      4'b0001: q_digit = 3'b001;
      4'b0010: q_digit = 3'b010;
      4'b0011: q_digit = {2'b01, lsb_magn_2or3};
      4'b01??: q_digit = 3'b011;
      4'b10??: q_digit = 3'b111;
      4'b1100: q_digit = {2'b11, lsb_magn_2or3};
      4'b1101: q_digit = 3'b110;
      4'b1110: q_digit = 3'b101;
      default: q_digit = 3'b000;
    endcase
  end


  reg [N:0] mult_den;

  always @(q_digit[1:0] or one_den_r or three_den_r) begin
    (* parallel_case *)
    case (q_digit[1:0])
      2'b00: mult_den = {(N+1){1'b0}};
      2'b01: mult_den = {1'b0, one_den_r};
      2'b10: mult_den = {one_den_r, 1'b0};
      2'b11: mult_den = three_den_r;
    endcase
  end

  assign four_rem = {prem_hi_r[N-2:0],2'd0};

  wire   sub  = ~q_digit[2];

  assign nrem = four_rem + (mult_den ^ {(N+1){sub}}) + {{N{1'b0}},sub};


  always @(posedge cpu_clk) begin
    if (div_start_i)
      prem_hi_r <= {1'b0,({N{~zer}} & num_i)};
    else if (div_proc_o)
      prem_hi_r <= nrem;
  end



  reg   [N-1:0] q_r;

  reg   [N-1:0] qm_r;

  always @(posedge cpu_clk) begin
    if (div_start_i)
      q_r <= {N{1'b0}};
    else if (div_proc_o) begin
      (* parallel_case *)
      case (q_digit)
        3'b000:  q_r <= { q_r[N-3:0],2'b00};
        3'b001:  q_r <= { q_r[N-3:0],2'b01};
        3'b010:  q_r <= { q_r[N-3:0],2'b10};
        3'b011:  q_r <= { q_r[N-3:0],2'b11};
        3'b111:  q_r <= {qm_r[N-3:0],2'b01};
        3'b110:  q_r <= {qm_r[N-3:0],2'b10};
        default: q_r <= {qm_r[N-3:0],2'b11};
      endcase
    end
  end

  always @(posedge cpu_clk) begin
    if (div_start_i)
      qm_r <= {{(N-2){1'b0}},2'b11};
    else if (div_proc_o) begin
      (* parallel_case *)
      case (q_digit)
        3'b000:  qm_r <= {qm_r[N-3:0],2'b11};
        3'b001:  qm_r <= { q_r[N-3:0],2'b00};
        3'b010:  qm_r <= { q_r[N-3:0],2'b01};
        3'b011:  qm_r <= { q_r[N-3:0],2'b10};
        3'b111:  qm_r <= {qm_r[N-3:0],2'b00};
        3'b110:  qm_r <= {qm_r[N-3:0],2'b01};
        default: qm_r <= {qm_r[N-3:0],2'b10};
      endcase
    end
  end




  assign rem_o  = prem_hi_r[N-1:0] + ({N{prem_hi_r[N]}} & one_den_r[N-1:0]);


  assign qtnt_o = q_r + {N{prem_hi_r[N]}};

endmodule
module r4div_fract58
#(
    parameter N      = 58,
    parameter LOG2N2 =  5
)
(

  input              cpu_clk,

  input              pipeline_flush_i,
  input              div_start_i,
  output reg         div_proc_o,
  output reg         div_valid_o,
  input              wb_taking_div_i,

  input              s1o_opc_0_i,
  input              s1o_dbz_i,

  input      [N-1:0] num_i,
  input      [N-1:0] den_i,

  input              s1o_op_fp64_arith_i,

  output reg         dbz_o,
  output     [N-1:0] rem_o,
  output     [N-1:0] qtnt_o
);



  wire zer = s1o_dbz_i | s1o_opc_0_i;


  localparam [LOG2N2-1:0] DIV_COUNT_MAX_D = 5'd28;
  localparam [LOG2N2-1:0] DIV_COUNT_MAX_S = 5'd13;

  reg [LOG2N2-1:0] div_count_r;

  always @(posedge cpu_clk) begin
    if (pipeline_flush_i) begin
      div_valid_o <= 1'b0;
      dbz_o       <= 1'b0;
      div_proc_o  <= 1'b0;
      div_count_r <= {LOG2N2{1'b0}};
    end
    else if (div_start_i) begin
      if (zer) begin
        div_valid_o <= 1'b1;
        dbz_o       <= s1o_dbz_i;
        div_proc_o  <= 1'b0;
        div_count_r <= {LOG2N2{1'b0}};
      end
      else begin
        div_valid_o <= 1'b0;
        dbz_o       <= 1'b0;
        div_proc_o  <= 1'b1;
        div_count_r <= s1o_op_fp64_arith_i ? DIV_COUNT_MAX_D : DIV_COUNT_MAX_S;
      end
    end
    else if (wb_taking_div_i) begin
      div_valid_o <= 1'b0;
      dbz_o       <= 1'b0;
      div_proc_o  <= 1'b0;
      div_count_r <= {LOG2N2{1'b0}};
    end
    else if (div_proc_o) begin
      if (~(|div_count_r)) begin
        div_valid_o <= 1'b1;
        div_proc_o  <= 1'b0;
      end
      else
        div_count_r <= div_count_r + {LOG2N2{1'b1}};
    end
  end


  reg [N-1:0] one_den_r;
  reg   [N:0] three_den_r;

  always @(posedge cpu_clk) begin
    if (div_start_i) begin
      one_den_r   <= den_i;
      three_den_r <= {1'b0, den_i} + {den_i, 1'b0};
    end
  end


  wire   [N:0] four_rem;
  wire   [N:0] nrem;
  reg    [N:0] prem_hi_r;
  wire   [3:0] trunc_rem;


  assign trunc_rem = prem_hi_r[N:N-3];


  reg  [2:0] q_digit;

  wire       lsb_magn_2or3 = ~one_den_r[N-2];

  always @(trunc_rem or lsb_magn_2or3) begin
    (* parallel_case *)
    casez (trunc_rem)
      4'b0000: q_digit = 3'b000;
      4'b0001: q_digit = 3'b001;
      4'b0010: q_digit = 3'b010;
      4'b0011: q_digit = {2'b01, lsb_magn_2or3};
      4'b01??: q_digit = 3'b011;
      4'b10??: q_digit = 3'b111;
      4'b1100: q_digit = {2'b11, lsb_magn_2or3};
      4'b1101: q_digit = 3'b110;
      4'b1110: q_digit = 3'b101;
      default: q_digit = 3'b000;
    endcase
  end


  reg [N:0] mult_den;

  always @(q_digit[1:0] or one_den_r or three_den_r) begin
    (* parallel_case *)
    case (q_digit[1:0])
      2'b00: mult_den = {(N+1){1'b0}};
      2'b01: mult_den = {1'b0, one_den_r};
      2'b10: mult_den = {one_den_r, 1'b0};
      2'b11: mult_den = three_den_r;
    endcase
  end

  assign four_rem = {prem_hi_r[N-2:0],2'd0};

  wire   sub  = ~q_digit[2];

  assign nrem = four_rem + (mult_den ^ {(N+1){sub}}) + {{N{1'b0}},sub};


  always @(posedge cpu_clk) begin
    if (div_start_i)
      prem_hi_r <= {1'b0,({N{~zer}} & num_i)};
    else if (div_proc_o)
      prem_hi_r <= nrem;
  end



  reg   [N-1:0] q_r;

  reg   [N-1:0] qm_r;

  always @(posedge cpu_clk) begin
    if (div_start_i)
      q_r <= {N{1'b0}};
    else if (div_proc_o) begin
      (* parallel_case *)
      case (q_digit)
        3'b000:  q_r <= { q_r[N-3:0],2'b00};
        3'b001:  q_r <= { q_r[N-3:0],2'b01};
        3'b010:  q_r <= { q_r[N-3:0],2'b10};
        3'b011:  q_r <= { q_r[N-3:0],2'b11};
        3'b111:  q_r <= {qm_r[N-3:0],2'b01};
        3'b110:  q_r <= {qm_r[N-3:0],2'b10};
        default: q_r <= {qm_r[N-3:0],2'b11};
      endcase
    end
  end

  always @(posedge cpu_clk) begin
    if (div_start_i)
      qm_r <= {{(N-2){1'b0}},2'b11};
    else if (div_proc_o) begin
      (* parallel_case *)
      case (q_digit)
        3'b000:  qm_r <= {qm_r[N-3:0],2'b11};
        3'b001:  qm_r <= { q_r[N-3:0],2'b00};
        3'b010:  qm_r <= { q_r[N-3:0],2'b01};
        3'b011:  qm_r <= { q_r[N-3:0],2'b10};
        3'b111:  qm_r <= {qm_r[N-3:0],2'b00};
        3'b110:  qm_r <= {qm_r[N-3:0],2'b01};
        default: qm_r <= {qm_r[N-3:0],2'b10};
      endcase
    end
  end




  assign rem_o  = prem_hi_r[N-1:0] + ({N{prem_hi_r[N]}} & one_den_r[N-1:0]);


  assign qtnt_o = q_r + {N{prem_hi_r[N]}};

endmodule