P3_L0_document:CPU初搭建!(Logisim)
设计方案
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信号说明
测试方案
实际上做的时候,运行教程上给的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.
如图,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.在上述提示的模块之外,你是否在实际实现时设计了其他的模块?如果是的话,请给出介绍和设计的思路。
以上是我实现的所有模块,并未设计其它模块。
4.事实上,实现 nop
空指令,我们并不需要将它加入控制信号真值表,为什么?
nop指令指令码为0x00000000,在一个周期内不需要进行任何操作;而controller输出的所有端口在opcode、func没有符合既有控制信号的情况下默认设为0,符合不进行任何操作的需求。
5.阅读 Pre 的 “MIPS 指令集及汇编语言” 一节中给出的测试样例,评价其强度(可从各个指令的覆盖情况,单一指令各种行为的覆盖情况等方面分析),并指出具体的不足之处。
1)beq
测试样例:
p3给出的指导:
beq指令处,情况未考虑充分。目标均在此跳转指令之后,可以增加目标在此跳转指令之前、目标是此跳转指令的情况。
2)add、sub、ori、lui
测试样例:
p3给出的指导:
寄存器数据和无符号立即数方面,均未满足以上的分类,可以增加这些情况的指令。
3)lw、sw
测试样例:
p3给出的指导:
可以增加:
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。
「真诚赞赏,手留余香」
真诚赞赏,手留余香
使用微信扫描二维码完成支付
