我们计组老师让我们写出jalr的实现, 于是正好总结一下单周期cpu是如何执行指令的.

alt text

周期开始, PC在时钟周期上升沿读取送来的地址, 随后组合电路 Instruction Memory 在一个短小的延迟后输出了指令.

随后, 指令被分为了多个部分, 送往寄存器文件, 立即数生成器和控制单元.

我们现在主要关注作为I-type 指令的 jalr, 其指令格式是: alt text

其作用是将当前 PC 中的地址送入 rd (通常是 ra), 然后把 rs1 + immediate 的值送入PC.

return一般用代码 jalr x0, ra, x0 实现.

我们可以看到, 其 0~6 位的 opcode 被送往了 control 单元.

然后, 在阅读了 opcode 后, control 单元会生成以下信号:

  1. ALUop , 这是一个两位的指令, 被送往ALU. 其用于决定ALU执行什么类型的运算. (add sub and or… etc.)

不同情况下的ALUop如下: alt text

在这里, 我们的ALU要实现一个加法, 并且不需要查看funct3的值. 我们可以合理推测其ALUOP也是 00.

ALU control 在收到ALUOP后, 发现自己不需要看funt3 和 funt7, 于是生成了一个 值为 0010 的ALU control.

而 ALU control 将会告诉ALU, 其需要做的就是对其的两个输入求和.

  1. ALUsrc 用于控制ALU的第二个输入是立即数还是寄存器, 这里我们是I型指令, 于是ALUSrc 为1.

  2. Memread, MemtoReg, RegWrite: 这个例子中不需要读写内存, 但是需要向寄存器写入数据. 因此前两者为0, RegWrite为1.

  3. Jump (这是我们新增的一个控制) 用于控制ALU的结果是否会用于PC跳转, 这里我们需要将PC设为imm + rs1, 因此毋庸置疑要设为1.

  4. Branch 关于PC的跳转, 我们已经交由Jump控制, 所以Branch 的值无关紧要.

现在, 所有信号均已就位. 数据继续运行.

指令的19~15位被送入寄存器文件, ALU的端口Read data 1 被送入了一个数据.

与此同时, 指令的11~7位被送入了寄存器文件. 这是我们的rd寄存器.

整个指令被送入了立即数生成器, 它生成了一个imm.

由于ALUSrc 的存在, Mux被标记为1, 立即数和rs里的值被执行加法.

把ALU输出的值和Jump做一个与(这里增加一个与门), 接入上方的mux. (注意这里不要经过移位器, jalrj-type , b-type 不同, 立即数是不左移的.)

然后把jumpbranchzero的与做一个或, 接入mux的控制位, 这么一来这个问题就解决了.

即使如此, 还是有很多小知识点没有总结, 我会在期中考试前夕完成一个完整的知识点总结. 今晚要完成离散数学的第四章内容.