diff --git a/doc/serv_csr_int.png b/doc/serv_csr_int.png index c19c7a13..5f5a0938 100644 Binary files a/doc/serv_csr_int.png and b/doc/serv_csr_int.png differ diff --git a/rtl/serv_csr.v b/rtl/serv_csr.v index e67d9be6..49ec01ed 100644 --- a/rtl/serv_csr.v +++ b/rtl/serv_csr.v @@ -3,6 +3,7 @@ module serv_csr ( input wire i_clk, //State + input wire i_init, input wire i_en, input wire i_cnt0to3, input wire i_cnt3, @@ -11,8 +12,7 @@ module serv_csr input wire i_mem_op, input wire i_mtip, input wire i_trap, - input wire i_pending_irq, - output wire o_new_irq, + output reg o_new_irq, //Control input wire i_e_op, input wire i_ebreak, @@ -71,15 +71,15 @@ module serv_csr assign o_csr_in = csr_in; - assign o_new_irq = !timer_irq_r & timer_irq; - - always @(posedge i_clk) begin + if (!i_init & i_cnt_done) begin + timer_irq_r <= timer_irq; + o_new_irq <= timer_irq & !timer_irq_r; + end + if (i_mie_en & i_cnt7) mie_mtie <= csr_in; - timer_irq_r <= timer_irq; - /* The mie bit in mstatus gets updated under three conditions @@ -124,12 +124,12 @@ module serv_csr */ if (i_mcause_en & i_en & i_cnt0to3 | (i_trap & i_cnt_done)) begin mcause3_0[3] <= (i_e_op & !i_ebreak) | (!i_trap & csr_in); - mcause3_0[2] <= i_pending_irq | i_mem_op | (!i_trap & mcause3_0[3]); - mcause3_0[1] <= i_pending_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & mcause3_0[2]); - mcause3_0[0] <= i_pending_irq | i_e_op | (!i_trap & mcause3_0[1]); + mcause3_0[2] <= o_new_irq | i_mem_op | (!i_trap & mcause3_0[3]); + mcause3_0[1] <= o_new_irq | i_e_op | (i_mem_op & i_mem_cmd) | (!i_trap & mcause3_0[2]); + mcause3_0[0] <= o_new_irq | i_e_op | (!i_trap & mcause3_0[1]); end if (i_mcause_en & i_cnt_done | i_trap) - mcause31 <= i_trap ? i_pending_irq : csr_in; + mcause31 <= i_trap ? o_new_irq : csr_in; end endmodule diff --git a/rtl/serv_state.v b/rtl/serv_state.v index 6287d8f1..ef2302c0 100644 --- a/rtl/serv_state.v +++ b/rtl/serv_state.v @@ -5,7 +5,6 @@ module serv_state input wire i_clk, input wire i_rst, input wire i_new_irq, - output reg o_pending_irq, input wire i_dbus_ack, output wire o_ibus_cyc, input wire i_ibus_ack, @@ -49,6 +48,7 @@ module serv_state reg stage_two_req; reg init_done; + reg misalign_trap_sync; reg [4:2] o_cnt; reg [3:0] o_cnt_r; @@ -70,7 +70,7 @@ module serv_state assign cnt4 = (o_cnt[4:2] == 3'd1) & o_cnt_r[0]; assign o_cnt7 = (o_cnt[4:2] == 3'd1) & o_cnt_r[3]; - + assign o_alu_shamt_en = o_cnt0to3 | cnt4 | !o_init; //Take branch for jump or branch instructions (opcode == 1x0xx) if @@ -86,14 +86,16 @@ module serv_state assign o_dbus_cyc = !o_cnt_en & init_done & i_mem_op & !i_mem_misalign; - wire trap_pending = WITH_CSR & ((o_ctrl_jump & i_ctrl_misalign) | (i_mem_op & i_mem_misalign)); - //Prepare RF for reads when a new instruction is fetched // or when stage one caused an exception (rreq implies a write request too) - assign o_rf_rreq = i_ibus_ack | (stage_two_req & trap_pending); + assign o_rf_rreq = i_ibus_ack | (stage_two_req & misalign_trap_sync); //Prepare RF for writes when everything is ready to enter stage two - assign o_rf_wreq = ((i_shift_op & (i_alu_sh_done | !i_sh_right) & init_done) | (i_mem_op & i_dbus_ack) | (stage_two_req & (i_slt_op | i_branch_op))) & !trap_pending; + // and the first stage didn't cause a misalign exception + assign o_rf_wreq = !misalign_trap_sync & + ((i_shift_op & (i_alu_sh_done | !i_sh_right) & init_done) | + (i_mem_op & i_dbus_ack) | + (stage_two_req & (i_slt_op | i_branch_op))); assign o_rf_rd_en = i_rd_op & o_cnt_en & !o_init; @@ -112,7 +114,7 @@ module serv_state assign o_ibus_cyc = ibus_cyc & !i_rst; - assign o_init = two_stage_op & !o_pending_irq & !init_done; + assign o_init = two_stage_op & !i_new_irq & !init_done; always @(posedge i_clk) begin //ibus_cyc changes on three conditions. @@ -170,38 +172,24 @@ module serv_state end end + assign o_ctrl_trap = WITH_CSR & (i_e_op | i_new_irq | misalign_trap_sync); + generate if (WITH_CSR) begin - reg irq_sync; - reg misalign_trap_sync; - - assign o_ctrl_trap = i_e_op | o_pending_irq | misalign_trap_sync; - - always @(posedge i_clk) begin - if (i_ibus_ack) - irq_sync <= 1'b0; - if (i_new_irq) - irq_sync <= 1'b1; - - if (i_ibus_ack) - o_pending_irq <= irq_sync; - - if (stage_two_req) - misalign_trap_sync <= trap_pending; - if (o_cnt_done) - misalign_trap_sync <= 1'b0; - if (i_rst) - if (RESET_STRATEGY != "NONE") begin - misalign_trap_sync <= 1'b0; - irq_sync <= 1'b0; - o_pending_irq <= 1'b0; - end - - end // always @ (posedge i_clk) - end else begin - assign o_ctrl_trap = 0; - always @(*) - o_pending_irq = 1'b0; - end + //trap_pending is only guaranteed to have correct value during the + // last cycle of the init stage + wire trap_pending = WITH_CSR & ((take_branch & i_ctrl_misalign) | + (i_mem_op & i_mem_misalign)); + + always @(posedge i_clk) begin + if (o_cnt_done) + misalign_trap_sync <= trap_pending & o_init; + if (i_rst) + if (RESET_STRATEGY != "NONE") + misalign_trap_sync <= 1'b0; + end + end else + always @(*) + misalign_trap_sync = 1'b0; endgenerate endmodule diff --git a/rtl/serv_top.v b/rtl/serv_top.v index a8f43067..3113073b 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -149,7 +149,6 @@ module serv_top wire rf_csr_out; wire new_irq; - wire pending_irq; wire [1:0] lsb; @@ -162,7 +161,6 @@ module serv_top .i_rst (i_rst), //State .i_new_irq (new_irq), - .o_pending_irq (pending_irq), .i_alu_cmp (alu_cmp), .o_init (init), .o_cnt_en (cnt_en), @@ -428,6 +426,7 @@ module serv_top ( .i_clk (clk), //State + .i_init (init), .i_en (cnt_en), .i_cnt0to3 (cnt0to3), .i_cnt3 (cnt3), @@ -436,7 +435,6 @@ module serv_top .i_mem_op (mem_op), .i_mtip (i_timer_irq), .i_trap (trap), - .i_pending_irq (pending_irq), .o_new_irq (new_irq), //Control .i_e_op (e_op),