BUAA-CO-P4 基于verilog的单周期MIPS架构CPU

改动

相比P3,需要增加的:

  1. 自行实现ROM、RAM
  2. 实例化&端口映射
  3. 改为同步复位
  4. 用initial对reg赋初值
  5. 对P3中集成alu进行拆分:增加aluControl来进行operand1、operand2的选择
  6. 对grf的修改
    • 现在默认RA1接rs,RA2接rt
    • 若需读取二者以外的寄存器,可临时为grf添加RA3RD3,为aluControl添加rd3
  7. DM添加LoadType\SaveType,为lh、sh、lb、sb等指令的添加预留可扩展性

注意项

  1. case语句要写default
  2. 用综合的check syntax检查
  3. verilog默认数字为十进制32位数:除了明确十进制数,一定带上格式
  4. 避免任何可能产生锁存器的地方
  5. 缩减异或: 对于一个 n 位的向量 A[n-1:0],表达式 ^A 在逻辑上等价于:A[n-1] ^ A[n-2] ^ ... ^ A[1] ^ A[0]
  6. 到底是要用rs还是RsData
    • 需要在命名和顶层连线时注意区分。

实例化

1
2
3
4
5
6
7
// 格式: module_name instance_name ( .port_name(wire_name), ... );
control ctrl_unit (
.opcode(opcode),
.reg_write(reg_write),
.mem_to_reg(mem_to_reg)
// ... connect other ports
);

可拓展

  1. dm相关
    • 可增加dmSel模块来模拟MUX对写入dm的地址和数据进行选择
    • lb/sb的实现

层次设计

EXT(扩展单元)

  • 核心任务 把16位立即数扩展到32位
  • 整体设计 能够对立即数进行零扩展/符号扩展
  • 模块规格
    信号名 方向 位宽 描述
    immOrOffset I 16 待扩展的立即数
    EXTop I 1 扩展方式选择信号:
    1 - 符号扩展
    0 - 零扩展
    immEXT O 32 扩展后的立即数

aluControl

  • 整体设计 为alu选择operand1,operand2
  • 模块规格
    信号名 方向 位宽 描述
    rs I 32 rs value
    rt I 32 rt value
    immEXT I 32 扩展后的立即数
    shamt I 5 shamt
    aluControlSel I 3 选择信号
    000:rs/rt
    001:rs/imm
    operand1 O 32 operand1
    operand2 O 32 operand2

ALU

  • 整体设计
    • 能够实现多种运算功能,并根据op选择对应功能
      op 运算
      0000 无符号op1 + op2
      0001 无符号op1 - op2
      0010 op1 & op2
      0011 op1 | op2
      0100 op2低16位加载至高位,低位补0
  • 模块规格
    信号名 方向 位宽 描述
    op I 4 选择运算功能
    operand1 I 32 operand1
    operand2 I 32 operand2
    result O 32 运算结果
    equal O 1 判断是否相等

NPC

  • 核心任务 计算下一周期PC应更新成的值

  • 整体设计 - 顺序执行: NPC = PC + 4 - 分支跳转:NPC = (PC + 4) + (SignExtend(offset)) - j跳转:NPC = PC31…28||instr_index||00 - jr跳转:NPC = GPR[rs]

  • 模块规格

    信号名 方向 位宽 描述
    equal I 1 判断reg rs、rt所存值是否相同
    immEXT I 32 拓展后的立即数(offset)
    instr_index I 26 instr_index
    NPCop I 3 000:NPC = PC + 4
    001:分支跳转
    010:j
    011:jr
    rd1OrRs I 32 rs储存的值
    pc I 32 当前指令地址
    npc O 32 pc更新值

IFU

  • 核心任务:根据PC中的地址,从ROM中读出指令输出,同时更新PC
  • 整体设计
    • 地址转换逻辑

      • 地址偏移:pc - 0x00003000
      • 将PC的字节地址转换为ROM的字地址
    • ROM:用1024个[31:0]reg来构建ROM

    • 载入数据?

      1
      2
      3
      initial begin
      $readmemh("code.txt", imem);
      end
  • 模块规格
    信号名 方向 位宽 描述
    reset I 1 同步复位信号
    clk I 1 时钟信号
    npc I 32 pc更新值
    Instruction O 32 指令机器码
    pc O 32 当前pc

GRF(通用寄存器组)

  • 核心任务:为ALU提供快速的数据源,并接收计算结果

  • 整体设计

    • 读数据:指令最多需要同时读取两个不同地址的数据 - 两个读端口
    • 写数据
    • 0 号寄存器的值始终保持为 0。其他寄存器初始值(复位后)均为 0,无需专门设置

  • 模块规格:

    信号名 方向 位宽 描述
    reset I 1 异步复位信号
    clk I 1 时钟信号
    RA1 I 5 读地址1
    RA2 I 5 读地址2
    WA I 5 写地址
    WD I 32 写数据
    RegWrite I 1 写使能信号
    RD1 O 32 读数据1
    RD2 O 32 读数据2

    注:这里的“地址”指的是GRF中的第n个reg

DM(数据存储器)

  • 核心任务 根据 CPU 提供的地址,进行读或写操作。它连接了 CPU 的核心与外部数据存储。
  • 整体设计
    • 使用 RAM 实现,容量为 3072 × 32bit,应具有异步复位功能,复位值0x00000000

    • 起始地址0x00000000地址范围0x00000000 ~ 0x00002FFF

    • RAM 应使用双端口模式,即设置 RAM 的 Data Interface 属性为 Separate load and store ports

  • 模块规格
    信号名 方向 位宽 描述
    Address I 32 读/写地址
    WriteData I 32 要写入的数据
    MemWrite I 1 写使能信号
    MemRead I 1 读使能信号
    clk I 1 时钟信号
    reset I 1 异步复位信号
    PC I 32 当前指令的地址
    LoadType I 2 load模式选择信号
    2’b00:lw
    2’b01:lh
    SaveType I 2 Save模式选择信号
    2’b00:sw
    2’b01:sh
    MemData O 32 读出的数据

