在verilog中递增一个计数器变量:组合式或顺序式[英] Incrementing a counter variable in verilog: combinational or sequential

本文是小编为大家收集整理的关于在verilog中递增一个计数器变量:组合式或顺序式的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在为DataPath电路实现FSM控制器.控制器内部递增计数器.当我模拟下面的程序时,从未更新计数器.

reg[3:0] counter;

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

然而,如https://stackoverflow.com/questions/8015551/verilog-best-practice-incrementing-a-varible--1. verilog ferilog最佳实践 - 增加变量并仅在顺序块中递增计数器,计数器会增加.

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在仿真时间开始时,因此添加1至x为x.

2)这就是组合循环.该块对"计数器"的变化很敏感,因此即使假设"计数器"被初始化为0,模拟器将永远循环更新"计数器",并且模拟时间将永远不会前进.即.

always block executes -> counter = 1
counter has changed
always block executes -> counter = 2
counter has changed
and so on...

如果您要在其中放一个$ Display语句,您可能会看到此循环发生.否则,似乎只是悬挂了模拟器,不会写波.

第二个示例工作的原因是,您有一个触发器打破组合循环.在每个时钟边缘,"计数器"都会使用" 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

本文地址:https://www.itbaoku.cn/post/2090975.html

问题描述

I am implementing an FSM controller for a datapath circuit. The controller increments a counter internally. When I simulated the program below, the counter was never updated.

reg[3:0] counter;

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

However, on creating an extra variable, counter_next, as described in Verilog Best Practice - Incrementing a variable and incrementing the counter only in the sequential block, the counter gets incremented.

reg[3:0] counter, counter_next;

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

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

Why doesn't the counter get incremented in the previous case? Anything I'm missing?

推荐答案

Ok. I'm assuming that you left some code out of your first example since that shouldn't even compile. However, I think I can elucidate the issue for you anyway.

In a block that looks like this:

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

there are two problems.

1) counter is never initialized. All 'reg' type variables are X at the start of simulation time so adding 1 to X is X.

2) This is what is considered a combinational loop. The block is sensitive to changes in 'counter' so even assuming that 'counter' was initialized to 0 the simulator would loop forever updating 'counter' and simulation time will never advance. i.e.

always block executes -> counter = 1
counter has changed
always block executes -> counter = 2
counter has changed
and so on...

If you were to put a $display statement in there you could see this loop occurring. Otherwise it'll just appear that the simulator is hung and no waves will be written.

The reason the 2nd example works is that you have a flip-flop breaking the combinational loop. At each clock edge 'counter' gets updated with the current value of 'counter_next'. Then the combinational block executes once (and only once) to calculate the new version of 'counter_next'.

You're still lacking an initialization of 'counter' through a reset clause or initial statement so for completeness.

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