只有一条指令的CPU
根据ISA规范设计CPU
约定一些寄存器的位宽:
- PC位宽为4位, 初值为
0 - GPR有4个, 位宽均为8位
- 支持如下3条指令
7 6 5 4 3 2 1 0
+----+----+-----+-----+
| 00 | rd | rs1 | rs2 | R[rd]=R[rs1]+R[rs2] add指令, 寄存器相加
+----+----+-----+-----+
| 10 | rd | imm | R[rd]=imm li指令, 装入立即数, 高位补0
+----+----+-----+-----+
| 11 | addr | rs2 | if (R[0]!=R[rs2]) PC=addr bner0指令, 若不等于R[0]则跳转
+----+----------+-----+
将这个用数字电路实现的sISA指令集的CPU称为sCPU
指令周期(instruction cycle)
执行一条指令的步骤
- 取指(fetch): 根据当前PC, 在存储器中找到一条指令
- 译码(decode): 看这条指令具体是什么指令, 操作数是哪些
- 以
li指令为例, 操作数需要看立即数是多少, 需要写入哪个目的寄存器
- 执行(execute): 对操作数进行处理, 必要时更新指定的目的寄存器
- 更新PC: 让PC指向下一条指令
实现CPU=用数字电路实现上述过程的每一个步骤
Q:为什么叫”周期”?
这就好比人的”呼吸周期”:吸气(取指) 屏气(译码) 呼气(执行)。呼完气后,你必须回到吸气状态,不能停下来。
取指
一个PC寄存器 -> 数字电路的寄存器
根据PC在存储器中找到一条指令 ->需要实现存储器
存储器
可寻址的存储单元集合
- 存储器中的内容按顺序排布
- 给出一个地址,存储器可以读出该地址对应的内容
将存储器看成一个由比特构成的矩阵
矩阵的每一行称为一个存储字(word)
-
地址=行的编号,行的数量=存储器的深度(depth)
-
一个存储字包含多位数据, 其位宽称为存储器的宽度(width)
通常用深度x宽度表示一个存储器的规格. 例如, 一个2x3的存储器排布如下, 其中表示第行第列所存储的比特
| 地址 | 存储字 |
|---|---|
| 0 | b_{(0,2)}$$b_{(0,1)}$$b_{(0,0)} |
| 1 | b_{(1,2)}$$b_{(1,1)}$$b_{(1,0)} |
存储器可以分别只读存储器(Read-Only Memory, ROM) 和随机访问存储器(Random Access Memory, RAM),
前者不支持写入, 而后者支持
用ROM实现取指操作
ROM的结构

左上方的译码器称为地址译码器
和地址译码器输出相连的导线称为**“字线”(word line)**, 每条字线对应一个存储字
和或门输出相连的导线称为**“位线”(bit line)**, 每条位线对应存储字的一位
给定地址addr, 可以读出ROM中的相应存储字, 其工作过程如下:
- 地址译码器将输入的地址转换成一组独热码
- 由于独热码中只有一位有效, 故所有字线中, 只有地址
addr对应的字线有效, 使得该行中存放的信息可以通过与门
- 其余行因字线无效, 存放的信息均被与门过滤为
0
- 被选中的存储字的每一位经过或门传输到位线, 向存储器外部输出
你可以把这个 ROM 想象成一个管理非常严格的图书馆档案室。
- 地址译码器 (1-2 Decoder) —— 管理员
- 你给管理员一个编号(
addr,比如 0 或 1)。- 管理员手里有两把钥匙,但他一次只能用一把。
- 如果
addr=0,他打开第 0 排架子的灯(第 0 条字线变亮/变高电平)。- 如果
addr=1,他打开第 1 排架子的灯(第 1 条字线变亮/变高电平)。- 重点:同一时间,只有一排架子是亮的,其他的全是黑的。
- 存储单元 (“0”/“1” 常数 + AND门) —— 架子上的书
- 每一排架子上放着预先写好的书(也就是图中的常数 “0”/“1”)。
- AND门的作用(过滤):
- 如果灯没亮(字线=0):不管书上写啥,你都看不见(输出全是 0)。
- 如果灯亮了(字线=1):书上写的是 1 你就看到 1,写的是 0 你就看到 0。
- 位线与或门 (Bit Line + OR Gate) —— 复印机出口
- 因为一次只有一排架子是亮的,所以对于每一列(每一位)来说,要么是”0+0”,要么是”1+0”,要么是”0+1”。
- OR门 把大家汇聚起来。因为没被选中的行全是 0,所以输出的结果 = 被选中那一行的内容。
图中的地址译码器, 与门和或门, 在功能上共同构成了一个3位的2选1多路选择器
因此ROM的读操作也可以看作是从多个存储字中选择一个
- 地址
addr就是多路选择器的选择端 - 所有存储字分别作为多路选择器的数据端
ROM中存储的信息是直接通过高低电平编码的, 因此ROM从功能上也可以看作是数据端为常数的多路选择器
| 电路组件 | 存储器术语 | 形象比喻 | 逻辑功能 |
|---|---|---|---|
| 译码器输出线 | 字线 (Word Line) | 这行架子的灯开关 | 决定哪一行被激活 (独热码) |
| OR门输入线 | 位线 (Bit Line) | 竖着的传送带 | 收集这一列的数据 |
| 常数+AND门 | 存储单元 (Cell) | 书本内容 + 可视窗口 | 只有被选中时才展示内容 |
| 整个结构 | ROM | 自动翻书机 | 硬连线的多路选择器 (MUX) |
译码
根据指令的编码识别指令的功能
用电路在二进制层面实现译码功能
- 操作码译码:根据指令的操作码识别指令的功能
- 目前只需要实现一条
li指令,无需进行 - 操作数译码:从指令的编码中识别出相应的操作数
- 解析出
li指令中的rd和imm字段(位抽取操作)
执行
li指令的功能:将立即数imm写入rd寄存器
考虑如何实现ISA的GPR
- GPR需要支持寻址
- GPR电路的本质也是一个存储器
- GPR需要作为目标寄存器被指令写入
- 支持写入的存储器,RAM
RAM的读操作结构

