diff --git a/id_stage.sv b/id_stage.sv index 773dde24..eeae970b 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -55,11 +55,12 @@ module id_stage output logic [31:0] jump_target_o, // IF and ID stage signals - output logic compressed_instr_o, output logic [2:0] pc_mux_sel_o, output logic [1:0] exc_pc_mux_o, output logic force_nop_o, + input logic illegal_c_insn_i, + input logic [31:0] current_pc_if_i, input logic [31:0] current_pc_id_i, @@ -140,6 +141,7 @@ module id_stage input logic [31:0] regfile_alu_wdata_fw_i, // Performance Counters + output logic perf_compressed_o, // current instrution is compressed output logic perf_jump_o, // we are executing a jump instruction output logic perf_branch_o, // we are executing a branch instruction output logic perf_jr_stall_o, // jump-register-hazard @@ -149,6 +151,7 @@ module id_stage // Compressed instruction decoding logic [31:0] instr; + logic is_compressed; // Immediate decoding and sign extension logic [31:0] imm_i_type; @@ -267,14 +270,10 @@ module id_stage assign pc_mux_sel_o = (exc_pc_sel == 1'b1) ? `PC_EXCEPTION : pc_mux_sel_int; - // compressed instruction decoding - compressed_decoder compressed_decoder_i ( - .instr_i ( instr_rdata_i ), - .instr_o ( instr ), - .is_compressed_o ( compressed_instr_o ), - .illegal_instr_o ( illegal_c_insn ) - ); + assign instr = instr_rdata_i; + assign is_compressed = (instr[1:0] != 2'b11); + assign perf_compressed_o = is_compressed; // immediate extraction and sign extension assign imm_i_type = { {20 {instr[31]}}, instr[31:20] }; @@ -414,7 +413,7 @@ module id_stage `IMM_I: immediate_b = imm_i_type; `IMM_S: immediate_b = imm_s_type; `IMM_U: immediate_b = imm_u_type; - `IMM_PCINCR: immediate_b = compressed_instr_o ? 32'h2 : 32'h4; + `IMM_PCINCR: immediate_b = is_compressed ? 32'h2 : 32'h4; default: immediate_b = imm_i_type; endcase; // case (immediate_mux_sel) end @@ -591,7 +590,7 @@ module id_stage .irq_present_i ( irq_present ), // Exception Controller Signals - .illegal_c_insn_i ( illegal_c_insn ), + .illegal_c_insn_i ( illegal_c_insn_i ), .illegal_insn_o ( illegal_insn ), .trap_insn_o ( trap_insn ), .pc_valid_i ( pc_valid ), diff --git a/if_stage.sv b/if_stage.sv index a35d5245..63603517 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -55,6 +55,7 @@ module if_stage // Output of IF Pipeline stage output logic [31:0] instr_rdata_id_o, // read instruction is sampled and sent to ID stage for decoding + output logic illegal_c_insn_id_o, // compressed decoder thinks this is an invalid instruction output logic [31:0] current_pc_if_o, output logic [31:0] current_pc_id_o, @@ -441,20 +442,40 @@ module if_stage offset_fsm_cs == UNALIGNED_16) || instr_req_o; + + // compressed instruction decoding, or more precisely compressed instruction + // expander + // + // since it does not matter where we decompress instructions, we do it here + // to ease timing closure + logic [31:0] instr_decompressed; + logic illegal_c_insn; + + compressed_decoder compressed_decoder_i + ( + .instr_i ( instr_rdata_int ), + .instr_o ( instr_decompressed ), + .is_compressed_o ( ), + .illegal_instr_o ( illegal_c_insn ) + ); + + // IF-ID pipeline registers, frozen when the ID stage is stalled always_ff @(posedge clk, negedge rst_n) begin : IF_ID_PIPE_REGISTERS if (rst_n == 1'b0) begin - instr_rdata_id_o <= '0; - current_pc_id_o <= '0; + instr_rdata_id_o <= '0; + illegal_c_insn_id_o <= 1'b0; + current_pc_id_o <= '0; end else begin if (~stall_id_i) begin : ENABLED_PIPE - instr_rdata_id_o <= instr_rdata_int; - current_pc_id_o <= current_pc_if_o; + instr_rdata_id_o <= instr_decompressed; + illegal_c_insn_id_o <= illegal_c_insn; + current_pc_id_o <= current_pc_if_o; end end end diff --git a/riscv_core.sv b/riscv_core.sv index a5b0cf83..5baad467 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -83,6 +83,7 @@ module riscv_core // IF/ID signals logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage + logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage logic [31:0] current_pc_if; // Current Program counter logic [31:0] current_pc_id; // Current Program counter logic force_nop_id; @@ -90,7 +91,7 @@ module riscv_core logic [1:0] exc_pc_mux_id; // Mux selector for exception PC // ID performance counter signals - logic compressed_instr; + logic perf_compressed; logic is_decoding; @@ -240,9 +241,10 @@ module riscv_core .instr_rdata_i ( instr_rdata_i ), // outputs to ID stage - .instr_rdata_id_o ( instr_rdata_id ), // Output of IF Pipeline stage - .current_pc_if_o ( current_pc_if ), // current pc - .current_pc_id_o ( current_pc_id ), // current pc + .instr_rdata_id_o ( instr_rdata_id ), // Output of IF Pipeline stage + .illegal_c_insn_id_o ( illegal_c_insn_id ), + .current_pc_if_o ( current_pc_if ), // current pc in IF stage + .current_pc_id_o ( current_pc_id ), // current pc in ID stage // Forwrding ports - control signals .force_nop_i ( force_nop_id ), // select incoming instr or NOP @@ -308,11 +310,11 @@ module riscv_core .exc_pc_mux_o ( exc_pc_mux_id ), .force_nop_o ( force_nop_id ), + .illegal_c_insn_i ( illegal_c_insn_id ), + .current_pc_if_i ( current_pc_if ), .current_pc_id_i ( current_pc_id ), - .compressed_instr_o ( compressed_instr ), - // STALLS .stall_if_o ( stall_if ), .stall_id_o ( stall_id ), @@ -391,6 +393,7 @@ module riscv_core .regfile_we_wb_i ( regfile_we_wb ), // write enable for the register file .regfile_wdata_wb_i ( regfile_wdata ), // write data to commit in the register file + .perf_compressed_o ( perf_compressed ), .perf_jump_o ( perf_jump ), .perf_branch_o ( perf_branch ), .perf_jr_stall_o ( perf_jr_stall ), @@ -540,9 +543,9 @@ module riscv_core .epcr_o ( epcr ), // performance counter related signals - .stall_id_i ( stall_id ), - .is_compressed_i ( compressed_instr ), - .is_decoding_i ( is_decoding ), + .stall_id_i ( stall_id ), + .is_compressed_i ( perf_compressed ), + .is_decoding_i ( is_decoding ), .instr_fetch_i ( ~instr_ack_int ), @@ -646,7 +649,7 @@ module riscv_core begin // get current PC and instruction instr = id_stage_i.instr[31:0]; - compressed = id_stage_i.compressed_instr_o; + compressed = id_stage_i.is_compressed; pc = id_stage_i.current_pc_id_i; // get register values