CPU设计实战 第四章实践任务一 第四个bug

文章分析了一个CPU在执行过程中出现PC值错误的问题,发现PC值未按预期进行跳转。通过检查反汇编文件,定位到跳转指令,然后在硬件描述语言(VHDL或Verilog)中发现取指阶段的`br_taken`信号错误。进一步排查发现`br_bus`的位宽设置不正确,导致`br_taken`的值无法正确传递,从而修复了问题。修改`BR_BUS_WD`的定义为33位解决了这个问题。
摘要由CSDN通过智能技术生成

[ 2107 ns] Error!!! reference: PC = 0xbfc0038c, wb_rf_wnum = 0x04, wb_rf_wdata = 0xbfb00000 mycpu : PC = 0xbfc00010, wb_rf_wnum = 0x08, wb_rf_wdata = 0x80000000

看到这个报错后,发现是PC的值出错,PC此时的值应该是0xbfc0038c,但是实际PC的值确是0xbfc00010,运行仿真后,查看各阶段的PC:

在PC=0xbfc00010以前,发现均是按顺序执行PC=PC+4,未发现什么异常,而结果却显示此时正确的PC值应该是0xbfc0038c,所以想到可能是PC值为0xbfc00010前面的指令中包含有跳转指令但实际却未执行跳转指令导致的,要想知道这个需要打开CPU_CDE\soft\func_lab3\obj目录下的test.s(该文件是生成的反汇编文件)文件,打开后可看到指令的执行过程,查找0xbfc00010前的指令,结果发现在PC=0xbfc00008时,应该执行跳转指令且可看到跳转的地址刚好是正确的PC地址,现在我们找到了错误的原因,接下来就是解决为什么在PC=0xbfc00008时没有发生跳转。

由于取指阶段使用来取出指令的,所以我们先看取指阶段,打开IF_stage.v,找和pc有关的变量,首先是fs_pc,发现:

 fs_pc <= nextpc;

发现去与nextpc有关,接着找nextpc的和什么相关,发现:

 assign nextpc       = br_taken ? br_target : seq_pc; 
 assign seq_pc       = fs_pc + 3'h4;

可看到当br_taken为0时nextpc=seq_pc,而seq_pc=fs_pc+3'h4,即当br_taken为0时顺序执行,当br_taken值为1时,nextpc =br_target,此时将执行跳转。通过查看波形可看到,在fs_pc=bfc00008时,br_taken的值为0,这便是错误的原因,此时应该执行跳转指令,br_taken的值应该为1才对。下面就分析为什么br_taken的值出现错误。

首先,发现:

 assign {br_taken,br_target} = br_bus;

br_taken的值与br_bus有关,接下来寻找br_bus和什么有关,打开ID_stage.v,查找br_bus,发现在译码阶段:

 assign br_bus       = {br_taken,br_target};

而br_taken,和br_target的值又和下面的变量有关:

 assign br_taken = (   inst_beq  &&  rs_eq_rt
                    || inst_bne  && !rs_eq_rt
                    || inst_jal
                    || inst_jr
                   ) && ds_valid;
 assign br_target = (inst_beq || inst_bne) ? (fs_pc + {{14{imm[15]}}, imm[15:0], 2'b0}) :
                    (inst_jr)              ? rs_value :
                   /*inst_jal*/              {fs_pc[31:28], jidx[25:0], 2'b0};

查看波形可知此时br_taken的值为1,在当前阶段时正确的,可传给br_bus后就出错了,这时发现br_bus好像并没有接受到br_taken的值,因为此时assign br_bus = {br_taken,br_target};应该是拼接后的结果,可看到br_bus只与br_target的值相同,细心观察后发现,br_bus的位宽设置错了,应该是33位,而这里却只有32位,这便是出错的原因,br_bus根本没用接收到br_taken的值。

 查找定义br_bus的位置,发现:

   output [`BR_BUS_WD       -1:0] br_bus

打开mycpu.h

 `ifndef MYCPU_H
     `define MYCPU_H
 ​
     `define BR_BUS_WD       32
     `define FS_TO_DS_BUS_WD 64
     `define DS_TO_ES_BUS_WD 136
     `define ES_TO_MS_BUS_WD 71
     `define MS_TO_WS_BUS_WD 70
     `define WS_TO_RF_BUS_WD 38
 `endif

果然发现BR_BUS_WD为32,而它应该是33,修改代码如下:

 `ifndef MYCPU_H
     `define MYCPU_H
 ​
     `define BR_BUS_WD       33
     `define FS_TO_DS_BUS_WD 64
     `define DS_TO_ES_BUS_WD 136
     `define ES_TO_MS_BUS_WD 71
     `define MS_TO_WS_BUS_WD 70
     `define WS_TO_RF_BUS_WD 38
 `endif

至此第四个bug解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值