[ 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解决。