【BUAA-CO】P3-用Logisim搭建单周期CPU

Posted by     一簇枣泥 on Sunday, November 5, 2023

P3_L0_document:CPU初搭建!(Logisim)

设计方案

20231105设计图.png

1.controller

输出信号 add sub ori lw sw beq lui jal
ALUSrc 0 0 1 1 1 0 0 0
ALUop 0000 0001 0010 0000 0000 0001 0 0
MemWrite 0 0 0 0 1 0 0 0
branch 0 0 0 0 0 1 0 0
RegWrite 1 1 1 1 0 0 1 1
RegDst 1 1 0 0 x 0 0 0
MemToReg 00 00 00 01 x 00 10 11
EXTop x x 00 01 01 01 10 0
jal 0 0 0 0 0 0 0 1

ALUSrc:

ALU运算数的来源

ALUop:

ALU进行什么样的运算?(点开ALU小图观察可得)

Memwrite:

数据存储DM写使能

branch:

是否branch?

RegWrite:

寄存器是否能写入值?连接写使能WE

RegDst:

destination,把哪个reg当作写入的寄存器?

MemToReg:

传什么值给寄存器堆存储?
0-ALU Result;
1-DM Load Data

EXTop:

00-zero extend
01-sign extend
10-imm|| 016,立即数加载至高位

jal:

是否是jal?

2. Next PC的选择

PCSrc = branch & ALUzero 假如这个指令是跳转指令,则ALUop=0001(-),计算结果为0则PCSrc=1,发生跳转。

3.GRF信号说明

GRF信号说明

测试方案

实际上做的时候,运行教程上给的testcode经常会输出x,于是将教程的testcode分为几块debug。

ori $a0, $0, 123
ori $a1, $a0, 456
nop

然而,在运行第一块ori代码的时候就出现了错误。进入controller查看后,发现是ori的连线连错了或门,于是问题得到解决。

以下是我根据教程代码补充所得的测试方案:

ori $a0, $0, 123
ori $a1, $a0, 456
lui $a2, 123            
lui $a3, 0xffff         
ori $a3, $a3, 0xffff    
add $s0, $a0, $a2      
add $s1, $a0, $a3      
add $s2, $a3, $a3      
ori $t0, $0, 0x0000
sw $a0, 0($t0)
sw $a1, 4($t0)
sw $a2, 8($t0)
sw $a3, 12($t0)
sw $s0, 16($t0)
sw $s1, 20($t0)
sw $s2, 24($t0)
lw $a0, 0($t0)
lw $a1, 12($t0)
sw $a0, 28($t0)
sw $a1, 32($t0)
ori $a0, $0, 1
ori $a1, $0, 2
ori $a2, $0, 1
loop0:
beq $a0, $a1, loop1     
beq $a0, $a2, loop2     
beq $a0, $a2, loop0
loop1:sw $a0, 36($t0)
loop2:sw $a1, 40($t0)

ori $t0, $0, 100
sw $a0, -4($t0)
sw $a1, 4($t0)
sw $a2, -8($t0)
sw $a3, 12($t0)
sw $s0, 16($t0)
sw $s1, 20($t0)
sw $s2, 24($t0)
lw $a0, -4($t0)
lw $a1, -8($t0)
sw $a0, 28($t0)
sw $a1, 32($t0)

第一次上机出现了none 0/1value,目前找出来了两个bug:

1.DM数据存储器没有取13-2位,而取了11-0位,这样会导致12、13位非零值的地址中的数据可以相互调用且相互覆盖,产生错误值!

2. 20231105错误连线

如图,21号寄存器连线时连到了20号寄存器那里,所以会有多信号导入(?)导致输出非零值。
这更加说明测试代码需要覆盖全部的寄存器!!!
我写了新的测试代码如下:

.text
ori $20, $0, 12
ori $21, $0, 13
add $23, $20, $21
add $24, $21, $20   #important to detect the problem!

ori $zero, $31, 10
ori $1, $0, 10
ori $2, $1, 10
ori $3, $2, 10
ori $4, $3, 10
ori $5, $4, 10
ori $6, $5, 10
ori $7, $6, 10
ori $8, $7, 10
ori $9, $8, 10
ori $10, $9, 10
ori $11, $10, 10
ori $12, $11, 10
ori $13, $12, 10
ori $14, $13, 10
ori $15, $14, 10
ori $16, $15, 10
ori $17, $16, 10
ori $18, $17, 10
ori $19, $18, 10
ori $20, $19, 10
ori $21, $20, 10
ori $22, $21, 10
ori $23, $22, 10
ori $24, $23, 10
ori $25, $24, 10
ori $26, $25, 10
ori $27, $26, 10
ori $28, $27, 10
ori $29, $28, 10
ori $30, $29, 10
ori $31, $30, 10


ori $a0, $0, 1
add $a1, $a0, $0
ori $a2, $0, 30
sub $a2, $a0, $a0
sub $a2, $a1, $a0
add $a1, $a0, $a2
sub $0, $0, $a1
lui $t0, 0
lui $t0, 1
lui $t0, 2
lui $t0, 3
lui $t0, 65533
lui $t0, 65534
lui $t0, 65535
lui $t0, 25779
lui $t0, 42578
lui $t1, 42524
sub $t0, $t0, $0
sub $t0, $t0, $a0
sub $t0, $t0, $t1

sub $t0, $t0, $t0
ori $t0, 4
lui $a0, 65533
add $a0, $a0, $t1
sw $a0, 4($t0)
ori $t0, 576
sw $a0, 8($t0)
sw $a0, 0($t0)
sw $a0, -4($t0)
sw $a0, -8($t0)