grfSel

  • 核心任务 决定写入grf的地址和数据
  • 模块设计
    信号名 方向 位宽 描述
    RegDst I 3 GRF写回地址选择信号:
    001:rt
    000:rd
    010:rs
    011:GPR[31]
    WDsel I 2 GRF写入数据选择信号:
    00:ALU运算结果
    01:DM读出的数据(lw)
    10:PC + 4
    rs I 5 rs
    rt I 5 rt
    rd I 5 rd
    ALUresult I 32 ALU运算结果
    MemData I 32 DM读出的数据
    PC I 32 PC
    WA O 5 WA
    WD O 32 WD

instrSplitter

  • 核心任务 对指令机器码进行拆分
  • 模块设计
    信号名 方向 位宽 描述
    Instruction I 32 指令
    opcode O 6 instr[31:26]
    rs O 5 instr[25:21]
    rt O 5 instr[20:16]
    rd O 5 instr[15:11]
    shamt O 5 instr[10:6]
    funct O 6 instr[5:0]
    instr_index I 26 instr[25:0]
    immOrOffset I 16 instr[15:0]

Controller

  • 核心任务:根据当前正在执行的指令输出对应控制信号

  • 整体设计 解码逻辑 = 和逻辑 + 或逻辑

    • 和逻辑:识别

      • 将输入的机器码识别为相应指令
    • 或逻辑:生成

      • 根据输入指令生成对应的控制信号
      • 控制信号表;
        控制信号\指令 add sub ori lw sw beq lui jal jr
        RegWrite 1 1 1 1 0 0 1 1 0
        aluControlSel 000 000 001 001 001 000 001 000 000
        ALUop 0000 0001 0011 0000 0000 0000 0100 0000 0000
        MemWrite 0 0 0 0 1 0 0 0 0
        MemRead 0 0 0 1 0 0 0 0 0
        EXTop 0 0 0 1 1 1 0 0 0
        RegDst 000 000 001 001 000 000 001 011 000
        WDsel 00 00 00 01 00 00 00 10 00
        NPCop 000 000 000 000 000 001 000 010 011
  • 模块规格

    信号名 方向 位宽 描述
    opcode I 6 指令[31:26]位
    funct I 6 指令[5:0]位
    RegWrite O 1 GRF写使能信号
    aluControlSel O 3 alu操作数选择信号
    000:rs/rt
    001:rs/imm
    ALUop O 4 ALU运算模式选择信号
    MemWrite O 1 DM写使能信号
    MemRead O 1 DM读使能信号
    EXTop O 1 EXT扩展模式选择信号
    RegDst O 3 GRF写回地址选择信号:
    001:rt
    000:rd
    010:rs
    011:GPR[31]
    WDsel O 2 GRF写入数据选择信号:
    00:ALU运算结果
    01:DM读出的数据(lw)
    10:PC + 4
    NPCop O 3 PC更新模式选择信号:
    000:顺序执行
    001:beq分支跳转
    010:j/jal跳转
    011:jr跳转

测试方案

工具

借用Mars_CO.jar进行检查。

使用

  1. 命令行进入Mars_CO.jar所在目录
  2. 测试文件也放在这个目录下
  3. 在命令行运行
    1
    java -jar Mars_CO.jar test.asm mc CompactLargeText coL1

思考题

  1. 阅读下面给出的 DM 的输入示例中(示例 DM 容量为 4KB,即 32bit × 1024字),根据你的理解回答,这个 addr 信号又是从哪里来的?地址信号 addr 位数为什么是 [11:2] 而不是 [9:0] ?

    DM示意图

    • 这个addr由alu给出(alu对gpr(base)(sign_ext)offset做加运算)
    • addr以字节为单位,对应到以字为单位的DM,故应除以4,即取[11:2]
  2. 思考上述两种控制器设计的译码方式,给出代码示例,并尝试对比各方式的优劣。

    • 记录指令对应的控制信号如何取值:
      • 优点:思考流畅,一次模拟一整条指令的运行过程即可;便于调试,找到出错指令对应分支进行检查即可
      • 缺点:controll模块繁杂
    • 记录控制信号每种取值所对应的指令:
      • 优点:每个信号利用一个assign表达式描述即可,代码冗余少;
      • 缺点:可读性差,较难找出错误在哪儿
  3. 在相应的部件中,复位信号的设计都是同步复位,这与 P3 中的设计要求不同。请对比同步复位与异步复位这两种方式的 reset 信号与 clk 信号优先级的关系。

    • 同步复位:clk优先
    • 异步复位:reset优先
  4. C 语言是一种弱类型程序设计语言。C 语言中不对计算结果溢出进行处理,这意味着 C 语言要求程序员必须很清楚计算结果是否会导致溢出。因此,如果仅仅支持 C 语言,MIPS 指令的所有计算指令均可以忽略溢出。 请说明为什么在忽略溢出的前提下,addi 与 addiu 是等价的,add 与 addu 是等价的。

    • addaddu 执行的加法计算是完全一样的,唯一的区别在于add指令多了一个溢出检测异常处理的步骤:

         if temp32 ≠ temp31 then
         SignalException(IntegerOverflow)
         else
         GPR[rd] ← temp31..0
         endif
      

      忽略溢出时add与addu等价。

    • addiaddiu同理

Copyright © 2026 CRZ's Blog

Powered by Hexo • Theme Candelas