2 added 4 characters in body
source | link

If you are primarily a software engineer, you can think of Verilog as using internal copies of the assigned variables within the always block. In implementation terms, the "internal variables" are not really there, but it is never the less a good way of visualising how it works.

Consider the following code:

wire a, b;
always @ (posedge clk) begin
    a = a + 1;
    if (a) ...
end
always @ (posedge clk) begin
    b <= b + 1;
    if (b) ...
end

This is effectively performed as:

wire a, b;
always @ (posedge clk) begin
    var a_int = a;
    a_int = aa_int + 1;
    if (a_int) ...
    a = a_int;
end
always @ (posedge clk) begin
    var b_int = b;
    b_int = b + 1;
    if (b) ...
    b = b_int;
end

Notice how non-blocking statements cause any calculations to be performed on the external (global if you will) variable. However blocking statements cause the calculations to be performed using the internal (local) variable.

At the end of the always block, the resulting value of the internal variable is assigned back to the external one.

In your case, you are using non-blocking assignments for count, so your calculations will use the external variable, which will contain the "old" value, and not the "new" incremented value.


As you become more familiar, you start instead thinking in terms of hardware as @Oldfart describes.


Side note: This is why it is a bad idea to mix blocking and non-blocking. You end up calculating on an unpredictable combination of internal and external values, which can result in very different synthesis vs simulation results.

If you are primarily a software engineer, you can think of Verilog as using internal copies of the assigned variables within the always block. In implementation terms, the "internal variables" are not really there, but it is never the less a good way of visualising how it works.

Consider the following code:

wire a, b;
always @ (posedge clk) begin
    a = a + 1;
    if (a) ...
end
always @ (posedge clk) begin
    b <= b + 1;
    if (b) ...
end

This is effectively performed as:

wire a, b;
always @ (posedge clk) begin
    var a_int = a;
    a_int = a + 1;
    if (a_int) ...
    a = a_int;
end
always @ (posedge clk) begin
    var b_int = b;
    b_int = b + 1;
    if (b) ...
    b = b_int;
end

Notice how non-blocking statements cause any calculations to be performed on the external (global if you will) variable. However blocking statements cause the calculations to be performed using the internal (local) variable.

At the end of the always block, the resulting value of the internal variable is assigned back to the external one.

In your case, you are using non-blocking assignments for count, so your calculations will use the external variable, which will contain the "old" value, and not the "new" incremented value.


As you become more familiar, you start instead thinking in terms of hardware as @Oldfart describes.


Side note: This is why it is a bad idea to mix blocking and non-blocking. You end up calculating on an unpredictable combination of internal and external values, which can result in very different synthesis vs simulation results.

If you are primarily a software engineer, you can think of Verilog as using internal copies of the assigned variables within the always block. In implementation terms, the "internal variables" are not really there, but it is never the less a good way of visualising how it works.

Consider the following code:

wire a, b;
always @ (posedge clk) begin
    a = a + 1;
    if (a) ...
end
always @ (posedge clk) begin
    b <= b + 1;
    if (b) ...
end

This is effectively performed as:

wire a, b;
always @ (posedge clk) begin
    var a_int = a;
    a_int = a_int + 1;
    if (a_int) ...
    a = a_int;
end
always @ (posedge clk) begin
    var b_int = b;
    b_int = b + 1;
    if (b) ...
    b = b_int;
end

Notice how non-blocking statements cause any calculations to be performed on the external (global if you will) variable. However blocking statements cause the calculations to be performed using the internal (local) variable.

At the end of the always block, the resulting value of the internal variable is assigned back to the external one.

In your case, you are using non-blocking assignments for count, so your calculations will use the external variable, which will contain the "old" value, and not the "new" incremented value.


As you become more familiar, you start instead thinking in terms of hardware as @Oldfart describes.


Side note: This is why it is a bad idea to mix blocking and non-blocking. You end up calculating on an unpredictable combination of internal and external values, which can result in very different synthesis vs simulation results.

1
source | link

If you are primarily a software engineer, you can think of Verilog as using internal copies of the assigned variables within the always block. In implementation terms, the "internal variables" are not really there, but it is never the less a good way of visualising how it works.

Consider the following code:

wire a, b;
always @ (posedge clk) begin
    a = a + 1;
    if (a) ...
end
always @ (posedge clk) begin
    b <= b + 1;
    if (b) ...
end

This is effectively performed as:

wire a, b;
always @ (posedge clk) begin
    var a_int = a;
    a_int = a + 1;
    if (a_int) ...
    a = a_int;
end
always @ (posedge clk) begin
    var b_int = b;
    b_int = b + 1;
    if (b) ...
    b = b_int;
end

Notice how non-blocking statements cause any calculations to be performed on the external (global if you will) variable. However blocking statements cause the calculations to be performed using the internal (local) variable.

At the end of the always block, the resulting value of the internal variable is assigned back to the external one.

In your case, you are using non-blocking assignments for count, so your calculations will use the external variable, which will contain the "old" value, and not the "new" incremented value.


As you become more familiar, you start instead thinking in terms of hardware as @Oldfart describes.


Side note: This is why it is a bad idea to mix blocking and non-blocking. You end up calculating on an unpredictable combination of internal and external values, which can result in very different synthesis vs simulation results.