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

Patrick Maupin
Guest

Thu May 20, 2010 8:28 pm   



On May 20, 3:08 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:

Quote:
Cummings' guideline to use only blocking assignments for combinatorial
logic is problematic, because it creates an unnecessary exception that
encourages something that is inherently dangerous.

Can you show a real-world example of this danger?

Quote:
The fact that communication based on blocking assignments works for
combinatorial logic is a coincidence and actually not that trivial to
prove. It depends not only on the inherent nature of combinatorial
logic, but also on "sensible usage".

Blocking assignments to "registers" inside non-clocked blocks and
continuous assignments to "wires" are essentially the same thing. I
don't see this as any kind of coincidence. If proof of a non-clocked
set of gates requires some sort of inherent propagation delay, that
might make the proof suspect, unless you can also prove that the
propagation delay is the correct magnitude.

Quote:
Cummings' guidelines are problematic in general because they
artificially discuss races in the context of synthesizable logic. But
Verilog, the language, doesn't care about synthesis. Races are races,
and there are plenty of race opportunities in high level models and
test benches also. Those cases need a working guideline too.

In general, the bad effects of a race in your test bench will be that
the test fails. In general the bad effects of a post-synthesis race
are either, again, that the test fails (if you are lucky) or that the
silicon fails (if you are unlucky). So why is it a problem to explain
things in the context of synthesis?

Quote:
So here it is: Decaluwe's universal guideline for race-free HDL
assignments.
"""
Use non-blocking assignments (signals) for communication.
Use blocking assignments (variables) for local computation.
"""

[ Rest of comment on this snipped. ]

Yes, this will work. But in practice, examination to insure that
these guidelines have been followed can be more time-consuming than if
other guidelines are followed, and it may be possible, using just
these guidelines, to write code that may be more conceptually
difficult to understand than the code you write using other
guidelines. But that's (obviously) just my opinion.

Regards,
Pat

Jonathan Bromley
Guest

Thu May 20, 2010 9:34 pm   



On Thu, 20 May 2010 10:28:11 -0700 (PDT), Patrick Maupin wrote:

Quote:
On May 20, 3:08 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:

Cummings' guideline to use only blocking assignments for combinatorial
logic is problematic, because it creates an unnecessary exception that
encourages something that is inherently dangerous.

Can you show a real-world example of this danger?

Easily, if you will permit the choice of "real world" to
extend somewhat outside the very constrained bounds of
RTL-for-synthesis.

Quote:
The fact that communication based on blocking assignments works for
combinatorial logic is a coincidence and actually not that trivial to
prove. It depends not only on the inherent nature of combinatorial
logic, but also on "sensible usage".

I suspect that Jan, like me, is unhappy about Verilog's
completely uncontrolled concurrency model.

Decades ago, software folk discovered that you need some
structures and disciplines to make concurrency work.
Without them, processes merrily trample on each other's
variables and all bets are off. There are many possible
ways to do it right, some prettier than others:

- evaluate/update disciplines (VHDL, SystemC, various other
discrete-event simulation languages)
- semaphores (readily available as OS primitives in many
environments)
- monitors (ditto) - VHDL protected types are a bit like this
- Ada-style client-server rendezvous
- CSP (Occam, Handel-C, Haste)

And then there's Verilog:
- anyone can mess with any shared variable at any time,
with an explicit caveat in the language that you can't
expect any kind of built-in control

So I would totally support Jan's position that combinational
logic, with its acyclic dependencies and stateless behaviour,
is a special case that just happens to work well in Verilog.
The late addition of nonblocking assignment to Verilog was,
I suggest, an admission that this uncontrolled concurrency
was indeed a very serious problem in other situations.
Clocked logic is just one such, but one that is likely to
be evident and problematic for hardware designers.

Quote:
Blocking assignments to "registers" inside non-clocked blocks and
continuous assignments to "wires" are essentially the same thing.

In the synthesis mindset, yes. But only there. In the
semantics of Verilog as a simulation language (and that's
how it's defined) they are as different as chalk and cheese.
They happen to give the same results if you use them
to model zero-delay combinational logic. Of course
that is partly a reflection of Verilog's cleverly
focused design for its chosen applications.

Quote:
don't see this as any kind of coincidence.

No more than the "coincidence" that concurrent signal
assignment and a combunational-style process in VHDL
are exactly equivalent by definition. And there they
both exhibit delta-delay behaviour. Once again:
combinational logic is a special case that can be
handled in a variety of ways. Some of those ways don't
work reliably for more general concurrency problems.

Quote:
If proof of a non-clocked
set of gates requires some sort of inherent propagation delay, that
might make the proof suspect, unless you can also prove that the
propagation delay is the correct magnitude.

There is of course no such "proof"; indeed, the nature of
combinational logic (output must be a pure function of
inputs) makes it possible to prove just the opposite.
I don't think that in any way invalidates Jan's concerns,
except possibly from a myopic RTL-centric viewpoint.
--
Jonathan Bromley

Patrick Maupin
Guest

Fri May 21, 2010 12:28 am   



On May 20, 3:34 pm, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:
Quote:
On Thu, 20 May 2010 10:28:11 -0700 (PDT), Patrick Maupin wrote:
On May 20, 3:08 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:

Cummings' guideline to use only blocking assignments for combinatorial
logic is problematic, because it creates an unnecessary exception that
encourages something that is inherently dangerous.

Can you show a real-world example of this danger?

Easily, if you will permit the choice of "real world" to
extend somewhat outside the very constrained bounds of
RTL-for-synthesis.

OK, I'll bite. Show me...

[ Other stuff snipped..]

Quote:
I suspect that Jan, like me, is unhappy about Verilog's
completely uncontrolled concurrency model.

Decades ago, software folk discovered that you need some
structures and disciplines to make concurrency work.  
Without them, processes merrily trample on each other's
variables and all bets are off.  There are many possible
ways to do it right, some prettier than others:

- evaluate/update disciplines (VHDL, SystemC, various other
  discrete-event simulation languages)
- semaphores (readily available as OS primitives in many
  environments)
- monitors (ditto) - VHDL protected types are a bit like this
- Ada-style client-server rendezvous
- CSP (Occam, Handel-C, Haste)

While the language constructs are nice, certainly it is possible to do
useful concurrency work in C. And semaphores, monitors, and mutexes
are used from C every day without a fundamental language rework. (As
an aside, while erlang or go may be the way of the future, replacing
Ada and Occam as the way of the future, and while the C/C++ standard
may lurch towards the future by digesting those really useful bits
from other languages, it is possible that the dominant system language
for a long time to come will be called C, just as the dominant
technical language is called English.)

Quote:
And then there's Verilog:
- anyone can mess with any shared variable at any time,
  with an explicit caveat in the language that you can't
  expect any kind of built-in control

Au contraire. It may not be as great as some of the languages you
mentioned, but it's certainly much better than C. If you want to
insure that another process can never see incoherent state between
variable X and variable Y, just make sure you update them at exactly
the same time. No semaphore, mutex, or monitor required. Also,
unlike C, (assuming you at least follow the rule of at most one module
per file) two different processes in different files cannot write to
the same "shared variable" in synthesizable code at all, and can't
very easily do it inadvertently in non-synthesizable code.

Quote:
So I would totally support Jan's position that combinational
logic, with its acyclic dependencies and stateless behaviour,
is a special case that just happens to work well in Verilog.

Special case, perhaps. Coincidence? I think not :-)

Quote:
The late addition of nonblocking assignment to Verilog was,
I suggest, an admission that this uncontrolled concurrency
was indeed a very serious problem in other situations.
Clocked logic is just one such, but one that is likely to
be evident and problematic for hardware designers.

Blocking assignments to "registers" inside non-clocked blocks and
continuous assignments to "wires" are essentially the same thing.

