在verilog中增加计数器变量:组合或顺序

时间:2012-12-29 16:08:34

标签: hardware verilog fpga sequential

我正在为数据路径电路实现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;

为什么计数器在前一种情况下不会增加?我缺少什么?

1 个答案:

答案 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