diff --git a/doc/cs_registers.rst b/doc/cs_registers.rst index 9f29a7c1..7c673b54 100644 --- a/doc/cs_registers.rst +++ b/doc/cs_registers.rst @@ -90,18 +90,24 @@ Reset Value: ``0x0000_1800`` +-------+-----+---------------------------------------------------------------------------------+ | Bit# | R/W | Description | +-------+-----+---------------------------------------------------------------------------------+ -| 12:11 | R | **MPP:** Statically 2'b11 and cannot be altered (read-only). | +| 21 | RW | **TW:** Timeout Wait (WFI executed in User Mode will trap to Machine Mode). | ++-------+-----+---------------------------------------------------------------------------------+ +| 17 | RW | **MPRV:** Modify Privilege (Loads and stores use MPP for privilege checking). | ++-------+-----+---------------------------------------------------------------------------------+ +| 12:11 | RW | **MPP:** Machine Previous Privilege mode. | +-------+-----+---------------------------------------------------------------------------------+ | 7 | RW | **Previous Interrupt Enable (MPIE)**, i.e., before entering exception handling. | +-------+-----+---------------------------------------------------------------------------------+ | 3 | RW | **Interrupt Enable (MIE):** If set to 1'b1, interrupts are globally enabled. | +-------+-----+---------------------------------------------------------------------------------+ -When an exception is encountered, ``mstatus``.MPIE will be set to ``mstatus``.MIE. -When the MRET instruction is executed, the value of MPIE will be stored back to ``mstatus``.MIE. +When an exception is encountered, ``mstatus``.MPIE will be set to ``mstatus``.MIE, and ``mstatus``.MPP will be set to the current privilege mode. +When the MRET instruction is executed, the value of MPIE will be stored back to ``mstatus``.MIE, and the privilege mode will be restored from ``mstatus``.MPP. If you want to enable interrupt handling in your exception handler, set ``mstatus``.MIE to 1'b1 inside your handler code. +Only Machine Mode and User Mode are supported. +Any write to ``mstatus``.MPP of an unsupported value will be interpreted as Machine Mode. Machine ISA Register (misa) --------------------------- @@ -276,6 +282,15 @@ Reset Value: ``0x0000_0000`` | address[33:2] | +----------------+ +Time Registers (time(h)) +------------------------ + +CSR Address: ``0xC01 / 0xC81`` + +The User Mode ``time(h)`` registers are not implemented in Ibex. +Any access to these registers will trap. +It is recommended that trap handler software provides a means of accessing platform-defined ``mtime(h)`` timers where available. + .. _csr-mhartid: Hardware Thread ID (mhartid) diff --git a/doc/exception_interrupts.rst b/doc/exception_interrupts.rst index 99be67e4..3f9a0fb2 100644 --- a/doc/exception_interrupts.rst +++ b/doc/exception_interrupts.rst @@ -15,6 +15,12 @@ For more information, see the :ref:`cs-registers` documentation. The core starts fetching at the address made by concatenating the most significant 3 bytes of the boot address and the reset value (0x80) as the least significant byte. It is assumed that the boot address is supplied via a register to avoid long paths to the instruction fetch unit. +Privilege Modes +--------------- + +Ibex supports operation in Machine Mode (M-Mode) and User Mode (U-Mode). +The core resets into M-Mode and will jump to M-Mode on any interrupt or exception. +On execution of an MRET instruction, the core will return to the Privilege Mode stored in ``mstatus``.MPP. Interrupts ---------- @@ -80,7 +86,9 @@ Ibex can trigger an exception due to the following exception causes: +----------------+---------------------------------------------------------------+ | 7 | Store access fault | +----------------+---------------------------------------------------------------+ -| 11 | Environment call from M-mode (ECALL) | +| 8 | Environment call from U-Mode (ECALL) | ++----------------+---------------------------------------------------------------+ +| 11 | Environment call from M-Mode (ECALL) | +----------------+---------------------------------------------------------------+ The illegal instruction exception, instruction access fault, LSU error exceptions and ECALL instruction exceptions cannot be disabled and are always active. diff --git a/doc/introduction.rst b/doc/introduction.rst index b21235db..e1f44b1a 100644 --- a/doc/introduction.rst +++ b/doc/introduction.rst @@ -53,7 +53,7 @@ In addition, the following instruction set extensions are available. Most content of the RISC-V privileged specification is optional. Ibex currently supports the following features according to the RISC-V Privileged Specification, version 1.11. -* M mode +* M-Mode and U-Mode * All CSRs listed in :ref:`cs-registers` * Performance counters as described in :ref:`performance-counters` * Vectorized trap handling as described at :ref:`exceptions-interrupts` diff --git a/lint/verilator_waiver.vlt b/lint/verilator_waiver.vlt index 4df10e58..fca9dc95 100644 --- a/lint/verilator_waiver.vlt +++ b/lint/verilator_waiver.vlt @@ -69,9 +69,9 @@ lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 199 // Signal unoptimizable: Feedback to clock or circular logic: // ibex_core.id_stage_i.controller_i.ctrl_fsm_cs // Issue lowrisc/ibex#211 -lint_off -msg UNOPTFLAT -file "*/rtl/ibex_controller.sv" -lines 98 +lint_off -msg UNOPTFLAT -file "*/rtl/ibex_controller.sv" -lines 100 // Signal unoptimizable: Feedback to clock or circular logic: // ibex_core.cs_registers_i.mie_q // Issue lowrisc/ibex#212 -lint_off -msg UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -lines 149 +lint_off -msg UNOPTFLAT -file "*/rtl/ibex_cs_registers.sv" -lines 162 diff --git a/rtl/ibex_controller.sv b/rtl/ibex_controller.sv index 1977279e..c521e9bd 100644 --- a/rtl/ibex_controller.sv +++ b/rtl/ibex_controller.sv @@ -74,6 +74,8 @@ module ibex_controller ( output logic csr_restore_mret_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, // stall signals input logic stall_lsu_i, @@ -108,6 +110,7 @@ module ibex_controller ( logic halt_if; logic flush_id; logic illegal_dret; + logic illegal_umode; logic exc_req_lsu; logic special_req; logic enter_debug_mode; @@ -157,11 +160,17 @@ module ibex_controller ( // "Executing DRET outside of Debug Mode causes an illegal instruction exception." // [Debug Spec v0.13.2, p.41] assign illegal_dret = dret_insn & ~debug_mode_q; + + // Some instructions can only be executed in M-Mode + assign illegal_umode = (priv_mode_i != PRIV_LVL_M) & + // MRET must be in M-Mode. TW means trap WFI to M-Mode. + (mret_insn | (csr_mstatus_tw_i & wfi_insn)); + // This is recorded in the illegal_insn_q flop to help timing. Specifically // it is needed to break the path from ibex_cs_registers/illegal_csr_insn_o // to pc_set_o. Clear when controller is in FLUSH so it won't remain set // once illegal instruction is handled. - assign illegal_insn_d = (illegal_insn_i | illegal_dret) & (ctrl_fsm_cs != FLUSH); + assign illegal_insn_d = (illegal_insn_i | illegal_dret | illegal_umode) & (ctrl_fsm_cs != FLUSH); // exception requests // requests are flopped in exc_req_q. This is cleared when controller is in @@ -486,7 +495,8 @@ module ibex_controller ( csr_mtval_o = instr_is_compressed_i ? {16'b0, instr_compressed_i} : instr_i; end else if (ecall_insn) begin - exc_cause_o = EXC_CAUSE_ECALL_MMODE; + exc_cause_o = (priv_mode_i == PRIV_LVL_M) ? EXC_CAUSE_ECALL_MMODE : + EXC_CAUSE_ECALL_UMODE; end else if (ebrk_insn) begin if (debug_mode_q) begin diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index 007ea813..303f5338 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -196,7 +196,10 @@ module ibex_core #( logic csr_mtvec_init; logic [31:0] csr_mtvec; logic [31:0] csr_mtval; - priv_lvl_e priv_mode; + logic csr_mstatus_tw; + priv_lvl_e priv_mode_id; + priv_lvl_e priv_mode_if; + priv_lvl_e priv_mode_lsu; // debug mode and dcsr configuration logic debug_mode; @@ -412,6 +415,8 @@ module ibex_core #( .csr_restore_mret_id_o ( csr_restore_mret_id ), // restore mstatus upon MRET .csr_save_cause_o ( csr_save_cause ), .csr_mtval_o ( csr_mtval ), + .priv_mode_i ( priv_mode_id ), + .csr_mstatus_tw_i ( csr_mstatus_tw ), .illegal_csr_insn_i ( illegal_csr_insn_id ), // LSU @@ -572,7 +577,9 @@ module ibex_core #( // Hart ID from outside .hart_id_i ( hart_id_i ), - .priv_mode_o ( priv_mode ), + .priv_mode_id_o ( priv_mode_id ), + .priv_mode_if_o ( priv_mode_if ), + .priv_mode_lsu_o ( priv_mode_lsu ), // mtvec .csr_mtvec_o ( csr_mtvec ), @@ -597,6 +604,7 @@ module ibex_core #( .csr_meip_o ( csr_meip ), .csr_mfip_o ( csr_mfip ), .csr_mstatus_mie_o ( csr_mstatus_mie ), + .csr_mstatus_tw_o ( csr_mstatus_tw ), .csr_mepc_o ( csr_mepc ), // PMP @@ -640,11 +648,14 @@ module ibex_core #( if (PMPEnable) begin : g_pmp logic [33:0] pmp_req_addr [PMP_NUM_CHAN]; pmp_req_e pmp_req_type [PMP_NUM_CHAN]; + priv_lvl_e pmp_priv_lvl [PMP_NUM_CHAN]; assign pmp_req_addr[PMP_I] = {2'b00,instr_addr_o[31:0]}; assign pmp_req_type[PMP_I] = PMP_ACC_EXEC; + assign pmp_priv_lvl[PMP_I] = priv_mode_if; assign pmp_req_addr[PMP_D] = {2'b00,data_addr_o[31:0]}; assign pmp_req_type[PMP_D] = data_we_o ? PMP_ACC_WRITE : PMP_ACC_READ; + assign pmp_priv_lvl[PMP_D] = priv_mode_lsu; ibex_pmp #( .PMPGranularity ( PMPGranularity ), @@ -656,13 +667,18 @@ module ibex_core #( // Interface to CSRs .csr_pmp_cfg_i ( csr_pmp_cfg ), .csr_pmp_addr_i ( csr_pmp_addr ), - .priv_mode_i ( priv_mode ), + .priv_mode_i ( pmp_priv_lvl ), // Access checking channels .pmp_req_addr_i ( pmp_req_addr ), .pmp_req_type_i ( pmp_req_type ), .pmp_req_err_o ( pmp_req_err ) ); end else begin : g_no_pmp + // Unused signal tieoff + priv_lvl_e unused_priv_lvl_if, unused_priv_lvl_ls; + assign unused_priv_lvl_if = priv_mode_if; + assign unused_priv_lvl_ls = priv_mode_lsu; + // Output tieoff assign pmp_req_err[PMP_I] = 1'b0; assign pmp_req_err[PMP_D] = 1'b0; end @@ -675,7 +691,7 @@ module ibex_core #( rvfi_intr <= '0; rvfi_order <= '0; rvfi_insn <= '0; - rvfi_mode <= '0; + rvfi_mode <= {PRIV_LVL_M}; rvfi_rs1_addr <= '0; rvfi_rs2_addr <= '0; rvfi_pc_rdata <= '0; @@ -696,7 +712,7 @@ module ibex_core #( rvfi_intr <= rvfi_intr_d; rvfi_order <= rvfi_order + 64'(rvfi_valid); rvfi_insn <= rvfi_insn_id; - rvfi_mode <= PRIV_LVL_M; // TODO: Update for user mode support + rvfi_mode <= {priv_mode_id}; rvfi_rs1_addr <= rvfi_rs1_addr_id; rvfi_rs2_addr <= rvfi_rs2_addr_id; rvfi_pc_rdata <= pc_id; diff --git a/rtl/ibex_cs_registers.sv b/rtl/ibex_cs_registers.sv index c1631794..b96f66b2 100644 --- a/rtl/ibex_cs_registers.sv +++ b/rtl/ibex_cs_registers.sv @@ -24,7 +24,12 @@ module ibex_cs_registers #( // Hart ID input logic [31:0] hart_id_i, - output ibex_pkg::priv_lvl_e priv_mode_o, + + // Privilege mode + output ibex_pkg::priv_lvl_e priv_mode_id_o, + output ibex_pkg::priv_lvl_e priv_mode_if_o, + output ibex_pkg::priv_lvl_e priv_mode_lsu_o, + output logic csr_mstatus_tw_o, // mtvec output logic [31:0] csr_mtvec_o, @@ -112,8 +117,15 @@ module ibex_cs_registers #( logic mie; logic mpie; priv_lvl_e mpp; + logic mprv; + logic tw; } Status_t; + typedef struct packed { + logic mpie; + priv_lvl_e mpp; + } StatusStk_t; + // struct for mip/mie CSRs typedef struct packed { logic irq_software; @@ -145,6 +157,7 @@ module ibex_cs_registers #( logic [31:0] exception_pc; // CSRs + priv_lvl_e priv_lvl_q, priv_lvl_d; Status_t mstatus_q, mstatus_d; Interrupts_t mie_q, mie_d; logic [31:0] mscratch_q, mscratch_d; @@ -160,7 +173,7 @@ module ibex_cs_registers #( // CSRs for recoverable NMIs // NOTE: these CSRS are nonstandard, see https://github.com/riscv/riscv-isa-manual/issues/261 - Status_t mstack_q, mstack_d; + StatusStk_t mstack_q, mstack_d; logic [31:0] mstack_epc_q, mstack_epc_d; logic [5:0] mstack_cause_q, mstack_cause_d; @@ -205,11 +218,11 @@ module ibex_cs_registers #( assign mhpmcounter_idx = csr_addr[4:0]; // See RISC-V Privileged Specification, version 1.11, Section 2.1 - assign illegal_csr_priv = 1'b0; // we only support M-mode + assign illegal_csr_priv = (csr_addr[9:8] > {priv_lvl_q}); assign illegal_csr_write = (csr_addr[11:10] == 2'b11) && csr_wreq; - assign illegal_csr_insn_o = illegal_csr | illegal_csr_write | illegal_csr_priv; + assign illegal_csr_insn_o = csr_access_i & (illegal_csr | illegal_csr_write | illegal_csr_priv); - // mip CSR is purely combintational - must be able to re-enable the clock upon WFI + // mip CSR is purely combinational - must be able to re-enable the clock upon WFI assign mip.irq_software = irq_software_i & mie_q.irq_software; assign mip.irq_timer = irq_timer_i & mie_q.irq_timer; assign mip.irq_external = irq_external_i & mie_q.irq_external; @@ -230,6 +243,7 @@ module ibex_cs_registers #( csr_rdata_int[CSR_MSTATUS_MIE_BIT] = mstatus_q.mie; csr_rdata_int[CSR_MSTATUS_MPIE_BIT] = mstatus_q.mpie; csr_rdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW] = mstatus_q.mpp; + csr_rdata_int[CSR_MSTATUS_MPRV_BIT] = mstatus_q.mprv; end // misa @@ -324,7 +338,7 @@ module ibex_cs_registers #( if ((csr_addr[4:0] == 5'b00000) || // CSR_MCOUNTINHIBIT (csr_addr[4:0] == 5'b00001) || (csr_addr[4:0] == 5'b00010)) begin - illegal_csr = csr_access_i; + illegal_csr = 1'b1; end end else if ((csr_addr & CSR_MASK_MCOUNTER) == CSR_OFF_MCOUNTER) begin @@ -333,7 +347,7 @@ module ibex_cs_registers #( if ((csr_addr[4:0] == 5'b00000) || // CSR_MCYCLE (csr_addr[4:0] == 5'b00001) || (csr_addr[4:0] == 5'b00010)) begin // CSR_MINSTRET - illegal_csr = csr_access_i; + illegal_csr = 1'b1; end end else if ((csr_addr & CSR_MASK_MCOUNTER) == CSR_OFF_MCOUNTERH) begin @@ -342,10 +356,10 @@ module ibex_cs_registers #( if ((csr_addr[4:0] == 5'b00000) || // CSR_MCYCLEH (csr_addr[4:0] == 5'b00001) || (csr_addr[4:0] == 5'b00010)) begin // CSR_MINSTRETH - illegal_csr = csr_access_i; + illegal_csr = 1'b1; end end else begin - illegal_csr = csr_access_i; + illegal_csr = 1'b1; end end endcase @@ -355,6 +369,7 @@ module ibex_cs_registers #( always_comb begin exception_pc = pc_id_i; + priv_lvl_d = priv_lvl_q; mstatus_d = mstatus_q; mie_d = mie_q; mscratch_d = mscratch_q; @@ -382,8 +397,14 @@ module ibex_cs_registers #( mstatus_d = '{ mie: csr_wdata_int[CSR_MSTATUS_MIE_BIT], mpie: csr_wdata_int[CSR_MSTATUS_MPIE_BIT], - mpp: PRIV_LVL_M + mpp: csr_wdata_int[CSR_MSTATUS_MPP_BIT_HIGH:CSR_MSTATUS_MPP_BIT_LOW], + mprv: csr_wdata_int[CSR_MSTATUS_MPRV_BIT], + tw: csr_wdata_int[CSR_MSTATUS_TW_BIT] }; + // Convert illegal values to M-mode + if ((mstatus_d.mpp != PRIV_LVL_M) && (mstatus_d.mpp != PRIV_LVL_U)) begin + mstatus_d.mpp = PRIV_LVL_M; + end end // interrupt enable @@ -413,7 +434,10 @@ module ibex_cs_registers #( CSR_DCSR: begin dcsr_d = csr_wdata_int; dcsr_d.xdebugver = XDEBUGVER_STD; - dcsr_d.prv = PRIV_LVL_M; // only M-mode is supported + // Change to PRIV_LVL_M if sofware writes an unsupported value + if ((dcsr_d.prv != PRIV_LVL_M) && (dcsr_d.prv != PRIV_LVL_U)) begin + dcsr_d.prv = PRIV_LVL_M; + end // currently not supported: dcsr_d.nmip = 1'b0; @@ -471,15 +495,16 @@ module ibex_cs_registers #( if (debug_csr_save_i) begin // all interrupts are masked // do not update cause, epc, tval, epc and status - dcsr_d.prv = PRIV_LVL_M; + dcsr_d.prv = priv_lvl_q; dcsr_d.cause = debug_cause_i; depc_d = exception_pc; end else begin + priv_lvl_d = PRIV_LVL_M; mtval_d = csr_mtval_i; mstatus_d.mie = 1'b0; // disable interrupts // save current status mstatus_d.mpie = mstatus_q.mie; - mstatus_d.mpp = PRIV_LVL_M; + mstatus_d.mpp = priv_lvl_q; mepc_d = exception_pc; mcause_d = {csr_mcause_i}; // save previous status for recoverable NMI @@ -491,12 +516,15 @@ module ibex_cs_registers #( end // csr_save_cause_i csr_restore_mret_i: begin // MRET + priv_lvl_d = mstatus_q.mpp; mstatus_d.mie = mstatus_q.mpie; // re-enable interrupts // restore previous status for recoverable NMI mstatus_d.mpie = mstack_q.mpie; mstatus_d.mpp = mstack_q.mpp; mepc_d = mstack_epc_q; mcause_d = mstack_cause_q; + mstack_d.mpie = 1'b1; + mstack_d.mpp = PRIV_LVL_U; end // csr_restore_mret_i default:; @@ -538,6 +566,7 @@ module ibex_cs_registers #( assign csr_mtvec_o = mtvec_q; assign csr_mstatus_mie_o = mstatus_q.mie; + assign csr_mstatus_tw_o = mstatus_q.tw; assign debug_single_step_o = dcsr_q.step; assign debug_ebreakm_o = dcsr_q.ebreakm; @@ -546,10 +575,13 @@ module ibex_cs_registers #( // actual registers always_ff @(posedge clk_i or negedge rst_ni) begin if (!rst_ni) begin + priv_lvl_q <= PRIV_LVL_M; mstatus_q <= '{ mie: 1'b0, - mpie: 1'b0, - mpp: PRIV_LVL_M + mpie: 1'b1, + mpp: PRIV_LVL_U, + mprv: 1'b0, + tw: 1'b0 }; mie_q <= '0; mscratch_q <= '0; @@ -568,15 +600,15 @@ module ibex_cs_registers #( dscratch1_q <= '0; mstack_q <= '{ - mie: 1'b0, - mpie: 1'b0, - mpp: PRIV_LVL_M + mpie: 1'b1, + mpp: PRIV_LVL_U }; mstack_epc_q <= '0; mstack_cause_q <= '0; end else begin // update CSRs + priv_lvl_q <= priv_lvl_d; mstatus_q <= mstatus_d; mie_q <= mie_d; mscratch_q <= mscratch_d; @@ -596,7 +628,12 @@ module ibex_cs_registers #( end end - assign priv_mode_o = mstatus_q.mpp; + // Send current priv level to the decoder + assign priv_mode_id_o = priv_lvl_q; + // New instruction fetches need to account for updates to priv_lvl_q this cycle + assign priv_mode_if_o = priv_lvl_d; + // Load/store instructions must factor in MPRV for PMP checking + assign priv_mode_lsu_o = mstatus_q.mprv ? mstatus_q.mpp : priv_lvl_q; // ----------------- // PMP registers diff --git a/rtl/ibex_id_stage.sv b/rtl/ibex_id_stage.sv index 351a76a9..71b7a0c9 100644 --- a/rtl/ibex_id_stage.sv +++ b/rtl/ibex_id_stage.sv @@ -75,6 +75,8 @@ module ibex_id_stage #( output logic csr_restore_mret_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, // Interface to load store unit @@ -438,6 +440,8 @@ module ibex_id_stage #( .csr_restore_mret_id_o ( csr_restore_mret_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 Signal .debug_mode_o ( debug_mode_o ), diff --git a/rtl/ibex_pkg.sv b/rtl/ibex_pkg.sv index 8df2f466..de6c2990 100644 --- a/rtl/ibex_pkg.sv +++ b/rtl/ibex_pkg.sv @@ -180,6 +180,7 @@ typedef enum logic [5:0] { EXC_CAUSE_BREAKPOINT = {1'b0, 5'd03}, EXC_CAUSE_LOAD_ACCESS_FAULT = {1'b0, 5'd05}, EXC_CAUSE_STORE_ACCESS_FAULT = {1'b0, 5'd07}, + EXC_CAUSE_ECALL_UMODE = {1'b0, 5'd08}, EXC_CAUSE_ECALL_MMODE = {1'b0, 5'd11} } exc_cause_e; @@ -293,6 +294,8 @@ parameter int unsigned CSR_MSTATUS_MIE_BIT = 3; parameter int unsigned CSR_MSTATUS_MPIE_BIT = 7; parameter int unsigned CSR_MSTATUS_MPP_BIT_LOW = 11; parameter int unsigned CSR_MSTATUS_MPP_BIT_HIGH = 12; +parameter int unsigned CSR_MSTATUS_MPRV_BIT = 17; +parameter int unsigned CSR_MSTATUS_TW_BIT = 21; // CSR interrupt pending/enable bits parameter int unsigned CSR_MSIX_BIT = 3; diff --git a/rtl/ibex_pmp.sv b/rtl/ibex_pmp.sv index e54edaba..beb00689 100644 --- a/rtl/ibex_pmp.sv +++ b/rtl/ibex_pmp.sv @@ -19,8 +19,7 @@ module ibex_pmp #( input ibex_pkg::pmp_cfg_t csr_pmp_cfg_i [PMPNumRegions], input logic [33:0] csr_pmp_addr_i [PMPNumRegions], - input ibex_pkg::priv_lvl_e priv_mode_i, // Current priv mode, assumed to - // be the same for all channels + input ibex_pkg::priv_lvl_e priv_mode_i [PMPNumChan], // Access checking channels input logic [33:0] pmp_req_addr_i [PMPNumChan], input ibex_pkg::pmp_req_e pmp_req_type_i [PMPNumChan], @@ -104,8 +103,8 @@ module ibex_pmp #( ~|region_match_partial[c][r-1:0]; end end - assign access_fault[c] = (priv_mode_i == PRIV_LVL_M) ? |machine_access_fault[c] : - ~|user_access_allowed[c]; + assign access_fault[c] = (priv_mode_i[c] == PRIV_LVL_M) ? |machine_access_fault[c] : + ~|user_access_allowed[c]; assign pmp_req_err_o[c] = access_fault[c]; end