In the synthesis mindset, yes.  But only there.  In the
semantics of Verilog as a simulation language (and that's
how it's defined) they are as different as chalk and cheese.
They happen to give the same results if you use them
to model zero-delay combinational logic.  Of course
that is partly a reflection of Verilog's cleverly
focused design for its chosen applications.

I do view the synthesis results as the end product, yes. Anything
that has to be done in the testbench is ancillary to that (and by the
way, Verilog's laissez-faire attitude to coding is a double-edged
sword that can, in some cases, make the test code very readable and
maintainable).

Quote:
don't see this as any kind of coincidence.

No more than the "coincidence" that concurrent signal
assignment and a combunational-style process in VHDL
are exactly equivalent by definition. And there they
both exhibit delta-delay behaviour.  Once again:
combinational logic is a special case that can be
handled in a variety of ways.  Some of those ways don't
work reliably for more general concurrency problems.

If proof of a non-clocked
set of gates requires some sort of inherent propagation delay, that
might make the proof suspect, unless you can also prove that the
propagation delay is the correct magnitude.

There is of course no such "proof"; indeed, the nature of
combinational logic (output must be a pure function of
inputs) makes it possible to prove just the opposite.

Agreed.

Quote:
I don't think that in any way invalidates Jan's concerns,
except possibly from a myopic RTL-centric viewpoint.

Guilty as charged. While the process of getting to correct
synthesizable logic is interesting, useful, and necessary, the actual
synthesizable logic itself is, if not more interesting, at least more
useful and necessary.

Regards,
Pat

Jonathan Bromley
Guest

Fri May 21, 2010 10:44 am   



Patrick,

I don't have time to write a complete reply just now,
but I can't let this piece of nonsense go unchallenged:

[me]
Quote:
And then there's Verilog:
- anyone can mess with any shared variable at any time,
snip

[Pat]
Quote:
If you want to
insure that another process can never see incoherent state between
variable X and variable Y, just make sure you update them at exactly
the same time.

That is simply untrue:

always @(posedge clock)
X = some_expression;
always @(posedge clock)
Y = some_other_expression;
always @(posedge clock) begin : observer
if (some relationship between X and Y) ....;
end

"observer" has absolutely no guarantee of coherence of X and Y.
So, you may say, let's update them together:

always @(posedge clock) begin
X = some_expression;
Y = some_other_expression;
end

Bzzzt! Doesn't work: Verilog does not guarantee atomic execution
of a zero-time sequential block, so "observer" still has no
guarantee of coherence. So we must resort to yet another
special case (and even this unusable mess isn't strictly
guaranteed to give atomic update, even though it will
most likely do so in practice):

always @(posedge clock)
{X,Y} = {some_expression, some_other_expression};

Quote:
No semaphore, mutex, or monitor required.

You're kidding, right? In Verilog you make this
work correctly by wheeling out the evaluate/update
model made possible by nonblocking assignment.
In other environments you would use other exclusion
or synchronisation primitives. Either way, you need
some discipline.

Verilog is _much_ worse than C in this regard because
it has concurrency constructs built in to the language,
but they are completely undisciplined. In C, to get
concurrency you must appeal to some library or toolkit;
if properly designed, that library will provide not
only the parallelism but also the synchronisation
primitives that you need, so you get a proper way to
do things as a single package.

I'll try to respond more thoughtfully to your other
points over the weekend.
--
Jonathan Bromley

nemo
Guest

Fri May 21, 2010 11:13 am   



On May 20, 10:15 am, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:
Quote:
Rick,

I was not aware that Verilog did not use delta delays in combinatorial
assignments.  I would say in this case blocking assignments are a bad
thing.  If I am gating my clock, then that introduces delays.  If
simulating a delta delay causes issues in my simulation, then that
would match the real world, no?  I suppose there are tools used to
assure that minimum hold times are maintained, which is where clock
skew would bite you.

Right - I think the idea is that clock gating would normally
be designed (after P&R) to avoid hold time trouble, but it's
tough to represent that in your RTL, so one possible way out
is to arrange that zero-delay combinational logic is "faster"
than zero-delay clock-to-output propagation of a FF.  This will
automatically give RTL zero-delay sim that matches your finished
device with real delays in it.

Personally I think this is a strange concept that a zero-delay sim
should be... I can't think of a word, "optimized" is not right,
"tweaked" seems biased... "adjusted" to allow a particular type of
design to simulate as if there were no delay in a logic element, but
that there is a delay in sequential elements. This can be handled
very easily by adding explicit delays to sequential elements. Then it
is very clear that an assumption is being made about relative delays.
I guess this shows that I never gate clocks. I can see how this would
be a real can of worms.

Has anyone here used clock gating in VHDL? How do you handle that?


Quote:
How could combinatorial blocks be merged or even properly be evaluated
without delta delays?  Help me understand.

assign A = B xor C;
assign B = not C;

That's a perfect example: the simulator can analyse the
dependencies among variables, and then collapse that to
(approximately!)

  always @(C) begin
    B = not C;
    A = B xor C;
  end

The transformation saves some swapping between processes,
and there's no visible difference to the user.  

Except that it produces a glitch free output which is not realistic.
Of course, in the real world the implemented logic will be determined
by the tools so there may or may not be a glitch in the output. So I
guess this is similar to clock gating.


Quote:
BTW, is there a reason why the non-delay assignment is called
"blocking"?  I'm trying to come up with a way to remember the names
correctly.  It seems to me the delayed assignment would be called
blocking...

"Blocking" in the sense of blocking the flow of procedural
execution until the update has taken effect.  The meaning
is more obvious when you add intra-assignment delay (roughly
equivalent to VHDL "after" delay):

  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.


Quote:
Line (2) evaluates EXPR, but then does NOT block; it simultaneously:
- sets up a scheduled update of A at a time 5 units in the future;
- moves on immediately to execution of the next statement.

The second form (2), nonblocking, is very similar to VHDL
  A <= transport EXPR after 5 ns;

The first form (1), blocking, is effectively:
  temp_variable = EXPR;
  #5;  // like WAIT FOR 5 NS;
  A = temp_variable;

Anyway, that's the reason for the [non]blocking naming, I think.

I don't think anyone can be blamed for wanting to steer clear
of all this stuff....

Yeah, it will be interesting to learn.

Rick

nemo
Guest

Fri May 21, 2010 11:19 am   



On May 20, 1:28 pm, Patrick Maupin <pmau...@gmail.com> wrote:
Quote:
On May 20, 3:08 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:

Cummings' guideline to use only blocking assignments for combinatorial
logic is problematic, because it creates an unnecessary exception that
encourages something that is inherently dangerous.

Can you show a real-world example of this danger?

The fact that communication based on blocking assignments works for
combinatorial logic is a coincidence and actually not that trivial to
prove. It depends not only on the inherent nature of combinatorial
logic, but also on "sensible usage".

Blocking assignments to "registers" inside non-clocked blocks and
continuous assignments to "wires" are essentially the same thing.  I
don't see this as any kind of coincidence.  If proof of a non-clocked
set of gates requires some sort of inherent propagation delay, that
might make the proof suspect, unless you can also prove that the
propagation delay is the correct magnitude.

Cummings' guidelines are problematic in general because they
artificially discuss races in the context of synthesizable logic. But
Verilog, the language, doesn't care about synthesis. Races are races,
and there are plenty of race opportunities in high level models and
test benches also. Those cases need a working guideline too.

In general, the bad effects of a race in your test bench will be that
the test fails.  In general the bad effects of a post-synthesis race
are either, again, that the test fails (if you are lucky) or that the
silicon fails (if you are unlucky).  So why is it a problem to explain
things in the context of synthesis?

So here it is: Decaluwe's universal guideline for race-free HDL
assignments.
"""
Use non-blocking assignments (signals) for communication.
Use blocking assignments (variables) for local computation.
"""

[ Rest of comment on this snipped. ]

Yes, this will work.  But in practice, examination to insure that
these guidelines have been followed can be more time-consuming than if
other guidelines are followed, and it may be possible, using just
these guidelines, to write code that may be more conceptually
difficult to understand than the code you write using other
guidelines.  But that's (obviously) just my opinion.

This last guideline is essentially what VHDL does. Variables only
have scope within a process so can not be used for communication
between processes. What guidelines would accomplish the same thing
and be easier to verify? Sounds like something a tool should be
checking for you.

Rick

Jan Decaluwe
Guest

Fri May 21, 2010 12:07 pm   



On May 20, 7:28 pm, Patrick Maupin <pmau...@gmail.com> wrote:
Quote:
On May 20, 3:08 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:

Cummings' guideline to use only blocking assignments for combinatorial
logic is problematic, because it creates an unnecessary exception that
encourages something that is inherently dangerous.

Can you show a real-world example of this danger?

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.

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

Quote:
The fact that communication based on blocking assignments works for
combinatorial logic is a coincidence and actually not that trivial to
prove. It depends not only on the inherent nature of combinatorial
logic, but also on "sensible usage".

Blocking assignments to "registers" inside non-clocked blocks and
continuous assignments to "wires" are essentially the same thing.  I
don't see this as any kind of coincidence.

That is not what I was talking about.

Suppose you start manipulating clocks combinatorially, using assigns
or blocking assignments. I don't see why the resulting transactions
would be race-free. I immediately add that this is probably
nonsensical usage, and that in practice, blocking assignment-based
communication works for the special case of "meaningful" combinatorial
logic. But do you see why I call that a coincidence? It feels like
plain luck based on shaky foundations.

Quote:
Cummings' guidelines are problematic in general because they
artificially discuss races in the context of synthesizable logic. But
Verilog, the language, doesn't care about synthesis. Races are races,
and there are plenty of race opportunities in high level models and
test benches also. Those cases need a working guideline too.

In general, the bad effects of a race in your test bench will be that
the test fails.  In general the bad effects of a post-synthesis race
are either, again, that the test fails (if you are lucky) or that the
silicon fails (if you are unlucky).  So why is it a problem to explain
things in the context of synthesis?

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

Quote:
So here it is: Decaluwe's universal guideline for race-free HDL
assignments.
"""
Use non-blocking assignments (signals) for communication.
Use blocking assignments (variables) for local computation.
"""

[ Rest of comment on this snipped. ]

Yes, this will work.  But in practice, examination to insure that
these guidelines have been followed can be more time-consuming than if
other guidelines are followed

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. It seems obvious that my proposal will make the work
of the reviewer or the linting tool both more meaningful and much
simpler.

Jan

Jan Decaluwe
Guest

Fri May 21, 2010 2:12 pm   



On May 20, 10:34 pm, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:

Quote:
I suspect that Jan, like me, is unhappy about Verilog's
completely uncontrolled concurrency model.

Absolutely correct. Rather unhappy :-)

