mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 12:57:13 -04:00
JAL working
This commit is contained in:
parent
6d8d6287b4
commit
c9a0ffdc7d
8 changed files with 277 additions and 207 deletions
29
alu.sv
29
alu.sv
|
@ -36,6 +36,7 @@ module alu
|
|||
input logic [`ALU_OP_WIDTH-1:0] operator_i,
|
||||
input logic [31:0] operand_a_i,
|
||||
input logic [31:0] operand_b_i,
|
||||
input logic [31:0] operand_c_i, // for jump target calculation
|
||||
input logic carry_i,
|
||||
input logic flag_i,
|
||||
|
||||
|
@ -44,12 +45,15 @@ module alu
|
|||
input logic [1:0] vec_ext_i,
|
||||
|
||||
output logic [31:0] result_o,
|
||||
output logic [31:0] jump_target_o,
|
||||
output logic overflow_o,
|
||||
output logic carry_o,
|
||||
output logic flag_o
|
||||
);
|
||||
|
||||
|
||||
logic [31:0] pc_after_jal;
|
||||
|
||||
logic [31:0] operand_a_rev; // bit reversed signal of operand_a_i
|
||||
|
||||
// bit reverse operand_a for left shifts
|
||||
|
@ -140,6 +144,9 @@ module alu
|
|||
assign {carry_out[2], adder_result[23:16]} = adder_op_a[23:16] + adder_op_b[23:16] + carry_in[2];
|
||||
assign {carry_out[3], adder_result[31:24]} = adder_op_a[31:24] + adder_op_b[31:24] + carry_in[3];
|
||||
|
||||
// additional 32 bit adder for PC after JAL(R) instruction
|
||||
assign pc_after_jal = operand_c_i + 32'd4;
|
||||
|
||||
|
||||
// averaging by right shifting of one bit
|
||||
logic [31:0] result_avg;
|
||||
|
@ -539,18 +546,19 @@ module alu
|
|||
|
||||
always_comb
|
||||
begin
|
||||
shift_left = 1'b0;
|
||||
shift_amt = operand_b_i;
|
||||
result_o = 'x;
|
||||
carry_o = 1'b0;
|
||||
overflow_o = 1'b0;
|
||||
flag_o = 1'b0;
|
||||
shift_left = 1'b0;
|
||||
shift_amt = operand_b_i;
|
||||
result_o = 'x;
|
||||
jump_target_o = 1'b0;
|
||||
carry_o = 1'b0;
|
||||
overflow_o = 1'b0;
|
||||
flag_o = 1'b0;
|
||||
|
||||
unique case (operator_i)
|
||||
// Standard Operations
|
||||
`ALU_ADD, `ALU_ADDC, `ALU_SUB:
|
||||
begin // Addition defined above
|
||||
result_o = adder_result[31:0];
|
||||
result_o = adder_result;
|
||||
carry_o = carry_out[3];
|
||||
overflow_o = (adder_op_a[31] ^ adder_result[31]) & (adder_op_b[31] ^ adder_result[31]); // ++ => - and -- => +
|
||||
end
|
||||
|
@ -559,6 +567,13 @@ module alu
|
|||
`ALU_OR: result_o = operand_a_i | operand_b_i;
|
||||
`ALU_XOR: result_o = operand_a_i ^ operand_b_i;
|
||||
|
||||
// Jump Target Calculation
|
||||
`ALU_JAL:
|
||||
begin
|
||||
result_o = pc_after_jal;
|
||||
jump_target_o = adder_result;
|
||||
end
|
||||
|
||||
// Shift Operations
|
||||
`ALU_MOVHI:
|
||||
begin
|
||||
|
|
|
@ -53,6 +53,7 @@ module controller
|
|||
output logic extend_immediate_o, // Extend a 16 bit immediate to 32 bit
|
||||
output logic [1:0] alu_op_a_mux_sel_o, // Operator a is selected between reg value, PC or immediate
|
||||
output logic [1:0] alu_op_b_mux_sel_o, // Operator b is selected between reg value or immediate
|
||||
output logic alu_op_c_mux_sel_o, // Operator c is selected between reg value or PC
|
||||
output logic alu_pc_mux_sel_o, // selects IF or ID PC for ALU computations
|
||||
output logic [3:0] immediate_mux_sel_o,
|
||||
|
||||
|
@ -134,6 +135,9 @@ module controller
|
|||
output logic [1:0] operand_b_fw_mux_sel_o, // regfile rb data selector form ID stage
|
||||
output logic [1:0] operand_c_fw_mux_sel_o, // regfile rc data selector form ID stage
|
||||
|
||||
// Jump target calcuation done detection
|
||||
input logic jump_in_ex_i, // jump is being calculated in ALU
|
||||
|
||||
output logic drop_instruction_o, // prevent instruction to enter ID stage
|
||||
`ifdef BRANCH_PREDICTION
|
||||
output logic wrong_branch_taken_o, // 1 if the wrong branch was selected
|
||||
|
@ -175,7 +179,7 @@ module controller
|
|||
logic mfspr_stall;
|
||||
logic instr_ack_stall;
|
||||
logic load_stall;
|
||||
logic jr_stall;
|
||||
logic j_stall;
|
||||
|
||||
logic set_npc;
|
||||
`ifdef BRANCH_PREDICTION
|
||||
|
@ -207,6 +211,7 @@ module controller
|
|||
extend_immediate_o = 1'b0;
|
||||
alu_op_a_mux_sel_o = `OP_A_REGA_OR_FWD;
|
||||
alu_op_b_mux_sel_o = `OP_B_REGB_OR_FWD;
|
||||
alu_op_c_mux_sel_o = `OP_C_REGC_OR_FWD;
|
||||
alu_pc_mux_sel_o = 1'b1;
|
||||
|
||||
vector_mode_o = `VEC_MODE32;
|
||||
|
@ -318,6 +323,7 @@ module controller
|
|||
pc_mux_sel_o = `PC_FROM_ALU;
|
||||
alu_op_a_mux_sel_o = `OP_A_CURRPC;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
alu_op_c_mux_sel_o = `OP_C_CURRPC;
|
||||
immediate_mux_sel_o = `IMM_UJ;
|
||||
alu_operator = `ALU_JAL;
|
||||
regfile_alu_we = 1'b1;
|
||||
|
@ -330,6 +336,7 @@ module controller
|
|||
if (instr_rdata_i ==? `INSTR_JALR) begin
|
||||
pc_mux_sel_o = `PC_FROM_ALU;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
alu_op_c_mux_sel_o = `OP_C_CURRPC;
|
||||
immediate_mux_sel_o = `IMM_I;
|
||||
alu_operator = `ALU_JAL;
|
||||
regfile_alu_we = 1'b1;
|
||||
|
@ -1141,13 +1148,13 @@ module controller
|
|||
|
||||
endcase; // case (instr_rdata_i[6:0])
|
||||
|
||||
// synopsys translate_off
|
||||
if (illegal_insn_o == 1'b1) begin
|
||||
// synopsys translate_off
|
||||
$display("%t: Illegal instruction:", $time, instr_rdata_i);
|
||||
prettyPrintInstruction(instr_rdata_i);
|
||||
$display("%t: Illegal instruction:", $time);
|
||||
prettyPrintInstruction(instr_rdata_i, id_stage.current_pc_id_i);
|
||||
$stop;
|
||||
// synopsys translate_on
|
||||
end
|
||||
// synopsys translate_on
|
||||
|
||||
// misaligned access was detected by the LSU
|
||||
if (data_misaligned_i == 1'b1)
|
||||
|
@ -1196,7 +1203,7 @@ module controller
|
|||
mfspr_stall = 1'b0;
|
||||
mtspr_stall = 1'b0;
|
||||
load_stall = 1'b0;
|
||||
jr_stall = 1'b0;
|
||||
j_stall = 1'b0;
|
||||
deassert_we = 1'b0;
|
||||
|
||||
|
||||
|
@ -1230,16 +1237,24 @@ module controller
|
|||
// Stall because of jr path
|
||||
// - Load results cannot directly be forwarded to PC
|
||||
// - Multiplication results cannot be forwarded to PC
|
||||
if (((instr_rdata_i[6:0] == `OPCODE_JALR) || (instr_rdata_i[6:0] == `OPCODE_JAL)) &&
|
||||
if ((instr_rdata_i[6:0] == `OPCODE_JALR) &&
|
||||
(((regfile_we_wb_i == 1'b1) && (reg_d_wb_is_reg_b_id == 1'b1) && (data_rvalid_i == 1'b1)) ||
|
||||
((regfile_we_ex_i == 1'b1) && (reg_d_ex_is_reg_b_id == 1'b1)) ||
|
||||
((regfile_alu_we_fw_i == 1'b1) && (reg_d_alu_is_reg_b_id == 1'b1) && (mult_is_running_ex_i == 1'b1))) )
|
||||
begin
|
||||
jr_stall = 1'b1;
|
||||
j_stall = 1'b1;
|
||||
deassert_we = 1'b1;
|
||||
end
|
||||
|
||||
/*
|
||||
// Stall because of JAL/JALR
|
||||
// Stall until jump target is calculated in EX (1 cycle, then fetch instruction)
|
||||
if ( (instr_rdata_i[6:0] == `OPCODE_JAL || instr_rdata_i[6:0] == `OPCODE_JALR) &&
|
||||
(jump_in_ex_i == 1'b0) )
|
||||
begin
|
||||
j_stall = 1'b1;
|
||||
//deassert_we = 1'b1;
|
||||
end
|
||||
|
||||
`ifdef BRANCH_PREDICTION
|
||||
// Stall because of set_flag path
|
||||
if (wrong_branch_taken)
|
||||
|
@ -1247,14 +1262,13 @@ module controller
|
|||
deassert_we = 1'b1;
|
||||
end
|
||||
`endif
|
||||
*/
|
||||
|
||||
end
|
||||
|
||||
`ifdef BRANCH_PREDICTION
|
||||
assign drop_instruction_o = wrong_branch_taken;
|
||||
assign drop_instruction_o = wrong_branch_taken | j_stall;
|
||||
`else
|
||||
assign drop_instruction_o = 1'b0;
|
||||
assign drop_instruction_o = j_stall;
|
||||
`endif
|
||||
|
||||
// Stall because of IF miss
|
||||
|
@ -1285,8 +1299,8 @@ module controller
|
|||
// 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 | mfspr_stall | mtspr_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_stall_i | (~pc_valid_i));
|
||||
stall_id_o = instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_stall_i;
|
||||
stall_if_o = (instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | j_stall | lsu_stall | misalign_stall | dbg_stall_i | (~pc_valid_i));
|
||||
stall_id_o = instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | j_stall | lsu_stall | misalign_stall | dbg_stall_i;
|
||||
stall_ex_o = instr_ack_stall | lsu_stall | dbg_stall_i;
|
||||
stall_wb_o = lsu_stall | dbg_stall_i;
|
||||
end
|
||||
|
@ -1297,14 +1311,14 @@ module controller
|
|||
// RiscV register encoding: rs1 is [19:15], rs2 is [24:20], rd is [11:7] //
|
||||
// Or10n register encoding: ra is [20:16], rb is [15:11], rd is [25:21] //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
assign reg_d_ex_is_reg_a_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_RS1]) && (rega_used == 1'b1);
|
||||
assign reg_d_ex_is_reg_b_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_RS2]) && (regb_used == 1'b1);
|
||||
assign reg_d_ex_is_reg_c_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_RD]) && (regc_used == 1'b1);
|
||||
assign reg_d_wb_is_reg_a_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_RS1]) && (rega_used == 1'b1);
|
||||
assign reg_d_wb_is_reg_b_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_RS2]) && (regb_used == 1'b1);
|
||||
assign reg_d_wb_is_reg_c_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_RD]) && (regc_used == 1'b1);
|
||||
assign reg_d_alu_is_reg_a_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_RS1]) && (rega_used == 1'b1);
|
||||
assign reg_d_alu_is_reg_b_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_RS2]) && (regb_used == 1'b1);
|
||||
assign reg_d_ex_is_reg_a_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1);
|
||||
assign reg_d_ex_is_reg_b_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1);
|
||||
assign reg_d_ex_is_reg_c_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_D]) && (regc_used == 1'b1);
|
||||
assign reg_d_wb_is_reg_a_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1);
|
||||
assign reg_d_wb_is_reg_b_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1);
|
||||
assign reg_d_wb_is_reg_c_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_D]) && (regc_used == 1'b1);
|
||||
assign reg_d_alu_is_reg_a_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1);
|
||||
assign reg_d_alu_is_reg_b_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1);
|
||||
//assign reg_d_alu_is_reg_c_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_RD]) && (regc_used == 1'b1);
|
||||
|
||||
always_comb
|
||||
|
|
37
ex_stage.sv
37
ex_stage.sv
|
@ -119,7 +119,10 @@ module ex_stage
|
|||
output logic [4:0] regfile_alu_waddr_fw_o,
|
||||
output logic regfile_alu_we_fw_o,
|
||||
output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL
|
||||
output logic [31:0] regfile_alu_wdata_fw_pc_o // forward to PC, no multiplication
|
||||
output logic [31:0] regfile_alu_wdata_fw_pc_o, // forward to PC, no multiplication
|
||||
|
||||
// JAL/JALR jumpt target calculation (to IF)
|
||||
output logic [31:0] jump_target_o
|
||||
|
||||
`ifdef TCDM_ADDR_PRECAL
|
||||
,
|
||||
|
@ -134,6 +137,7 @@ module ex_stage
|
|||
|
||||
// Internal output of the LU
|
||||
logic [31:0] alu_result;
|
||||
logic [31:0] alu_jump_target_int;
|
||||
|
||||
logic [31:0] alu_adder_lsu_int; // to LS unit
|
||||
|
||||
|
@ -182,6 +186,10 @@ module ex_stage
|
|||
assign data_addr_ex_o = (prepost_useincr_i == 1'b1) ? alu_adder_lsu_int : alu_operand_a_i;
|
||||
|
||||
|
||||
// PC calculation for JAL/JALR
|
||||
assign jump_target_o = alu_jump_target_int;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// _ _ _ _ //
|
||||
// / \ | | | | | | //
|
||||
|
@ -192,21 +200,22 @@ module ex_stage
|
|||
////////////////////////////
|
||||
alu alu_i
|
||||
(
|
||||
.operator_i ( alu_operator_i ),
|
||||
.operand_a_i ( alu_operand_a_i ),
|
||||
.operand_b_i ( alu_operand_b_i ),
|
||||
.carry_i ( alu_carry_i ),
|
||||
.flag_i ( alu_flag_i ),
|
||||
.operator_i ( alu_operator_i ),
|
||||
.operand_a_i ( alu_operand_a_i ),
|
||||
.operand_b_i ( alu_operand_b_i ),
|
||||
.operand_c_i ( alu_operand_c_i ),
|
||||
.carry_i ( alu_carry_i ),
|
||||
.flag_i ( alu_flag_i ),
|
||||
|
||||
.vector_mode_i ( vector_mode_i ),
|
||||
.cmp_mode_i ( alu_cmp_mode_i ),
|
||||
.vec_ext_i ( alu_vec_ext_i ),
|
||||
.vector_mode_i ( vector_mode_i ),
|
||||
.cmp_mode_i ( alu_cmp_mode_i ),
|
||||
.vec_ext_i ( alu_vec_ext_i ),
|
||||
|
||||
.adder_lsu_o ( alu_adder_lsu_int ),
|
||||
.result_o ( alu_result ),
|
||||
.overflow_o ( alu_overflow_int ), // Internal signal
|
||||
.carry_o ( alu_carry_int ), // Internal signal
|
||||
.flag_o ( alu_flag_o )
|
||||
.result_o ( alu_result ),
|
||||
.jump_target_o ( alu_jump_target_int ),
|
||||
.overflow_o ( alu_overflow_int ), // Internal signal
|
||||
.carry_o ( alu_carry_int ), // Internal signal
|
||||
.flag_o ( alu_flag_o )
|
||||
);
|
||||
|
||||
|
||||
|
|
193
id_stage.sv
193
id_stage.sv
|
@ -177,111 +177,113 @@ module id_stage
|
|||
|
||||
|
||||
// Immediate decoding and sign extension
|
||||
logic [31:0] imm_i_type;
|
||||
logic [31:0] imm_s_type;
|
||||
logic [31:0] imm_sb_type;
|
||||
logic [31:0] imm_u_type;
|
||||
logic [31:0] imm_uj_type;
|
||||
logic [31:0] imm_i_type;
|
||||
logic [31:0] imm_s_type;
|
||||
logic [31:0] imm_sb_type;
|
||||
logic [31:0] imm_u_type;
|
||||
logic [31:0] imm_uj_type;
|
||||
|
||||
logic [31:0] immediate_b; // contains the immediate for operand b
|
||||
logic [31:0] immediate_b; // contains the immediate for operand b
|
||||
|
||||
logic [31:0] current_pc; // PC to be used in ALU (either IF or ID)
|
||||
logic [31:0] current_pc; // PC to be used in ALU (either IF or ID)
|
||||
|
||||
logic exc_pc_sel;
|
||||
logic [2:0] pc_mux_sel_int; // selects next PC in if stage
|
||||
logic pc_from_immediate_mux_sel = 1'b0; // TODO: FIXME
|
||||
logic exc_pc_sel;
|
||||
logic [2:0] pc_mux_sel_int; // selects next PC in if stage
|
||||
//logic pc_from_immediate_mux_sel = 1'b0; // TODO: FIXME (remove)
|
||||
|
||||
logic irq_present;
|
||||
logic irq_present;
|
||||
|
||||
// Signals running between controller and exception controller
|
||||
logic jump_in_id;
|
||||
logic jump_in_ex; // registered copy of jump_in_id
|
||||
logic illegal_insn;
|
||||
logic trap_insn;
|
||||
logic pipe_flush;
|
||||
logic pc_valid;
|
||||
logic clear_isr_running;
|
||||
logic jump_in_id;
|
||||
logic jump_in_ex; // registered copy of jump_in_id
|
||||
logic illegal_insn;
|
||||
logic trap_insn;
|
||||
logic pipe_flush;
|
||||
logic pc_valid;
|
||||
logic clear_isr_running;
|
||||
|
||||
|
||||
logic [4:0] regfile_addr_ra_id;
|
||||
logic [4:0] regfile_addr_rb_id;
|
||||
logic [4:0] regfile_addr_rc_id;
|
||||
logic [4:0] regfile_addr_ra_id;
|
||||
logic [4:0] regfile_addr_rb_id;
|
||||
logic [4:0] regfile_addr_rc_id;
|
||||
|
||||
logic [4:0] regfile_waddr_id;
|
||||
logic [4:0] regfile_alu_waddr_id;
|
||||
logic regfile_alu_we_id;
|
||||
logic [4:0] regfile_waddr_id;
|
||||
logic [4:0] regfile_alu_waddr_id;
|
||||
logic regfile_alu_we_id;
|
||||
|
||||
logic [31:0] regfile_data_ra_id;
|
||||
logic [31:0] regfile_data_rb_id;
|
||||
logic [31:0] regfile_data_rc_id;
|
||||
logic [31:0] regfile_data_ra_id;
|
||||
logic [31:0] regfile_data_rb_id;
|
||||
logic [31:0] regfile_data_rc_id;
|
||||
|
||||
logic imm_sign_ext_sel;
|
||||
logic imm_sign_ext_sel;
|
||||
|
||||
// ALU Control
|
||||
logic [`ALU_OP_WIDTH-1:0] alu_operator;
|
||||
logic [1:0] alu_op_a_mux_sel;
|
||||
logic [1:0] alu_op_b_mux_sel;
|
||||
logic scalar_replication;
|
||||
logic [`ALU_OP_WIDTH-1:0] alu_operator;
|
||||
logic [1:0] alu_op_a_mux_sel;
|
||||
logic [1:0] alu_op_b_mux_sel;
|
||||
logic alu_op_c_mux_sel;
|
||||
logic scalar_replication;
|
||||
|
||||
logic [1:0] vector_mode;
|
||||
logic [1:0] alu_cmp_mode;
|
||||
logic [1:0] alu_vec_ext;
|
||||
logic [1:0] vector_mode;
|
||||
logic [1:0] alu_cmp_mode;
|
||||
logic [1:0] alu_vec_ext;
|
||||
|
||||
logic alu_pc_mux_sel;
|
||||
logic [3:0] immediate_mux_sel;
|
||||
logic alu_pc_mux_sel;
|
||||
logic [3:0] immediate_mux_sel;
|
||||
|
||||
// Multiplier Control
|
||||
logic mult_is_running; // output of the controller (1 if the opcode is a multiplication)
|
||||
logic [1:0] mult_sel_subword; // Select a subword when doing multiplications
|
||||
logic [1:0] mult_signed_mode; // Signed mode multiplication at the output of the controller, and before the pipe registers
|
||||
logic mult_use_carry; // Enables carry in for the MAC
|
||||
logic mult_mac_en; // Enables the use of the accumulator
|
||||
logic mult_is_running; // output of the controller (1 if the opcode is a multiplication)
|
||||
logic [1:0] mult_sel_subword; // Select a subword when doing multiplications
|
||||
logic [1:0] mult_signed_mode; // Signed mode multiplication at the output of the controller, and before the pipe registers
|
||||
logic mult_use_carry; // Enables carry in for the MAC
|
||||
logic mult_mac_en; // Enables the use of the accumulator
|
||||
|
||||
logic eoc; // End of computation generated from the controller
|
||||
logic eoc; // End of computation generated from the controller
|
||||
|
||||
// Register Write Control
|
||||
logic regfile_wdata_mux_sel;
|
||||
logic regfile_we_id;
|
||||
logic [1:0] regfile_alu_waddr_mux_sel; // TODO: FixMe -> 1bit
|
||||
logic regfile_wdata_mux_sel;
|
||||
logic regfile_we_id;
|
||||
logic [1:0] regfile_alu_waddr_mux_sel; // TODO: FixMe -> 1bit
|
||||
|
||||
// Special-Purpose Register Write Control
|
||||
logic sp_we_id;
|
||||
logic sp_we_id;
|
||||
|
||||
// Data Memory Control
|
||||
logic data_we_id;
|
||||
logic [1:0] data_type_id;
|
||||
logic data_sign_ext_id;
|
||||
logic [1:0] data_reg_offset_id;
|
||||
logic data_req_id;
|
||||
logic data_we_id;
|
||||
logic [1:0] data_type_id;
|
||||
logic data_sign_ext_id;
|
||||
logic [1:0] data_reg_offset_id;
|
||||
logic data_req_id;
|
||||
|
||||
// hwloop signals
|
||||
logic [1:0] hwloop_regid;
|
||||
logic [2:0] hwloop_we;
|
||||
logic hwloop_wb_mux_sel;
|
||||
logic [1:0] hwloop_cnt_mux_sel;
|
||||
logic [31:0] hwloop_cnt;
|
||||
logic hwloop_jump;
|
||||
logic hwloop_enable;
|
||||
logic [1:0] hwloop_regid;
|
||||
logic [2:0] hwloop_we;
|
||||
logic hwloop_wb_mux_sel;
|
||||
logic [1:0] hwloop_cnt_mux_sel;
|
||||
logic [31:0] hwloop_cnt;
|
||||
logic hwloop_jump;
|
||||
logic hwloop_enable;
|
||||
|
||||
// Supervision Register
|
||||
logic set_flag;
|
||||
logic set_carry;
|
||||
logic set_overflow;
|
||||
logic set_flag;
|
||||
logic set_carry;
|
||||
logic set_overflow;
|
||||
|
||||
logic prepost_useincr;
|
||||
logic prepost_useincr;
|
||||
|
||||
// Forwarding
|
||||
logic [1:0] operand_a_fw_mux_sel;
|
||||
logic [1:0] operand_b_fw_mux_sel;
|
||||
logic [1:0] operand_c_fw_mux_sel;
|
||||
logic [31:0] operand_a_fw_id;
|
||||
logic [31:0] operand_b_fw_id;
|
||||
logic [1:0] operand_a_fw_mux_sel;
|
||||
logic [1:0] operand_b_fw_mux_sel;
|
||||
logic [1:0] operand_c_fw_mux_sel;
|
||||
logic [31:0] operand_a_fw_id;
|
||||
logic [31:0] operand_b_fw_id;
|
||||
|
||||
logic [31:0] alu_operand_a;
|
||||
logic [31:0] alu_operand_b;
|
||||
logic [31:0] alu_operand_c;
|
||||
logic [31:0] operand_b; // before going through the scalar replication mux
|
||||
logic [31:0] operand_b_vec; // scalar replication of operand_b for 8 and 16 bit
|
||||
logic [31:0] alu_operand_a;
|
||||
logic [31:0] alu_operand_b;
|
||||
logic [31:0] alu_operand_c;
|
||||
logic [31:0] operand_b; // before going through the scalar replication mux
|
||||
logic [31:0] operand_b_vec; // scalar replication of operand_b for 8 and 16 bit
|
||||
logic [31:0] operand_c;
|
||||
|
||||
|
||||
// TODO: FIXME temporary assignments while not everything is implemented (e.g. exceptions)
|
||||
|
@ -301,12 +303,13 @@ module id_stage
|
|||
instr_rdata_i[20], instr_rdata_i[30:21], 1'b0 };
|
||||
|
||||
// source registers
|
||||
assign regfile_addr_ra_id = instr_rdata_i[`REG_RS1];
|
||||
assign regfile_addr_rb_id = instr_rdata_i[`REG_RS2];
|
||||
assign regfile_addr_ra_id = instr_rdata_i[`REG_S1];
|
||||
assign regfile_addr_rb_id = instr_rdata_i[`REG_S2];
|
||||
//assign regfile_addr_rc_id = instr_rdata_i[25:21];
|
||||
assign regfile_addr_rc_id = 32'd0;
|
||||
|
||||
// destination registers
|
||||
assign regfile_waddr_id = instr_rdata_i[`REG_RD];
|
||||
assign regfile_waddr_id = instr_rdata_i[`REG_D];
|
||||
|
||||
//assign alu_vec_ext = instr_rdata_i[9:8];
|
||||
|
||||
|
@ -333,14 +336,14 @@ module id_stage
|
|||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PC offset for `PC_FROM_IMM PC mux
|
||||
//assign pc_from_immediate_o = imm_uj_type;
|
||||
always_comb
|
||||
begin : pc_from_immediate_mux
|
||||
case (pc_from_immediate_mux_sel)
|
||||
1'b0: pc_from_immediate_o = imm_uj_type; // JAL
|
||||
1'b1: pc_from_immediate_o = imm_i_type; // JALR
|
||||
endcase // case (pc_from_immediate_mux_sel)
|
||||
end
|
||||
//assign pc_from_immediate_o = imm_uj_type; // riscv no longer used
|
||||
//always_comb
|
||||
//begin : pc_from_immediate_mux
|
||||
// case (pc_from_immediate_mux_sel)
|
||||
// 1'b0: pc_from_immediate_o = imm_uj_type; // JAL
|
||||
// 1'b1: pc_from_immediate_o = imm_i_type; // JALR
|
||||
// endcase // case (pc_from_immediate_mux_sel)
|
||||
//end
|
||||
|
||||
// PC Mux
|
||||
always_comb
|
||||
|
@ -472,14 +475,23 @@ module id_stage
|
|||
// |_| //
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
// ALU OP C Mux
|
||||
always_comb
|
||||
begin : alu_operand_c_mux
|
||||
case (alu_op_c_mux_sel)
|
||||
`OP_C_CURRPC: operand_c = current_pc;
|
||||
default: operand_c = regfile_data_rc_id;
|
||||
endcase // case (alu_op_c_mux_sel)
|
||||
end
|
||||
|
||||
// Operand c forwarding mux
|
||||
always_comb
|
||||
begin : operand_c_fw_mux
|
||||
case (operand_c_fw_mux_sel)
|
||||
`SEL_FW_EX: alu_operand_c = regfile_alu_wdata_fw_i;
|
||||
`SEL_FW_WB: alu_operand_c = regfile_wdata_wb_i;
|
||||
`SEL_REGFILE: alu_operand_c = regfile_data_rc_id;
|
||||
default: alu_operand_c = regfile_data_rc_id;
|
||||
`SEL_REGFILE: alu_operand_c = operand_c;
|
||||
default: alu_operand_c = operand_c;
|
||||
endcase; // case (operand_b_fw_mux_sel)
|
||||
end
|
||||
|
||||
|
@ -551,6 +563,7 @@ module id_stage
|
|||
.extend_immediate_o ( imm_sign_ext_sel ),
|
||||
.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 ),
|
||||
.alu_pc_mux_sel_o ( alu_pc_mux_sel ),
|
||||
.immediate_mux_sel_o ( immediate_mux_sel ),
|
||||
|
||||
|
@ -638,11 +651,13 @@ module id_stage
|
|||
.operand_b_fw_mux_sel_o ( operand_b_fw_mux_sel ),
|
||||
.operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ),
|
||||
|
||||
.jump_in_ex_i ( jump_in_ex ),
|
||||
|
||||
// branch prediction
|
||||
.drop_instruction_o ( drop_instruction_o ),
|
||||
.drop_instruction_o ( drop_instruction_o ),
|
||||
`ifdef BRANCH_PREDICTION
|
||||
.wrong_branch_taken_o ( wrong_branch_taken_o ),
|
||||
.take_branch_o ( take_branch_o ),
|
||||
.wrong_branch_taken_o ( wrong_branch_taken_o ),
|
||||
.take_branch_o ( take_branch_o ),
|
||||
`endif
|
||||
// Stall signals
|
||||
.stall_if_o ( stall_if_o ),
|
||||
|
|
10
if_stage.sv
10
if_stage.sv
|
@ -52,7 +52,8 @@ module if_stage
|
|||
input logic force_nop_i, // insert a NOP in the pipe
|
||||
input logic [31:0] exception_pc_reg_i, // address used to restore the program counter when the interrupt/exception is served
|
||||
input logic [31:0] pc_from_regfile_i, // pc from reg file
|
||||
input logic [31:0] pc_from_immediate_i, // pc from immediate
|
||||
input logic [31:0] pc_from_alu_i, // calculated jump target form ALU
|
||||
//input logic [31:0] pc_from_immediate_i, // pc from immediate
|
||||
input logic [31:0] pc_from_hwloop_i, // pc from hwloop start addr
|
||||
input logic [2:0] pc_mux_sel_i, // sel for pc multiplexer
|
||||
input logic pc_mux_boot_i, // load boot address as PC
|
||||
|
@ -93,8 +94,8 @@ module if_stage
|
|||
// Address to fetch the instruction
|
||||
assign instr_addr_o = next_pc;
|
||||
|
||||
assign branch_taken = current_pc_id_o + pc_from_immediate_i;
|
||||
assign branch_not_taken = current_pc_if_o + 32'd4;
|
||||
//assign branch_taken = current_pc_id_o + pc_from_immediate_i;
|
||||
//assign branch_not_taken = current_pc_if_o + 32'd4;
|
||||
|
||||
// Next PC Selection: pc_mux_sel_i comes from id_stage.controller
|
||||
always_comb
|
||||
|
@ -103,7 +104,8 @@ module if_stage
|
|||
`INCR_PC: begin next_pc = current_pc_if_o + 32'd4; end // PC is incremented and points the next instruction
|
||||
`NO_INCR: begin next_pc = current_pc_if_o; end // PC is not incremented
|
||||
`PC_FROM_REGFILE: begin next_pc = pc_from_regfile_i; end // PC is taken from the regfile
|
||||
`PC_FROM_IMM: begin next_pc = branch_taken; end // PC is taken from current PC in id + the immediate displacement
|
||||
`PC_FROM_ALU: begin next_pc = pc_from_alu_i; end // use calculated jump target from ALU
|
||||
//`PC_FROM_IMM: begin next_pc = branch_taken; end // PC is taken from current PC in id + the immediate displacement
|
||||
`PC_EXCEPTION: begin next_pc = exc_pc; end // PC that points to the exception
|
||||
`EXC_PC_REG: begin next_pc = exception_pc_reg_i; end // restore the PC when exiting from interr/ecpetions
|
||||
`HWLOOP_ADDR: begin next_pc = pc_from_hwloop_i; end // PC is taken from hwloop start addr
|
||||
|
|
|
@ -164,13 +164,13 @@
|
|||
*/
|
||||
|
||||
// Source/Destination register instruction index
|
||||
`define REG_RS1 19:15
|
||||
`define REG_RS2 24:20
|
||||
`define REG_RD 11:07
|
||||
`define REG_S1 19:15
|
||||
`define REG_S2 24:20
|
||||
`define REG_D 11:07
|
||||
|
||||
|
||||
// synopsis translate off
|
||||
function void prettyPrintInstruction(input [31:0] instr);
|
||||
function void prettyPrintInstruction(input [31:0] instr, input [31:0] pc);
|
||||
string opcode;
|
||||
begin
|
||||
unique case (instr[6:0])
|
||||
|
@ -188,10 +188,10 @@ function void prettyPrintInstruction(input [31:0] instr);
|
|||
default: opcode = "Unknown";
|
||||
endcase // unique case (instr[6:0])
|
||||
|
||||
$display("%t: %s Instruction 0x%h.", $time, opcode, instr[31:0]);
|
||||
$display("%t: %s Instruction 0x%h at 0x%h.", $time, opcode, instr[31:0], pc[31:0]);
|
||||
$display("%t: | fct7 | rs2 | rs1 | | rd | opc. |", $time);
|
||||
$display("%t: 0b %b %b %b %b %b %b", $time, instr[31:25], instr[`REG_RS2],
|
||||
instr[`REG_RS1], instr[14:12], instr[`REG_RD], instr[6:0]);
|
||||
$display("%t: 0b %b %b %b %b %b %b", $time, instr[31:25], instr[`REG_S2],
|
||||
instr[`REG_S1], instr[14:12], instr[`REG_D], instr[6:0]);
|
||||
$display();
|
||||
end
|
||||
endfunction // prettyPrintInstruction
|
||||
|
@ -268,6 +268,9 @@ endfunction // prettyPrintInstruction
|
|||
`define ALU_FL1 6'b11_0011
|
||||
`define ALU_CLB 6'b11_0001
|
||||
|
||||
// next PC and PC+4 computation for JAL/JALR in RiscV
|
||||
`define ALU_JAL 6'b11_1000
|
||||
|
||||
|
||||
// Vector Mode
|
||||
`define VEC_MODE32 2'b00
|
||||
|
@ -321,20 +324,24 @@ endfunction // prettyPrintInstruction
|
|||
`define SR_DSX 5'd13
|
||||
|
||||
// forwarding operand mux
|
||||
`define SEL_REGFILE 2'b00
|
||||
`define SEL_FW_EX 2'b01
|
||||
`define SEL_FW_WB 2'b10
|
||||
`define SEL_REGFILE 2'b00
|
||||
`define SEL_FW_EX 2'b01
|
||||
`define SEL_FW_WB 2'b10
|
||||
|
||||
// operand a selection
|
||||
`define OP_A_REGA_OR_FWD 2'b00
|
||||
`define OP_A_CURRPC 2'b10
|
||||
`define OP_A_IMM16 2'b11
|
||||
`define OP_A_ZERO 2'b11
|
||||
`define OP_A_REGA_OR_FWD 2'b00
|
||||
`define OP_A_CURRPC 2'b10
|
||||
`define OP_A_IMM16 2'b11
|
||||
`define OP_A_ZERO 2'b11
|
||||
|
||||
// operand b selection
|
||||
`define OP_B_REGB_OR_FWD 2'b00
|
||||
`define OP_B_REGC_OR_FWD 2'b01
|
||||
`define OP_B_IMM 2'b10
|
||||
`define OP_B_REGB_OR_FWD 2'b00
|
||||
`define OP_B_REGC_OR_FWD 2'b01
|
||||
`define OP_B_IMM 2'b10
|
||||
|
||||
// operand c selection
|
||||
`define OP_C_REGC_OR_FWD 1'b0
|
||||
`define OP_C_CURRPC 1'b1
|
||||
|
||||
// immediate selection
|
||||
// - `define IMM_5N11 4'b0000
|
||||
|
@ -357,7 +364,8 @@ endfunction // prettyPrintInstruction
|
|||
`define INCR_PC 3'b000
|
||||
`define NO_INCR 3'b001
|
||||
`define PC_FROM_REGFILE 3'b010
|
||||
`define PC_FROM_IMM 3'b011
|
||||
//`define PC_FROM_IMM 3'b011 Replaced in RiscV
|
||||
`define PC_FROM_ALU 3'b011
|
||||
`define PC_EXCEPTION 3'b100
|
||||
`define EXC_PC_REG 3'b101
|
||||
`define HWLOOP_ADDR 3'b110
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
// Additional contributions by: //
|
||||
// //
|
||||
// //
|
||||
// Create Date: 06/08/2014 //
|
||||
// Design Name: Instruction Fetch interface //
|
||||
// Create Date: 06/08/2014 //
|
||||
// Design Name: Instruction Fetch interface //
|
||||
// Module Name: instr_core_interface.sv //
|
||||
// Project Name: OR10N //
|
||||
// Language: SystemVerilog //
|
||||
|
@ -31,20 +31,20 @@ module instr_core_interface
|
|||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
|
||||
|
||||
|
||||
input logic req_i,
|
||||
input logic [31:0] addr_i,
|
||||
output logic ack_o,
|
||||
output logic [31:0] rdata_o,
|
||||
|
||||
|
||||
|
||||
|
||||
output logic instr_req_o,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic instr_gnt_i,
|
||||
input logic instr_r_valid_i,
|
||||
input logic [31:0] instr_r_rdata_i,
|
||||
|
||||
|
||||
input logic stall_if_i,
|
||||
|
||||
input logic drop_request_i
|
||||
|
@ -58,7 +58,7 @@ module instr_core_interface
|
|||
|
||||
logic wait_gnt;
|
||||
logic [31:0] addr_Q;
|
||||
|
||||
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if(rst_n == 1'b0)
|
||||
|
@ -70,19 +70,19 @@ module instr_core_interface
|
|||
else
|
||||
begin
|
||||
CS <= NS;
|
||||
|
||||
|
||||
if(wait_gnt)
|
||||
addr_Q <= addr_i;
|
||||
|
||||
|
||||
if(save_rdata)
|
||||
rdata_Q <= instr_r_rdata_i;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
always_comb
|
||||
begin
|
||||
|
||||
|
||||
instr_req_o = 1'b0;
|
||||
ack_o = 1'b0;
|
||||
save_rdata = 1'b0;
|
||||
|
@ -90,16 +90,16 @@ module instr_core_interface
|
|||
instr_addr_o = addr_i;
|
||||
|
||||
wait_gnt = 1'b0;
|
||||
|
||||
|
||||
case(CS)
|
||||
|
||||
IDLE :
|
||||
|
||||
IDLE :
|
||||
begin
|
||||
instr_req_o = req_i;
|
||||
ack_o = 1'b0;
|
||||
rdata_o = rdata_Q;
|
||||
|
||||
|
||||
|
||||
|
||||
if(req_i)
|
||||
begin
|
||||
if(instr_gnt_i) //~> granted request
|
||||
|
@ -115,10 +115,10 @@ module instr_core_interface
|
|||
end
|
||||
end // case: IDLE
|
||||
|
||||
|
||||
|
||||
WAIT_GNT :
|
||||
begin
|
||||
|
||||
|
||||
instr_addr_o = addr_Q;
|
||||
instr_req_o = 1'b1;
|
||||
|
||||
|
@ -131,17 +131,17 @@ module instr_core_interface
|
|||
// else
|
||||
NS = WAIT_GNT;
|
||||
end
|
||||
|
||||
|
||||
end // case: WAIT_GNT
|
||||
|
||||
|
||||
PENDING :
|
||||
|
||||
|
||||
PENDING :
|
||||
begin
|
||||
|
||||
if(instr_r_valid_i)
|
||||
begin
|
||||
save_rdata = 1'b1;
|
||||
|
||||
|
||||
ack_o = 1'b1;
|
||||
if(stall_if_i)
|
||||
begin
|
||||
|
@ -165,7 +165,7 @@ module instr_core_interface
|
|||
end
|
||||
else
|
||||
NS = IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
@ -174,23 +174,23 @@ module instr_core_interface
|
|||
ack_o = 1'b0;
|
||||
end
|
||||
end // case: PENDING
|
||||
|
||||
WAIT_RVALID :
|
||||
|
||||
WAIT_RVALID :
|
||||
begin
|
||||
|
||||
|
||||
|
||||
|
||||
if(instr_r_valid_i)
|
||||
begin
|
||||
|
||||
|
||||
ack_o = 1'b1;
|
||||
save_rdata = 1'b1;
|
||||
|
||||
|
||||
|
||||
|
||||
if(stall_if_i)
|
||||
begin
|
||||
instr_req_o = 1'b0;
|
||||
NS = WAIT_IF_STALL;
|
||||
|
||||
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
@ -205,7 +205,7 @@ module instr_core_interface
|
|||
else
|
||||
NS = IDLE;
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
else
|
||||
begin
|
||||
|
@ -214,14 +214,14 @@ module instr_core_interface
|
|||
instr_req_o = 1'b0;
|
||||
end
|
||||
end // case: WAIT_RVALID
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
WAIT_IF_STALL :
|
||||
begin
|
||||
ack_o = 1'b1;
|
||||
rdata_o = rdata_Q;
|
||||
|
||||
|
||||
if(stall_if_i)
|
||||
begin
|
||||
instr_req_o = 1'b0;
|
||||
|
@ -229,7 +229,7 @@ module instr_core_interface
|
|||
end
|
||||
else
|
||||
begin
|
||||
|
||||
|
||||
instr_req_o = req_i;
|
||||
if(req_i)
|
||||
if(instr_gnt_i)
|
||||
|
@ -241,11 +241,11 @@ module instr_core_interface
|
|||
else
|
||||
NS = IDLE;
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
end // case: WAIT_IF_STALL
|
||||
|
||||
|
||||
ABORT:
|
||||
begin
|
||||
ack_o = 1'b1;
|
||||
|
@ -264,17 +264,17 @@ module instr_core_interface
|
|||
NS = IDLE;
|
||||
end
|
||||
end // case: ABORT
|
||||
|
||||
|
||||
default :
|
||||
|
||||
|
||||
default :
|
||||
begin
|
||||
NS = IDLE;
|
||||
instr_req_o = 1'b0;
|
||||
end
|
||||
|
||||
|
||||
endcase
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
endmodule
|
|
@ -89,7 +89,10 @@ module riscv_core
|
|||
|
||||
|
||||
// Forwarding
|
||||
logic [31:0] pc_from_immediate_id; //take PC from immediate in case of Jump
|
||||
//logic [31:0] pc_from_immediate_id; //take PC from immediate in case of Jump
|
||||
|
||||
// Jump handling
|
||||
logic [31:0] jump_target;
|
||||
|
||||
// Stalling
|
||||
logic stall_if; // Stall instruction fetch(deassert request)
|
||||
|
@ -278,7 +281,8 @@ module riscv_core
|
|||
.force_nop_i ( force_nop_id ), // select incoming instr or NOP
|
||||
.exception_pc_reg_i ( epcr ), // Exception PC register
|
||||
.pc_from_regfile_i ( pc_from_regfile_id ), // pc from reg file
|
||||
.pc_from_immediate_i ( pc_from_immediate_id ), // pc from immediate
|
||||
//.pc_from_immediate_i ( pc_from_immediate_id ), // pc from immediate
|
||||
.pc_from_alu_i ( jump_target ), // calculated jump target from ALU (EX)
|
||||
.pc_from_hwloop_i ( hwloop_targ_addr ), // pc from hwloop start address
|
||||
.pc_mux_sel_i ( pc_mux_sel_id ), // sel for pc multiplexer
|
||||
.pc_mux_boot_i ( pc_mux_boot ), // load boot address as PC
|
||||
|
@ -362,7 +366,7 @@ module riscv_core
|
|||
.pc_from_regfile_o ( pc_from_regfile_id ),
|
||||
.current_pc_if_i ( current_pc_if ),
|
||||
.current_pc_id_i ( current_pc_id ),
|
||||
.pc_from_immediate_o ( pc_from_immediate_id ),
|
||||
//.pc_from_immediate_o ( pc_from_immediate_id ),
|
||||
|
||||
.sr_flag_fw_i ( sr_flag_fw ),
|
||||
.sr_flag_i ( sr_flag ),
|
||||
|
@ -563,6 +567,9 @@ module riscv_core
|
|||
.sp_we_wb_o ( sp_we_wb ),
|
||||
.eoc_o ( eoc_wb ),
|
||||
|
||||
// Jump target address
|
||||
.jump_target_o ( jump_target ),
|
||||
|
||||
// To ID stage: Forwarding signals
|
||||
.regfile_alu_waddr_fw_o ( regfile_alu_waddr_fw ),
|
||||
.regfile_alu_we_fw_o ( regfile_alu_we_fw ),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue