Rij*_*zic 1 assembly verilog mips cpu-architecture iverilog
我正在用 Verilog 创建一个模拟。
我有一个内存模块,加载了 MIPS 指令,如下所示......
20082000
200d2030
8dad0000
240a0001
ad0a0000
..
..
..
Run Code Online (Sandbox Code Playgroud)
存储模块将指令输出到“控制”模块的输入端,该模块有以下信号:
RegDst、跳转、分支、MemRead、MemtoReg、ALUOp、MemWrite、ALUSrc、RegWrite
将为内存模块加载的支持指令列表生成信号值。add、addi等指令
我如何知道对于给定指令信号是真还是假?
你必须分解每条指令的作用。
以MIPS绿卡为例。
所有 R 型指令共享某些控制信号,这些信号遵循其基本指令格式 - 例如,它们源/读取rs&rt和目标/写入rd,这意味着:
RegDest是真的(rd是写的,不是rt)RegWrite是真的(写了一些reg)ALUSrc为真(第二个 alu 输入来自寄存器,而不是立即数)I-Type 指令都具有某些共享的控制信号模式:
RegDest为 false(已写入, I-Typert没有)rdRegWrite是真的(写了一些reg)ALUSrc为假(第二个 alu 输入来自立即数,而不是来自寄存器)除了加载和存储之外,没有指令接触内存,因此MemRead和MemWrite对于所有其他指令都是假的。 MemRead仅适用于装载,MemWrite仅适用于商店。
MemtoReg对于加载为 true,因为结果来自内存,但对于大多数其他指令为 false,因为结果(如果有)来自 ALU。
对于许多指令来说,其中一些控制信号并不重要,因此可以归类为“不关心”,而不是真或假(硬件都可以)。例如,由于存储指令将数据发送到内存,因此它不会更新 CPU 寄存器 - 因此,MemToReg对此并不关心,因为无论如何都不会写入寄存器(对于分支来说也是如此,因为它们也不写/更新寄存器)。
当RegWrite为假时,则MemtoReg无关紧要(即不在乎)。
与大多数其他信号不同,ALUOp 是一个比单个布尔值更大的控制信号。因此,ALU 需要知道要执行什么操作,对于 R 类型指令,这来自funct指令字段,而对于 I 类型指令,这来自操作码字段本身。
对于加载和存储,ALU(在单周期MIPS CPU中)用于执行寻址模式计算,因此应该告诉ALU进行加法。
对于分支(在单周期 MIPS CPU 中),应该告诉 ALU 进行减法(即比较)。
高级:硬件是所有指令所需的所有组件的联合。控制信号用于为正在执行的任何单个指令“激活”适当的硬件组件 - 但是,技巧是这些信号实际上并不激活组件,而是选择在执行后是否接受或忽略它们的输出根据正在执行的指令,它们分别计算出有用或无用的东西。
这有点奇怪,但是所有需要的硬件组件(对于每条可能的指令)的联合一直坐在那里做一些事情(除非使用非常先进的节能电路)。因此,控制信号所做的——不是关闭对当前指令没有贡献的组件——是简单地忽略它们的计算结果,而是倾向于相关的东西。
例如,实际上,立即数硬件是在每个指令的每个周期上对I-Type 16 位立即数进行符号扩展,但是仅当指令实际上是 I-Type 时才使用该计算值,否则由于控制而被忽略信号(ALUSrc)。
虽然我们可能认为这效率低下,但有一个值得赞赏的并行性能,即提前计算不必要的东西,以防万一需要它们,并且仅在了解更多信息后才将其抑制。