4

我正在为数据路径电路实现 FSM 控制器。控制器在内部增加一个计数器。当我模拟下面的程序时,计数器从未更新。

reg[3:0] counter;

//incrementing counter in combinational block
counter = counter + 4'b1;

但是,在创建额外变量 counter_next 时,如Verilog 最佳实践 - 增加变量并仅在顺序块中增加计数器中所述,计数器会增加。

reg[3:0] counter, counter_next;

//sequential block
always @(posedge clk) 
   counter <= counter_next;

//combinational block
counter_next = counter + 4'b1;

为什么在前一种情况下计数器不增加?有什么我想念的吗?

4

1 回答 1

9

好的。我假设您在第一个示例中留下了一些代码,因为它甚至不应该编译。但是,我想无论如何我都可以为您阐明这个问题。

在一个看起来像这样的块中:

always @(*) begin // or always @(counter)
    counter = counter + 4'b1;
end

有两个问题。

1) 计数器从未初始化。所有 'reg' 类型的变量在仿真开始时都是 X,所以在 X 上加 1 就是 X。

2)这被认为是组合循环。该块对“计数器”的变化很敏感,因此即使假设“计数器”被初始化为 0,模拟器也会永远循环更新“计数器”并且模拟时间永远不会提前。IE

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”。

为了完整性,您仍然缺少通过重置子句或初始语句对“计数器”进行初始化。

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
于 2012-12-29T21:12:25.003 回答