动手设计 CPU(三)—— 微程序控制的存储器读写系统设计
一、架构设计
在设计完第一个练习架构 — 微程序控制的运算器设计
之后,我们进入了第二个架构的设计过程 — 微程序控制的存储器读写系统设计
,接下来我们来探讨一下如何进行实现。
下图为我们将要设计的微程序控制的运算器的整体架构。
根据上述的架构,我们暂用下述的指令进行设计。
上述架构的整体逻辑是,uPC+CROM+uIR
选出一个指令,然后根据 XPC
与 XMAR
两个信号从数据选择器中选出 PC 中或 MAR 中的地址,根据选出的地址,对 RAM 进行读取或写入。
其中 R 寄存器
用于存数,MAR
用于存地址,因此我们需要利用上述这个架构实现下述 4 个指令。
- 从 0 号单元中取出 Ad1 放入 MAR
- 将 MAR 地址传入 RAM 中,取出对应数据,存入 R 寄存器
- 从 1 号单元中取出 Ad2 放入 MAR
- 将 R 寄存器中数据存入 MAR 中对应的地址单元
我们再次将上述电路中的元件分离,逐一实现 R、MAR、PC、RAM、数据选择器,具体实现逻辑如下所示。
二、元件实现
(1) R 寄存器
我们通过封装 74374 — 锁存器的输入输出来实现 R 寄存器,该寄存器的主要特点在于 OEN 的三态允许控制端,比普通的寄存器更适合应用在 CPU 设计中。
封装一下,即可得到下述的 R 寄存器。
(2) MAR 地址寄存器
对比 R 寄存器使用了锁存器,MAR 寄存器则可以直接使用普通的寄存器完成,即直接调用 74273 进行实现,主要目的就是封装输入、输出端。
封装一下,即可得到下述的 MAR 寄存器。
(3) PC 指令寄存器
PC 指令寄存器与第二篇文章中所实现的 uPC 没有较大差别,因此我们直接对 74161 进行封装即可,主要目的仍然是封装输入、输出端,让电路设计地更加间接。
封装一下,即可得到下述的 PC 指令寄存器。
(4) RAM
与 ROM 的设计过程一致,点击下图的按钮,根据流程即可设计 1-port 的 RAM,此处设计部分为 Quartus 应用的操作,不明白的可以继续查询网上资料,此处不再赘言。
最后的设计成果如下所示。
这里有两个地方需要注意一下。
- wren 低电平时读允许,高电平时写允许。
- CLK 下降沿打入
(5) 数据选择器
此处我们需要实现二选一的数据选择器,即按照每一位进行与运算,从而选出我们想要的数据,实现思路较为简单,具体电路如下所示。
封装一下,即可得到对应的二选一数据选择器。
三、完整电路实现
设计完上述的 5 个元件之后,再根据最开始给出的架构,即可搭建出我们要设计的架构 微程序控制的存储器读写系统设计
,具体搭建电路如下。
其中可以发现,指令中的 WR 和 RD 被合并成了一个 ,其实 XPC 和 XMAR 也可以合成一个 ,但是为了设计方便,此处没有进行合并。
除此之外,需要仔细关注三个时钟输入端。在一开始的设计中,CLK1 和 CLK2 其实是设计成同一个输入端的,但是由于延迟的存在,可能会发生 IR 的信号还没传过来,CLK2 的上升沿就到了,导致传递出去的信号仍然是旧的 IR 信号,从而导致错误。
如下图所示,PC 突然发生了变化便是由于延迟的问题,调了好久才找到原因…T^T
正因为上述的原因,最后将 CLK1、CLK2、CLK_ram 三个时钟端进行了分离,才成功仿真成功!
四、仿真测试
CROM 指令预存
此处的 4 条指令便执行了文章开头要求实现的 4 条指令。
- 从 0 号单元中取出 Ad1 放入 MAR
- 将 MAR 地址传入 RAM 中,取出对应数据,存入 R 寄存器
- 从 1 号单元中取出 Ad2 放入 MAR
- 将 R 寄存器中数据存入 MAR 中对应的地址单元
RAM 数据预存
仿真结果
将上述数据导入存储器中,再按下述波形调整 CLK1、CLK2、CLK_ram 三个波形,即每一次先执行 CLK1 传入指令,再执行 CLK_ram 输出结果,最后执行 CLK2 将数据传入对应寄存器中。
观察 PC_out、mar_out、R_out、ran_out 不难发现上述指令均执行成功!
五、总结
至此,我们即实现了 微程序控制的存储器读写系统设计
的架构,与上一个架构一致,没有太大难度,主要的目的仍然是熟悉环境,并且设计一些基础元件,例如 MAR、PC、RAM 等。
除此之外,对比第一个架构,这个架构的设计过程中,时钟安排对结果的影响更加明显,这要求我们在之后的设计中,一定要仔细观察时钟,不能将时钟瞎合并,否则会因为延迟导致出错。
CPU 设计第三篇结束,旅程仍在继续!????????????