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

Commit 56e108c

Browse files
committed
feat: pipeline CPU with forwarding
1 parent 8e4b730 commit 56e108c

File tree

14 files changed

+394
-62
lines changed

14 files changed

+394
-62
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
- [x] 系统 Ⅰ lab5-1/lab5-2:单周期 CPU
1212
- [x] extra:单周期 CPU with 特权指令/异常处理
1313
- [x] 系统 Ⅱ lab1:流水线 CPU (stall)
14-
- [ ] 系统 Ⅱ lab2:流水线 CPU (forwarding)
14+
- [x] 系统 Ⅱ lab2:流水线 CPU (forwarding)
1515
- [ ] 系统 Ⅱ lab7:流水线 CPU with 特权指令/异常处理
1616
- [ ] 系统 Ⅲ lab1:流水线 CPU with 动态分支预测
1717
- [ ] 系统 Ⅲ lab2:流水线 CPU with Cache

src/CPU.v

Lines changed: 130 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,21 @@ module CPU(
2222
wire [3:0] alu_op;
2323
wire [1:0] pc_src, mem_to_reg;
2424
wire reg_write, alu_src, branch, b_type, auipc, mem_write_;
25+
wire mem_read, bubble_stop, jump;
2526
reg [31:0] ID_EX_data1, ID_EX_data2;
2627
reg [31:0] ID_EX_pc, ID_EX_imm;
28+
reg [4:0] ID_EX_rs1, ID_EX_rs2;
2729
reg [4:0] ID_EX_write_addr;
2830
reg [3:0] ID_EX_alu_op;
2931
reg [1:0] ID_EX_pc_src, ID_EX_mem_to_reg;
3032
reg ID_EX_reg_write, ID_EX_alu_src, ID_EX_branch, ID_EX_b_type, ID_EX_auipc, ID_EX_mem_write;
33+
reg ID_EX_mem_read;
3134

3235
wire [31:0] alu_data1, alu_data2, alu_result;
3336
wire alu_zero;
37+
wire [2:0] forwardA, forwardB;
38+
wire [1:0] forwardC;
39+
wire [31:0] ex_mem_data2;
3440
reg [31:0] EX_MEM_alu_result, EX_MEM_pc, EX_MEM_imm;
3541
reg [31:0] EX_MEM_data2;
3642
reg [4:0] EX_MEM_write_addr;
@@ -66,6 +72,9 @@ module CPU(
6672
ID_EX_b_type <= 1'b0;
6773
ID_EX_auipc <= 1'b0;
6874
ID_EX_mem_write <= 1'b0;
75+
ID_EX_mem_read <= 1'b0;
76+
ID_EX_rs1 <= 5'b0;
77+
ID_EX_rs2 <= 5'b0;
6978
EX_MEM_alu_result <= 32'b0;
7079
EX_MEM_pc <= 32'b0;
7180
EX_MEM_imm <= 32'b0;
@@ -85,30 +94,63 @@ module CPU(
8594
MEM_WB_mem_to_reg <= 2'b0;
8695
MEM_WB_reg_write <= 1'b0;
8796
end
88-
else begin
89-
pc <= pc_next;
97+
else begin
98+
if (bubble_stop) begin
99+
ID_EX_alu_op <= 4'b0;
100+
ID_EX_pc_src <= 2'b0;
101+
ID_EX_mem_to_reg <= 2'b0;
102+
ID_EX_reg_write <= 1'b0;
103+
ID_EX_alu_src <= 1'b0;
104+
ID_EX_branch <= 1'b0;
105+
ID_EX_b_type <= 1'b0;
106+
ID_EX_auipc <= 1'b0;
107+
ID_EX_mem_write <= 1'b0;
108+
ID_EX_mem_read <= 1'b0;
109+
end else if (jump) begin
110+
pc <= pc_next;
90111

91-
IF_ID_pc <= pc;
92-
IF_ID_inst <= inst;
112+
IF_ID_pc <= pc;
113+
IF_ID_inst <= 32'h00000013;
114+
115+
ID_EX_pc_src <= pc_src;
116+
ID_EX_mem_to_reg <= mem_to_reg;
117+
ID_EX_reg_write <= reg_write;
118+
ID_EX_alu_src <= alu_src;
119+
ID_EX_branch <= branch;
120+
ID_EX_b_type <= b_type;
121+
ID_EX_auipc <= auipc;
122+
ID_EX_alu_op <= alu_op;
123+
ID_EX_mem_write <= mem_write_;
124+
ID_EX_mem_read <= mem_read;
125+
end else begin
126+
pc <= pc_next;
93127

128+
IF_ID_pc <= pc;
129+
IF_ID_inst <= inst;
130+
131+
ID_EX_pc_src <= pc_src;
132+
ID_EX_mem_to_reg <= mem_to_reg;
133+
ID_EX_reg_write <= reg_write;
134+
ID_EX_alu_src <= alu_src;
135+
ID_EX_branch <= branch;
136+
ID_EX_b_type <= b_type;
137+
ID_EX_auipc <= auipc;
138+
ID_EX_alu_op <= alu_op;
139+
ID_EX_mem_write <= mem_write_;
140+
ID_EX_mem_read <= mem_read;
141+
end
142+
94143
ID_EX_pc <= IF_ID_pc;
95144
ID_EX_data1 <= read_data1;
96145
ID_EX_data2 <= read_data2;
97146
ID_EX_imm <= imm;
98147
ID_EX_write_addr <= IF_ID_inst[11:7];
99-
ID_EX_pc_src <= pc_src;
100-
ID_EX_mem_to_reg <= mem_to_reg;
101-
ID_EX_reg_write <= reg_write;
102-
ID_EX_alu_src <= alu_src;
103-
ID_EX_branch <= branch;
104-
ID_EX_b_type <= b_type;
105-
ID_EX_auipc <= auipc;
106-
ID_EX_alu_op <= alu_op;
107-
ID_EX_mem_write <= mem_write_;
148+
ID_EX_rs1 <= IF_ID_inst[19:15];
149+
ID_EX_rs2 <= IF_ID_inst[24:20];
108150

109151
EX_MEM_pc <= ID_EX_pc;
110152
EX_MEM_imm <= ID_EX_imm;
111-
EX_MEM_data2 <= ID_EX_data2;
153+
EX_MEM_data2 <= ex_mem_data2;
112154
EX_MEM_alu_result <= alu_result;
113155
EX_MEM_write_addr <= ID_EX_write_addr;
114156
EX_MEM_pc_src <= ID_EX_pc_src;
@@ -131,6 +173,34 @@ module CPU(
131173

132174
//--------------------ID--------------------//
133175

176+
StallUnit stallunit (
177+
.ID_EX_mem_read(ID_EX_mem_read),
178+
.ID_EX_rd(ID_EX_write_addr),
179+
.IF_ID_rs1(IF_ID_inst[19:15]),
180+
.IF_ID_rs2(IF_ID_inst[24:20]),
181+
.jump(jump),
182+
.ID_EX_reg_write(ID_EX_reg_write),
183+
.bubble_stop(bubble_stop)
184+
);
185+
186+
assign jal_addr = IF_ID_pc + imm;
187+
wire [31:0] reg1, reg2;
188+
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;
189+
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;
190+
assign jalr_addr = reg1 + reg2;
191+
192+
MuxPC mux_pc (
193+
.I0(jump ? pc : pc + 4),
194+
.I1(jalr_addr),
195+
.I2(jal_addr),
196+
.I3(jal_addr),
197+
.s(pc_src),
198+
.branch(branch),
199+
.b_type(b_type),
200+
.alu_res(reg1 ^ reg2),
201+
.o(pc_next)
202+
);
203+
134204
Regs regs (
135205
.clk(clk),
136206
.rst(rst),
@@ -157,7 +227,9 @@ module CPU(
157227
.branch(branch),
158228
.b_type(b_type),
159229
.mem_write(mem_write_),
160-
.auipc(auipc)
230+
.auipc(auipc),
231+
.mem_read(mem_read),
232+
.jump(jump)
161233
);
162234

163235
ImmGen immgen (
@@ -167,17 +239,45 @@ module CPU(
167239

168240
//--------------------EX--------------------//
169241

170-
Mux2x32 mux2x32_1 (
242+
ForwardingUnit forwarding (
243+
.EX_MEM_rd(EX_MEM_write_addr),
244+
.MEM_WB_rd(MEM_WB_write_addr),
245+
.ID_EX_rs1(ID_EX_rs1),
246+
.ID_EX_rs2(ID_EX_rs2),
247+
.EX_MEM_reg_write(EX_MEM_reg_write),
248+
.MEM_WB_reg_write(MEM_WB_reg_write),
249+
.EX_MEM_mem_to_reg(EX_MEM_mem_to_reg),
250+
.MEM_WB_mem_to_reg(MEM_WB_mem_to_reg),
251+
.auipc(ID_EX_auipc),
252+
.alu_src_b(ID_EX_alu_src),
253+
.ForwardA(forwardA),
254+
.ForwardB(forwardB),
255+
.ForwardC(forwardC)
256+
);
257+
258+
Mux8x32 mux_alu_a (
171259
.I0(ID_EX_data1),
172-
.I1(ID_EX_pc),
173-
.s(ID_EX_auipc),
260+
.I1(EX_MEM_alu_result),
261+
.I2(write_data),
262+
.I3(ID_EX_pc),
263+
.I4(EX_MEM_pc + 4),
264+
.I5(MEM_WB_pc + 4),
265+
.I6(EX_MEM_imm),
266+
.I7(MEM_WB_imm),
267+
.s(forwardA),
174268
.o(alu_data1)
175269
);
176270

177-
Mux2x32 mux2x32_2 (
271+
Mux8x32 mux_alu_b (
178272
.I0(ID_EX_data2),
179-
.I1(ID_EX_imm),
180-
.s(ID_EX_alu_src),
273+
.I1(EX_MEM_alu_result),
274+
.I2(write_data),
275+
.I3(ID_EX_imm),
276+
.I4(EX_MEM_pc + 4),
277+
.I5(MEM_WB_pc + 4),
278+
.I6(EX_MEM_imm),
279+
.I7(MEM_WB_imm),
280+
.s(forwardB),
181281
.o(alu_data2)
182282
);
183283

@@ -189,28 +289,20 @@ module CPU(
189289
.zero(alu_zero)
190290
);
191291

292+
Mux4x32 mux_data2 (
293+
.I0(ID_EX_data2),
294+
.I1(EX_MEM_alu_result),
295+
.I2(write_data),
296+
.I3(32'h00000000),
297+
.s(forwardC),
298+
.o(ex_mem_data2)
299+
);
300+
192301
//--------------------MEM--------------------//
193302
assign addr_out = EX_MEM_alu_result;
194303
assign data_out = EX_MEM_data2;
195304
assign mem_write = EX_MEM_mem_write;
196305

197-
assign jal_addr = EX_MEM_pc + EX_MEM_imm;
198-
assign jalr_addr = EX_MEM_alu_result;
199-
200-
MuxPC mux_pc (
201-
.I0(pc + 4),
202-
.I1(jalr_addr),
203-
.I2(jal_addr),
204-
.I3(jal_addr),
205-
.s(EX_MEM_pc_src),
206-
.branch(EX_MEM_branch),
207-
.b_type(EX_MEM_b_type),
208-
.alu_res(EX_MEM_alu_result),
209-
.o(pc_next)
210-
);
211-
212-
// assign pc_next = pc + 4;
213-
214306
//--------------------WB--------------------//
215307

216308
Mux4x32 mux4x32 (

src/CoreSim.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ module CoreSim;
1212

1313
initial begin
1414
$dumpvars(0, CoreSim);
15-
#320 $finish;
15+
#1000 $finish;
1616
end
1717

1818
initial begin

src/components/Control.v

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ module Control (
1212
output reg mem_write, // write RAM or not
1313
output reg branch, // is branch or not
1414
output reg b_type, // 1 -> beq, 0 -> bne
15-
output reg auipc // is auipc or not
15+
output reg auipc, // is auipc or not
16+
output reg mem_read,
17+
output reg jump
1618
);
1719
`include "AluOp.vh"
1820
always @(*) begin
@@ -25,11 +27,13 @@ module Control (
2527
branch = 0;
2628
b_type = 0;
2729
auipc = 0;
30+
mem_read = 0;
31+
jump = 0;
2832

2933
case (op_code)
3034
7'b0000011: begin // lw
3135
reg_write = 1; alu_src_b = 1; alu_op = ADD;
32-
mem_to_reg = 2'b11;
36+
mem_to_reg = 2'b11; mem_read = 1;
3337
end
3438
7'b0100011: begin // sw
3539
alu_src_b = 1; alu_op = ADD; mem_write = 1;
@@ -51,9 +55,11 @@ module Control (
5155
end
5256
7'b1100011: begin // bne beq
5357
alu_op = XOR; branch = 1; b_type = ~funct3[0];
58+
jump = 1;
5459
end
5560
7'b1101111: begin // jal
56-
pc_src = 2'b10; reg_write = 1; mem_to_reg = 2'b10;
61+
pc_src = 2'b10; reg_write = 1; mem_to_reg = 2'b10;
62+
jump = 1;
5763
end
5864
7'b0110111: begin // lui
5965
reg_write = 1; mem_to_reg = 2'b01;
@@ -67,7 +73,7 @@ module Control (
6773
end
6874
7'b1100111: begin // jalr
6975
pc_src = 2'b01; reg_write = 1; mem_to_reg = 2'b10;
70-
alu_src_b = 1;
76+
alu_src_b = 1; jump = 1;
7177
end
7278
endcase
7379
end

src/components/ForwardingUnit.v

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
`timescale 1ns / 1ps
2+
3+
4+
module ForwardingUnit(
5+
input [4:0] EX_MEM_rd,
6+
input [4:0] MEM_WB_rd,
7+
input [4:0] ID_EX_rs1,
8+
input [4:0] ID_EX_rs2,
9+
input EX_MEM_reg_write,
10+
input MEM_WB_reg_write,
11+
input [1:0] EX_MEM_mem_to_reg,
12+
input [1:0] MEM_WB_mem_to_reg,
13+
input auipc,
14+
input alu_src_b,
15+
output reg [2:0] ForwardA, // 00 来自寄存器,01 来自 EX/MEM,10 来自 MEM/WB,11 来自 PC
16+
// 100 来自 EX/MEM 的 PC + 4,101 来自 MEM/WB 的 PC + 4
17+
// 110 来自 EX/MEM 的 imm,111 来自 MEM/WB 的 imm
18+
output reg [2:0] ForwardB, // 00 来自寄存器,01 来自 EX/MEM,10 来自 MEM/WB,11 来自 imm
19+
output reg [1:0] ForwardC
20+
);
21+
always @(*) begin
22+
if (auipc) begin
23+
assign ForwardA = 3'b011;
24+
end else begin
25+
if (EX_MEM_reg_write == 1 && EX_MEM_rd != 0 && EX_MEM_rd == ID_EX_rs1) begin
26+
if (EX_MEM_mem_to_reg == 2'b01) assign ForwardA = 3'b110;
27+
else if (EX_MEM_mem_to_reg == 2'b10) assign ForwardA = 3'b100;
28+
else assign ForwardA = 3'b001;
29+
end else if (MEM_WB_reg_write == 1 && MEM_WB_rd != 0 && MEM_WB_rd == ID_EX_rs1) begin
30+
if (MEM_WB_mem_to_reg == 2'b01) assign ForwardA = 3'b111;
31+
else if (MEM_WB_mem_to_reg == 2'b10) assign ForwardA = 3'b101;
32+
else assign ForwardA = 3'b010;
33+
end else begin
34+
assign ForwardA = 3'b000;
35+
end
36+
end
37+
if (alu_src_b) begin
38+
assign ForwardB = 3'b011;
39+
end else begin
40+
if (EX_MEM_reg_write == 1 && EX_MEM_rd != 0 && EX_MEM_rd == ID_EX_rs2) begin
41+
if (EX_MEM_mem_to_reg == 2'b01) assign ForwardB = 3'b110;
42+
else if (EX_MEM_mem_to_reg == 2'b10) assign ForwardB = 3'b100;
43+
else assign ForwardB = 3'b001;
44+
end else if (MEM_WB_reg_write == 1 && MEM_WB_rd != 0 && MEM_WB_rd == ID_EX_rs2) begin
45+
if (MEM_WB_mem_to_reg == 2'b01) assign ForwardB = 3'b111;
46+
else if (MEM_WB_mem_to_reg == 2'b10) assign ForwardB = 3'b101;
47+
else assign ForwardB = 3'b010;
48+
end else begin
49+
assign ForwardB = 3'b000;
50+
end
51+
end
52+
if (EX_MEM_reg_write && EX_MEM_rd != 0 && EX_MEM_rd == ID_EX_rs2) assign ForwardC = 2'b01;
53+
else if (MEM_WB_reg_write && MEM_WB_rd != 0 && MEM_WB_rd == ID_EX_rs2) assign ForwardC = 2'b01;
54+
else assign ForwardC = 2'b00;
55+
end
56+
endmodule

src/components/Regs.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module Regs (
2525
assign read_data_2 = (read_addr_2 == 0) ? 0 : register[read_addr_2]; // read
2626
assign debug_reg = (debug_reg_addr == 0) ? 0 : register[debug_reg_addr];
2727

28-
always @(posedge clk or posedge rst) begin
28+
always @(negedge clk or posedge rst) begin
2929
if (rst == 1) for (i = 1; i < 32; i = i + 1) register[i] <= 0; // reset
3030
else if (we == 1 && write_addr != 0) register[write_addr] <= write_data;
3131
end

src/components/StallUnit.v

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
`timescale 1ns / 1ps
2+
3+
module StallUnit(
4+
input ID_EX_mem_read,
5+
input [4:0] ID_EX_rd,
6+
input [4:0] IF_ID_rs1,
7+
input [4:0] IF_ID_rs2,
8+
input jump,
9+
input ID_EX_reg_write,
10+
output bubble_stop
11+
);
12+
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));
13+
endmodule

0 commit comments

Comments
 (0)