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

```reg[3:0] counter;

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

```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...
```

```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
```

### 问题描述

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
```