MIPS32三种指令集格式
注意右边为低位,左边为高位。
R型指令
6bits | 5bits | 5bits | 5bits | 5bits | 6bits |
---|---|---|---|---|---|
$$OP$$ | $$R_{s}$$ | $$R_{t}$$ | $$R_{d}$$ | $$shamt$$ | $$funct$$ |
R型指令的 OP
恒为0;
由于mips提供了32个通用寄存器,故 OP
后是三个5bits的寄存器编号:Rs
和 Rt
为两个源寄存器, Rd
为目的寄存器;
shamt
表示用于移位的偏移量,5bits可以表示0-31位的偏移量;
funct
表示其指令功能,如32为加法、34为减法。
I型指令
6bits | 5bits | 5bits | 16bits |
---|---|---|---|
$$OP$$ | $$R_{s}$$ | $$R_{t}$$ | 立即数 |
OP
表示指令功能;
Rs
为源寄存器, Rt
有可能作为目标寄存器用于写入。
J型指令
6bits | 26bits |
---|---|
$$OP$$ | 立即数 |
6bits操作码和26bits的立即数。
所以对于指令的解析,如果 OP
为0那么看 funct
,反之通过 OP
可以唯一确认指令的功能。
需要实现的八条指令
五条I型指令
三条R型指令
单周期硬布线控制器
指令译码逻辑
电路模板中给出了 OP
、 FUNC
(funct)通道,以及需要实现的八种指令分别的通道。另外还给出了 R_TYPE
即R型指令通道来辨别R型运算指令(注意SYSCALL是特殊的R型指令,不在这一类别)。
对照之前的MIPS指令格式,编写译码逻辑。如果 OP
非0,那么通过 OP
判断指令功能;如果为0(R型指令),那么通过 FUNC
来判断指令功能;如果是R型运算指令,则 R_TYPE
置高电平。
最终效果:
ALU控制逻辑
即生成 ALU_OP
。一共有五个指令需要通过 ALU_OP
调用对应的ALU运算功能,分别为 LW
、 SW
、 ADDI
、 ADD
和 SLT
。只有 SLT
为小于比较,其他均为加法。 LW
、 SW
两个指令的地址是通过基址寻址产生的,所以需要调用加法运算。
查看题目提供的MIPS ALU可以看到所需的 ALU_OP
: 加法为5H, 小于比较为BH。可以通过多路分配器来实现,执行 SLT
时输出BH,反之为5H:
另外 BEQ
和 BNE
指令也使用到了ALU,它们使用ALU判断两个操作数是否相等,这有独立的信号引出,和 ALU_OP
无关。
控制信号逻辑
需要将指令译码信号转换为控制信号,这里解释一下每个信号的连线含义:
根据题意, SYSCALL
表示了 Halt
停机, BEQ
和 BNE
是两个条件跳转指令,这三个信号直接和对应的信号相连。
MemToReg
即从存储器中读取数据写入寄存器, MemWrite
即将寄存器中的数据写入存储器。显然对应 LW
和 SW
,直接相连即可。
AluSrc
控制ALU操作数的来源。注意需要调用ALU的指令,它们的第二个操作数可能来自于寄存器,也可能来自于立即数( ADDI
、 LW
和 SW
)。我的电路中用1代表第二个操作数为立即数,0代表存储在寄存器中。
RegWrite
控制寄存器文件的写入,即该条指令需要将运算结果写入寄存器,显然两条R型运算指令以及 ADDI
和 LW
需要。
RegDst
控制计算结果的地址。由于R型指令和I型指令的指令格式中,指定目的寄存器的五位二进制数位置不同(R型11-15,I型16-20),所以需要区分。我的电路中用1代表R型指令,0代表I型指令。
最终实现如下:
单周期MIPS(硬布线)
需要使用CS3410中的MIPS RAM,Memory中的ROM、Register、Counter,实验模板提供的MIPS ALU、MIPS Regifile,以及其他Logisim自带的模块。
PC
、 IR
等信号都已引出, RegWrite
和 MemWrite
与单周期硬布线控制器中的信号对应。 RDin
为寄存器文件写入信号,应引出RegFile的Din脚相连;而 MDin
为存储器写入信号,应与MIPS RAM的数据写入端相连。
由于我们实现的是8条MIPS32指令,每条指令的长度是相同的。所以PC每次加4 (Bytes),且对ROM寻址时,低两位忽略才是字地址。根据指令格式可以将指令的每个部分拆分出来,注意立即数需要进行有符号扩展为32bits才能参与运算:
实验测试使用的指令(sort.hex)需要自己写入ROM中,只有很短一小段:
2010ffff 20110000 ae300200 22100001 22310004 ae300200 22100001 22310004
ae300200 22100001 22310004 ae300200 22100001 22310004 ae300200 22100001
22310004 ae300200 22100001 22310004 ae300200 22100001 22310004 ae300200
8020 2011001c 8e130200 8e340200 274402a 11000002 ae330200 ae140200
2231fffc 1611fff8 22100004 2011001c 1611fff5 2002000a c
指令解析出的操作数地址、写入地址和立即数会被立即送到RegFile中;寄存器文件将R1#和R2#的数据取出送到R1和R2,它们和立即数被送向ALU。由于无论是何种指令,该过程都会进行,所以RegDst、RegWrite和AluSrc控制着整个单元取用需要的数据而舍弃垃圾值。ALU将运算结果和比较结果从“=”脚和“R”脚送出。注意如果计算的是地址,获得的是字节地址。
添加上RAM相关的两个信号 MemToReg
和 MemWrite
就是简单模式了,这里就不说了。
PC每个时钟周期+4,如果符合调整条件,则附加上偏移量,注意偏移量为指令条数。总周期数用Counter计数。Halt停机,停止PC和周期数计数器即可,正常应在第224个周期停机。
其实按照实验提供的示意图依样画葫芦会更容易点,分块主要为了讲解相对清晰。最终的电路如下:
By SDUST weilinfox