data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv
1: b'%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:15: Cannot find include file: prim_assert.sv\n`include "prim_assert.sv" \n         ^~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl,data/full_repos/permissive/509468557/prim_assert.sv\n             data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl,data/full_repos/permissive/509468557/prim_assert.sv.v\n             data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl,data/full_repos/permissive/509468557/prim_assert.sv.sv\n             prim_assert.sv\n             prim_assert.sv.v\n             prim_assert.sv.sv\n             obj_dir/prim_assert.sv\n             obj_dir/prim_assert.sv.v\n             obj_dir/prim_assert.sv.sv\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:18: syntax error, unexpected ::, expecting \')\' or \',\'\n    parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast\n                      ^~\n                                                                                                                     : ... Perhaps \'ibex_pkg\' is a package which needs to be predeclared? (IEEE 1800-2017 26.3)\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:21: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic             rst_ni,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:22: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic             mult_en_i,   \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:23: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic             div_en_i,    \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:24: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic             mult_sel_i,  \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:25: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic             div_sel_i,   \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:26: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  ibex_pkg::md_op_e operator_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:28: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [31:0]      op_a_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:29: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [31:0]      op_b_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:30: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [33:0]      alu_adder_ext_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:31: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [31:0]      alu_adder_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:32: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic             equal_to_zero_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:33: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic             data_ind_timing_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:35: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [32:0]      alu_operand_a_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:36: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [32:0]      alu_operand_b_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:38: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [33:0]      imd_val_q_i[2],\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:39: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [33:0]      imd_val_d_o[2],\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:40: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [1:0]       imd_val_we_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:42: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic             multdiv_ready_id_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:44: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [31:0]      multdiv_result_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:45: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic             valid_o\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:93: syntax error, unexpected assign\n  assign unused_mult_sel_i = mult_sel_i;\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:114: Define or directive not defined: \'`ASSERT_KNOWN\'\n  `ASSERT_KNOWN(DivEnKnown, div_en_internal)\n  ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:115: Define or directive not defined: \'`ASSERT_KNOWN\'\n  `ASSERT_KNOWN(MultEnKnown, mult_en_internal)\n  ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:116: Define or directive not defined: \'`ASSERT_KNOWN\'\n  `ASSERT_KNOWN(MultDivEnKnown, multdiv_en)\n  ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:128: syntax error, unexpected assign\n  assign unused_imd_val = imd_val_q_i[1][33:32];\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:130: syntax error, unexpected assign\n  assign unused_mac_res_ext = mac_res_ext[34];\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:155: syntax error, unexpected assign\n    assign mult1_res = $signed({mult1_sign_a, mult1_op_a}) * $signed({mult1_sign_b, mult1_op_b});\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:255: Define or directive not defined: \'`ASSERT_KNOWN\'\n    `ASSERT_KNOWN(IbexMultStateKnown, mult_state_q)\n    ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:272: syntax error, unexpected assign\n    assign mac_res_signed =\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:373: Define or directive not defined: \'`ASSERT_KNOWN\'\n    `ASSERT_KNOWN(IbexMultStateKnown, mult_state_q)\n    ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:380: syntax error, unexpected assign\n  assign unused_alu_adder_ext = {alu_adder_ext_i[33],alu_adder_ext_i[0]};\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_multdiv_fast.sv:522: Define or directive not defined: \'`ASSERT\'\n  `ASSERT(IbexMultDivStateValid, md_state_q inside {\n  ^~~~~~~\n%Error: Exiting due to 34 error(s)\n'
module ibex_multdiv_fast #(
    parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast
  ) (
    input  logic             clk_i,
    input  logic             rst_ni,
    input  logic             mult_en_i,
    input  logic             div_en_i,
    input  logic             mult_sel_i,
    input  logic             div_sel_i,
    input  ibex_pkg::md_op_e operator_i,
    input  logic  [1:0]      signed_mode_i,
    input  logic [31:0]      op_a_i,
    input  logic [31:0]      op_b_i,
    input  logic [33:0]      alu_adder_ext_i,
    input  logic [31:0]      alu_adder_i,
    input  logic             equal_to_zero_i,
    input  logic             data_ind_timing_i,

    output logic [32:0]      alu_operand_a_o,
    output logic [32:0]      alu_operand_b_o,

    input  logic [33:0]      imd_val_q_i[2],
    output logic [33:0]      imd_val_d_o[2],
    output logic [1:0]       imd_val_we_o,

    input  logic             multdiv_ready_id_i,

    output logic [31:0]      multdiv_result_o,
    output logic             valid_o
);

  import ibex_pkg::*;


  logic signed [34:0] mac_res_signed;
  logic        [34:0] mac_res_ext;
  logic        [33:0] accum;
  logic        sign_a, sign_b;
  logic        mult_valid;
  logic        signed_mult;


  logic [33:0] mac_res_d, op_remainder_d;

  logic [33:0] mac_res;


  logic        div_sign_a, div_sign_b;
  logic        is_greater_equal;
  logic        div_change_sign, rem_change_sign;
  logic [31:0] one_shift;
  logic [31:0] op_denominator_q;
  logic [31:0] op_numerator_q;
  logic [31:0] op_quotient_q;
  logic [31:0] op_denominator_d;
  logic [31:0] op_numerator_d;
  logic [31:0] op_quotient_d;
  logic [31:0] next_remainder;
  logic [32:0] next_quotient;
  logic [31:0] res_adder_h;
  logic        div_valid;
  logic [ 4:0] div_counter_q, div_counter_d;
  logic        multdiv_en;
  logic        mult_hold;
  logic        div_hold;
  logic        div_by_zero_d, div_by_zero_q;

  logic        mult_en_internal;
  logic        div_en_internal;

  typedef enum logic [2:0] {
    MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH
  } md_fsm_e;
  md_fsm_e md_state_q, md_state_d;

  logic unused_mult_sel_i;
  assign unused_mult_sel_i = mult_sel_i;

  assign mult_en_internal = mult_en_i & ~mult_hold;
  assign div_en_internal  = div_en_i & ~div_hold;

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      div_counter_q    <= '0;
      md_state_q       <= MD_IDLE;
      op_numerator_q   <= '0;
      op_quotient_q    <= '0;
      div_by_zero_q    <= '0;
    end else if (div_en_internal) begin
      div_counter_q    <= div_counter_d;
      op_numerator_q   <= op_numerator_d;
      op_quotient_q    <= op_quotient_d;
      md_state_q       <= md_state_d;
      div_by_zero_q    <= div_by_zero_d;
    end
  end

  `ASSERT_KNOWN(DivEnKnown, div_en_internal)
  `ASSERT_KNOWN(MultEnKnown, mult_en_internal)
  `ASSERT_KNOWN(MultDivEnKnown, multdiv_en)

  assign multdiv_en = mult_en_internal | div_en_internal;


  assign imd_val_d_o[0] = div_sel_i ? op_remainder_d : mac_res_d;
  assign imd_val_we_o[0] = multdiv_en;

  assign imd_val_d_o[1] = {2'b0, op_denominator_d};
  assign imd_val_we_o[1] = div_en_internal;
  assign op_denominator_q = imd_val_q_i[1][31:0];
  logic [1:0] unused_imd_val;
  assign unused_imd_val = imd_val_q_i[1][33:32];
  logic unused_mac_res_ext;
  assign unused_mac_res_ext = mac_res_ext[34];

  assign signed_mult      = (signed_mode_i != 2'b00);
  assign multdiv_result_o = div_sel_i ? imd_val_q_i[0][31:0] : mac_res_d[31:0];



  if (RV32M == RV32MSingleCycle) begin : gen_mult_single_cycle

    typedef enum logic {
      MULL, MULH
    } mult_fsm_e;
    mult_fsm_e mult_state_q, mult_state_d;

    logic signed [33:0] mult1_res, mult2_res, mult3_res;
    logic [33:0]        mult1_res_uns;
    logic [33:32]       unused_mult1_res_uns;
    logic [15:0]        mult1_op_a, mult1_op_b;
    logic [15:0]        mult2_op_a, mult2_op_b;
    logic [15:0]        mult3_op_a, mult3_op_b;
    logic               mult1_sign_a, mult1_sign_b;
    logic               mult2_sign_a, mult2_sign_b;
    logic               mult3_sign_a, mult3_sign_b;
    logic [33:0]        summand1, summand2, summand3;

    assign mult1_res = $signed({mult1_sign_a, mult1_op_a}) * $signed({mult1_sign_b, mult1_op_b});
    assign mult2_res = $signed({mult2_sign_a, mult2_op_a}) * $signed({mult2_sign_b, mult2_op_b});
    assign mult3_res = $signed({mult3_sign_a, mult3_op_a}) * $signed({mult3_sign_b, mult3_op_b});

    assign mac_res_signed = $signed(summand1) + $signed(summand2) + $signed(summand3);

    assign mult1_res_uns  = $unsigned(mult1_res);
    assign mac_res_ext    = $unsigned(mac_res_signed);
    assign mac_res        = mac_res_ext[33:0];

    assign sign_a = signed_mode_i[0] & op_a_i[31];
    assign sign_b = signed_mode_i[1] & op_b_i[31];



    assign mult1_sign_a = 1'b0;
    assign mult1_sign_b = 1'b0;
    assign mult1_op_a = op_a_i[`OP_L];
    assign mult1_op_b = op_b_i[`OP_L];


    assign mult2_sign_a = 1'b0;
    assign mult2_sign_b = sign_b;
    assign mult2_op_a = op_a_i[`OP_L];
    assign mult2_op_b = op_b_i[`OP_H];


    assign accum[17:0] = imd_val_q_i[0][33:16];
    assign accum[33:18] = {16{signed_mult & imd_val_q_i[0][33]}};

    always_comb begin



      mult3_sign_a = sign_a;
      mult3_sign_b = 1'b0;
      mult3_op_a = op_a_i[`OP_H];
      mult3_op_b = op_b_i[`OP_L];

      summand1 = {18'h0, mult1_res_uns[`OP_H]};
      summand2 = $unsigned(mult2_res);
      summand3 = $unsigned(mult3_res);


      mac_res_d = {2'b0, mac_res[`OP_L], mult1_res_uns[`OP_L]};
      mult_valid = mult_en_i;
      mult_state_d = MULL;

      mult_hold = 1'b0;

      unique case (mult_state_q)

        MULL: begin
          if (operator_i != MD_OP_MULL) begin
            mac_res_d = mac_res;
            mult_valid = 1'b0;
            mult_state_d = MULH;
          end else begin
            mult_hold = ~multdiv_ready_id_i;
          end
        end

        MULH: begin

          mult3_sign_a = sign_a;
          mult3_sign_b = sign_b;
          mult3_op_a = op_a_i[`OP_H];
          mult3_op_b = op_b_i[`OP_H];
          mac_res_d = mac_res;

          summand1 = '0;
          summand2 = accum;
          summand3 = $unsigned(mult3_res);

          mult_state_d = MULL;
          mult_valid = 1'b1;

          mult_hold = ~multdiv_ready_id_i;
        end

        default: begin
          mult_state_d = MULL;
        end

      endcase
    end

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        mult_state_q <= MULL;
      end else begin
        if (mult_en_internal) begin
          mult_state_q <= mult_state_d;
        end
      end
    end

    assign unused_mult1_res_uns = mult1_res_uns[33:32];


    `ASSERT_KNOWN(IbexMultStateKnown, mult_state_q)



  end else begin : gen_mult_fast
    logic [15:0] mult_op_a;
    logic [15:0] mult_op_b;

    typedef enum logic [1:0] {
      ALBL, ALBH, AHBL, AHBH
    } mult_fsm_e;
    mult_fsm_e mult_state_q, mult_state_d;





    assign mac_res_signed =
        $signed({sign_a, mult_op_a}) * $signed({sign_b, mult_op_b}) + $signed(accum);
    assign mac_res_ext    = $unsigned(mac_res_signed);
    assign mac_res        = mac_res_ext[33:0];

    always_comb begin
      mult_op_a    = op_a_i[`OP_L];
      mult_op_b    = op_b_i[`OP_L];
      sign_a       = 1'b0;
      sign_b       = 1'b0;
      accum        = imd_val_q_i[0];
      mac_res_d    = mac_res;
      mult_state_d = mult_state_q;
      mult_valid   = 1'b0;
      mult_hold    = 1'b0;

      unique case (mult_state_q)

        ALBL: begin

          mult_op_a = op_a_i[`OP_L];
          mult_op_b = op_b_i[`OP_L];
          sign_a    = 1'b0;
          sign_b    = 1'b0;
          accum     = '0;
          mac_res_d = mac_res;
          mult_state_d = ALBH;
        end

        ALBH: begin

          mult_op_a = op_a_i[`OP_L];
          mult_op_b = op_b_i[`OP_H];
          sign_a    = 1'b0;
          sign_b    = signed_mode_i[1] & op_b_i[31];

          accum     = {18'b0, imd_val_q_i[0][31:16]};
          if (operator_i == MD_OP_MULL) begin
            mac_res_d = {2'b0, mac_res[`OP_L], imd_val_q_i[0][`OP_L]};
          end else begin

            mac_res_d = mac_res;
          end
          mult_state_d = AHBL;
        end

        AHBL: begin

          mult_op_a = op_a_i[`OP_H];
          mult_op_b = op_b_i[`OP_L];
          sign_a    = signed_mode_i[0] & op_a_i[31];
          sign_b    = 1'b0;
          if (operator_i == MD_OP_MULL) begin
            accum        = {18'b0, imd_val_q_i[0][31:16]};
            mac_res_d    = {2'b0, mac_res[15:0], imd_val_q_i[0][15:0]};
            mult_valid   = 1'b1;


            mult_state_d = ALBL;
            mult_hold    = ~multdiv_ready_id_i;
          end else begin
            accum        = imd_val_q_i[0];
            mac_res_d    = mac_res;
            mult_state_d = AHBH;
          end
        end

        AHBH: begin


          mult_op_a = op_a_i[`OP_H];
          mult_op_b = op_b_i[`OP_H];
          sign_a    = signed_mode_i[0] & op_a_i[31];
          sign_b    = signed_mode_i[1] & op_b_i[31];
          accum[17: 0]  = imd_val_q_i[0][33:16];
          accum[33:18]  = {16{signed_mult & imd_val_q_i[0][33]}};

          mac_res_d    = mac_res;
          mult_valid   = 1'b1;


          mult_state_d = ALBL;
          mult_hold    = ~multdiv_ready_id_i;
        end
        default: begin
          mult_state_d = ALBL;
        end
      endcase
    end

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        mult_state_q <= ALBL;
      end else begin
        if (mult_en_internal) begin
          mult_state_q <= mult_state_d;
        end
      end
    end


    `ASSERT_KNOWN(IbexMultStateKnown, mult_state_q)

  end


  assign res_adder_h    = alu_adder_ext_i[32:1];
  logic [1:0] unused_alu_adder_ext;
  assign unused_alu_adder_ext = {alu_adder_ext_i[33],alu_adder_ext_i[0]};

  assign next_remainder = is_greater_equal ? res_adder_h[31:0] : imd_val_q_i[0][31:0];
  assign next_quotient  = is_greater_equal ? {1'b0, op_quotient_q} | {1'b0, one_shift} :
                                             {1'b0, op_quotient_q};

  assign one_shift      = {31'b0, 1'b1} << div_counter_q;




  always_comb begin
    if ((imd_val_q_i[0][31] ^ op_denominator_q[31]) == 1'b0) begin
      is_greater_equal = (res_adder_h[31] == 1'b0);
    end else begin
      is_greater_equal = imd_val_q_i[0][31];
    end
  end

  assign div_sign_a      = op_a_i[31] & signed_mode_i[0];
  assign div_sign_b      = op_b_i[31] & signed_mode_i[1];
  assign div_change_sign = (div_sign_a ^ div_sign_b) & ~div_by_zero_q;
  assign rem_change_sign = div_sign_a;


  always_comb begin
    div_counter_d    = div_counter_q - 5'h1;
    op_remainder_d   = imd_val_q_i[0];
    op_quotient_d    = op_quotient_q;
    md_state_d       = md_state_q;
    op_numerator_d   = op_numerator_q;
    op_denominator_d = op_denominator_q;
    alu_operand_a_o  = {32'h0  , 1'b1};
    alu_operand_b_o  = {~op_b_i, 1'b1};
    div_valid        = 1'b0;
    div_hold         = 1'b0;
    div_by_zero_d    = div_by_zero_q;

    unique case(md_state_q)
      MD_IDLE: begin
        if (operator_i == MD_OP_DIV) begin




          op_remainder_d = '1;
          md_state_d     = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A;


          div_by_zero_d  = equal_to_zero_i;
        end else begin




          op_remainder_d = {2'b0, op_a_i};
          md_state_d     = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A;
        end

        alu_operand_a_o  = {32'h0  , 1'b1};
        alu_operand_b_o  = {~op_b_i, 1'b1};
        div_counter_d    = 5'd31;
      end

      MD_ABS_A: begin

        op_quotient_d   = '0;

        op_numerator_d  = div_sign_a ? alu_adder_i : op_a_i;
        md_state_d      = MD_ABS_B;
        div_counter_d   = 5'd31;

        alu_operand_a_o = {32'h0  , 1'b1};
        alu_operand_b_o = {~op_a_i, 1'b1};
      end

      MD_ABS_B: begin

        op_remainder_d   = { 33'h0, op_numerator_q[31]};

        op_denominator_d = div_sign_b ? alu_adder_i : op_b_i;
        md_state_d       = MD_COMP;
        div_counter_d    = 5'd31;

        alu_operand_a_o  = {32'h0  , 1'b1};
        alu_operand_b_o  = {~op_b_i, 1'b1};
      end

      MD_COMP: begin
        op_remainder_d  = {1'b0, next_remainder[31:0], op_numerator_q[div_counter_d]};
        op_quotient_d   = next_quotient[31:0];
        md_state_d      = (div_counter_q == 5'd1) ? MD_LAST : MD_COMP;

        alu_operand_a_o = {imd_val_q_i[0][31:0], 1'b1};
        alu_operand_b_o = {~op_denominator_q[31:0], 1'b1};
      end

      MD_LAST: begin
        if (operator_i == MD_OP_DIV) begin


          op_remainder_d = {1'b0, next_quotient};
        end else begin

          op_remainder_d = {2'b0, next_remainder[31:0]};
        end

        alu_operand_a_o  = {imd_val_q_i[0][31:0], 1'b1};
        alu_operand_b_o  = {~op_denominator_q[31:0], 1'b1};

        md_state_d = MD_CHANGE_SIGN;
      end

      MD_CHANGE_SIGN: begin
        md_state_d  = MD_FINISH;
        if (operator_i == MD_OP_DIV) begin
          op_remainder_d = (div_change_sign) ? {2'h0, alu_adder_i} : imd_val_q_i[0];
        end else begin
          op_remainder_d = (rem_change_sign) ? {2'h0, alu_adder_i} : imd_val_q_i[0];
        end

        alu_operand_a_o  = {32'h0  , 1'b1};
        alu_operand_b_o  = {~imd_val_q_i[0][31:0], 1'b1};
      end

      MD_FINISH: begin


        md_state_d = MD_IDLE;
        div_hold   = ~multdiv_ready_id_i;
        div_valid   = 1'b1;
      end

      default: begin
        md_state_d = MD_IDLE;
      end
    endcase
  end

  assign valid_o = mult_valid | div_valid;


  `ASSERT(IbexMultDivStateValid, md_state_q inside {
      MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH})

`ifdef FORMAL
  `ifdef YOSYS
    `include "formal_tb_frag.svh"
  `endif
`endif

endmodule
module ibex_multdiv_fast #(
    parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast
  ) (
    input  logic             clk_i,
    input  logic             rst_ni,
    input  logic             mult_en_i,
    input  logic             div_en_i,
    input  logic             mult_sel_i,
    input  logic             div_sel_i,
    input  ibex_pkg::md_op_e operator_i,
    input  logic  [1:0]      signed_mode_i,
    input  logic [31:0]      op_a_i,
    input  logic [31:0]      op_b_i,
    input  logic [33:0]      alu_adder_ext_i,
    input  logic [31:0]      alu_adder_i,
    input  logic             equal_to_zero_i,
    input  logic             data_ind_timing_i,

    output logic [32:0]      alu_operand_a_o,
    output logic [32:0]      alu_operand_b_o,

    input  logic [33:0]      imd_val_q_i[2],
    output logic [33:0]      imd_val_d_o[2],
    output logic [1:0]       imd_val_we_o,

    input  logic             multdiv_ready_id_i,

    output logic [31:0]      multdiv_result_o,
    output logic             valid_o
);


  import ibex_pkg::*;


  logic signed [34:0] mac_res_signed;
  logic        [34:0] mac_res_ext;
  logic        [33:0] accum;
  logic        sign_a, sign_b;
  logic        mult_valid;
  logic        signed_mult;


  logic [33:0] mac_res_d, op_remainder_d;

  logic [33:0] mac_res;


  logic        div_sign_a, div_sign_b;
  logic        is_greater_equal;
  logic        div_change_sign, rem_change_sign;
  logic [31:0] one_shift;
  logic [31:0] op_denominator_q;
  logic [31:0] op_numerator_q;
  logic [31:0] op_quotient_q;
  logic [31:0] op_denominator_d;
  logic [31:0] op_numerator_d;
  logic [31:0] op_quotient_d;
  logic [31:0] next_remainder;
  logic [32:0] next_quotient;
  logic [31:0] res_adder_h;
  logic        div_valid;
  logic [ 4:0] div_counter_q, div_counter_d;
  logic        multdiv_en;
  logic        mult_hold;
  logic        div_hold;
  logic        div_by_zero_d, div_by_zero_q;

  logic        mult_en_internal;
  logic        div_en_internal;

  typedef enum logic [2:0] {
    MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH
  } md_fsm_e;
  md_fsm_e md_state_q, md_state_d;

  logic unused_mult_sel_i;
  assign unused_mult_sel_i = mult_sel_i;

  assign mult_en_internal = mult_en_i & ~mult_hold;
  assign div_en_internal  = div_en_i & ~div_hold;

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      div_counter_q    <= '0;
      md_state_q       <= MD_IDLE;
      op_numerator_q   <= '0;
      op_quotient_q    <= '0;
      div_by_zero_q    <= '0;
    end else if (div_en_internal) begin
      div_counter_q    <= div_counter_d;
      op_numerator_q   <= op_numerator_d;
      op_quotient_q    <= op_quotient_d;
      md_state_q       <= md_state_d;
      div_by_zero_q    <= div_by_zero_d;
    end
  end

  `ASSERT_KNOWN(DivEnKnown, div_en_internal)
  `ASSERT_KNOWN(MultEnKnown, mult_en_internal)
  `ASSERT_KNOWN(MultDivEnKnown, multdiv_en)

  assign multdiv_en = mult_en_internal | div_en_internal;


  assign imd_val_d_o[0] = div_sel_i ? op_remainder_d : mac_res_d;
  assign imd_val_we_o[0] = multdiv_en;

  assign imd_val_d_o[1] = {2'b0, op_denominator_d};
  assign imd_val_we_o[1] = div_en_internal;
  assign op_denominator_q = imd_val_q_i[1][31:0];
  logic [1:0] unused_imd_val;
  assign unused_imd_val = imd_val_q_i[1][33:32];
  logic unused_mac_res_ext;
  assign unused_mac_res_ext = mac_res_ext[34];

  assign signed_mult      = (signed_mode_i != 2'b00);
  assign multdiv_result_o = div_sel_i ? imd_val_q_i[0][31:0] : mac_res_d[31:0];



  if (RV32M == RV32MSingleCycle) begin : gen_mult_single_cycle

    typedef enum logic {
      MULL, MULH
    } mult_fsm_e;
    mult_fsm_e mult_state_q, mult_state_d;

    logic signed [33:0] mult1_res, mult2_res, mult3_res;
    logic [33:0]        mult1_res_uns;
    logic [33:32]       unused_mult1_res_uns;
    logic [15:0]        mult1_op_a, mult1_op_b;
    logic [15:0]        mult2_op_a, mult2_op_b;
    logic [15:0]        mult3_op_a, mult3_op_b;
    logic               mult1_sign_a, mult1_sign_b;
    logic               mult2_sign_a, mult2_sign_b;
    logic               mult3_sign_a, mult3_sign_b;
    logic [33:0]        summand1, summand2, summand3;

    assign mult1_res = $signed({mult1_sign_a, mult1_op_a}) * $signed({mult1_sign_b, mult1_op_b});
    assign mult2_res = $signed({mult2_sign_a, mult2_op_a}) * $signed({mult2_sign_b, mult2_op_b});
    assign mult3_res = $signed({mult3_sign_a, mult3_op_a}) * $signed({mult3_sign_b, mult3_op_b});

    assign mac_res_signed = $signed(summand1) + $signed(summand2) + $signed(summand3);

    assign mult1_res_uns  = $unsigned(mult1_res);
    assign mac_res_ext    = $unsigned(mac_res_signed);
    assign mac_res        = mac_res_ext[33:0];

    assign sign_a = signed_mode_i[0] & op_a_i[31];
    assign sign_b = signed_mode_i[1] & op_b_i[31];



    assign mult1_sign_a = 1'b0;
    assign mult1_sign_b = 1'b0;
    assign mult1_op_a = op_a_i[`OP_L];
    assign mult1_op_b = op_b_i[`OP_L];


    assign mult2_sign_a = 1'b0;
    assign mult2_sign_b = sign_b;
    assign mult2_op_a = op_a_i[`OP_L];
    assign mult2_op_b = op_b_i[`OP_H];


    assign accum[17:0] = imd_val_q_i[0][33:16];
    assign accum[33:18] = {16{signed_mult & imd_val_q_i[0][33]}};

    always_comb begin



      mult3_sign_a = sign_a;
      mult3_sign_b = 1'b0;
      mult3_op_a = op_a_i[`OP_H];
      mult3_op_b = op_b_i[`OP_L];

      summand1 = {18'h0, mult1_res_uns[`OP_H]};
      summand2 = $unsigned(mult2_res);
      summand3 = $unsigned(mult3_res);


      mac_res_d = {2'b0, mac_res[`OP_L], mult1_res_uns[`OP_L]};
      mult_valid = mult_en_i;
      mult_state_d = MULL;

      mult_hold = 1'b0;

      unique case (mult_state_q)

        MULL: begin
          if (operator_i != MD_OP_MULL) begin
            mac_res_d = mac_res;
            mult_valid = 1'b0;
            mult_state_d = MULH;
          end else begin
            mult_hold = ~multdiv_ready_id_i;
          end
        end

        MULH: begin

          mult3_sign_a = sign_a;
          mult3_sign_b = sign_b;
          mult3_op_a = op_a_i[`OP_H];
          mult3_op_b = op_b_i[`OP_H];
          mac_res_d = mac_res;

          summand1 = '0;
          summand2 = accum;
          summand3 = $unsigned(mult3_res);

          mult_state_d = MULL;
          mult_valid = 1'b1;

          mult_hold = ~multdiv_ready_id_i;
        end

        default: begin
          mult_state_d = MULL;
        end

      endcase
    end

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        mult_state_q <= MULL;
      end else begin
        if (mult_en_internal) begin
          mult_state_q <= mult_state_d;
        end
      end
    end

    assign unused_mult1_res_uns = mult1_res_uns[33:32];


    `ASSERT_KNOWN(IbexMultStateKnown, mult_state_q)



  end else begin : gen_mult_fast
    logic [15:0] mult_op_a;
    logic [15:0] mult_op_b;

    typedef enum logic [1:0] {
      ALBL, ALBH, AHBL, AHBH
    } mult_fsm_e;
    mult_fsm_e mult_state_q, mult_state_d;





    assign mac_res_signed =
        $signed({sign_a, mult_op_a}) * $signed({sign_b, mult_op_b}) + $signed(accum);
    assign mac_res_ext    = $unsigned(mac_res_signed);
    assign mac_res        = mac_res_ext[33:0];

    always_comb begin
      mult_op_a    = op_a_i[`OP_L];
      mult_op_b    = op_b_i[`OP_L];
      sign_a       = 1'b0;
      sign_b       = 1'b0;
      accum        = imd_val_q_i[0];
      mac_res_d    = mac_res;
      mult_state_d = mult_state_q;
      mult_valid   = 1'b0;
      mult_hold    = 1'b0;

      unique case (mult_state_q)

        ALBL: begin

          mult_op_a = op_a_i[`OP_L];
          mult_op_b = op_b_i[`OP_L];
          sign_a    = 1'b0;
          sign_b    = 1'b0;
          accum     = '0;
          mac_res_d = mac_res;
          mult_state_d = ALBH;
        end

        ALBH: begin

          mult_op_a = op_a_i[`OP_L];
          mult_op_b = op_b_i[`OP_H];
          sign_a    = 1'b0;
          sign_b    = signed_mode_i[1] & op_b_i[31];

          accum     = {18'b0, imd_val_q_i[0][31:16]};
          if (operator_i == MD_OP_MULL) begin
            mac_res_d = {2'b0, mac_res[`OP_L], imd_val_q_i[0][`OP_L]};
          end else begin

            mac_res_d = mac_res;
          end
          mult_state_d = AHBL;
        end

        AHBL: begin

          mult_op_a = op_a_i[`OP_H];
          mult_op_b = op_b_i[`OP_L];
          sign_a    = signed_mode_i[0] & op_a_i[31];
          sign_b    = 1'b0;
          if (operator_i == MD_OP_MULL) begin
            accum        = {18'b0, imd_val_q_i[0][31:16]};
            mac_res_d    = {2'b0, mac_res[15:0], imd_val_q_i[0][15:0]};
            mult_valid   = 1'b1;


            mult_state_d = ALBL;
            mult_hold    = ~multdiv_ready_id_i;
          end else begin
            accum        = imd_val_q_i[0];
            mac_res_d    = mac_res;
            mult_state_d = AHBH;
          end
        end

        AHBH: begin


          mult_op_a = op_a_i[`OP_H];
          mult_op_b = op_b_i[`OP_H];
          sign_a    = signed_mode_i[0] & op_a_i[31];
          sign_b    = signed_mode_i[1] & op_b_i[31];
          accum[17: 0]  = imd_val_q_i[0][33:16];
          accum[33:18]  = {16{signed_mult & imd_val_q_i[0][33]}};

          mac_res_d    = mac_res;
          mult_valid   = 1'b1;


          mult_state_d = ALBL;
          mult_hold    = ~multdiv_ready_id_i;
        end
        default: begin
          mult_state_d = ALBL;
        end
      endcase
    end

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        mult_state_q <= ALBL;
      end else begin
        if (mult_en_internal) begin
          mult_state_q <= mult_state_d;
        end
      end
    end


    `ASSERT_KNOWN(IbexMultStateKnown, mult_state_q)

  end


  assign res_adder_h    = alu_adder_ext_i[32:1];
  logic [1:0] unused_alu_adder_ext;
  assign unused_alu_adder_ext = {alu_adder_ext_i[33],alu_adder_ext_i[0]};

  assign next_remainder = is_greater_equal ? res_adder_h[31:0] : imd_val_q_i[0][31:0];
  assign next_quotient  = is_greater_equal ? {1'b0, op_quotient_q} | {1'b0, one_shift} :
                                             {1'b0, op_quotient_q};

  assign one_shift      = {31'b0, 1'b1} << div_counter_q;




  always_comb begin
    if ((imd_val_q_i[0][31] ^ op_denominator_q[31]) == 1'b0) begin
      is_greater_equal = (res_adder_h[31] == 1'b0);
    end else begin
      is_greater_equal = imd_val_q_i[0][31];
    end
  end

  assign div_sign_a      = op_a_i[31] & signed_mode_i[0];
  assign div_sign_b      = op_b_i[31] & signed_mode_i[1];
  assign div_change_sign = (div_sign_a ^ div_sign_b) & ~div_by_zero_q;
  assign rem_change_sign = div_sign_a;


  always_comb begin
    div_counter_d    = div_counter_q - 5'h1;
    op_remainder_d   = imd_val_q_i[0];
    op_quotient_d    = op_quotient_q;
    md_state_d       = md_state_q;
    op_numerator_d   = op_numerator_q;
    op_denominator_d = op_denominator_q;
    alu_operand_a_o  = {32'h0  , 1'b1};
    alu_operand_b_o  = {~op_b_i, 1'b1};
    div_valid        = 1'b0;
    div_hold         = 1'b0;
    div_by_zero_d    = div_by_zero_q;

    unique case(md_state_q)
      MD_IDLE: begin
        if (operator_i == MD_OP_DIV) begin




          op_remainder_d = '1;
          md_state_d     = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A;


          div_by_zero_d  = equal_to_zero_i;
        end else begin




          op_remainder_d = {2'b0, op_a_i};
          md_state_d     = (!data_ind_timing_i && equal_to_zero_i) ? MD_FINISH : MD_ABS_A;
        end

        alu_operand_a_o  = {32'h0  , 1'b1};
        alu_operand_b_o  = {~op_b_i, 1'b1};
        div_counter_d    = 5'd31;
      end

      MD_ABS_A: begin

        op_quotient_d   = '0;

        op_numerator_d  = div_sign_a ? alu_adder_i : op_a_i;
        md_state_d      = MD_ABS_B;
        div_counter_d   = 5'd31;

        alu_operand_a_o = {32'h0  , 1'b1};
        alu_operand_b_o = {~op_a_i, 1'b1};
      end

      MD_ABS_B: begin

        op_remainder_d   = { 33'h0, op_numerator_q[31]};

        op_denominator_d = div_sign_b ? alu_adder_i : op_b_i;
        md_state_d       = MD_COMP;
        div_counter_d    = 5'd31;

        alu_operand_a_o  = {32'h0  , 1'b1};
        alu_operand_b_o  = {~op_b_i, 1'b1};
      end

      MD_COMP: begin
        op_remainder_d  = {1'b0, next_remainder[31:0], op_numerator_q[div_counter_d]};
        op_quotient_d   = next_quotient[31:0];
        md_state_d      = (div_counter_q == 5'd1) ? MD_LAST : MD_COMP;

        alu_operand_a_o = {imd_val_q_i[0][31:0], 1'b1};
        alu_operand_b_o = {~op_denominator_q[31:0], 1'b1};
      end

      MD_LAST: begin
        if (operator_i == MD_OP_DIV) begin


          op_remainder_d = {1'b0, next_quotient};
        end else begin

          op_remainder_d = {2'b0, next_remainder[31:0]};
        end

        alu_operand_a_o  = {imd_val_q_i[0][31:0], 1'b1};
        alu_operand_b_o  = {~op_denominator_q[31:0], 1'b1};

        md_state_d = MD_CHANGE_SIGN;
      end

      MD_CHANGE_SIGN: begin
        md_state_d  = MD_FINISH;
        if (operator_i == MD_OP_DIV) begin
          op_remainder_d = (div_change_sign) ? {2'h0, alu_adder_i} : imd_val_q_i[0];
        end else begin
          op_remainder_d = (rem_change_sign) ? {2'h0, alu_adder_i} : imd_val_q_i[0];
        end

        alu_operand_a_o  = {32'h0  , 1'b1};
        alu_operand_b_o  = {~imd_val_q_i[0][31:0], 1'b1};
      end

      MD_FINISH: begin


        md_state_d = MD_IDLE;
        div_hold   = ~multdiv_ready_id_i;
        div_valid   = 1'b1;
      end

      default: begin
        md_state_d = MD_IDLE;
      end
    endcase
  end

  assign valid_o = mult_valid | div_valid;


  `ASSERT(IbexMultDivStateValid, md_state_q inside {
      MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH})

`ifdef FORMAL
  `ifdef YOSYS
    `include "formal_tb_frag.svh"
  `endif
`endif

endmodule