多周期CPU设计
Posted OneDay-X
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多周期CPU设计相关的知识,希望对你有一定的参考价值。
------更新一下bug(测试代码有毒)-------
和单周期CPU的设计相同,都是为了实现一系列的指令功能,但需要指出的是何为多周期(注意与前面写道的单周期的区别,这也是设计的关键之处)
多周期CPU指的是将整个CPU的执行过程分成几个阶段,每个阶段用一个时钟去完成,然后开始下一条指令的执行,而每种指令执行时所用的时钟数不尽相同,这就是所谓的多周期CPU。
理解完多周期与单周期的区别后,开始我们的多周期CPU设计之路(可以随时对应单周期的设计,注意联系与区别)。
需要设计的指令及格式如下:
==>算术运算指令
(1)add rd, rs, rt
000000 | rs(5位) | rt(5位) | rd(5位) | reserved |
功能:rd<-rs + rt
(2)sub rd, rs, rt
000001 | rs(5位) | rt(5位) | rd(5位) | reserved |
完成功能:rd<-rs - rt
(3)addi rt, rs, immediate
000010 | rs(5位) | rt(5位) | immediate(16位) |
功能:rt<-rs + (sign-extend)immediate
==>逻辑运算指令
(4)or rd, rs, rt
010000 | rs(5位) | rt(5位) | rd(5位) | reserved |
功能:rd<-rs | rt
(5)and rd, rs, rt
010001 | rs(5位) | rt(5位) | rd(5位) | reserved |
功能:rd<-rs & rt
(6)ori rt, rs, immediate
010010 | rs(5位) | rt(5位) | immediate |
功能:rt<-rs | (zero-extend)immediate
==>移位指令
(7)sll rd, rs,sa
011000 | rs(5位) | 未用 | rd(5位) | sa | reserved |
功能:rd<-rs<<(zero-extend)sa,左移sa位 ,(zero-extend)sa
==>传送指令
(8)move rd, rs
100000 | rs(5位) | 00000 | rd(5位) | reserved |
功能:rd<-rs + $0
==>比较指令
(9) slt rd, rs, rt
100111 | rs(5位) | rt(5位) | rd(5位) | reserved |
功能:如果(rs<rt),则rd=1; 否则 rd=0
==>存储器读写指令
(10)sw rt, immediate(rs)
110000 | rs(5位) | rt(5位) | immediate(16位) |
功能:memory[rs+ (sign-extend)immediate]<-rt
(11)lw rt, immediate(rs)
110001 | rs(5位) | rt(5位) | immediate(16位) |
功能:rt <- memory[rs + (sign-extend)immediate]
==>分支指令
(12)beq rs,rt, immediate (说明:immediate是从pc+4开始和转移到的指令之间间隔条数)
110100 | rs(5位) | rt(5位) | immediate(16位) |
功能:if(rs=rt) pc <-pc+ 4 + (sign-extend)immediate <<2
==>跳转指令
(13)j addr
111000 | addr[27..2] |
功能:pc <{pc[31..28],addr[27..2],0,0},转移
(14)jr rs
111001 | rs(5位) | 未用 | 未用 | reserved |
功能:pc<-rs,转移
==>调用子程序指令
(15)jal addr
111010 | addr[27..2] |
功能:调用子程序,pc <- {pc[31..28],addr[27..2],0,0};$31<-pc+4,返回地址设置;子程序返回,需用指令 jr $31。
==>停机指令
(16)halt (停机指令)
111111 | 00000000000000000000000000(26位) |
设计原理
(1) 取指令(IF):根据程序计数器pc中的指令地址,从存储器中取出一条指令,同时,pc根据指令字长度自动递增产生下一条指令所需要的指令地址,但遇到“地址转移”指令时,则控制器把“转移地址”送入pc,当然得到的“地址”需要做些变换才送入pc。
(2) 指令译码(ID):对取指令操作中得到的指令进行分析并译码,确定这条指令需要完成的操作,从而产生相应的操作控制信号,用于驱动执行状态中的各种操作。
(3) 指令执行(EXE):根据指令译码得到的操作控制信号,具体地执行指令动作,然后转移到结果写回状态。
(4) 存储器访问(MEM):所有需要访问存储器的操作都将在这个步骤中执行,该步骤给出存储器的数据地址,把数据写入到存储器中数据地址所指定的存储单元或者从存储器中得到数据地址单元中的数据。
(5) 结果写回(WB):指令执行的结果或者访问存储器中得到的数据写回相应的目的寄存器中。
实验中就按照这五个阶段进行设计,这样一条指令的执行最长需要五个(小)时钟周期才能完成,但具体情况怎样?要根据该条指令的情况而定,有些指令不需要五个时钟周期的,这就是多周期的CPU。
MIPS32的指令的三种格式:
R类型:
31 26 25 21 20 16 15 11 10 6 5 0
op | rs | rt | rd | sa | func |
6位 5位 5位 5位 5位 6位
I类型:
31 26 25 21 20 16 15 0
op | rs | rt | immediate |
6位 5位 5位 16位
J类型:
31 26 25 0
op | address |
6位 26位
其中,
op:为操作码;
rs:为第1个源操作数寄存器,寄存器地址(编号)是00000~11111,00~1F;
rt:为第2个源操作数寄存器,或目的操作数寄存器,寄存器地址(同上);
rd:为目的操作数寄存器,寄存器地址(同上);
sa:为位移量(shift amt),移位指令用于指定移多少位;
func:为功能码,在寄存器类型指令中(R类型)用来指定指令的功能;
immediate:为16位立即数,用作无符号的逻辑操作数、有符号的算术操作数、数据加载(Laod)/数据保存(Store)指令的数据地址字节偏移量和分支指令中相对程序计数器(PC)的有符号偏移量;
address:为地址。
状态的转移有的是无条件的,例如从IF状态转移到ID 和 EXE状态就是无条件的;有些是有条件的,例如ID 或 EXE状态之后不止一个状态,到底转向哪个状态由该指令功能,即指令操作码决定。每个状态代表一个时钟周期。
图3是多周期CPU控制部件的电路结构,三个D触发器用于保存当前状态,是时序逻辑电路,RST用于初始化状态“000“,另外两个部分都是组合逻辑电路,一个用于产生下一个阶段的状态,另一个用于产生每个阶段的控制信号。从图上可看出,下个状态取决于指令操作码和当前状态;而每个阶段的控制信号取决于指令操作码、当前状态和反映运算结果的状态zero标志等。
图4是一个简单的基本上能够在单周期上完成所要求设计的指令功能的数据通路和必要的控制线路图。其中指令和数据各存储在不同存储器中,即有指令存储器和数据存储器。访问存储器时,先给出地址,然后由读/写信号控制(1-写,0-读。当然,也可以由时钟信号控制,但必须在图上画出来)。对于寄存器组,读操作时,给出寄存器地址(编号),输出端就直接输出相应数据;而在写操作时,在 WE使能信号为1时,在时钟边沿触发写入。图中控制信号功能如表1所示,表2是ALU运算功能表。
特别提示,图上增加IR指令寄存器,目的是使指令代码保持稳定,还有pc增加写使能控制信号pcWre,也是确保pc适时修改,原因都是和多周期工作的CPU有关。ADR、BDR、ALUout、ALUM2DR四个寄存器不需要写使能信号,其作用是切分数据通路,将大组合逻辑切分为若干个小组合逻辑,大延时变为多个分段小延时。
表1 控制信号作用
控制信号名 | 状态“0” | 状态“1” |
PCWre | PC不更改,相关指令:halt | PC更改,相关指令:除指令halt外 |
ALUSrcB | 来自寄存器堆data2输出,相关指令:add、sub、addi、or、and、ori、move、beq、slt | 来自sign或zero扩展的立即数,相关指令:addi、ori、lw、sw、sll |
ALUM2Reg | 来自ALU运算结果的输出,相关指令:add、sub、addi、or、and、ori、slt、sll、move | 来自数据存储器(Data MEM)的输出,相关指令:lw |
RegWre | 无写寄存器组寄存器,相关指令: beq、j、sw、jr、halt | 寄存器组寄存器写使能,相关指令:add、sub、addi、or、and、ori、move、slt、sll、lw、jal |
WrRegData | 写入寄存器组寄存器的数据来自pc+4(pc4),相关指令:jal,写$31 | 写入寄存器组寄存器的数据来自存储器、寄存器组寄存器和ALU运算结果,相关指令:add、addi、sub、or、and、ori、slt、sll、move、lw |
InsMemRW | 读指令存储器(Ins. Data),初始化为0 | 写指令存储器 |
DataMemRW | 读数据存储器(Data MEM),相关指令:lw | 写数据存储器,相关指令:sw |
IRWre | IR(指令寄存器)不更改 | IR寄存器写使能。向指令存储器发出读指令代码后,这个信号也接着发出,在时钟上升沿,IR接收从指令存储器送来的指令代码。与每条指令都相关。 |
| ||
ALUOp[2..0] | ALU 8种运算功能选择(000-111),看功能表 | |
PCSrc[1..0] | 00:pc<-pc+4,相关指令:add、addi、sub、or、ori、and、move、 slt、sll、sw、lw、beq(zero=0) 01:pc<-pc+4+(sign-extend)immediate,同时zero=1,相关指令:beq 10:pc<-rs,相关指令:jr 11:pc<-pc(31..28],addr,0,0 ,相关指令:j、jal | |
RegOut[1..0] | 写寄存器组寄存器的地址,来自: 00:0x1F($31),相关指令:jal,用于保存返回地址($31<-pc+4) 01:rt字段,相关指令:addi、ori、lw 10:rd字段,相关指令:add、sub、or、and、move、slt、sll 11:未用 | |
ExtSel[1..0] | 00:(zero-extend)sa,相关指令:sll 01:(zero-extend)immediate,相关指令:ori 10:(sign-extend)immediate,相关指令:addi、lw、sw、beq 11:未用 |
相关部件及引脚说明:
InstructionMemory:指令存储器,
Iaddr,指令地址输入端口
DataIn,存储器数据输入端口
DataOut,存储器数据输出端口
RW,指令存储器读写控制信号,为1写,为0读
DataMemory:数据存储器,
Daddr,数据地址输入端口
DataIn,存储器数据输入端口
DataOut,存储器数据输出端口
RW,数据存储器读写控制信号,为1写,为0读
RegisterFile:(寄存器组)
Read Reg1,rs寄存器地址输入端口
Read Reg2,rt寄存器地址输入端口
Write Reg,将数据写入的寄存器,其地址输入端口(rt、rd)
Write Data,写入寄存器的数据输入端口
Read Data1,rs寄存器数据输出端口
Read Data2,rt寄存器数据输出端口
WE,写使能信号,为1时,在时钟上升沿写入
IR: 指令寄存器,用于存放正在执行的指令代码
ALU:
result,ALU运算结果
zero,运算结果标志,结果为0输出1,否则输出0
表2 ALU运算功能表
ALUOp[2..0] | 功能 | 描述 |
000 | Y = A + B | 加 |
001 | Y = A – B | 减 |
010 | if (A<B) Y = 1; else Y = 0; | 比较A与B |
011 | Y = A>>B | A右移B位 |
100 | Y = A<<B | A左移B位 |
101 | Y = A ∨ B | 或 |
110 | Y = A ∧ B | 与 |
111 | Y = A ⊕ B | 异或 |
以上是关于多周期CPU设计的主要内容,如果未能解决你的问题,请参考以下文章
Computer Organization笔记11多周期CPU