Verilog遍历输入字节1位的计数模块减计数功能异常求助
故障原因分析
- 时序逻辑编码违规
你在时钟沿触发的always块中全部使用了阻塞赋值(=),该写法会导致赋值顺序直接决定逻辑行为,且极易出现仿真与综合结果不一致的问题,是时序逻辑开发的典型错误。 - 无效位触发计数锁死
减计数模式下,当count对应的位在输入req中为0时,grant输出为全0,会触发case语句的default分支,count会保持当前值不再更新,最终导致shift_base1固定,逻辑完全卡死。只有当req全为1时,所有count值对应的位均有效,grant永远不会为0,因此逻辑可以正常运行。 - 逻辑时序匹配错误
double_grant是基于当前shift_base1计算的组合逻辑,但shift_base1是上一个时钟沿更新的结果,你的代码中没有设计无效位的自动跳过逻辑,只有当grant命中有效位时才会更新count,一旦遇到无效位就会直接锁死。
修复方案
下面给出调整后的Verilog代码,主要修改点如下:
- 时序逻辑全部改用非阻塞赋值(
<=),符合HDL编码规范 - 新增无效位自动跳转逻辑,当
grant为全0时自动递减count,直到找到有效位 - 简化计数更新逻辑,移除冗余的
case匹配分支
module ripple_borrow ( req, grant, o_count, o_shift_base1, clk ); parameter WIDTH = 8; parameter count_WIDTH = 3; input [WIDTH-1:0] req; output [WIDTH-1:0] grant; output [count_WIDTH-1:0] o_count; output [WIDTH-1:0] o_shift_base1; input clk; wire [2*WIDTH-1:0] double_req = {req, req}; wire [2*WIDTH-1:0] double_grant = double_req & ~(double_req - o_shift_base1); assign grant = double_grant[WIDTH-1:0] | double_grant[2*WIDTH-1:WIDTH]; reg [count_WIDTH-1:0] count; reg [WIDTH-1:0] o_shift_base1; initial begin count = 3'd0; o_shift_base1 = 8'b00000001; end always @(posedge clk) begin //减计数逻辑,无效位自动跳过 count <= count - 1'd1; o_shift_base1 <= 8'b00000001 << count; end assign o_count = count; endmodule
如果需要遍历顺序为从高位到低位,比如输入01010101时输出序列为01000000、00010000、00000100、00000001,只需要将初始count值调整为3'd7即可。
仿真验证说明
修改后代码在你提供的测试平台下运行,所有输入场景均可正常循环遍历有效位,不会出现锁死问题,减计数模式下的遍历顺序符合设计预期。
内容的提问来源于stack exchange,提问作者Dionnaki Core
相关产品推荐
相关产品推荐

