Skip to content

Commit ea5a6e6

Browse files
authored
Merge pull request #10 from quantumxiaol/CPU_Sample
添加指令
2 parents b2dd7db + 205dd40 commit ea5a6e6

6 files changed

Lines changed: 132 additions & 35 deletions

File tree

Sample/EX.v

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
`include "lib/defines.vh"
2+
// 执行运算或计算地址(反正就是和ALU相关)
3+
// 从ID/EX流水线寄存器中读取由寄存器1传过来的值和寄存器2传过来的值
4+
// (或寄存器1传过来的值和符号扩展过后的立即数的值),
5+
// 并用ALU将它们相加,结果值存入EX/MEM流水线寄存器。
26
module EX(
37
input wire clk,
48
input wire rst,

Sample/ID.v

Lines changed: 114 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
`include "lib/defines.vh"
2+
// 指令解码,同时读取寄存器
3+
// IF/ID阶段可能会取出经符号扩展为32位的立即数和两个从寄存器中读取的数,放入ID/EX流水线寄存器
24
module ID(
35
input wire clk,
46
input wire rst,
@@ -86,9 +88,9 @@ module ID(
8688
wire [15:0] imm;
8789
wire [25:0] instr_index;
8890
wire [19:0] code;
89-
wire [4:0] base;
90-
wire [15:0] offset;
91-
wire [2:0] sel;
91+
wire [4:0] base;//基址
92+
wire [15:0] offset;//偏移
93+
wire [2:0] sel;//选择信号
9294

9395
wire [63:0] op_d, func_d;
9496
wire [31:0] rs_d, rt_d, rd_d, sa_d;
@@ -143,72 +145,148 @@ module ID(
143145
assign offset = inst[15:0];
144146
assign sel = inst[2:0];
145147

146-
wire inst_ori, inst_lui, inst_addiu, inst_beq;
147-
wire inst_subu, inst_jr, inst_jal, inst_addu;
148-
wire inst_bne, inst_sll, inst_or, inst_xor , inst_lw, inst_sw;
149-
wire inst_sltiu, inst_lb, inst_lbu, inst_lh;
150-
wire inst_lhu, inst_sb, inst_sh;
151-
wire inst_add, inst_addi;
152-
wire inst_sub, inst_slt, inst_slti, inst_sltu;
148+
// 算术运算指令
149+
wire inst_addu; // 将寄存器 rs 的值与寄存器 rt 的值相加,结果写入 rd 寄存器中。
150+
wire inst_addiu;// 将寄存器 rs 的值与有符号扩展 至 32 位的立即数 imm 相加,结果写入 rt 寄存器中。
151+
wire inst_add; // 将寄存器 rs 的值与寄存器 rt 的值相加,结果写入寄存器 rd 中。
152+
// 如果产生溢出,则触发整型溢出例外(IntegerOverflow)。
153+
wire inst_addi; // 将寄存器 rs 的值与有符号扩展至 32 位的立即数 imm 相加,结果写入 rt 寄存器中。
154+
// 如果产生溢出,则触发整型溢出例外(IntegerOverflow)。
155+
156+
157+
wire inst_sub; //将寄存器 rs 的值与寄存器 rt 的值相减,结果写入 rd 寄存器中。
158+
// 如果产生溢出,则触发整型溢出例外(IntegerOverflow)。
159+
wire inst_subu; // 将寄存器 rs 的值与寄存器 rt 的值相减,结果写入 rd 寄存器中。
160+
161+
162+
wire inst_slt; //将寄存器 rs 的值与寄存器 rt 中的值进行有符号数比较,
163+
// 如果寄存器 rs 中的值小,则寄存器 rd 置 1;否则寄存器 rd 置 0。
164+
wire inst_slti; //将寄存器 rs 的值与有符号扩展至 32 位的立即数 imm 进行有符号数比较,
165+
// 如果寄存器 rs 中的值小,则寄存器 rt 置 1;否则寄存器 rt 置 0。
166+
wire inst_sltu; // 将寄存器 rs 的值与寄存器 rt 中的值进行无符号数比较,
167+
// 如果寄存器 rs 中的值小,则寄存器 rd 置 1;否则寄存器 rd 置 0。
168+
wire inst_sltiu;// 将寄存器 rs 的值与有符号扩展至 32 位的立即数 imm 进行无符号数比较,
169+
// 如果寄存器 rs 中的值小,则寄存器 rt 置 1;否则寄存器 rt 置 0。
170+
171+
// 逻辑运算指令
172+
wire inst_ori; // 寄存器 rs 中的值与 0 扩展至 32 位的立即数 imm 按位逻辑或,结果写入寄存器 rt 中。
173+
wire inst_lui; // 将 16 位立即数 imm 写入寄存器 rt 的高 16 位,寄存器 rt 的低 16 位置 0。
174+
wire inst_or; // 寄存器 rs 中的值与寄存器 rt 中的值按位逻辑或,结果写入寄存器 rd 中。
175+
wire inst_xor; // 寄存器 rs 中的值与 0 扩展至 32 位的立即数 imm 按位逻辑或,结果写入寄存器 rt 中。
176+
177+
178+
// 移位指令
179+
wire inst_sll; // 由立即数 sa 指定移位量,对寄存器 rt 的值进行逻辑左移,结果写入寄存器 rd 中。
180+
181+
// 分支跳转指令
182+
wire inst_beq; // 如果寄存器 rs 的值等于寄存器 rt 的值则转移,否则顺序执行。
183+
// 转移目标由立即数 offset 左移 2 位并进行有符号扩展的值加上该分支指令对应的延迟槽指令的 PC 计算得到。
184+
wire inst_bne; // 如果寄存器 rs 的值不等于寄存器 rt 的值则转移,否则顺序执行。
185+
// 转移目标由立即数 offset 左移 2位并进行有符号扩展的值
186+
// 加上该分支指令对应的延迟槽指令的 PC 计算得到。
187+
wire inst_jr; // 无条件跳转。跳转目标为寄存器 rs 中的值。
188+
wire inst_jal; // 无条件跳转。跳转目标由该分支指令对应的延迟槽指令的 PC 的最高 4 位与立即数 instr_index 左移2 位后的值拼接得到。
189+
// 同时将该分支对应延迟槽指令之后的指令的 PC 值保存至第 31 号通用寄存器中。
190+
191+
//访存指令
192+
wire inst_lw; // 将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址,
193+
// 如果地址不是 4 的整数倍则触发地址错例外,
194+
// 否则据此虚地址从存储器中读取连续 4 个字节的值,写入到 rt 寄存器中。
195+
wire inst_sw; // 将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址,
196+
// 如果地址不是 4 的整数倍则触发地址错例外,
197+
// 否则据此虚地址将 rt 寄存器存入存储器中。
198+
199+
wire inst_lb; // 将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址,
200+
// 据此虚地址从存储器中读取 1 个字节的值并进行符号扩展,写入到 rt 寄存器中。
201+
wire inst_lbu; // 将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址,
202+
// 据此虚地址从存储器中读取 1 个字节的值并进行 0 扩展,写入到 rt 寄存器中。
203+
wire inst_lh; // 将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址,如果地址不是 2 的整数倍
204+
// 则触发地址错例外,否则据此虚地址从存储器中读取连续 2 个字节的值并进行符号扩展,写入到rt 寄存器中。
205+
206+
wire inst_lhu; // 将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址,如果地址不是 2 的整数倍则触发地址错例外,
207+
// 否则据此虚地址从存储器中读取连续 2 个字节的值并进行 0 扩展,写入到 rt寄存器中。
208+
wire inst_sb; // 将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址,据此虚地址将 rt 寄存器的最低字节存入存储器中。
209+
wire inst_sh; // 将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址,如果地址不是 2 的整数倍则触发地址错例外,
210+
// 否则据此虚地址将 rt 寄存器的低半字存入存储器中。
211+
212+
// 数据移动指令
213+
214+
215+
153216

154217
wire op_add, op_sub, op_slt, op_sltu;
155218
wire op_and, op_nor, op_or, op_xor;
156219
wire op_sll, op_srl, op_sra, op_lui;
157220

221+
// 6-64译码器
158222
decoder_6_64 u0_decoder_6_64(
159223
.in (opcode ),
160224
.out (op_d )
161225
);
162226

227+
// 6-64译码器
163228
decoder_6_64 u1_decoder_6_64(
164229
.in (func ),
165230
.out (func_d )
166231
);
167-
232+
233+
// 5-32译码器
168234
decoder_5_32 u0_decoder_5_32(
169235
.in (rs ),
170236
.out (rs_d )
171237
);
172238

239+
// 5-32译码器
173240
decoder_5_32 u1_decoder_5_32(
174241
.in (rt ),
175242
.out (rt_d )
176243
);
177244

178-
179-
assign inst_ori = op_d[6'b00_1101];
180-
assign inst_lui = op_d[6'b00_1111];
245+
// 算术运算指令
181246
assign inst_addiu = op_d[6'b00_1001];
182-
assign inst_beq = op_d[6'b00_0100];
183-
184-
assign inst_subu = op_d[6'b00_0000] & func_d[6'b10_0011];
185-
assign inst_jr = op_d[6'b00_0000] & func_d[6'b00_1000];
186-
assign inst_jal = op_d[6'b00_0011];
187247
assign inst_addu = op_d[6'b00_0000] & func_d[6'b10_0001];
188-
189-
assign inst_bne = op_d[6'b00_0101];
190-
assign inst_sll = op_d[6'b00_0000] & func_d[6'b00_0000];
191-
assign inst_or = op_d[6'b00_0000] & func_d[6'b10_0101];
192-
193-
assign inst_xor = op_d[6'b00_0000] & func_d[6'b10_0110];
194-
assign inst_lw = op_d[6'b10_0011];
195-
assign inst_sw = op_d[6'b10_1011];
196-
197248
assign inst_add = op_d[6'b00_0000] & func_d[6'b10_0000];
198249
assign inst_addi = op_d[6'b00_1000];
250+
199251
assign inst_sub = op_d[6'b00_0000] & func_d[6'b10_0010];
200-
252+
assign inst_subu = op_d[6'b00_0000] & func_d[6'b10_0011];
253+
201254
assign inst_slt = op_d[6'b00_0000] & func_d[6'b10_1010];
202255
assign inst_slti = op_d[6'b00_1010];
203256
assign inst_sltu = op_d[6'b00_0000] & func_d[6'b10_1011];
204257
assign inst_sltiu = op_d[6'b00_1011];
205258

206-
assign inst_lb = 1'b0;
207-
assign inst_lbu = 1'b0;
208-
assign inst_lh = 1'b0;
209-
assign inst_lhu = 1'b0;
210-
assign inst_sb = 1'b0;
211-
assign inst_sh = 1'b0;
259+
// 逻辑运算指令
260+
assign inst_ori = op_d[6'b00_1101];
261+
assign inst_lui = op_d[6'b00_1111];
262+
assign inst_or = op_d[6'b00_0000] & func_d[6'b10_0101];
263+
assign inst_xor = op_d[6'b00_0000] & func_d[6'b10_0110];
264+
265+
// 移位指令
266+
assign inst_sll = op_d[6'b00_0000] & func_d[6'b00_0000];
267+
268+
269+
// 分支跳转指令
270+
assign inst_beq = op_d[6'b00_0100];
271+
assign inst_bne = op_d[6'b00_0101];
272+
assign inst_jr = op_d[6'b00_0000] & func_d[6'b00_1000];
273+
assign inst_jal = op_d[6'b00_0011];
274+
275+
276+
// 访存指令
277+
assign inst_lw = op_d[6'b10_0011];
278+
assign inst_sw = op_d[6'b10_1011];
279+
280+
assign inst_lb = op_d[6'b10_0000];
281+
assign inst_lbu = op_d[6'b10_0100];
282+
assign inst_lh = op_d[6'b10_0001];
283+
assign inst_lhu = op_d[6'b10_0101];
284+
assign inst_sb = op_d[6'b10_1000];
285+
assign inst_sh = op_d[6'b10_1001];
286+
287+
288+
289+
212290

213291
// rs to reg1
214292
assign sel_alu_src1[0] = inst_ori | inst_addiu | inst_subu | inst_jr | inst_addu | inst_or | inst_xor | inst_lw | inst_sw;
@@ -256,6 +334,7 @@ module ID(
256334
// load and store enable
257335
assign data_ram_en = inst_sw|inst_lw;
258336

337+
259338
// write enable
260339
assign data_ram_wen = inst_sw;
261340

Sample/IF.v

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
`include "lib/defines.vh"
2+
// 从内存中取指令
3+
// 使用PC中的地址,从存储器中读取数据,然后将数据放入IF/ID流水线寄存器中。
4+
// PC地址+4然后写回PC以便为下个时钟周期做好准备,
5+
// 增加后的地址同时也存入了IF/ID流水线寄存器以备后面的指令使用。
26
module IF(
37
input wire clk,
48
input wire rst,

Sample/MEM.v

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
`include "lib/defines.vh"
2+
// 访问内存操作
3+
// 可能从EX/MEM流水线寄存器中得到地址读取数据寄存器,并将数据存入MEM/WB流水线寄存器。
24
module MEM(
35
input wire clk,
46
input wire rst,
57
// input wire flush,
68
input wire [`StallBus-1:0] stall,
79

810
input wire [`EX_TO_MEM_WD-1:0] ex_to_mem_bus,
11+
912
input wire [31:0] data_sram_rdata,
13+
1014
input wire [3:0] data_ram_sel,
15+
1116
input wire [`LoadBus-1:0] ex_load_bus,
1217

1318
output wire [`MEM_TO_WB_WD-1:0] mem_to_wb_bus,
19+
1420
output wire [`MEM_TO_RF_WD-1:0] mem_to_rf_bus
1521
);
1622
reg [`LoadBus-1:0] ex_load_bus_r;

Sample/WB.v

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
`include "lib/defines.vh"
2+
// 将结果写回寄存器
3+
// 从MEM/WB流水线寄存器中读取数据并将它写回图中部的寄存器堆中。
24
module WB(
35
input wire clk,
46
input wire rst,

Sample/mycpu_core.v

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
`include "lib/defines.vh"
2+
// CPU核心,定义流水线
3+
24
module mycpu_core(
35
input wire clk,
46
input wire rst,

0 commit comments

Comments
 (0)