Verilog中bitreverse位反转函数返回结果晚一个时钟周期问题
Verilog位反转函数输出延迟1时钟周期问题修复
问题现象
在Verilog中实现字内比特顺序翻转函数时,函数位反转逻辑本身功能正确,但调用后不会在当前时钟周期返回结果,输出延迟1个时钟周期。
使用的位反转函数代码:
function [n-1:0] bitreverse; input [n-1:0] in; reg [n:0] idx; for(idx = 0; idx <= (n-1); idx = idx + 1) begin bitreverse [idx]= in[(n-1)-idx]; end endfunction
调用逻辑代码:
parameter K = 4; parameter N = K*2; parameter n = $clog2(N); reg [n-1:0] j = 0; reg [n-1:0] i = 0; always @(posedge clock) begin: Decode if (j <= N-1) begin i = bitreverse(j); // 后续业务逻辑 j = j +1; end end
实际运行波形:
问题根因
这个延迟不是函数本身的逻辑错误,是三个不规范编码点叠在一起导致的仿真异常:
- 定义的function默认是静态类型,内部声明的
idx寄存器是全局静态存储的,所有函数调用共享这一个变量,仿真调度时容易残留上一次调用的中间状态,无法保证当次调用的循环逻辑在当前执行周期内完成 - 时钟触发的时序always块中,对
j和i都使用了阻塞赋值=,这是Verilog编码的典型问题:时序逻辑用阻塞赋值会打乱仿真事件调度顺序,轻则出现结果晚一拍的现象,严重时会导致仿真结果和最终综合出的电路功能完全不一致 - 纯组合逻辑的位反转运算被放在时序块内执行,进一步放大了调度异常的影响
修复方案
- 把位反转函数声明为
automatic自动类型,循环变量改用integer类型,函数内部加完整的begin-end块界定作用域,彻底避免静态变量导致的状态残留:
function automatic [n-1:0] bitreverse; input [n-1:0] in; integer idx; begin for(idx = 0; idx < n; idx = idx + 1) begin bitreverse[idx] = in[(n-1)-idx]; end end endfunction
- 把位反转逻辑从时序always块中剥离,用组合逻辑赋值实现,保证
i随时跟随j变化无延迟;时序块内的寄存器更新统一改用非阻塞赋值<=,从根源上避免调度顺序问题:
parameter K = 4; parameter N = K*2; parameter n = $clog2(N); reg [n-1:0] j = 0; wire [n-1:0] i; // 组合逻辑完成位反转,无时钟延迟 assign i = bitreverse(j); always @(posedge clock) begin: Decode if (j <= N-1) begin // 此处直接使用i的值完成后续逻辑 // 其他业务逻辑 j <= j + 1; // 时序寄存器更新统一用非阻塞赋值 end end
修改后位反转结果会在j变化的当拍稳定输出,不存在1个时钟周期的延迟。
内容的提问来源于stack exchange,提问作者R0WTAG
相关产品推荐
相关产品推荐

