EDAboard.com | EDAboard.eu | EDAboard.de | EDAboard.co.uk | RTV forum PL | NewsGroups PL

Non-Blocking versus blocking

elektroda.net NewsGroups Forum Index - Verilog Language - Non-Blocking versus blocking

Goto page Previous  1, 2, 3, 4  Next

Jonathan Bromley
Guest

Sat May 22, 2010 10:38 pm   



On Fri, 21 May 2010 11:40:22 -0700 (PDT), Patrick Maupin wrote:

Quote:
Yes, I should have known that you would be both pedantic and
dismissive.

"Pedantic" I regard as a compliment in this context, because
it's too easy to say things that are unclear or have loopholes;
pedantry is useful. "Dismissive" is less welcome; I'm sorry
you felt that. I think we are diametrically opposed on some
"cultural" issues about how these things are best done, but
that doesn't mean I dismiss your position; I'm just rather
keen to expose any weaknesses I perceive in it :-)

Quote:
Of course you know I believe that
[the use of NBA to give meaning to "at the same time"]
is the right answer, so of course you show an opposite example.

Yes, because it is important to be pedantic. The notion of
"at the same time" is not at all simple in Verilog (take
a look at the LRM description of the scheduler!) and it
is completely inappropriate to use such a phrase when
trying to be precise about what makes sense and what doesn't.
By contrast, VHDL's extremely rigid evaluate/update model
makes it rather easy to reason about "at the same time"
provided you avoid a very tiny set of well-documented
loopholes in the language (the broken form of shared
variable in VHDL93, sharing access to files).

Quote:
Ahhh, so you *do* understand.

Well, of course I do to some extent; and, of course, so
do you. We both know perfectly well how to achieve the
results we need. The difference seems to be that you
are a vigorous apologist for the status quo, while I
would love to have things be very different. However,
I'm sufficiently pragmatic to know that I can't make
a real difference. That doesn't, and shouldn't, stop
me having a good old rant about it from time to time :-)

Quote:
But yes, a C semaphore or mutex or
monitor requires something *below* the level of the language

I don't think I agree with that. C is a sufficiently low-level
language that you can create those primitives within the core
language if you wish to do so.

Quote:
whereas
the Verilog language itself provides the needed primitives, and, let's
face it, "evaluate/update" is what has to happen with clocked
processes in all but the simplest cases.

Right; but Verilog does leave Pandora's box wide open, doesn't it?
Since Verilog does not _enforce_ the use of nonblocking assignment
to shared variables, it effectively has free uncontrolled sharing
of variables among concurrent processes. And yet it didn't, until
SystemVerilog, have even a mutex or semaphore available! This
situation is tolerable only because many (most??) Verilog users
are working within a framework that looks pretty much like
synthesisable logic, where a few fairly simple coding guidelines
are enough to keep you out of trouble. Anyone who's tried to
write a reasonably sophisticated testbench in Verilog, with
multiple threads of control, either is familiar with the
problem of mutual exclusion and has tricks for dealing with
it, or has their head buried in the sand.

--
Jonathan Bromley

Andy
Guest

Sat May 22, 2010 11:40 pm   



On May 21, 1:40 pm, Patrick Maupin <pmau...@gmail.com> wrote:
Quote:

You can easily be as undisciplined in C.  The fact that C has no
concurrency, but C + package allows you concurrency doesn't mean that
C + package enforces anything on the user.


And just like C + package, Verilog does not enforce anything either.

Andy

Patrick Maupin
Guest

Sun May 23, 2010 6:22 am   



On May 22, 4:38 pm, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:
Quote:
On Fri, 21 May 2010 11:40:22 -0700 (PDT), Patrick Maupin wrote:
Yes, I should have known that you would be both pedantic and
dismissive.

"Pedantic" I regard as a compliment in this context, because
it's too easy to say things that are unclear or have loopholes;
pedantry is useful. "Dismissive" is less welcome; I'm sorry
you felt that.

Well, you did use the word "nonsense" instead of simply explaining
that my statement simply required a (bit, lot?) more qualification...

Quote:
I think we are diametrically opposed on some
"cultural" issues about how these things are best done, but
that doesn't mean I dismiss your position; I'm just rather
keen to expose any weaknesses I perceive in it Smile

Sure, and the pedantry is fine and helpful in that regard.

Quote:
Of course you know I believe that

[the use of NBA to give meaning to "at the same time"]

is the right answer, so of course you show an opposite example.

Yes, because it is important to be pedantic. The notion of
"at the same time" is not at all simple in Verilog (take
a look at the LRM description of the scheduler!) and it
is completely inappropriate to use such a phrase when
trying to be precise about what makes sense and what doesn't.

But, if all assignments in clocked processes are nonblocking, "at the
same time" can make a great deal of sense when dealing with
combinations of those signals.

Quote:
By contrast, VHDL's extremely rigid evaluate/update model
makes it rather easy to reason about "at the same time"
provided you avoid a very tiny set of well-documented
loopholes in the language (the broken form of shared
variable in VHDL93, sharing access to files).

Sure, but VHDL has its own set of problems.

Quote:

Ahhh, so you *do* understand.

Well, of course I do to some extent; and, of course, so
do you. We both know perfectly well how to achieve the
results we need. The difference seems to be that you
are a vigorous apologist for the status quo, while I
would love to have things be very different.

I wouldn't mind terribly if things were different in some ways, but on
balance, I prefer Verilog over VHDL. For one thing, I
programmatically generate a lot of RTL, and I find it extremely easy
to generate Verilog. It's low-level enough that it doesn't get in the
way of trying to place application-specific abstractions on top of it.

Quote:
However,
I'm sufficiently pragmatic to know that I can't make
a real difference. That doesn't, and shouldn't, stop
me having a good old rant about it from time to time Smile

Be my guest. But it would nice if you could rant in such a way that
you made the actual target of the rant a bit clearer at the top of the
post :-)

