diff --git a/rtl/ibex_id_stage.sv b/rtl/ibex_id_stage.sv index 81fe19253..a7c27f768 100644 --- a/rtl/ibex_id_stage.sv +++ b/rtl/ibex_id_stage.sv @@ -1076,9 +1076,15 @@ module ibex_id_stage #( end // Signal which instructions to count as retired in minstret, all traps along with ebrk and - // ecall instructions are not counted. + // ecall instructions are not counted. Writes to minstret/minstreth themselves are also excluded + // to avoid incrementing right after a write. + logic minstret_write; + assign minstret_write = csr_access_o & + (csr_op_o inside {CSR_OP_WRITE, CSR_OP_SET, CSR_OP_CLEAR}) & + (csr_addr_o inside {CSR_MINSTRET, CSR_MINSTRETH}); + assign instr_perf_count_id_o = ~ebrk_insn & ~ecall_insn_dec & ~illegal_insn_dec & - ~illegal_csr_insn_i & ~instr_fetch_err_i; + ~illegal_csr_insn_i & ~instr_fetch_err_i & ~minstret_write; // An instruction is ready to move to the writeback stage (or retire if there is no writeback // stage) diff --git a/rtl/ibex_wb_stage.sv b/rtl/ibex_wb_stage.sv index 38ce421ca..5c8075de4 100644 --- a/rtl/ibex_wb_stage.sv +++ b/rtl/ibex_wb_stage.sv @@ -155,7 +155,7 @@ module ibex_wb_stage #( // Speculative versions of the signals do not factor in exceptions and whether the instruction // is done yet. These are used to get correct values for instructions reading the relevant // performance counters in the ID stage. - assign perf_instr_ret_wb_spec_o = wb_count_q; + assign perf_instr_ret_wb_spec_o = wb_count_q & wb_valid_q; assign perf_instr_ret_compressed_wb_spec_o = perf_instr_ret_wb_spec_o & wb_compressed_q; assign perf_instr_ret_wb_o = instr_done_wb_o & wb_count_q & ~(lsu_resp_valid_i & lsu_resp_err_i);