Add non-maskeable interrupt (NMI)

This commit is contained in:
Pirmin Vogel 2019-07-16 14:05:01 +01:00
parent 71a33e1ca1
commit 327d836281
4 changed files with 21 additions and 4 deletions

View file

@ -74,6 +74,7 @@ module ibex_controller (
input logic csr_meip_i, // external interrupt pending
input logic [14:0] csr_mfip_i, // fast interrupt pending
input logic irq_pending_i, // interrupt request pending
input logic irq_nm_i, // non-maskeable interrupt
// debug signals
input logic debug_req_i,
@ -111,6 +112,7 @@ module ibex_controller (
ctrl_fsm_e ctrl_fsm_cs, ctrl_fsm_ns;
logic nmi_mode_q, nmi_mode_d;
logic debug_mode_q, debug_mode_d;
logic load_err_q, load_err_d;
logic store_err_q, store_err_d;
@ -165,7 +167,8 @@ module ibex_controller (
assign enter_debug_mode = debug_req_i & ~debug_mode_q;
// interrupts including NMI are ignored while in debug mode [Debug Spec v0.13.2, p.39]
assign handle_irq = irq_pending_i & csr_mstatus_mie_i & ~debug_mode_q;
assign handle_irq = ~debug_mode_q &
((irq_nm_i & ~nmi_mode_q) | (irq_pending_i & csr_mstatus_mie_i));
// generate ID of fast interrupts, highest priority to highest ID
always_comb begin : gen_mfip_id
@ -221,6 +224,7 @@ module ibex_controller (
debug_csr_save_o = 1'b0;
debug_cause_o = DBG_CAUSE_EBREAK;
debug_mode_d = debug_mode_q;
nmi_mode_d = 1'b0;
perf_tbranch_o = 1'b0;
perf_jump_o = 1'b0;
@ -263,7 +267,7 @@ module ibex_controller (
// normal execution flow
// in debug mode or single step mode we leave immediately (wfi=nop)
if (irq_pending_i || debug_req_i || debug_mode_q || debug_single_step_i) begin
if (irq_nm_i || irq_pending_i || debug_req_i || debug_mode_q || debug_single_step_i) begin
ctrl_fsm_ns = FIRST_FETCH;
end
end
@ -361,7 +365,10 @@ module ibex_controller (
csr_save_cause_o = 1'b1;
// interrupt priorities according to Privileged Spec v1.11 p.31
if (csr_mfip_i) begin
if (irq_nm_i && !nmi_mode_q) begin
exc_cause_o = EXC_CAUSE_IRQ_NM;
nmi_mode_d = 1'b1; // enter NMI mode
end else if (csr_mfip_i != 15'b0) begin
exc_cause_o = exc_cause_e'({1'b1, mfip_id});
end else if (csr_meip_i) begin
exc_cause_o = EXC_CAUSE_IRQ_EXTERNAL_M;
@ -506,6 +513,9 @@ module ibex_controller (
pc_mux_o = PC_ERET;
pc_set_o = 1'b1;
csr_restore_mret_id_o = 1'b1;
if (nmi_mode_q) begin
nmi_mode_d = 1'b0; // exit NMI mode
end
end else if (dret_insn_i) begin
pc_mux_o = PC_DRET;
pc_set_o = 1'b1;
@ -551,11 +561,13 @@ module ibex_controller (
always_ff @(posedge clk_i or negedge rst_ni) begin : update_regs
if (!rst_ni) begin
ctrl_fsm_cs <= RESET;
nmi_mode_q <= 1'b0;
debug_mode_q <= 1'b0;
load_err_q <= 1'b0;
store_err_q <= 1'b0;
end else begin
ctrl_fsm_cs <= ctrl_fsm_ns;
nmi_mode_q <= nmi_mode_d;
debug_mode_q <= debug_mode_d;
load_err_q <= load_err_d;
store_err_q <= store_err_d;

View file

@ -70,6 +70,7 @@ module ibex_core #(
input logic irq_timer_i,
input logic irq_external_i,
input logic [14:0] irq_fast_i,
input logic irq_nm_i, // non-maskeable interrupt
// Debug Interface
input logic debug_req_i,
@ -273,7 +274,7 @@ module ibex_core #(
assign core_busy = core_ctrl_firstfetch ? 1'b1 : core_busy_q;
assign clock_en = core_busy | debug_req_i | irq_pending;
assign clock_en = core_busy | debug_req_i | irq_pending | irq_nm_i;
// main clock gate of the core
// generates all clocks except the one for the debug unit which is
@ -428,6 +429,7 @@ module ibex_core #(
.csr_meip_i ( csr_meip ),
.csr_mfip_i ( csr_mfip ),
.irq_pending_i ( irq_pending ),
.irq_nm_i ( irq_nm_i ),
// Debug Signal
.debug_cause_o ( debug_cause ),

View file

@ -113,6 +113,7 @@ module ibex_id_stage #(
input logic csr_meip_i,
input logic [14:0] csr_mfip_i,
input logic irq_pending_i,
input logic irq_nm_i,
input logic lsu_load_err_i,
input logic lsu_store_err_i,
@ -446,6 +447,7 @@ module ibex_id_stage #(
.csr_meip_i ( csr_meip_i ),
.csr_mfip_i ( csr_mfip_i ),
.irq_pending_i ( irq_pending_i ),
.irq_nm_i ( irq_nm_i ),
// CSR Controller Signals
.csr_save_if_o ( csr_save_if_o ),

View file

@ -188,6 +188,7 @@ typedef enum logic [5:0] {
EXC_CAUSE_IRQ_EXTERNAL_M = {1'b1, 5'd11},
// EXC_CAUSE_IRQ_FAST_0 = {1'b1, 5'd16},
// EXC_CAUSE_IRQ_FAST_14 = {1'b1, 5'd30},
EXC_CAUSE_IRQ_NM = {1'b1, 5'd31}, // == EXC_CAUSE_IRQ_FAST_15
EXC_CAUSE_INSN_ADDR_MISA = {1'b0, 5'd00},
EXC_CAUSE_ILLEGAL_INSN = {1'b0, 5'd01},
EXC_CAUSE_BREAKPOINT = {1'b0, 5'd03},