存储单元采用带使能端的D触发器
给定地址addr,读出存储器中相应的内容
结构类似于ROM
RAM的写操作结构

待写入数据D
并非所有时刻都需要进行写入操作, 因此还需要一个写使能信号EN, 指示当前是否需要写入
写入RAM的工作原理
待写入数据D通过位线将每一位分别连接到每一个存储字中相应位的D端
写使能EN通过与门对地址译码器输出的独热码进行过滤, 并与字线连接
将每一行的字线分别连接到对应存储器中相应的EN端
被选中的存储字将更新为待写入数据D
RAM的完整结构

- 单端口RAM”(single port RAM):在同一时刻只能通过一个地址访问其中的一个存储字
- 多端口RAM”(multi-port RAM):在同一时刻可以通过多个地址访问其中的多个存储字
更新PC
对PC寄存器加1即可
通过计数器实现
实现完整的sCPU
添加add指令
取指
和li一样
译码
操作码译码
- 检查指令的
opcode来确定是什么指令 - 识别输入的取值 -> n选1译码器
opcode只有2位, 使用一个2-4译码器- 输出的独热码可以指示当前指令属于何种指令, 这样的译码器称为指令译码器
- 这组独热码通常作为控制信号, 用于控制部分电路如何工作
操作数译码
读出rs1和rs2作为源操作数
还需要为GPR添加两个读端口
GPR模块应至少包含如下端口信号:
- 第1个读端口:
raddr1(读地址),rdata1(读数据) - 第2个读端口:
raddr2,rdata2 - 写端口:
waddr(写地址),wdata(写数据),wen(写使能),clk(时钟)
执行
用加法器实现加法操作
采用多路选择器,根据指令的类别对写入GPR的数据进行选择
- 如果当前指令是加法指令, 就选择加法器的结果
- 否则选择
li指令的立即数
更新PC
同li
添加bner0指令
取指,操作码译码同之前
操作数译码
bner0还需要读出R[0], 因此可以把0作为GPR的raddr1端口的输入
通过多路选择器解决问题
执行
比较器实现比较
更新PC
- 只有当前指令为
bner0指令, 且比较结果不相等, 才将PC更新为addr字段 - 其余情况应将PC更新为PC加1
需要将GPR的wen置为无效
重新审视CPU设计
添加指令的过程
- 分析指令的预期行为
- 根据指令的行为在数据流动的方向上依次添加所需的部件
- 数据在CPU中流动的路径和路径上的相关部件, 称为CPU的数据通路(data path)
- 有GPR, 加法器, 存储器, 比较器等
- 当多条指令的数据通路出现冲突时, 通常需要引入一些额外的电路, 来控制数据如何流动
- 这些额外的电路属于CPU中的控制逻辑
- 其中决定控制逻辑行为的信号称为控制信号
控制信号的设计
| 指令 | wdata的选择 | wen | raddr1的选择 | 更新PC的选择 |
|---|---|---|---|---|
add | 加法器的输出 | 1 | 指令的rs1 | PC + 1 |
li | 立即数 | 1 | X | PC + 1 |
bner0 | X | 0 | 0 | 指令的addr |
其中, X表示无关项(don’t care), 选择什么都可以
在CPU上执行程序 = 用程序编译出的指令序列控制CPU电路进行状态转移
交流与留言
这里使用无需登录的轻量评论系统。你可以留下问题、反馈、勘误或交流想法。