[英]Incrementing a counter variable in verilog: combinational or sequential
我正在为数据路径电路实现FSM控制器。 控制器在内部递增计数器。 当我模拟下面的程序时,计数器从未更新过。
reg[3:0] counter;
//incrementing counter in combinational block
counter = counter + 4'b1;
但是,在创建额外变量counter_next时,如Verilog Best Practice中所述 - 递增变量并仅在顺序块中递增计数器,计数器会递增。
reg[3:0] counter, counter_next;
//sequential block
always @(posedge clk)
counter <= counter_next;
//combinational block
counter_next = counter + 4'b1;
为什么计数器在前一种情况下不会增加? 我缺少什么?
好。 我假设你从第一个例子中留下了一些代码,因为它甚至不应该编译。 但是,我想我无论如何都可以为你解释这个问题。
在一个看起来像这样的块:
always @(*) begin // or always @(counter)
counter = counter + 4'b1;
end
有两个问题。
1)计数器永远不会初始化。 所有'reg'类型变量在模拟时间开始时都是X,因此在X中加1是X.
2)这被认为是一个组合循环。 该块对“计数器”的变化很敏感,因此即使假设“计数器”初始化为0,模拟器也会永远循环更新“计数器”,模拟时间永远不会超前。 即
always block executes -> counter = 1
counter has changed
always block executes -> counter = 2
counter has changed
and so on...
如果你在那里放一个$ display语句,你可以看到这个循环发生了。 否则它只会显示模拟器挂起并且不会写入波形。
第二个例子工作的原因是你有一个触发器打破了组合循环。 在每个时钟边沿,'counter'用'counter_next'的当前值更新。 然后组合块执行一次(并且仅执行一次)以计算“counter_next”的新版本。
由于完整性,你仍然缺少通过reset子句或初始语句初始化'counter'。
reg [3:0] counter;
reg [3:0] counter_next;
always @(*) begin
counter_next = counter + 1;
end
always @(posedge clk or negedge rst_l) begin
if (!rst_l)
counter <= 4'b0;
else
counter <= counter_next;
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.