This commit is contained in:
2023-02-28 09:10:42 +08:00
commit a657a360bf
68 changed files with 5025 additions and 0 deletions

View File

@@ -0,0 +1,106 @@
`timescale 1ns / 1ps
module alu(
input [10:0] alu_op ,
input [31:0] alu_src1 ,
input [31:0] alu_src2 ,
output [31:0] alu_result,
output Carry ,
output Sign ,
output Overflow ,
output Zero
);
wire op_lui;
wire op_add;
wire op_sub;
wire op_or;
wire op_slt;
wire op_sltu;
wire op_xor;
wire op_and;
wire op_sll;
wire op_srl;
wire op_sra;
assign op_lui = alu_op[ 0];
assign op_add = alu_op[ 1];
assign op_sub = alu_op[ 2];
assign op_slt = alu_op[ 3];
assign op_sltu = alu_op[ 4];
assign op_xor = alu_op[ 5];
assign op_or = alu_op[ 6];
assign op_and = alu_op[ 7];
assign op_sll = alu_op[ 8];
assign op_srl = alu_op[ 9];
assign op_sra = alu_op[10];
wire [31:0] lui_result;
wire [31:0] add_sub_result;
wire [31:0] slt_result;
wire [31:0] sltu_result;
wire [31:0] xor_result;
wire [31:0] or_result;
wire [31:0] and_result;
wire [31:0] sll_result;
wire [31:0] sr64_result;
wire [31:0] sr_result;
// 32-bit adder
wire [31:0] adder_a;
wire [31:0] adder_b;
wire adder_cin;
wire [31:0] adder_result;
wire adder_cout;
assign adder_a = alu_src1;
assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2;
assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0;
assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin;
// ADD, SUB result
assign add_sub_result = adder_result;
// SLT result
assign slt_result[31:1] = 31'b0;
assign slt_result[0] = (alu_src1[31] & ~alu_src2[31])
| ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]);
// SLTU result
assign sltu_result[31:1] = 31'b0;
assign sltu_result[0] = ~adder_cout;
// bitwise operation
assign or_result = alu_src1 | alu_src2;
assign and_result = alu_src1 & alu_src2;
assign xor_result = alu_src1 ^ alu_src2;
assign lui_result = alu_src2;
// SLL result
assign sll_result = alu_src1 << alu_src2[4:0];
// SRL, SRA result
assign sr64_result = {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0];
assign sr_result = sr64_result[31:0];
// final result mux
assign alu_result = ({32{op_add|op_sub}} & add_sub_result)
| ({32{op_slt }} & slt_result)
| ({32{op_sltu }} & sltu_result)
| ({32{op_or }} & or_result)
| ({32{op_xor }} & xor_result)
| ({32{op_and }} & and_result)
| ({32{op_lui }} & lui_result)
| ({32{op_sll }} & sll_result)
| ({32{op_srl|op_sra}} & sr_result);
assign Carry = op_sub ^ adder_cout;
assign Sign = alu_result[31];
assign Overflow = (op_add|op_sub) ? ( adder_a[31] & adder_b[31] & adder_cout)
| (~adder_a[31] & ~adder_b[31] & ~adder_cout)
: 1'b0;
assign Zero = (alu_result == 32'b0);
endmodule

View File

@@ -0,0 +1,22 @@
`ifndef CPU_H
`define CPU_H
`define BR_BUS_WD 33
`define DS_TO_FW_BUS_WD 10
`define ES_TO_FW_BUS_WD 12
`define MS_TO_FW_BUS_WD 6
`define FW_TO_ES_BUS_WD 5
`define MS_TO_ES_BUS_WD 32
`define WS_TO_ES_BUS_WD 32
`define DS_TO_LU_BUS_WD 10
`define ES_TO_LU_BUS_WD 10
`define LU_TO_DS_BUS_WD 1
`define FS_TO_DS_BUS_WD 64
`define DS_TO_ES_BUS_WD 178
`define ES_TO_MS_BUS_WD 120
`define MS_TO_WS_BUS_WD 103
`define WS_TO_RF_BUS_WD 38
`endif

View File

@@ -0,0 +1,227 @@
`timescale 1ns / 1ps
`include "cpu.h"
module cpu_top(
input clk,
input resetn,
// inst ram interface
output instr_ram_en,
output [ 3:0] instr_ram_wen,
output [31:0] instr_ram_addr,
output [31:0] instr_ram_wdata,
input [31:0] instr_ram_rdata,
// data ram interface
output data_ram_en,
output [ 3:0] data_ram_wen,
output [31:0] data_ram_addr,
output [31:0] data_ram_wdata,
input [31:0] data_ram_rdata,
// trace debug interface
output [31:0] debug_wb_pc,
output [ 3:0] debug_wb_rf_wen,
output [ 4:0] debug_wb_rf_wnum,
output [31:0] debug_wb_rf_wdata,
input [ 4:0] rf_raddr,
output [31:0] rf_rdata
);
reg reset;
always @(posedge clk) reset <= ~resetn;
wire ds_allowin;
wire es_allowin;
wire ms_allowin;
wire ws_allowin;
wire fs_to_ds_valid;
wire ds_to_es_valid;
wire es_to_ms_valid;
wire ms_to_ws_valid;
wire [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus;
wire [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus;
wire [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus;
wire [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus;
wire [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus;
wire [`BR_BUS_WD -1:0] br_bus;
wire [`DS_TO_FW_BUS_WD -1:0] ds_to_fw_bus;
wire [`ES_TO_FW_BUS_WD -1:0] es_to_fw_bus;
wire [`MS_TO_FW_BUS_WD -1:0] ms_to_fw_bus;
wire [`FW_TO_ES_BUS_WD -1:0] fw_to_es_bus;
wire [`MS_TO_ES_BUS_WD -1:0] ms_to_es_bus;
wire [`WS_TO_ES_BUS_WD -1:0] ws_to_es_bus;
wire [`DS_TO_LU_BUS_WD -1:0] ds_to_lu_bus;
wire [`ES_TO_LU_BUS_WD -1:0] es_to_lu_bus;
wire lu_stall;
wire dh_flush;
wire dh_stall;
wire fs_stall;
wire fs_flush;
wire ds_flush;
wire es_flush;
wire ms_flush;
wire ws_flush;
// IF stage
if_stage if_stage(
.clk (clk ),
.reset (reset ),
.fs_flush (fs_flush ),
.fs_stall (fs_stall ),
//allowin
.ds_allowin (ds_allowin ),
//brbus
.br_bus (br_bus ),
//outputs
.fs_to_ds_valid (fs_to_ds_valid ),
.fs_to_ds_bus (fs_to_ds_bus ),
// inst ram interface
.instr_ram_en (instr_ram_en ),
.instr_ram_wen (instr_ram_wen ),
.instr_ram_addr (instr_ram_addr ),
.instr_ram_wdata(instr_ram_wdata),
.instr_ram_rdata(instr_ram_rdata)
);
// ID stage
id_stage id_stage(
.clk (clk ),
.reset (reset ),
.ds_flush (ds_flush ),
.stall (lu_stall ),
//allowin
.es_allowin (es_allowin ),
.ds_allowin (ds_allowin ),
//from fs
.fs_to_ds_valid (fs_to_ds_valid ),
.fs_to_ds_bus (fs_to_ds_bus ),
//to es
.ds_to_es_valid (ds_to_es_valid ),
.ds_to_es_bus (ds_to_es_bus ),
//to fw
.ds_to_fw_bus (ds_to_fw_bus ),
//to lu
.ds_to_lu_bus (ds_to_lu_bus ),
//to rf: for write back
.ws_to_rf_bus (ws_to_rf_bus ),
//to pipctr
.dh_flush (dh_flush ),
.dh_stall (dh_stall ),
.rf_raddr (rf_raddr ),
.rf_rdata (rf_rdata )
);
// EXE stage
exe_stage exe_stage(
.clk (clk ),
.reset (reset ),
.es_flush (es_flush ),
//allowin
.ms_allowin (ms_allowin ),
.es_allowin (es_allowin ),
//from ds
.ds_to_es_valid (ds_to_es_valid ),
.ds_to_es_bus (ds_to_es_bus ),
//from ms
.ms_to_es_bus (ms_to_es_bus ),
//from ws
.ws_to_es_bus (ws_to_es_bus ),
//from fw
.fw_to_es_bus (fw_to_es_bus ),
//to lu
.es_to_lu_bus (es_to_lu_bus ),
//to fw
.es_to_fw_bus (es_to_fw_bus ),
//to ms
.es_to_ms_valid (es_to_ms_valid ),
.es_to_ms_bus (es_to_ms_bus ),
// data ram interface
.data_ram_en (data_ram_en ),
.data_ram_wen (data_ram_wen ),
.data_ram_addr (data_ram_addr ),
.data_ram_wdata (data_ram_wdata )
);
// MEM stage
mem_stage mem_stage(
.clk (clk ),
.reset (reset ),
.ms_flush (ms_flush ),
//allowin
.ws_allowin (ws_allowin ),
.ms_allowin (ms_allowin ),
//from es
.es_to_ms_valid (es_to_ms_valid ),
.es_to_ms_bus (es_to_ms_bus ),
//to fs
.br_bus (br_bus ),
//to es: for forward
.ms_to_es_bus (ms_to_es_bus ),
//to fw
.ms_to_fw_bus (ms_to_fw_bus ),
//to ws
.ms_to_ws_valid (ms_to_ws_valid ),
.ms_to_ws_bus (ms_to_ws_bus ),
//from data-ram
.data_ram_rdata (data_ram_rdata)
);
// WB stage
wb_stage wb_stage(
.clk (clk ),
.reset (reset ),
.ws_flush (ws_flush ),
//allowin
.ws_allowin (ws_allowin ),
//from ms
.ms_to_ws_valid (ms_to_ws_valid ),
.ms_to_ws_bus (ms_to_ws_bus ),
//to rf: for write back
.ws_to_rf_bus (ws_to_rf_bus ),
//to es: for forward
.ws_to_es_bus (ws_to_es_bus ),
//trace debug interface
.debug_wb_pc (debug_wb_pc ),
.debug_wb_rf_wen (debug_wb_rf_wen ),
.debug_wb_rf_wnum (debug_wb_rf_wnum ),
.debug_wb_rf_wdata(debug_wb_rf_wdata)
);
// Forward
forward u_forward(
.clk (clk ),
.ds_to_fw_bus (ds_to_fw_bus),
.es_to_fw_bus (es_to_fw_bus),
.ms_to_fw_bus (ms_to_fw_bus),
.fw_to_es_bus (fw_to_es_bus)
);
// Load Use
loaduse u_loaduse(
.clk (clk ),
.reset (reset ),
.ds_to_lu_bus (ds_to_lu_bus),
.es_to_lu_bus (es_to_lu_bus),
.ds_stall (lu_stall ),
.es_flush (lu_flush )
);
piplinectr u_piplinectr(
.clk (clk ),
.reset (reset ),
.lu_flush (lu_flush),
.dh_flush (dh_flush),
.dh_stall (dh_stall),
.fs_stall (fs_stall),
.fs_flush (fs_flush),
.ds_flush (ds_flush),
.es_flush (es_flush),
.ms_flush (ms_flush),
.ws_flush (ws_flush)
);
endmodule

