data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv
1: b'%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:17: 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_id_stage.sv:18: Cannot find include file: dv_fcov_macros.svh\n`include "dv_fcov_macros.svh" \n         ^~~~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:22: 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_id_stage.sv:25: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter bit               BranchTargetALU = 0,\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:26: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter bit               SpecBranch      = 0,\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:27: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter bit               WritebackStage  = 0,\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:28: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter bit               BranchPredictor = 0\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:29: syntax error, unexpected \')\', expecting \';\'\n) (\n^\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:31: 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_id_stage.sv:33: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      ctrl_busy_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:34: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      illegal_insn_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:37: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic                      instr_valid_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:38: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [31:0]               instr_rdata_i,          \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:39: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [31:0]               instr_rdata_alu_i,      \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:40: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [15:0]               instr_rdata_c_i,        \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:41: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic                      instr_is_compressed_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:42: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic                      instr_bp_taken_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:43: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      instr_req_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:44: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      instr_first_cycle_id_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:45: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      instr_valid_clear_o,    \n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:46: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      id_in_ready_o,          \n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:47: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      icache_inval_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:50: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic                      branch_decision_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:53: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      pc_set_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:54: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      pc_set_spec_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:55: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output ibex_pkg::pc_sel_e         pc_mux_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:57: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output ibex_pkg::exc_pc_sel_e     exc_pc_mux_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:61: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic                      instr_fetch_err_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:62: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic                      instr_fetch_err_plus2_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:64: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [31:0]               pc_id_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:67: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic                      ex_valid_i,        \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:68: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic                      lsu_resp_valid_i,  \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:70: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output ibex_pkg::alu_op_e         alu_operator_ex_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:72: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [31:0]               alu_operand_b_ex_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:75: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [1:0]                imd_val_we_ex_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:76: syntax error, unexpected input, expecting IDENTIFIER or \'=\' or do or final\n    input  logic [33:0]               imd_val_d_ex_i[2],\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:77: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [33:0]               imd_val_q_ex_o[2],\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:80: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [31:0]               bt_a_operand_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:81: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [31:0]               bt_b_operand_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:84: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      mult_en_ex_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:85: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      div_en_ex_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:86: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      mult_sel_ex_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:87: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      div_sel_ex_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:88: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output ibex_pkg::md_op_e          multdiv_operator_ex_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:90: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [31:0]               multdiv_operand_a_ex_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:91: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic [31:0]               multdiv_operand_b_ex_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:92: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      multdiv_ready_id_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:95: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      csr_access_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:96: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output ibex_pkg::csr_op_e         csr_op_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/ibex/src/main/resources/vsrc/ibex/rtl/ibex_id_stage.sv:98: syntax error, unexpected output, expecting IDENTIFIER or \'=\' or do or final\n    output logic                      csr_save_if_o,\n    ^~~~~~\n%Error: Exiting due to too many errors encountered; --error-limit=50\n'
module ibex_id_stage #(
    parameter bit               RV32E           = 0,
    parameter ibex_pkg::rv32m_e RV32M           = ibex_pkg::RV32MFast,
    parameter ibex_pkg::rv32b_e RV32B           = ibex_pkg::RV32BNone,
    parameter bit               DataIndTiming   = 1'b0,
    parameter bit               BranchTargetALU = 0,
    parameter bit               SpecBranch      = 0,
    parameter bit               WritebackStage  = 0,
    parameter bit               BranchPredictor = 0
) (
    input  logic                      clk_i,
    input  logic                      rst_ni,

    output logic                      ctrl_busy_o,
    output logic                      illegal_insn_o,


    input  logic                      instr_valid_i,
    input  logic [31:0]               instr_rdata_i,
    input  logic [31:0]               instr_rdata_alu_i,
    input  logic [15:0]               instr_rdata_c_i,
    input  logic                      instr_is_compressed_i,
    input  logic                      instr_bp_taken_i,
    output logic                      instr_req_o,
    output logic                      instr_first_cycle_id_o,
    output logic                      instr_valid_clear_o,
    output logic                      id_in_ready_o,
    output logic                      icache_inval_o,


    input  logic                      branch_decision_i,


    output logic                      pc_set_o,
    output logic                      pc_set_spec_o,
    output ibex_pkg::pc_sel_e         pc_mux_o,
    output logic                      nt_branch_mispredict_o,
    output ibex_pkg::exc_pc_sel_e     exc_pc_mux_o,
    output ibex_pkg::exc_cause_e      exc_cause_o,

    input  logic                      illegal_c_insn_i,
    input  logic                      instr_fetch_err_i,
    input  logic                      instr_fetch_err_plus2_i,

    input  logic [31:0]               pc_id_i,


    input  logic                      ex_valid_i,
    input  logic                      lsu_resp_valid_i,

    output ibex_pkg::alu_op_e         alu_operator_ex_o,
    output logic [31:0]               alu_operand_a_ex_o,
    output logic [31:0]               alu_operand_b_ex_o,


    input  logic [1:0]                imd_val_we_ex_i,
    input  logic [33:0]               imd_val_d_ex_i[2],
    output logic [33:0]               imd_val_q_ex_o[2],


    output logic [31:0]               bt_a_operand_o,
    output logic [31:0]               bt_b_operand_o,


    output logic                      mult_en_ex_o,
    output logic                      div_en_ex_o,
    output logic                      mult_sel_ex_o,
    output logic                      div_sel_ex_o,
    output ibex_pkg::md_op_e          multdiv_operator_ex_o,
    output logic  [1:0]               multdiv_signed_mode_ex_o,
    output logic [31:0]               multdiv_operand_a_ex_o,
    output logic [31:0]               multdiv_operand_b_ex_o,
    output logic                      multdiv_ready_id_o,


    output logic                      csr_access_o,
    output ibex_pkg::csr_op_e         csr_op_o,
    output logic                      csr_op_en_o,
    output logic                      csr_save_if_o,
    output logic                      csr_save_id_o,
    output logic                      csr_save_wb_o,
    output logic                      csr_restore_mret_id_o,
    output logic                      csr_restore_dret_id_o,
    output logic                      csr_save_cause_o,
    output logic [31:0]               csr_mtval_o,
    input  ibex_pkg::priv_lvl_e       priv_mode_i,
    input  logic                      csr_mstatus_tw_i,
    input  logic                      illegal_csr_insn_i,
    input  logic                      data_ind_timing_i,


    output logic                      lsu_req_o,
    output logic                      lsu_we_o,
    output logic [1:0]                lsu_type_o,
    output logic                      lsu_sign_ext_o,
    output logic [31:0]               lsu_wdata_o,

    input  logic                      lsu_req_done_i,




    input  logic                      lsu_addr_incr_req_i,
    input  logic [31:0]               lsu_addr_last_i,


    input  logic                      csr_mstatus_mie_i,
    input  logic                      irq_pending_i,
    input  ibex_pkg::irqs_t           irqs_i,
    input  logic                      irq_nm_i,
    output logic                      nmi_mode_o,

    input  logic                      lsu_load_err_i,
    input  logic                      lsu_store_err_i,


    output logic                      debug_mode_o,
    output ibex_pkg::dbg_cause_e      debug_cause_o,
    output logic                      debug_csr_save_o,
    input  logic                      debug_req_i,
    input  logic                      debug_single_step_i,
    input  logic                      debug_ebreakm_i,
    input  logic                      debug_ebreaku_i,
    input  logic                      trigger_match_i,


    input  logic [31:0]               result_ex_i,
    input  logic [31:0]               csr_rdata_i,


    output logic [4:0]                rf_raddr_a_o,
    input  logic [31:0]               rf_rdata_a_i,
    output logic [4:0]                rf_raddr_b_o,
    input  logic [31:0]               rf_rdata_b_i,
    output logic                      rf_ren_a_o,
    output logic                      rf_ren_b_o,


    output logic [4:0]                rf_waddr_id_o,
    output logic [31:0]               rf_wdata_id_o,
    output logic                      rf_we_id_o,
    output logic                      rf_rd_a_wb_match_o,
    output logic                      rf_rd_b_wb_match_o,


    input  logic [4:0]                rf_waddr_wb_i,
    input  logic [31:0]               rf_wdata_fwd_wb_i,
    input  logic                      rf_write_wb_i,

    output  logic                     en_wb_o,
    output  ibex_pkg::wb_instr_type_e instr_type_wb_o,
    output  logic                     instr_perf_count_id_o,
    input logic                       ready_wb_i,
    input logic                       outstanding_load_wb_i,
    input logic                       outstanding_store_wb_i,


    output logic                      perf_jump_o,
    output logic                      perf_branch_o,
    output logic                      perf_tbranch_o,
    output logic                      perf_dside_wait_o,

    output logic                      perf_mul_wait_o,
    output logic                      perf_div_wait_o,
    output logic                      instr_id_done_o
);

  import ibex_pkg::*;


  logic        illegal_insn_dec;
  logic        ebrk_insn;
  logic        mret_insn_dec;
  logic        dret_insn_dec;
  logic        ecall_insn_dec;
  logic        wfi_insn_dec;

  logic        wb_exception;

  logic        branch_in_dec;
  logic        branch_spec, branch_set_spec, branch_set_raw_spec;
  logic        branch_set, branch_set_raw, branch_set_raw_d;
  logic        branch_jump_set_done_q, branch_jump_set_done_d;
  logic        branch_not_set;
  logic        branch_taken;
  logic        jump_in_dec;
  logic        jump_set_dec;
  logic        jump_set, jump_set_raw;

  logic        instr_first_cycle;
  logic        instr_executing_spec;
  logic        instr_executing;
  logic        instr_done;
  logic        controller_run;
  logic        stall_ld_hz;
  logic        stall_mem;
  logic        stall_multdiv;
  logic        stall_branch;
  logic        stall_jump;
  logic        stall_id;
  logic        stall_wb;
  logic        flush_id;
  logic        multicycle_done;


  logic [31:0] imm_i_type;
  logic [31:0] imm_s_type;
  logic [31:0] imm_b_type;
  logic [31:0] imm_u_type;
  logic [31:0] imm_j_type;
  logic [31:0] zimm_rs1_type;

  logic [31:0] imm_a;
  logic [31:0] imm_b;



  rf_wd_sel_e  rf_wdata_sel;
  logic        rf_we_dec, rf_we_raw;
  logic        rf_ren_a, rf_ren_b;
  logic        rf_ren_a_dec, rf_ren_b_dec;


  assign rf_ren_a = instr_valid_i & ~instr_fetch_err_i & ~illegal_insn_o & rf_ren_a_dec;
  assign rf_ren_b = instr_valid_i & ~instr_fetch_err_i & ~illegal_insn_o & rf_ren_b_dec;

  assign rf_ren_a_o = rf_ren_a;
  assign rf_ren_b_o = rf_ren_b;

  logic [31:0] rf_rdata_a_fwd;
  logic [31:0] rf_rdata_b_fwd;


  alu_op_e     alu_operator;
  op_a_sel_e   alu_op_a_mux_sel, alu_op_a_mux_sel_dec;
  op_b_sel_e   alu_op_b_mux_sel, alu_op_b_mux_sel_dec;
  logic        alu_multicycle_dec;
  logic        stall_alu;

  logic [33:0] imd_val_q[2];

  op_a_sel_e   bt_a_mux_sel;
  imm_b_sel_e  bt_b_mux_sel;

  imm_a_sel_e  imm_a_mux_sel;
  imm_b_sel_e  imm_b_mux_sel, imm_b_mux_sel_dec;


  logic        mult_en_id, mult_en_dec;
  logic        div_en_id, div_en_dec;
  logic        multdiv_en_dec;
  md_op_e      multdiv_operator;
  logic [1:0]  multdiv_signed_mode;


  logic        lsu_we;
  logic [1:0]  lsu_type;
  logic        lsu_sign_ext;
  logic        lsu_req, lsu_req_dec;
  logic        data_req_allowed;


  logic        csr_pipe_flush;

  logic [31:0] alu_operand_a;
  logic [31:0] alu_operand_b;






  assign alu_op_a_mux_sel = lsu_addr_incr_req_i ? OP_A_FWD        : alu_op_a_mux_sel_dec;
  assign alu_op_b_mux_sel = lsu_addr_incr_req_i ? OP_B_IMM        : alu_op_b_mux_sel_dec;
  assign imm_b_mux_sel    = lsu_addr_incr_req_i ? IMM_B_INCR_ADDR : imm_b_mux_sel_dec;






  assign imm_a = (imm_a_mux_sel == IMM_A_Z) ? zimm_rs1_type : '0;


  always_comb begin : alu_operand_a_mux
    unique case (alu_op_a_mux_sel)
      OP_A_REG_A:  alu_operand_a = rf_rdata_a_fwd;
      OP_A_FWD:    alu_operand_a = lsu_addr_last_i;
      OP_A_CURRPC: alu_operand_a = pc_id_i;
      OP_A_IMM:    alu_operand_a = imm_a;
      default:     alu_operand_a = pc_id_i;
    endcase
  end

  if (BranchTargetALU) begin : g_btalu_muxes

    always_comb begin : bt_operand_a_mux
      unique case (bt_a_mux_sel)
        OP_A_REG_A:  bt_a_operand_o = rf_rdata_a_fwd;
        OP_A_CURRPC: bt_a_operand_o = pc_id_i;
        default:     bt_a_operand_o = pc_id_i;
      endcase
    end


    always_comb begin : bt_immediate_b_mux
      unique case (bt_b_mux_sel)
        IMM_B_I:         bt_b_operand_o = imm_i_type;
        IMM_B_B:         bt_b_operand_o = imm_b_type;
        IMM_B_J:         bt_b_operand_o = imm_j_type;
        IMM_B_INCR_PC:   bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4;
        default:         bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4;
      endcase
    end


    always_comb begin : immediate_b_mux
      unique case (imm_b_mux_sel)
        IMM_B_I:         imm_b = imm_i_type;
        IMM_B_S:         imm_b = imm_s_type;
        IMM_B_U:         imm_b = imm_u_type;
        IMM_B_INCR_PC:   imm_b = instr_is_compressed_i ? 32'h2 : 32'h4;
        IMM_B_INCR_ADDR: imm_b = 32'h4;
        default:         imm_b = 32'h4;
      endcase
    end
    `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside {
        IMM_B_I,
        IMM_B_S,
        IMM_B_U,
        IMM_B_INCR_PC,
        IMM_B_INCR_ADDR})
  end else begin : g_nobtalu
    op_a_sel_e  unused_a_mux_sel;
    imm_b_sel_e unused_b_mux_sel;

    assign unused_a_mux_sel = bt_a_mux_sel;
    assign unused_b_mux_sel = bt_b_mux_sel;
    assign bt_a_operand_o   = '0;
    assign bt_b_operand_o   = '0;


    always_comb begin : immediate_b_mux
      unique case (imm_b_mux_sel)
        IMM_B_I:         imm_b = imm_i_type;
        IMM_B_S:         imm_b = imm_s_type;
        IMM_B_B:         imm_b = imm_b_type;
        IMM_B_U:         imm_b = imm_u_type;
        IMM_B_J:         imm_b = imm_j_type;
        IMM_B_INCR_PC:   imm_b = instr_is_compressed_i ? 32'h2 : 32'h4;
        IMM_B_INCR_ADDR: imm_b = 32'h4;
        default:         imm_b = 32'h4;
      endcase
    end
    `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside {
        IMM_B_I,
        IMM_B_S,
        IMM_B_B,
        IMM_B_U,
        IMM_B_J,
        IMM_B_INCR_PC,
        IMM_B_INCR_ADDR})
  end


  assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : rf_rdata_b_fwd;





  for (genvar i=0; i<2; i++) begin : gen_intermediate_val_reg
    always_ff @(posedge clk_i or negedge rst_ni) begin : intermediate_val_reg
      if (!rst_ni) begin
        imd_val_q[i] <= '0;
      end else if (imd_val_we_ex_i[i]) begin
        imd_val_q[i] <= imd_val_d_ex_i[i];
      end
    end
  end

  assign imd_val_q_ex_o = imd_val_q;






  assign rf_we_id_o = rf_we_raw & instr_executing & ~illegal_csr_insn_i;


  always_comb begin : rf_wdata_id_mux
    unique case (rf_wdata_sel)
      RF_WD_EX:  rf_wdata_id_o = result_ex_i;
      RF_WD_CSR: rf_wdata_id_o = csr_rdata_i;
      default:   rf_wdata_id_o = result_ex_i;
    endcase
  end





  ibex_decoder #(
      .RV32E           ( RV32E           ),
      .RV32M           ( RV32M           ),
      .RV32B           ( RV32B           ),
      .BranchTargetALU ( BranchTargetALU )
  ) decoder_i (
      .clk_i                           ( clk_i                ),
      .rst_ni                          ( rst_ni               ),


      .illegal_insn_o                  ( illegal_insn_dec     ),
      .ebrk_insn_o                     ( ebrk_insn            ),
      .mret_insn_o                     ( mret_insn_dec        ),
      .dret_insn_o                     ( dret_insn_dec        ),
      .ecall_insn_o                    ( ecall_insn_dec       ),
      .wfi_insn_o                      ( wfi_insn_dec         ),
      .jump_set_o                      ( jump_set_dec         ),
      .branch_taken_i                  ( branch_taken         ),
      .icache_inval_o                  ( icache_inval_o       ),


      .instr_first_cycle_i             ( instr_first_cycle    ),
      .instr_rdata_i                   ( instr_rdata_i        ),
      .instr_rdata_alu_i               ( instr_rdata_alu_i    ),
      .illegal_c_insn_i                ( illegal_c_insn_i     ),


      .imm_a_mux_sel_o                 ( imm_a_mux_sel        ),
      .imm_b_mux_sel_o                 ( imm_b_mux_sel_dec    ),
      .bt_a_mux_sel_o                  ( bt_a_mux_sel         ),
      .bt_b_mux_sel_o                  ( bt_b_mux_sel         ),

      .imm_i_type_o                    ( imm_i_type           ),
      .imm_s_type_o                    ( imm_s_type           ),
      .imm_b_type_o                    ( imm_b_type           ),
      .imm_u_type_o                    ( imm_u_type           ),
      .imm_j_type_o                    ( imm_j_type           ),
      .zimm_rs1_type_o                 ( zimm_rs1_type        ),


      .rf_wdata_sel_o                  ( rf_wdata_sel         ),
      .rf_we_o                         ( rf_we_dec            ),

      .rf_raddr_a_o                    ( rf_raddr_a_o         ),
      .rf_raddr_b_o                    ( rf_raddr_b_o         ),
      .rf_waddr_o                      ( rf_waddr_id_o        ),
      .rf_ren_a_o                      ( rf_ren_a_dec         ),
      .rf_ren_b_o                      ( rf_ren_b_dec         ),


      .alu_operator_o                  ( alu_operator         ),
      .alu_op_a_mux_sel_o              ( alu_op_a_mux_sel_dec ),
      .alu_op_b_mux_sel_o              ( alu_op_b_mux_sel_dec ),
      .alu_multicycle_o                ( alu_multicycle_dec   ),


      .mult_en_o                       ( mult_en_dec          ),
      .div_en_o                        ( div_en_dec           ),
      .mult_sel_o                      ( mult_sel_ex_o        ),
      .div_sel_o                       ( div_sel_ex_o         ),
      .multdiv_operator_o              ( multdiv_operator     ),
      .multdiv_signed_mode_o           ( multdiv_signed_mode  ),


      .csr_access_o                    ( csr_access_o         ),
      .csr_op_o                        ( csr_op_o             ),


      .data_req_o                      ( lsu_req_dec          ),
      .data_we_o                       ( lsu_we               ),
      .data_type_o                     ( lsu_type             ),
      .data_sign_extension_o           ( lsu_sign_ext         ),


      .jump_in_dec_o                   ( jump_in_dec          ),
      .branch_in_dec_o                 ( branch_in_dec        )
  );




  always_comb begin : csr_pipeline_flushes
    csr_pipe_flush = 1'b0;






    if (csr_op_en_o == 1'b1 && (csr_op_o == CSR_OP_WRITE || csr_op_o == CSR_OP_SET)) begin
      if (csr_num_e'(instr_rdata_i[31:20]) == CSR_MSTATUS   ||
          csr_num_e'(instr_rdata_i[31:20]) == CSR_MIE) begin
        csr_pipe_flush = 1'b1;
      end
    end else if (csr_op_en_o == 1'b1 && csr_op_o != CSR_OP_READ) begin
      if (csr_num_e'(instr_rdata_i[31:20]) == CSR_DCSR      ||
          csr_num_e'(instr_rdata_i[31:20]) == CSR_DPC       ||
          csr_num_e'(instr_rdata_i[31:20]) == CSR_DSCRATCH0 ||
          csr_num_e'(instr_rdata_i[31:20]) == CSR_DSCRATCH1) begin
        csr_pipe_flush = 1'b1;
      end
    end
  end





  assign illegal_insn_o = instr_valid_i & (illegal_insn_dec | illegal_csr_insn_i);

  ibex_controller #(
    .WritebackStage  ( WritebackStage  ),
    .BranchPredictor ( BranchPredictor )
  ) controller_i (
      .clk_i                          ( clk_i                   ),
      .rst_ni                         ( rst_ni                  ),

      .ctrl_busy_o                    ( ctrl_busy_o             ),


      .illegal_insn_i                 ( illegal_insn_o          ),
      .ecall_insn_i                   ( ecall_insn_dec          ),
      .mret_insn_i                    ( mret_insn_dec           ),
      .dret_insn_i                    ( dret_insn_dec           ),
      .wfi_insn_i                     ( wfi_insn_dec            ),
      .ebrk_insn_i                    ( ebrk_insn               ),
      .csr_pipe_flush_i               ( csr_pipe_flush          ),


      .instr_valid_i                  ( instr_valid_i           ),
      .instr_i                        ( instr_rdata_i           ),
      .instr_compressed_i             ( instr_rdata_c_i         ),
      .instr_is_compressed_i          ( instr_is_compressed_i   ),
      .instr_bp_taken_i               ( instr_bp_taken_i        ),
      .instr_fetch_err_i              ( instr_fetch_err_i       ),
      .instr_fetch_err_plus2_i        ( instr_fetch_err_plus2_i ),
      .pc_id_i                        ( pc_id_i                 ),


      .instr_valid_clear_o            ( instr_valid_clear_o     ),
      .id_in_ready_o                  ( id_in_ready_o           ),
      .controller_run_o               ( controller_run          ),


      .instr_req_o                    ( instr_req_o             ),
      .pc_set_o                       ( pc_set_o                ),
      .pc_set_spec_o                  ( pc_set_spec_o           ),
      .pc_mux_o                       ( pc_mux_o                ),
      .nt_branch_mispredict_o         ( nt_branch_mispredict_o  ),
      .exc_pc_mux_o                   ( exc_pc_mux_o            ),
      .exc_cause_o                    ( exc_cause_o             ),


      .lsu_addr_last_i                ( lsu_addr_last_i         ),
      .load_err_i                     ( lsu_load_err_i          ),
      .store_err_i                    ( lsu_store_err_i         ),
      .wb_exception_o                 ( wb_exception            ),


      .branch_set_i                   ( branch_set              ),
      .branch_set_spec_i              ( branch_set_spec         ),
      .branch_not_set_i               ( branch_not_set          ),
      .jump_set_i                     ( jump_set                ),


      .csr_mstatus_mie_i              ( csr_mstatus_mie_i       ),
      .irq_pending_i                  ( irq_pending_i           ),
      .irqs_i                         ( irqs_i                  ),
      .irq_nm_i                       ( irq_nm_i                ),
      .nmi_mode_o                     ( nmi_mode_o              ),


      .csr_save_if_o                  ( csr_save_if_o           ),
      .csr_save_id_o                  ( csr_save_id_o           ),
      .csr_save_wb_o                  ( csr_save_wb_o           ),
      .csr_restore_mret_id_o          ( csr_restore_mret_id_o   ),
      .csr_restore_dret_id_o          ( csr_restore_dret_id_o   ),
      .csr_save_cause_o               ( csr_save_cause_o        ),
      .csr_mtval_o                    ( csr_mtval_o             ),
      .priv_mode_i                    ( priv_mode_i             ),
      .csr_mstatus_tw_i               ( csr_mstatus_tw_i        ),


      .debug_mode_o                   ( debug_mode_o            ),
      .debug_cause_o                  ( debug_cause_o           ),
      .debug_csr_save_o               ( debug_csr_save_o        ),
      .debug_req_i                    ( debug_req_i             ),
      .debug_single_step_i            ( debug_single_step_i     ),
      .debug_ebreakm_i                ( debug_ebreakm_i         ),
      .debug_ebreaku_i                ( debug_ebreaku_i         ),
      .trigger_match_i                ( trigger_match_i         ),

      .stall_id_i                     ( stall_id                ),
      .stall_wb_i                     ( stall_wb                ),
      .flush_id_o                     ( flush_id                ),
      .ready_wb_i                     ( ready_wb_i              ),


      .perf_jump_o                    ( perf_jump_o             ),
      .perf_tbranch_o                 ( perf_tbranch_o          )
  );

  assign multdiv_en_dec   = mult_en_dec | div_en_dec;

  assign lsu_req         = instr_executing ? data_req_allowed & lsu_req_dec  : 1'b0;
  assign mult_en_id      = instr_executing ? mult_en_dec                     : 1'b0;
  assign div_en_id       = instr_executing ? div_en_dec                      : 1'b0;

  assign lsu_req_o               = lsu_req;
  assign lsu_we_o                = lsu_we;
  assign lsu_type_o              = lsu_type;
  assign lsu_sign_ext_o          = lsu_sign_ext;
  assign lsu_wdata_o             = rf_rdata_b_fwd;




  assign csr_op_en_o             = csr_access_o & instr_executing & instr_id_done_o;

  assign alu_operator_ex_o           = alu_operator;
  assign alu_operand_a_ex_o          = alu_operand_a;
  assign alu_operand_b_ex_o          = alu_operand_b;

  assign mult_en_ex_o                = mult_en_id;
  assign div_en_ex_o                 = div_en_id;

  assign multdiv_operator_ex_o       = multdiv_operator;
  assign multdiv_signed_mode_ex_o    = multdiv_signed_mode;
  assign multdiv_operand_a_ex_o      = rf_rdata_a_fwd;
  assign multdiv_operand_b_ex_o      = rf_rdata_b_fwd;





  if (BranchTargetALU && !DataIndTiming) begin : g_branch_set_direct


    assign branch_set_raw      = branch_set_raw_d;
    assign branch_set_raw_spec = branch_spec;
  end else begin : g_branch_set_flop


    logic branch_set_raw_q;

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        branch_set_raw_q <= 1'b0;
      end else begin
        branch_set_raw_q <= branch_set_raw_d;
      end
    end




    assign branch_set_raw      = (BranchTargetALU && !data_ind_timing_i) ? branch_set_raw_d :
                                                                           branch_set_raw_q;


    assign branch_set_raw_spec = (BranchTargetALU && !data_ind_timing_i) ? branch_spec :
                                                                           branch_set_raw_q;
  end


  assign branch_jump_set_done_d = (branch_set_raw | jump_set_raw | branch_jump_set_done_q) &
    ~instr_valid_clear_o;

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      branch_jump_set_done_q <= 1'b0;
    end else begin
      branch_jump_set_done_q <= branch_jump_set_done_d;
    end
  end








  assign jump_set        = jump_set_raw        & ~branch_jump_set_done_q;
  assign branch_set      = branch_set_raw      & ~branch_jump_set_done_q;
  assign branch_set_spec = branch_set_raw_spec & ~branch_jump_set_done_q;



  if (DataIndTiming) begin : g_sec_branch_taken
    logic branch_taken_q;

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        branch_taken_q <= 1'b0;
      end else begin
        branch_taken_q <= branch_decision_i;
      end
    end

    assign branch_taken = ~data_ind_timing_i | branch_taken_q;

  end else begin : g_nosec_branch_taken



    assign branch_taken = 1'b1;

  end




  `ASSERT(NeverDoubleBranch, branch_set & ~instr_bp_taken_i |=> ~branch_set)
  `ASSERT(NeverDoubleJump, jump_set & ~instr_bp_taken_i |=> ~jump_set)





  typedef enum logic { FIRST_CYCLE, MULTI_CYCLE } id_fsm_e;
  id_fsm_e id_fsm_q, id_fsm_d;

  always_ff @(posedge clk_i or negedge rst_ni) begin : id_pipeline_reg
    if (!rst_ni) begin
      id_fsm_q <= FIRST_CYCLE;
    end else if (instr_executing) begin
      id_fsm_q <= id_fsm_d;
    end
  end






  always_comb begin
    id_fsm_d                = id_fsm_q;
    rf_we_raw               = rf_we_dec;
    stall_multdiv           = 1'b0;
    stall_jump              = 1'b0;
    stall_branch            = 1'b0;
    stall_alu               = 1'b0;
    branch_set_raw_d        = 1'b0;
    branch_spec             = 1'b0;
    branch_not_set          = 1'b0;
    jump_set_raw            = 1'b0;
    perf_branch_o           = 1'b0;

    if (instr_executing_spec) begin
      unique case (id_fsm_q)
        FIRST_CYCLE: begin
          unique case (1'b1)
            lsu_req_dec: begin
              if (!WritebackStage) begin

                id_fsm_d    = MULTI_CYCLE;
              end else begin
                if(~lsu_req_done_i) begin
                  id_fsm_d  = MULTI_CYCLE;
                end
              end
            end
            multdiv_en_dec: begin

              if (~ex_valid_i) begin


                id_fsm_d      = MULTI_CYCLE;
                rf_we_raw     = 1'b0;
                stall_multdiv = 1'b1;
              end
            end
            branch_in_dec: begin



              id_fsm_d         = (data_ind_timing_i || (!BranchTargetALU && branch_decision_i)) ?
                                     MULTI_CYCLE : FIRST_CYCLE;
              stall_branch     = (~BranchTargetALU & branch_decision_i) | data_ind_timing_i;
              branch_set_raw_d = (branch_decision_i | data_ind_timing_i);

              if (BranchPredictor) begin
                branch_not_set = ~branch_decision_i;
              end


              branch_spec   = SpecBranch ? 1'b1 : branch_decision_i;
              perf_branch_o = 1'b1;
            end
            jump_in_dec: begin


              id_fsm_d      = BranchTargetALU ? FIRST_CYCLE : MULTI_CYCLE;
              stall_jump    = ~BranchTargetALU;
              jump_set_raw  = jump_set_dec;
            end
            alu_multicycle_dec: begin
              stall_alu     = 1'b1;
              id_fsm_d      = MULTI_CYCLE;
              rf_we_raw     = 1'b0;
            end
            default: begin
              id_fsm_d      = FIRST_CYCLE;
            end
          endcase
        end

        MULTI_CYCLE: begin
          if(multdiv_en_dec) begin
            rf_we_raw       = rf_we_dec & ex_valid_i;
          end

          if (multicycle_done & ready_wb_i) begin
            id_fsm_d        = FIRST_CYCLE;
          end else begin
            stall_multdiv   = multdiv_en_dec;
            stall_branch    = branch_in_dec;
            stall_jump      = jump_in_dec;
          end
        end

        default: begin
          id_fsm_d          = FIRST_CYCLE;
        end
      endcase
    end
  end


  assign multdiv_ready_id_o = ready_wb_i;

  `ASSERT(StallIDIfMulticycle, (id_fsm_q == FIRST_CYCLE) & (id_fsm_d == MULTI_CYCLE) |-> stall_id)




  assign stall_id = stall_ld_hz | stall_mem | stall_multdiv | stall_jump | stall_branch |
                      stall_alu;




  `ASSERT(IllegalInsnStallMustBeMemStall, illegal_insn_o & stall_id |-> stall_mem &
    ~(stall_ld_hz | stall_multdiv | stall_jump | stall_branch | stall_alu))

  assign instr_done = ~stall_id & ~flush_id & instr_executing;



  assign instr_first_cycle      = instr_valid_i & (id_fsm_q == FIRST_CYCLE);


  assign instr_first_cycle_id_o = instr_first_cycle;

  if (WritebackStage) begin : gen_stall_mem

    logic rf_rd_a_wb_match;
    logic rf_rd_b_wb_match;

    logic rf_rd_a_hz;
    logic rf_rd_b_hz;

    logic outstanding_memory_access;

    logic instr_kill;

    assign multicycle_done = lsu_req_dec ? ~stall_mem : ex_valid_i;


    assign outstanding_memory_access = (outstanding_load_wb_i | outstanding_store_wb_i) &
                                       ~lsu_resp_valid_i;


    assign data_req_allowed = ~outstanding_memory_access;









    assign instr_kill = instr_fetch_err_i |
                        wb_exception      |
                        ~controller_run;

















    assign instr_executing_spec = instr_valid_i      &
                                  ~instr_fetch_err_i &
                                  controller_run     &
                                  ~stall_ld_hz;

    assign instr_executing = instr_valid_i              &
                             ~instr_kill                &
                             ~stall_ld_hz               &
                             ~outstanding_memory_access;

    `ASSERT(IbexExecutingSpecIfExecuting, instr_executing |-> instr_executing_spec)

    `ASSERT(IbexStallIfValidInstrNotExecuting,
      instr_valid_i & ~instr_kill & ~instr_executing |-> stall_id)

    `ASSERT(IbexCannotRetireWithPendingExceptions,
      instr_done |-> ~(wb_exception | outstanding_memory_access))






    assign stall_mem = instr_valid_i &
                       (outstanding_memory_access | (lsu_req_dec & ~lsu_req_done_i));



    `ASSERT(IbexStallMemNoRequest,
      instr_valid_i & lsu_req_dec & ~instr_done |-> ~lsu_req_done_i)

    assign rf_rd_a_wb_match = (rf_waddr_wb_i == rf_raddr_a_o) & |rf_raddr_a_o;
    assign rf_rd_b_wb_match = (rf_waddr_wb_i == rf_raddr_b_o) & |rf_raddr_b_o;

    assign rf_rd_a_wb_match_o = rf_rd_a_wb_match;
    assign rf_rd_b_wb_match_o = rf_rd_b_wb_match;



    assign rf_rd_a_hz = rf_rd_a_wb_match & rf_ren_a;
    assign rf_rd_b_hz = rf_rd_b_wb_match & rf_ren_b;




    assign rf_rdata_a_fwd = rf_rd_a_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_a_i;
    assign rf_rdata_b_fwd = rf_rd_b_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_b_i;

    assign stall_ld_hz = outstanding_load_wb_i & (rf_rd_a_hz | rf_rd_b_hz);

    assign instr_type_wb_o = ~lsu_req_dec ? WB_INSTR_OTHER :
                              lsu_we      ? WB_INSTR_STORE :
                                            WB_INSTR_LOAD;

    assign instr_id_done_o = en_wb_o & ready_wb_i;


    assign stall_wb = en_wb_o & ~ready_wb_i;

    assign perf_dside_wait_o = instr_valid_i & ~instr_kill &
                               (outstanding_memory_access | stall_ld_hz);
  end else begin : gen_no_stall_mem

    assign multicycle_done = lsu_req_dec ? lsu_resp_valid_i : ex_valid_i;

    assign data_req_allowed = instr_first_cycle;



    assign stall_mem = instr_valid_i & (lsu_req_dec & (~lsu_resp_valid_i | instr_first_cycle));


    assign stall_ld_hz   = 1'b0;


    assign instr_executing_spec = instr_valid_i & ~instr_fetch_err_i & controller_run;
    assign instr_executing = instr_executing_spec;

    `ASSERT(IbexStallIfValidInstrNotExecuting,
      instr_valid_i & ~instr_fetch_err_i & ~instr_executing & controller_run |-> stall_id)



    assign rf_rdata_a_fwd = rf_rdata_a_i;
    assign rf_rdata_b_fwd = rf_rdata_b_i;

    assign rf_rd_a_wb_match_o = 1'b0;
    assign rf_rd_b_wb_match_o = 1'b0;




    logic unused_data_req_done_ex;
    logic [4:0] unused_rf_waddr_wb;
    logic unused_rf_write_wb;
    logic unused_outstanding_load_wb;
    logic unused_outstanding_store_wb;
    logic unused_wb_exception;
    logic [31:0] unused_rf_wdata_fwd_wb;

    assign unused_data_req_done_ex     = lsu_req_done_i;
    assign unused_rf_waddr_wb          = rf_waddr_wb_i;
    assign unused_rf_write_wb          = rf_write_wb_i;
    assign unused_outstanding_load_wb  = outstanding_load_wb_i;
    assign unused_outstanding_store_wb = outstanding_store_wb_i;
    assign unused_wb_exception         = wb_exception;
    assign unused_rf_wdata_fwd_wb      = rf_wdata_fwd_wb_i;

    assign instr_type_wb_o = WB_INSTR_OTHER;
    assign stall_wb        = 1'b0;

    assign perf_dside_wait_o = instr_executing & lsu_req_dec & ~lsu_resp_valid_i;

    assign instr_id_done_o = instr_done;
  end



  assign instr_perf_count_id_o = ~ebrk_insn & ~ecall_insn_dec & ~illegal_insn_dec &
      ~illegal_csr_insn_i & ~instr_fetch_err_i;



  assign en_wb_o = instr_done;

  assign perf_mul_wait_o = stall_multdiv & mult_en_dec;
  assign perf_div_wait_o = stall_multdiv & div_en_dec;





  `DV_FCOV_SIGNAL_GEN_IF(logic, rf_rd_wb_hz,
    (gen_stall_mem.rf_rd_a_hz | gen_stall_mem.rf_rd_b_hz) & instr_valid_i, WritebackStage)
  `DV_FCOV_SIGNAL(logic, branch_taken,
    instr_executing & (id_fsm_q == FIRST_CYCLE) & branch_decision_i)
  `DV_FCOV_SIGNAL(logic, branch_not_taken,
    instr_executing & (id_fsm_q == FIRST_CYCLE) & ~branch_decision_i)






  `ASSERT_KNOWN_IF(IbexAluOpMuxSelKnown, alu_op_a_mux_sel, instr_valid_i)
  `ASSERT(IbexAluAOpMuxSelValid, instr_valid_i |-> alu_op_a_mux_sel inside {
      OP_A_REG_A,
      OP_A_FWD,
      OP_A_CURRPC,
      OP_A_IMM})
  `ASSERT_KNOWN_IF(IbexBTAluAOpMuxSelKnown, bt_a_mux_sel, instr_valid_i)
  `ASSERT(IbexBTAluAOpMuxSelValid, instr_valid_i |-> bt_a_mux_sel inside {
      OP_A_REG_A,
      OP_A_CURRPC})
  `ASSERT_KNOWN_IF(IbexBTAluBOpMuxSelKnown, bt_b_mux_sel, instr_valid_i)
  `ASSERT(IbexBTAluBOpMuxSelValid, instr_valid_i |-> bt_b_mux_sel inside {
      IMM_B_I,
      IMM_B_B,
      IMM_B_J,
      IMM_B_INCR_PC})
  `ASSERT(IbexRegfileWdataSelValid, instr_valid_i |-> rf_wdata_sel inside {
      RF_WD_EX,
      RF_WD_CSR})
  `ASSERT_KNOWN(IbexWbStateKnown, id_fsm_q)


  `ASSERT_KNOWN_IF(IbexBranchDecisionValid, branch_decision_i,
      instr_valid_i && !(illegal_csr_insn_i || instr_fetch_err_i))


  `ASSERT_KNOWN_IF(IbexIdInstrKnown, instr_rdata_i,
      instr_valid_i && !(illegal_c_insn_i || instr_fetch_err_i))


  `ASSERT_KNOWN_IF(IbexIdInstrALUKnown, instr_rdata_alu_i,
      instr_valid_i && !(illegal_c_insn_i || instr_fetch_err_i))


  `ASSERT(IbexMulticycleEnableUnique,
      $onehot0({lsu_req_dec, multdiv_en_dec, branch_in_dec, jump_in_dec}))




  `ASSERT(IbexDuplicateInstrMatch, instr_valid_i |-> instr_rdata_i === instr_rdata_alu_i)

  `ifdef CHECK_MISALIGNED
  `ASSERT(IbexMisalignedMemoryAccess, !lsu_addr_incr_req_i)
  `endif

endmodule
module ibex_id_stage #(
    parameter bit               RV32E           = 0,
    parameter ibex_pkg::rv32m_e RV32M           = ibex_pkg::RV32MFast,
    parameter ibex_pkg::rv32b_e RV32B           = ibex_pkg::RV32BNone,
    parameter bit               DataIndTiming   = 1'b0,
    parameter bit               BranchTargetALU = 0,
    parameter bit               SpecBranch      = 0,
    parameter bit               WritebackStage  = 0,
    parameter bit               BranchPredictor = 0
) (
    input  logic                      clk_i,
    input  logic                      rst_ni,

    output logic                      ctrl_busy_o,
    output logic                      illegal_insn_o,


    input  logic                      instr_valid_i,
    input  logic [31:0]               instr_rdata_i,
    input  logic [31:0]               instr_rdata_alu_i,
    input  logic [15:0]               instr_rdata_c_i,
    input  logic                      instr_is_compressed_i,
    input  logic                      instr_bp_taken_i,
    output logic                      instr_req_o,
    output logic                      instr_first_cycle_id_o,
    output logic                      instr_valid_clear_o,
    output logic                      id_in_ready_o,
    output logic                      icache_inval_o,


    input  logic                      branch_decision_i,


    output logic                      pc_set_o,
    output logic                      pc_set_spec_o,
    output ibex_pkg::pc_sel_e         pc_mux_o,
    output logic                      nt_branch_mispredict_o,
    output ibex_pkg::exc_pc_sel_e     exc_pc_mux_o,
    output ibex_pkg::exc_cause_e      exc_cause_o,

    input  logic                      illegal_c_insn_i,
    input  logic                      instr_fetch_err_i,
    input  logic                      instr_fetch_err_plus2_i,

    input  logic [31:0]               pc_id_i,


    input  logic                      ex_valid_i,
    input  logic                      lsu_resp_valid_i,

    output ibex_pkg::alu_op_e         alu_operator_ex_o,
    output logic [31:0]               alu_operand_a_ex_o,
    output logic [31:0]               alu_operand_b_ex_o,


    input  logic [1:0]                imd_val_we_ex_i,
    input  logic [33:0]               imd_val_d_ex_i[2],
    output logic [33:0]               imd_val_q_ex_o[2],


    output logic [31:0]               bt_a_operand_o,
    output logic [31:0]               bt_b_operand_o,


    output logic                      mult_en_ex_o,
    output logic                      div_en_ex_o,
    output logic                      mult_sel_ex_o,
    output logic                      div_sel_ex_o,
    output ibex_pkg::md_op_e          multdiv_operator_ex_o,
    output logic  [1:0]               multdiv_signed_mode_ex_o,
    output logic [31:0]               multdiv_operand_a_ex_o,
    output logic [31:0]               multdiv_operand_b_ex_o,
    output logic                      multdiv_ready_id_o,


    output logic                      csr_access_o,
    output ibex_pkg::csr_op_e         csr_op_o,
    output logic                      csr_op_en_o,
    output logic                      csr_save_if_o,
    output logic                      csr_save_id_o,
    output logic                      csr_save_wb_o,
    output logic                      csr_restore_mret_id_o,
    output logic                      csr_restore_dret_id_o,
    output logic                      csr_save_cause_o,
    output logic [31:0]               csr_mtval_o,
    input  ibex_pkg::priv_lvl_e       priv_mode_i,
    input  logic                      csr_mstatus_tw_i,
    input  logic                      illegal_csr_insn_i,
    input  logic                      data_ind_timing_i,


    output logic                      lsu_req_o,
    output logic                      lsu_we_o,
    output logic [1:0]                lsu_type_o,
    output logic                      lsu_sign_ext_o,
    output logic [31:0]               lsu_wdata_o,

    input  logic                      lsu_req_done_i,




    input  logic                      lsu_addr_incr_req_i,
    input  logic [31:0]               lsu_addr_last_i,


    input  logic                      csr_mstatus_mie_i,
    input  logic                      irq_pending_i,
    input  ibex_pkg::irqs_t           irqs_i,
    input  logic                      irq_nm_i,
    output logic                      nmi_mode_o,

    input  logic                      lsu_load_err_i,
    input  logic                      lsu_store_err_i,


    output logic                      debug_mode_o,
    output ibex_pkg::dbg_cause_e      debug_cause_o,
    output logic                      debug_csr_save_o,
    input  logic                      debug_req_i,
    input  logic                      debug_single_step_i,
    input  logic                      debug_ebreakm_i,
    input  logic                      debug_ebreaku_i,
    input  logic                      trigger_match_i,


    input  logic [31:0]               result_ex_i,
    input  logic [31:0]               csr_rdata_i,


    output logic [4:0]                rf_raddr_a_o,
    input  logic [31:0]               rf_rdata_a_i,
    output logic [4:0]                rf_raddr_b_o,
    input  logic [31:0]               rf_rdata_b_i,
    output logic                      rf_ren_a_o,
    output logic                      rf_ren_b_o,


    output logic [4:0]                rf_waddr_id_o,
    output logic [31:0]               rf_wdata_id_o,
    output logic                      rf_we_id_o,
    output logic                      rf_rd_a_wb_match_o,
    output logic                      rf_rd_b_wb_match_o,


    input  logic [4:0]                rf_waddr_wb_i,
    input  logic [31:0]               rf_wdata_fwd_wb_i,
    input  logic                      rf_write_wb_i,

    output  logic                     en_wb_o,
    output  ibex_pkg::wb_instr_type_e instr_type_wb_o,
    output  logic                     instr_perf_count_id_o,
    input logic                       ready_wb_i,
    input logic                       outstanding_load_wb_i,
    input logic                       outstanding_store_wb_i,


    output logic                      perf_jump_o,
    output logic                      perf_branch_o,
    output logic                      perf_tbranch_o,
    output logic                      perf_dside_wait_o,

    output logic                      perf_mul_wait_o,
    output logic                      perf_div_wait_o,
    output logic                      instr_id_done_o
);


  import ibex_pkg::*;


  logic        illegal_insn_dec;
  logic        ebrk_insn;
  logic        mret_insn_dec;
  logic        dret_insn_dec;
  logic        ecall_insn_dec;
  logic        wfi_insn_dec;

  logic        wb_exception;

  logic        branch_in_dec;
  logic        branch_spec, branch_set_spec, branch_set_raw_spec;
  logic        branch_set, branch_set_raw, branch_set_raw_d;
  logic        branch_jump_set_done_q, branch_jump_set_done_d;
  logic        branch_not_set;
  logic        branch_taken;
  logic        jump_in_dec;
  logic        jump_set_dec;
  logic        jump_set, jump_set_raw;

  logic        instr_first_cycle;
  logic        instr_executing_spec;
  logic        instr_executing;
  logic        instr_done;
  logic        controller_run;
  logic        stall_ld_hz;
  logic        stall_mem;
  logic        stall_multdiv;
  logic        stall_branch;
  logic        stall_jump;
  logic        stall_id;
  logic        stall_wb;
  logic        flush_id;
  logic        multicycle_done;


  logic [31:0] imm_i_type;
  logic [31:0] imm_s_type;
  logic [31:0] imm_b_type;
  logic [31:0] imm_u_type;
  logic [31:0] imm_j_type;
  logic [31:0] zimm_rs1_type;

  logic [31:0] imm_a;
  logic [31:0] imm_b;



  rf_wd_sel_e  rf_wdata_sel;
  logic        rf_we_dec, rf_we_raw;
  logic        rf_ren_a, rf_ren_b;
  logic        rf_ren_a_dec, rf_ren_b_dec;


  assign rf_ren_a = instr_valid_i & ~instr_fetch_err_i & ~illegal_insn_o & rf_ren_a_dec;
  assign rf_ren_b = instr_valid_i & ~instr_fetch_err_i & ~illegal_insn_o & rf_ren_b_dec;

  assign rf_ren_a_o = rf_ren_a;
  assign rf_ren_b_o = rf_ren_b;

  logic [31:0] rf_rdata_a_fwd;
  logic [31:0] rf_rdata_b_fwd;


  alu_op_e     alu_operator;
  op_a_sel_e   alu_op_a_mux_sel, alu_op_a_mux_sel_dec;
  op_b_sel_e   alu_op_b_mux_sel, alu_op_b_mux_sel_dec;
  logic        alu_multicycle_dec;
  logic        stall_alu;

  logic [33:0] imd_val_q[2];

  op_a_sel_e   bt_a_mux_sel;
  imm_b_sel_e  bt_b_mux_sel;

  imm_a_sel_e  imm_a_mux_sel;
  imm_b_sel_e  imm_b_mux_sel, imm_b_mux_sel_dec;


  logic        mult_en_id, mult_en_dec;
  logic        div_en_id, div_en_dec;
  logic        multdiv_en_dec;
  md_op_e      multdiv_operator;
  logic [1:0]  multdiv_signed_mode;


  logic        lsu_we;
  logic [1:0]  lsu_type;
  logic        lsu_sign_ext;
  logic        lsu_req, lsu_req_dec;
  logic        data_req_allowed;


  logic        csr_pipe_flush;

  logic [31:0] alu_operand_a;
  logic [31:0] alu_operand_b;






  assign alu_op_a_mux_sel = lsu_addr_incr_req_i ? OP_A_FWD        : alu_op_a_mux_sel_dec;
  assign alu_op_b_mux_sel = lsu_addr_incr_req_i ? OP_B_IMM        : alu_op_b_mux_sel_dec;
  assign imm_b_mux_sel    = lsu_addr_incr_req_i ? IMM_B_INCR_ADDR : imm_b_mux_sel_dec;






  assign imm_a = (imm_a_mux_sel == IMM_A_Z) ? zimm_rs1_type : '0;


  always_comb begin : alu_operand_a_mux
    unique case (alu_op_a_mux_sel)
      OP_A_REG_A:  alu_operand_a = rf_rdata_a_fwd;
      OP_A_FWD:    alu_operand_a = lsu_addr_last_i;
      OP_A_CURRPC: alu_operand_a = pc_id_i;
      OP_A_IMM:    alu_operand_a = imm_a;
      default:     alu_operand_a = pc_id_i;
    endcase
  end

  if (BranchTargetALU) begin : g_btalu_muxes

    always_comb begin : bt_operand_a_mux
      unique case (bt_a_mux_sel)
        OP_A_REG_A:  bt_a_operand_o = rf_rdata_a_fwd;
        OP_A_CURRPC: bt_a_operand_o = pc_id_i;
        default:     bt_a_operand_o = pc_id_i;
      endcase
    end


    always_comb begin : bt_immediate_b_mux
      unique case (bt_b_mux_sel)
        IMM_B_I:         bt_b_operand_o = imm_i_type;
        IMM_B_B:         bt_b_operand_o = imm_b_type;
        IMM_B_J:         bt_b_operand_o = imm_j_type;
        IMM_B_INCR_PC:   bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4;
        default:         bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4;
      endcase
    end


    always_comb begin : immediate_b_mux
      unique case (imm_b_mux_sel)
        IMM_B_I:         imm_b = imm_i_type;
        IMM_B_S:         imm_b = imm_s_type;
        IMM_B_U:         imm_b = imm_u_type;
        IMM_B_INCR_PC:   imm_b = instr_is_compressed_i ? 32'h2 : 32'h4;
        IMM_B_INCR_ADDR: imm_b = 32'h4;
        default:         imm_b = 32'h4;
      endcase
    end
    `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside {
        IMM_B_I,
        IMM_B_S,
        IMM_B_U,
        IMM_B_INCR_PC,
        IMM_B_INCR_ADDR})
  end else begin : g_nobtalu
    op_a_sel_e  unused_a_mux_sel;
    imm_b_sel_e unused_b_mux_sel;

    assign unused_a_mux_sel = bt_a_mux_sel;
    assign unused_b_mux_sel = bt_b_mux_sel;
    assign bt_a_operand_o   = '0;
    assign bt_b_operand_o   = '0;


    always_comb begin : immediate_b_mux
      unique case (imm_b_mux_sel)
        IMM_B_I:         imm_b = imm_i_type;
        IMM_B_S:         imm_b = imm_s_type;
        IMM_B_B:         imm_b = imm_b_type;
        IMM_B_U:         imm_b = imm_u_type;
        IMM_B_J:         imm_b = imm_j_type;
        IMM_B_INCR_PC:   imm_b = instr_is_compressed_i ? 32'h2 : 32'h4;
        IMM_B_INCR_ADDR: imm_b = 32'h4;
        default:         imm_b = 32'h4;
      endcase
    end
    `ASSERT(IbexImmBMuxSelValid, instr_valid_i |-> imm_b_mux_sel inside {
        IMM_B_I,
        IMM_B_S,
        IMM_B_B,
        IMM_B_U,
        IMM_B_J,
        IMM_B_INCR_PC,
        IMM_B_INCR_ADDR})
  end


  assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : rf_rdata_b_fwd;





  for (genvar i=0; i<2; i++) begin : gen_intermediate_val_reg
    always_ff @(posedge clk_i or negedge rst_ni) begin : intermediate_val_reg
      if (!rst_ni) begin
        imd_val_q[i] <= '0;
      end else if (imd_val_we_ex_i[i]) begin
        imd_val_q[i] <= imd_val_d_ex_i[i];
      end
    end
  end

  assign imd_val_q_ex_o = imd_val_q;






  assign rf_we_id_o = rf_we_raw & instr_executing & ~illegal_csr_insn_i;


  always_comb begin : rf_wdata_id_mux
    unique case (rf_wdata_sel)
      RF_WD_EX:  rf_wdata_id_o = result_ex_i;
      RF_WD_CSR: rf_wdata_id_o = csr_rdata_i;
      default:   rf_wdata_id_o = result_ex_i;
    endcase
  end





  ibex_decoder #(
      .RV32E           ( RV32E           ),
      .RV32M           ( RV32M           ),
      .RV32B           ( RV32B           ),
      .BranchTargetALU ( BranchTargetALU )
  ) decoder_i (
      .clk_i                           ( clk_i                ),
      .rst_ni                          ( rst_ni               ),


      .illegal_insn_o                  ( illegal_insn_dec     ),
      .ebrk_insn_o                     ( ebrk_insn            ),
      .mret_insn_o                     ( mret_insn_dec        ),
      .dret_insn_o                     ( dret_insn_dec        ),
      .ecall_insn_o                    ( ecall_insn_dec       ),
      .wfi_insn_o                      ( wfi_insn_dec         ),
      .jump_set_o                      ( jump_set_dec         ),
      .branch_taken_i                  ( branch_taken         ),
      .icache_inval_o                  ( icache_inval_o       ),


      .instr_first_cycle_i             ( instr_first_cycle    ),
      .instr_rdata_i                   ( instr_rdata_i        ),
      .instr_rdata_alu_i               ( instr_rdata_alu_i    ),
      .illegal_c_insn_i                ( illegal_c_insn_i     ),


      .imm_a_mux_sel_o                 ( imm_a_mux_sel        ),
      .imm_b_mux_sel_o                 ( imm_b_mux_sel_dec    ),
      .bt_a_mux_sel_o                  ( bt_a_mux_sel         ),
      .bt_b_mux_sel_o                  ( bt_b_mux_sel         ),

      .imm_i_type_o                    ( imm_i_type           ),
      .imm_s_type_o                    ( imm_s_type           ),
      .imm_b_type_o                    ( imm_b_type           ),
      .imm_u_type_o                    ( imm_u_type           ),
      .imm_j_type_o                    ( imm_j_type           ),
      .zimm_rs1_type_o                 ( zimm_rs1_type        ),


      .rf_wdata_sel_o                  ( rf_wdata_sel         ),
      .rf_we_o                         ( rf_we_dec            ),

      .rf_raddr_a_o                    ( rf_raddr_a_o         ),
      .rf_raddr_b_o                    ( rf_raddr_b_o         ),
      .rf_waddr_o                      ( rf_waddr_id_o        ),
      .rf_ren_a_o                      ( rf_ren_a_dec         ),
      .rf_ren_b_o                      ( rf_ren_b_dec         ),


      .alu_operator_o                  ( alu_operator         ),
      .alu_op_a_mux_sel_o              ( alu_op_a_mux_sel_dec ),
      .alu_op_b_mux_sel_o              ( alu_op_b_mux_sel_dec ),
      .alu_multicycle_o                ( alu_multicycle_dec   ),


      .mult_en_o                       ( mult_en_dec          ),
      .div_en_o                        ( div_en_dec           ),
      .mult_sel_o                      ( mult_sel_ex_o        ),
      .div_sel_o                       ( div_sel_ex_o         ),
      .multdiv_operator_o              ( multdiv_operator     ),
      .multdiv_signed_mode_o           ( multdiv_signed_mode  ),


      .csr_access_o                    ( csr_access_o         ),
      .csr_op_o                        ( csr_op_o             ),


      .data_req_o                      ( lsu_req_dec          ),
      .data_we_o                       ( lsu_we               ),
      .data_type_o                     ( lsu_type             ),
      .data_sign_extension_o           ( lsu_sign_ext         ),


      .jump_in_dec_o                   ( jump_in_dec          ),
      .branch_in_dec_o                 ( branch_in_dec        )
  );




  always_comb begin : csr_pipeline_flushes
    csr_pipe_flush = 1'b0;






    if (csr_op_en_o == 1'b1 && (csr_op_o == CSR_OP_WRITE || csr_op_o == CSR_OP_SET)) begin
      if (csr_num_e'(instr_rdata_i[31:20]) == CSR_MSTATUS   ||
          csr_num_e'(instr_rdata_i[31:20]) == CSR_MIE) begin
        csr_pipe_flush = 1'b1;
      end
    end else if (csr_op_en_o == 1'b1 && csr_op_o != CSR_OP_READ) begin
      if (csr_num_e'(instr_rdata_i[31:20]) == CSR_DCSR      ||
          csr_num_e'(instr_rdata_i[31:20]) == CSR_DPC       ||
          csr_num_e'(instr_rdata_i[31:20]) == CSR_DSCRATCH0 ||
          csr_num_e'(instr_rdata_i[31:20]) == CSR_DSCRATCH1) begin
        csr_pipe_flush = 1'b1;
      end
    end
  end





  assign illegal_insn_o = instr_valid_i & (illegal_insn_dec | illegal_csr_insn_i);

  ibex_controller #(
    .WritebackStage  ( WritebackStage  ),
    .BranchPredictor ( BranchPredictor )
  ) controller_i (
      .clk_i                          ( clk_i                   ),
      .rst_ni                         ( rst_ni                  ),

      .ctrl_busy_o                    ( ctrl_busy_o             ),


      .illegal_insn_i                 ( illegal_insn_o          ),
      .ecall_insn_i                   ( ecall_insn_dec          ),
      .mret_insn_i                    ( mret_insn_dec           ),
      .dret_insn_i                    ( dret_insn_dec           ),
      .wfi_insn_i                     ( wfi_insn_dec            ),
      .ebrk_insn_i                    ( ebrk_insn               ),
      .csr_pipe_flush_i               ( csr_pipe_flush          ),


      .instr_valid_i                  ( instr_valid_i           ),
      .instr_i                        ( instr_rdata_i           ),
      .instr_compressed_i             ( instr_rdata_c_i         ),
      .instr_is_compressed_i          ( instr_is_compressed_i   ),
      .instr_bp_taken_i               ( instr_bp_taken_i        ),
      .instr_fetch_err_i              ( instr_fetch_err_i       ),
      .instr_fetch_err_plus2_i        ( instr_fetch_err_plus2_i ),
      .pc_id_i                        ( pc_id_i                 ),


      .instr_valid_clear_o            ( instr_valid_clear_o     ),
      .id_in_ready_o                  ( id_in_ready_o           ),
      .controller_run_o               ( controller_run          ),


      .instr_req_o                    ( instr_req_o             ),
      .pc_set_o                       ( pc_set_o                ),
      .pc_set_spec_o                  ( pc_set_spec_o           ),
      .pc_mux_o                       ( pc_mux_o                ),
      .nt_branch_mispredict_o         ( nt_branch_mispredict_o  ),
      .exc_pc_mux_o                   ( exc_pc_mux_o            ),
      .exc_cause_o                    ( exc_cause_o             ),


      .lsu_addr_last_i                ( lsu_addr_last_i         ),
      .load_err_i                     ( lsu_load_err_i          ),
      .store_err_i                    ( lsu_store_err_i         ),
      .wb_exception_o                 ( wb_exception            ),


      .branch_set_i                   ( branch_set              ),
      .branch_set_spec_i              ( branch_set_spec         ),
      .branch_not_set_i               ( branch_not_set          ),
      .jump_set_i                     ( jump_set                ),


      .csr_mstatus_mie_i              ( csr_mstatus_mie_i       ),
      .irq_pending_i                  ( irq_pending_i           ),
      .irqs_i                         ( irqs_i                  ),
      .irq_nm_i                       ( irq_nm_i                ),
      .nmi_mode_o                     ( nmi_mode_o              ),


      .csr_save_if_o                  ( csr_save_if_o           ),
      .csr_save_id_o                  ( csr_save_id_o           ),
      .csr_save_wb_o                  ( csr_save_wb_o           ),
      .csr_restore_mret_id_o          ( csr_restore_mret_id_o   ),
      .csr_restore_dret_id_o          ( csr_restore_dret_id_o   ),
      .csr_save_cause_o               ( csr_save_cause_o        ),
      .csr_mtval_o                    ( csr_mtval_o             ),
      .priv_mode_i                    ( priv_mode_i             ),
      .csr_mstatus_tw_i               ( csr_mstatus_tw_i        ),


      .debug_mode_o                   ( debug_mode_o            ),
      .debug_cause_o                  ( debug_cause_o           ),
      .debug_csr_save_o               ( debug_csr_save_o        ),
      .debug_req_i                    ( debug_req_i             ),
      .debug_single_step_i            ( debug_single_step_i     ),
      .debug_ebreakm_i                ( debug_ebreakm_i         ),
      .debug_ebreaku_i                ( debug_ebreaku_i         ),
      .trigger_match_i                ( trigger_match_i         ),

      .stall_id_i                     ( stall_id                ),
      .stall_wb_i                     ( stall_wb                ),
      .flush_id_o                     ( flush_id                ),
      .ready_wb_i                     ( ready_wb_i              ),


      .perf_jump_o                    ( perf_jump_o             ),
      .perf_tbranch_o                 ( perf_tbranch_o          )
  );

  assign multdiv_en_dec   = mult_en_dec | div_en_dec;

  assign lsu_req         = instr_executing ? data_req_allowed & lsu_req_dec  : 1'b0;
  assign mult_en_id      = instr_executing ? mult_en_dec                     : 1'b0;
  assign div_en_id       = instr_executing ? div_en_dec                      : 1'b0;

  assign lsu_req_o               = lsu_req;
  assign lsu_we_o                = lsu_we;
  assign lsu_type_o              = lsu_type;
  assign lsu_sign_ext_o          = lsu_sign_ext;
  assign lsu_wdata_o             = rf_rdata_b_fwd;




  assign csr_op_en_o             = csr_access_o & instr_executing & instr_id_done_o;

  assign alu_operator_ex_o           = alu_operator;
  assign alu_operand_a_ex_o          = alu_operand_a;
  assign alu_operand_b_ex_o          = alu_operand_b;

  assign mult_en_ex_o                = mult_en_id;
  assign div_en_ex_o                 = div_en_id;

  assign multdiv_operator_ex_o       = multdiv_operator;
  assign multdiv_signed_mode_ex_o    = multdiv_signed_mode;
  assign multdiv_operand_a_ex_o      = rf_rdata_a_fwd;
  assign multdiv_operand_b_ex_o      = rf_rdata_b_fwd;





  if (BranchTargetALU && !DataIndTiming) begin : g_branch_set_direct


    assign branch_set_raw      = branch_set_raw_d;
    assign branch_set_raw_spec = branch_spec;
  end else begin : g_branch_set_flop


    logic branch_set_raw_q;

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        branch_set_raw_q <= 1'b0;
      end else begin
        branch_set_raw_q <= branch_set_raw_d;
      end
    end




    assign branch_set_raw      = (BranchTargetALU && !data_ind_timing_i) ? branch_set_raw_d :
                                                                           branch_set_raw_q;


    assign branch_set_raw_spec = (BranchTargetALU && !data_ind_timing_i) ? branch_spec :
                                                                           branch_set_raw_q;
  end


  assign branch_jump_set_done_d = (branch_set_raw | jump_set_raw | branch_jump_set_done_q) &
    ~instr_valid_clear_o;

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      branch_jump_set_done_q <= 1'b0;
    end else begin
      branch_jump_set_done_q <= branch_jump_set_done_d;
    end
  end








  assign jump_set        = jump_set_raw        & ~branch_jump_set_done_q;
  assign branch_set      = branch_set_raw      & ~branch_jump_set_done_q;
  assign branch_set_spec = branch_set_raw_spec & ~branch_jump_set_done_q;



  if (DataIndTiming) begin : g_sec_branch_taken
    logic branch_taken_q;

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        branch_taken_q <= 1'b0;
      end else begin
        branch_taken_q <= branch_decision_i;
      end
    end

    assign branch_taken = ~data_ind_timing_i | branch_taken_q;

  end else begin : g_nosec_branch_taken



    assign branch_taken = 1'b1;

  end




  `ASSERT(NeverDoubleBranch, branch_set & ~instr_bp_taken_i |=> ~branch_set)
  `ASSERT(NeverDoubleJump, jump_set & ~instr_bp_taken_i |=> ~jump_set)





  typedef enum logic { FIRST_CYCLE, MULTI_CYCLE } id_fsm_e;
  id_fsm_e id_fsm_q, id_fsm_d;

  always_ff @(posedge clk_i or negedge rst_ni) begin : id_pipeline_reg
    if (!rst_ni) begin
      id_fsm_q <= FIRST_CYCLE;
    end else if (instr_executing) begin
      id_fsm_q <= id_fsm_d;
    end
  end






  always_comb begin
    id_fsm_d                = id_fsm_q;
    rf_we_raw               = rf_we_dec;
    stall_multdiv           = 1'b0;
    stall_jump              = 1'b0;
    stall_branch            = 1'b0;
    stall_alu               = 1'b0;
    branch_set_raw_d        = 1'b0;
    branch_spec             = 1'b0;
    branch_not_set          = 1'b0;
    jump_set_raw            = 1'b0;
    perf_branch_o           = 1'b0;

    if (instr_executing_spec) begin
      unique case (id_fsm_q)
        FIRST_CYCLE: begin
          unique case (1'b1)
            lsu_req_dec: begin
              if (!WritebackStage) begin

                id_fsm_d    = MULTI_CYCLE;
              end else begin
                if(~lsu_req_done_i) begin
                  id_fsm_d  = MULTI_CYCLE;
                end
              end
            end
            multdiv_en_dec: begin

              if (~ex_valid_i) begin


                id_fsm_d      = MULTI_CYCLE;
                rf_we_raw     = 1'b0;
                stall_multdiv = 1'b1;
              end
            end
            branch_in_dec: begin



              id_fsm_d         = (data_ind_timing_i || (!BranchTargetALU && branch_decision_i)) ?
                                     MULTI_CYCLE : FIRST_CYCLE;
              stall_branch     = (~BranchTargetALU & branch_decision_i) | data_ind_timing_i;
              branch_set_raw_d = (branch_decision_i | data_ind_timing_i);

              if (BranchPredictor) begin
                branch_not_set = ~branch_decision_i;
              end


              branch_spec   = SpecBranch ? 1'b1 : branch_decision_i;
              perf_branch_o = 1'b1;
            end
            jump_in_dec: begin


              id_fsm_d      = BranchTargetALU ? FIRST_CYCLE : MULTI_CYCLE;
              stall_jump    = ~BranchTargetALU;
              jump_set_raw  = jump_set_dec;
            end
            alu_multicycle_dec: begin
              stall_alu     = 1'b1;
              id_fsm_d      = MULTI_CYCLE;
              rf_we_raw     = 1'b0;
            end
            default: begin
              id_fsm_d      = FIRST_CYCLE;
            end
          endcase
        end

        MULTI_CYCLE: begin
          if(multdiv_en_dec) begin
            rf_we_raw       = rf_we_dec & ex_valid_i;
          end

          if (multicycle_done & ready_wb_i) begin
            id_fsm_d        = FIRST_CYCLE;
          end else begin
            stall_multdiv   = multdiv_en_dec;
            stall_branch    = branch_in_dec;
            stall_jump      = jump_in_dec;
          end
        end

        default: begin
          id_fsm_d          = FIRST_CYCLE;
        end
      endcase
    end
  end


  assign multdiv_ready_id_o = ready_wb_i;

  `ASSERT(StallIDIfMulticycle, (id_fsm_q == FIRST_CYCLE) & (id_fsm_d == MULTI_CYCLE) |-> stall_id)




  assign stall_id = stall_ld_hz | stall_mem | stall_multdiv | stall_jump | stall_branch |
                      stall_alu;




  `ASSERT(IllegalInsnStallMustBeMemStall, illegal_insn_o & stall_id |-> stall_mem &
    ~(stall_ld_hz | stall_multdiv | stall_jump | stall_branch | stall_alu))

  assign instr_done = ~stall_id & ~flush_id & instr_executing;



  assign instr_first_cycle      = instr_valid_i & (id_fsm_q == FIRST_CYCLE);


  assign instr_first_cycle_id_o = instr_first_cycle;

  if (WritebackStage) begin : gen_stall_mem

    logic rf_rd_a_wb_match;
    logic rf_rd_b_wb_match;

    logic rf_rd_a_hz;
    logic rf_rd_b_hz;

    logic outstanding_memory_access;

    logic instr_kill;

    assign multicycle_done = lsu_req_dec ? ~stall_mem : ex_valid_i;


    assign outstanding_memory_access = (outstanding_load_wb_i | outstanding_store_wb_i) &
                                       ~lsu_resp_valid_i;


    assign data_req_allowed = ~outstanding_memory_access;









    assign instr_kill = instr_fetch_err_i |
                        wb_exception      |
                        ~controller_run;

















    assign instr_executing_spec = instr_valid_i      &
                                  ~instr_fetch_err_i &
                                  controller_run     &
                                  ~stall_ld_hz;

    assign instr_executing = instr_valid_i              &
                             ~instr_kill                &
                             ~stall_ld_hz               &
                             ~outstanding_memory_access;

    `ASSERT(IbexExecutingSpecIfExecuting, instr_executing |-> instr_executing_spec)

    `ASSERT(IbexStallIfValidInstrNotExecuting,
      instr_valid_i & ~instr_kill & ~instr_executing |-> stall_id)

    `ASSERT(IbexCannotRetireWithPendingExceptions,
      instr_done |-> ~(wb_exception | outstanding_memory_access))






    assign stall_mem = instr_valid_i &
                       (outstanding_memory_access | (lsu_req_dec & ~lsu_req_done_i));



    `ASSERT(IbexStallMemNoRequest,
      instr_valid_i & lsu_req_dec & ~instr_done |-> ~lsu_req_done_i)

    assign rf_rd_a_wb_match = (rf_waddr_wb_i == rf_raddr_a_o) & |rf_raddr_a_o;
    assign rf_rd_b_wb_match = (rf_waddr_wb_i == rf_raddr_b_o) & |rf_raddr_b_o;

    assign rf_rd_a_wb_match_o = rf_rd_a_wb_match;
    assign rf_rd_b_wb_match_o = rf_rd_b_wb_match;



    assign rf_rd_a_hz = rf_rd_a_wb_match & rf_ren_a;
    assign rf_rd_b_hz = rf_rd_b_wb_match & rf_ren_b;




    assign rf_rdata_a_fwd = rf_rd_a_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_a_i;
    assign rf_rdata_b_fwd = rf_rd_b_wb_match & rf_write_wb_i ? rf_wdata_fwd_wb_i : rf_rdata_b_i;

    assign stall_ld_hz = outstanding_load_wb_i & (rf_rd_a_hz | rf_rd_b_hz);

    assign instr_type_wb_o = ~lsu_req_dec ? WB_INSTR_OTHER :
                              lsu_we      ? WB_INSTR_STORE :
                                            WB_INSTR_LOAD;

    assign instr_id_done_o = en_wb_o & ready_wb_i;


    assign stall_wb = en_wb_o & ~ready_wb_i;

    assign perf_dside_wait_o = instr_valid_i & ~instr_kill &
                               (outstanding_memory_access | stall_ld_hz);
  end else begin : gen_no_stall_mem

    assign multicycle_done = lsu_req_dec ? lsu_resp_valid_i : ex_valid_i;

    assign data_req_allowed = instr_first_cycle;



    assign stall_mem = instr_valid_i & (lsu_req_dec & (~lsu_resp_valid_i | instr_first_cycle));


    assign stall_ld_hz   = 1'b0;


    assign instr_executing_spec = instr_valid_i & ~instr_fetch_err_i & controller_run;
    assign instr_executing = instr_executing_spec;

    `ASSERT(IbexStallIfValidInstrNotExecuting,
      instr_valid_i & ~instr_fetch_err_i & ~instr_executing & controller_run |-> stall_id)



    assign rf_rdata_a_fwd = rf_rdata_a_i;
    assign rf_rdata_b_fwd = rf_rdata_b_i;

    assign rf_rd_a_wb_match_o = 1'b0;
    assign rf_rd_b_wb_match_o = 1'b0;




    logic unused_data_req_done_ex;
    logic [4:0] unused_rf_waddr_wb;
    logic unused_rf_write_wb;
    logic unused_outstanding_load_wb;
    logic unused_outstanding_store_wb;
    logic unused_wb_exception;
    logic [31:0] unused_rf_wdata_fwd_wb;

    assign unused_data_req_done_ex     = lsu_req_done_i;
    assign unused_rf_waddr_wb          = rf_waddr_wb_i;
    assign unused_rf_write_wb          = rf_write_wb_i;
    assign unused_outstanding_load_wb  = outstanding_load_wb_i;
    assign unused_outstanding_store_wb = outstanding_store_wb_i;
    assign unused_wb_exception         = wb_exception;
    assign unused_rf_wdata_fwd_wb      = rf_wdata_fwd_wb_i;

    assign instr_type_wb_o = WB_INSTR_OTHER;
    assign stall_wb        = 1'b0;

    assign perf_dside_wait_o = instr_executing & lsu_req_dec & ~lsu_resp_valid_i;

    assign instr_id_done_o = instr_done;
  end



  assign instr_perf_count_id_o = ~ebrk_insn & ~ecall_insn_dec & ~illegal_insn_dec &
      ~illegal_csr_insn_i & ~instr_fetch_err_i;



  assign en_wb_o = instr_done;

  assign perf_mul_wait_o = stall_multdiv & mult_en_dec;
  assign perf_div_wait_o = stall_multdiv & div_en_dec;





  `DV_FCOV_SIGNAL_GEN_IF(logic, rf_rd_wb_hz,
    (gen_stall_mem.rf_rd_a_hz | gen_stall_mem.rf_rd_b_hz) & instr_valid_i, WritebackStage)
  `DV_FCOV_SIGNAL(logic, branch_taken,
    instr_executing & (id_fsm_q == FIRST_CYCLE) & branch_decision_i)
  `DV_FCOV_SIGNAL(logic, branch_not_taken,
    instr_executing & (id_fsm_q == FIRST_CYCLE) & ~branch_decision_i)






  `ASSERT_KNOWN_IF(IbexAluOpMuxSelKnown, alu_op_a_mux_sel, instr_valid_i)
  `ASSERT(IbexAluAOpMuxSelValid, instr_valid_i |-> alu_op_a_mux_sel inside {
      OP_A_REG_A,
      OP_A_FWD,
      OP_A_CURRPC,
      OP_A_IMM})
  `ASSERT_KNOWN_IF(IbexBTAluAOpMuxSelKnown, bt_a_mux_sel, instr_valid_i)
  `ASSERT(IbexBTAluAOpMuxSelValid, instr_valid_i |-> bt_a_mux_sel inside {
      OP_A_REG_A,
      OP_A_CURRPC})
  `ASSERT_KNOWN_IF(IbexBTAluBOpMuxSelKnown, bt_b_mux_sel, instr_valid_i)
  `ASSERT(IbexBTAluBOpMuxSelValid, instr_valid_i |-> bt_b_mux_sel inside {
      IMM_B_I,
      IMM_B_B,
      IMM_B_J,
      IMM_B_INCR_PC})
  `ASSERT(IbexRegfileWdataSelValid, instr_valid_i |-> rf_wdata_sel inside {
      RF_WD_EX,
      RF_WD_CSR})
  `ASSERT_KNOWN(IbexWbStateKnown, id_fsm_q)


  `ASSERT_KNOWN_IF(IbexBranchDecisionValid, branch_decision_i,
      instr_valid_i && !(illegal_csr_insn_i || instr_fetch_err_i))


  `ASSERT_KNOWN_IF(IbexIdInstrKnown, instr_rdata_i,
      instr_valid_i && !(illegal_c_insn_i || instr_fetch_err_i))


  `ASSERT_KNOWN_IF(IbexIdInstrALUKnown, instr_rdata_alu_i,
      instr_valid_i && !(illegal_c_insn_i || instr_fetch_err_i))


  `ASSERT(IbexMulticycleEnableUnique,
      $onehot0({lsu_req_dec, multdiv_en_dec, branch_in_dec, jump_in_dec}))




  `ASSERT(IbexDuplicateInstrMatch, instr_valid_i |-> instr_rdata_i === instr_rdata_alu_i)

  `ifdef CHECK_MISALIGNED
  `ASSERT(IbexMisalignedMemoryAccess, !lsu_addr_incr_req_i)
  `endif

endmodule