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

文章描述了一次对CPU设计中数据错误的追踪和修复过程。通过分析错误信息,发现wb_rf_wdata值不正确,追溯到ALU模块的SRL操作存在问题。在SRL和SRA结果处理部分,发现代码中位宽定义错误,修正后解决了问题。
摘要由CSDN通过智能技术生成

[ 888537 ns] Error!!! reference: PC = 0xbfc88c90, wb_rf_wnum = 0x02, wb_rf_wdata = 0xadff20c0 mycpu : PC = 0xbfc88c90, wb_rf_wnum = 0x02, wb_rf_wdata = 0x2dff20c0

从报错信息上来看,PC值是对的,但是wb_rf_wdata的值是错的,从报错可以看出是wb_rf_wdata的值应该是0xadff20c0而此时是0x2dff20c0,下面要做的就是找到bug位于哪里,由变量名wb_rf_wdata可知,该变量应该在访存阶段,打开WB.stage.v,找到wb_rf_wdata变量发现:

 assign debug_wb_rf_wdata = ws_final_result;

继续查找wc_final_result与什么有关:

 assign {ws_gr_we       ,  //69:69
         ws_dest        ,  //68:64
         ws_final_result,  //63:32
         ws_pc             //31:0
        } = ms_to_ws_bus_r;

发现wc_final_result是由ms_to_ws_bus_r赋值的,由ms_to_ws_bus_r继续找下去,发现:

  ms_to_ws_bus_r <= ms_to_ws_bus;

所以接下来找ms_to_ws_bus和什么相关,打开MEM_stage.v查找ms_to_ws_bus发现:

 assign ms_to_ws_bus = {ms_gr_we       ,  //69:69
                        ms_dest        ,  //68:64
                        ms_final_result,  //63:32
                        ms_pc             //31:0
                       };

由此可知,ws_final_result的值是由ms_final_result传递过去的,接下来查找ms_final_result发现:

 assign ms_final_result = ms_res_from_mem ? mem_result
                                          : ms_alu_result;

ms_final_result的值由该问号表达式决定,通过查看波形发现ms_res_from_mem的值为0,所以ms_final_result=ms_alu_result,ms_alu_result的值出错就是导致错误的原因,下面继续追ms_alu_result发现:

 assign {ms_res_from_mem,  //70:70
         ms_gr_we       ,  //69:69
         ms_dest        ,  //68:64
         ms_alu_result  ,  //63:32
         ms_pc             //31:0
        } = es_to_ms_bus_r;

ms_alu_result与es_to_ms_bus_r有关,而es_to_ms_bus_r又与es_to_ms_bus有关,接下来打开EXE_stage.v,查找es_to_ms_bus发现:

 assign es_to_ms_bus = {es_res_from_mem,  //70:70
                        es_gr_we       ,  //69:69
                        es_dest        ,  //68:64
                        es_alu_result  ,  //63:32
                        es_pc             //31:0
                       };

所以 ms_alu_result的值由es_alu_result得到,接下来排查es_alu_result发现:

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

通过波形查看es_alu_result的值发现,此时es_alu_result的值为0x2dff20c0,因为.alu_result是output变量,所以判断是ALU内部出现了错误,我们先查看一下PC=0xbfc88c90执行的是什么操作,打开test.s查看反汇编代码,搜索xbfc88c90,发现:

 bfc88c90:   00081002    srl v0,t0,0x0

所以执行的是SRL逻辑右移操作,接下来打开alu.v排查SRL相关代码,首先看到控制信号op_srl,通过波形查看到op_srl此时的值确实是1,接着继续查找发现:

 assign alu_result = ({32{op_add|op_sub}} & add_sub_result)
                   | ({32{op_slt       }} & slt_result)
                   | ({32{op_sltu      }} & sltu_result)
                   | ({32{op_and       }} & and_result)
                   | ({32{op_nor       }} & nor_result)
                   | ({32{op_or        }} & or_result)
                   | ({32{op_xor       }} & xor_result)
                   | ({32{op_lui       }} & lui_result)
                   | ({32{op_sll       }} & sll_result)
                   | ({32{op_srl|op_sra}} & sr_result); // op_srl表示逻辑右移,op_sra表示算术右移 

可看到当op_srl的值为1的时候,alu_result=sr_result,接下来查看sr_result的值和什么有关,发现:

 // SRL, SRA result
 assign sr64_result = {{32{op_sra & alu_src2[31]}}, alu_src2[31:0]} >> alu_src1[4:0];
 assign sr_result   = sr64_result[30:0];

看到这里,通过波形查看sr64_result的值,发现是0xadff20c0(10101101111111110010000011000000),而sr_result的值是0x2dff20c0(00101101111111110010000011000000)只有一位的差别,这下就明白了,错误的原因就是sr64_result[30:0]这里位宽写错了,应该是32位,而这里只有31位,修改代码如下:

 // SRL, SRA result
 assign sr64_result = {{32{op_sra & alu_src2[31]}}, alu_src2[31:0]} >> alu_src1[4:0];
 assign sr_result   = sr64_result[31:0];

值得一提的是这里通过利用op_sra & alu_src2[31]巧妙的将逻辑右移和算术右移的结果都用sr_result来表示,当op_sra为0时表示执行的是SRL(逻辑右移),右移后左边补32个0,sr64_result[31:0]就是逻辑右移的结果。当op_sra为1时,表示执行的是SRA(算术右移),右移后左边补32个符号位(正数补0,负数补1),此时sr64_result[31:0]就是算术右移的结果。

至此第六个bug解决,第四章实践任务一的所有bug全部解决。

 

此时测试已通过。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值