diff --git a/rtl/serv_csr.v b/rtl/serv_csr.v index b827958..df9f249 100644 --- a/rtl/serv_csr.v +++ b/rtl/serv_csr.v @@ -71,38 +71,56 @@ module serv_csr always @(posedge i_clk) begin - /* - Note: To save resources mstatus_mpie (mstatus bit 7) is not - readable or writable from sw - */ - if (i_mstatus_en & i_cnt3) - mstatus_mie <= csr_in; - if (i_mie_en & i_cnt7) mie_mtie <= csr_in; timer_irq_r <= timer_irq; - if (i_mret) begin - mstatus_mie <= mstatus_mpie; - end + /* + The mie bit in mstatus gets updated under three conditions - if (i_trap_taken) begin - mstatus_mpie <= mstatus_mie; - mstatus_mie <= 1'b0; - mcause31 <= i_pending_irq; - mcause3_0 <= i_pending_irq ? 4'd7 : - i_e_op ? {!i_ebreak, 3'b011} : - i_mem_misalign ? {2'b01, i_mem_cmd, 1'b0} : - 4'd0; - end + When a trap is taken, the bit is cleared + During an mret instruction, the bit is restored from mpie + During a mstatus CSR access instruction it's assigned when + bit 3 gets updated - if (i_mcause_en & i_en) begin - if (i_cnt0to3) - mcause3_0 <= {csr_in, mcause3_0[3:1]}; - if (i_cnt_done) - mcause31 <= csr_in; - end + These conditions are all mutually exclusibe + */ + if (i_trap_taken | i_mstatus_en & i_cnt3 | i_mret) + mstatus_mie <= !i_trap_taken & (i_mret ? mstatus_mpie : csr_in); + + /* + Note: To save resources mstatus_mpie (mstatus bit 7) is not + readable or writable from sw + */ + if (i_trap_taken) + mstatus_mpie <= mstatus_mie; + + /* + The four lowest bits in mcause hold the exception code + + These bits get updated under three conditions + + During an mcause CSR access function, they are assigned when + bits 0 to 3 gets updated + + During an external interrupt the exception code is set to + 7, since SERV only support timer interrupts + + During an exception, the exception code is assigned to indicate + if it was caused by an ebreak instruction (3), + ecall instruction (11), misaligned load (4), misaligned store (6) + or misaligned jump (0) + */ + if (i_mcause_en & i_en & i_cnt0to3 | i_trap_taken) + mcause3_0 <= !i_trap_taken ? {csr_in, mcause3_0[3:1]} : + i_pending_irq ? 4'd7 : + i_e_op ? {!i_ebreak, 3'b011} : + i_mem_misalign ? {2'b01, i_mem_cmd, 1'b0} : + 4'd0; + + if (i_mcause_en & i_cnt_done | i_trap_taken) + mcause31 <= i_trap_taken ? i_pending_irq : csr_in; end endmodule