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

Commit a9cdb2b

Browse files
committed
feat: single cycle CPU with privileged ISA
1 parent bfbed38 commit a9cdb2b

File tree

21 files changed

+1368
-21
lines changed

21 files changed

+1368
-21
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
.DS_Store
22

33
src/core.vvp
4-
src/dump.vcd
5-
src/wave.gtkw
4+
src/dump.vcd

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
系统贯通课程会逐步实现一个 RISC-V 五级流水线 CPU,并实现异常处理、分支预测、Cache 等功能。本 repo 通过分支、tag 等来记录实验进度,保存各阶段成果。
1010

1111
- [x] 系统 Ⅰ lab5-1/lab5-2:单周期 CPU
12-
- [ ] extra:单周期 CPU with 特权指令/异常处理
12+
- [x] extra:单周期 CPU with 特权指令/异常处理
1313
- [ ] 系统 Ⅱ lab1:流水线 CPU (stall)
1414
- [ ] 系统 Ⅱ lab2:流水线 CPU (forwarding)
1515
- [ ] 系统 Ⅱ lab7:流水线 CPU with 特权指令/异常处理

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-
#220 $finish;
15+
#520000 $finish;
1616
end
1717

1818
initial begin

src/SCPU.v

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@ module SCPU(
1313
output [31:0] debug_reg
1414
);
1515
wire [3:0] alu_op;
16-
wire [1:0] pc_src, mem_to_reg;
16+
wire [1:0] pc_src;
17+
wire [2:0] mem_to_reg;
1718
wire reg_write, alu_src, branch, b_type, auipc;
19+
wire [1:0] trap;
20+
wire [11:0] csr_read_addr, csr_write_addr;
21+
wire csr_write, csr_write_src, rev_imm;
1822