Quote:
But yes, a C semaphore or mutex or
monitor requires something *below* the level of the language

I don't think I agree with that. C is a sufficiently low-level
language that you can create those primitives within the core
language if you wish to do so.

Well, it's been a decade and a half since I've done any of that sort
of thing in C, but IIRC, the core language doesn't have, e.g. atomic
operations. Now it may be that "i += 1" is usually atomic on a
processor that supports atomic increment; but with multiprocessing,
all bets are off, unless you use (e.g. on the x86) a LOCK prefix in
front of the INC instruction. (In a multiprocessing environment, even
disabling interrupts will be insufficient to guarantee
sychronization.) On a multiprocessin X86, you really need to be able
to do things like LOCK and XCHG or XADD for a full set of primitives,
and I don't think the C language directly supports this; at least not
back when I was doing a lot of C.

Quote:
whereas
the Verilog language itself provides the needed primitives, and, let's
face it, "evaluate/update" is what has to happen with clocked
processes in all but the simplest cases.

Right; but Verilog does leave Pandora's box wide open, doesn't it?

Absolutely.

Quote:
Since Verilog does not _enforce_ the use of nonblocking assignment
to shared variables, it effectively has free uncontrolled sharing
of variables among concurrent processes.

Right, but as you know, I always use nonblocking assignments in
clocked processes, so really and truly, this is a non-issue for me.

Quote:
And yet it didn't, until
SystemVerilog, have even a mutex or semaphore available!

And, to my knowledge, C still doesn't either...

Quote:
This
situation is tolerable only because many (most??) Verilog users
are working within a framework that looks pretty much like
synthesisable logic, where a few fairly simple coding guidelines
are enough to keep you out of trouble.

Yes. As I mentioned, myopically speaking Smile, that's the closest to
the final product.

Quote:
Anyone who's tried to
write a reasonably sophisticated testbench in Verilog, with
multiple threads of control, either is familiar with the
problem of mutual exclusion and has tricks for dealing with
it, or has their head buried in the sand.

Sure, but at the end of the day, you can probably get into trouble
with synchronization (where trouble is defined as "unexpected
behavior") in any language. Personally, although there will always be
room for improvement, I think that the "new world order" (at least for
the world where I live) where synthesizable stuff is in Verilog and
testbenches are moving to System Verilog, is really not too bad.

Regards,
Pat

Patrick Maupin
Guest

Sun May 23, 2010 6:23 am   



On May 22, 3:40 pm, Andy <jonesa...@comcast.net> wrote:
Quote:
On May 21, 1:40 pm, Patrick Maupin <pmau...@gmail.com> wrote:

You can easily be as undisciplined in C.  The fact that C has no
concurrency, but C + package allows you concurrency doesn't mean that
C + package enforces anything on the user.

And just like C + package, Verilog does not enforce anything either.

Yes. By "as undisciplined" I meant "equally undisciplined." Sorry if
that was unclear.

Regards,
Pat

Jan Decaluwe
Guest

Sun May 23, 2010 4:46 pm   



On May 21, 8:59 pm, Patrick Maupin <pmau...@gmail.com> wrote:
Quote:
On May 21, 4:07 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:

Use blocking assignments for communication anywhere else, and you
immediately have race problems. Just look in the manuals of mainstream
synthesis vendors for plenty of problematic examples.

So by "anywhere else" you mean in a sequential block.  Yes, I don't do
that.

No, I do mean anywhere else, in particular also for verification-
related tasks where the RTL paradigm does not apply, and which is
typically the bulk of the work.

(When I use the word "sequential" in the context of HDL coding, I mean
RTL. Of course, if you would define it as "anything non-
combinatorial", we are saying the same thing.)

Quote:
"As a matter of forming good coding habits", avoid blocking
assignments for communication altogether, and stop worrying about
races.

Well, I just avoid blocking assignments at all in sequential blocks.
As we have discussed previously, that can also be a viable strategy.

I know what you do for synthesis, now let's see about test benches.

Quote:
Given the fact that races are costly in any case, do you see the value
of having one single guideline that covers everything?

Yes, but I also see the cost.  For example, in a large block with
intermingled blocking/non-blocking assignments, there might be a lot
of scrolling back and forth to determine if a variable is local or
not.  For another example, if you need the local variable in another
block, now you have to go back and check all the uses of it and
possibly do some recoding.

Correct. Note that VHDL makes this task much easier and less costly as
safe communication is enforced by the language.

Quote:
I have a single guideline that covers everything; Cummings has a set
of guidelines that covers synthesis only and that introduces a number
of special cases.

Cummings certainly covers synthesis.  What in his guidelines will
break for non-synthesis?

Short answer: nothing, but that is irrelevant because nobody wants
similar restrictions beyond synthesis.

Long answer: this is a puzzling question.

First, the fact that Cummings talks specifically about synthesis tells
me indirectly that he doesn't want to impose anything similar for test
benches and higher level modeling. I don't want to give the impression
of critisizing him for something he doesn't say, I have enough work
with what he actually does say already :-)

Then, his guidelines are formulated in RTL jargon, which makes them
not applicable at higher levels. We first need a translation step that
extracts the "spirit" of his guidelines.

The spirit of his guidelines is: use only a single type of assignment
in any given always block. To me, it is close to obvious that no
Verilog verification engineer will find this acceptable. But of
course, what I find obvious doesn't count, so I will state my
hypothesis explicitly in a form that can be disproven.

My hypothesis is that anyone serious about using Verilog for
verification will, in the same always block:
1) want reliable communication, hence non-blocking assignments.
2) systematically need variable semantics internally for modeling,
hence blocking assignments.

If this is right, the spirit of Cummings is not applicable and you
basically need my guideline. Actually, I suspect that this is what
most Verilog verification engineers are doing already, and I would be
rather surprized if you didn't.

Jan

Patrick Maupin
Guest

Sun May 23, 2010 8:38 pm   



