Mod-16计数器代码中for循环工作机制的技术问询
Mod-16计数器代码疑问解答
代码重现
module counter_16 ( input clk, input reset, // Synchronous active-high reset output reg [3:0] q); integer i; always @(posedge clk) begin q<=0; if (reset) q <= 4'd0; else for (i=0; i<16; i=i+1) begin q <= q+1; end end endmodule
问题解答
1. 每个时钟沿触发时输出会不会变为15?
不会。实际运行时,每个非复位的时钟沿到来后,q的值只会在上一个值的基础上加1(和普通Mod-16计数器行为一致),不会直接跳到15。当q走到15后,下一个时钟沿会自动溢出回到0,完成Mod-16循环。
2. always块中for循环的工作原理
要理解这个for循环,必须先明确Verilog中非阻塞赋值(<=)的核心特性:
- 非阻塞赋值的右侧表达式会在时钟沿触发时立即计算,使用的是触发前的变量旧值;
- 所有非阻塞赋值的左侧更新,会在整个
always块执行完毕后统一完成; - 同一个变量的多次非阻塞赋值,只有最后一次的更新会生效(若所有更新的目标值相同,结果等价于只执行一次)。
回到你的代码:
当reset为低时,for循环会执行16次q <= q+1,但每次计算q+1时,用的都是时钟沿触发前q的旧值,所以这16次赋值的右侧结果完全相同(都是旧q值 +1)。在块执行完毕后,q只会被更新为这个相同的值,等同于只执行了一次q <= q+1。
另外,开头的q<=0会被后续的赋值覆盖——因为后续的reset分支或else分支的赋值语句在代码顺序上更靠后,最终生效的是最后一条对q的非阻塞赋值。
简单说:这个for循环在硬件上没有实际意义,它不会让q在一个时钟周期内加16,反而因为非阻塞赋值的特性,最终效果和去掉for循环、直接写q <= q+1完全一致。
内容的提问来源于stack exchange,提问作者Sanskar jaiswal
相关产品推荐
相关产品推荐