1923
Control control (
2024
.op_code(inst[6:0]),
2125
.funct3(inst[14:12]),
2226
.funct7_5(inst[30]),
27+
.csr(inst[31:20]),
2328
.pc_src(pc_src), // 2'b00 表示pc的数据来自pc+4, 2'b01 表示数据来自JALR跳转地址, 2'b10表示数据来自JAL跳转地址(包括branch). branch 跳转根据条件决定
2429
.reg_write(reg_write), // 1'b1 表示写寄存器
2530
.alu_src_b(alu_src_b), // 1'b1 表示ALU B口的数据源来自imm, 1'b0表示数据来自Reg[rs2]
@@ -28,7 +33,13 @@ module SCPU(
2833
.mem_write(mem_write), // 1'b1 表示写data memory, 1'b0表示读data memory
2934
.branch(branch), // 1'b1 表示是branch类型的指令
3035
.b_type(b_type), // 1'b1 表示beq, 1'b0 表示bne
31-
.auipc(auipc)
36+
.auipc(auipc),
37+
.trap(trap),
38+
.csr_read_addr(csr_read_addr),
39+
.csr_write_addr(csr_write_addr),
40+
.csr_write(csr_write),
41+
.csr_write_src(csr_write_src),
42+
.rev_imm(rev_imm)
3243
);
3344

3445
Datapath datapath (
@@ -48,7 +59,13 @@ module SCPU(
4859
.data_out(data_out),
4960
.pc_out(pc_out),
5061
.debug_reg_addr(debug_reg_addr),
51-
.debug_reg(debug_reg)
62+
.debug_reg(debug_reg),
63+
.trap(trap),
64+
.csr_read_addr(csr_read_addr),
65+
.csr_write_addr(csr_write_addr),
66+
.csr_write(csr_write),
67+
.csr_write_src(csr_write_src),
68+
.rev_imm(rev_imm)
5269
);
5370

5471
endmodule

src/components/CSRs.v

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
`timescale 1ns / 1ps
2+
3+
module CSRs (
4+
input clk,
5+
input rst,
6+
input we,
7+
input [1:0] trap, // 00 no trap, 01 ecall, 10 unimp
8+
input [31:0] pc,
9+
input [11:0] csr_read_addr,
10+
input [11:0] csr_write_addr,
11+
input [31:0] csr_write_data,
12+
output [31:0] csr_read_data
13+
);
14+
reg [31:0] mstatus, mepc, mtvec, mcause;
15+
16+
assign csr_read_data = (csr_read_addr == 12'h300) ? mstatus :
17+
(csr_read_addr == 12'h341) ? mepc :
18+
(csr_read_addr == 12'h305) ? mtvec :
19+
(csr_read_addr == 12'h342) ? mcause : 0;
20+
21+
always @(negedge clk or posedge rst) begin
22+
if (rst == 1) begin
23+
mstatus <= 0;
24+
mepc <= 0;
25+
mtvec <= 0;
26+
mcause <= 0;
27+
end
28+
else if (trap != 0) begin
29+
if (trap == 2'b01) begin
30+
mepc <= pc;
31+
mcause <= 11;
32+
end
33+
else if (trap == 2'b10) begin
34+
mepc <= pc;
35+
mcause <= 2;
36+
end
37+
end
38+
else if (we == 1) begin
39+
if (csr_write_addr == 12'h300) mstatus <= csr_write_data;
40+
else if (csr_write_addr == 12'h341) mepc <= csr_write_data;
41+
else if (csr_write_addr == 12'h305) mtvec <= csr_write_data;
42+
else if (csr_write_addr == 12'h342) mcause <= csr_write_data;
43+
end
44+
end
45+
endmodule

src/components/Control.v

Lines changed: 90 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,22 @@ module Control (
44
input [6:0] op_code,
55
input [2:0] funct3,
66
input funct7_5,
7+
input [11:0] csr,
78
output reg [1:0] pc_src, // 00 pc+4 01 JALR 10 JAL
89
output reg reg_write, // write register or not
910
output reg alu_src_b, // 0 -> from register, 1 -> from imm
1011
output reg [3:0] alu_op, // ALUop
11-
output reg [1:0] mem_to_reg, // 00 -> ALU, 01 -> imm, 10 -> pc+4, 11 -> RAM
12+
output reg [2:0] mem_to_reg, // 00 -> ALU, 01 -> imm, 10 -> pc+4, 11 -> RAM
1213
output reg mem_write, // write RAM or not
1314
output reg branch, // is branch or not
1415
output reg b_type, // 1 -> beq, 0 -> bne
15-
output reg auipc // is auipc or not
16+
output reg auipc, // is auipc or not
17+
output reg [1:0] trap, // 00 no trap, 01 ecall, 10 unimp
18+
output reg [11:0] csr_read_addr,
19+
output reg [11:0] csr_write_addr,
20+
output reg csr_write,
21+
output reg csr_write_src,
22+
output reg rev_imm
1623
);
1724
`include "AluOp.vh"
1825
always @(*) begin
@@ -25,11 +32,17 @@ module Control (
2532
branch = 0;
2633
b_type = 0;
2734
auipc = 0;
35+
trap = 0;
36+
csr_write = 0;
37+
rev_imm = 0;
38+
csr_read_addr = 0;
39+
csr_write_addr = 0;
40+
csr_write_src = 0;
2841

2942
case (op_code)
3043
7'b0000011: begin // lw
3144
reg_write = 1; alu_src_b = 1; alu_op = ADD;
32-
mem_to_reg = 2'b11;
45+
mem_to_reg = 3'b011;
3346
end
3447
7'b0100011: begin // sw
3548
alu_src_b = 1; alu_op = ADD; mem_write = 1;
@@ -51,12 +64,20 @@ module Control (
5164
end
5265
7'b1100011: begin // bne beq
5366
alu_op = XOR; branch = 1; b_type = ~funct3[0];
67+
case (funct3)
68+
3'b000: begin alu_op = XOR; b_type = 1; end // beq
69+
3'b001: begin alu_op = XOR; b_type = 0; end // bne
70+
3'b100: begin alu_op = SLT; b_type = 0; end // blt
71+
3'b101: begin alu_op = SLT; b_type = 1; end // bge
72+
3'b110: begin alu_op = SLTU; b_type = 0; end // bltu
73+
3'b111: begin alu_op = SLTU; b_type = 1; end // bgeu
74+
endcase
5475
end
5576
7'b1101111: begin // jal
56-
pc_src = 2'b10; reg_write = 1; mem_to_reg = 2'b10;
77+
pc_src = 2'b10; reg_write = 1; mem_to_reg = 3'b010;
5778
end
5879
7'b0110111: begin // lui
59-
reg_write = 1; mem_to_reg = 2'b01;
80+
reg_write = 1; mem_to_reg = 3'b001;
6081
end
6182
7'b0110011: begin // add slt and or sll srl sltu
6283
reg_write = 1;
@@ -66,8 +87,70 @@ module Control (
6687
auipc = 1;
6788
end
6889
7'b1100111: begin // jalr
69-
pc_src = 2'b01; reg_write = 1; mem_to_reg = 2'b10;
70-
alu_src_b = 1; alu_op = ADD;
90+
pc_src = 2'b01; reg_write = 1; mem_to_reg = 3'b010;
91+
alu_src_b = 1;
92+
end
93+
7'b1110011: begin
94+
case (funct3)
95+
3'b000: begin
96+
case (csr)
97+
12'b000000000000: begin // ecall
98+
trap = 2'b01; csr_read_addr = 12'h305;
99+
pc_src = 2'b11;
100+
end
101+
12'b001100000010: begin // mret
102+
trap = 2'b11;
103+
csr_read_addr = 12'h341; pc_src = 2'b11;
104+
end
105+
default: begin
106+
trap = 2'b10; csr_read_addr = 12'h305;
107+
pc_src = 2'b11;
108+
end
109+
endcase
110+
end
111+
3'b001: begin // csrrw **Note**: Just implement for csrw and csrr
112+
if (csr != 12'h300 && csr != 12'h341 && csr != 12'h305 && csr != 12'h342) begin
113+
trap = 2'b10; csr_read_addr = 12'h305;
114+
pc_src = 2'b11;
115+
end else begin
116+
csr_write = 1; csr_read_addr = csr;
117+
csr_write_addr = csr; csr_write_src = 0;
118+
reg_write = 1; mem_to_reg = 3'b100;
119+
end
120+
end
121+
3'b010: begin // csrrs
122+
if (csr != 12'h300 && csr != 12'h341 && csr != 12'h305 && csr != 12'h342) begin
123+
trap = 2'b10; csr_read_addr = 12'h305;
124+
pc_src = 2'b11;
125+
end else begin
126+
// csr_write = 1; csr_read_addr = imm[11:0];
127+
// csr_write_addr = imm[11:0]; csr_write_src = 1;
128+
// alu_op = OR; alu_src_b = 2'b10;
129+
// reg_write = 1; mem_to_reg = 3'b100;
130+
csr_write = 0; csr_read_addr = csr; // csrr
131+
reg_write = 1; mem_to_reg = 3'b100;
132+
end
133+
end
134+
3'b011: begin // csrrc
135+
csr_write = 1; csr_read_addr = csr;
136+
csr_write_addr = csr; csr_write_src = 1;
137+
alu_op = AND; alu_src_b = 2'b10; rev_imm = 1;
138+
reg_write = 1; mem_to_reg = 3'b100;
139+
end
140+
3'b101: begin // csrrwi
141+
142+
end
143+
3'b110: begin // csrrsi
144+
145+
end
146+
3'b111: begin // csrrci
147+
148+
end
149+
endcase
150+
end
151+
default: begin
152+
trap = 2'b10; csr_read_addr = 12'h305;
153+
pc_src = 2'b11;
71154
end
72155
endcase
73156
end

src/components/Datapath.v

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,20 @@ module Datapath(
1010
input b_type, // 0 -> bne, 1 -> beq
1111
input auipc, // whether auipc or not
1212
input [3:0] alu_op, // ALU operation
13-
input [1:0] mem_to_reg, // 00 -> from ALU, 01 -> from imm, 10 -> from pc+4, 11 -> from RAM
13+
input [2:0] mem_to_reg, // 00 -> from ALU, 01 -> from imm, 10 -> from pc+4, 11 -> from RAM
1414
input [31:0] inst_in, // now instruction
1515
input [31:0] data_in, // data from data memory
1616
output [31:0] addr_out, // data memory address
1717
output [31:0] data_out, // data to data memory
1818
output [31:0] pc_out, // connect to instruction memory
1919
input [4:0] debug_reg_addr,
20-
output [31:0] debug_reg
20+
output [31:0] debug_reg,
21+
input [1:0] trap,
22+
input [11:0] csr_read_addr,
23+
input [11:0] csr_write_addr,
24+
input csr_write,
25+
input csr_write_src,
26+
input rev_imm
2127
);
2228
reg [31:0] pc;
2329
wire [31:0] pc_next;
@@ -26,6 +32,7 @@ module Datapath(
2632
wire alu_zero;
2733
wire [31:0] imm;
2834
wire [31:0] jal_addr, jalr_addr;
35+
wire [31:0] csr_read_data, csr_write_data;
2936

3037
assign pc_out = pc;
3138
assign addr_out = alu_result;
@@ -54,6 +61,18 @@ module Datapath(
5461
.debug_reg(debug_reg)
5562
);
5663

64+
CSRs csr (
65+
.clk(clk),
66+
.rst(rst),
67+
.we(csr_write),
68+
.trap(trap),
69+
.pc(pc),
70+
.csr_read_addr(csr_read_addr),
71+
.csr_write_addr(csr_write_addr),
72+
.csr_write_data(read_data_1),
73+
.csr_read_data(csr_read_data)
74+
);
75+
5776
ImmGen immgen (
5877
.inst(inst_in),
5978
.imm(imm)
@@ -81,11 +100,15 @@ module Datapath(
81100
.zero(alu_zero)
82101
);
83102

84-
Mux4x32 mux4x32 (
103+
Mux8x32 mux8x32 (
85104
.I0(alu_result),
86105
.I1(imm),
87106
.I2(pc + 4),
88107
.I3(data_in),
108+
.I4(csr_read_data),
109+
.I5(0),
110+
.I6(0),
111+
.I7(0),
89112
.s(mem_to_reg),
90113
.o(write_data)
91114
);
@@ -97,7 +120,7 @@ module Datapath(
97120
.I0(pc + 4),
98121
.I1(jalr_addr),
99122
.I2(jal_addr),
100-
.I3(jal_addr),
123+
.I3(csr_read_data),
101124
.s(pc_src),
102125
.branch(branch),
103126
.b_type(b_type),

src/memory/ROM.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module ROM (
77
reg [31:0] rom [0:2047];
88

99
initial begin
10-
$readmemh("tests/full.hex", rom);
10+
$readmemh("tests/Priviledged/advance.hex", rom);
1111
end
1212

1313
assign out = rom[address];

0 commit comments

Comments
 (0)