On May 23, 8:46 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:
Quote:
On May 21, 8:59 pm, Patrick Maupin <pmau...@gmail.com> wrote:

On May 21, 4:07 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:
Use blocking assignments for communication anywhere else, and you
immediately have race problems. Just look in the manuals of mainstream
synthesis vendors for plenty of problematic examples.

So by "anywhere else" you mean in a sequential block.  Yes, I don't do
that.

No, I do mean anywhere else, in particular also for verification-
related tasks where the RTL paradigm does not apply, and which is
typically the bulk of the work.

OK. I saw "synthesis" in the original, and thought that was what we
were talking about. Also, you mentioned that you never use blocking
assignments for "communication." Depending on what you mean by
"communication", that could be extremely limiting in a testbench, so I
assumed the context was RTL.

Quote:
(When I use the word "sequential" in the context of HDL coding, I mean
RTL. Of course, if you would define it as "anything non-
combinatorial", we are saying the same thing.)

Well, if we have to have more categories than combinatorial and
sequential, I would call the third category "advanced." "Advanced" is
really sequential, but is usually a tiny portion of the design. It
can happen in both testbenches and synthesizable logic, however. For
example, in synthesizable it could be I/O latches, or clock gaters.
In testbenches, the same thing, plus clock generation and a few other
corner cases.

In general, you don't need that much advanced stuff, and in general
(especially in RTL) the junior guy isn't coding it, so I have to say
up front, that while it would be nice for a set of guidelines to cover
"advanced", it really isn't that bad if the rules have to be bent a
bit for the advanced stuff.

Quote:
"As a matter of forming good coding habits", avoid blocking
assignments for communication altogether, and stop worrying about
races.

Well, I just avoid blocking assignments at all in sequential blocks.
As we have discussed previously, that can also be a viable strategy.

I know what you do for synthesis, now let's see about test benches.

Testbenches have slightly relaxed rules, which probably violate your
rule about not using blocking assignments for communications. For
example, if I am generating a signal that is an asynchronous input to
RTL, there is no reason not to use nonblocking assignments to create
it. However, we still follow the rule of not mixing blocking and
nonblocking in the same block.

Quote:
Given the fact that races are costly in any case, do you see the value
of having one single guideline that covers everything?

Yes, but I also see the cost.  For example, in a large block with
intermingled blocking/non-blocking assignments, there might be a lot
of scrolling back and forth to determine if a variable is local or
not.  For another example, if you need the local variable in another
block, now you have to go back and check all the uses of it and
possibly do some recoding.

Correct. Note that VHDL makes this task much easier and less costly as
safe communication is enforced by the language.

You say that like the cost is unbearable, and like VHDL doesn't have
other costs.

Quote:
I have a single guideline that covers everything; Cummings has a set
of guidelines that covers synthesis only and that introduces a number
of special cases.

Cummings certainly covers synthesis.  What in his guidelines will
break for non-synthesis?

Short answer: nothing, but that is irrelevant because nobody wants
similar restrictions beyond synthesis.

Certainly, one of Cummings's major objectives is to insure that
simulation and synthesis results match, and there is no requirement
for that in a testbench. But in that vein, if I understand your
guideline about blocking assignments correctly, I don't want *that*
restriction for a testbench at all.

Quote:
Long answer: this is a puzzling question.

First, the fact that Cummings talks specifically about synthesis tells
me indirectly that he doesn't want to impose anything similar for test
benches and higher level modeling. I don't want to give the impression
of critisizing him for something he doesn't say, I have enough work
with what he actually does say already Smile

Well, you agree that some guidelines are required for testbenches. In
fact, if I understand you correctly, you yourself have a guideline
that I don't follow for testbenches. So, as a starting point, you
could do much worse than reading Cummings's papers and understanding
the reasoning behind his guidelines.

Quote:
Then, his guidelines are formulated in RTL jargon, which makes them
not applicable at higher levels. We first need a translation step that
extracts the "spirit" of his guidelines.

I can agree with that.

Quote:
The spirit of his guidelines is: use only a single type of assignment
in any given always block.

I do that.

Quote:
To me, it is close to obvious that no
Verilog verification engineer will find this acceptable.

Our dedicated testbench engineers are much more adamant than I am
about following this guideline, so I really don't know how you arrived
at this conclusion.

Quote:
But of
course, what I find obvious doesn't count, so I will state my
hypothesis explicitly in a form that can be disproven.

My hypothesis is that anyone serious about using Verilog for
verification will, in the same always block:
1) want reliable communication, hence non-blocking assignments.

When a testbench is generating a completely independent signal for
simulation purposes (for an async input), non-blocking assignments may
not be required at all.

Quote:
2) systematically need variable semantics internally for modeling,
hence blocking assignments.

When a testbench is manipulating dependent signals, we code that like
the RTL -- the blocking and nonblocking assignments are in *different*
always blocks. Honestly, this is not a terrible burden.

Quote:
If this is right, the spirit of Cummings is not applicable and you
basically need my guideline. Actually, I suspect that this is what
most Verilog verification engineers are doing already, and I would be
rather surprized if you didn't.

If I understand your guideline correctly, it says any varying inputs
to my DUT need to be created from nonblocking assignments inside the
testbench. I certainly don't need or want that guideline.

Regards,
Pat

Ali Karaali
Guest

Mon May 24, 2010 12:06 am   



On 23 Mayıs, 00:06, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:
Quote:
On Sat, 22 May 2010 10:24:52 -0700 (PDT), Ali Karaali wrote:
[Jonathan Bromley]

always@(*) begin
   a = b;
   c = a;
end
these statements are executed sequentaly, a = b blocks the c = d;

When b is assigned to a, the always star block will be activated again
because
right handside of the variable is changed?
When activated the block stars immediately or after finish the
execution path?
So the right values is assigned after two iteration but it takes very
small time?

Quote:

Hope this helps you to see what's happening.
--
Jonathan Bromley


