计算机组成原理上机实验6 多周期CPU
2018-05-10
90105 字
300 分钟

实验目的

  1. 实现一个多周期MIPS指令集的CPU,支持包括lw、sw、R-type、addi、beq、bgtz、j等指令。
  2. 运行一个计算斐波那契数列的程序,初始为3,3。

实验平台

实验过程(分析)

  1. 模块化设计,主要有以下几个模块

    a) alu模块——算术逻辑单元

    b) regfile模块——寄存器文件

    c) mux模块和mux4模块——2路和4路选择器

    d) IP核生成的Mem模块——存放数据段和代码段

    e) nextpclogic模块——计算下一个PC

    f) dff模块——D触发器,用于多周期各段寄存

    g) control模块——FSM控制regfile、IMem、DMem、nextpclogic和alu

    h) top模块——实例化前几个模块,连接各个信号

  2. alu模块使用case语句判断8种操作类型。

  3. regfile模块用组合逻辑读,时序逻辑写。

  4. Mem是同步读,同步写,且由指定coe文件初始化,coe文件的内容是16进制文本,由Mars编译一个汇编代码生成。

  5. nextpclogic模块通过组合逻辑计算出nextPC的值。

  6. dff模块用一个always在时钟沿触发实现非阻塞赋值。

  7. control模块内实现一个有限状态机,三段式实现:

    (1)时钟上升沿,改变当前状态,cstate<=nstate

    (2)组合逻辑根据当前状态和指令计算次态nstate

    (3)时钟下降沿,根据次态nstate,更新各控制信号(将在下一个上升沿起作用),下一周期需要使用的信号置为对应值,不使用的选择信号置x,不使用的使能置0。

    控制信号如下表:

    状态 S15 S0 S1 S2 S3 S4 S5 S6 S7 S8 S9 S10 S11
    功能信号 Rst Start Instr decode MM addr MM read read WB MM write R-type EXE R-type WB Beq Addi EXE Addi WB Jump
    LorD 0 0 x x 1 x 1 x x x x x x
    MemRead 1 0 0 1 0 0 0 0 0 0 0 0
    MemWrite 0 0 0 0 0 1 0 0 0 0 0 0
    IRWrite 1 0 0 0 0 0 0 0 0 0 0 0
    RegDst x x x x 0 x x 1 x x 0 x
    MemtoReg x x x x 1 x x 0 x x 0 x
    RegWrite 0 0 0 0 1 0 0 1 0 0 1 0
    ALUSrcASel 0 0 1 x x x 1 x 1 1 x x
    ALUSrcBSel 01 11 10 xx xx xx 00 xx 00 10 xx xx
    ALUControl 001 001 001 xxx xxx xxx xxx 010 001 xxx xxx
    Branch 0 0 0 0 0 0 0 0 1 0 0 0
    PCWrite 1 1 0 0 0 0 0 0 0 0 0 0 1
    PCSrc 11① 00 xx xx xx xx xx xx xx 01 xx xx 10
    注:①rst状态下PCSrc=11,利用4路选择器的剩余1路,置初始nextPC=0.

    ②根据Funct具体设置不同的ALUControl

    状态机如下:

  1. top模块实例化其他所有模块,连接各个信号。

  2. bgtz的实现:bgtz是伪指令(类似地有la和li),不是MIPS指令集的指令,编译时会进行处理,转换为几条指令实现。

    这里我用以下三条指令

     slt <div class="mathjax-inline"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="2.649ex" height="2.509ex" style="vertical-align: -0.671ex;" viewBox="0 -791.3 1140.5 1080.4" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title">
    
    t6,
zero,
t1 > 0, that
t6 = 1, else
t6 = 0 addi
t7,
zero,1 # set $t7 = 1 beq
t6,
t7,loop # jump if
t6 = 1, that is to say,
t1 > 0

实现

 bgtz $t1, loop        # repeat if not finished yet.
  1. ram模块的初始化

    IP核选择Block Memory,设置为Single Port RAM,

    宽度为32,深度为256

    选中Load Init File设置,选择初始化coe文件的路径,

    其中coe文件内容为(Text段为0-63,Data段为64-255)

    MEMORY_INITIALIZATION_RADIX=16;
    MEMORY_INITIALIZATION_VECTOR=
    20080100
    200d0150
    8dad0000
    200b0154
    8d6b0000
    200c0154
    8d8c0004
    ad0b0000
    ad0c0004
    21a9fffe
    8d0b0000
    8d0c0004
    016c5020
    ad0a0008
    21080004
    2129ffff
    0009702a
    200f0001
    11cffff7
    08000013
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000000
    00000014
    00000003
    00000003
    …
    
  2. 完整的数据通路

  3. 分析结果

    .data
    fibs: .word   0 : 20        # "array" of  20 words to contain fib values
    size: .word  20             # size of "array" 
    temp: .word 3 3
    .text
          la   $t0, fibs        # load address of array
          la   $t5, size        # load address of size variable
          lw   <div class="mathjax-inline"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="5.103ex" height="2.843ex" style="vertical-align: -0.838ex;" viewBox="0 -863.1 2197.2 1223.9" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title">
    
    t5, 0( t5) # load array size la $t3, temp # load lw
    t3, 0(
    t3) la $t4, temp lw
    t4, 4(
    t4) sw
    t3, 0(
    t0) # F[0] = $t3 sw
    t4, 4(
    t0) # F[1] = $t4 addi
    t1,
    t5, -2 # Counter for loop, will execute (size-2) times loop: lw
    t3, 0(
    t0) # Get value from array F[n] lw
    t4, 4(
    t0) # Get value from array F[n+1] add
    t2,
    t3,
    t2 = F[n] + F[n+1] sw
    t2, 8(
    t0) # Store F[n+2] = F[n] + F[n+1] in array addi
    t0,
    t0, 4 # increment address of Fib. number source addi
    t1,
    t1, -1 # decrement loop counter slt
    t6,
    zero,
    t1 > 0, that
    t6 = 1, else
    t6 = 0 addi
    t7,
    zero,1 # set $t7 = 1 beq
    t6,
    t7,loop # jump if
    t6 = 1, that is to say,
    t1 > 0 out: j out

    完整汇编代码如上,可知程序先向内存数据段读取数组首地址($t0)和大小($t5,循环次数),读取并写入f[0]=3, f[1]=3,然后循环18次,执行f[i]=f[i-1]+f[i-2]计算斐波那契数列。

    如果CPU编写正确,Mem [0-19](由于Data和Text在同一个Ram,故实际上是在64-83)内容将是3、3、6、9、15、24、39、63、102、165、267、432、699、1131、1830、2961、4791、7752、12543、20295

    Reg内容将是:

    $t0:最后一次循环后数组基址——256+4*18=328

    $t1:剩余循环次数——0

    $t2:最后一次的计算结果——20295

    $t3:最后一次的计算数1——7752

    $t4:最后一次的计算数2——12543

    $t5:数组大小——20

    $t6:最后一次不跳转——0

    $t7:1

实验结果

附录: