Incorrect behaviour of a non-blocking assignment.

Guest
Hi all,
In this Verilog code, clk1 is correctly lifted high at t = 5, but clk2
is not lifted high at t = 10. Instead, it goes high at t = 15, even
though *all* assignments are non blocking. This program, though, works
correctly using the fork-join construct. Any ideas why is it so ??? I
am using NCVerilog compiler and Simvision viewer.

module surprise (clk1, clk2);
output clk1, clk2;
reg clk1, clk2;

initial
begin
clk1 <= 1'b0;
clk2 <= 1'b0;
#5 clk1 <= 1'b1;
#10 clk2 <= 1'b1;
#15 $finish;
end

initial
begin
$shm_open ("surprise.shm");
$shm_probe ("as");
end

endmodule

Best regards,
Amit.
 
<amitsheth@gmail.com> wrote in message
news:1147942037.103192.244660@i40g2000cwc.googlegroups.com...
Hi all,
In this Verilog code, clk1 is correctly lifted high at t = 5, but clk2
is not lifted high at t = 10. Instead, it goes high at t = 15, even
though *all* assignments are non blocking. This program, though, works
correctly using the fork-join construct. Any ideas why is it so ??? I
am using NCVerilog compiler and Simvision viewer.

module surprise (clk1, clk2);
output clk1, clk2;
reg clk1, clk2;

initial
begin
clk1 <= 1'b0;
clk2 <= 1'b0;
#5 clk1 <= 1'b1;
#10 clk2 <= 1'b1;
#15 $finish;
end

initial
begin
$shm_open ("surprise.shm");
$shm_probe ("as");
end

endmodule

Best regards,
Amit.
The #s are additive. It completes #5 first then #10 and then #15. That's why
clk2 rises at #15.

It works with fork/join because this construct simulataneously runs the
logic within each fork. I assume you have:
fork
begin
#5 clk1 = 1;
end
begin
#10 clk2 = 1;
end
join

That will run both the clk1 and clk2 statements at the same time instead of
waiting until one completes before starting the next.

Mike
 
But then, isn't this against the defined behaviour of a non-blocking
assignment in Verilog ?
 
amitsheth@gmail.com wrote:
But then, isn't this against the defined behaviour of a non-blocking
assignment in Verilog ?

No. When you have:
#n stmt;

what it means is delay for n time units and then do stmt. Doesn't
matter what stmt is. In this context, #n is blocking.

If you want to delay a non-blocking assignment without blocking the
execution of the code that follows it, put the delay after the <=, as
in:
a <= #5 b;
c <= #10 d;

This will do what you expected.

-cb
 
The assignment is nonblocking. The delay control that you put in front
of the statement is blocking. The statement will not start to execute
until the delay has passed. Note that this also means that the
right-hand-side of the assignment will not be evaluated until the delay
has passed either.

If you wanted to start the assignment immediately, and then proceed to
the next statement without blocking, but delay the completion of the
assignment, then you need to use an intra-assignment delay. The syntax
for this would be

clk1 <= #5 1'b1;
clk2 <= #10 1'b1;

This will evaluate the right-hand-side, then schedule the update to
happen after the delay, and then continue with the following statement
without blocking.
 
Just to be 100% clear, the following is identical to your code:

initial
begin
clk1 <= 1'b0;
clk2 <= 1'b0;
#5;
clk1 <= 1'b1;
#10;
clk2 <= 1'b1;
#15;
$finish;
end

Can you see how the delays work now?
 
Many, many thanks to all of you for clarifying my doubts !!!

Best regards,
Amit.
 

Welcome to EDABoard.com

Sponsor

Back
Top