Jonathan Bromley
Guest

Mon May 24, 2010 11:29 am   



On May 23, 10:06 pm, Ali Karaali <ali...@gmail.com> wrote:

Quote:
always@(*) begin
   a = b;
   c = a;
end

When b is assigned to a, the always star block
will be activated again because
right handside of the variable is changed?

Yes, but....

Quote:
When activated the block stars immediately or after finish the
execution path?

That's not quite the right question. It's important to see
that "always@*" is not a Verilog keyword. What's really
happening is...

always
@* begin
...
end

And, of course, "always" is a procedural infinite loop,
exactly equivalent to "initial forever" or, if you
prefer, "initial while(1)". Some people think, wrongly,
that "always @*" represents a block of code that is
automatically launched whenever an input signal
changes value. That is not the case. The infinite
loop starts to execute at time 0. It immediately
freezes at the @* event control, waiting until
there is a value change on one or more of its inputs;
the event control is then released, and execution
proceeds. The software (procedural code) in the
begin...end block then executes to the end, and
then the "always" construct causes execution to
loop back to the beginning and the whole thing
starts all over again, waiting for @*.

So let's use this understanding to follow what
happens in your example:

1)
At time 0, the "always" statement starts to execute.
2)
Immediately, its execution freezes on @*.
3)
Some time later, some other code changes the value
of variable 'b'.
4)
The @* event control is released; execution of your
code proceeds. First, 'a' is updated with the new
value of 'b'. Next, 'c' is updated with the new
value of 'a' (which came from 'b', of course). This
is just normal software-like execution. Blocking
assignment (with no delay) works exactly like normal
assignment in C or other imperative languages.
5)
Execution has now reached the "end", so the "always"
iterates and execution once more hits the @*. Note
that both 'a' and 'c' already have their correct new
values, after only one iteration of the code.

So far, so clear. Now things get a little more
difficult. As you say, there is a value change
on 'a'. Does that release the @*? I would argue
that it does not, because 'a' already has its new
value at the moment when execution reaches @*.
There is no further value change on 'a'.
However, some simulators (I believe) compute
"value change" by looking at the value of a
variable before and after the execution of code
at a given point in time. Such a simulator might
now see that 'a' has changed since the beginning
of the time-slot, and therefore might choose to
release the @* for a second time. THIS DOES NOT
MATTER because your code describes proper
combinational logic and the second iteration,
if it occurs, will give exactly the same results
as before.

Quote:
So the right values is assigned after two iteration
but it takes very small time?

Possibly.... see above.

Now it's your chance to show how well you understand
all this... let's try another example....

always @* begin
a <= b;
c <= a;
end

Can you "tell the story" of this code, in the same
way as I did for your example? The final result
is almost the same, but the processing is very
different.........

Jonathan Bromley

Ali Karaali
Guest

Mon May 24, 2010 2:03 pm   



On 24 Mayıs, 11:29, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:
Quote:
On May 23, 10:06 pm, Ali Karaali <ali...@gmail.com> wrote:

always@(*) begin
   a = b;
   c = a;
end

When b is assigned to a, the always star block
will be activated again because
right handside of the variable is changed?

Yes, but....

When activated the block stars immediately or after finish the
execution path?

That's not quite the right question.  It's important to see
that "always@*" is not a Verilog keyword.  What's really
happening is...

  always
    @* begin
      ...
    end

And, of course, "always" is a procedural infinite loop,
exactly equivalent to "initial forever" or, if you
prefer, "initial while(1)".  Some people think, wrongly,
that "always @*" represents a block of code that is
automatically launched whenever an input signal
changes value.  That is not the case.  The infinite
loop starts to execute at time 0.  It immediately
freezes at the @* event control, waiting until
there is a value change on one or more of its inputs;
the event control is then released, and execution
proceeds.  The software (procedural code) in the
begin...end block then executes to the end, and
then the "always" construct causes execution to
loop back to the beginning and the whole thing
starts all over again, waiting for @*.

So let's use this understanding to follow what
happens in your example:

1)
At time 0, the "always" statement starts to execute.
2)
Immediately, its execution freezes on @*.
3)
Some time later, some other code changes the value
of variable 'b'.
4)
The @* event control is released; execution of your
code proceeds.  First, 'a' is updated with the new
value of 'b'.  Next, 'c' is updated with the new
value of 'a' (which came from 'b', of course).  This
is just normal software-like execution.  Blocking
assignment (with no delay) works exactly like normal
assignment in C or other imperative languages.
5)
Execution has now reached the "end", so the "always"
iterates and execution once more hits the @*.  Note
that both 'a' and 'c' already have their correct new
values, after only one iteration of the code.

So far, so clear.  Now things get a little more
difficult.  As you say, there is a value change
on 'a'.  Does that release the @*?  I would argue
that it does not, because 'a' already has its new
value at the moment when execution reaches @*.
There is no further value change on 'a'.
However, some simulators (I believe) compute
"value change" by looking at the value of a
variable before and after the execution of code
at a given point in time.  Such a simulator might
now see that 'a' has changed since the beginning
of the time-slot, and therefore might choose to
release the @* for a second time.  THIS DOES NOT
MATTER because your code describes proper
combinational logic and the second iteration,
if it occurs, will give exactly the same results
as before.

So the right values is assigned after two iteration
but it takes very small time?

Possibly.... see above.

Now it's your chance to show how well you understand
all this... let's try another example....

  always @* begin
    a <= b;
    c <= a;
  end

Can you "tell the story" of this code, in the same
way as I did for your example?  The final result
is almost the same, but the processing is very
different.........

Jonathan Bromley

For example
@t = 0 a = 3, b = 5, c = 2;

