Vivado 2020.2下寄存器堆R_data输出XXX无法读取数据故障排查
问题根因及修复方案
1. 顶层状态机组合逻辑敏感列表不完整,变量未完全赋值生成锁存
你编写的组合逻辑块always @(State, Rst, count)敏感列表遗漏了go、i、a_o三个输入信号,会导致仿真时组合逻辑输出不会随这些信号的变化实时更新。同时done、count、i、temp、a_i这几个变量仅在部分case分支中赋值,未覆盖所有分支,综合时会生成锁存器,仿真初始值为X且无法正确更新,直接导致寄存器堆的读地址i[3:0]为X,读出来的a_o自然就是不确定值。
修复方法:
- 将组合逻辑敏感列表改为
always @(*)自动推导所有敏感信号 - 在组合逻辑块最开始给所有输出变量赋默认值,避免生成锁存:
always @(*) begin // 所有变量先给默认值 R_en = 0; W_en = 0; StateNext = s1; done = 0; count = 0; i = 0; temp = 0; a_i = 0; case(State) // 原有case逻辑保持不变 endcase end
2. 遍历索引变量i定义为组合逻辑变量,无法保存迭代值
你用来遍历16个寄存器的索引变量i是在组合逻辑块中赋值的,组合逻辑没有存储功能,每次组合逻辑更新后值无法保留到下一个状态周期,导致遍历逻辑完全失效。
修复方法:
将i改为时序逻辑更新,把i的赋值从组合逻辑块移到时序逻辑块中:
// 移除组合逻辑里的i、count、done赋值,改为时序逻辑更新 always @(posedge Clk) begin if (Rst == 1) begin State <= s1; i <= 0; count <= 0; done <= 0; end else begin State <= StateNext; // 按状态更新对应变量 case(StateNext) s2: begin i <= 0; count <=0; done <=0; end s8: i <= i + 1; s7: count <= count + 1; s5: done <= 1; endcase end end
3. 复位释放时机与时钟上升沿对齐,存在仿真调度问题
你的测试激励中Rst在200ns时刻拉低,恰好和第一个时钟上升沿的时刻完全重合,仿真时同步复位可能不会被正确采样,导致寄存器堆的初始值没有被正确写入,所有存储单元初始为X。
修复方法:
调整测试激励的复位释放时间,错开时钟沿:
initial begin Rst = 1; #300 // 错开200ns的时钟上升沿,保证复位至少被一个时钟沿采到 Rst = 0; go = 1; end
按照上述三点修改后,寄存器堆的读地址会正常输出0~15的遍历值,读使能有效时就能正确读出存储单元的初始值,不会再出现不确定值。
内容的提问来源于stack exchange,提问作者broncosaurus
相关产品推荐
相关产品推荐

