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,
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
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 113 |
Nodes: | 8 (1 / 7) |
Uptime: | 27:18:27 |
Calls: | 2,498 |
Files: | 8,649 |
Messages: | 1,905,707 |