lw $t1, 8($t0)
lw $t2, 0($t0)
lw $t3, -4($t0)
lw $t4, -8($t0)

注意测试时,一个寄存器的读入功能和写出功能都要测试到才好!

思考题汇总

1.上面我们介绍了通过 FSM 理解单周期 CPU 的基本方法。请大家指出单周期 CPU 所用到的模块中,哪些发挥状态存储功能,哪些发挥状态转移功能。

状态存储功能:PC寄存器、GRF寄存器堆中的寄存器

状态转移功能:对于前半段PC-FSM:EXT、PC+4等模块均为状态转移模块;对于后半段GRF-FSM:ALU、DM、controller均发挥状态转移功能。

2.现在我们的模块中 IM 使用 ROM, DM 使用 RAM, GRF 使用 Register,这种做法合理吗? 请给出分析,若有改进意见也请一并给出。

初步分析认为合理。

IM使用ROM:指令一经编译运行,将无法被改变,故选择ROM只读存储器

DM使用RAM:数据可被修改、可被读出,故选择RAM可写随机存储器,并将load和store端口分开

GRF使用Register:寄存器堆,故使用寄存器(?)除了register之外还能使用什么呢

3.在上述提示的模块之外,你是否在实际实现时设计了其他的模块?如果是的话,请给出介绍和设计的思路。

image-20231029154654874

以上是我实现的所有模块,并未设计其它模块。

4.事实上,实现 nop 空指令,我们并不需要将它加入控制信号真值表,为什么?

nop指令指令码为0x00000000,在一个周期内不需要进行任何操作;而controller输出的所有端口在opcode、func没有符合既有控制信号的情况下默认设为0,符合不进行任何操作的需求。

5.阅读 Pre 的 “MIPS 指令集及汇编语言” 一节中给出的测试样例,评价其强度(可从各个指令的覆盖情况,单一指令各种行为的覆盖情况等方面分析),并指出具体的不足之处。

1)beq

测试样例:

image-20231029164042881

p3给出的指导:

image-20231029164120400

beq指令处,情况未考虑充分。目标均在此跳转指令之后,可以增加目标在此跳转指令之前、目标是此跳转指令的情况。

2)add、sub、ori、lui

测试样例:

image-20231029164603011

p3给出的指导:

image-20231029164436476

寄存器数据和无符号立即数方面,均未满足以上的分类,可以增加这些情况的指令。

3)lw、sw

测试样例:

image-20231029164916362

p3给出的指导:

image-20231029164942764

可以增加:

1.目标寄存器是[^$0]时的lw指令;

2.offset是负数和零的情况;

3.[^$base]寄存器中的值是正数和负数的情况。

4)others

  • 可以将32个寄存器初始化成非零值,有利于简化一开始都是零互相赋值的情况。

  • 为更正确地进行测试,如果利用 Mars 进行对拍,应该将 Mars 和自己的 CPU 内存保持一致,因此需要在 Mars 中将 Memory Configuration 设置为 Compact,Data at Address 0。才能让 Mars 的 PC 起始于 0x3000, DM 起始于 0x0000。

一些心得

1.强测对比中测:寄存器覆盖面更广,地址覆盖面更广;

2.上次上机失败原因:addr地址连错+grf多驱动。(但愿这是全部的原因!/praise)

grf多驱动:两个寄存器导线连在了一起。假如两个寄存器的值一样,那么不会出现问题;但是不一样的话,会出现一个信号有两个驱动源,造成问题。

在 Logisim 中,当输出为 “Z” 时,表示输出处于高阻态(High Impedance)状态,即输出电平无法确定,通常发生在以下几种情况下:

1.未连接线: 如果输出端未连接到任何元件或连接到其他逻辑电路中,输出将处于高阻态。确保您的电路中所有必要的信号线都正确连接。

2.多重驱动: 当两个或多个元件尝试驱动同一输出时,可能会导致输出为高阻态。这种情况下,您需要确保只有一个元件可以控制输出。

3.冲突的逻辑: 如果电路中存在逻辑冲突,导致对同一输出有不同的逻辑值要求,输出也可能为高阻态。

4.未初始化元件: 如果元件没有得到适当的初始化,输出可能会处于高阻态。确保您的电路中所有元件都按照其规格正确初始化。

5.时序问题: 时序问题也可能导致输出处于高阻态,例如时钟不同步或信号传播延迟问题。

6.逻辑设计错误: 错误的逻辑设计可能导致输出无法确定。确保您的电路设计是正确的,逻辑正确。

在 Logisim 中,当输出为 “X” 时,表示输出的状态为未知或不确定。这通常发生在以下几种情况下:

1.未连接线: 如果输出端未连接到任何元件或连接到其他逻辑电路中,输出将处于未知状态(“X”)。

2.初始化问题: 有时,元件可能没有得到正确的初始化,导致输出为 “X”。确保您的电路中所有元件都按照其规格正确初始化。

3.逻辑错误: 电路中的逻辑错误可能导致输出为 “X”。逻辑错误可能包括不完整的逻辑路径、未定义的操作等。

4.时序问题: 时序问题也可能导致输出为 “X”,例如时钟不同步或信号传播延迟问题。

5.电路设计错误: 错误的电路设计或不一致的信号状态要求可能导致输出不确定。

3.学姐建议:可以把MUX的include enable都设成no,这样就没有使能端了。

4.注意branch指令不要撞:错误如booez指令不成立的时候,beq成立导致也跳转。可以做两个op判断beq和booez。

「真诚赞赏,手留余香」

一簇枣泥的博客

真诚赞赏,手留余香

使用微信扫描二维码完成支付