P4 CPU设计文档
设计要求
处理器为 32 位单周期处理器,不考虑延迟槽,应支持的指令集为:
add, sub, ori, lw, sw, beq, lui, jal, jr, nop,其中:nop为空指令,机器码0x00000000,不进行任何有效行为(修改寄存器等)。add, sub按无符号加减法处理(不考虑溢出)。
需要采用模块化和层次化设计。顶层文件为 mips.v,有效的驱动信号要求包括且仅包括同步复位信号 reset 和时钟信号 clk,接口定义如下:
1
2
3
4module mips(
input clk,
input reset
);
设计草稿
数据通路模块定义
PC
| 信号名 | 方向 | 功能 |
|---|---|---|
| NPC[31:0] | I | 输入下一个 PC 值 |
| clk | I | 时钟信号 |
| reset | I | 同步复位信号 |
| PC[31:0] | O | 输出当前 PC 值 |
NPC
| 信号名 | 方向 | 功能 |
|---|---|---|
| PC[31:0] | I | 输入当前的 PC 值,用于计算 NPC 值 |
| offset[31:0] | I | 偏移量 |
| nPC_sel[2:0] | I | NPC 输出选择信号 |
| Branch | I | 跳转信号 |
| instr_index[25:0] | I | 机器码 26 位 instr_index |
| Ra[31:0] | I | 输入$ra 寄存器的值 |
| NPC[31:0] | O | 输出 NPC 值 |
| PC_add_4[31:0] | O | 输出 PC+4 值 |
nPC_sel 的信号功能:
| 信号 | 功能 |
|---|---|
| 3’b000 | NPC = PC + 4 |
| 3’b001 | NPC = Branch ? PC + 4 + (offset << 2) : PC + 4 |
| 3’b010 | NPC = (PC31...28的 32 位无符号扩展数 << 28) + (instr_index 的 32 位无符号拓展数 << 2) |
| 3’b011 | NPC = Ra |
IM
| 信号 | 方向 | 功能 |
|---|---|---|
| A[31:0] | I | 输入指令地址 |
| RD[31:0] | O | 输出指令 |
由于指令地址起始值为 0x0000_3000,对 A 减去 0x0000_3000 后,取其[13:2]位值,记为 no,从指令存储器中取第 no 条指令输出给 RD。
指令存储器容量为 4096 × 32bit。
GRF
| 信号 | 方向 | 功能 |
|---|---|---|
| A1[4:0] | I | 输入需要读取的寄存器 Reg1 的序号 |
| A2[4:0] | I | 输入需要读取的寄存器 Reg2 的序号 |
| A3[4:0] | I | 输入需要写入的寄存器的序号 |
| WD3[31:0] | I | 写入数据 |
| clk | I | 时钟信号 |
| WE3 | I | 写使能信号 |
| reset | I | 同步复位信号 |
| PC[31:0] | I | 相应指令的储存地址 |
| RD1[31:0] | O | 输出从寄存器 Reg1 中读取的内容 |
| RD2[31:0] | O | 输出从寄存器 Reg2 中读取的内容 |
0 号寄存器值始终为 0。
DM
| 信号 | 方向 | 功能 |
|---|---|---|
| A[31:0] | I | 输入内存地址 |
| WD[31:0] | I | 输入需要写入的数据 |
| clk | I | 时钟信号 |
| reset | I | 同步复位信号 |
| WE | I | 写使能信号 |
| PC[31:0] | I | 相应指令的储存地址 |
| RD[31:0] | O | 输出从内存中读取的数据 |
取 A[13:2]的值记为 no,表示数据存储器第 no 处位置。
数据存储器容量为 3072 × 32bit。
ALU
| 信号 | 方向 | 功能 |
|---|---|---|
| SrcA[31:0] | I | 输入计算数 A |
| SrcB[31:0] | I | 输入计算数 B |
| Shift[4:0] | I | 输入移位量 Shift |
| Op[2:0] | I | 操作数 Op |
| Result[31:0] | O | 输出运算结果 |
| Zero | O | Zero = (A == B); |
Op 信号功能:
| 信号 | 类型 | 操作 |
|---|---|---|
| 3’b000 | ADD(无符号,不考虑溢出) | SrcA + SrcB |
| 3’b001 | SUB(无符号,不考虑溢出) | SrcA - SrcB |
| 3’b010 | OR | SrcA | SrcB |
| 3’b011 | SHIFT | SrcB << Shift |
EXT
| 信号 | 方向 | 功能 |
|---|---|---|
| Imm[15:0] | I | 输入 16 位立即数 |
| ExtOp | I | 扩展类型 |
| Ext_Imm[31:0] | O | 输出扩展立即数 |
ExtOp 信号功能:
| 信号 | 操作 |
|---|---|
| 1’b0 | 无符号拓展 |
| 1’b1 | 符号拓展 |
控制单元模块
| 信号 | 方向 | 功能 |
|---|---|---|
| Op[5:0] | I | 机器码 Op 字段 |
| Funct[5:0] | I | 机器码 Funct 字段 |
| RegDst[1:0] | O | 指定要写入的寄存器地址 |
| ALUSrc[1:0] | O | 指定 ALU 的 SrcB |
| MemtoReg[1:0] | O | 指定写入 GRF 的源数据 |
| RegWrite | O | GRF 写使能信号 |
| MemWrite | O | DM 写使能信号 |
| nPC_sel[2:0] | O | 指定 NPC 的值 |
| ExtOp[1:0] | O | 指定立即数扩展类型 |
| ALUOp[2:0] | O | 指定 ALU 运算类型 |
| ShiftOp | O | 指定移位量 |
RegDst 信号功能:
| 信号 | 写入寄存器地址 |
|---|---|
| 2’b00 | Instr[20:16] |
| 2’b01 | Instr[15:11] |
| 2’b10 | 31 |
ALUSrc 信号功能:
| 信号 | SrcB |
|---|---|
| 2’b00 | GRF 的 RD2 |
| 2’b01 | Ext_Imm |
MemtoReg 信号功能:
| 信号 | 写入 GRF 的源数据 |
|---|---|
| 2’b00 | ALU 的 Result |
| 2’b01 | DM 的 RD |
| 2’b10 | PC+4 |
ShiftOp 信号功能:
| 信号 | 移位量 |
|---|---|
| 1’b0 | 16 |
nPC_sel 信号接入 NPC,ExtOp 信号接入 EXT,ALUOp 信号接入 ALU。
指令与信号的对应关系参照 Logisim 的 Control Unit:


