diff --git a/controller.sv b/controller.sv index f8cc267e..d2e3626a 100644 --- a/controller.sv +++ b/controller.sv @@ -45,7 +45,10 @@ module riscv_controller input logic rega_used_i, // register A is used input logic regb_used_i, // register B is used + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE input logic regc_used_i, // register C is used + `endif // THREE_PORT_REG_FILE // from IF/ID pipeline input logic instr_valid_i, // instruction coming from IF/ID pipeline is valid @@ -96,15 +99,21 @@ module riscv_controller input logic regfile_we_ex_i, // FW: write enable from EX stage input logic [4:0] regfile_waddr_wb_i, // FW: write address from WB stage input logic regfile_we_wb_i, // FW: write enable from WB stage + input logic [4:0] regfile_alu_waddr_fw_i, // FW: ALU/MUL write address from EX stage input logic regfile_alu_we_fw_i, // FW: ALU/MUL write enable from EX stage // forwarding signals output logic [1:0] operand_a_fw_mux_sel_o, // regfile ra data selector form ID stage output logic [1:0] operand_b_fw_mux_sel_o, // regfile rb data selector form ID stage + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE output logic [1:0] operand_c_fw_mux_sel_o, // regfile rc data selector form ID stage + `endif // THREE_PORT_REG_FILE // forwarding detection signals + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE input logic reg_d_ex_is_reg_a_i, input logic reg_d_ex_is_reg_b_i, input logic reg_d_ex_is_reg_c_i, @@ -114,6 +123,14 @@ module riscv_controller input logic reg_d_alu_is_reg_a_i, input logic reg_d_alu_is_reg_b_i, input logic reg_d_alu_is_reg_c_i, + `else + input logic reg_d_ex_is_reg_a_i, + input logic reg_d_ex_is_reg_b_i, + input logic reg_d_wb_is_reg_a_i, + input logic reg_d_wb_is_reg_b_i, + input logic reg_d_alu_is_reg_a_i, + input logic reg_d_alu_is_reg_b_i, + `endif // THREE_PORT_REG_FILE // stall signals @@ -559,7 +576,10 @@ module riscv_controller // default assignements operand_a_fw_mux_sel_o = SEL_REGFILE; operand_b_fw_mux_sel_o = SEL_REGFILE; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE operand_c_fw_mux_sel_o = SEL_REGFILE; + `endif // THREE_PORT_REG_FILE // Forwarding WB -> ID if (regfile_we_wb_i == 1'b1) @@ -568,19 +588,25 @@ module riscv_controller operand_a_fw_mux_sel_o = SEL_FW_WB; if (reg_d_wb_is_reg_b_i == 1'b1) operand_b_fw_mux_sel_o = SEL_FW_WB; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE if (reg_d_wb_is_reg_c_i == 1'b1) operand_c_fw_mux_sel_o = SEL_FW_WB; + `endif // THREE_PORT_REG_FILE end // Forwarding EX -> ID if (regfile_alu_we_fw_i == 1'b1) begin - if (reg_d_alu_is_reg_a_i == 1'b1) - operand_a_fw_mux_sel_o = SEL_FW_EX; - if (reg_d_alu_is_reg_b_i == 1'b1) - operand_b_fw_mux_sel_o = SEL_FW_EX; - if (reg_d_alu_is_reg_c_i == 1'b1) - operand_c_fw_mux_sel_o = SEL_FW_EX; + if (reg_d_alu_is_reg_a_i == 1'b1) + operand_a_fw_mux_sel_o = SEL_FW_EX; + if (reg_d_alu_is_reg_b_i == 1'b1) + operand_b_fw_mux_sel_o = SEL_FW_EX; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE + if (reg_d_alu_is_reg_c_i == 1'b1) + operand_c_fw_mux_sel_o = SEL_FW_EX; + `endif // THREE_PORT_REG_FILE end // for misaligned memory accesses diff --git a/decoder.sv b/decoder.sv index 638c2063..105006f6 100644 --- a/decoder.sv +++ b/decoder.sv @@ -47,7 +47,10 @@ module riscv_decoder output logic rega_used_o, // rs1 is used by current instruction output logic regb_used_o, // rs2 is used by current instruction + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE output logic regc_used_o, // rs3 is used by current instruction + `endif // THREE_PORT_REG_FILE // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT @@ -66,7 +69,11 @@ module riscv_decoder output logic [ALU_OP_WIDTH-1:0] alu_operator_o, // ALU operation selection output logic [2:0] alu_op_a_mux_sel_o, // operand a selection: reg value, PC, immediate or zero output logic [2:0] alu_op_b_mux_sel_o, // operand b selection: reg value or immediate + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE output logic [1:0] alu_op_c_mux_sel_o, // operand c selection: reg value or jump target + `endif // THREE_PORT_REG_FILE + // CONFIG_REGION: VEC_SUPPORT `ifdef VEC_SUPPORT output logic [1:0] alu_vec_mode_o, // selects between 32 bit, 16 bit and 8 bit vectorial modes @@ -74,7 +81,10 @@ module riscv_decoder `endif // VEC_SUPPORT output logic [0:0] imm_a_mux_sel_o, // immediate selection for operand a output logic [3:0] imm_b_mux_sel_o, // immediate selection for operand b + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE output logic [1:0] regc_mux_o, // register c selection: S3, RD or 0 + `endif // THREE_PORT_REG_FILE // CONFIG_REGION: MUL_SUPPORT `ifdef MUL_SUPPORT @@ -158,7 +168,10 @@ module riscv_decoder alu_operator_o = ALU_SLTU; alu_op_a_mux_sel_o = OP_A_REGA_OR_FWD; alu_op_b_mux_sel_o = OP_B_REGB_OR_FWD; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE alu_op_c_mux_sel_o = OP_C_REGC_OR_FWD; + `endif // THREE_PORT_REG_FILE // CONFIG_REGION: VEC_SUPPORT `ifdef VEC_SUPPORT alu_vec_mode_o = VEC_MODE32; @@ -214,7 +227,10 @@ module riscv_decoder rega_used_o = 1'b0; regb_used_o = 1'b0; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE regc_used_o = 1'b0; + `endif // THREE_PORT_REG_FILE // CONFIG_REGION: BIT_SUPPORT @@ -271,7 +287,10 @@ module riscv_decoder OPCODE_BRANCH: begin // Branch jump_target_mux_sel_o = JT_COND; jump_in_id = BRANCH_COND; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE alu_op_c_mux_sel_o = OP_C_JT; + `endif // THREE_PORT_REG_FILE rega_used_o = 1'b1; regb_used_o = 1'b1; @@ -335,12 +354,23 @@ module riscv_decoder // offset from immediate imm_b_mux_sel_o = IMMB_S; alu_op_b_mux_sel_o = OP_B_IMM; - end else begin + end + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE + else begin // offset from register regc_used_o = 1'b1; alu_op_b_mux_sel_o = OP_B_REGC_OR_FWD; regc_mux_o = REGC_RD; end + `else + // Register offset is illegal since no register c available + else begin + data_req = 1'b0; + data_we_o = 1'b0; + illegal_insn_o = 1'b1; + end + `endif // THREE_PORT_REG_FILE // store size unique case (instr_rdata_i[13:12]) @@ -718,6 +748,9 @@ module riscv_decoder end end + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE + OPCODE_PULP_OP: begin // PULP specific ALU instructions with three source operands regfile_alu_we = 1'b1; rega_used_o = 1'b1; @@ -815,6 +848,7 @@ module riscv_decoder end endcase end + `endif // THREE_PORT_REG_FILE // CONFIG_REGION: VEC_SUPPORT `ifdef VEC_SUPPORT diff --git a/ex_stage.sv b/ex_stage.sv index 51619b15..0feb9766 100644 --- a/ex_stage.sv +++ b/ex_stage.sv @@ -156,6 +156,7 @@ module riscv_ex_stage // // //////////////////////////// + // CONFIG_REGION: SIMPLE_ALU `ifdef SIMPLE_ALU riscv_alu_simplified alu_i @@ -178,7 +179,7 @@ module riscv_ex_stage assign alu_ready = 1'b1; // As there is no divider, ALU always takes only one cycle - `else + `else // SIMPLE_ALU riscv_alu alu_i ( @@ -216,7 +217,7 @@ module riscv_ex_stage .ex_ready_i ( ex_ready_o ) ); - `endif + `endif // SIMPLE_ALU //////////////////////////////////////////////////////////////// diff --git a/id_stage.sv b/id_stage.sv index 16c7dd7b..ff5bc423 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -98,7 +98,8 @@ module riscv_id_stage #( output logic [31:0] alu_operand_a_ex_o, output logic [31:0] alu_operand_b_ex_o, - output logic [31:0] alu_operand_c_ex_o, + output logic [31:0] alu_operand_c_ex_o, // Still needed if 2r1w reg file used + // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT output logic [ 4:0] bmask_a_ex_o, @@ -240,7 +241,10 @@ module riscv_id_stage #( logic rega_used_dec; logic regb_used_dec; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic regc_used_dec; + `endif // THREE_PORT_REG_FILE // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT logic bmask_needed_dec; @@ -290,7 +294,10 @@ module riscv_id_stage #( // Register file interface logic [4:0] regfile_addr_ra_id; logic [4:0] regfile_addr_rb_id; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic [4:0] regfile_addr_rc_id; + `endif // THREE_PORT_REG_FILE logic [4:0] regfile_waddr_id; logic [4:0] regfile_alu_waddr_id; @@ -298,14 +305,20 @@ module riscv_id_stage #( logic [31:0] regfile_data_ra_id; logic [31:0] regfile_data_rb_id; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic [31:0] regfile_data_rc_id; + `endif // THREE_PORT_REG_FILE // ALU Control logic [ALU_OP_WIDTH-1:0] alu_operator; logic [2:0] alu_op_a_mux_sel; logic [2:0] alu_op_b_mux_sel; logic [1:0] alu_op_c_mux_sel; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic [1:0] regc_mux; + `endif // THREE_PORT_REG_FILE logic [0:0] imm_a_mux_sel; logic [3:0] imm_b_mux_sel; @@ -364,11 +377,17 @@ module riscv_id_stage #( // Forwarding logic [1:0] operand_a_fw_mux_sel; logic [1:0] operand_b_fw_mux_sel; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic [1:0] operand_c_fw_mux_sel; + `endif // THREE_PORT_REG_FILE logic [31:0] operand_a_fw_id; logic [31:0] operand_b_fw_id; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic [31:0] operand_c_fw_id; - + `endif // THREE_PORT_REG_FILE + logic [31:0] operand_b; // CONFIG_REGION: VEC_SUPPORT `ifdef VEC_SUPPORT @@ -377,7 +396,7 @@ module riscv_id_stage #( logic [31:0] alu_operand_a; logic [31:0] alu_operand_b; - logic [31:0] alu_operand_c; + logic [31:0] alu_operand_c; // Still needed if 2r1w reg file used // Immediates for ID // CONFIG_REGION: BIT_SUPPORT @@ -417,6 +436,8 @@ module riscv_id_stage #( `endif // VEC_SUPPORT // Forwarding detection signals + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic reg_d_ex_is_reg_a_id; logic reg_d_ex_is_reg_b_id; logic reg_d_ex_is_reg_c_id; @@ -426,6 +447,14 @@ module riscv_id_stage #( logic reg_d_alu_is_reg_a_id; logic reg_d_alu_is_reg_b_id; logic reg_d_alu_is_reg_c_id; + `else + logic reg_d_ex_is_reg_a_id; + logic reg_d_ex_is_reg_b_id; + logic reg_d_wb_is_reg_a_id; + logic reg_d_wb_is_reg_b_id; + logic reg_d_alu_is_reg_a_id; + logic reg_d_alu_is_reg_b_id; + `endif // THREE_PORT_REG_FILE assign instr = instr_rdata_i; @@ -469,6 +498,8 @@ module riscv_id_stage #( assign regfile_addr_ra_id = instr[`REG_S1]; assign regfile_addr_rb_id = instr[`REG_S2]; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE // register C mux always_comb begin @@ -479,18 +510,26 @@ module riscv_id_stage #( default: regfile_addr_rc_id = '0; endcase end + `endif // THREE_PORT_REG_FILE //--------------------------------------------------------------------------- // destination registers //--------------------------------------------------------------------------- assign regfile_waddr_id = instr[`REG_D]; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE + // Second Register Write Address Selection // Used for prepost load/store and multiplier assign regfile_alu_waddr_id = regfile_alu_waddr_mux_sel ? regfile_waddr_id : regfile_addr_ra_id; + + `endif // THREE_PORT_REG_FILE // Forwarding control signals + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE assign reg_d_ex_is_reg_a_id = (regfile_waddr_ex_o == regfile_addr_ra_id) && (rega_used_dec == 1'b1) && (regfile_addr_ra_id != '0); assign reg_d_ex_is_reg_b_id = (regfile_waddr_ex_o == regfile_addr_rb_id) && (regb_used_dec == 1'b1) && (regfile_addr_rb_id != '0); assign reg_d_ex_is_reg_c_id = (regfile_waddr_ex_o == regfile_addr_rc_id) && (regc_used_dec == 1'b1) && (regfile_addr_rc_id != '0); @@ -500,6 +539,14 @@ module riscv_id_stage #( assign reg_d_alu_is_reg_a_id = (regfile_alu_waddr_fw_i == regfile_addr_ra_id) && (rega_used_dec == 1'b1) && (regfile_addr_ra_id != '0); assign reg_d_alu_is_reg_b_id = (regfile_alu_waddr_fw_i == regfile_addr_rb_id) && (regb_used_dec == 1'b1) && (regfile_addr_rb_id != '0); assign reg_d_alu_is_reg_c_id = (regfile_alu_waddr_fw_i == regfile_addr_rc_id) && (regc_used_dec == 1'b1) && (regfile_addr_rc_id != '0); + `else // THREE_PORT_REG_FILE + assign reg_d_ex_is_reg_a_id = (regfile_waddr_ex_o == regfile_addr_ra_id) && (rega_used_dec == 1'b1) && (regfile_addr_ra_id != '0); + assign reg_d_ex_is_reg_b_id = (regfile_waddr_ex_o == regfile_addr_rb_id) && (regb_used_dec == 1'b1) && (regfile_addr_rb_id != '0); + assign reg_d_wb_is_reg_a_id = (regfile_waddr_wb_i == regfile_addr_ra_id) && (rega_used_dec == 1'b1) && (regfile_addr_ra_id != '0); + assign reg_d_wb_is_reg_b_id = (regfile_waddr_wb_i == regfile_addr_rb_id) && (regb_used_dec == 1'b1) && (regfile_addr_rb_id != '0); + assign reg_d_alu_is_reg_a_id = (regfile_alu_waddr_fw_i == regfile_addr_ra_id) && (rega_used_dec == 1'b1) && (regfile_addr_ra_id != '0); + assign reg_d_alu_is_reg_b_id = (regfile_alu_waddr_fw_i == regfile_addr_rb_id) && (regb_used_dec == 1'b1) && (regfile_addr_rb_id != '0); + `endif // THREE_PORT_REG_FILE @@ -595,15 +642,18 @@ module riscv_id_stage #( // | |_| | |_) | __/ | | (_| | | | | (_| | / ___ \ // // \___/| .__/ \___|_| \__,_|_| |_|\__,_| /_/ \_\ // // |_| // - //////////////////////////////////////////////////////// - + /////////////////////////////////////////////////////// +/ // ALU_Op_a Mux always_comb begin : alu_operand_a_mux case (alu_op_a_mux_sel) OP_A_REGA_OR_FWD: alu_operand_a = operand_a_fw_id; OP_A_REGB_OR_FWD: alu_operand_a = operand_b_fw_id; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE OP_A_REGC_OR_FWD: alu_operand_a = operand_c_fw_id; + `endif // THREE_PORT_REG_FILE OP_A_CURRPC: alu_operand_a = pc_id_i; OP_A_IMM: alu_operand_a = imm_a; default: alu_operand_a = operand_a_fw_id; @@ -669,7 +719,10 @@ module riscv_id_stage #( case (alu_op_b_mux_sel) OP_B_REGA_OR_FWD: operand_b = operand_a_fw_id; OP_B_REGB_OR_FWD: operand_b = operand_b_fw_id; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE OP_B_REGC_OR_FWD: operand_b = operand_c_fw_id; + `endif // THREE_PORT_REG_FILE OP_B_IMM: operand_b = imm_b; OP_B_BMASK: operand_b = $unsigned(operand_b_fw_id[4:0]); default: operand_b = operand_b_fw_id; @@ -734,6 +787,8 @@ module riscv_id_stage #( // |_| // ////////////////////////////////////////////////////// + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE // ALU OP C Mux always_comb begin : alu_operand_c_mux @@ -756,6 +811,19 @@ module riscv_id_stage #( endcase; // case (operand_c_fw_mux_sel) end + `else + // ALU OP C Mux + always_comb + begin : alu_operand_c_mux + case (alu_op_c_mux_sel) + OP_C_REGB_OR_FWD: alu_operand_c = operand_b_fw_id; + OP_C_JT: alu_operand_c = jump_target; + default: alu_operand_c = operand_b_fw_id; + endcase // case (alu_op_c_mux_sel) + end + + `endif // THREE_PORT_REG_FILE + /////////////////////////////////////////////////////////////////////////// // ___ _ _ _ ___ ____ // @@ -845,6 +913,8 @@ module riscv_id_stage #( .raddr_a_i ( regfile_addr_ra_id ), .rdata_a_o ( regfile_data_ra_id ), + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE // Read port b .raddr_b_i ( regfile_addr_rb_id ), .rdata_b_o ( regfile_data_rb_id ), @@ -852,19 +922,38 @@ module riscv_id_stage #( // Read port c .raddr_c_i ( (dbg_reg_rreq_i == 1'b0) ? regfile_addr_rc_id : dbg_reg_raddr_i ), .rdata_c_o ( regfile_data_rc_id ), + `else + .raddr_b_i ( (dbg_reg_rreq_i == 1'b0) ? regfile_addr_rb_id : dbg_reg_raddr_i ), + .rdata_b_o ( regfile_data_rb_id ), + `endif // THREE_PORT_REG_FILE + + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE // Write port a .waddr_a_i ( regfile_waddr_wb_i ), .wdata_a_i ( regfile_wdata_wb_i ), .we_a_i ( regfile_we_wb_i ), // Write port b - .waddr_b_i ( (dbg_reg_wreq_i == 1'b0) ? regfile_alu_waddr_fw_i : dbg_reg_waddr_i ), + .waddr_b_i ( (dbg_reg_wreq_i == 1'b0) ? regfile_alu_waddr_fw_i : dbg_reg_waddr_i ), .wdata_b_i ( (dbg_reg_wreq_i == 1'b0) ? regfile_alu_wdata_fw_i : dbg_reg_wdata_i ), .we_b_i ( (dbg_reg_wreq_i == 1'b0) ? regfile_alu_we_fw_i : 1'b1 ) + + `else + // Write port a (multiplex between ALU and LSU) + .waddr_a_i ( (dbg_reg_wreq_i == 1'b0) ? ( (regfile_alu_we_fw_i == 1'b1) ? regfile_alu_waddr_fw_i : regfile_waddr_wb_i) : dbg_reg_waddr_i ), + .wdata_a_i ( (dbg_reg_wreq_i == 1'b0) ? ( (regfile_alu_we_fw_i == 1'b1) ? regfile_alu_wdata_fw_i : regfile_wdata_wb_i) : dbg_reg_wdata_i ), + .we_a_i ( (dbg_reg_wreq_i == 1'b0) ? (regfile_alu_we_fw_i | regfile_we_wb_i) : 1'b1 ) + `endif // THREE_PORT_REG_FILE ); + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE assign dbg_reg_rdata_o = regfile_data_rc_id; + `else + assign dbg_reg_rdata_o = regfile_data_rb_id; + `endif // THREE_PORT_REG_FILE /////////////////////////////////////////////// @@ -894,7 +983,10 @@ module riscv_id_stage #( .rega_used_o ( rega_used_dec ), .regb_used_o ( regb_used_dec ), + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE .regc_used_o ( regc_used_dec ), + `endif // THREE_PORT_REG_FILE // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT @@ -914,6 +1006,7 @@ module riscv_id_stage #( .alu_op_a_mux_sel_o ( alu_op_a_mux_sel ), .alu_op_b_mux_sel_o ( alu_op_b_mux_sel ), .alu_op_c_mux_sel_o ( alu_op_c_mux_sel ), + // CONFIG_REGION: VEC_SUPPORT `ifdef VEC_SUPPORT .alu_vec_mode_o ( alu_vec_mode ), @@ -921,7 +1014,10 @@ module riscv_id_stage #( `endif // VEC_SUPPORT .imm_a_mux_sel_o ( imm_a_mux_sel ), .imm_b_mux_sel_o ( imm_b_mux_sel ), + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE .regc_mux_o ( regc_mux ), + `endif // THREE_PORT_REG_FILE // CONFIG_REGION: MUL_SUPPORT `ifdef MUL_SUPPORT @@ -999,7 +1095,10 @@ module riscv_id_stage #( .rega_used_i ( rega_used_dec ), .regb_used_i ( regb_used_dec ), + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE .regc_used_i ( regc_used_dec ), + `endif // THREE_PORT_REG_FILE // from IF/ID pipeline .instr_valid_i ( instr_valid_i ), @@ -1050,11 +1149,13 @@ module riscv_id_stage #( .regfile_waddr_wb_i ( regfile_waddr_wb_i ), // Write address for register file from ex-wb- pipeline registers .regfile_we_wb_i ( regfile_we_wb_i ), - // regfile port 2 + // regfile port 2 (or multiplexer signal in case of a 2r1w) .regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw_i ), .regfile_alu_we_fw_i ( regfile_alu_we_fw_i ), // Forwarding detection signals + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE .reg_d_ex_is_reg_a_i ( reg_d_ex_is_reg_a_id ), .reg_d_ex_is_reg_b_i ( reg_d_ex_is_reg_b_id ), .reg_d_ex_is_reg_c_i ( reg_d_ex_is_reg_c_id ), @@ -1064,11 +1165,21 @@ module riscv_id_stage #( .reg_d_alu_is_reg_a_i ( reg_d_alu_is_reg_a_id ), .reg_d_alu_is_reg_b_i ( reg_d_alu_is_reg_b_id ), .reg_d_alu_is_reg_c_i ( reg_d_alu_is_reg_c_id ), + `else + .reg_d_ex_is_reg_a_i ( reg_d_ex_is_reg_a_id ), + .reg_d_ex_is_reg_b_i ( reg_d_ex_is_reg_b_id ), + .reg_d_wb_is_reg_a_i ( reg_d_wb_is_reg_a_id ), + .reg_d_wb_is_reg_b_i ( reg_d_wb_is_reg_b_id ), + `endif // THREE_PORT_REG_FILE + // Forwarding signals .operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ), .operand_b_fw_mux_sel_o ( operand_b_fw_mux_sel ), + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE .operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ), + `endif // THREE_PORT_REG_FILE // Stall signals .halt_if_o ( halt_if_o ), @@ -1192,7 +1303,7 @@ always_ff @(posedge clk, negedge rst_n) alu_operator_ex_o <= ALU_SLTU; alu_operand_a_ex_o <= '0; alu_operand_b_ex_o <= '0; - alu_operand_c_ex_o <= '0; + alu_operand_c_ex_o <= '0; // Still needed for jump target if 2r1w reg file used // CONFIG_REGION: BIT_SUPPORT `ifdef BIT_SUPPORT diff --git a/include/riscv_config.sv b/include/riscv_config.sv index 88bf6640..0f654229 100644 --- a/include/riscv_config.sv +++ b/include/riscv_config.sv @@ -69,6 +69,10 @@ // Dependent definitions +// enables 3r2w reg file (rather than 2r1w) +//`define THREE_PORT_REG_FILE + + `ifndef MUL_SUPPORT `ifndef VEC_SUPPORT `ifndef BIT_SUPPORT @@ -78,8 +82,6 @@ // use simplified ALU `define SIMPLE_ALU -// reduce register file to 1w2r -`define TWO_PORT_REG_FILE `endif `endif diff --git a/register_file.sv b/register_file.sv index d7709c20..004a91dd 100644 --- a/register_file.sv +++ b/register_file.sv @@ -24,6 +24,8 @@ // // //////////////////////////////////////////////////////////////////////////////// +`include "riscv_config.sv" + module riscv_register_file #( parameter ADDR_WIDTH = 5, @@ -44,19 +46,27 @@ module riscv_register_file input logic [ADDR_WIDTH-1:0] raddr_b_i, output logic [DATA_WIDTH-1:0] rdata_b_o, + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE //Read port R3 input logic [ADDR_WIDTH-1:0] raddr_c_i, output logic [DATA_WIDTH-1:0] rdata_c_o, + `endif // THREE_PORT_REG_FILE // Write port W1 input logic [ADDR_WIDTH-1:0] waddr_a_i, input logic [DATA_WIDTH-1:0] wdata_a_i, - input logic we_a_i, + input logic we_a_i + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE + , + // Write port W2 input logic [ADDR_WIDTH-1:0] waddr_b_i, input logic [DATA_WIDTH-1:0] wdata_b_i, input logic we_b_i + `endif // THREE_PORT_REG_FILE ); localparam NUM_WORDS = 2**ADDR_WIDTH; @@ -64,11 +74,17 @@ module riscv_register_file logic [DATA_WIDTH-1:0] mem[NUM_WORDS]; logic [NUM_WORDS-1:1] waddr_onehot_a; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic [NUM_WORDS-1:1] waddr_onehot_b, waddr_onehot_b_q; + `endif // THREE_PORT_REG_FILE logic [NUM_WORDS-1:1] mem_clocks; logic [DATA_WIDTH-1:0] wdata_a_q; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic [DATA_WIDTH-1:0] wdata_b_q; + `endif // THREE_PORT_REG_FILE logic clk_int; @@ -77,15 +93,16 @@ module riscv_register_file int unsigned k; genvar x; - genvar y; //----------------------------------------------------------------------------- //-- READ : Read address decoder RAD //----------------------------------------------------------------------------- assign rdata_a_o = mem[raddr_a_i]; assign rdata_b_o = mem[raddr_b_i]; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE assign rdata_c_o = mem[raddr_c_i]; - + `endif // THREE_PORT_REG_FILE //----------------------------------------------------------------------------- // WRITE : SAMPLE INPUT DATA @@ -94,7 +111,12 @@ module riscv_register_file cluster_clock_gating CG_WE_GLOBAL ( .clk_i ( clk ), + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE .en_i ( we_a_i | we_b_i ), + `else + .en_i ( we_a_i ), + `endif // THREE_PORT_REG_FILE .test_en_i ( test_en_i ), .clk_o ( clk_int ) ); @@ -104,16 +126,21 @@ module riscv_register_file begin : sample_waddr if (~rst_n) begin wdata_a_q <= '0; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE wdata_b_q <= '0; waddr_onehot_b_q <= '0; + `endif // THREE_PORT_REG_FILE end else begin if(we_a_i) wdata_a_q <= wdata_a_i; - + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE if(we_b_i) wdata_b_q <= wdata_b_i; waddr_onehot_b_q <= waddr_onehot_b; + `endif // THREE_PORT_REG_FILE end end @@ -131,6 +158,8 @@ module riscv_register_file end end + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE always_comb begin : p_WADb for(j = 1; j < NUM_WORDS; j++) @@ -141,6 +170,7 @@ module riscv_register_file waddr_onehot_b[j] = 1'b0; end end + `endif // THREE_PORT_REG_FILE //----------------------------------------------------------------------------- //-- WRITE : Clock gating (if integrated clock-gating cells are available) @@ -151,7 +181,12 @@ module riscv_register_file cluster_clock_gating CG_Inst ( .clk_i ( clk_int ), + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE .en_i ( waddr_onehot_a[x] | waddr_onehot_b[x] ), + `else + .en_i ( waddr_onehot_a[x] ), + `endif // THREE_PORT_REG_FILE .test_en_i ( test_en_i ), .clk_o ( mem_clocks[x] ) ); @@ -175,7 +210,12 @@ module riscv_register_file for(k = 1; k < NUM_WORDS; k++) begin : w_WordIter if(mem_clocks[k] == 1'b1) + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE mem[k] = waddr_onehot_b_q[k] ? wdata_b_q : wdata_a_q; + `else + mem[k] = wdata_a_q; + `endif // THREE_PORT_REG_FILE end end diff --git a/register_file_ff.sv b/register_file_ff.sv index 7f9e214e..0d91d5f9 100644 --- a/register_file_ff.sv +++ b/register_file_ff.sv @@ -20,6 +20,8 @@ // // //////////////////////////////////////////////////////////////////////////////// +`include "riscv_config.sv" + module riscv_register_file #( parameter ADDR_WIDTH = 5, @@ -40,26 +42,37 @@ module riscv_register_file input logic [ADDR_WIDTH-1:0] raddr_b_i, output logic [DATA_WIDTH-1:0] rdata_b_o, + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE //Read port R3 input logic [ADDR_WIDTH-1:0] raddr_c_i, output logic [DATA_WIDTH-1:0] rdata_c_o, + `endif // THREE_PORT_REG_FILE // Write port W1 input logic [ADDR_WIDTH-1:0] waddr_a_i, input logic [DATA_WIDTH-1:0] wdata_a_i, - input logic we_a_i, + input logic we_a_i + + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE + , // Write port W2 input logic [ADDR_WIDTH-1:0] waddr_b_i, input logic [DATA_WIDTH-1:0] wdata_b_i, input logic we_b_i + `endif // THREE_PORT_REG_FILE ); localparam NUM_WORDS = 2**ADDR_WIDTH; logic [NUM_WORDS-1:0][DATA_WIDTH-1:0] rf_reg; logic [NUM_WORDS-1:0] we_a_dec; + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE logic [NUM_WORDS-1:0] we_b_dec; + `endif // THREE_PORT_REG_FILE always_comb begin : we_a_decoder @@ -71,6 +84,8 @@ module riscv_register_file end end + // CONFIG_REGION: THREE_PORT_REG_FILE + `ifdef THREE_PORT_REG_FILE always_comb begin : we_b_decoder for (int i=0; i