View File

@@ -0,0 +1,153 @@
`timescale 1ns / 1ps
module ctrsignal(
input [ 6:0] OP,
input [ 2:0] func3,
input [ 6:0] func7,
output [ 4:0] ExtOp,
output [ 1:0] ALUAsrc,
output [ 2:0] ALUBsrc,
output [10:0] ALUctr,
output RegWr,
output MemtoReg,
output MemWr,
output [ 5:0] Branch,
output [ 1:0] Jump,
output [ 2:0] Store,
output [ 4:0] Load,
output shamt
);
wire u_type;
wire j_type;
wire s_type;
wire i_type;
wire b_type;
wire r_type;
wire instr_lui ;
wire instr_auipc;
wire instr_jal ;
wire instr_jalr ;
wire instr_beq ;
wire instr_bne ;
wire instr_blt ;
wire instr_bge ;
wire instr_bltu ;
wire instr_bgeu ;
wire instr_lb ;
wire instr_lh ;
wire instr_lw ;
wire instr_lbu ;
wire instr_lhu ;
wire instr_sb ;
wire instr_sh ;
wire instr_sw ;
wire instr_addi ;
wire instr_slti ;
wire instr_sltiu;
wire instr_xori ;
wire instr_ori ;
wire instr_andi ;
wire instr_slli ;
wire instr_srli ;
wire instr_srai ;
wire instr_add ;
wire instr_sub ;
wire instr_sll ;
wire instr_slt ;
wire instr_sltu ;
wire instr_xor ;
wire instr_srl ;
wire instr_sra ;
wire instr_or ;
wire instr_and ;
assign u_type = (OP == 7'b0110111) || (OP == 7'b0010111);
assign j_type = (OP == 7'b1101111);
assign s_type = (OP == 7'b0100011);
assign i_type = (OP == 7'b1100111) || (OP == 7'b0000011) ||(OP == 7'b0010011);
assign b_type = (OP == 7'b1100011);
assign r_type = (OP == 7'b0110011);
assign instr_lui = (OP == 7'b0110111) ;
assign instr_auipc = (OP == 7'b0010111) ;
assign instr_jal = (OP == 7'b1101111) ;
assign instr_jalr = (OP == 7'b1100111) ;
assign instr_beq = b_type & (func3 == 3'b000) ;
assign instr_bne = b_type & (func3 == 3'b001) ;
assign instr_blt = b_type & (func3 == 3'b100) ;
assign instr_bge = b_type & (func3 == 3'b101) ;
assign instr_bltu = b_type & (func3 == 3'b110) ;
assign instr_bgeu = b_type & (func3 == 3'b111) ;
assign instr_lb = (OP == 7'b0000011) & (func3 == 3'b000) ;
assign instr_lh = (OP == 7'b0000011) & (func3 == 3'b001) ;
assign instr_lw = (OP == 7'b0000011) & (func3 == 3'b010) ;
assign instr_lbu = (OP == 7'b0000011) & (func3 == 3'b100) ;
assign instr_lhu = (OP == 7'b0000011) & (func3 == 3'b101) ;
assign instr_sb = s_type & (func3 == 3'b000) ;
assign instr_sh = s_type & (func3 == 3'b001) ;
assign instr_sw = s_type & (func3 == 3'b010) ;
assign instr_addi = (OP == 7'b0010011) & (func3 == 3'b000) ;
assign instr_slti = (OP == 7'b0010011) & (func3 == 3'b010) ;
assign instr_sltiu = (OP == 7'b0010011) & (func3 == 3'b011) ;
assign instr_xori = (OP == 7'b0010011) & (func3 == 3'b100) ;
assign instr_ori = (OP == 7'b0010011) & (func3 == 3'b110) ;
assign instr_andi = (OP == 7'b0010011) & (func3 == 3'b111) ;
assign instr_slli = (OP == 7'b0010011) & (func3 == 3'b001) & (func7 == 7'b0000000);
assign instr_srli = (OP == 7'b0010011) & (func3 == 3'b101) & (func7 == 7'b0000000);
assign instr_srai = (OP == 7'b0010011) & (func3 == 3'b101) & (func7 == 7'b0100000);
assign instr_add = r_type & (func3 == 3'b000) & (func7 == 7'b0000000);
assign instr_sub = r_type & (func3 == 3'b000) & (func7 == 7'b0100000);
assign instr_sll = r_type & (func3 == 3'b001) & (func7 == 7'b0000000);
assign instr_slt = r_type & (func3 == 3'b010) & (func7 == 7'b0000000);
assign instr_sltu = r_type & (func3 == 3'b011) & (func7 == 7'b0000000);
assign instr_xor = r_type & (func3 == 3'b100) & (func7 == 7'b0000000);
assign instr_srl = r_type & (func3 == 3'b101) & (func7 == 7'b0000000);
assign instr_sra = r_type & (func3 == 3'b101) & (func7 == 7'b0100000);
assign instr_or = r_type & (func3 == 3'b110) & (func7 == 7'b0000000);
assign instr_and = r_type & (func3 == 3'b111) & (func7 == 7'b0000000);
assign ExtOp = {u_type,
j_type,
s_type,
i_type,
b_type
};
assign ALUAsrc = { j_type | instr_auipc, // pc
~j_type & ~instr_auipc // rs1_value
};
assign ALUBsrc = { u_type | s_type | i_type, // imm
j_type, // 4
b_type | r_type // rs2_value
};
assign ALUctr[ 0] = instr_lui ;
assign ALUctr[ 1] = instr_lb | instr_lh | instr_lw | instr_lbu
| instr_lhu | instr_sb | instr_sh | instr_sw
| instr_addi | instr_add | instr_auipc | j_type ;
assign ALUctr[ 2] = instr_sub | b_type ;
assign ALUctr[ 3] = instr_slt | instr_slti ;
assign ALUctr[ 4] = instr_sltu | instr_sltiu ;
assign ALUctr[ 5] = instr_xori | instr_xor ;
assign ALUctr[ 6] = instr_ori | instr_or ;
assign ALUctr[ 7] = instr_and | instr_andi ;
assign ALUctr[ 8] = instr_slli | instr_sll ;
assign ALUctr[ 9] = instr_srli | instr_srl ;
assign ALUctr[10] = instr_srai | instr_sra ;
assign RegWr = ~(instr_sw | instr_sh | instr_sb) & ~b_type;
assign MemtoReg = instr_lb | instr_lh | instr_lw | instr_lbu | instr_lhu;
assign MemWr = s_type;
assign Branch = { instr_bgeu, instr_bltu , instr_bge, instr_blt , instr_bne, instr_beq};
assign Jump = { instr_jalr, instr_jal};
assign Load = { instr_lhu , instr_lbu , instr_lw , instr_lh , instr_lb};
assign Store = { instr_sw , instr_sh , instr_sb};
assign shamt = instr_slli | instr_srli | instr_srai;
endmodule

View File

@@ -0,0 +1,192 @@
`timescale 1ns / 1ps
`include "cpu.h"
module exe_stage(
input clk ,
input reset ,
input es_flush,
input ms_allowin ,
output es_allowin ,
input ds_to_es_valid,
input [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus ,
input [`MS_TO_ES_BUS_WD -1:0] ms_to_es_bus ,
input [`WS_TO_ES_BUS_WD -1:0] ws_to_es_bus ,
input [`FW_TO_ES_BUS_WD -1:0] fw_to_es_bus ,
output [`ES_TO_FW_BUS_WD -1:0] es_to_fw_bus ,
output [`ES_TO_LU_BUS_WD -1:0] es_to_lu_bus ,
output es_to_ms_valid,
output [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus ,
output data_ram_en ,
output [ 3:0] data_ram_wen ,
output [31:0] data_ram_addr ,
output [31:0] data_ram_wdata
);
reg es_valid ;
wire es_ready_go ;
reg [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus_r;
wire [ 1:0] es_ALUAsrc ;
wire [ 2:0] es_ALUBsrc ;
wire [10:0] es_ALUctr ;
wire [ 5:0] es_Branch ;
wire [ 1:0] es_Jump ;
wire es_MemtoReg ;
wire es_MemWr ;
wire es_RegWr ;
wire [ 4:0] es_Load ;
wire [ 2:0] es_Store ;
wire es_shamt ;
wire [31:0] es_imm ;
wire [31:0] es_rs1_value;
wire [31:0] es_rs2_value;
wire [ 4:0] es_rd ;
wire [ 4:0] es_rs1 ;
wire [ 4:0] es_rs2 ;
wire [31:0] es_pc ;
assign { es_ALUctr , //177:167
es_shamt , //166:166
es_Load , //166:162
es_Store , //161:159
es_MemWr , //158:158
es_Branch , //157:152
es_Jump , //151:150
es_MemtoReg , //149:149
es_RegWr , //148:148
es_ALUAsrc , //147:146
es_ALUBsrc , //145:143
es_rd , //142:138
es_rs1 , //137:133
es_rs2 , //132:128
es_imm , //127:96
es_rs1_value , //95 :64
es_rs2_value , //63 :32
es_pc //31 :0
} = ds_to_es_bus_r;
wire [ 31:0] br_target ;
wire [31:0] es_alu_src1 ;
wire [31:0] es_alu_src2 ;
wire [31:0] es_alu_result;
wire es_Carry ;
wire es_Sign ;
wire es_Overflow ;
wire es_Zero ;
assign es_to_ms_bus = { es_Carry , //119:119
es_Sign , //118:118
es_Overflow , //117:117
es_Zero , //116:116
br_target , //115:84
es_Load , //83 :79
es_Branch , //78 :73
es_Jump , //72 :71
es_MemtoReg , //70 :70
es_RegWr , //69 :69
es_rd , //68 :64
es_alu_result , //63 :32
es_pc //31 :0
};
wire [ 1:0] BusAFw;
wire [ 1:0] BusBFw;
wire DiSrc;
assign {BusAFw,
BusBFw,
DiSrc } = fw_to_es_bus;
wire [31:0] rf_wdata;
wire [31:0] ms_alu_result;
assign rf_wdata = ws_to_es_bus[31:0];
assign ms_alu_result = ms_to_es_bus[31:0];
assign es_to_fw_bus = {es_rs2, es_rd, es_RegWr, es_MemWr};
assign es_to_lu_bus = {es_rd, es_Load};
wire [31:0] es_rs1_forward;
wire [31:0] es_rs2_forward;
assign es_ready_go = 1'b1;
assign es_allowin = !es_valid || es_ready_go && ms_allowin;
assign es_to_ms_valid = es_valid && es_ready_go;
always @(posedge clk) begin
if (reset) begin
es_valid <= 1'b0;
end
else if (es_allowin) begin
es_valid <= ds_to_es_valid;
end
if (reset || es_flush) begin
ds_to_es_bus_r <= 0;
end
else if (ds_to_es_valid && es_allowin) begin
ds_to_es_bus_r <= ds_to_es_bus;
end
// else begin
// ds_to_es_bus_r <= 0;
// end
end
assign es_rs1_forward = (BusAFw == 2'b00) ? es_rs1_value :
(BusAFw == 2'b01) ? rf_wdata :
(BusAFw == 2'b10) ? ms_alu_result :
32'b0;
assign es_rs2_forward = (BusBFw == 2'b00) ? es_rs2_value :
(BusBFw == 2'b01) ? rf_wdata :
(BusBFw == 2'b10) ? ms_alu_result :
32'b0;
assign es_alu_src1 = ({32{es_ALUAsrc[1]}} & es_pc)
| ({32{es_ALUAsrc[0]}} & es_rs1_forward);
assign es_alu_src2 = ({32{es_ALUBsrc[2]}} & (es_shamt ? {27'b0, es_imm[4:0]} : es_imm))
| ({32{es_ALUBsrc[1]}} & 32'd4)
| ({32{es_ALUBsrc[0]}} & es_rs2_forward);
alu u_alu(
.alu_op (es_ALUctr ),
.alu_src1 (es_alu_src1 ),
.alu_src2 (es_alu_src2 ),
.alu_result (es_alu_result),
.Carry (es_Carry ),
.Sign (es_Sign ),
.Overflow (es_Overflow ),
.Zero (es_Zero )
);
assign data_ram_en = 1'b1;
assign data_ram_wen = (es_MemWr && es_valid) ?
(({4{es_Store[0]}} &
({4{es_alu_result[1:0] == 2'b00}} & 4'b0001)
| ({4{es_alu_result[1:0] == 2'b01}} & 4'b0010)
| ({4{es_alu_result[1:0] == 2'b10}} & 4'b0100)
| ({4{es_alu_result[1:0] == 2'b11}} & 4'b1000))
| ({4{es_Store[1]}} &
({4{es_alu_result[1:0] == 2'b01}} & 4'b0011 )
| ({4{es_alu_result[1:0] == 2'b10}} & 4'b1100 ))
| ({4{es_Store[2]}} & 4'b1111 ))
: 4'b0000 ;
assign data_ram_addr = es_alu_result;
assign data_ram_wdata = DiSrc ? rf_wdata :
(es_Store[0] ? {4{es_rs2_value[ 7:0]}} :
es_Store[1] ? {2{es_rs2_value[15:0]}} :
es_Store[2] ? es_rs2_value :
32'b0 );
assign br_target = ({{31{es_Jump[1] }}, 1'b0} & (es_alu_src1 + es_imm))
| ( {32{es_Jump[0] | (^es_Branch)}} & (es_pc + es_imm));
endmodule

View File

@@ -0,0 +1,136 @@
`timescale 1ns / 1ps
`include "cpu.h"
module forward(
input clk,
input [`DS_TO_FW_BUS_WD - 1:0] ds_to_fw_bus,
input [`ES_TO_FW_BUS_WD - 1:0] es_to_fw_bus,
input [`MS_TO_FW_BUS_WD - 1:0] ms_to_fw_bus,
output [`FW_TO_ES_BUS_WD - 1:0] fw_to_es_bus
);
wire [4:0] ds_rs1;
wire [4:0] ds_rs2;
wire [4:0] es_rs2;
wire [4:0] es_rd ;
wire es_MemWr;
wire es_RegWr;
wire [4:0] ms_rd ;
wire ms_RegWr;
wire [1:0] BusAFw;
wire [1:0] BusBFw;
wire DiSrc;
reg [`FW_TO_ES_BUS_WD - 1:0] fw_to_es_bus_r;
assign {ds_rs1, ds_rs2} = ds_to_fw_bus;
assign {es_rs2, es_rd , es_RegWr, es_MemWr} = es_to_fw_bus;
assign {ms_rd , ms_RegWr } = ms_to_fw_bus;
assign BusAFw[0] = ms_RegWr && (ms_rd != 5'b0) && (es_rd != ds_rs1) && (ms_rd == ds_rs1);
assign BusAFw[1] = es_RegWr && (es_rd != 5'b0) && (es_rd == ds_rs1) ;
assign BusBFw[0] = ms_RegWr && (ms_rd != 5'b0) && (es_rd != ds_rs2) && (ms_rd == ds_rs2);
assign BusBFw[1] = es_RegWr && (es_rd != 5'b0) && (es_rd == ds_rs2) ;
assign DiSrc = ms_RegWr && (ms_rd != 5'b0) && (ms_rd == es_rs2) && es_MemWr ;
always @(posedge clk) begin
fw_to_es_bus_r <= {BusAFw, BusBFw, DiSrc};
end
assign fw_to_es_bus = fw_to_es_bus_r;
endmodule
module loaduse(
input clk,
input reset,
input [`DS_TO_LU_BUS_WD -1:0] ds_to_lu_bus,
input [`ES_TO_LU_BUS_WD -1:0] es_to_lu_bus,
output ds_stall,
output es_flush
);
wire [4:0] ds_sr1;
wire [4:0] ds_sr2;
wire [4:0] es_Load;
wire [4:0] es_rd;
wire stall;
assign {ds_sr1, ds_sr2 } = ds_to_lu_bus;
assign {es_rd , es_Load} = es_to_lu_bus;
assign stall = ^es_Load &&
(((ds_sr1 == es_rd) && (ds_sr1 != 5'b0)) || ((ds_sr2 == es_rd) && (ds_sr2 != 5'b0)));
assign ds_stall = stall;
assign es_flush = stall;
endmodule
module piplinectr(
input clk,
input reset,
input lu_flush,
input dh_flush,
input dh_stall,
output fs_stall,
output fs_flush,
output ds_flush,
output es_flush,
output ms_flush,
output ws_flush
);
reg [7:0] flush;
reg [1:0] stall;
always @(posedge clk) begin
if(reset) begin
flush <= 5'b0;
end
else if(lu_flush) begin
flush <= {flush[6] , lu_flush , flush[4:0], 1'b0};
end
else if(dh_flush) begin
flush <= {flush[6:5], {3{dh_flush}}, flush[1:0], 1'b0};
end
else begin
flush <= {flush[6:0] , 1'b0};
end
if(reset) begin
stall <= 2'b0;
end
else if(dh_stall) begin
stall <= {stall[0], dh_stall};
end
else begin
stall <= {stall[0], 1'b0};
end
end
assign {ws_flush,
ms_flush,
es_flush,
ds_flush,
fs_flush} = flush[7:3] | {2'b0, lu_flush, 2'b0} | {3'b0, dh_flush, dh_flush};
assign fs_stall = ^stall | dh_stall;
endmodule

View File

@@ -0,0 +1,185 @@
`timescale 1ns / 1ps
`include "cpu.h"
module id_stage(
input clk,
input reset,
input ds_flush,
input es_allowin,
output ds_allowin,
input fs_to_ds_valid,
input [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus,
output ds_to_es_valid,
output [`DS_TO_ES_BUS_WD -1:0] ds_to_es_bus,
output [`DS_TO_FW_BUS_WD -1:0] ds_to_fw_bus,
input stall,
output [`DS_TO_LU_BUS_WD -1:0] ds_to_lu_bus,
input [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus,
output dh_flush,
output dh_stall,
input [ 4 :0] rf_raddr,
output [31 :0] rf_rdata
);
reg ds_valid;
wire ds_ready_go;
wire [31 :0] fs_pc;
reg [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus_r;
assign fs_pc = fs_to_ds_bus[31:0];
wire [31:0] ds_instr;
wire [31:0] ds_pc;
assign {ds_instr,
ds_pc } = fs_to_ds_bus_r;
wire rf_we;
wire [ 4:0] rf_waddr;
wire [31:0] rf_wdata;
assign {rf_we , //37:37
rf_waddr, //36:32
rf_wdata //31:0
} = ws_to_rf_bus;
wire [ 4:0] ExtOp;
wire [ 1:0] ALUAsrc;
wire [ 2:0] ALUBsrc;
wire [10:0] ALUctr;
wire [ 5:0] Branch;
wire [ 1:0] Jump;
wire MemtoReg;
wire MemWr;
wire RegWr;
wire [ 4:0] Load;
wire [ 2:0] Store;
wire shamt;
wire [31:0] imm;
wire [31:0] rs1_value;
wire [31:0] rs2_value;
wire [ 6:0] op;
wire [ 6:0] func7;
wire [ 2:0] func3;
wire [ 4:0] rs2;
wire [ 4:0] rs1;
wire [ 4:0] rd;
wire [31:0] immI;
wire [31:0] immS;
wire [31:0] immB;
wire [31:0] immU;
wire [31:0] immJ;
wire [ 4:0] rf_raddr1;
wire [ 31:0] rf_rdata1;
wire [ 4:0] rf_raddr2;
wire [ 31:0] rf_rdata2;
assign ds_to_es_bus= { ALUctr , //177:167
shamt , //166:166
Load , //166:162
Store , //161:159
MemWr , //158:158
Branch , //157:152
Jump , //151:150
MemtoReg , //149:149
RegWr , //148:148
ALUAsrc , //147:146
ALUBsrc , //145:143
rd , //142:138
rs1 , //137:133
rs2 , //132:128
imm , //127:96
rs1_value , //95 :64
rs2_value , //63 :32
ds_pc //31 :0
};
assign ds_to_fw_bus = {rs1, rs2};
assign ds_to_lu_bus = {rs1, rs2};
assign ds_ready_go = !stall;
assign ds_allowin = !ds_valid || ds_ready_go && es_allowin;
assign ds_to_es_valid = ds_valid && ds_ready_go;
always @(posedge clk) begin
if (reset) begin
ds_valid <= 1'b0;
end
else if (ds_allowin) begin
ds_valid <= fs_to_ds_valid;
end
if (reset || ds_flush) begin
fs_to_ds_bus_r <= 0;
end
else if (fs_to_ds_valid && ds_allowin) begin
fs_to_ds_bus_r <= fs_to_ds_bus;
end
end
assign op = ds_instr[ 6: 0];
assign func7 = ds_instr[31:25];
assign func3 = ds_instr[14:12];
assign rs2 = ds_instr[24:20];
assign rs1 = ds_instr[19:15];
assign rd = ds_instr[11: 7];
assign immI = {{20{ds_instr[31]}}, ds_instr[31:20]};
assign immU = { ds_instr[31:12] , 12'b0};
assign immS = {{20{ds_instr[31]}}, ds_instr[31:25], ds_instr[11: 7]};
assign immB = {{20{ds_instr[31]}}, ds_instr[7] , ds_instr[30:25], ds_instr[11: 8], 1'b0};
assign immJ = {{12{ds_instr[31]}}, ds_instr[19:12], ds_instr[20] , ds_instr[30:21], 1'b0};
ctrsignal u_ctrsignal(
.OP(op),
.func3 (func3 ),
.func7 (func7 ),
.ExtOp (ExtOp ),
.ALUAsrc (ALUAsrc ),
.ALUBsrc (ALUBsrc ),
.ALUctr (ALUctr ),
.RegWr (RegWr ),
.MemtoReg (MemtoReg),
.MemWr (MemWr ),
.Branch (Branch ),
.Jump (Jump ),
.Load (Load ),
.Store (Store ),
.shamt (shamt )
);
assign imm = ({32{ExtOp[4]}} & immU)
| ({32{ExtOp[3]}} & immJ)
| ({32{ExtOp[2]}} & immS)
| ({32{ExtOp[1]}} & immI)
| ({32{ExtOp[0]}} & immB);
assign rf_raddr1 = rs1;
assign rf_raddr2 = rs2;
regfile u_regfile(
.clk (clk ),
.reset (reset ),
.raddr1 (rf_raddr1),
.rdata1 (rf_rdata1),
.raddr2 (rf_raddr2),
.rdata2 (rf_rdata2),
.raddr3 (rf_raddr ),
.rdata3 (rf_rdata ),
.we (rf_we ),
.waddr (rf_waddr ),
.wdata (rf_wdata )
);
assign rs1_value = rf_rdata1;
assign rs2_value = rf_rdata2;
assign dh_flush = ^Jump || ^Branch;
assign dh_stall = ^Branch;
endmodule

View File

@@ -0,0 +1,73 @@
`timescale 1ns / 1ps
`include "cpu.h"
module if_stage(
input clk,
input reset,
input fs_flush,
input fs_stall,
input ds_allowin,
input [`BR_BUS_WD -1:0] br_bus,
output fs_to_ds_valid,
output [`FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus,
output instr_ram_en,
output [ 3:0] instr_ram_wen,
output [31:0] instr_ram_addr,
output [31:0] instr_ram_wdata,
input [31:0] instr_ram_rdata
);
reg fs_valid;
wire fs_ready_go;
wire fs_allowin;
wire to_fs_valid;
wire [31:0] seq_pc;
wire [31:0] nextpc;
wire br_taken;
wire [31:0] br_target;
assign {br_taken, br_target} = br_bus;
wire [31:0] fs_instr;
reg [31:0] fs_pc;
assign fs_to_ds_bus = {fs_instr, fs_pc};
assign to_fs_valid = ~reset;
assign seq_pc = fs_pc + 3'h4;
assign nextpc = br_taken ? br_target :
fs_stall ? fs_pc :
seq_pc;
// IF stage
assign fs_ready_go = !(fs_flush);
assign fs_allowin = !fs_valid || fs_ready_go && ds_allowin;
assign fs_to_ds_valid = fs_valid && fs_ready_go;
always @(posedge clk) begin
if (reset) begin
fs_valid <= 1'b0;
end
else if (fs_allowin) begin
fs_valid <= to_fs_valid;
end
if (reset || (fs_flush && !fs_stall)) begin
fs_pc <= 32'hfffffffc;
end
else if (to_fs_valid && fs_allowin) begin
fs_pc <= nextpc;
end
end
assign instr_ram_en = to_fs_valid && fs_allowin;
assign instr_ram_wen = 4'h0;
assign instr_ram_addr = nextpc;
assign instr_ram_wdata = 32'b0;
assign fs_instr = instr_ram_rdata;
endmodule

View File

@@ -0,0 +1,125 @@
`timescale 1ns / 1ps
`include "cpu.h"
module mem_stage(
input clk ,
input reset ,
input ms_flush,
input ws_allowin ,
output ms_allowin ,
//from es
input es_to_ms_valid,
input [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus ,
//to es
output [`MS_TO_ES_BUS_WD -1:0] ms_to_es_bus ,
//to fw
output [`MS_TO_FW_BUS_WD -1:0] ms_to_fw_bus ,
//to ws
output ms_to_ws_valid,
output [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus ,
output [`BR_BUS_WD -1:0] br_bus ,
//from data-sram
input [31 :0] data_ram_rdata
);
reg ms_valid;
wire ms_ready_go;
reg [`ES_TO_MS_BUS_WD -1:0] es_to_ms_bus_r;
wire [ 5:0] ms_Branch ;
wire [ 1:0] ms_Jump ;
wire ms_MemtoReg ;
wire ms_MemWr ;
wire ms_RegWr ;
wire [ 4:0] ms_Load ;
wire [ 4:0] ms_rd ;
wire [ 4:0] ms_rs1 ;
wire [ 4:0] ms_rs2 ;
wire [31:0] ms_alu_result;
wire [31:0] ms_pc ;
wire [31:0] br_target ;
wire ms_Carry ;
wire ms_Sign ;
wire ms_Overflow ;
wire ms_Zero ;
wire br_taken ;
assign { ms_Carry , //119:119
ms_Sign , //118:118
ms_Overflow , //117:117
ms_Zero , //116:116
br_target , //115:84
ms_Load , //83 :79
ms_Branch , //78 :73
ms_Jump , //72 :71
ms_MemtoReg , //70 :70
ms_RegWr , //69 :69
ms_rd , //68 :64
ms_alu_result , //63 :32
ms_pc //31 :0
} = es_to_ms_bus_r;
wire [31:0] mem_result;
assign br_bus = { br_taken, //32:32
br_target //31:0
};
assign ms_to_es_bus = { ms_alu_result};
assign ms_to_fw_bus = { ms_rd , ms_RegWr};
assign ms_to_ws_bus = { ms_MemtoReg , //102:102
ms_RegWr , //101:101
mem_result , //100:69
ms_rd , //68 :64
ms_alu_result , //63 :32
ms_pc //31 :0
};
assign ms_ready_go = 1'b1;
assign ms_allowin = !ms_valid || ms_ready_go && ws_allowin;
assign ms_to_ws_valid = ms_valid && ms_ready_go;
always @(posedge clk) begin
if (reset) begin
ms_valid <= 1'b0;
end
else if (ms_allowin) begin
ms_valid <= es_to_ms_valid;
end
if (reset || ms_flush) begin
es_to_ms_bus_r <= 0;
end
else if (es_to_ms_valid && ms_allowin) begin
es_to_ms_bus_r <= es_to_ms_bus;
end
// else begin
// es_to_ms_bus_r <= 0;
// end
end
assign mem_result = (ms_Load[0] || ms_Load[3]) ? ((ms_alu_result[1:0] == 2'b00) ? {{24{ms_Load[3] ? data_ram_rdata[ 7] : 1'b0 }}, data_ram_rdata[ 7:0] }:
(ms_alu_result[1:0] == 2'b01) ? {{16{ms_Load[3] ? data_ram_rdata[ 7] : 1'b0 }}, data_ram_rdata[ 7:0], 8'b0}:
(ms_alu_result[1:0] == 2'b10) ? {{ 8{ms_Load[3] ? data_ram_rdata[ 7] : 1'b0 }}, data_ram_rdata[ 7:0], 16'b0}:
{ data_ram_rdata[ 7:0], 24'b0}
) :
(ms_Load[1] || ms_Load[4]) ? ((ms_alu_result[1:0] == 2'b00) ? {{16{ms_Load[4] ? data_ram_rdata[15] : 1'b0 }}, data_ram_rdata[15:0] }:
{ data_ram_rdata[15:0], 16'b0}
) :
ms_Load[2] ? ( data_ram_rdata
) : 32'b0;
assign br_taken = ( ms_Branch[0] & ms_Zero )
| ( ms_Branch[1] & ~ms_Zero )
| ( ms_Branch[2] & (ms_Sign != ms_Overflow) )
| ( ms_Branch[3] & (ms_Zero | (ms_Sign == ms_Overflow)))
| ( ms_Branch[4] & ms_Carry )
| ( ms_Branch[5] & (ms_Zero | ~ms_Carry ))
| (^ms_Jump );
endmodule

View File

@@ -0,0 +1,45 @@
module regfile(
input clk,
input reset,
// READ PORT 1
input [ 4:0] raddr1,
output [31:0] rdata1,
// READ PORT 2
input [ 4:0] raddr2,
output [31:0] rdata2,
// READ PORT 3
input [ 4:0] raddr3,
output [31:0] rdata3,
// WRITE PORT
input we, //write enable, HIGH valid
input [ 4:0] waddr,
input [31:0] wdata
);
reg [31:0] rf[31:0];
integer i = 0;
//WRITE
always @(posedge clk) begin
if (reset) begin
for(i = 0; i < 32; i = i + 1) begin
rf[i] <= 32'b0;
end
end
else if (we) begin
rf[waddr]<= wdata;
end
end
//READ OUT 1
assign rdata1 = (we & (raddr1 == waddr)) ? wdata :
( raddr1 == 5'b0 ) ? 32'b0 :
rf[raddr1];
//READ OUT 2
assign rdata2 = (we & (raddr2 == waddr)) ? wdata :
( raddr2 == 5'b0 ) ? 32'b0 :
rf[raddr2];
//READ OUT 3
assign rdata3 = (we & (raddr3 == waddr)) ? wdata :
( raddr3 == 5'b0 ) ? 32'b0 :
rf[raddr3];
endmodule

View File

@@ -0,0 +1,95 @@
`timescale 1ns / 1ps
module soc_top(
input resetn,
input clk,
input [ 4:0] switch,
output [15:0] led
);
wire cpu_clk;
reg cpu_resetn;
wire [31:0] led32;
assign led = led32[15:0];
always @(posedge cpu_clk)
begin
cpu_resetn <= resetn;
end
pll u_pll(
.clk_in1 (clk),
.clk_out1 (cpu_clk)
);
//cpu instr ram
wire cpu_instr_en;
wire [ 3:0] cpu_instr_wen;
wire [31:0] cpu_instr_addr;
wire [31:0] cpu_instr_wdata;
wire [31:0] cpu_instr_rdata;
//cpu data ram
wire cpu_data_en;
wire [ 3:0] cpu_data_wen;
wire [31:0] cpu_data_addr;
wire [31:0] cpu_data_wdata;
wire [31:0] cpu_data_rdata;
//debug signals
wire [31:0] debug_wb_pc;
wire [ 3:0] debug_wb_rf_wen;
wire [ 4:0] debug_wb_rf_wnum;
wire [31:0] debug_wb_rf_wdata;
cpu_top cpu(
.clk (cpu_clk ),
.resetn (cpu_resetn),
.instr_ram_en (cpu_instr_en ),
.instr_ram_wen (cpu_instr_wen ),
.instr_ram_addr (cpu_instr_addr ),
.instr_ram_wdata (cpu_instr_wdata),
.instr_ram_rdata (cpu_instr_rdata),
.data_ram_en (cpu_data_en ),
.data_ram_wen (cpu_data_wen ),
.data_ram_addr (cpu_data_addr ),
.data_ram_wdata (cpu_data_wdata),
.data_ram_rdata (cpu_data_rdata),
//debug
.debug_wb_pc (debug_wb_pc ),
.debug_wb_rf_wen (debug_wb_rf_wen ),
.debug_wb_rf_wnum (debug_wb_rf_wnum ),
.debug_wb_rf_wdata(debug_wb_rf_wdata),
.rf_raddr (switch ),
.rf_rdata (led32 )
);
//instr ram
instr_ram instr_ram
(
.clka (cpu_clk ),
.ena (cpu_instr_en ),
.wea (cpu_instr_wen ), //3:0
.addra (cpu_instr_addr[17:2]), //15:0
.dina (cpu_instr_wdata ), //31:0
.douta (cpu_instr_rdata ) //31:0
);
//data ram
data_ram data_ram
(
.clka (cpu_clk ),
.ena (cpu_data_en ),
.wea (cpu_data_wen ), //3:0
.addra (cpu_data_addr[17:2] ), //15:0
.dina (cpu_data_wdata ), //31:0
.douta (cpu_data_rdata ) //31:0
);
endmodule

View File

@@ -0,0 +1,84 @@
`timescale 1ns / 1ps
`include "cpu.h"
module wb_stage(
input clk ,
input reset ,
input ws_flush,
output ws_allowin ,
input ms_to_ws_valid,
input [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus,
//to rf: for write back
output [`WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus,
//to es
output [`WS_TO_ES_BUS_WD -1:0] ws_to_es_bus,
//trace debug interface
output [31:0] debug_wb_pc,
output [ 3:0] debug_wb_rf_wen ,
output [ 4:0] debug_wb_rf_wnum,
output [31:0] debug_wb_rf_wdata
);
reg ws_valid;
wire ws_ready_go;
reg [`MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus_r;
wire ws_MemtoReg ;
wire ws_RegWr ;
wire [31:0] ws_mem_result ;
wire [ 4:0] ws_rd ;
wire [31:0] ws_alu_result ;
wire [31:0] ws_pc ;
assign { ws_MemtoReg , //102:102
ws_RegWr , //101:101
ws_mem_result , //100:69
ws_rd , //68 :64
ws_alu_result , //63 :32
ws_pc //31 :0
} = ms_to_ws_bus_r;
wire rf_we;
wire [4 :0] rf_waddr;
wire [31:0] rf_wdata;
assign ws_to_rf_bus = {rf_we , //37:37
rf_waddr, //36:32
rf_wdata //31:0
};
assign ws_to_es_bus = {rf_wdata};
assign ws_ready_go = 1'b1;
assign ws_allowin = !ws_valid || ws_ready_go;
always @(posedge clk) begin
if (reset) begin
ws_valid <= 1'b0;
end
else if (ws_allowin) begin
ws_valid <= ms_to_ws_valid;
end
if (reset || ws_flush) begin
ms_to_ws_bus_r <= 0;
end
else if (ms_to_ws_valid && ws_allowin) begin
ms_to_ws_bus_r <= ms_to_ws_bus;
end
// else begin
// ms_to_ws_bus_r <= 0;
// end
end
assign rf_we = ws_RegWr && ws_valid;
assign rf_waddr = ws_rd;
assign rf_wdata = ws_MemtoReg ? ws_mem_result :
ws_alu_result;
// debug info generate
assign debug_wb_pc = ws_pc;
assign debug_wb_rf_wen = {4{rf_we}};
assign debug_wb_rf_wnum = ws_rd;
assign debug_wb_rf_wdata = rf_wdata;
endmodule