data/full_repos/permissive/447681894/pythondata_cpu_marocchino/verilog/rtl/verilog/or1k_marocchino_int_div.v
data/verilator_xmls/4b23c4c2-cf3f-4ffd-baf5-c6c43a6d4882.xml
module or1k_marocchino_int_div
#(
  parameter OPTION_OPERAND_WIDTH = 32
)
(

  input                                 cpu_clk,


  input                                 pipeline_flush_i,
  input                                 padv_wrbk_i,
  input                                 grant_wrbk_to_div_i,


  input      [OPTION_OPERAND_WIDTH-1:0] exec_div_a1_i,
  input      [OPTION_OPERAND_WIDTH-1:0] exec_div_b1_i,


  input                                 exec_op_div_i,
  input                                 exec_op_div_signed_i,
  input                                 exec_op_div_unsigned_i,


  output                                idiv_taking_op_o,
  output                                div_valid_o,



  output reg                            wrbk_div_carry_set_o,
  output reg                            wrbk_div_carry_clear_o,

  output reg                            wrbk_div_overflow_set_o,
  output reg                            wrbk_div_overflow_clear_o,

  input                                 except_overflow_enable_i,
  output                                exec_except_overflow_div_o,
  output reg                            wrbk_except_overflow_div_o,

  output reg [OPTION_OPERAND_WIDTH-1:0] wrbk_div_result_o
);

  localparam DIVDW        = OPTION_OPERAND_WIDTH;
  localparam LOG2_DIVDW_2 = 4;


  wire [DIVDW-1:0] s3t_div_result;
  wire             s3o_dbz;
  reg              s3o_div_signed, s3o_div_unsigned;
  wire             div_s3_rdy;
  reg              wrbk_div_miss_r;



  reg [5:0] div_count;
  reg       div_proc_r;

  reg       div_s3_rdy_r;
  reg       div_valid_r;


  wire   div_s3_busy = div_proc_r | (div_s3_rdy_r & wrbk_div_miss_r);

  assign idiv_taking_op_o = exec_op_div_i & (~div_s3_busy);



  always @(posedge cpu_clk) begin
    if (pipeline_flush_i) begin
      div_s3_rdy_r <= 1'b0;
      div_proc_r   <= 1'b0;
      div_count    <= 6'd0;
    end
    else if (idiv_taking_op_o) begin
      div_s3_rdy_r <= 1'b0;
      div_proc_r   <= 1'b1;
      div_count    <= DIVDW;
    end
    else if (div_s3_rdy_r & (~wrbk_div_miss_r)) begin
      div_s3_rdy_r <= 1'b0;
      div_proc_r   <= 1'b0;
      div_count    <= 6'd0;
    end
    else if (div_proc_r) begin
      if (div_count == 6'd1) begin
        div_s3_rdy_r <= 1'b1;
        div_proc_r   <= 1'b0;
      end
      div_count <= div_count - 6'd1;
    end
  end



  always @(posedge cpu_clk) begin
    if (pipeline_flush_i)
      div_valid_r <= 1'b0;
    else if (div_proc_r & (div_count == 6'd1))
      div_valid_r <= 1'b1;
    else if (padv_wrbk_i & grant_wrbk_to_div_i)
      div_valid_r <= wrbk_div_miss_r ? div_s3_rdy_r : 1'b0;
  end


  assign div_s3_rdy  = div_s3_rdy_r;
  assign div_valid_o = div_valid_r;



  reg [DIVDW-1:0] div_n;
  reg [DIVDW-1:0] div_d;
  reg [DIVDW-1:0] div_r;
  reg             div_neg;
  reg             dbz_r;


  wire op_div_sign_a = exec_div_a1_i[DIVDW-1] & exec_op_div_signed_i;
  wire op_div_sign_b = exec_div_b1_i[DIVDW-1] & exec_op_div_signed_i;


  wire [DIVDW:0] div_sub = {div_r[DIVDW-2:0],div_n[DIVDW-1]} - div_d;

  always @(posedge cpu_clk) begin
    if (idiv_taking_op_o) begin



      div_n   <= (exec_div_a1_i ^ {DIVDW{op_div_sign_a}}) + {{(DIVDW-1){1'b0}},op_div_sign_a};
      div_d   <= (exec_div_b1_i ^ {DIVDW{op_div_sign_b}}) + {{(DIVDW-1){1'b0}},op_div_sign_b};
      div_r   <= {DIVDW{1'b0}};
      div_neg <= (op_div_sign_a ^ op_div_sign_b);
      dbz_r   <= (exec_div_b1_i == {DIVDW{1'b0}});
      s3o_div_signed   <= exec_op_div_signed_i;
      s3o_div_unsigned <= exec_op_div_unsigned_i;
    end
    else if (~div_valid_r) begin
      if (~div_sub[DIVDW]) begin
        div_r <= div_sub[DIVDW-1:0];
        div_n <= {div_n[DIVDW-2:0], 1'b1};
      end
      else begin
        div_r <= {div_r[DIVDW-2:0],div_n[DIVDW-1]};
        div_n <= {div_n[DIVDW-2:0], 1'b0};
      end
    end
  end

  assign s3t_div_result = (div_n ^ {DIVDW{div_neg}}) + {{(DIVDW-1){1'b0}},div_neg};
  assign s3o_dbz = dbz_r;






  always @(posedge cpu_clk) begin
    if (pipeline_flush_i)
      wrbk_div_miss_r <= 1'b0;
    else if (padv_wrbk_i & grant_wrbk_to_div_i)
      wrbk_div_miss_r <= 1'b0;
    else if (~wrbk_div_miss_r)
      wrbk_div_miss_r <= div_s3_rdy;
  end


  wire div_carry_set      = s3o_div_unsigned &   s3o_dbz;
  wire div_carry_clear    = s3o_div_unsigned & (~s3o_dbz);


  wire div_overflow_set   = s3o_div_signed &   s3o_dbz;
  wire div_overflow_clear = s3o_div_signed & (~s3o_dbz);


  reg [DIVDW-1:0] div_result_p;
  reg             div_carry_set_p;
  reg             div_carry_clear_p;
  reg             div_overflow_set_p;
  reg             div_overflow_clear_p;

  always @(posedge cpu_clk) begin
    if (~wrbk_div_miss_r) begin
      div_result_p         <= s3t_div_result;
      div_carry_set_p      <= div_carry_set;
      div_carry_clear_p    <= div_carry_clear;
      div_overflow_set_p   <= div_overflow_set;
      div_overflow_clear_p <= div_overflow_clear;
    end
  end


  wire   mux_except_overflow_div    = except_overflow_enable_i & (wrbk_div_miss_r ? div_overflow_set_p : div_overflow_set);
  assign exec_except_overflow_div_o = grant_wrbk_to_div_i & mux_except_overflow_div;


  wire [DIVDW-1:0] wrbk_div_result_m = wrbk_div_miss_r ? div_result_p : s3t_div_result;

  always @(posedge cpu_clk) begin
    if (padv_wrbk_i) begin
      if (grant_wrbk_to_div_i)
        wrbk_div_result_o <= wrbk_div_result_m;
      else
        wrbk_div_result_o <= {DIVDW{1'b0}};
    end
  end


  always @(posedge cpu_clk) begin
    if (padv_wrbk_i & grant_wrbk_to_div_i) begin

      wrbk_div_carry_set_o        <= wrbk_div_miss_r ? div_carry_set_p : div_carry_set;
      wrbk_div_carry_clear_o      <= wrbk_div_miss_r ? div_carry_clear_p : div_carry_clear;

      wrbk_div_overflow_set_o     <= wrbk_div_miss_r ? div_overflow_set_p : div_overflow_set;
      wrbk_div_overflow_clear_o   <= wrbk_div_miss_r ? div_overflow_clear_p : div_overflow_clear;

      wrbk_except_overflow_div_o  <= mux_except_overflow_div;
    end
    else begin

      wrbk_div_carry_set_o        <= 1'b0;
      wrbk_div_carry_clear_o      <= 1'b0;

      wrbk_div_overflow_set_o     <= 1'b0;
      wrbk_div_overflow_clear_o   <= 1'b0;

      wrbk_except_overflow_div_o  <= 1'b0;
    end
  end

endmodule
module or1k_marocchino_int_div
#(
  parameter OPTION_OPERAND_WIDTH = 32
)
(

  input                                 cpu_clk,


  input                                 pipeline_flush_i,
  input                                 padv_wrbk_i,
  input                                 grant_wrbk_to_div_i,


  input      [OPTION_OPERAND_WIDTH-1:0] exec_div_a1_i,
  input      [OPTION_OPERAND_WIDTH-1:0] exec_div_b1_i,


  input                                 exec_op_div_i,
  input                                 exec_op_div_signed_i,
  input                                 exec_op_div_unsigned_i,


  output                                idiv_taking_op_o,
  output                                div_valid_o,



  output reg                            wrbk_div_carry_set_o,
  output reg                            wrbk_div_carry_clear_o,

  output reg                            wrbk_div_overflow_set_o,
  output reg                            wrbk_div_overflow_clear_o,

  input                                 except_overflow_enable_i,
  output                                exec_except_overflow_div_o,
  output reg                            wrbk_except_overflow_div_o,

  output reg [OPTION_OPERAND_WIDTH-1:0] wrbk_div_result_o
);


  localparam DIVDW        = OPTION_OPERAND_WIDTH;
  localparam LOG2_DIVDW_2 = 4;


  wire [DIVDW-1:0] s3t_div_result;
  wire             s3o_dbz;
  reg              s3o_div_signed, s3o_div_unsigned;
  wire             div_s3_rdy;
  reg              wrbk_div_miss_r;



  reg [5:0] div_count;
  reg       div_proc_r;

  reg       div_s3_rdy_r;
  reg       div_valid_r;


  wire   div_s3_busy = div_proc_r | (div_s3_rdy_r & wrbk_div_miss_r);

  assign idiv_taking_op_o = exec_op_div_i & (~div_s3_busy);



  always @(posedge cpu_clk) begin
    if (pipeline_flush_i) begin
      div_s3_rdy_r <= 1'b0;
      div_proc_r   <= 1'b0;
      div_count    <= 6'd0;
    end
    else if (idiv_taking_op_o) begin
      div_s3_rdy_r <= 1'b0;
      div_proc_r   <= 1'b1;
      div_count    <= DIVDW;
    end
    else if (div_s3_rdy_r & (~wrbk_div_miss_r)) begin
      div_s3_rdy_r <= 1'b0;
      div_proc_r   <= 1'b0;
      div_count    <= 6'd0;
    end
    else if (div_proc_r) begin
      if (div_count == 6'd1) begin
        div_s3_rdy_r <= 1'b1;
        div_proc_r   <= 1'b0;
      end
      div_count <= div_count - 6'd1;
    end
  end



  always @(posedge cpu_clk) begin
    if (pipeline_flush_i)
      div_valid_r <= 1'b0;
    else if (div_proc_r & (div_count == 6'd1))
      div_valid_r <= 1'b1;
    else if (padv_wrbk_i & grant_wrbk_to_div_i)
      div_valid_r <= wrbk_div_miss_r ? div_s3_rdy_r : 1'b0;
  end


  assign div_s3_rdy  = div_s3_rdy_r;
  assign div_valid_o = div_valid_r;



  reg [DIVDW-1:0] div_n;
  reg [DIVDW-1:0] div_d;
  reg [DIVDW-1:0] div_r;
  reg             div_neg;
  reg             dbz_r;


  wire op_div_sign_a = exec_div_a1_i[DIVDW-1] & exec_op_div_signed_i;
  wire op_div_sign_b = exec_div_b1_i[DIVDW-1] & exec_op_div_signed_i;


  wire [DIVDW:0] div_sub = {div_r[DIVDW-2:0],div_n[DIVDW-1]} - div_d;

  always @(posedge cpu_clk) begin
    if (idiv_taking_op_o) begin



      div_n   <= (exec_div_a1_i ^ {DIVDW{op_div_sign_a}}) + {{(DIVDW-1){1'b0}},op_div_sign_a};
      div_d   <= (exec_div_b1_i ^ {DIVDW{op_div_sign_b}}) + {{(DIVDW-1){1'b0}},op_div_sign_b};
      div_r   <= {DIVDW{1'b0}};
      div_neg <= (op_div_sign_a ^ op_div_sign_b);
      dbz_r   <= (exec_div_b1_i == {DIVDW{1'b0}});
      s3o_div_signed   <= exec_op_div_signed_i;
      s3o_div_unsigned <= exec_op_div_unsigned_i;
    end
    else if (~div_valid_r) begin
      if (~div_sub[DIVDW]) begin
        div_r <= div_sub[DIVDW-1:0];
        div_n <= {div_n[DIVDW-2:0], 1'b1};
      end
      else begin
        div_r <= {div_r[DIVDW-2:0],div_n[DIVDW-1]};
        div_n <= {div_n[DIVDW-2:0], 1'b0};
      end
    end
  end

  assign s3t_div_result = (div_n ^ {DIVDW{div_neg}}) + {{(DIVDW-1){1'b0}},div_neg};
  assign s3o_dbz = dbz_r;






  always @(posedge cpu_clk) begin
    if (pipeline_flush_i)
      wrbk_div_miss_r <= 1'b0;
    else if (padv_wrbk_i & grant_wrbk_to_div_i)
      wrbk_div_miss_r <= 1'b0;
    else if (~wrbk_div_miss_r)
      wrbk_div_miss_r <= div_s3_rdy;
  end


  wire div_carry_set      = s3o_div_unsigned &   s3o_dbz;
  wire div_carry_clear    = s3o_div_unsigned & (~s3o_dbz);


  wire div_overflow_set   = s3o_div_signed &   s3o_dbz;
  wire div_overflow_clear = s3o_div_signed & (~s3o_dbz);


  reg [DIVDW-1:0] div_result_p;
  reg             div_carry_set_p;
  reg             div_carry_clear_p;
  reg             div_overflow_set_p;
  reg             div_overflow_clear_p;

  always @(posedge cpu_clk) begin
    if (~wrbk_div_miss_r) begin
      div_result_p         <= s3t_div_result;
      div_carry_set_p      <= div_carry_set;
      div_carry_clear_p    <= div_carry_clear;
      div_overflow_set_p   <= div_overflow_set;
      div_overflow_clear_p <= div_overflow_clear;
    end
  end


  wire   mux_except_overflow_div    = except_overflow_enable_i & (wrbk_div_miss_r ? div_overflow_set_p : div_overflow_set);
  assign exec_except_overflow_div_o = grant_wrbk_to_div_i & mux_except_overflow_div;


  wire [DIVDW-1:0] wrbk_div_result_m = wrbk_div_miss_r ? div_result_p : s3t_div_result;

  always @(posedge cpu_clk) begin
    if (padv_wrbk_i) begin
      if (grant_wrbk_to_div_i)
        wrbk_div_result_o <= wrbk_div_result_m;
      else
        wrbk_div_result_o <= {DIVDW{1'b0}};
    end
  end


  always @(posedge cpu_clk) begin
    if (padv_wrbk_i & grant_wrbk_to_div_i) begin

      wrbk_div_carry_set_o        <= wrbk_div_miss_r ? div_carry_set_p : div_carry_set;
      wrbk_div_carry_clear_o      <= wrbk_div_miss_r ? div_carry_clear_p : div_carry_clear;

      wrbk_div_overflow_set_o     <= wrbk_div_miss_r ? div_overflow_set_p : div_overflow_set;
      wrbk_div_overflow_clear_o   <= wrbk_div_miss_r ? div_overflow_clear_p : div_overflow_clear;

      wrbk_except_overflow_div_o  <= mux_except_overflow_div;
    end
    else begin

      wrbk_div_carry_set_o        <= 1'b0;
      wrbk_div_carry_clear_o      <= 1'b0;

      wrbk_div_overflow_set_o     <= 1'b0;
      wrbk_div_overflow_clear_o   <= 1'b0;

      wrbk_except_overflow_div_o  <= 1'b0;
    end
  end

endmodule