HUST组原实验
单总线CPU设计(三级时序)
1. RISC-V指令译码器设计
查阅RISC-V指令手册,利用Ctrl+F查找这些指令,或者大萝卜发的RISCV指令码表,可以得到以下指令码。
指令 | OPCODE | FUNCT3 |
---|---|---|
LW |
00000 11 | 010 |
SW |
01000 11 | 010 |
BEQ |
11000 11 | 000 |
ADDI |
00100 11 | 000 |
SLT |
01100 11 | 010 |
- 实验中直接将5位
OPCODE
和3位FUNCT3
组成8位指令码,与OP_Funct3
比较即可。
2. 变长指令周期—时序发生器FSM设计
单总线结构中如果采用变长指令周期,不同指令机器周期数不同,每个机器周期节拍数也是可变化的,具体状态图如下:
- 根据这个状态转换图,可以知道前4个周期S0-S3都是固定不变的取指周期,而
LW
、SW
、BEQ
有2个节拍的计算周期,ADDI
、ADD
以及与ADD
同为R型指令的SLT
直接进入执行周期。 - 因此现态到次态的转换从3-4为前三条指令,从3-6为后两条指令,
ERET
和IntR
为中断相关信号,忽略即可。 - 其余状态转换依次填写。
- 填完之后将对应的逻辑表达式粘贴到logisim分析电路即可。
打开 工程->分析组合逻辑电路。
把对应的表达式复制到对应的输出。
3. 变长指令周期—时序发生器输出函数设计
- 依然根据该图填表,M开头的表示哪个周期,T开头表示哪个节拍。由于只到S8状态,所以9和10忽略。
- 填写完后复制表达式到logisim中生成电路即可。
4. 硬布线控制器组合逻辑单元
这一关需要综合指令周期、节拍、控制信号填表,具体需要查阅大萝卜发送的最新第六章RISCV典型5条指令操作流程及控制信号(P13页)。
先熟悉一下单总线CPU的结构。
- CPU中所有运算器、控制器、寄存器等都由一条内部公共总线连接。
- 总线上可以有多个模块同时接收数据
- 某一时刻只能有一个模块向总线发送数据,否则出现数据冲突。所以向内总线输出的部件均采用三态门控制,只有控制信号为1时,才向总线输出数据。如
PCout
为1,时,PC寄存器才能向内总线输出指令地址。
以下为控制信号及功能方便查阅。
指令对应的结构和功能
x
代表寄存器,x[rs1]
即rs1号寄存器。
LW
: 从主存地址x[rs1] + sign-extend(offset)
读取四个字节,写入x[rd]
,12位立即数offset
符号扩展为32位才能送ALU
计算访存地址,是一个典型的变址寻址。汇编代码为
lw rd,offset(rs1)
LW
分为取值、计算、执行三个周期。- 5条指令的取值周期均相同,PC需要送入AR地址寄存器(
PCout=1
,ARin=1
),以便从主存中读取该指令;同时送入暂存器X
(Xin=1
),以便将PC+4
,即加指令长度,送入Z
。(运算器ALU采用了两个暂存寄存器X
,Z
,其中X
用于暂存ALU的一个操作数,另一个操作数来自内总线,Z
用于暂存运算结果。) Z
将数据传回PC(Zout=1
,PCin=1
),将指令从主存读入数据寄存器DR(Read=1
,DREin=1
)。- DR的值送入指令寄存器IR(
DRout=1
,IRin=1
)。 - 在理解了各个节拍的操作和控制信号的功能后,才方便自行推断后续
SLT
指令的控制信号。
SW
: 将x[rs2]
的4个字节存入主存地址x[rs1]+sign-extend(offset)
。汇编代码为
sw rs2,offset(rs1)
SW
分为取值、计算、执行三个周期。取指周期与LW
相同。
BEQ
: 若寄存器x[rs1]
和寄存器x[rs2]
的值相等,把PC
的值设为当前值加上符号位扩展的偏移offset
。汇编代码为
beq rs1,rs2,offset
offset
的值表示分支目标地址相对下一条指令也就是PC+4
的指令条数,所以计算分支目标地址时应该将PC的值(取指阶段已更新为PC+4
)与offset
符号扩展为32位再左移两位后的值相加,左移两位的目的是计算字节偏移。
ADDI
: 把符号位扩展的立即数加到寄存器x[rs1]
上,结果写入x[rd]
。忽略算术溢出。汇编代码为
addi rd,rs1,imm
SLT
: 比较x[rs1]
和x[rs2]
中的数,如果x[rs1]
更小,向x[rd]
写入1,否则写入0。汇编代码为
slt rd,rs1,rs2
- 书中并未给出SLT指令的控制流程,但ADD和SLT均为R型指令,区别仅仅在于指令字中的
funct
字段不同,最终 ALU 进行的运算不同而已,可参考ADD指令。
ADD
:将rs1
与rs2
寄存器相加结果送rd
寄存器。汇编代码为
add rd,rs1,rs2
- 将寄存器
rs1
的内容送X
,再将寄存器rs2
的内容送 ALU 进行加法运算, 最后将结果送rd
寄存器
由此推断出SLT的控制信号:
节拍 | 操作 | 功能说明 | 控制信号 |
---|---|---|---|
T1 | R[rs1]→X | rs1寄存器内容送暂存器X,准备进行运算 | Rout=Xin=1 |
T2 | R[rs2]+X→Z | rs2寄存器内容送ALU进行SLT运算,结果送Z | Rout=Rs1/2=SLT=1 |
T3 | PSW→R[rd] | 暂存器Z的运算结果送目的寄存器rd | Zout=Rin=1 |
可以看出,相比ADD指令,SLT指令仅仅是改变了T2节拍的ADD
信号为SLT
信号,以控制ALU运算。
至此,所有周期节拍对应信号已确定,将表填好后表达式输入logisim生成电路即可。
表如下:
调试
如图,控制总线的信号出现了错误,ErrBit
指出了出错的第一位信号,0d
指出了是第12位发生了错误,此时应该先查看硬布线控制器中的组合逻辑单元,此时可以根据OCinput
判断出是哪个指令,哪个周期,哪个节拍出现了问题(图中0284(00010 100 0010 0)
代表:SW
指令,Mif
周期,T3
节拍),再根据出现问题的一行,找到出错信号,改成ControlBus
的正确信号即可。
5. 变长指令周期—硬布线控制器设计
- 将线路正确连接即可。
- 注意状态寄存器为下降沿,状态机和输出函数为变长指令的封装电路。
6. 变长指令周期—单总线CPU设计
- 加载sort-5-riscv.hex到RAM即可。
- ctrl+k进行仿真,最后指令数会停在251,最后一条指令为
beq zero,zero,0
,是个死循环。
单总线CPU设计(现代时序)
1. RISC-V单总线CPU设计
同上
2. 单总线CPU微程序入口查找逻辑
微程序:仿照程序设计的基本方法,将实现指令系统中所有指令功能所需要的所有控制信 号,按照一定的规则编码成微指令,若干条实现同一条指令功能的微指令构成一段微程序。
将实现所有指令的微程序存放在一个只读存储器中,这个存储器称为控制存储器。
每条机器指令对应一段微程序,一段微程序包括若干条微指令。
上个实验是将控制信号用电路来实现,依然是这个图。
而这个实验用的微程序,将所有控制信号放在控制存储器中。
从控存中取出的数据,即微指令字包括微操作控制字段,判别测试字段,下址字段三部分, 下址字段用于指示即将访问的下一条微指令的地址,判别字段用于地址逻辑转移。
本实验采用的是下址字段法,由下址字段直接给出下一条微指令的地址。采用如下的状态机来设计微指令的存放。
因此五条指令的入口地址依次确定。
将逻辑表达式生成电路即可。
3. 单总线CPU微程序条件判别测试逻辑
判别测试字段(上图控制信号中 P0-P2)指出微指令执行过程中需要测试的外部条件,如是否要根据指令译码进行微程序分支、进位、运算结果是否为零、是否是当前微程序的最后一 条微指令等。
信号 | 输入输出 | 位宽 | 功能描述 |
---|---|---|---|
P0 | 输入 | 1 | 判别测试位,为1表示要根据指令功能进行微程序分支 |
P1 | 输入 | 1 | 判别测试位,为1表示要根据equal标志进行微程序分支 |
equal | 输入 | 1 | 条件状态位,表示运算相等 |
S4~S0 | 输入 | 1 | 现态输出第0位 |
根据信号填表(因为后面中断实验还用到了该表,这个实验的已经覆盖掉了)即可,最终电路如下。
4. 单总线CPU微程序控制器设计
将三级时序实验的控制信号填入下表即可,下址字段为该微指令地址+1。注意beq分支。
填写完成后,右下角的检查程序会显示正确。
5. 采用微程序的单总线CPU设计
在RAM中加载
sort-5-riscv.hex
程序,ctrl+k自动运行,程序应该运行至0x7c1节拍停下,指令计数为251,注意最后一条指令是一条beq分支指令,会跳回当前指令继续执行,是死循环。
6. 现代时序硬布线控制器状态机设计
依然根据这张状态转换图来填写表格。
7. 现代时序硬布线控制器设计
正确连线即可。
RISC-V现代时序中断机制实现
2. 支持中断的微程序入口查找逻辑
相比上一个实验,只是多了一条中断指令。
根据这个加入中断的状态转换图填表即可。
3. 支持中断的微程序条件判别测试逻辑
- 先查看信号的功能描述
信号 | 功能描述 |
---|---|
Cnt | 测试用例编号,注意是十六进制 |
P0 | 条件测试位,根据指令功能进行微程序分支P~IR~ |
P1 | 条件测试位,根据PSW.equal标记进行分支Pequal |
P2 | 条件测试位,表示是最后一条微指令,需要判断中断请求IntR |
equal | 相等标记 |
IntR | 中断请求信号 |
MuxSel | 后续地址多路选择控制信号 |
- 查看微程序控制器+中断的电路,可以看成判别逻辑根据5位输入确定选择5路中的哪一路。
- P0为1时,
MuxSel
为1,选择对应指令的入口地址。 - P1为1且
equal
为1时,进行beq
分支,MuxSel
为2,选择beq
入口地址。 - P2为1且
IntR
为1时,进行中断分支,MuxSel
为3,选择中断入口地址。 - P1比P2优先考虑
- 其余情况为顺序地址。
因为后面实验发现表格有误,所以面向实验测试集编程的表格,仅供参考。
4. 支持中断的微程序控制器设计
正确连线即可。
5. 支持中断的微程序单总线CPU设计
根据中断控制器的示意图连线。
- 中断1、2分别对应多路选择器的1、2端口。
- 用三态门根据中断控制信号进行内总线的读取数据和输出数据。
- D触发器相当于IE寄存器。
- 中断的入口地址需要用
rars1_3_1.jar
文件查看。
中断入口地址查看
- 在当前文件夹打开终端,使用命令
java -jar rars1_3_1.jar
。 - 打开
Sort-5-int-riscv.asm
文件,在Settings中勾选对应选项。 - 在Run菜单中选择Assemble,即可查看对应中断程序的入口地址。
- 将对应地址用常量输入多路选择器的端口。
在RAM中加载sort-5-int-riscv.hex
程序,执行后停在了指令计数252处。
点击1按钮,观察RAM内容,可以看到程序将在90开始的8个字单元全部加1。
点击2按钮,观察RAM内容,可以看到程序将在a0开始的8个字单元全部减1。
6. 支持中断的现代时序硬布线控制器状态机设计
依然根据这个图填表即可。
(日常面向测试集填表了)
7. 支持中断的现代时序硬布线控制器设计
还是连线。
- 控制存储器中需要加载对应的微指令程序,相比上一个微指令表,只是多了一个中断指令,还有将下址字段法换成了计数器法。
- 计数器法: 微指令中不再包括下址字段部分,可有效减少微指令字长度,缩小控存容量开销,当判别测试字段不符合待测试的状态条件时,表示微程序顺序执行,后继微指令地址由
μAR
加1得到,否则根据约定修改的μAR
值实现微程序分支。- 此时应该在判别测试字段额外增加一个结束微指令判别测试位
Pend
,当Pend
为1时表示当前微指令是当前微程序的最后一条微指令,由地址转移逻辑将取指令微程序入口地址送微地址寄存器μAR
。
- 此时应该在判别测试字段额外增加一个结束微指令判别测试位
至此所有实验都做完了,恭喜你通(lei)关(si)了!