diff --git a/rtl/cve2_controller.sv b/rtl/cve2_controller.sv index 3e8a70cf2e..88e56dbb7d 100644 --- a/rtl/cve2_controller.sv +++ b/rtl/cve2_controller.sv @@ -109,6 +109,7 @@ module cve2_controller #( logic nmi_mode_q, nmi_mode_d; logic debug_mode_q, debug_mode_d; + dbg_cause_e debug_cause_d, debug_cause_q; logic load_err_q, load_err_d; logic store_err_q, store_err_d; logic exc_req_q, exc_req_d; @@ -312,6 +313,26 @@ module cve2_controller #( assign unused_irq_timer = irqs_i.irq_timer; + // Record the debug cause outside of the FSM + // The decision to enter debug_mode and the write of the cause to DCSR happen + // in seperate steps within the FSM. Hence, there are a small number of cycles + // where a change in external stimulus can cause the cause to be recorded incorrectly. + assign debug_cause_d = trigger_match_i ? DBG_CAUSE_TRIGGER : + ebrk_insn_prio ? DBG_CAUSE_EBREAK : + debug_req_i ? DBG_CAUSE_HALTREQ : + do_single_step_d ? DBG_CAUSE_STEP : + DBG_CAUSE_NONE ; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + debug_cause_q <= DBG_CAUSE_NONE; + end else begin + debug_cause_q <= debug_cause_d; + end + end + + assign debug_cause_o = debug_cause_q; + ///////////////////// // Core controller // ///////////////////// @@ -346,7 +367,6 @@ module cve2_controller #( flush_id = 1'b0; debug_csr_save_o = 1'b0; - debug_cause_o = DBG_CAUSE_EBREAK; debug_mode_d = debug_mode_q; nmi_mode_d = nmi_mode_q; @@ -531,13 +551,6 @@ module cve2_controller #( debug_csr_save_o = 1'b1; csr_save_cause_o = 1'b1; - if (trigger_match_i) begin - debug_cause_o = DBG_CAUSE_TRIGGER; // (priority 4) - end else if (debug_req_i) begin - debug_cause_o = DBG_CAUSE_HALTREQ; // (priority 1) - end else begin - debug_cause_o = DBG_CAUSE_STEP; // (priority 0, lowest) - end // enter debug mode debug_mode_d = 1'b1; @@ -567,7 +580,6 @@ module cve2_controller #( // dcsr debug_csr_save_o = 1'b1; - debug_cause_o = DBG_CAUSE_EBREAK; end // enter debug mode