测试方案
借助讨论区的.asm
自动生成文件main.exe,生成随机测试代码。然后根据自己编写的脚本将
Mars 和 ISE 的输出结果重定向到相应的文件:
1 | @echo off |
最后将两个 txt 文本的内容对拍以查找错误。
思考题
1. 阅读下面给出的 DM 的输入示例中(示例 DM 容量为 4KB,即 32bit × 1024 字),根据你的理解回答,这个 addr 信号又是从哪里来的?地址信号 addr 位数为什么是 [11:2] 而不是 [9:0] ?

addr信号来自ALU的输出。
由于输入的 memory address 地址值都是 4
的倍数,所以取addr的[11:2]位。
2. 思考上述两种控制器设计的译码方式,给出代码示例,并尝试对比各方式的优劣。
1.指令对应的控制信号如何取值:
1 | always @(*)begin |
2.控制信号每种取值所对应的指令
1 | wire add = Op == 6'b0 && Funct == 6'h20; |
第一种方式便于查错,但代码量大。第二种便于插入新指令、代码量小,但不容易维护。
3. 在相应的部件中,复位信号的设计都是同步复位,这与 P3 中的设计要求不同。请对比同步复位与异步复位这两种方式的 reset 信号与 clk 信号优先级的关系。
同步复位,clk信号优先级>reset信号:
1 | always@(posedge clk)begin |
异步复位,clk信号优先级<reset信号:
1 | always@(posedge clk or posedge reset)begin |
4. C 语言是一种弱类型程序设计语言。C 语言中不对计算结果溢出进行处理,这意味着 C 语言要求程序员必须很清楚计算结果是否会导致溢出。因此,如果仅仅支持 C 语言,MIPS 指令的所有计算指令均可以忽略溢出。 请说明为什么在忽略溢出的前提下,addi 与 addiu 是等价的,add 与 addu 是等价的。提示:阅读《MIPS32® Architecture For Programmers Volume II: The
MIPS32® Instruction Set》中相关指令的 Operation 部分。
addi:

addiu:

可见若不考虑溢出,addi和addiu最终都是将GPR[rs] + sign_extend(immediate)赋值到GPR[rt]中。add和addu同理。