In 1990, I designed a chip with Verilog, using blocking assignments
only because that's all there was at the time. Non-blocking behavior
was provided by using modules and ports - otherwise Verilog would have
been completely unusable at the time.

Much later, in 2000, I found out that simulation vendors had exploited
loopholes in the Verilog standard to take away non-blocking behavior
from ports. In other words, my trusted coding style and legacy code
had now become undeterministic and unreliable.

When I complained about this, I experienced not a single grain of
sympathy or understanding from the Verilog design community. Instead,
they started to explain the loopholes to me. The message was that I
had been stupid to think that it was possible to design with Verilog
in a reliable way at the time.

At that moment, I developed a fundamental distrust against Verilog's
zero-delay (non)model, and against Verilog's design community and its
guru's in the same pass. I learned to forgive VHDL almost anything
just for giving us the delta cycle algorithm. When using Verilog, I
tried to do it as much as possible as VHDL. And whenever I hear
someone sing the praises of Verilog's ease of use, I invariably think:
you don't have enough experience.

For my outcry in despair at the time, see:

http://groups.google.com/group/comp.lang.verilog/browse_frm/thread/edc6d326a821c9a9/67ec9f89afe22b3b

Jan

Jonathan Bromley
Guest

Fri May 21, 2010 3:37 pm   



