diff --git a/controller.sv b/controller.sv index e84da3b5..48cfba6d 100644 --- a/controller.sv +++ b/controller.sv @@ -44,7 +44,6 @@ module controller // decoder related signals output logic deassert_we_o, // deassert write enable for next instruction input logic illegal_insn_i, // decoder encountered an invalid instruction - input logic trap_insn_i, // decoder encountered a trap instruction input logic eret_insn_i, // decoder encountered an eret instruction input logic pipe_flush_i, // decoder wants to do a pipe flush @@ -67,9 +66,6 @@ module controller input logic data_req_ex_i, // data memory access is currently performed in EX stage input logic data_misaligned_i, - input logic lsu_ready_ex_i, - input logic lsu_ready_wb_i, - // hwloop signals input logic hwloop_jump_i, // modify pc_mux_sel to select the hwloop addr @@ -108,10 +104,17 @@ module controller output logic [1:0] operand_c_fw_mux_sel_o, // regfile rc data selector form ID stage // stall signals - output logic stall_if_o, // Stall IF stage (deassert requests) - output logic stall_id_o, // Stall ID stage (and instr and data memory interface) ( ID_STAGE ) - output logic stall_ex_o, // Stall ex stage ( EX_STAGE ) - output logic stall_wb_o, // Stall write to register file due contentions ( WB_STAGE ) + output logic halt_if_o, + output logic halt_id_o, + + output logic misaligned_stall_o, + output logic jr_stall_o, + output logic load_stall_o, + + input logic if_valid_i, // IF stage is done + input logic id_valid_i, // ID stage is done + input logic ex_valid_i, // EX stage is done + input logic wb_valid_i, // WB stage is done // Performance Counters output logic perf_jump_o, // we are executing a jump instruction (j, jr, jal, jalr) @@ -137,16 +140,6 @@ module controller logic reg_d_alu_is_reg_c_id; - logic misalign_stall; - logic instr_ack_stall; - logic load_stall; - logic jr_stall; - logic trap_stall; - - logic halt_if; - logic halt_id; - - `ifndef SYNTHESIS // synopsys translate_off // make sure we are called later so that we do not generate messages for @@ -185,8 +178,8 @@ module controller core_busy_o = 1'b1; is_decoding_o = 1'b0; - halt_if = 1'b0; - halt_id = 1'b0; + halt_if_o = 1'b0; + halt_id_o = 1'b0; dbg_trap_o = 1'b0; illegal_insn_o = 1'b0; clear_isr_running_o = 1'b0; @@ -249,7 +242,7 @@ module controller // handle conditional branches if (jump_in_dec_i == `BRANCH_COND) begin // handle branch if decision is available in next cycle - if (~stall_id_o) + if (id_valid_i) ctrl_fsm_ns = BRANCH; end @@ -293,8 +286,8 @@ module controller // sleep if (pipe_flush_i || exc_pipe_flush_i) begin - halt_if = 1'b1; - halt_id = 1'b1; + halt_if_o = 1'b1; + halt_id_o = 1'b1; ctrl_fsm_ns = FLUSH_EX; end @@ -304,13 +297,14 @@ module controller if(trap_hit_i && jump_in_dec_i != `BRANCH_COND) begin // halt pipeline immediately - halt_if = 1'b1; - halt_id = 1'b1; + halt_if_o = 1'b1; + halt_id_o = 1'b1; + // TODO: take a second look at this // make sure the current instruction has been executed // before changing state to non-decode - if (~stall_ex_o) - ctrl_fsm_ns = DBG_FLUSH_EX; + //if (~stall_ex_o) + ctrl_fsm_ns = DBG_SIGNAL; end end @@ -326,12 +320,12 @@ module controller // be executed (NPC) if (trap_hit_i) begin - halt_if = 1'b1; - halt_id = 1'b1; + halt_if_o = 1'b1; + halt_id_o = 1'b1; - ctrl_fsm_ns = DBG_FLUSH_EX; + ctrl_fsm_ns = DBG_SIGNAL; end else begin - if (~stall_id_o) + if (if_valid_i) ctrl_fsm_ns = DECODE; end end else begin @@ -343,41 +337,41 @@ module controller // be executed (NPC) if (trap_hit_i) begin - ctrl_fsm_ns = DBG_FLUSH_EX; + ctrl_fsm_ns = DBG_SIGNAL; end else begin - if (~stall_id_o) + if (if_valid_i) ctrl_fsm_ns = DECODE; end end end - // make sure EX stage is flushed - DBG_FLUSH_EX: - begin - halt_if = 1'b1; - halt_id = 1'b1; + // // make sure EX stage is flushed + // DBG_FLUSH_EX: + // begin + // halt_if_o = 1'b1; + // halt_id_o = 1'b1; - if(stall_ex_o == 1'b0) - ctrl_fsm_ns = DBG_FLUSH_WB; - end + // if(stall_ex_o == 1'b0) + // ctrl_fsm_ns = DBG_FLUSH_WB; + // end - // make sure WB stage is flushed - DBG_FLUSH_WB: - begin - halt_if = 1'b1; - halt_id = 1'b1; + // // make sure WB stage is flushed + // DBG_FLUSH_WB: + // begin + // halt_if_o = 1'b1; + // halt_id_o = 1'b1; - if(stall_ex_o == 1'b0) - ctrl_fsm_ns = DBG_SIGNAL; - end + // if(stall_ex_o == 1'b0) + // ctrl_fsm_ns = DBG_SIGNAL; + // end // now we can signal to the debugger that our pipeline is empty and it // can examine our current state DBG_SIGNAL: begin dbg_trap_o = 1'b1; - halt_if = 1'b1; - halt_id = 1'b1; + halt_if_o = 1'b1; + halt_id_o = 1'b1; ctrl_fsm_ns = DBG_WAIT; end @@ -386,19 +380,19 @@ module controller // we wait until it is done and go back to DECODE DBG_WAIT: begin - halt_if = 1'b1; - halt_id = 1'b1; + halt_if_o = 1'b1; + halt_id_o = 1'b1; if(dbg_set_npc_i == 1'b1) begin - halt_id = 1'b0; + halt_id_o = 1'b0; pc_mux_sel_o = `PC_DBG_NPC; pc_set_o = 1'b1; ctrl_fsm_ns = DBG_WAIT; end if(dbg_stall_i == 1'b0) begin - halt_if = 1'b0; - halt_id = 1'b0; + halt_if_o = 1'b0; + halt_id_o = 1'b0; ctrl_fsm_ns = DECODE; end end @@ -406,29 +400,29 @@ module controller // flush the pipeline, insert NOP into EX stage FLUSH_EX: begin - halt_if = 1'b1; - halt_id = 1'b1; + halt_if_o = 1'b1; + halt_id_o = 1'b1; - if(~stall_ex_o) + if(ex_valid_i) ctrl_fsm_ns = FLUSH_WB; end // flush the pipeline, insert NOP into EX and WB stage FLUSH_WB: begin - halt_if = 1'b1; - halt_id = 1'b1; + halt_if_o = 1'b1; + halt_id_o = 1'b1; if (~fetch_enable_i) begin // we are requested to go to sleep - if(~stall_wb_o) + if(wb_valid_i) ctrl_fsm_ns = SLEEP; end else begin // unstall pipeline and continue operation - halt_if = 1'b0; - halt_id = 1'b0; + halt_if_o = 1'b0; + halt_id_o = 1'b0; - if (~stall_id_o) + if (id_valid_i) ctrl_fsm_ns = DECODE; end end @@ -450,8 +444,8 @@ module controller ///////////////////////////////////////////////////////////// always_comb begin - load_stall = 1'b0; - jr_stall = 1'b0; + load_stall_o = 1'b0; + jr_stall_o = 1'b0; deassert_we_o = 1'b0; // deassert WE when the core is not decoding instructions @@ -467,7 +461,7 @@ module controller ((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) ) begin deassert_we_o = 1'b1; - load_stall = 1'b1; + load_stall_o = 1'b1; end // Stall because of jr path @@ -479,32 +473,13 @@ module controller ((regfile_we_ex_i == 1'b1) && (reg_d_ex_is_reg_a_id == 1'b1)) || ((regfile_alu_we_fw_i == 1'b1) && (reg_d_alu_is_reg_a_id == 1'b1))) ) begin - jr_stall = 1'b1; + jr_stall_o = 1'b1; deassert_we_o = 1'b1; end end - // Stall because of IF miss - assign instr_ack_stall = ~instr_ack_i; - - assign misalign_stall = data_misaligned_i; - - assign trap_stall = trap_insn_i; - - - //////////////////////////////////////////////////////////////////////////////////////////// - // Freeze Unit. This unit controls the pipeline stages // - //////////////////////////////////////////////////////////////////////////////////////////// - always_comb - begin - // we unstall the if_stage if the debug unit wants to set a new - // pc, so that the new value gets written into current_pc_if and is - // used by the instr_core_interface - stall_if_o = instr_ack_stall | load_stall | jr_stall | (~lsu_ready_ex_i) | (~lsu_ready_wb_i) | misalign_stall | halt_if | (jump_in_id_i == `BRANCH_COND); - stall_id_o = instr_ack_stall | load_stall | jr_stall | (~lsu_ready_ex_i) | (~lsu_ready_wb_i) | misalign_stall | halt_id; - stall_ex_o = instr_ack_stall | (~lsu_ready_ex_i) | (~lsu_ready_wb_i) | dbg_stall_i; - stall_wb_o = (~lsu_ready_wb_i) | dbg_stall_i; - end + // stall because of misaligned data access + assign misaligned_stall_o = data_misaligned_i; //////////////////////////////////////////////////////////////////////////////////////////// @@ -582,7 +557,7 @@ module controller // Performance Counters assign perf_jump_o = (jump_in_id_i == `BRANCH_JAL || jump_in_id_i == `BRANCH_JALR); assign perf_branch_o = (jump_in_id_i == `BRANCH_COND); - assign perf_jr_stall_o = jr_stall; - assign perf_ld_stall_o = load_stall; + assign perf_jr_stall_o = jr_stall_o; + assign perf_ld_stall_o = load_stall_o; endmodule // controller diff --git a/cs_registers.sv b/cs_registers.sv index 967f112a..271d2df3 100644 --- a/cs_registers.sv +++ b/cs_registers.sv @@ -54,7 +54,7 @@ module cs_registers output logic [31:0] epcr_o, // Performance Counters - input logic stall_id_i, // stall ID stage + input logic id_valid_i, // ID stage is done input logic is_compressed_i, // compressed instruction in ID input logic is_decoding_i, // controller is in DECODE state @@ -82,7 +82,7 @@ module cs_registers `endif // Performance Counter Signals - logic stall_id_q; + logic id_valid_q; logic [N_PERF_COUNTERS-1:0] PCCR_in; // input signals for each counter category logic [N_PERF_COUNTERS-1:0] PCCR_inc, PCCR_inc_q; // should the counter be increased? @@ -227,17 +227,16 @@ module cs_registers // // ///////////////////////////////////////////////////////////////// - assign PCCR_in[0] = 1'b1; // cycle counter - assign PCCR_in[1] = ~stall_id_i & is_decoding_i; // instruction counter - assign PCCR_in[2] = ld_stall_i & (~stall_id_q); // nr of load use hazards - assign PCCR_in[3] = jr_stall_i & (~stall_id_q); // nr of jump register hazards - assign PCCR_in[4] = instr_fetch_i; // cycles waiting for instruction fetches - assign PCCR_in[5] = mem_load_i; // nr of loads - assign PCCR_in[6] = mem_store_i; // nr of stores - assign PCCR_in[7] = jump_i & (~stall_id_q); // nr of jumps (unconditional) - assign PCCR_in[8] = branch_i & (~stall_id_q); // nr of branches (conditional) - assign PCCR_in[9] = ~stall_id_i & is_decoding_i - & is_compressed_i; // compressed instruction counter + assign PCCR_in[0] = 1'b1; // cycle counter + assign PCCR_in[1] = id_valid_q & is_decoding_i; // instruction counter + assign PCCR_in[2] = ld_stall_i & id_valid_q; // nr of load use hazards + assign PCCR_in[3] = jr_stall_i & id_valid_q; // nr of jump register hazards + assign PCCR_in[4] = instr_fetch_i; // cycles waiting for instruction fetches + assign PCCR_in[5] = mem_load_i; // nr of loads + assign PCCR_in[6] = mem_store_i; // nr of stores + assign PCCR_in[7] = jump_i & id_valid_q; // nr of jumps (unconditional) + assign PCCR_in[8] = branch_i & id_valid_q; // nr of branches (conditional) + assign PCCR_in[9] = id_valid_q & is_decoding_i & is_compressed_i; // compressed instruction counter // assign external performance counters generate @@ -358,7 +357,7 @@ module cs_registers begin if (rst_n == 1'b0) begin - stall_id_q <= 1'b0; + id_valid_q <= 1'b0; PCER_q <= 'h0; PCMR_q <= 2'h3; @@ -371,7 +370,7 @@ module cs_registers end else begin - stall_id_q <= stall_id_i; + id_valid_q <= id_valid_i; PCER_q <= PCER_n; PCMR_q <= PCMR_n; diff --git a/decoder.sv b/decoder.sv index a78e30f7..358c21d3 100644 --- a/decoder.sv +++ b/decoder.sv @@ -97,7 +97,6 @@ module riscv_decoder logic regfile_mem_we; logic regfile_alu_we; logic data_req; - logic data_we; logic [2:0] hwloop_we; logic trap_insn; @@ -155,7 +154,7 @@ module riscv_decoder csr_access_o = 1'b0; csr_op = `CSR_OP_NONE; - data_we = 1'b0; + data_we_o = 1'b0; data_type_o = 2'b00; data_sign_extension_o = 1'b0; data_reg_offset_o = 2'b00; @@ -249,7 +248,7 @@ module riscv_decoder `OPCODE_STORE, `OPCODE_STORE_POST: begin data_req = 1'b1; - data_we = 1'b1; + data_we_o = 1'b1; rega_used_o = 1'b1; regb_used_o = 1'b1; alu_operator = `ALU_ADD; @@ -278,7 +277,7 @@ module riscv_decoder 2'b10: data_type_o = 2'b00; // SW default: begin data_req = 1'b0; - data_we = 1'b0; + data_we_o = 1'b0; illegal_insn_o = 1'b1; end endcase @@ -852,7 +851,6 @@ module riscv_decoder assign regfile_mem_we_o = (deassert_we_i) ? 1'b0 : regfile_mem_we; assign regfile_alu_we_o = (deassert_we_i) ? 1'b0 : regfile_alu_we; assign data_req_o = (deassert_we_i) ? 1'b0 : data_req; - assign data_we_o = (deassert_we_i) ? 1'b0 : data_we; // TODO: is this needed? assign alu_operator_o = (deassert_we_i) ? `ALU_NOP : alu_operator; assign mult_en_o = (deassert_we_i) ? 1'b0 : mult_en; assign hwloop_we_o = (deassert_we_i) ? 3'b0 : hwloop_we; diff --git a/ex_stage.sv b/ex_stage.sv index 9036666c..3d4e213c 100644 --- a/ex_stage.sv +++ b/ex_stage.sv @@ -53,8 +53,6 @@ module ex_stage input logic mult_mac_en_i, // input from ID stage - input logic stall_wb_i, - input logic [4:0] regfile_alu_waddr_i, input logic regfile_alu_we_i, @@ -77,7 +75,14 @@ module ex_stage // To IF: Jump and branch target and decision output logic [31:0] jump_target_o, - output logic branch_decision_o + output logic branch_decision_o, + + // Stall Control + input logic lsu_ready_ex_i, // EX part of LSU is done + + output logic ex_ready_o, // EX stage ready for new data + output logic ex_valid_o, // EX stage gets new data + input logic wb_ready_i // WB stage ready for new data ); @@ -165,12 +170,19 @@ module ex_stage end else begin - if (stall_wb_i == 1'b0) + if (ex_valid_o) // wb_ready_i is implied begin regfile_we_wb_o <= regfile_we_i; regfile_waddr_wb_o <= regfile_waddr_i; + end else if (wb_ready_i) begin + // we are ready for a new instruction, but there is none available, + // so we just flush the current one out of the pipe + regfile_we_wb_o <= 1'b0; end end end + assign ex_ready_o = lsu_ready_ex_i & wb_ready_i; + assign ex_valid_o = ex_ready_o; + endmodule diff --git a/id_stage.sv b/id_stage.sv index 3852980f..7d601318 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -65,10 +65,16 @@ module id_stage input logic [31:0] current_pc_id_i, // Stalls - output logic stall_if_o, - output logic stall_id_o, - output logic stall_ex_o, - output logic stall_wb_o, + output logic halt_if_o, // controller requests a halt of the IF stage + + output logic id_ready_o, // ID stage is ready for the next instruction + input logic ex_ready_i, // EX stage is ready for the next instruction + + input logic if_ready_i, // IF stage is done + input logic if_valid_i, // IF stage is done + output logic id_valid_o, // ID stage is done + input logic ex_valid_i, // EX stage is done + input logic wb_valid_i, // WB stage is done // To the Pipeline ID/EX output logic [31:0] regfile_rb_data_ex_o, @@ -114,9 +120,6 @@ module id_stage output logic prepost_useincr_ex_o, input logic data_misaligned_i, - input logic lsu_ready_ex_i, - input logic lsu_ready_wb_i, - // Interrupt signals input logic irq_i, input logic irq_nm_i, @@ -169,6 +172,10 @@ module id_stage logic [1:0] jump_in_dec; + logic misaligned_stall; + logic jr_stall; + logic load_stall; + // Immediate decoding and sign extension logic [31:0] imm_i_type; @@ -617,7 +624,6 @@ module id_stage // decoder related signals .deassert_we_o ( deassert_we ), .illegal_insn_i ( illegal_insn_dec ), - .trap_insn_i ( trap_insn ), .eret_insn_i ( eret_insn_dec ), .pipe_flush_i ( pipe_flush_dec ), @@ -640,9 +646,6 @@ module id_stage .data_req_ex_i ( data_req_ex_o ), .data_misaligned_i ( data_misaligned_i ), - .lsu_ready_ex_i ( lsu_ready_ex_i ), - .lsu_ready_wb_i ( lsu_ready_wb_i ), - // hwloop signals .hwloop_jump_i ( hwloop_jump ), @@ -684,10 +687,17 @@ module id_stage .operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ), // Stall signals - .stall_if_o ( stall_if_o ), - .stall_id_o ( stall_id_o ), - .stall_ex_o ( stall_ex_o ), - .stall_wb_o ( stall_wb_o ), + .halt_if_o ( halt_if_o ), + .halt_id_o ( halt_id ), + + .misaligned_stall_o ( misaligned_stall ), + .jr_stall_o ( jr_stall ), + .load_stall_o ( load_stall ), + + .if_valid_i ( if_valid_i ), + .id_valid_i ( id_valid_o ), + .ex_valid_i ( ex_valid_i ), + .wb_valid_i ( wb_valid_i ), // Performance Counters .perf_jump_o ( perf_jump_o ), @@ -734,7 +744,7 @@ module id_stage .core_busy_i ( core_busy_o ), .jump_in_id_i ( jump_in_id_o ), .jump_in_ex_i ( jump_in_ex_o ), - .stall_id_i ( stall_id_o ), + .stall_id_i ( ~id_valid ), .illegal_insn_i ( illegal_insn ), .trap_insn_i ( trap_insn ), .drop_instruction_i ( 1'b0 ), @@ -792,7 +802,7 @@ module id_stage .hwloop_regid_i ( hwloop_regid ), // from controller - .stall_id_i ( stall_id_o ), + .stall_id_i ( ~id_valid ), // to hwloop controller .hwloop_start_addr_o ( hwloop_start_addr ), @@ -850,67 +860,91 @@ module id_stage data_misaligned_ex_o <= 1'b0; - jump_in_ex_o <= 2'b0; + jump_in_ex_o <= `BRANCH_NONE; end - else if ((stall_ex_o == 1'b0) && (data_misaligned_i == 1'b1)) - begin // misaligned access case, only unstall alu operands + else if (data_misaligned_i) begin + // misaligned data access case + if (ex_ready_i) + begin // misaligned access case, only unstall alu operands - // if we are using post increments, then we have to use the - // original value of the register for the second memory access - // => keep it stalled - if (prepost_useincr_ex_o == 1'b1) - begin - alu_operand_a_ex_o <= alu_operand_a; + // if we are using post increments, then we have to use the + // original value of the register for the second memory access + // => keep it stalled + if (prepost_useincr_ex_o == 1'b1) + begin + alu_operand_a_ex_o <= alu_operand_a; + end + + alu_operand_b_ex_o <= alu_operand_b; + regfile_alu_we_ex_o <= regfile_alu_we_id; + prepost_useincr_ex_o <= prepost_useincr; + + data_misaligned_ex_o <= 1'b1; end - - alu_operand_b_ex_o <= alu_operand_b; - regfile_alu_we_ex_o <= regfile_alu_we_id; - prepost_useincr_ex_o <= prepost_useincr; - - data_misaligned_ex_o <= 1'b1; end - else if ((stall_ex_o == 1'b0) && (data_misaligned_i == 1'b0)) - begin // unstall the whole pipeline - regfile_rb_data_ex_o <= operand_b_fw_id; + else if (~data_misaligned_i) begin + if (id_valid_o) + begin // unstall the whole pipeline + regfile_rb_data_ex_o <= operand_b_fw_id; - alu_operator_ex_o <= alu_operator; - alu_operand_a_ex_o <= alu_operand_a; - alu_operand_b_ex_o <= alu_operand_b; - alu_operand_c_ex_o <= alu_operand_c; + alu_operator_ex_o <= alu_operator; + alu_operand_a_ex_o <= alu_operand_a; + alu_operand_b_ex_o <= alu_operand_b; + alu_operand_c_ex_o <= alu_operand_c; - vector_mode_ex_o <= vector_mode; - alu_cmp_mode_ex_o <= alu_cmp_mode; - alu_vec_ext_ex_o <= alu_vec_ext; + vector_mode_ex_o <= vector_mode; + alu_cmp_mode_ex_o <= alu_cmp_mode; + alu_vec_ext_ex_o <= alu_vec_ext; - mult_en_ex_o <= mult_en; - mult_sel_subword_ex_o <= mult_sel_subword; - mult_signed_mode_ex_o <= mult_signed_mode; - mult_mac_en_ex_o <= mult_mac_en; + mult_en_ex_o <= mult_en; + mult_sel_subword_ex_o <= mult_sel_subword; + mult_signed_mode_ex_o <= mult_signed_mode; + mult_mac_en_ex_o <= mult_mac_en; - regfile_waddr_ex_o <= regfile_waddr_id; - regfile_we_ex_o <= regfile_we_id; + regfile_waddr_ex_o <= regfile_waddr_id; + regfile_we_ex_o <= regfile_we_id; - regfile_alu_waddr_ex_o <= regfile_alu_waddr_id; - regfile_alu_we_ex_o <= regfile_alu_we_id; + regfile_alu_waddr_ex_o <= regfile_alu_waddr_id; + regfile_alu_we_ex_o <= regfile_alu_we_id; - prepost_useincr_ex_o <= prepost_useincr; + prepost_useincr_ex_o <= prepost_useincr; - csr_access_ex_o <= csr_access; - csr_op_ex_o <= csr_op; + csr_access_ex_o <= csr_access; + csr_op_ex_o <= csr_op; - data_we_ex_o <= data_we_id; - data_type_ex_o <= data_type_id; - data_sign_ext_ex_o <= data_sign_ext_id; - data_reg_offset_ex_o <= data_reg_offset_id; - data_req_ex_o <= data_req_id; + data_we_ex_o <= data_we_id; + data_type_ex_o <= data_type_id; + data_sign_ext_ex_o <= data_sign_ext_id; + data_reg_offset_ex_o <= data_reg_offset_id; + data_req_ex_o <= data_req_id; - data_misaligned_ex_o <= 1'b0; + data_misaligned_ex_o <= 1'b0; - jump_in_ex_o <= jump_in_id_o; + jump_in_ex_o <= jump_in_id_o; + end else if(ex_ready_i) begin + // EX stage is ready but we don't have a new instruction for it, + // so we set all write enables to 0, but unstall the pipe + + regfile_we_ex_o <= 1'b0; + + regfile_alu_we_ex_o <= 1'b0; + + csr_op_ex_o <= `CSR_OP_NONE; + + data_req_ex_o <= 1'b0; + + data_misaligned_ex_o <= 1'b0; + + jump_in_ex_o <= `BRANCH_NONE; + end end end + // stall control + assign id_ready_o = (~misaligned_stall) & (~jr_stall) & (~load_stall) & ex_ready_i; + assign id_valid_o = (~halt_id) & if_ready_i & id_ready_o; + endmodule diff --git a/if_stage.sv b/if_stage.sv index 446786b3..5d84ed91 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -80,8 +80,10 @@ module if_stage input logic [31:0] dbg_npc_i, // pipeline stall - input logic stall_if_i, - input logic stall_id_i, + input logic halt_if_i, + output logic if_ready_o, + input logic id_ready_i, + output logic if_valid_o, // misc signals output logic if_busy_o // is the IF stage busy fetching instructions? @@ -219,10 +221,10 @@ module if_stage end else begin offset_fsm_cs <= offset_fsm_ns; - if (stall_if_i) - branch_req_Q <= branch_req | branch_req_Q; - else + if (if_valid_o) branch_req_Q <= 1'b0; + else + branch_req_Q <= branch_req | branch_req_Q; end end @@ -252,7 +254,7 @@ module if_stage if (fetch_valid) begin valid_o = 1'b1; // an instruction is ready for ID stage - if (req_i && ~stall_if_i) begin + if (req_i && if_valid_o) begin if (~is_compressed[0]) begin // 32 bit aligned instruction found @@ -277,7 +279,7 @@ module if_stage if (is_compressed[1]) begin valid_o = 1'b1; // an instruction is ready for ID stage - if (req_i && ~stall_if_i) begin + if (req_i && if_valid_o) begin // next instruction will be aligned fetch_ready = 1'b1; offset_fsm_ns = WAIT_ALIGNED; @@ -288,7 +290,7 @@ module if_stage if (fetch_unaligned_valid) begin valid_o = 1'b1; // an instruction is ready for ID stage - if (req_i && ~stall_if_i) begin + if (req_i && if_valid_o) begin // next instruction will be unaligned fetch_ready = 1'b1; offset_fsm_ns = WAIT_UNALIGNED; @@ -367,7 +369,7 @@ module if_stage end else begin - if (~stall_id_i) + if (if_valid_o) begin : ENABLED_PIPE instr_rdata_id_o <= instr_decompressed; illegal_c_insn_id_o <= illegal_c_insn; @@ -377,4 +379,7 @@ module if_stage end end + assign if_ready_o = valid_o & id_ready_i; + assign if_valid_o = (~halt_if_i) & if_ready_o & (jump_in_id_i != `BRANCH_COND); + endmodule diff --git a/load_store_unit.sv b/load_store_unit.sv index 03e27106..6a29a910 100644 --- a/load_store_unit.sv +++ b/load_store_unit.sv @@ -65,7 +65,7 @@ module load_store_unit output logic lsu_ready_ex_o, // LSU ready for new data in EX stage output logic lsu_ready_wb_o, // LSU ready for new data in WB stage - input logic ex_stall_i + input logic ex_valid_i ); logic [31:0] data_addr_int; @@ -317,6 +317,7 @@ module load_store_unit // output to register file assign data_rdata_ex_o = (data_rvalid_i == 1'b1) ? data_rdata_ext : rdata_q; + // output to data interface assign data_addr_o = data_addr_int; assign data_wdata_o = data_wdata; assign data_we_o = data_we_ex_i; @@ -346,10 +347,10 @@ module load_store_unit if(data_gnt_i) begin lsu_ready_ex_o = 1'b1; - if(ex_stall_i) - NS = WAIT_RVALID_EX_STALL; - else + if (ex_valid_i) NS = WAIT_RVALID; + else + NS = WAIT_RVALID_EX_STALL; end end end //~ IDLE @@ -367,16 +368,18 @@ module load_store_unit lsu_ready_wb_o = 1'b1; end - if(data_req_ex_i) begin + if (data_req_ex_i) begin lsu_ready_ex_o = 1'b0; - if(data_gnt_i) begin + if (data_gnt_i) begin lsu_ready_ex_o = 1'b1; - if(ex_stall_i) - NS = WAIT_RVALID_EX_STALL; - else + if(ex_valid_i) NS = WAIT_RVALID; + else + NS = WAIT_RVALID_EX_STALL; + end else begin + NS = IDLE; end end else begin // no request, so go to IDLE @@ -392,19 +395,19 @@ module load_store_unit data_req_o = 1'b0; if (data_rvalid_i) begin - if (ex_stall_i) begin - // we have to wait until ex_stall is deasserted - NS = IDLE_EX_STALL; - end else begin + if (ex_valid_i) begin // we are done and can go back to idle // the data is safely stored already NS = IDLE; + end else begin + // we have to wait until ex_stall is deasserted + NS = IDLE_EX_STALL; end end else begin // we didn't yet receive the rvalid, so we check the ex_stall // signal. If we are no longer stalled we can change to the "normal" // WAIT_RVALID state - if (~ex_stall_i) + if (ex_valid_i) NS = WAIT_RVALID; end end @@ -412,7 +415,7 @@ module load_store_unit IDLE_EX_STALL: begin // wait for us to be unstalled and then change back to IDLE state - if (~ex_stall_i) begin + if (ex_valid_i) begin NS = IDLE; end end diff --git a/riscv_core.sv b/riscv_core.sv index 09e5f07a..7315e421 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -105,12 +105,6 @@ module riscv_core logic branch_decision; - // Stalling - logic stall_if; // Stall instruction fetch(deassert request) - logic stall_id; // Stall PC stage and instr memory and data memo - logic stall_ex; // Stall EX Stage - logic stall_wb; // Stall write back stage - logic core_busy; logic if_busy; @@ -167,6 +161,17 @@ module riscv_core logic data_req_ex; logic data_misaligned_ex; + // stall control + logic halt_if; + logic if_ready; + logic id_ready; + logic ex_ready; + + logic if_valid; + logic id_valid; + logic ex_valid; + logic wb_valid; + logic lsu_ready_ex; logic lsu_ready_wb; @@ -269,8 +274,10 @@ module riscv_core .jump_target_ex_i ( jump_target_ex ), // pipeline stalls - .stall_if_i ( stall_if ), - .stall_id_i ( stall_id ), + .halt_if_i ( halt_if ), + .if_ready_o ( if_ready ), + .id_ready_i ( id_ready ), + .if_valid_o ( if_valid ), .if_busy_o ( if_busy ) ); @@ -316,10 +323,16 @@ module riscv_core .current_pc_id_i ( current_pc_id ), // Stalls - .stall_if_o ( stall_if ), - .stall_id_o ( stall_id ), - .stall_ex_o ( stall_ex ), - .stall_wb_o ( stall_wb ), + .halt_if_o ( halt_if ), + + .if_ready_i ( if_ready ), + .id_ready_o ( id_ready ), + .ex_ready_i ( ex_ready ), + + .if_valid_i ( if_valid ), + .id_valid_o ( id_valid ), + .ex_valid_i ( ex_valid ), + .wb_valid_i ( wb_valid ), // From the Pipeline ID/EX .regfile_rb_data_ex_o ( regfile_rb_data_ex ), @@ -365,9 +378,6 @@ module riscv_core .prepost_useincr_ex_o ( useincr_addr_ex ), .data_misaligned_i ( data_misaligned ), - .lsu_ready_ex_i ( lsu_ready_ex ), - .lsu_ready_wb_i ( lsu_ready_wb ), - // Interrupt Signals .irq_i ( irq_i ), // incoming interrupts .irq_nm_i ( irq_nm_i ), // incoming interrupts @@ -439,9 +449,6 @@ module riscv_core .csr_access_i ( csr_access_ex ), .csr_rdata_i ( csr_rdata ), - // input from ID stage - .stall_wb_i ( stall_wb ), - // From ID Stage: Regfile control signals .regfile_waddr_i ( regfile_waddr_ex ), .regfile_we_i ( regfile_we_ex ), @@ -460,7 +467,14 @@ module riscv_core // To ID stage: Forwarding signals .regfile_alu_waddr_fw_o ( regfile_alu_waddr_fw ), .regfile_alu_we_fw_o ( regfile_alu_we_fw ), - .regfile_alu_wdata_fw_o ( regfile_alu_wdata_fw ) + .regfile_alu_wdata_fw_o ( regfile_alu_wdata_fw ), + + // stall control + .lsu_ready_ex_i ( lsu_ready_ex ), + + .ex_ready_o ( ex_ready ), + .ex_valid_o ( ex_valid ), + .wb_ready_i ( lsu_ready_wb ) ); @@ -474,8 +488,8 @@ module riscv_core //////////////////////////////////////////////////////////////////////////////////////// load_store_unit load_store_unit_i ( - .clk ( clk ), - .rst_n ( rst_n ), + .clk ( clk ), + .rst_n ( rst_n ), // signal from ex stage .data_we_ex_i ( data_we_ex ), @@ -507,9 +521,10 @@ module riscv_core .lsu_ready_ex_o ( lsu_ready_ex ), .lsu_ready_wb_o ( lsu_ready_wb ), - .ex_stall_i ( stall_ex ) + .ex_valid_i ( ex_valid ) ); + assign wb_valid = lsu_ready_wb; ////////////////////////////////////// // ____ ____ ____ // @@ -549,7 +564,7 @@ module riscv_core .epcr_o ( epcr ), // performance counter related signals - .stall_id_i ( stall_id ), + .id_valid_i ( id_valid ), .is_compressed_i ( is_compressed_id ), .is_decoding_i ( is_decoding ), @@ -666,7 +681,7 @@ module riscv_core rs2_value = id_stage_i.operand_b_fw_id; // special case for WFI because we don't wait for unstalling there - if ((id_stage_i.stall_ex_o == 1'b0 && is_decoding) || id_stage_i.controller_i.pipe_flush_i) + if ((id_valid && is_decoding) || id_stage_i.controller_i.pipe_flush_i) begin mnemonic = ""; imm = 0;