CPU设计实战-第四章实践任务一简单CPU参考设计调试

简单CPU参考设计调试之DeBug—MyCPU部分

记一笔:
Run All 选项是在进入仿真页面之后才有的选项,且其运行的过程在右下角提示。
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第1张图片

1.信号传递Bug

CPU设计实战-第四章实践任务一简单CPU参考设计调试_第2张图片
分别添加五段的PC信号值不难发现,IF_PC => ID_PC未通 EXE_PC,即执行阶段未接收到来自译码阶段的PC值。检查发现:
if把数据传给了id,但是id_stage里面没有进行fs_to_ds_bus_r <= fs_to_ds_bus。去id模块,发现ds_valid没有被赋值。
修改前:
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第3张图片
修改后:

always @(posedge clk) begin                     // Bug 1
    if(reset) begin
        ds_valid <= 1'b0;
    end
    else if(ds_allowin) begin
        ds_valid <= fs_to_ds_valid;
    end
    if (fs_to_ds_valid && ds_allowin) begin
        fs_to_ds_bus_r <= fs_to_ds_bus;
    end
end

2.典型"Z"信号Bug

CPU设计实战-第四章实践任务一简单CPU参考设计调试_第4张图片
这种情况往往是因为变量没有赋值造成的。找到id_stage模块发现:
load_op没有相关赋值语句。在合适的位置添加即可:
load_op表示的是load的operate部分此部分应该与lw指令相连接。
在这里插入图片描述

仿真Bug小插曲

完成上面的逻辑Bug,重新进行仿真,出现如下小插曲:
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第5张图片
此种提示大部分是由于敲代码时有些变量敲错的问题,所以不用惊慌。点击ok就能查看到问题精确定位的文件路径:
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第6张图片
以记事本打开便可以看到精确的错误定位。
我的Bug定位为:ID.stage 的第 128行和第三行

CPU设计实战-第四章实践任务一简单CPU参考设计调试_第7张图片

运用新工具-基于Trace比对的调试

3.Addiu指令实例传参Bug

Run All之后出现第一个trace比对错误,其比对错误信息提示来自如下相关代码:
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第8张图片
可以看出其比对的相关信息依次是:PC值、写回的目的寄存器、写回的目的数据
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第9张图片
分析:PC值为 0x bfc00000,其代表的具体是哪一条指令呢?
lab3\CPU_CDE\soft\func_lab3\obj\test.s 中搜索 bfc00000 可以看到其对应的指令:
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第10张图片
0x2408 ffff 其对应的指令 001001 00000 01000 1111111111111111
查表可知,其对应的指令格式为addiu指令,且出错位置在写的数据上,所以需要排查alu模块与EXE_stage模块,发现:
EXE_stage模块参数实例化错误
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第11张图片
更改为:

alu u_alu(                 
    .alu_op     (es_alu_op    ),
    .alu_src1   (es_alu_src1  ),
    .alu_src2   (es_alu_src2  ),
    .alu_result (es_alu_result)
    );

4.Bug

CPU设计实战-第四章实践任务一简单CPU参考设计调试_第12张图片
可以看到 PC 出错了,肯定是要找分支指令或者跳转指令,我们看看附近的几条指令(test.s文件)。

/media/sf_func_lab3/start.S:19
bfc00004:	2408ffff 	li	t0,-1
/media/sf_func_lab3/start.S:20
bfc00008:	100000e0 	b	bfc0038c <locate>
/media/sf_func_lab3/start.S:21
bfc0000c:	00000000 	nop
/media/sf_func_lab3/start.S:24
bfc00010:	3c088000 	lui	t0,0x8000
/media/sf_func_lab3/start.S:25
bfc00014:	25290001 	addiu	t1,t1,1

很明显可以看到 bfc00008 这条指令是分支指令,而 mycpu 没进行跳转。
首先先说明 nop 指令,这里很善良的将延迟槽指令设置为 nop,和上面一样,nop 指令也不需要特别实现。
控制流首先流入预取指阶段,然后预取指阶段更新 PC 并且访问 RAM 获得指令,PC 和 RAM 最终同时流入译码阶段,在译码阶段通过组合逻辑控制预取指阶段完成跳转。
我们 预期的执行顺序
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第13张图片
可以看到,在我们的预期中,分支指令的前置判断是由译码阶段完成的。
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第14张图片
这条 B 指令由 r0 恒为 0 和 BEQ 指令得到。
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第15张图片
我们可以发现在这条延迟槽指令时,本应有assign br_bus = {br_taken,br_target};,但是最下端两个信号却相同,所以即可找出问题。
问题出现文件路径:\lab3\CPU_CDE\mycpu_verify\rtl\myCPU\mycpu.h
更改位宽:

`define BR_BUS_WD       33

5.Bug

全局出错
在这里插入图片描述
这个错误还是在alu模块(前后位宽不匹配赋值):
在这里插入图片描述
更改:

assign sr_result   = sr64_result[31:0];

6.Bug

CPU设计实战-第四章实践任务一简单CPU参考设计调试_第16张图片
循环这种情况是由于 RTL 代码中存在组合回路,不好找,若恰巧看到这行,它的错误还是很明显的。
alu.v模块的错误:
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第17张图片
更改:

assign or_result  = alu_src1 | alu_src2;

PC-Bug小插曲

上面依次解决完之后,重新运行发现这个现象。。。
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第18张图片
观察发现:每次运行报错的写回级的PC与trace.txt不一致,但是其目的寄存器号和数据却是正确的。什么原因造成的呢?

7.最后一个Bug

错误文件路径:mycpu_verify => rtl => myCPU => tools.v
CPU设计实战-第四章实践任务一简单CPU参考设计调试_第19张图片
仔细一点就会发现这里的decoder_6_64模块的译码根本不够64位,即只有【62:0】,所以应该更改为:

generate for (i=0; i<64; i=i+1) begin:gen_for_dec_6_64     //Bug 7

成功上板视频展示:

上板实验时建议先把所有拨码开关拨上,此时的计数速度最慢,便于观察实验现象。然后可以拨下一两个,速度适中。
视频链接:简单CPU设计参考实践任务

参考:

借鉴相关博客链接:
CPU设计实战 lab3
CPU设计实战lab3—任务1 简单CPU参考设计调试

你可能感兴趣的:(计算机硬件,fpga开发)