On May 21, 12:12 pm, Jan Decaluwe <j...@jandecaluwe.com> wrote:

Quote:

At least Evan Lavelle backed you up Smile
--
Jonathan Bromley

Jan Decaluwe
Guest

Fri May 21, 2010 4:20 pm   



On May 21, 2:37 pm, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:
Quote:
On May 21, 12:12 pm, Jan Decaluwe <j...@jandecaluwe.com> wrote:

For my outcry in despair at the time, see:

http://groups.google.com/group/comp.lang.verilog/browse_frm/thread/ed...

At least Evan Lavelle backed you up Smile
--
Jonathan Bromley

That's right. My thanks to him, even if they are little out-of-date Smile

Patrick Maupin
Guest

Fri May 21, 2010 9:40 pm   



On May 21, 2:44 am, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:
Quote:
Patrick,

I don't have time to write a complete reply just now,
but I can't let this piece of nonsense go unchallenged:

[me]> > And then there's Verilog:
- anyone can mess with any shared variable at any time,

snip
[Pat]

If you want to
insure that another process can never see incoherent state between
variable X and variable Y, just make sure you update them at exactly
the same time.

That is simply untrue:

always @(posedge clock)
  X = some_expression;
always @(posedge clock)
  Y = some_other_expression;
always @(posedge clock) begin : observer
  if (some relationship between X and Y) ....;