1-) At time = 0 always is started to execute
2-) it is freezed on @*.
3-) (@t = 2 b = 7) b is changed somewhere and @* is released and
the execution is started at the end of begin keyword.
4-) "assigned b to a" in a queue, therefore b isn't change.
(@t = 2) a = 3 b = 7 c = 2 ( a = 7 is in the queue)
5-) "assigned a to c" in a queue too, c isn't change either.
(@t = 2) a = 3 b = 7 c = 2 ( c = 3 is in the queue)
6-) Whole statements is finished so fetch the queue elements,
(@t = 2 + delta_t) b is assigned to a
a = 7 b = 7 c = 2
@(t = 2 + delta_t)and a (a = 3; the value of 'a' at t = 2) is assigned
to c but
a = 7 b = 7 c = 3
7-) And freeze @*
Cool But a was changed so @* is released.
9-) "assigned b to a" in a queue.
(@t = 2 + delta_t)a = 7, b = 7, c = 3
10-)"assigned a to c" in a queue too.
(@t = 2 + delta_t)a = 7, b = 7, c = 3 (c = 7 in the queue)
11-) Whole statements is finished
(@t = 2 + 2*delta_t)and a is assigned to c
a = 7 b = 7 c = 7

But I need to think about all of them again.
@6 How much time does between two assignment have?
a = 7 between c = 3
isn't againg a delta time, right?


Ali

Jonathan Bromley
Guest

Mon May 24, 2010 4:53 pm   



Ali,

Quote:
  always @* begin
    a <= b;
    c <= a;
  end

Can you "tell the story" of this code, in the same
way as I did for your example?  The final result
is almost the same, but the processing is very
different.........

Hey, wait a minute. This isn't what's supposed to
happen here. The idea is that lazy students ask
idiotic questions, and we tell them they are being
lazy. But now you go and ruin it: not only have
you asked a completely reasonable question based
on your own thoughtful concerns, but you also are
prepared to do some real work to dig deeper. Be
very careful... this might become a habit :-)

Quote:
For example
@t = 0 a = 3, b = 5, c = 2;

1-) At time = 0 always is started to execute
2-) it is freezed on @*.
3-) (@t = 2 b = 7) b is changed somewhere and @* is released and
the execution is started at the end of begin keyword.
4-) "assigned b to a" in a queue, therefore b isn't change.
(@t = 2) a = 3 b = 7 c = 2 ( a = 7 is in the queue)
5-) "assigned a to c" in a queue too, c isn't change either.
(@t = 2) a = 3 b = 7 c = 2 ( c = 3 is in the queue)
6-) Whole statements is finished

Correct so far.

Quote:
so fetch the queue elements,
(@t = 2 + delta_t) b is assigned to a
a = 7 b = 7 c = 2
@(t = 2 + delta_t)and a (a = 3; the value of 'a' at t = 2) is assigned
to c but
a = 7 b = 7 c = 3
7-) And freeze @*

Not quite. You have switched these around. FIRST the always
block loops around to @* and freezes. And the same thing
happens to any other always blocks that were running at the
same moment of simulation time. Then, when every one of
those always blocks is stuck at an @ or # event control,
the nonblocking assignments on the queue will take effect.

You say "+delta_t". That would be exactly correct for
VHDL. For Verilog, though, there is no exact idea of
a "delta cycle". But it's still a useful and sensible
idea.

Quote:
Cool But a  was changed so @* is released.
9-) "assigned b to a" in a queue.
(@t = 2 + delta_t)a = 7, b = 7, c = 3
10-)"assigned a to c" in a queue too.
(@t = 2 + delta_t)a = 7, b = 7, c = 3 (c = 7 in the queue)
11-) Whole statements is finished

and then back to freeze at @* again, and then...

Quote:
(@t = 2 + 2*delta_t)and a is assigned to c
a = 7 b = 7 c = 7

But I need to think about all of them again.
@6 How much time does between two assignment have?
a = 7 between c = 3
isn't againg a delta time, right?

No; all those nonblocking updates happen together.

However, it is DEFINED that they happen in the same
sequence that they were executed. Often this is not
so important, but there's one place where it is
essential. Consider this clocked logic:

always @(posedge clock) begin
Q <= 0; // default assignment
if (some_complicated_condition) begin
if (some_other_condition) begin
Q <= 1; // change your mind
end
end
end

This is a very useful coding trick, but you can see
that the two nonblocking assignments MUST take effect
in the same order that they were executed, if this
code is to make sense.

Regards
--
Jonathan Bromley

Jan Decaluwe
Guest

Mon May 24, 2010 6:33 pm   



On May 23, 7:38 pm, Patrick Maupin <pmau...@gmail.com> wrote:

Quote:
Certainly, one of Cummings's major objectives is to insure that
simulation and synthesis results match, and there is no requirement
for that in a testbench.  But in that vein, if I understand your
guideline about blocking assignments correctly, I don't want *that*
restriction for a testbench at all.

The guideline of not using blocking assignments for communication is
intended to guarantee, by construction, that simulation results of
exactly the same testbench, written in standard Verilog, match among
themselves: between different runs with other command line options,
simulator revisions and of course different simulators. Wouldn't you
agree that this goal makes at least as much sense?

Quote:
When a testbench is generating a completely independent signal for
simulation purposes (for an async input), non-blocking assignments may
not be required at all.

Independent doesn't mean "will never happen simultanuously". Depending
on the case, the parameters, independent clock period values,
randomized delay values, it may happen. With a blocking assignment,
the race potential is there, but it may be rare and obscure and
therefore hard to debug.

I grant to you that if this is a one-shot signal, it's unlikely that
this will cause a problem. But the real danger I see is this. You keep
the guideline not to mix blocking and nonblocking assignments in the
same always block, but apparently you relax the guideline to restrict
blocking assignments to purely combinatorial blocks. But blocking
assignments are much more expressive than nonblocking ones. Therefore,
the temptation to start using them in ways that are truly unsafe must
be almost irresistible. After all, everything will probably seem to
work fine at first. No guideline of yours prevents this; you have to
rely on the competence and discipline of each individual testbench
engineer.

