跳转至

共通 - 处理器实验概述

实验目标

在实验 2~4 中,我们已经接触了 ALU、寄存器堆、SRAM 控制器和 UART 控制器。本实验要把这些部件连接起来,让硬件能够根据内存中的指令,自动完成运算、访存和串口输出。

本实验的目的是在做较为复杂的能够运行监控程序的五级流水线处理器之前,让同学们通过一个简单的处理器设计来对每一条指令的执行有一个直观的感受。本实验的处理器与大实验基本类似,但只需要支持少数的指令即可。

由于本实验并不限制大家一定要实现多周期或者流水线 CPU,因此后面的实验文档将分为共通部分,以及流水线/多周期单独的部分以供大家参考。

阅读顺序

建议先了解目标程序,再选择 CPU 的实现方式,最后连接外设并验证完整系统:

  1. 阅读本节和程序和二进制文件,弄清楚程序做什么,以及如何将汇编代码变成 CPU 可以读取的机器码。
  2. 阅读多周期 v.s. 流水线,选择一种实现方式。
  3. 根据选择阅读多周期 CPU 的设计与实现,或流水线 CPU 的设计和实现。选择流水线的同学还需要阅读仲裁器和气泡和冲刷流水线。
  4. 阅读 SoC 设计,将 CPU 与 SRAM、UART 控制器连接起来。
  5. 按照实验内容完成实验和报告。

以上是阅读建议,具体实验要求以实验内容为准。

目标程序

在本实验中要实现的 CPU 需要支持的汇编程序如下:

    addi t0, zero, 0     # loop variable
    addi t1, zero, 100   # loop upper bound
    addi t2, zero, 0     # sum
loop:
    addi t0, t0, 1
    add t2, t0, t2
    beq t0, t1, next # i == 100?
    beq zero, zero, loop

next:   
    # store result
    lui t0, 0x80000  # base ram address
    sw t2, 0x100(t0)

    lui t0, 0x10000  # serial address
.TESTW1:
    lb t1, 5(t0)
    andi t1, t1, 0x20
    beq t1, zero, .TESTW1 
    # do not write when serial is in used

    addi a0, zero, 'd'
    sb a0, 0(t0)

.TESTW2:
    lb t1, 5(t0)
    andi t1, t1, 0x20
    beq t1, zero, .TESTW2

    addi a0, zero, 'o'
    sb a0, 0(t0)

.TESTW3:
    lb t1, 5(t0)
    andi t1, t1, 0x20
    beq t1, zero, .TESTW3

    addi a0, zero, 'n'
    sb a0, 0(t0)

.TESTW4:
    lb t1, 5(t0)
    andi t1, t1, 0x20
    beq t1, zero, .TESTW4

    addi a0, zero, 'e'
    sb a0, 0(t0)

.TESTW5:
    lb t1, 5(t0)
    andi t1, t1, 0x20
    beq t1, zero, .TESTW5

    addi a0, zero, '!'
    sb a0, 0(t0)

end:
    beq zero, zero, end 
    # loop forever, let pc under control

目标程序只用到了 8 条不同的指令。下表先说明它们的作用,后面的图片给出对应的编码格式。rs1 和 rs2 分别为两个源寄存器,rd 为目的寄存器,imm 为立即数。

指令 作用
lui 将立即数字段放到 rd 的高 20 位,低 12 位清零
beq 两个源寄存器的值相等时,跳转到当前指令地址加分支偏移的位置
lb 从地址 rs1 + imm 读取一个字节,符号扩展后写入 rd
sb 将 rs2 的低 8 位写入地址 rs1 + imm
sw 将 rs2 的 32 位值写入地址 rs1 + imm
addi 寄存器的值与符号扩展后的立即数相加,写入 rd
andi 寄存器的值与符号扩展后的立即数按位与,写入 rd
add 两个寄存器的值相加,写入 rd

指令编码如下:

关于指令的详细功能,可以参考以下两节的内容:

预期结果

目标程序先计算 1 + 2 + … + 100,将结果写入内存,再依次发送 done! 五个字符,最后停留在 end 处循环。

在云平台上预期的效果如下:

可以在串口上看到 done! 的输出,同时在 BaseRAM 的 0x100 偏移处看到 0x13ba=5050 的结果。

注意

这里的偏移 0x100 对应 CPU 使用的字节地址 0x8000_0100,不要把两者混淆。结果按小端方式存储,从低地址到高地址的四个字节依次为 ba 13 00 00。

关于云平台的操作方式,请参考:云平台使用指南

关于仿真的方式,请参考:Vivado 开发环境中的仿真

总结

本实验将前面实现的运算和总线访问部件组合成一个能够执行程序的处理器。无论选择多周期还是流水线,都要让指令正确地改变寄存器、内存和 PC,并通过现有控制器访问 SRAM 和 UART。

学完这节内容我需要做什么?

理解目标程序,选择你的 CPU 实现方式,按照阅读顺序继续学习相关的知识。

作者:cuibst (65.67%), 于越洋 (34.33%)