end

Yes, I should have known that you would be both pedantic and
dismissive.
What I said is not nonsense *if* you always use non-blocking
assignments in sequential blocks. Of course you know I believe that
is the right answer, so of course you show an opposite example.

<snipped lots more examples of blocking assignments>

Quote:
No semaphore, mutex, or monitor required.

You're kidding, right?  In Verilog you make this
work correctly by wheeling out the evaluate/update
model made possible by nonblocking assignment.

Ahhh, so you *do* understand. But yes, a C semaphore or mutex or
monitor requires something *below* the level of the language, 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.

Quote:
In other environments you would use other exclusion
or synchronisation primitives.  Either way, you need
some discipline.

Coding requires discipline. With verilog, there is no *extra*
discipline that would be required for the kind of IPC thing we were
discussing than there is for sequential coding in general.

Quote:
Verilog is _much_ worse than C in this regard because
it has concurrency constructs built in to the language,
but they are completely undisciplined.  In C, to get
concurrency you must appeal to some library or toolkit;
if properly designed, that library will provide not
only the parallelism but also the synchronisation
primitives that you need, so you get a proper way to
do things as a single package.

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.

Regards,
Pat

Patrick Maupin
Guest

Fri May 21, 2010 9:47 pm   



On May 21, 3:19 am, nemo <gnu...@gmail.com> wrote:

Quote:
This last guideline is essentially what VHDL does.  Variables only
have scope within a process so can not be used for communication
between processes.  What guidelines would accomplish the same thing
and be easier to verify?  Sounds like something a tool should be
checking for you.

Obviously opinions vary, but if you always use non-blocking
assignments in sequential blocks, and always use blocking assignments
in combinatorial blocks, and adhere to a few other guidelines, it's
very easy to spot issues at a glance.

Regards,
Pat

Patrick Maupin
Guest

Fri May 21, 2010 9:59 pm   



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

On May 20, 3:08 am, Jan Decaluwe <j...@jandecaluwe.com> wrote:

Cummings' guideline to use only blocking assignments for combinatorial
logic is problematic, because it creates an unnecessary exception that
encourages something that is inherently dangerous.

Can you show a real-world example of this danger?

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.

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.


[ stuff snipped]

Quote:
Suppose you start manipulating clocks combinatorially, using assigns
or blocking assignments. I don't see why the resulting transactions
would be race-free. I immediately add that this is probably
nonsensical usage, and that in practice, blocking assignment-based
communication works for the special case of "meaningful" combinatorial
logic. But do you see why I call that a coincidence? It feels like
plain luck based on shaky foundations.

