我正在为数据路径电路实现FSM控制器。控制器在内部递增计数器。当我模拟下面的程序时,计数器从未更新过。
reg[3:0] counter;
//incrementing counter in combinational block
counter = counter + 4'b1;
但是,在创建额外变量counter_next时,如Verilog Best Practice - Incrementing a variable中所述并仅在顺序块中递增计数器,计数器会递增。
reg[3:0] counter, counter_next;
//sequential block
always @(posedge clk)
counter <= counter_next;
//combinational block
counter_next = counter + 4'b1;
为什么计数器在前一种情况下不会增加?我缺少什么?
答案 0 :(得分:9)
确定。我假设你从第一个例子中留下了一些代码,因为它甚至不应该编译。但是,我想我无论如何都可以为你解释这个问题。
在一个看起来像这样的块中:
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'的新版本。
由于完整性,您仍然缺少通过重置子句或初始语句初始化'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