Skip to content
This repository has been archived by the owner on Jul 6, 2023. It is now read-only.

Commit

Permalink
feat: pipeline CPU with forwarding
Browse files Browse the repository at this point in the history
  • Loading branch information
TonyCrane committed Apr 26, 2023
1 parent 8e4b730 commit 56e108c
Show file tree
Hide file tree
Showing 14 changed files with 394 additions and 62 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- [x] 系统 Ⅰ lab5-1/lab5-2:单周期 CPU
- [x] extra:单周期 CPU with 特权指令/异常处理
- [x] 系统 Ⅱ lab1:流水线 CPU (stall)
- [ ] 系统 Ⅱ lab2:流水线 CPU (forwarding)
- [x] 系统 Ⅱ lab2:流水线 CPU (forwarding)
- [ ] 系统 Ⅱ lab7:流水线 CPU with 特权指令/异常处理
- [ ] 系统 Ⅲ lab1:流水线 CPU with 动态分支预测
- [ ] 系统 Ⅲ lab2:流水线 CPU with Cache
Expand Down
168 changes: 130 additions & 38 deletions src/CPU.v
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,21 @@ module CPU(
wire [3:0] alu_op;
wire [1:0] pc_src, mem_to_reg;
wire reg_write, alu_src, branch, b_type, auipc, mem_write_;
wire mem_read, bubble_stop, jump;
reg [31:0] ID_EX_data1, ID_EX_data2;
reg [31:0] ID_EX_pc, ID_EX_imm;
reg [4:0] ID_EX_rs1, ID_EX_rs2;
reg [4:0] ID_EX_write_addr;
reg [3:0] ID_EX_alu_op;
reg [1:0] ID_EX_pc_src, ID_EX_mem_to_reg;
reg ID_EX_reg_write, ID_EX_alu_src, ID_EX_branch, ID_EX_b_type, ID_EX_auipc, ID_EX_mem_write;
reg ID_EX_mem_read;

wire [31:0] alu_data1, alu_data2, alu_result;
wire alu_zero;
wire [2:0] forwardA, forwardB;
wire [1:0] forwardC;
wire [31:0] ex_mem_data2;
reg [31:0] EX_MEM_alu_result, EX_MEM_pc, EX_MEM_imm;
reg [31:0] EX_MEM_data2;
reg [4:0] EX_MEM_write_addr;
Expand Down Expand Up @@ -66,6 +72,9 @@ module CPU(
ID_EX_b_type <= 1'b0;
ID_EX_auipc <= 1'b0;
ID_EX_mem_write <= 1'b0;
ID_EX_mem_read <= 1'b0;
ID_EX_rs1 <= 5'b0;
ID_EX_rs2 <= 5'b0;
EX_MEM_alu_result <= 32'b0;
EX_MEM_pc <= 32'b0;
EX_MEM_imm <= 32'b0;
Expand All @@ -85,30 +94,63 @@ module CPU(
MEM_WB_mem_to_reg <= 2'b0;
MEM_WB_reg_write <= 1'b0;
end
else begin
pc <= pc_next;
else begin
if (bubble_stop) begin
ID_EX_alu_op <= 4'b0;
ID_EX_pc_src <= 2'b0;
ID_EX_mem_to_reg <= 2'b0;
ID_EX_reg_write <= 1'b0;
ID_EX_alu_src <= 1'b0;
ID_EX_branch <= 1'b0;
ID_EX_b_type <= 1'b0;
ID_EX_auipc <= 1'b0;
ID_EX_mem_write <= 1'b0;
ID_EX_mem_read <= 1'b0;
end else if (jump) begin
pc <= pc_next;

IF_ID_pc <= pc;
IF_ID_inst <= inst;
IF_ID_pc <= pc;
IF_ID_inst <= 32'h00000013;

ID_EX_pc_src <= pc_src;
ID_EX_mem_to_reg <= mem_to_reg;
ID_EX_reg_write <= reg_write;
ID_EX_alu_src <= alu_src;
ID_EX_branch <= branch;
ID_EX_b_type <= b_type;
ID_EX_auipc <= auipc;
ID_EX_alu_op <= alu_op;
ID_EX_mem_write <= mem_write_;
ID_EX_mem_read <= mem_read;
end else begin
pc <= pc_next;

IF_ID_pc <= pc;
IF_ID_inst <= inst;

ID_EX_pc_src <= pc_src;
ID_EX_mem_to_reg <= mem_to_reg;
ID_EX_reg_write <= reg_write;
ID_EX_alu_src <= alu_src;
ID_EX_branch <= branch;
ID_EX_b_type <= b_type;
ID_EX_auipc <= auipc;
ID_EX_alu_op <= alu_op;
ID_EX_mem_write <= mem_write_;
ID_EX_mem_read <= mem_read;
end

ID_EX_pc <= IF_ID_pc;
ID_EX_data1 <= read_data1;
ID_EX_data2 <= read_data2;
ID_EX_imm <= imm;
ID_EX_write_addr <= IF_ID_inst[11:7];
ID_EX_pc_src <= pc_src;
ID_EX_mem_to_reg <= mem_to_reg;
ID_EX_reg_write <= reg_write;
ID_EX_alu_src <= alu_src;
ID_EX_branch <= branch;
ID_EX_b_type <= b_type;
ID_EX_auipc <= auipc;
ID_EX_alu_op <= alu_op;
ID_EX_mem_write <= mem_write_;
ID_EX_rs1 <= IF_ID_inst[19:15];
ID_EX_rs2 <= IF_ID_inst[24:20];

EX_MEM_pc <= ID_EX_pc;
EX_MEM_imm <= ID_EX_imm;
EX_MEM_data2 <= ID_EX_data2;
EX_MEM_data2 <= ex_mem_data2;
EX_MEM_alu_result <= alu_result;
EX_MEM_write_addr <= ID_EX_write_addr;
EX_MEM_pc_src <= ID_EX_pc_src;
Expand All @@ -131,6 +173,34 @@ module CPU(

//--------------------ID--------------------//

StallUnit stallunit (
.ID_EX_mem_read(ID_EX_mem_read),
.ID_EX_rd(ID_EX_write_addr),
.IF_ID_rs1(IF_ID_inst[19:15]),
.IF_ID_rs2(IF_ID_inst[24:20]),
.jump(jump),
.ID_EX_reg_write(ID_EX_reg_write),
.bubble_stop(bubble_stop)
);

assign jal_addr = IF_ID_pc + imm;
wire [31:0] reg1, reg2;
assign reg1 = (jump && EX_MEM_reg_write && (EX_MEM_write_addr != 0) && (EX_MEM_write_addr == IF_ID_inst[19:15])) ? EX_MEM_alu_result : read_data1;
assign reg2 = (jump && EX_MEM_reg_write && (EX_MEM_write_addr != 0) && (EX_MEM_write_addr == IF_ID_inst[24:20])) ? EX_MEM_alu_result : read_data2;
assign jalr_addr = reg1 + reg2;

MuxPC mux_pc (
.I0(jump ? pc : pc + 4),
.I1(jalr_addr),
.I2(jal_addr),
.I3(jal_addr),
.s(pc_src),
.branch(branch),
.b_type(b_type),
.alu_res(reg1 ^ reg2),
.o(pc_next)
);

Regs regs (
.clk(clk),
.rst(rst),
Expand All @@ -157,7 +227,9 @@ module CPU(
.branch(branch),
.b_type(b_type),
.mem_write(mem_write_),
.auipc(auipc)
.auipc(auipc),
.mem_read(mem_read),
.jump(jump)
);

ImmGen immgen (
Expand All @@ -167,17 +239,45 @@ module CPU(

//--------------------EX--------------------//

Mux2x32 mux2x32_1 (
ForwardingUnit forwarding (
.EX_MEM_rd(EX_MEM_write_addr),
.MEM_WB_rd(MEM_WB_write_addr),
.ID_EX_rs1(ID_EX_rs1),
.ID_EX_rs2(ID_EX_rs2),
.EX_MEM_reg_write(EX_MEM_reg_write),
.MEM_WB_reg_write(MEM_WB_reg_write),
.EX_MEM_mem_to_reg(EX_MEM_mem_to_reg),
.MEM_WB_mem_to_reg(MEM_WB_mem_to_reg),
.auipc(ID_EX_auipc),
.alu_src_b(ID_EX_alu_src),
.ForwardA(forwardA),
.ForwardB(forwardB),
.ForwardC(forwardC)
);

Mux8x32 mux_alu_a (
.I0(ID_EX_data1),
.I1(ID_EX_pc),
.s(ID_EX_auipc),
.I1(EX_MEM_alu_result),
.I2(write_data),
.I3(ID_EX_pc),
.I4(EX_MEM_pc + 4),
.I5(MEM_WB_pc + 4),
.I6(EX_MEM_imm),
.I7(MEM_WB_imm),
.s(forwardA),
.o(alu_data1)
);

Mux2x32 mux2x32_2 (
Mux8x32 mux_alu_b (
.I0(ID_EX_data2),
.I1(ID_EX_imm),
.s(ID_EX_alu_src),
.I1(EX_MEM_alu_result),
.I2(write_data),
.I3(ID_EX_imm),
.I4(EX_MEM_pc + 4),
.I5(MEM_WB_pc + 4),
.I6(EX_MEM_imm),
.I7(MEM_WB_imm),
.s(forwardB),
.o(alu_data2)
);

Expand All @@ -189,28 +289,20 @@ module CPU(
.zero(alu_zero)
);

Mux4x32 mux_data2 (
.I0(ID_EX_data2),
.I1(EX_MEM_alu_result),
.I2(write_data),
.I3(32'h00000000),
.s(forwardC),
.o(ex_mem_data2)
);

//--------------------MEM--------------------//
assign addr_out = EX_MEM_alu_result;
assign data_out = EX_MEM_data2;
assign mem_write = EX_MEM_mem_write;

assign jal_addr = EX_MEM_pc + EX_MEM_imm;
assign jalr_addr = EX_MEM_alu_result;

MuxPC mux_pc (
.I0(pc + 4),
.I1(jalr_addr),
.I2(jal_addr),
.I3(jal_addr),
.s(EX_MEM_pc_src),
.branch(EX_MEM_branch),
.b_type(EX_MEM_b_type),
.alu_res(EX_MEM_alu_result),
.o(pc_next)
);

// assign pc_next = pc + 4;

//--------------------WB--------------------//

Mux4x32 mux4x32 (
Expand Down
2 changes: 1 addition & 1 deletion src/CoreSim.v
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module CoreSim;

initial begin
$dumpvars(0, CoreSim);
#320 $finish;
#1000 $finish;
end

initial begin
Expand Down
14 changes: 10 additions & 4 deletions src/components/Control.v
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ module Control (
output reg mem_write, // write RAM or not
output reg branch, // is branch or not
output reg b_type, // 1 -> beq, 0 -> bne
output reg auipc // is auipc or not
output reg auipc, // is auipc or not
output reg mem_read,
output reg jump
);
`include "AluOp.vh"
always @(*) begin
Expand All @@ -25,11 +27,13 @@ module Control (
branch = 0;
b_type = 0;
auipc = 0;
mem_read = 0;
jump = 0;

case (op_code)
7'b0000011: begin // lw
reg_write = 1; alu_src_b = 1; alu_op = ADD;
mem_to_reg = 2'b11;
mem_to_reg = 2'b11; mem_read = 1;
end
7'b0100011: begin // sw
alu_src_b = 1; alu_op = ADD; mem_write = 1;
Expand All @@ -51,9 +55,11 @@ module Control (
end
7'b1100011: begin // bne beq
alu_op = XOR; branch = 1; b_type = ~funct3[0];
jump = 1;
end
7'b1101111: begin // jal
pc_src = 2'b10; reg_write = 1; mem_to_reg = 2'b10;
pc_src = 2'b10; reg_write = 1; mem_to_reg = 2'b10;
jump = 1;
end
7'b0110111: begin // lui
reg_write = 1; mem_to_reg = 2'b01;
Expand All @@ -67,7 +73,7 @@ module Control (
end
7'b1100111: begin // jalr
pc_src = 2'b01; reg_write = 1; mem_to_reg = 2'b10;
alu_src_b = 1;
alu_src_b = 1; jump = 1;
end
endcase
end
Expand Down
56 changes: 56 additions & 0 deletions src/components/ForwardingUnit.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
`timescale 1ns / 1ps


module ForwardingUnit(
input [4:0] EX_MEM_rd,
input [4:0] MEM_WB_rd,
input [4:0] ID_EX_rs1,
input [4:0] ID_EX_rs2,
input EX_MEM_reg_write,
input MEM_WB_reg_write,
input [1:0] EX_MEM_mem_to_reg,
input [1:0] MEM_WB_mem_to_reg,
input auipc,
input alu_src_b,
output reg [2:0] ForwardA, // 00 来自寄存器,01 来自 EX/MEM,10 来自 MEM/WB,11 来自 PC
// 100 来自 EX/MEM 的 PC + 4,101 来自 MEM/WB 的 PC + 4
// 110 来自 EX/MEM 的 imm,111 来自 MEM/WB 的 imm
output reg [2:0] ForwardB, // 00 来自寄存器,01 来自 EX/MEM,10 来自 MEM/WB,11 来自 imm
output reg [1:0] ForwardC
);
always @(*) begin
if (auipc) begin
assign ForwardA = 3'b011;
end else begin
if (EX_MEM_reg_write == 1 && EX_MEM_rd != 0 && EX_MEM_rd == ID_EX_rs1) begin
if (EX_MEM_mem_to_reg == 2'b01) assign ForwardA = 3'b110;
else if (EX_MEM_mem_to_reg == 2'b10) assign ForwardA = 3'b100;
else assign ForwardA = 3'b001;
end else if (MEM_WB_reg_write == 1 && MEM_WB_rd != 0 && MEM_WB_rd == ID_EX_rs1) begin
if (MEM_WB_mem_to_reg == 2'b01) assign ForwardA = 3'b111;
else if (MEM_WB_mem_to_reg == 2'b10) assign ForwardA = 3'b101;
else assign ForwardA = 3'b010;
end else begin
assign ForwardA = 3'b000;
end
end
if (alu_src_b) begin
assign ForwardB = 3'b011;
end else begin
if (EX_MEM_reg_write == 1 && EX_MEM_rd != 0 && EX_MEM_rd == ID_EX_rs2) begin
if (EX_MEM_mem_to_reg == 2'b01) assign ForwardB = 3'b110;
else if (EX_MEM_mem_to_reg == 2'b10) assign ForwardB = 3'b100;
else assign ForwardB = 3'b001;
end else if (MEM_WB_reg_write == 1 && MEM_WB_rd != 0 && MEM_WB_rd == ID_EX_rs2) begin
if (MEM_WB_mem_to_reg == 2'b01) assign ForwardB = 3'b111;
else if (MEM_WB_mem_to_reg == 2'b10) assign ForwardB = 3'b101;
else assign ForwardB = 3'b010;
end else begin
assign ForwardB = 3'b000;
end
end
if (EX_MEM_reg_write && EX_MEM_rd != 0 && EX_MEM_rd == ID_EX_rs2) assign ForwardC = 2'b01;
else if (MEM_WB_reg_write && MEM_WB_rd != 0 && MEM_WB_rd == ID_EX_rs2) assign ForwardC = 2'b01;
else assign ForwardC = 2'b00;
end
endmodule
2 changes: 1 addition & 1 deletion src/components/Regs.v
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module Regs (
assign read_data_2 = (read_addr_2 == 0) ? 0 : register[read_addr_2]; // read
assign debug_reg = (debug_reg_addr == 0) ? 0 : register[debug_reg_addr];

always @(posedge clk or posedge rst) begin
always @(negedge clk or posedge rst) begin
if (rst == 1) for (i = 1; i < 32; i = i + 1) register[i] <= 0; // reset
else if (we == 1 && write_addr != 0) register[write_addr] <= write_data;
end
Expand Down
13 changes: 13 additions & 0 deletions src/components/StallUnit.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
`timescale 1ns / 1ps

module StallUnit(
input ID_EX_mem_read,
input [4:0] ID_EX_rd,
input [4:0] IF_ID_rs1,
input [4:0] IF_ID_rs2,
input jump,
input ID_EX_reg_write,
output bubble_stop
);
assign bubble_stop = (ID_EX_mem_read && (ID_EX_rd == IF_ID_rs1 || ID_EX_rd == IF_ID_rs2)) || (jump && ID_EX_reg_write && ID_EX_rd != 0 && (ID_EX_rd == IF_ID_rs1 || ID_EX_rd == IF_ID_rs2));
endmodule
Loading

0 comments on commit 56e108c

Please sign in to comment.