mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
Separated decoder and controller and cleanup
This commit is contained in:
parent
d27a2a3f63
commit
9858caff47
4 changed files with 1160 additions and 1025 deletions
942
controller.sv
942
controller.sv
File diff suppressed because it is too large
Load diff
867
decoder.sv
Normal file
867
decoder.sv
Normal file
|
@ -0,0 +1,867 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Company: IIS @ ETHZ - Federal Institute of Technology //
|
||||
// //
|
||||
// Engineer Andreas Traber - atraber@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// Matthias Baer - baermatt@student.ethz.ch //
|
||||
// Igor Loi - igor.loi@unibo.it //
|
||||
// Sven Stucki - svstucki@student.ethz.ch //
|
||||
// //
|
||||
// //
|
||||
// Create Date: 19/09/2013 //
|
||||
// Design Name: RISC-V processor core //
|
||||
// Module Name: decoder.sv //
|
||||
// Project Name: RI5CY //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Decoder //
|
||||
// //
|
||||
// //
|
||||
// Revision: //
|
||||
// Revision v0.1 - File Created, separated controller and decoder //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "defines.sv"
|
||||
|
||||
module decoder
|
||||
(
|
||||
// singals running to/from controller
|
||||
input logic deassert_we_i, // deassert we, we are stalled or not active
|
||||
input logic data_misaligned_i, // misaligned data load/store in progress
|
||||
|
||||
output logic illegal_insn_o, // illegal instruction encountered
|
||||
output logic trap_insn_o, // trap instruction encountered
|
||||
output logic eret_insn_o, // trap instruction encountered
|
||||
output logic pipe_flush_o, // pipeline flush is requested (e.g. WFI instruction)
|
||||
|
||||
output logic rega_used_o, // register A is used by current instruction
|
||||
output logic regb_used_o, // register B is used by current instruction
|
||||
output logic regc_used_o, // register C is used by current instruction
|
||||
|
||||
|
||||
// from IF/ID pipeline
|
||||
input logic [31:0] instr_rdata_i, // Instruction read from instr memory/cache: (sampled in the if stage)
|
||||
input logic illegal_c_insn_i, // compressed instruction decode failed
|
||||
|
||||
// ALU signals
|
||||
output logic [`ALU_OP_WIDTH-1:0] alu_operator_o, // Operator in the EX stage for the ALU block
|
||||
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 [2:0] immediate_mux_sel_o,
|
||||
|
||||
output logic [1:0] vector_mode_o, // selects between 32 bit, 16 bit and 8 bit vectorial modes
|
||||
output logic scalar_replication_o, // activates scalar_replication for vectorial mode
|
||||
output logic [1:0] alu_cmp_mode_o, // selects comparison mode for ALU (i.e. full, any, all)
|
||||
|
||||
// MUL related control signals
|
||||
output logic mult_en_o, // Perform a multiplication operation
|
||||
output logic [1:0] mult_sel_subword_o, // Select subwords for 16x16 bit of multiplier
|
||||
output logic [1:0] mult_signed_mode_o, // Multiplication in signed mode
|
||||
output logic mult_mac_en_o, // Use the accumulator after multiplication
|
||||
|
||||
// register file related signals
|
||||
output logic regfile_mem_we_o, // Write Enable to regfile
|
||||
output logic regfile_alu_we_o, // Write Enable to regfile 2nd port
|
||||
output logic regfile_alu_waddr_sel_o, // Select register write address for ALU/MUL operations
|
||||
|
||||
// CSR manipulation
|
||||
output logic csr_access_o, // perform an access to CSR
|
||||
output logic [1:0] csr_op_o, // operation to perform on CSR
|
||||
|
||||
// LD/ST unit signals
|
||||
output logic data_req_o, // Request for a transaction to data memory
|
||||
output logic data_we_o, // Write enable to data memory
|
||||
output logic prepost_useincr_o, // When not active bypass the alu result for address calculation = op_a
|
||||
output logic [1:0] data_type_o, // Data type on data memory: byte, half word or word
|
||||
output logic data_sign_extension_o, // Sign extension on read data from data memory
|
||||
output logic [1:0] data_reg_offset_o, // Offset in bytes inside register for stores
|
||||
|
||||
// hwloop signals
|
||||
output logic [2:0] hwloop_we_o, // write enable for hwloop regs
|
||||
output logic hwloop_start_mux_sel_o, // selects hwloop start address input
|
||||
output logic hwloop_end_mux_sel_o, // selects hwloop end address input
|
||||
output logic hwloop_cnt_mux_sel_o, // selects hwloop counter input
|
||||
|
||||
// jump/branches
|
||||
output logic [1:0] jump_in_dec_o, // jump_in_id without deassert
|
||||
output logic [1:0] jump_in_id_o, // jump is being calculated in ALU
|
||||
output logic [1:0] jump_target_mux_sel_o // jump target selection
|
||||
);
|
||||
|
||||
// write enable/request control
|
||||
logic regfile_mem_we;
|
||||
logic regfile_alu_we;
|
||||
logic data_req;
|
||||
logic data_we;
|
||||
logic [2:0] hwloop_we;
|
||||
|
||||
logic trap_insn;
|
||||
logic eret_insn;
|
||||
logic pipe_flush;
|
||||
|
||||
logic [1:0] jump_in_id;
|
||||
|
||||
logic [`ALU_OP_WIDTH-1:0] alu_operator;
|
||||
logic mult_en;
|
||||
logic [1:0] csr_op;
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// ____ _ //
|
||||
// | _ \ ___ ___ ___ __| | ___ _ __ //
|
||||
// | | | |/ _ \/ __/ _ \ / _` |/ _ \ '__| //
|
||||
// | |_| | __/ (_| (_) | (_| | __/ | //
|
||||
// |____/ \___|\___\___/ \__,_|\___|_| //
|
||||
// //
|
||||
/////////////////////////////////////////////
|
||||
|
||||
always_comb
|
||||
begin
|
||||
jump_in_id = `BRANCH_NONE;
|
||||
jump_target_mux_sel_o = `JT_JAL;
|
||||
|
||||
alu_operator = `ALU_NOP;
|
||||
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;
|
||||
|
||||
immediate_mux_sel_o = `IMM_I;
|
||||
|
||||
vector_mode_o = `VEC_MODE32;
|
||||
scalar_replication_o = 1'b0;
|
||||
alu_cmp_mode_o = `ALU_CMP_FULL;
|
||||
|
||||
mult_en = 1'b0;
|
||||
mult_signed_mode_o = 2'b00;
|
||||
mult_sel_subword_o = 2'b00;
|
||||
mult_mac_en_o = 1'b0;
|
||||
|
||||
regfile_mem_we = 1'b0;
|
||||
regfile_alu_we = 1'b0;
|
||||
regfile_alu_waddr_sel_o = 1'b1;
|
||||
|
||||
prepost_useincr_o = 1'b1;
|
||||
|
||||
hwloop_we = 3'b0;
|
||||
hwloop_start_mux_sel_o = 1'b0;
|
||||
hwloop_end_mux_sel_o = 1'b0;
|
||||
hwloop_cnt_mux_sel_o = 1'b0;
|
||||
|
||||
csr_access_o = 1'b0;
|
||||
csr_op = `CSR_OP_NONE;
|
||||
|
||||
data_we = 1'b0;
|
||||
data_type_o = 2'b00;
|
||||
data_sign_extension_o = 1'b0;
|
||||
data_reg_offset_o = 2'b00;
|
||||
data_req = 1'b0;
|
||||
|
||||
illegal_insn_o = 1'b0;
|
||||
trap_insn = 1'b0;
|
||||
eret_insn = 1'b0;
|
||||
pipe_flush = 1'b0;
|
||||
|
||||
rega_used_o = 1'b0;
|
||||
regb_used_o = 1'b0;
|
||||
regc_used_o = 1'b0;
|
||||
|
||||
|
||||
unique case (instr_rdata_i[6:0])
|
||||
|
||||
//////////////////////////////////////
|
||||
// _ _ _ __ __ ____ ____ //
|
||||
// | | | | | \/ | _ \/ ___| //
|
||||
// _ | | | | | |\/| | |_) \___ \ //
|
||||
// | |_| | |_| | | | | __/ ___) | //
|
||||
// \___/ \___/|_| |_|_| |____/ //
|
||||
// //
|
||||
//////////////////////////////////////
|
||||
|
||||
`OPCODE_JAL: begin // Jump and Link
|
||||
jump_target_mux_sel_o = `JT_JAL;
|
||||
jump_in_id = `BRANCH_JAL;
|
||||
// Calculate and store PC+4
|
||||
alu_op_a_mux_sel_o = `OP_A_CURRPC;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_PCINCR;
|
||||
alu_operator = `ALU_ADD;
|
||||
regfile_alu_we = 1'b1;
|
||||
// Calculate jump target (= PC + UJ imm)
|
||||
alu_op_c_mux_sel_o = `OP_C_JT;
|
||||
end
|
||||
|
||||
`OPCODE_JALR: begin // Jump and Link Register
|
||||
jump_target_mux_sel_o = `JT_JALR;
|
||||
jump_in_id = `BRANCH_JALR;
|
||||
// Calculate and store PC+4
|
||||
alu_op_a_mux_sel_o = `OP_A_CURRPC;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_PCINCR;
|
||||
alu_operator = `ALU_ADD;
|
||||
regfile_alu_we = 1'b1;
|
||||
// Calculate jump target (= RS1 + I imm)
|
||||
rega_used_o = 1'b1;
|
||||
alu_op_c_mux_sel_o = `OP_C_JT;
|
||||
|
||||
if (instr_rdata_i[14:12] != 3'b0) begin
|
||||
jump_in_id = `BRANCH_NONE;
|
||||
regfile_alu_we = 1'b0;
|
||||
illegal_insn_o = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
`OPCODE_BRANCH: begin // Branch
|
||||
jump_target_mux_sel_o = `JT_COND;
|
||||
jump_in_id = `BRANCH_COND;
|
||||
alu_op_c_mux_sel_o = `OP_C_JT;
|
||||
rega_used_o = 1'b1;
|
||||
regb_used_o = 1'b1;
|
||||
|
||||
unique case (instr_rdata_i[14:12])
|
||||
3'b000: alu_operator = `ALU_EQ;
|
||||
3'b001: alu_operator = `ALU_NE;
|
||||
3'b100: alu_operator = `ALU_LTS;
|
||||
3'b101: alu_operator = `ALU_GES;
|
||||
3'b110: alu_operator = `ALU_LTU;
|
||||
3'b111: alu_operator = `ALU_GEU;
|
||||
|
||||
default: begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
|
||||
//////////////////////////////////
|
||||
// _ ____ ______ _____ //
|
||||
// | | | _ \ / / ___|_ _| //
|
||||
// | | | | | |/ /\___ \ | | //
|
||||
// | |___| |_| / / ___) || | //
|
||||
// |_____|____/_/ |____/ |_| //
|
||||
// //
|
||||
//////////////////////////////////
|
||||
|
||||
`OPCODE_STORE,
|
||||
`OPCODE_STORE_POST: begin
|
||||
data_req = 1'b1;
|
||||
data_we = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
regb_used_o = 1'b1;
|
||||
alu_operator = `ALU_ADD;
|
||||
|
||||
// post-increment setup
|
||||
if (instr_rdata_i[6:0] == `OPCODE_STORE_POST) begin
|
||||
prepost_useincr_o = 1'b0;
|
||||
regfile_alu_waddr_sel_o = 1'b0;
|
||||
regfile_alu_we = 1'b1;
|
||||
end
|
||||
|
||||
if (instr_rdata_i[14] == 1'b0) begin
|
||||
// offset from immediate
|
||||
immediate_mux_sel_o = `IMM_S;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
end else begin
|
||||
// offset from register
|
||||
regc_used_o = 1'b1;
|
||||
alu_op_b_mux_sel_o = `OP_B_REGC_OR_FWD;
|
||||
end
|
||||
|
||||
// store size
|
||||
unique case (instr_rdata_i[13:12])
|
||||
2'b00: data_type_o = 2'b10; // SB
|
||||
2'b01: data_type_o = 2'b01; // SH
|
||||
2'b10: data_type_o = 2'b00; // SW
|
||||
default: begin
|
||||
data_req = 1'b0;
|
||||
data_we = 1'b0;
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
`OPCODE_LOAD,
|
||||
`OPCODE_LOAD_POST: begin
|
||||
data_req = 1'b1;
|
||||
regfile_mem_we = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
data_type_o = 2'b00;
|
||||
|
||||
// offset from immediate
|
||||
alu_operator = `ALU_ADD;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_I;
|
||||
|
||||
// post-increment setup
|
||||
if (instr_rdata_i[6:0] == `OPCODE_LOAD_POST) begin
|
||||
prepost_useincr_o = 1'b0;
|
||||
regfile_alu_waddr_sel_o = 1'b0;
|
||||
regfile_alu_we = 1'b1;
|
||||
end
|
||||
|
||||
// sign/zero extension
|
||||
data_sign_extension_o = ~instr_rdata_i[14];
|
||||
|
||||
// load size
|
||||
unique case (instr_rdata_i[13:12])
|
||||
2'b00: data_type_o = 2'b10; // LB
|
||||
2'b01: data_type_o = 2'b01; // LH
|
||||
2'b10: data_type_o = 2'b00; // LW
|
||||
default: data_type_o = 2'b00; // illegal or reg-reg
|
||||
endcase
|
||||
|
||||
// reg-reg load (different encoding)
|
||||
if (instr_rdata_i[14:12] == 3'b111) begin
|
||||
// offset from RS2
|
||||
regb_used_o = 1'b1;
|
||||
alu_op_b_mux_sel_o = `OP_B_REGB_OR_FWD;
|
||||
|
||||
// sign/zero extension
|
||||
data_sign_extension_o = ~instr_rdata_i[30];
|
||||
|
||||
// load size
|
||||
unique case (instr_rdata_i[31:25])
|
||||
7'b0000_000,
|
||||
7'b0100_000: data_type_o = 2'b10; // LB, LBU
|
||||
7'b0001_000,
|
||||
7'b0101_000: data_type_o = 2'b01; // LH, LHU
|
||||
7'b0010_000: data_type_o = 2'b00; // LW
|
||||
default: begin
|
||||
data_type_o = 2'b00;
|
||||
// illegal instruction
|
||||
data_req = 1'b0;
|
||||
regfile_mem_we = 1'b0;
|
||||
regfile_alu_we = 1'b0;
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (instr_rdata_i[14:12] == 3'b011 || instr_rdata_i[14:12] == 3'b110)
|
||||
begin
|
||||
// LD, LWU -> RV64 only
|
||||
data_req = 1'b0;
|
||||
regfile_mem_we = 1'b0;
|
||||
regfile_alu_we = 1'b0;
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
//////////////////////////
|
||||
// _ _ _ _ //
|
||||
// / \ | | | | | | //
|
||||
// / _ \ | | | | | | //
|
||||
// / ___ \| |__| |_| | //
|
||||
// /_/ \_\_____\___/ //
|
||||
// //
|
||||
//////////////////////////
|
||||
|
||||
`OPCODE_LUI: begin // Load Upper Immediate
|
||||
alu_op_a_mux_sel_o = `OP_A_ZERO;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_U;
|
||||
alu_operator = `ALU_ADD;
|
||||
regfile_alu_we = 1'b1;
|
||||
end
|
||||
|
||||
`OPCODE_AUIPC: begin // Add Upper Immediate to PC
|
||||
alu_op_a_mux_sel_o = `OP_A_CURRPC;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_U;
|
||||
alu_operator = `ALU_ADD;
|
||||
regfile_alu_we = 1'b1;
|
||||
end
|
||||
|
||||
`OPCODE_OPIMM: begin // Reigster-Immediate ALU Operations
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_I;
|
||||
regfile_alu_we = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
|
||||
unique case (instr_rdata_i[14:12])
|
||||
3'b000: alu_operator = `ALU_ADD; // Add Immediate
|
||||
3'b010: alu_operator = `ALU_SLTS; // Set to one if Lower Than Immediate
|
||||
3'b011: alu_operator = `ALU_SLTU; // Set to one if Lower Than Immediate Unsigned
|
||||
3'b100: alu_operator = `ALU_XOR; // Exclusive Or with Immediate
|
||||
3'b110: alu_operator = `ALU_OR; // Or with Immediate
|
||||
3'b111: alu_operator = `ALU_AND; // And with Immediate
|
||||
|
||||
3'b001: begin
|
||||
alu_operator = `ALU_SLL; // Shift Left Logical by Immediate
|
||||
if (instr_rdata_i[31:25] != 7'b0)
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
||||
3'b101: begin
|
||||
if (instr_rdata_i[31:25] == 7'b0)
|
||||
alu_operator = `ALU_SRL; // Shift Right Logical by Immediate
|
||||
else if (instr_rdata_i[31:25] == 7'b010_0000)
|
||||
alu_operator = `ALU_SRA; // Shift Right Arithmetically by Immediate
|
||||
else
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
||||
default: illegal_insn_o = 1'b1;
|
||||
endcase
|
||||
end
|
||||
|
||||
`OPCODE_OP: begin // Register-Register ALU operation
|
||||
regfile_alu_we = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
regb_used_o = 1'b1;
|
||||
|
||||
unique case ({instr_rdata_i[31:25], instr_rdata_i[14:12]})
|
||||
{7'b000_0000, 3'b000}: alu_operator = `ALU_ADD; // Add
|
||||
{7'b010_0000, 3'b000}: alu_operator = `ALU_SUB; // Sub
|
||||
|
||||
{7'b000_0000, 3'b010}: alu_operator = `ALU_SLTS; // Set Lower Than
|
||||
{7'b000_0000, 3'b011}: alu_operator = `ALU_SLTU; // Set Lower Than Unsigned
|
||||
|
||||
{7'b000_0000, 3'b100}: alu_operator = `ALU_XOR; // Xor
|
||||
{7'b000_0000, 3'b110}: alu_operator = `ALU_OR; // Or
|
||||
{7'b000_0000, 3'b111}: alu_operator = `ALU_AND; // And
|
||||
|
||||
{7'b000_0000, 3'b001}: alu_operator = `ALU_SLL; // Shift Left Logical
|
||||
{7'b000_0000, 3'b101}: alu_operator = `ALU_SRL; // Shift Right Logical
|
||||
{7'b010_0000, 3'b101}: alu_operator = `ALU_SRA; // Shift Right Arithmetic
|
||||
|
||||
{7'b000_0001, 3'b000}: mult_en = 1'b1; // Multiplication
|
||||
|
||||
default: begin
|
||||
regfile_alu_we = 1'b0;
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
/*
|
||||
|
||||
`OPCODE_ALU: begin // Arithmetic Operation
|
||||
rega_used_o = 1'b1;
|
||||
regb_used_o = 1'b1;
|
||||
|
||||
case (instr_rdata_i[9:8])
|
||||
2'b00: begin // ALU Operation
|
||||
regfile_alu_we = 1'b1;
|
||||
|
||||
casex (instr_rdata_i[3:0])
|
||||
4'b110X: begin // l.ext{b,h,w}{s,z}
|
||||
alu_operator = {3'b010, instr_rdata_i[7:6], instr_rdata_i[0]};
|
||||
regb_used_o = 1'b0; // register b is not used
|
||||
end
|
||||
4'b1111: begin // l.ff1
|
||||
alu_operator = `ALU_FF1;
|
||||
end
|
||||
endcase // casex (instr_rdata_i[3:2])
|
||||
end
|
||||
|
||||
2'b01: begin // l.fl1, l.clb, l.cnt
|
||||
regfile_alu_we = 1'b1;
|
||||
regb_used_o = 1'b0;
|
||||
|
||||
case (instr_rdata_i[3:0])
|
||||
4'b1101: alu_operator = `ALU_CNT;
|
||||
4'b1110: alu_operator = `ALU_CLB;
|
||||
4'b1111: alu_operator = `ALU_FL1;
|
||||
|
||||
default: begin
|
||||
// synopsys translate_off
|
||||
$display("%t: Illegal ALU instruction received.", $time);
|
||||
// synopsys translate_on
|
||||
regfile_alu_we = 1'b0; // disable Write Enable for illegal instruction
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase //~case(instr_rdata_i[3:0])
|
||||
end
|
||||
|
||||
2'b10: begin // Min, Max, Abs, Avg
|
||||
regfile_alu_we = 1'b1;
|
||||
|
||||
case (instr_rdata_i[3:0])
|
||||
4'b0000: alu_operator = `ALU_MIN;
|
||||
4'b0001: alu_operator = `ALU_MINU;
|
||||
4'b0010: alu_operator = `ALU_MAX;
|
||||
4'b0011: alu_operator = `ALU_MAXU;
|
||||
4'b0100: alu_operator = `ALU_AVG;
|
||||
4'b0101: alu_operator = `ALU_AVGU;
|
||||
|
||||
4'b1000: begin
|
||||
regb_used_o = 1'b0;
|
||||
alu_operator = `ALU_ABS;
|
||||
end
|
||||
|
||||
default: begin
|
||||
// synopsys translate_off
|
||||
$display("%t: Illegal ALU instruction received.", $time);
|
||||
// synopsys translate_on
|
||||
regfile_alu_we = 1'b0; // disable Write Enable for illegal instruction
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase //~case(instr_rdata_i[3:0])
|
||||
end
|
||||
endcase; // case (instr_rdata_i[9:8])
|
||||
end
|
||||
|
||||
`OPCODE_MAC: begin // MAC instruction
|
||||
mult_is_running = 1'b1;
|
||||
|
||||
rega_used_o = 1'b1;
|
||||
regb_used_o = 1'b1;
|
||||
|
||||
regfile_alu_waddr_sel_o = 2'b01;
|
||||
regfile_alu_we = 1'b1;
|
||||
|
||||
case (instr_rdata_i[6:5])
|
||||
2'b00: begin // MAC
|
||||
case (instr_rdata_i[3:0])
|
||||
4'b1000: begin // l.mac
|
||||
mult_mac_en_o = 1'b1;
|
||||
regc_used_o = 1'b1;
|
||||
set_carry = 1'b1;
|
||||
set_overflow = 1'b1;
|
||||
end
|
||||
|
||||
4'b1001: begin // l.mac.c
|
||||
mult_use_carry_o = 1'b1;
|
||||
mult_mac_en_o = 1'b1;
|
||||
regc_used_o = 1'b1;
|
||||
set_carry = 1'b1;
|
||||
set_overflow = 1'b1;
|
||||
end
|
||||
|
||||
default: begin
|
||||
// synopsys translate_off
|
||||
$display("%t: Illegal MAC instruction received.", $time);
|
||||
// synopsys translate_on
|
||||
regfile_alu_we = 1'b0;
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase // case (instr_rdata_i[3:0])
|
||||
end
|
||||
|
||||
2'b01: begin // MAC with subword selection
|
||||
vector_mode_o = `VEC_MODE216;
|
||||
mult_mac_en_o = 1'b1;
|
||||
regc_used_o = 1'b1;
|
||||
mult_sel_subword_o = instr_rdata_i[2:1];
|
||||
mult_signed_mode_o = instr_rdata_i[4:3];
|
||||
mult_use_carry_o = instr_rdata_i[0];
|
||||
set_carry = 1'b1;
|
||||
set_overflow = 1'b1;
|
||||
end
|
||||
|
||||
2'b11: begin // mult with subword selection
|
||||
vector_mode_o = `VEC_MODE216;
|
||||
mult_sel_subword_o = instr_rdata_i[2:1];
|
||||
mult_signed_mode_o = instr_rdata_i[4:3];
|
||||
end
|
||||
|
||||
default: begin
|
||||
// synopsys translate_off
|
||||
$display("%t: Illegal MAC instruction received.", $time);
|
||||
// synopsys translate_on
|
||||
regfile_alu_we = 1'b0;
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
`OPCODE_VEC: begin // vectorial alu operations
|
||||
rega_used_o = 1'b1;
|
||||
regfile_alu_we = 1'b1;
|
||||
|
||||
if (instr_rdata_i[0] == 1'b0) // choose vector size
|
||||
vector_mode_o = `VEC_MODE16;
|
||||
else
|
||||
vector_mode_o = `VEC_MODE8;
|
||||
|
||||
if ((instr_rdata_i[7:6] == 2'b01) || (instr_rdata_i[7:6] == 2'b10)) // replicate scalar 2 or 4 times
|
||||
scalar_replication_o = 1'b1;
|
||||
|
||||
if (instr_rdata_i[7:6] == 2'b10) // use immediate as operand b
|
||||
begin
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_VEC;
|
||||
end
|
||||
else
|
||||
regb_used_o = 1'b1;
|
||||
|
||||
// now decode the sub opcodes
|
||||
case (instr_rdata_i[5:1])
|
||||
5'b00000: alu_operator = `ALU_ADD;
|
||||
5'b00001: alu_operator = `ALU_SUB;
|
||||
5'b00010: alu_operator = `ALU_AVG;
|
||||
5'b00011: alu_operator = `ALU_MIN;
|
||||
5'b00100: alu_operator = `ALU_MAX;
|
||||
5'b00101: alu_operator = `ALU_SRL;
|
||||
5'b00110: alu_operator = `ALU_SRA;
|
||||
5'b00111: alu_operator = `ALU_SLL;
|
||||
|
||||
5'b01000: begin // lv32.mul
|
||||
regfile_alu_waddr_sel_o = 2'b01;
|
||||
mult_is_running = 1'b1;
|
||||
end
|
||||
|
||||
5'b01001: alu_operator = `ALU_OR;
|
||||
5'b01010: alu_operator = `ALU_XOR;
|
||||
5'b01011: alu_operator = `ALU_AND;
|
||||
|
||||
5'b01100: begin // lv32.ins
|
||||
alu_operator = `ALU_INS;
|
||||
scalar_replication_o = 1'b1;
|
||||
end
|
||||
|
||||
5'b10000: begin // lv32.abs
|
||||
regb_used_o = 1'b0; // abs does not use operand b
|
||||
alu_operator = `ALU_ABS;
|
||||
end
|
||||
|
||||
5'b10001: begin // lv32.ext
|
||||
regb_used_o = 1'b0;
|
||||
alu_operator = `ALU_EXT;
|
||||
end
|
||||
|
||||
default: begin // unknown instruction encountered
|
||||
regfile_alu_we = 1'b0;
|
||||
illegal_insn_o = 1'b1;
|
||||
// synopsys translate_off
|
||||
$display("%t: Unknown vector opcode 0x%h.", $time, instr_rdata_i[5:1]);
|
||||
// synopsys translate_on
|
||||
end
|
||||
endcase // instr_rdata[5:1]
|
||||
end
|
||||
|
||||
`OPCODE_VCMP: begin // Vectorial comparisons, i.e. lv32.cmp_*, lv32.all_*, lv32.any_*
|
||||
rega_used_o = 1'b1;
|
||||
regfile_alu_we = 1'b1;
|
||||
|
||||
if (instr_rdata_i[0] == 1'b0) // choose vector size
|
||||
vector_mode_o = `VEC_MODE16;
|
||||
else
|
||||
vector_mode_o = `VEC_MODE8;
|
||||
|
||||
if ((instr_rdata_i[7:6] == 2'b01) || (instr_rdata_i[7:6] == 2'b10)) // replicate scalar 2 or 4 times
|
||||
scalar_replication_o = 1'b1;
|
||||
|
||||
if (instr_rdata_i[7:6] == 2'b10) // use immediate as operand b
|
||||
begin
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_VEC;
|
||||
end
|
||||
else
|
||||
regb_used_o = 1'b1;
|
||||
|
||||
// now decode the sub opcodes for the ALU
|
||||
case (instr_rdata_i[3:1])
|
||||
3'b000: alu_operator = `ALU_EQ;
|
||||
3'b001: alu_operator = `ALU_NE;
|
||||
3'b010: alu_operator = `ALU_GTS;
|
||||
3'b011: alu_operator = `ALU_GES;
|
||||
3'b100: alu_operator = `ALU_LTS;
|
||||
3'b101: alu_operator = `ALU_LES;
|
||||
|
||||
default: begin // unknown instruction encountered
|
||||
illegal_insn_o = 1'b1;
|
||||
// synopsys translate_off
|
||||
$display("%t: Unknown vector opcode 0x%h.", $time, instr_rdata_i[5:1]);
|
||||
// synopsys translate_on
|
||||
end
|
||||
endcase //~case(instr_rdata_i[3:1])
|
||||
|
||||
alu_cmp_mode_o = instr_rdata_i[5:4]; // which kind of comparison do we have here, i.e. full, any, all
|
||||
|
||||
if((instr_rdata_i[5:4] == `ALU_CMP_ANY) || (instr_rdata_i[5:4] == `ALU_CMP_ALL))
|
||||
set_flag = 1'b1; // set the flag for lv32.all_* and lv32.any_*
|
||||
end
|
||||
|
||||
*/
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// ____ ____ _____ ____ ___ _ _ //
|
||||
// / ___|| _ \| ____/ ___|_ _| / \ | | //
|
||||
// \___ \| |_) | _|| | | | / _ \ | | //
|
||||
// ___) | __/| |__| |___ | | / ___ \| |___ //
|
||||
// |____/|_| |_____\____|___/_/ \_\_____| //
|
||||
// //
|
||||
////////////////////////////////////////////////
|
||||
|
||||
`OPCODE_SYSTEM: begin
|
||||
if (instr_rdata_i[14:12] == 3'b000)
|
||||
begin
|
||||
// non CSR related SYSTEM instructions
|
||||
unique case (instr_rdata_i[31:0])
|
||||
32'h00_00_00_73: // ECALL
|
||||
begin
|
||||
// environment (system) call
|
||||
// TODO: Handle in controller
|
||||
end
|
||||
|
||||
32'h00_10_00_73: // EBREAK
|
||||
begin
|
||||
// debugger trap
|
||||
trap_insn = 1'b1;
|
||||
end
|
||||
|
||||
32'h10_00_00_73: // ERET
|
||||
begin
|
||||
eret_insn = 1'b1;
|
||||
end
|
||||
|
||||
32'h10_20_00_73: // WFI
|
||||
begin
|
||||
// flush pipeline
|
||||
pipe_flush = 1'b1;
|
||||
end
|
||||
|
||||
default:
|
||||
begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
else
|
||||
begin
|
||||
// instruction to read/modify CSR
|
||||
csr_access_o = 1'b1;
|
||||
regfile_alu_we = 1'b1;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_I; // CSR address is encoded in I imm
|
||||
|
||||
if (instr_rdata_i[14] == 1'b1) begin
|
||||
// rs1 field is used as immediate
|
||||
alu_op_a_mux_sel_o = `OP_A_ZIMM;
|
||||
end else begin
|
||||
rega_used_o = 1'b1;
|
||||
alu_op_a_mux_sel_o = `OP_A_REGA_OR_FWD;
|
||||
end
|
||||
|
||||
unique case (instr_rdata_i[13:12])
|
||||
2'b01: csr_op = `CSR_OP_WRITE;
|
||||
2'b10: csr_op = `CSR_OP_SET;
|
||||
2'b11: csr_op = `CSR_OP_CLEAR;
|
||||
default: illegal_insn_o = 1'b1;
|
||||
endcase
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// _ ___ ___ ___ ___ ____ //
|
||||
// | | | \ \ / / | / _ \ / _ \| _ \ //
|
||||
// | |_| |\ \ /\ / /| | | | | | | | | |_) | //
|
||||
// | _ | \ V V / | |__| |_| | |_| | __/ //
|
||||
// |_| |_| \_/\_/ |_____\___/ \___/|_| //
|
||||
// //
|
||||
///////////////////////////////////////////////
|
||||
|
||||
`OPCODE_HWLOOP: begin
|
||||
jump_target_mux_sel_o = `JT_HWLP; // get PC + I imm from jump target adder
|
||||
|
||||
unique case (instr_rdata_i[14:12])
|
||||
3'b000: begin
|
||||
// lp.starti: set start address to PC + I-type immediate
|
||||
hwloop_we[0] = 1'b1;
|
||||
hwloop_start_mux_sel_o = 1'b0;
|
||||
// $display("%t: hwloop start address: %h", $time, instr_rdata_i);
|
||||
end
|
||||
3'b001: begin
|
||||
// lp.endi: set end address to PC + I-type immediate
|
||||
hwloop_we[1] = 1'b1;
|
||||
hwloop_end_mux_sel_o = 1'b0; // jump target
|
||||
// $display("%t: hwloop end address: %h", $time, instr_rdata_i);
|
||||
end
|
||||
3'b010: begin
|
||||
// lp.count initialize counter from rs1
|
||||
hwloop_we[2] = 1'b1;
|
||||
hwloop_cnt_mux_sel_o = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
// $display("%t: hwloop counter: %h", $time, instr_rdata_i);
|
||||
end
|
||||
3'b011: begin
|
||||
// lp.counti initialize counter from I-type immediate
|
||||
hwloop_we[2] = 1'b1;
|
||||
hwloop_cnt_mux_sel_o = 1'b0;
|
||||
// $display("%t: hwloop counter imm: %h", $time, instr_rdata_i);
|
||||
end
|
||||
3'b100: begin
|
||||
// lp.setup: initialize counter from rs1, set start address to
|
||||
// next instruction and end address to PC + I-type immediate
|
||||
hwloop_we = 3'b111;
|
||||
hwloop_start_mux_sel_o = 1'b1;
|
||||
hwloop_end_mux_sel_o = 1'b0;
|
||||
hwloop_cnt_mux_sel_o = 1'b1;
|
||||
rega_used_o = 1'b1;
|
||||
// $display("%t: hwloop setup: %h", $time, instr_rdata_i);
|
||||
end
|
||||
3'b101: begin
|
||||
// lp.setupi: initialize counter from I-type immediate, set start
|
||||
// address to next instruction and end address to PC + shifted
|
||||
// z-type immediate
|
||||
hwloop_we = 3'b111;
|
||||
hwloop_start_mux_sel_o = 1'b1;
|
||||
hwloop_end_mux_sel_o = 1'b1;
|
||||
hwloop_cnt_mux_sel_o = 1'b0;
|
||||
illegal_insn_o = 1'b1; // TODO: PC + z-imm currently not supported
|
||||
// $display("%t: hwloop setup imm: %h", $time, instr_rdata_i);
|
||||
end
|
||||
default: begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
default: begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
endcase
|
||||
|
||||
// make sure invalid compressed instruction causes an exception
|
||||
if (illegal_c_insn_i) begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
||||
// misaligned access was detected by the LSU
|
||||
// TODO: this section should eventually be moved out of the decoder
|
||||
if (data_misaligned_i == 1'b1)
|
||||
begin
|
||||
// only part of the pipeline is unstalled, make sure that the
|
||||
// correct operands are sent to the AGU
|
||||
alu_op_a_mux_sel_o = `OP_A_REGA_OR_FWD;
|
||||
alu_op_b_mux_sel_o = `OP_B_IMM;
|
||||
immediate_mux_sel_o = `IMM_PCINCR;
|
||||
|
||||
// if prepost increments are used, we do not write back the
|
||||
// second address since the first calculated address was
|
||||
// the correct one
|
||||
regfile_alu_we = 1'b0;
|
||||
|
||||
// if post increments are used, we must make sure that for
|
||||
// the second memory access we do use the adder
|
||||
prepost_useincr_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// deassert we signals (in case of stalls)
|
||||
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;
|
||||
assign csr_op_o = (deassert_we_i) ? `CSR_OP_NONE : csr_op;
|
||||
assign jump_in_id_o = (deassert_we_i) ? `BRANCH_NONE : jump_in_id;
|
||||
assign trap_insn_o = (deassert_we_i) ? 1'b0 : trap_insn;
|
||||
assign eret_insn_o = (deassert_we_i) ? 1'b0 : eret_insn; // TODO: do not deassert?
|
||||
assign pipe_flush_o = (deassert_we_i) ? 1'b0 : pipe_flush; // TODO: do not deassert?
|
||||
|
||||
assign jump_in_dec_o = jump_in_id;
|
||||
|
||||
endmodule // controller
|
298
id_stage.sv
298
id_stage.sv
|
@ -45,7 +45,6 @@ module id_stage
|
|||
// Interface to instruction memory
|
||||
input logic [31:0] instr_rdata_i, // comes from pipeline of IF stage
|
||||
output logic instr_req_o,
|
||||
input logic instr_gnt_i,
|
||||
input logic instr_ack_i,
|
||||
|
||||
// Jumps and branches
|
||||
|
@ -72,20 +71,10 @@ module id_stage
|
|||
output logic stall_wb_o,
|
||||
|
||||
// To the Pipeline ID/EX
|
||||
output logic [31:0] regfile_rb_data_ex_o,
|
||||
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 [`ALU_OP_WIDTH-1:0] alu_operator_ex_o,
|
||||
|
||||
output logic [1:0] vector_mode_ex_o,
|
||||
output logic [1:0] alu_cmp_mode_ex_o,
|
||||
output logic [1:0] alu_vec_ext_ex_o,
|
||||
|
||||
output logic mult_en_ex_o,
|
||||
output logic [1:0] mult_sel_subword_ex_o,
|
||||
output logic [1:0] mult_signed_mode_ex_o,
|
||||
output logic mult_mac_en_ex_o,
|
||||
output logic [31:0] regfile_rb_data_ex_o,
|
||||
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 [4:0] regfile_waddr_ex_o,
|
||||
output logic regfile_we_ex_o,
|
||||
|
@ -93,22 +82,37 @@ module id_stage
|
|||
output logic [4:0] regfile_alu_waddr_ex_o,
|
||||
output logic regfile_alu_we_ex_o,
|
||||
|
||||
output logic prepost_useincr_ex_o,
|
||||
input logic data_misaligned_i,
|
||||
// ALU
|
||||
output logic [`ALU_OP_WIDTH-1:0] alu_operator_ex_o,
|
||||
|
||||
output logic [31:0] hwloop_targ_addr_o,
|
||||
output logic hwloop_jump_o,
|
||||
output logic [1:0] vector_mode_ex_o,
|
||||
output logic [1:0] alu_cmp_mode_ex_o,
|
||||
output logic [1:0] alu_vec_ext_ex_o,
|
||||
|
||||
// MUL
|
||||
output logic mult_en_ex_o,
|
||||
output logic [1:0] mult_sel_subword_ex_o,
|
||||
output logic [1:0] mult_signed_mode_ex_o,
|
||||
output logic mult_mac_en_ex_o,
|
||||
|
||||
// CSR ID/EX
|
||||
output logic csr_access_ex_o,
|
||||
output logic [1:0] csr_op_ex_o,
|
||||
|
||||
// hwloop signals
|
||||
output logic [31:0] hwloop_targ_addr_o,
|
||||
output logic hwloop_jump_o,
|
||||
|
||||
// Interface to load store unit
|
||||
output logic data_req_ex_o,
|
||||
output logic data_we_ex_o,
|
||||
output logic [1:0] data_type_ex_o,
|
||||
output logic data_sign_ext_ex_o,
|
||||
output logic [1:0] data_reg_offset_ex_o,
|
||||
output logic data_misaligned_ex_o,
|
||||
output logic data_req_ex_o,
|
||||
|
||||
output logic prepost_useincr_ex_o,
|
||||
input logic data_misaligned_i,
|
||||
|
||||
input logic lsu_ready_ex_i,
|
||||
input logic lsu_ready_wb_i,
|
||||
|
@ -149,10 +153,23 @@ module id_stage
|
|||
output logic perf_ld_stall_o // load-use-hazard
|
||||
);
|
||||
|
||||
|
||||
// Compressed instruction decoding
|
||||
logic [31:0] instr;
|
||||
|
||||
// Decoder/Controller ID stage internal signals
|
||||
logic deassert_we;
|
||||
|
||||
logic illegal_insn_dec;
|
||||
logic trap_insn;
|
||||
logic eret_insn_dec;
|
||||
logic pipe_flush_dec;
|
||||
|
||||
logic rega_used_dec;
|
||||
logic regb_used_dec;
|
||||
logic regc_used_dec;
|
||||
|
||||
logic [1:0] jump_in_dec;
|
||||
|
||||
|
||||
// Immediate decoding and sign extension
|
||||
logic [31:0] imm_i_type;
|
||||
logic [31:0] imm_s_type;
|
||||
|
@ -166,14 +183,11 @@ module id_stage
|
|||
logic [31:0] jump_target; // calculated jump target (-> EX -> IF)
|
||||
|
||||
logic exc_pc_sel;
|
||||
logic [2:0] pc_mux_sel_int; // selects next PC in if stage
|
||||
|
||||
logic irq_present;
|
||||
|
||||
// Signals running between controller and exception controller
|
||||
logic illegal_insn;
|
||||
logic illegal_c_insn;
|
||||
logic trap_insn;
|
||||
logic trap_hit;
|
||||
logic pc_valid;
|
||||
logic clear_isr_running;
|
||||
|
@ -264,9 +278,6 @@ module id_stage
|
|||
logic [31:0] operand_c;
|
||||
|
||||
|
||||
assign pc_mux_sel_o = pc_mux_sel_int;
|
||||
|
||||
|
||||
assign instr = instr_rdata_i;
|
||||
|
||||
// immediate extraction and sign extension
|
||||
|
@ -510,6 +521,83 @@ module id_stage
|
|||
|
||||
assign dbg_reg_rdata_o = regfile_data_rc_id;
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// ____ _____ ____ ___ ____ _____ ____ //
|
||||
// | _ \| ____/ ___/ _ \| _ \| ____| _ \ //
|
||||
// | | | | _|| | | | | | | | | _| | |_) | //
|
||||
// | |_| | |__| |__| |_| | |_| | |___| _ < //
|
||||
// |____/|_____\____\___/|____/|_____|_| \_\ //
|
||||
// //
|
||||
///////////////////////////////////////////////
|
||||
|
||||
decoder decoder_i
|
||||
(
|
||||
// controller related signals
|
||||
.deassert_we_i ( deassert_we ),
|
||||
.data_misaligned_i ( data_misaligned_i ),
|
||||
|
||||
.illegal_insn_o ( illegal_insn_dec ),
|
||||
.trap_insn_o ( trap_insn ),
|
||||
.eret_insn_o ( eret_insn_dec ),
|
||||
.pipe_flush_o ( pipe_flush_dec ),
|
||||
|
||||
.rega_used_o ( rega_used_dec ),
|
||||
.regb_used_o ( regb_used_dec ),
|
||||
.regc_used_o ( regc_used_dec ),
|
||||
|
||||
|
||||
// from IF/ID pipeline
|
||||
.instr_rdata_i ( instr ),
|
||||
.illegal_c_insn_i ( illegal_c_insn_i ),
|
||||
|
||||
// ALU signals
|
||||
.alu_operator_o ( alu_operator ),
|
||||
.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 ),
|
||||
.immediate_mux_sel_o ( immediate_mux_sel ),
|
||||
|
||||
.vector_mode_o ( vector_mode ),
|
||||
.scalar_replication_o ( scalar_replication ),
|
||||
.alu_cmp_mode_o ( alu_cmp_mode ),
|
||||
|
||||
// MUL signals
|
||||
.mult_en_o ( mult_en ),
|
||||
.mult_sel_subword_o ( mult_sel_subword ),
|
||||
.mult_signed_mode_o ( mult_signed_mode ),
|
||||
.mult_mac_en_o ( mult_mac_en ),
|
||||
|
||||
// Register file control signals
|
||||
.regfile_mem_we_o ( regfile_we_id ),
|
||||
.regfile_alu_we_o ( regfile_alu_we_id ),
|
||||
.regfile_alu_waddr_sel_o ( regfile_alu_waddr_mux_sel ),
|
||||
|
||||
// CSR control signals
|
||||
.csr_access_o ( csr_access ),
|
||||
.csr_op_o ( csr_op ),
|
||||
|
||||
// Data bus interface
|
||||
.data_req_o ( data_req_id ),
|
||||
.data_we_o ( data_we_id ),
|
||||
.prepost_useincr_o ( prepost_useincr ),
|
||||
.data_type_o ( data_type_id ),
|
||||
.data_sign_extension_o ( data_sign_ext_id ),
|
||||
.data_reg_offset_o ( data_reg_offset_id ),
|
||||
|
||||
// hwloop signals
|
||||
.hwloop_we_o ( hwloop_we ),
|
||||
.hwloop_start_mux_sel_o ( hwloop_start_mux_sel ),
|
||||
.hwloop_end_mux_sel_o ( hwloop_end_mux_sel ),
|
||||
.hwloop_cnt_mux_sel_o ( hwloop_cnt_mux_sel ),
|
||||
|
||||
// jump/branches
|
||||
.jump_in_dec_o ( jump_in_dec ),
|
||||
.jump_in_id_o ( jump_in_id_o ),
|
||||
.jump_target_mux_sel_o ( jump_target_mux_sel )
|
||||
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// ____ ___ _ _ _____ ____ ___ _ _ _____ ____ //
|
||||
// / ___/ _ \| \ | |_ _| _ \ / _ \| | | | | ____| _ \ //
|
||||
|
@ -520,122 +608,94 @@ module id_stage
|
|||
////////////////////////////////////////////////////////////////////
|
||||
controller controller_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.fetch_enable_i ( fetch_enable_i ),
|
||||
.core_busy_o ( core_busy_o ),
|
||||
.is_decoding_o ( is_decoding_o ),
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
|
||||
// Signal from-to PC pipe (instr rdata) and instr mem system (req and ack)
|
||||
.instr_rdata_i ( instr ),
|
||||
.instr_req_o ( instr_req_o ),
|
||||
.instr_gnt_i ( instr_gnt_i ),
|
||||
.instr_ack_i ( instr_ack_i ),
|
||||
.fetch_enable_i ( fetch_enable_i ),
|
||||
.core_busy_o ( core_busy_o ),
|
||||
.is_decoding_o ( is_decoding_o ),
|
||||
|
||||
.pc_set_o ( pc_set_o ),
|
||||
.pc_mux_sel_o ( pc_mux_sel_int ),
|
||||
// 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 ),
|
||||
|
||||
// Alu signals
|
||||
.alu_operator_o ( alu_operator ),
|
||||
.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 ),
|
||||
.immediate_mux_sel_o ( immediate_mux_sel ),
|
||||
.rega_used_i ( rega_used_dec ),
|
||||
.regb_used_i ( regb_used_dec ),
|
||||
.regc_used_i ( regc_used_dec ),
|
||||
|
||||
.scalar_replication_o ( scalar_replication ),
|
||||
.vector_mode_o ( vector_mode ),
|
||||
.alu_cmp_mode_o ( alu_cmp_mode ),
|
||||
// from IF/ID pipeline
|
||||
.instr_rdata_i ( instr ),
|
||||
|
||||
// mult signals
|
||||
.mult_en_o ( mult_en ),
|
||||
.mult_sel_subword_o ( mult_sel_subword ),
|
||||
.mult_signed_mode_o ( mult_signed_mode ),
|
||||
.mult_mac_en_o ( mult_mac_en ),
|
||||
// from prefetcher
|
||||
.instr_req_o ( instr_req_o ),
|
||||
.instr_ack_i ( instr_ack_i ),
|
||||
|
||||
// Register file control signals
|
||||
.regfile_we_o ( regfile_we_id ),
|
||||
// to prefetcher
|
||||
.pc_set_o ( pc_set_o ),
|
||||
.pc_mux_sel_o ( pc_mux_sel_o ),
|
||||
|
||||
.regfile_alu_we_o ( regfile_alu_we_id ),
|
||||
.regfile_alu_waddr_mux_sel_o ( regfile_alu_waddr_mux_sel ),
|
||||
// LSU
|
||||
.data_req_ex_i ( data_req_ex_o ),
|
||||
.data_misaligned_i ( data_misaligned_i ),
|
||||
|
||||
.prepost_useincr_o ( prepost_useincr ),
|
||||
.data_misaligned_i ( data_misaligned_i ),
|
||||
|
||||
// CSR control signals
|
||||
.csr_access_o ( csr_access ),
|
||||
.csr_op_o ( csr_op ),
|
||||
|
||||
// Data bus interface
|
||||
.data_we_o ( data_we_id ),
|
||||
.data_type_o ( data_type_id ),
|
||||
.data_sign_extension_o ( data_sign_ext_id ),
|
||||
.data_reg_offset_o ( data_reg_offset_id ),
|
||||
.data_req_o ( data_req_id ),
|
||||
.data_req_ex_i ( data_req_ex_o ),
|
||||
|
||||
.lsu_ready_ex_i ( lsu_ready_ex_i ),
|
||||
.lsu_ready_wb_i ( lsu_ready_wb_i ),
|
||||
.lsu_ready_ex_i ( lsu_ready_ex_i ),
|
||||
.lsu_ready_wb_i ( lsu_ready_wb_i ),
|
||||
|
||||
// hwloop signals
|
||||
.hwloop_we_o ( hwloop_we ),
|
||||
.hwloop_start_mux_sel_o ( hwloop_start_mux_sel ),
|
||||
.hwloop_end_mux_sel_o ( hwloop_end_mux_sel ),
|
||||
.hwloop_cnt_mux_sel_o ( hwloop_cnt_mux_sel ),
|
||||
.hwloop_jump_i ( hwloop_jump ),
|
||||
.hwloop_jump_i ( hwloop_jump ),
|
||||
|
||||
// jump/branch control
|
||||
.jump_in_dec_i ( jump_in_dec ),
|
||||
.jump_in_id_i ( jump_in_id_o ),
|
||||
.jump_in_ex_i ( jump_in_ex_o ),
|
||||
|
||||
.branch_decision_i ( branch_decision_i ),
|
||||
|
||||
// Interrupt signals
|
||||
.irq_present_i ( irq_present ),
|
||||
.irq_present_i ( irq_present ),
|
||||
|
||||
// Exception Controller Signals
|
||||
.exc_pc_sel_i ( exc_pc_sel ),
|
||||
.illegal_c_insn_i ( illegal_c_insn_i ),
|
||||
.illegal_insn_o ( illegal_insn ),
|
||||
.trap_insn_o ( trap_insn ),
|
||||
.pc_valid_i ( pc_valid ),
|
||||
.clear_isr_running_o ( clear_isr_running ),
|
||||
.trap_hit_i ( trap_hit ),
|
||||
.exc_pipe_flush_i ( exc_pipe_flush ),
|
||||
.exc_pc_sel_i ( exc_pc_sel ),
|
||||
.pc_valid_i ( pc_valid ),
|
||||
.exc_pipe_flush_i ( exc_pipe_flush ),
|
||||
.trap_hit_i ( trap_hit ),
|
||||
.illegal_insn_o ( illegal_insn ),
|
||||
.clear_isr_running_o ( clear_isr_running ),
|
||||
|
||||
// Debug Unit Signals
|
||||
.dbg_stall_i ( dbg_stall_i ),
|
||||
.dbg_set_npc_i ( dbg_set_npc_i ),
|
||||
.dbg_trap_o ( dbg_trap_o ),
|
||||
.dbg_stall_i ( dbg_stall_i ),
|
||||
.dbg_set_npc_i ( dbg_set_npc_i ),
|
||||
.dbg_trap_o ( dbg_trap_o ),
|
||||
|
||||
// regfile port 1
|
||||
.regfile_waddr_ex_i ( regfile_waddr_ex_o ), // Write address for register file from ex-wb- pipeline registers
|
||||
.regfile_we_ex_i ( regfile_we_ex_o ),
|
||||
.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 ),
|
||||
// Forwarding signals from regfile
|
||||
.regfile_waddr_ex_i ( regfile_waddr_ex_o ), // Write address for register file from ex-wb- pipeline registers
|
||||
.regfile_we_ex_i ( regfile_we_ex_o ),
|
||||
.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_alu_waddr_fw_i ( regfile_alu_waddr_fw_i ),
|
||||
.regfile_alu_we_fw_i ( regfile_alu_we_fw_i ),
|
||||
.regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw_i ),
|
||||
.regfile_alu_we_fw_i ( regfile_alu_we_fw_i ),
|
||||
|
||||
// Forwarding signals
|
||||
.operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ),
|
||||
.operand_b_fw_mux_sel_o ( operand_b_fw_mux_sel ),
|
||||
.operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ),
|
||||
|
||||
// To controller (TODO: Remove when control/decode separated and moved)
|
||||
.jump_target_mux_sel_o ( jump_target_mux_sel ),
|
||||
.jump_in_ex_i ( jump_in_ex_o ),
|
||||
|
||||
.branch_decision_i ( branch_decision_i ),
|
||||
|
||||
// To exception controller and EX: Jump/Branch indication
|
||||
.jump_in_id_o ( jump_in_id_o ),
|
||||
.operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ),
|
||||
.operand_b_fw_mux_sel_o ( operand_b_fw_mux_sel ),
|
||||
.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 ),
|
||||
.stall_if_o ( stall_if_o ),
|
||||
.stall_id_o ( stall_id_o ),
|
||||
.stall_ex_o ( stall_ex_o ),
|
||||
.stall_wb_o ( stall_wb_o ),
|
||||
|
||||
// Performance Counters
|
||||
.perf_jump_o ( perf_jump_o ),
|
||||
.perf_branch_o ( perf_branch_o ),
|
||||
.perf_jr_stall_o ( perf_jr_stall_o ),
|
||||
.perf_ld_stall_o ( perf_ld_stall_o )
|
||||
.perf_jump_o ( perf_jump_o ),
|
||||
.perf_branch_o ( perf_branch_o ),
|
||||
.perf_jr_stall_o ( perf_jr_stall_o ),
|
||||
.perf_ld_stall_o ( perf_ld_stall_o )
|
||||
|
||||
);
|
||||
|
||||
|
|
|
@ -43,21 +43,21 @@ module riscv_core
|
|||
input logic [4:0] cluster_id_i,
|
||||
|
||||
// Instruction memory interface
|
||||
output logic [31:0] instr_addr_o,
|
||||
output logic instr_req_o,
|
||||
input logic [31:0] instr_rdata_i,
|
||||
input logic instr_grant_i,
|
||||
input logic instr_grant_i, // TODO: rename to instr_gnt_i
|
||||
input logic instr_rvalid_i,
|
||||
output logic [31:0] instr_addr_o,
|
||||
input logic [31:0] instr_rdata_i,
|
||||
|
||||
// Data memory interface
|
||||
output logic data_req_o,
|
||||
input logic data_gnt_i,
|
||||
input logic data_r_valid_i, // TODO: rename to data_rvalid_i
|
||||
output logic data_we_o,
|
||||
output logic [3:0] data_be_o,
|
||||
output logic [31:0] data_addr_o,
|
||||
output logic [31:0] data_wdata_o,
|
||||
output logic data_we_o,
|
||||
output logic data_req_o,
|
||||
output logic [3:0] data_be_o,
|
||||
input logic [31:0] data_rdata_i,
|
||||
input logic data_gnt_i,
|
||||
input logic data_r_valid_i,
|
||||
|
||||
// Interrupt inputs
|
||||
input logic irq_i, // level-triggered IR line
|
||||
|
@ -291,33 +291,31 @@ module riscv_core
|
|||
|
||||
// Processor Enable
|
||||
.fetch_enable_i ( fetch_enable_i ),
|
||||
|
||||
.jump_in_id_o ( jump_in_id ),
|
||||
.jump_in_ex_o ( jump_in_ex ),
|
||||
.branch_decision_i ( branch_decision ),
|
||||
|
||||
.jump_target_o ( jump_target_id ),
|
||||
|
||||
.core_busy_o ( core_busy ),
|
||||
.is_decoding_o ( is_decoding ),
|
||||
|
||||
// Interface to instruction memory
|
||||
.instr_rdata_i ( instr_rdata_id ),
|
||||
.instr_req_o ( instr_req_int ),
|
||||
.instr_gnt_i ( instr_grant_i ),
|
||||
.instr_ack_i ( instr_ack_int ),
|
||||
|
||||
// Jumps and branches
|
||||
.jump_in_id_o ( jump_in_id ),
|
||||
.jump_in_ex_o ( jump_in_ex ),
|
||||
.branch_decision_i ( branch_decision ),
|
||||
.jump_target_o ( jump_target_id ),
|
||||
|
||||
.pc_set_o ( pc_set ),
|
||||
.pc_mux_sel_o ( pc_mux_sel_id ),
|
||||
.exc_pc_mux_o ( exc_pc_mux_id ),
|
||||
|
||||
.is_compressed_i ( is_compressed_id ),
|
||||
.illegal_c_insn_i ( illegal_c_insn_id ),
|
||||
.is_compressed_i ( is_compressed_id ),
|
||||
|
||||
.current_pc_if_i ( current_pc_if ),
|
||||
.current_pc_id_i ( current_pc_id ),
|
||||
|
||||
// STALLS
|
||||
// Stalls
|
||||
.stall_if_o ( stall_if ),
|
||||
.stall_id_o ( stall_id ),
|
||||
.stall_ex_o ( stall_ex ),
|
||||
|
@ -325,20 +323,9 @@ module riscv_core
|
|||
|
||||
// From the Pipeline ID/EX
|
||||
.regfile_rb_data_ex_o ( regfile_rb_data_ex ),
|
||||
|
||||
.alu_operand_a_ex_o ( alu_operand_a_ex ),
|
||||
.alu_operand_b_ex_o ( alu_operand_b_ex ),
|
||||
.alu_operand_c_ex_o ( alu_operand_c_ex ),
|
||||
.alu_operator_ex_o ( alu_operator_ex ),
|
||||
|
||||
.vector_mode_ex_o ( vector_mode_ex ), // from ID to EX stage
|
||||
.alu_cmp_mode_ex_o ( alu_cmp_mode_ex ), // from ID to EX stage
|
||||
.alu_vec_ext_ex_o ( alu_vec_ext_ex ), // from ID to EX stage
|
||||
|
||||
.mult_en_ex_o ( mult_en_ex ), // from ID to EX stage
|
||||
.mult_sel_subword_ex_o ( mult_sel_subword_ex ), // from ID to EX stage
|
||||
.mult_signed_mode_ex_o ( mult_signed_mode_ex ), // from ID to EX stage
|
||||
.mult_mac_en_ex_o ( mult_mac_en_ex ), // from ID to EX stage
|
||||
|
||||
.regfile_waddr_ex_o ( regfile_waddr_ex ),
|
||||
.regfile_we_ex_o ( regfile_we_ex ),
|
||||
|
@ -346,6 +333,19 @@ module riscv_core
|
|||
.regfile_alu_we_ex_o ( regfile_alu_we_ex ),
|
||||
.regfile_alu_waddr_ex_o ( regfile_alu_waddr_ex ),
|
||||
|
||||
// ALU
|
||||
.alu_operator_ex_o ( alu_operator_ex ),
|
||||
|
||||
.vector_mode_ex_o ( vector_mode_ex ), // from ID to EX stage
|
||||
.alu_cmp_mode_ex_o ( alu_cmp_mode_ex ), // from ID to EX stage
|
||||
.alu_vec_ext_ex_o ( alu_vec_ext_ex ), // from ID to EX stage
|
||||
|
||||
// MUL
|
||||
.mult_en_ex_o ( mult_en_ex ), // from ID to EX stage
|
||||
.mult_sel_subword_ex_o ( mult_sel_subword_ex ), // from ID to EX stage
|
||||
.mult_signed_mode_ex_o ( mult_signed_mode_ex ), // from ID to EX stage
|
||||
.mult_mac_en_ex_o ( mult_mac_en_ex ), // from ID to EX stage
|
||||
|
||||
// CSR ID/EX
|
||||
.csr_access_ex_o ( csr_access_ex ),
|
||||
.csr_op_ex_o ( csr_op_ex ),
|
||||
|
@ -354,16 +354,17 @@ module riscv_core
|
|||
.hwloop_jump_o ( hwloop_jump ),
|
||||
.hwloop_targ_addr_o ( hwloop_target ),
|
||||
|
||||
.prepost_useincr_ex_o ( useincr_addr_ex ),
|
||||
.data_misaligned_i ( data_misaligned ),
|
||||
|
||||
// LSU
|
||||
.data_req_ex_o ( data_req_ex ), // to load store unit
|
||||
.data_we_ex_o ( data_we_ex ), // to load store unit
|
||||
.data_type_ex_o ( data_type_ex ), // to load store unit
|
||||
.data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit
|
||||
.data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit
|
||||
.data_req_ex_o ( data_req_ex ), // to load store unit
|
||||
.data_misaligned_ex_o ( data_misaligned_ex ), // to load store unit
|
||||
|
||||
.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 ),
|
||||
|
||||
|
@ -388,14 +389,15 @@ module riscv_core
|
|||
.dbg_set_npc_i ( dbg_set_npc ),
|
||||
|
||||
// Forward Signals
|
||||
.regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw ),
|
||||
.regfile_alu_we_fw_i ( regfile_alu_we_fw ),
|
||||
.regfile_alu_wdata_fw_i ( regfile_alu_wdata_fw ),
|
||||
|
||||
.regfile_waddr_wb_i ( regfile_waddr_fw_wb_o), // Write address ex-wb pipeline
|
||||
.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
|
||||
|
||||
.regfile_alu_waddr_fw_i ( regfile_alu_waddr_fw ),
|
||||
.regfile_alu_we_fw_i ( regfile_alu_we_fw ),
|
||||
.regfile_alu_wdata_fw_i ( regfile_alu_wdata_fw ),
|
||||
|
||||
// Performance Counters
|
||||
.perf_jump_o ( perf_jump ),
|
||||
.perf_branch_o ( perf_branch ),
|
||||
.perf_jr_stall_o ( perf_jr_stall ),
|
||||
|
@ -664,7 +666,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)
|
||||
if ((id_stage_i.stall_ex_o == 1'b0 && is_decoding) || id_stage_i.controller_i.pipe_flush_i)
|
||||
begin
|
||||
mnemonic = "";
|
||||
imm = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue