EDAboard.com | EDAboard.de | EDAboard.co.uk | WTWH Media

Could you explain the detail of this nonblocking?

Ask a question - edaboard.com

elektroda.net NewsGroups Forum Index - Verilog Language - Could you explain the detail of this nonblocking?

Robert Willy
Guest

Mon Sep 24, 2018 3:45 am   



Hello,
When I run the simulation of the below code, I am surprised after thinking
in more detail. nonblocking has two parts in operation: evaluation and
assignment. In this code snippet, delay 5 units is on the left assignment.
Although I looks like understanding it, I get puzzled after thinking it in
detail: Both C and D change to '02' after 5 delay units of C being '01':


Note: I use clock period=20 units
reg [2:0] C, D;

always @(posedge clk)
begin
#5 C <= 1;
#5 C <= 1+C;
D <= C + 1;
end


The even more puzzling thing is after I comment out the second '#5' line:

always @(posedge clk)
begin
#5 C <= 1;
D <= C + 1;
end

It is found D changes to '02' after 20 delay units of C being '01'!
That is, D changes to '02' after 5 delay units of the second clock rising
edge.
I don't find a useful explanation yet. Could you give me a short description
of the above two examples on the events to C and D?

Best Regards,

Gabor
Guest

Thu Sep 27, 2018 3:45 am   



On Sunday, 9/23/2018 10:18 PM, Robert Willy wrote:
Quote:
Hello,
When I run the simulation of the below code, I am surprised after thinking
in more detail. nonblocking has two parts in operation: evaluation and
assignment. In this code snippet, delay 5 units is on the left assignment.
Although I looks like understanding it, I get puzzled after thinking it in
detail: Both C and D change to '02' after 5 delay units of C being '01':


Note: I use clock period=20 units
reg [2:0] C, D;

always @(posedge clk)
begin
#5 C <= 1;
#5 C <= 1+C;
D <= C + 1;
end


The even more puzzling thing is after I comment out the second '#5' line:

always @(posedge clk)
begin
#5 C <= 1;
D <= C + 1;
end

It is found D changes to '02' after 20 delay units of C being '01'!
That is, D changes to '02' after 5 delay units of the second clock rising
edge.
I don't find a useful explanation yet. Could you give me a short description
of the above two examples on the events to C and D?

Best Regards,


It helps to understand how the simulator performs your code. It's a
bit unusual to use #delays before a non-blocking statement, but the
delay will affect the output as you noticed. A simulator runs each
always block as a sequential program. A #delay before a statement
creates a time delay before executing the statement. For a non-blocking
assignment, this means you wait 5 time units and then schedule the
assignment to take place when the sequence is complete. It's much more
common to code the #delay after the assignment operator like:
c <= #5 1;
This way the sequence flows without any time delay, but the scheduled
assignment happens 5 time units after the sequence completes. Looking
at your code:

always @(posedge clk)
begin
#5 C <= 1;
D <= C + 1;
end

at the first rising edge of clock, the simulator waits 5 time units
then schedules C to become 1 immediately following the execution of
the always block. Then it schedules D to become C + 1 (where C is
the value of C upon entering the block), again as soon as the block
completes. So if C were 0 initially, what you would see is that
5 time units after the first rising clock edge C would become 1
and D would also become 1 (0 + 1). On the next rising edge of
clock, C is already 1 so the scheduled assignment makes no changes.
However now the second assignment to D sees the value 1, and so
D becomes 2 (1 + 1). You'll see this 5 time units after the clock
edge because of the #5 in the first assignment.

Generally speaking, this code does not represent the behavior of
typical logic. The more typical approach is to use only delays
after the non-blocking assignment so the whole block completes in
0 time. Delays are scheduled rather than waited for sequentially.
In fact in your first code:

always @(posedge clk)
begin
#5 C <= 1;
#5 C <= 1+C;
D <= C + 1;
end

the two #5 delays are additive, so actions would occur 10 time
units after the clock edge. The code is interpreted as:

Wait for rising clock edge
wait for 5 time units
schedule C to become 1
wait 5 more time units
schedule C to become C + 1 (using value of C before the clock edge)
schedule D to become C + 1
Apply all scheduled assignments immediately

Note that the first assignment to C is overriden by the second
one. So if you started with C = 0, it would become 1 after the
first clock edge + 10 time units, then 2 after the next edge
plus 10 time units and so on. But if C started as unknown (X)
it would remain X forever.

--
Gabor

Robert Willy
Guest

Sat Sep 29, 2018 9:45 pm   



On Wednesday, September 26, 2018 at 9:39:28 PM UTC-5, Gabor wrote:
Quote:
On Sunday, 9/23/2018 10:18 PM, Robert Willy wrote:
Hello,
When I run the simulation of the below code, I am surprised after thinking
in more detail. nonblocking has two parts in operation: evaluation and
assignment. In this code snippet, delay 5 units is on the left assignment.
Although I looks like understanding it, I get puzzled after thinking it in
detail: Both C and D change to '02' after 5 delay units of C being '01':


Note: I use clock period=20 units
reg [2:0] C, D;

always @(posedge clk)
begin
#5 C <= 1;
#5 C <= 1+C;
D <= C + 1;
end


The even more puzzling thing is after I comment out the second '#5' line:

always @(posedge clk)
begin
#5 C <= 1;
D <= C + 1;
end

It is found D changes to '02' after 20 delay units of C being '01'!
That is, D changes to '02' after 5 delay units of the second clock rising
edge.
I don't find a useful explanation yet. Could you give me a short description
of the above two examples on the events to C and D?

Best Regards,


It helps to understand how the simulator performs your code. It's a
bit unusual to use #delays before a non-blocking statement, but the
delay will affect the output as you noticed. A simulator runs each
always block as a sequential program. A #delay before a statement
creates a time delay before executing the statement. For a non-blocking
assignment, this means you wait 5 time units and then schedule the
assignment to take place when the sequence is complete. It's much more
common to code the #delay after the assignment operator like:
c <= #5 1;
This way the sequence flows without any time delay, but the scheduled
assignment happens 5 time units after the sequence completes. Looking
at your code:

always @(posedge clk)
begin
#5 C <= 1;
D <= C + 1;
end

at the first rising edge of clock, the simulator waits 5 time units
then schedules C to become 1 immediately following the execution of
the always block. Then it schedules D to become C + 1 (where C is
the value of C upon entering the block), again as soon as the block
completes. So if C were 0 initially, what you would see is that
5 time units after the first rising clock edge C would become 1
and D would also become 1 (0 + 1). On the next rising edge of
clock, C is already 1 so the scheduled assignment makes no changes.
However now the second assignment to D sees the value 1, and so
D becomes 2 (1 + 1). You'll see this 5 time units after the clock
edge because of the #5 in the first assignment.

Generally speaking, this code does not represent the behavior of
typical logic. The more typical approach is to use only delays
after the non-blocking assignment so the whole block completes in
0 time. Delays are scheduled rather than waited for sequentially.
In fact in your first code:

always @(posedge clk)
begin
#5 C <= 1;
#5 C <= 1+C;
D <= C + 1;
end

the two #5 delays are additive, so actions would occur 10 time
units after the clock edge. The code is interpreted as:

Wait for rising clock edge
wait for 5 time units
schedule C to become 1
wait 5 more time units
schedule C to become C + 1 (using value of C before the clock edge)
schedule D to become C + 1
Apply all scheduled assignments immediately

Note that the first assignment to C is overriden by the second
one. So if you started with C = 0, it would become 1 after the
first clock edge + 10 time units, then 2 after the next edge
plus 10 time units and so on. But if C started as unknown (X)
it would remain X forever.

--
Gabor


Thanks Gabor. The above code snippet is from a Verilog tutorial. I learn
from you and my simulation as well. It helps a lot.

elektroda.net NewsGroups Forum Index - Verilog Language - Could you explain the detail of this nonblocking?

Ask a question - edaboard.com

Arabic version Bulgarian version Catalan version Czech version Danish version German version Greek version English version Spanish version Finnish version French version Hindi version Croatian version Indonesian version Italian version Hebrew version Japanese version Korean version Lithuanian version Latvian version Dutch version Norwegian version Polish version Portuguese version Romanian version Russian version Slovak version Slovenian version Serbian version Swedish version Tagalog version Ukrainian version Vietnamese version Chinese version Turkish version
EDAboard.com map