Quote:
When a testbench is manipulating dependent signals, we code that like
the RTL -- the blocking and nonblocking assignments are in *different*
always blocks.  Honestly, this is not a terrible burden.

As you know, I don't think highly of this coding style even for
synthesis. But with synthesis there is at least the typical argument
that such code is "closer to hardware". Obviously for testbenches this
doesn't count: the only thing that matters is expressing functionality
in the clearest way. So I wonder where the idea to use this coding
style for testbenches also comes from.

Quote:
If I understand your guideline correctly, it says any varying inputs
to my DUT need to be created from nonblocking assignments inside the
testbench.  I certainly don't need or want that guideline.

Let me start with apologies to Janick Bergeron, whose book "Writing
Testbenches" (2000 edition) I have been rereading on this occasion.

It's not my guideline, but his. I now realize that I read it a long
time ago, and then forgot about its origin. Obviously it made so much
sense that I started thinking it was my own idea Smile (To my credit, I
added the synthesis component, pointing out that it's the only
guideline you need in that case also.)

In my view the coding style you describe advocates the use of blocking
assignments in exactly the wrong way:
- a lax attitude towards blocking assignments for communication,
resulting in a real danger of non-deterministic, non-portable Verilog
test benches that may fail in mysterious ways
- severe restrictions on using blocking assignments locally, making it
cumbersome to use plain old variable semantics even if such usage
would be totally safe

Jan

Patrick Maupin
Guest

Mon May 24, 2010 8:32 pm   



On May 24, 10:33 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:
Quote:
On May 23, 7:38 pm, Patrick Maupin <pmau...@gmail.com> wrote:

Certainly, one of Cummings's major objectives is to insure that
simulation and synthesis results match, and there is no requirement
for that in a testbench.  But in that vein, if I understand your
guideline about blocking assignments correctly, I don't want *that*
restriction for a testbench at all.

The guideline of not using blocking assignments for communication is
intended to guarantee, by construction, that simulation results of
exactly the same testbench, written in standard Verilog, match among
themselves: between different runs with other command line options,
simulator revisions and of course different simulators. Wouldn't you
agree that this goal makes at least as much sense?

Nonblocking assignments will certainly guarantee this for signals
running off the same clock. If a signal is generated from a clock,
it's certainly a great idea, but for signals generated from a clock, I
already told you that we already use nonblocking assignments.

Quote:
When a testbench is generating a completely independent signal for
simulation purposes (for an async input), non-blocking assignments may
not be required at all.

Independent doesn't mean "will never happen simultanuously". Depending
on the case, the parameters, independent clock period values,
randomized delay values, it may happen. With a blocking assignment,
the race potential is there, but it may be rare and obscure and
therefore hard to debug.

"Independent" == "Not synchronous" == "Synchronizer required inside
the DUT" == "Lots of testing to insure that clock cross happens OK" ="give me whatever race potentials you've got." Seriously.

Quote:
I grant to you that if this is a one-shot signal, it's unlikely that
this will cause a problem.

Not a one-shot signal. An *independent* signal, that has to be
synchronized by the RTL.

Quote:
But the real danger I see is this. You keep
the guideline not to mix blocking and nonblocking assignments in the
same always block, but apparently you relax the guideline to restrict
blocking assignments to purely combinatorial blocks.

Yes, for stimulus.

Quote:
But blocking
assignments are much more expressive than nonblocking ones. Therefore,
the temptation to start using them in ways that are truly unsafe must
be almost irresistible.

You say that like I work with little children or something.

Quote:
After all, everything will probably seem to
work fine at first. No guideline of yours prevents this; you have to
rely on the competence and discipline of each individual testbench
engineer.

The guidelines *do* prevent this for a correct definition of
"independent". And trust me, an incompetent test engineer can screw
up no matter how many guidelines you give him.

Quote:
When a testbench is manipulating dependent signals, we code that like
the RTL -- the blocking and nonblocking assignments are in *different*
always blocks.  Honestly, this is not a terrible burden.

As you know, I don't think highly of this coding style even for
synthesis. But with synthesis there is at least the typical argument
that such code is "closer to hardware". Obviously for testbenches this
doesn't count: the only thing that matters is expressing functionality
in the clearest way. So I wonder where the idea to use this coding
style for testbenches also comes from.

You spent a lot of time saying "here, use this one rule on your
testbenches and your RTL; then they're the same." Then when I say our
testbenches and code mostly *are* the same, you act like that's
silly. Bah!

Quote:
If I understand your guideline correctly, it says any varying inputs
to my DUT need to be created from nonblocking assignments inside the
testbench.  I certainly don't need or want that guideline.

Let me start with apologies to Janick Bergeron, whose book "Writing
Testbenches" (2000 edition) I have been rereading on this occasion.

It's not my guideline, but his. I now realize that I read it a long
time ago, and then forgot about its origin. Obviously it made so much
sense that I started thinking it was my own idea Smile (To my credit, I
added the synthesis component, pointing out that it's the only
guideline you need in that case also.)

In my view the coding style you describe advocates the use of blocking
assignments in exactly the wrong way:
- a lax attitude towards blocking assignments for communication,

No, a clear understanding of the distinction between independent
stimulus and other stuff. Look, in most cases, if I'm generating
independent stimulus for a port, I don't even need to explicitly
generate a clock for it in the testbench. So, if something's
unclocked, and a random sweep is made to make sure that source
frequency and jitter variations aren't problems, how *exactly* does a
nonblocking assignment help me?

Quote:
resulting in a real danger of non-deterministic, non-portable Verilog
test benches that may fail in mysterious ways

But they're not and they don't. (We just migrated a bunch of chips
from Mentor to Cadence last year FWIW.)

Quote:
- severe restrictions on using blocking assignments locally, making it
cumbersome to use plain old variable semantics even if such usage
would be totally safe

You say "severe restriction" but that's simply not true. It's just a
different coding style which makes it very easy to reason about how
things work.

Regards,
Pat

Jonathan Bromley
Guest

