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

文章详细描述了一个硬件设计中的错误排查过程,从PC和wb_rf_wdata的异常值开始,通过追溯变量赋值路径,发现了信号Z的问题,最终定位到未赋值的load_op变量,确定是LW指令执行时的错误,并提出了修复方案。
摘要由CSDN通过智能技术生成

[ 2067 ns] Error!!! reference: PC = 0xbfc00000, wb_rf_wnum = 0x08, wb_rf_wdata = 0xffffffff mycpu : PC = 0xbfc00000, wb_rf_wnum = 0x08, wb_rf_wdata = 0xxxxxxxxX

由报错信息可知wb_rf_wdata的值应该为0xffffffff,而现在却是0xxxxxxxxX,而出现X的常见原因在第一个bug里已说明,下面要做的就是找到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_res_from_mem的值为Z,这便是导致出错的其中一个原因,但是这并不是最根本的原因,根本原因是找到ms_res_from_mem的值为什么是Z。而信号为Z这种错误往往是由下面两个原因导致的:

  1. RTL里声明为wire型的变量从未被赋值。

  2. 模块调用的信号未连接导致信号悬空。

接下来就是排查ms_res_from_mem出现Z的原因,发现:

 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;

所以接下来查找es_to_ms_bus_r和什么有关,发现es_to_ms_bus_r的值是由es_to_ms_bus赋值得到的,所以接下来排查es_to_ms_bus,打开MEM_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_res_from_mem的值由es_res_from_mem得到,紧接着发现:

 assign es_res_from_mem = es_load_op;

查找es_load_op发现:

 assign {es_alu_op      ,  //135:124
         es_load_op     ,  //123:123   
         es_src1_is_sa  ,  //122:122
         es_src1_is_pc  ,  //121:121
         es_src2_is_imm ,  //120:120
         es_src2_is_8   ,  //119:119
         es_gr_we       ,  //118:118
         es_mem_we      ,  //117:117
         es_dest        ,  //116:112
         es_imm         ,  //111:96
         es_rs_value    ,  //95 :64
         es_rt_value    ,  //63 :32
         es_pc             //31 :0
        } = ds_to_es_bus_r;

发现es_load_op与ds_to_es_bus_r有关,而ds_to_es_bus_r的值又与ds_to_es_bus有关,接下来排查ds_to_es_bus,打开ID_stage.v,查找ds_to_es_bus,发现:

 assign ds_to_es_bus = {alu_op      ,  //135:124
                        load_op     ,  //123:123
                        src1_is_sa  ,  //122:122
                        src1_is_pc  ,  //121:121
                        src2_is_imm ,  //120:120
                        src2_is_8   ,  //119:119
                        gr_we       ,  //118:118
                        mem_we      ,  //117:117
                        dest        ,  //116:112
                        imm         ,  //111:96
                        rs_value    ,  //95 :64
                        rt_value    ,  //63 :32
                        ds_pc          //31 :0
                       };

与上面的ds_to_es_bus_r对照发现es_load_op的值由load_op得到,接下来查找load_op,发现load_op只进行了定义:

 wire        load_op;

却未对load_op赋值,这就是导致前面信号出现Z的原因,接下来我们要给load_op赋值,而给load_op赋什么值呢?我们需要看load_op用于什么指令,因为load_op用在ds_to_es_bus,所以我们向执行阶段找,回到MEM_stage.v,查找ds_to_es_bus发现ds_to_es_bus_r用到了ds_to_es_bus的值,继续查看ds_to_es_bus_r发现:

 assign {es_alu_op      ,  //135:124
         es_load_op     ,  //123:123
         es_src1_is_sa  ,  //122:122
         es_src1_is_pc  ,  //121:121
         es_src2_is_imm ,  //120:120
         es_src2_is_8   ,  //119:119
         es_gr_we       ,  //118:118
         es_mem_we      ,  //117:117
         es_dest        ,  //116:112
         es_imm         ,  //111:96
         es_rs_value    ,  //95 :64
         es_rt_value    ,  //63 :32
         es_pc             //31 :0
        } = ds_to_es_bus_r;

其中包括es_load_op,在前面的分析中我们知道es_load_op和load_op的值一样,所以接下来我们排查es_load_op发现:

 assign es_res_from_mem = es_load_op;

发现与es_res_from_mem有关,从这可以看出load_op指令是一条与访存有关的指令。(实际上该结论在我们前面排查的时候应该就已经得到了)而lab3一共实现了19条指令,这19条指令里只有两条和访存有关,①LW(取字),②SW(存字)。这里很明显访存是取字,所以我们知道了load_op在这里应该执行的是LW指令,所以回到ID_stage.v添加代码给load_op赋值:

 assign load_op = inst_lw;

至此第二个bug解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值