I see. I agree that (as you have also pointed out in other posts) the
foundations of Verilog were somewhat shaky (at least in the sense of
not being regular and extremely well thought out) and that some of the
subsequent fixes have created a non-orthogonal language.
"Coincidence" sounds like a lucky accident we got there at all, when
at the end of the day, it was through a lot of hard work, so "hack"
might be a better word :-)

[ stuff snipped ]

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.

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?

Quote:
It seems obvious that my proposal will make the work
of the reviewer or the linting tool both more meaningful and much
simpler.

Well, I've shown you an example of how I would code something, so you
know my mileage varies on that.

Regards,
Pat

Ali Karaali
Guest

Sat May 22, 2010 8:24 pm   



[Jonathan Bromley]

Quote:
The second issue is that blocking assignment in combinational
logic allows you to implement clock gating without a delta
delay.

What do you mean by that(implementing clock gating)?

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

But what about these?
always@(*) begin
a = b; //statement1
c = d; //statement2
end
Is there any order of those staments?

As for the nonblocking,
Is there any order between nonblocking assignments in the same
execution
path according to the verilog standart?

always@(posedge clk) begin
a <= b;
c <= d;
end

Ali

Jonathan Bromley
Guest

Sat May 22, 2010 10:06 pm   



On Sat, 22 May 2010 10:24:52 -0700 (PDT), Ali Karaali wrote:

Quote:
[Jonathan Bromley]

The second issue is that blocking assignment in combinational
logic allows you to implement clock gating without a delta
delay.

What do you mean by that(implementing clock gating)?

If you're using an FPGA, please don't worry about it.

When designing ASICs for low power consumption, folk
often use clock gating to suppress the clock to some
part of the design when it's not active. This is
*not* usually a good idea in an FPGA design, but in
an ASIC it can be a useful technique. So let's
suppose that the designer has correctly crafted a
clock gating signal ClockIsActive, and has carefully
arranged its timing so that
MasterClock & ClockIsActive
will behave nicely, with no unpleasant glitches.
OK, so now we try...

always @(posedge MasterClock)
Qm <= something;

always @*
GatedClock <= MasterClock & ClockIsActive;

always @(posedge GatedClock)
Qg <= Qm;

The problem is that GatedClock is delayed by
one nonblocking assignment delay (a delta cycle)
in just the same way as Qm is delayed. So now
there is a simulation race condition between the
change of Qm and the (posedge GatedClock) that's
used to sample it.

However, if you change the clock gate logic to

always @*
GatedClock = MasterClock & ClockIsActive;

or, just as good,

assign GatedClock = MasterClock & ClockIsActive;

then the clock gate (and any other combinational logic)
updates earlier than the nonblocking assignments, and the
sampling of Qm in the GatedClock domain works correctly.

Of course, this is merely a trick to make zero-delay
simulation work correctly. In the finished device it's
very important to apply appropriate timing constraints
to ensure that the real logic also behaves in this way.


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

But what about these?
always@(*) begin
a = b; //statement1
c = d; //statement2
end
Is there any order of those staments?

Yes, certainly. Sequential statements in a begin...end block
are definitely executed in order. The whole point about blocking
assignment is that the assignment has completed (has taken effect)
before the next statement is executed. Just like normal software.

Quote:
As for the nonblocking,
Is there any order between nonblocking assignments in the same
execution
path according to the verilog standart?

always@(posedge clk) begin
a <= b;
c <= d;
end

Yes! The two assignments execute sequentially. Consequently the
order of activity is:

1) Evaluate "b"
2) Make a delayed assignment of that value to "a" - put the
assignment on the queue of future activity, but don't do it yet
3) Evaluete "d"
4) Make the delayed assignment to "c"
5) Do any other "always" blocks that were triggered by
(posedge clk), in the same way as I just described
6) When all such activity is finished, update the variables
that have scheduled delayed assignments, BUT DO IT IN THE
SAME ORDER IN WHICH THE CORRESPONDING ASSIGNMENTS WERE
EXECUTED (first-in first-out). Therefore, first update
"a" and then update "c".

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

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