Tue May 25, 2010 9:22 pm   



On Fri, 21 May 2010 01:13:21 -0700 (PDT), nemo wrote:

Quote:
  A = #5 EXPR;  // (1) Blocking
  A <= #5 EXPR; // (2) Nonblocking

Line (1) first evaluates EXPR, then blocks execution for 5 time units,
then updates A, then moves on to executing the next statement.

Wow! I didn't know it worked like that. I don't think that is the
same in VHDL. I think the VHDL "after" delay is done without blocking
the execution of the sequential flow even for variables.

Sorry, I just noticed I left this thread dangling.

Unless something changed while I wasn't looking, you can't
do AFTER-style delayed assignment to VHDL variables at all.
It works only for signals. Jolly good thing too :-)

One very interesting gnarly corner of all this is that
you cannot do _inertial_ delayed assignment to Verilog
variables. I think I pointed out that Verilog's NBA
A <= #5 EXPR;
is pretty close to VHDL's
A <= transport EXPR after 5 ns;

But what about a non-TRANSPORT delay in VHDL? That
inertial-type delay is available in Verilog [*] only
by using a continuous assign with a delay, or a wire
delay:

wire #3 W3; // net with 3 units delay
wire W5; // wire with no delay

assign #5 W5 = EXPR5; // *Driver* with 5-unit delay
// like VHDL concurrent W5 <= EXPR5 after 5 ns;

assign W3 = EXPR3; // no driver delay, just the net delay
// like VHDL concurrent W3 <= EXPR3 after 3 ns;

[*] Wait until Cary R. puts his head above the parapet to
explain all the other weird and wonderful timing machinery
you can use in Verilog thanks to primitives and specify blocks.
It's complicated and I almost never use it, so I won't even
try to explain - I'd get it badly wrong. Gate-level sim
people rely heavily on it.
--
Jonathan Bromley

Jan Decaluwe
Guest

Wed May 26, 2010 12:19 pm   



On May 24, 7:32 pm, Patrick Maupin <pmau...@gmail.com> wrote:
Quote:
On May 24, 10:33 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:

On May 23, 7:38 pm, Patrick Maupin <pmau...@gmail.com> wrote:

Certainly, one of Cummings's major objectives is to insure that
simulation and synthesis results match, and there is no requirement
for that in a testbench.  But in that vein, if I understand your
guideline about blocking assignments correctly, I don't want *that*
restriction for a testbench at all.

The guideline of not using blocking assignments for communication is
intended to guarantee, by construction, that simulation results of
exactly the same testbench, written in standard Verilog, match among
themselves: between different runs with other command line options,
simulator revisions and of course different simulators. Wouldn't you
agree that this goal makes at least as much sense?

Nonblocking assignments will certainly guarantee this for signals
running off the same clock.  If a signal is generated from a clock,
it's certainly a great idea, but for signals generated from a clock, I
already told you that we already use nonblocking assignments.

It might help if you stopped thinking about clocks. Verilog doesn't
know about them: all it sees are events that may happen
simultanuously.

Quote:
When a testbench is generating a completely independent signal for
simulation purposes (for an async input), non-blocking assignments may
not be required at all.

Independent doesn't mean "will never happen simultanuously". Depending
on the case, the parameters, independent clock period values,
randomized delay values, it may happen. With a blocking assignment,
the race potential is there, but it may be rare and obscure and
therefore hard to debug.

"Independent" == "Not synchronous" == "Synchronizer required inside
the DUT" == "Lots of testing to insure that clock cross happens OK" => "give me whatever race potentials you've got."  Seriously.

Thanks for pointing that out.

As a thought experiment, I will now construct a standards-compliant
Verilog simulation of your testbench that, given the same inputs,
produces different results. I will wait until a blocking assignment of
a new value happens in the same timestep as the sampling in the DUT.
Given your independent timing, and thanks to your extensive testing,
this situation will certainly happen. At that point, I will reverse
the order of the two events within the simulator engine. The sampled
value will now behave differently. Hence, I have proven that your
testbench is nondeterministic.

Quote:
But the real danger I see is this. You keep
the guideline not to mix blocking and nonblocking assignments in the
same always block, but apparently you relax the guideline to restrict
blocking assignments to purely combinatorial blocks.

Yes, for stimulus.

But blocking
assignments are much more expressive than nonblocking ones. Therefore,
the temptation to start using them in ways that are truly unsafe must
be almost irresistible.

You say that like I work with little children or something.

The fact is that it has happened and now the poison is in your
testbenches.

Quote:
After all, everything will probably seem to
work fine at first. No guideline of yours prevents this; you have to
rely on the competence and discipline of each individual testbench
engineer.

The guidelines *do* prevent this for a correct definition of
"independent".  

I have proven otherwise.

Quote:
When a testbench is manipulating dependent signals, we code that like
the RTL -- the blocking and nonblocking assignments are in *different*
always blocks.  Honestly, this is not a terrible burden.

As you know, I don't think highly of this coding style even for
synthesis. But with synthesis there is at least the typical argument
that such code is "closer to hardware". Obviously for testbenches this
doesn't count: the only thing that matters is expressing functionality
in the clearest way. So I wonder where the idea to use this coding
style for testbenches also comes from.

You spent a lot of time saying "here, use this one rule on your
testbenches and your RTL; then they're the same."  Then when I say our
testbenches and code mostly *are* the same, you act like that's
silly.  Bah!

In another post, I have warned explicitly about the danger that
Cumming's rule for blocking assignments, while safe in his specific
case, may encourage unsafe coding practices. You asked for a real-life
example of this danger, and I wasn't able to come up with a very good
one readily.

It now turns out that your own case provides an excellent example of
what I mean. In the same pass, it validates my concern from somewhat
speculative to very real. My case against Cumming's guidelines has
therefore become much stronger.

Quote:
If I understand your guideline correctly, it says any varying inputs
to my DUT need to be created from nonblocking assignments inside the
testbench.  I certainly don't need or want that guideline.

Let me start with apologies to Janick Bergeron, whose book "Writing
Testbenches" (2000 edition) I have been rereading on this occasion.

It's not my guideline, but his. I now realize that I read it a long
time ago, and then forgot about its origin. Obviously it made so much
sense that I started thinking it was my own idea Smile (To my credit, I
added the synthesis component, pointing out that it's the only
guideline you need in that case also.)

In my view the coding style you describe advocates the use of blocking
assignments in exactly the wrong way:
- a lax attitude towards blocking assignments for communication,

No, a clear understanding of the distinction between independent
stimulus and other stuff.  Look, in most cases, if I'm generating
independent stimulus for a port, I don't even need to explicitly
generate a clock for it in the testbench.

For a clear understanding, I repeat my suggestion to stop thinking
about clocks.

Quote:
 So, if something's
unclocked, and a random sweep is made to make sure that source
frequency and jitter variations aren't problems, how *exactly* does a
nonblocking assignment help me?

With nonblocking assignments, any standards compliant Verilog
simulator would, given the same inputs, always give you the same
results, guaranteed. Hence, your testbenches would now be
deterministic.

Quote:
resulting in a real danger of non-deterministic, non-portable Verilog
test benches that may fail in mysterious ways

But they're not and they don't.  (We just migrated a bunch of chips
from Mentor to Cadence last year FWIW.)

I have proven that your test benches are nonderministic. You have
strong evidence that this nondeterminism is not revealed between
Mentor and Cadence, which happens to be in line with my expectations.

Jan

Patrick Maupin
Guest

Wed May 26, 2010 8:18 pm   



On May 26, 4:19 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:

Quote:
It might help if you stopped thinking about clocks. Verilog doesn't
know about them: all it sees are events that may happen
simultanuously.

Sorry, one of the reasons I like Verilog is that it doesn't try to get
in the way of thinking about the clocks (when that's what I need to be
thinking about).

Quote:
"Independent" == "Not synchronous" == "Synchronizer required inside
the DUT" == "Lots of testing to insure that clock cross happens OK" => > "give me whatever race potentials you've got."  Seriously.

Thanks for pointing that out.

As a thought experiment, I will now construct a standards-compliant
Verilog simulation of your testbench that, given the same inputs,
produces different results. I will wait until a blocking assignment of
a new value happens in the same timestep as the sampling in the DUT.
Given your independent timing, and thanks to your extensive testing,
this situation will certainly happen. At that point, I will reverse
the order of the two events within the simulator engine. The sampled
value will now behave differently. Hence, I have proven that your
testbench is nondeterministic.

Yes, but you *completely missed* the point, EVEN THOUGH I CLEARLY
POINTED IT OUT, where *it doesn't matter at all*, because the
testbench is sweeping to prove in testing that it doesn't matter which
side of an internal clock an external transition happens on. Enough
data is taken that, at the margin, where a single sample could have
been in one timeslot or the next, IT REALLY DOESN'T MATTER.

Quote:
The fact is that it has happened and now the poison is in your
testbenches.

There is no poison. The testbenches work. The chips work. The fact
that one simulator might order a few events differently than another
is of no consequence.

Quote:
The guidelines *do* prevent this for a correct definition of
"independent".  

I have proven otherwise.

No, you have proven (which I already knew) that Verilog won't
guarantee whether signal A or B happens first, which is a problem with
a fragile DUT where precise ordering of one signal vs. another is
important. You took the time to prove this AFTER I went out of my way
to explain that we don't do that.

Quote:
In another post, I have warned explicitly about the danger that
Cumming's rule for blocking assignments, while safe in his specific
case, may encourage unsafe coding practices. You asked for a real-life
example of this danger, and I wasn't able to come up with a very good
one readily.

That's because there is no good case.

Quote:
It now turns out that your own case provides an excellent example of
what I mean. In the same pass, it validates my concern from somewhat
speculative to very real. My case against Cumming's guidelines has
therefore become much stronger.

That's because you don't understand, either deliberately or not.

Quote:
For a clear understanding, I repeat my suggestion to stop thinking
about clocks.

And I just explained very carefully that I *absolutely don't* need to
think about clocks when generating stimulus, because the stimulus is
*independent* of any clock, and if it matters whether stimulus that
occurs at the same time as a device clock (within some epsilon) falls
on one side or the other of the clock, then we have a broken device.

Quote:
I have proven that your test benches are nonderministic.

Yes, at the margins, for cases where I already told you we are doing
huge sweeps of data. Guess what? In real life, the DUT needs to cope
with non-deterministic input. For the testbench, it is sufficient to
insure that all possible cases are covered, not that all possible
cases are covered in exactly the same fashion on every possible
simulator.

Quote:
You have
strong evidence that this nondeterminism is not revealed between
Mentor and Cadence, which happens to be in line with my expectations.

It wouldn't be revealed for *any* compliant simulator we used, because
the tests are constructed in a manner where *it doesn't matter*
whether you believe that or not.

We have been doing this for *years* and have never had a broken chip
due to this thing you seem to think is the most important thing in the
world.

Regards,
Pat

Goto page Previous  1, 2, 3, 4  Next

elektroda.net NewsGroups Forum Index - Verilog Language - Non-Blocking versus blocking

Arabic versionBulgarian versionCatalan versionCzech versionDanish versionGerman versionGreek versionEnglish versionSpanish versionFinnish versionFrench versionHindi versionCroatian versionIndonesian versionItalian versionHebrew versionJapanese versionKorean versionLithuanian versionLatvian versionDutch versionNorwegian versionPolish versionPortuguese versionRomanian versionRussian versionSlovak versionSlovenian versionSerbian versionSwedish versionTagalog versionUkrainian versionVietnamese versionChinese version
RTV map EDAboard.com map News map EDAboard.eu map EDAboard.de map EDAboard.co.uk map Opony