<= and =

M

Mahurshi Akilla

Guest
i have read somewhere that whenever we're dealing with registers in
always @ blocks, we should ALWAYS use &lt;= and that whenever we're using
pure combinatorial logic outside of always @ blocks, we should ALWAYS
use =

could anyone let me (a newbie) know if this is true?
 
Mahurshi Akilla wrote:

i have read somewhere that whenever we're dealing with registers in
always @ blocks, we should ALWAYS use &lt;= and that whenever we're using
pure combinatorial logic outside of always @ blocks, we should ALWAYS
use =

could anyone let me (a newbie) know if this is true?
Have a look at Cliff Cummings: "Verilog Coding styles, that kill" (you
will find it as PDF in the web.)

Short:
1) Outside always-blocks (assign) use "=" (you don't have any option).
2) For combinational logic use "=".
3) For sequential logic use "&lt;=".

Ralf
 
thanks.

this is probably a pretty dumb question. but i figured i should ask it
anyway. i promise the questions get smarter as i learn more and more
of this behavioral coding.

if i have a

FLIPLOP ---------- LOGIC ------------- FLIPFLOP

1. should the logic go under an always @(posedge clk) ? or should it
be done seperately?

2. if it goes under always @(posedge clk), i am assuming, we'll use "="
for that comb. logic, is that a safe assumption?
 
i have read somewhere that whenever we're dealing with registers in
always @ blocks, we should ALWAYS use &lt;= and that whenever we're using
pure combinatorial logic outside of always @ blocks, we should ALWAYS
use =
Your rules are not a bad approximation to the truth. You can also put
combinatorial logic inside an always block (and "need" to, to do
things like muxes and priority encoderr that require case statements).
When you put combinatorial logic in an always block, one uses a reg,
and one uses =, a blocking assignment, and if possible one should use
the Verilog 2001 "always @ *" as the wrapper for the block.

There are even more subtle cases to deal with, especially when
assigning multiple registers (especially when some of the registers
are both source and target) in the same always block, see below. In
those cases, you want to think carefully what you mean. You may after
careful deliberation, decide that some code fragments are not good
style and are more trouble than they are worth.

always @ (posedge clk)
begin
a &lt;= b; // a gets the old value of b
b &lt;= a; // b gets the old value of a
end

always @ (posedge clk)
begin
a &lt;= a + 1;
if (b == 0) c &lt;= a; // c gets the old value of a, not the new
end

always @ (posedge clk)
begin
a = a + 1; // note that I used a blocking assign here
if (b == 0) c &lt;= a; // c gets the new value of a, not the old
end

There are people who have thought long about the various issues of &lt;=
and =, Cliff Cummings is famous for it, and you would do well to read
their advice.

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 
Mahurshi Akilla wrote:

if i have a

FLIPLOP ---------- LOGIC ------------- FLIPFLOP

1. should the logic go under an always @(posedge clk) ? or should it
be done seperately?
This depends on you. If one version seems to be more readable to you,
you got the decision.

I take the example from you other posting:

always @(posedge clk)
begin
sum &lt;= a + b;
end

Here combinational logic plus the flipflops are modeled. You could also
write

always @(a or b)
begin
result = a + b;
end

always @(posedge clk)
begin
sum &lt;= result;
end

but this would be less readable.


2. if it goes under always @(posedge clk), i am assuming, we'll use "="
for that comb. logic, is that a safe assumption?
No. Everything inside a an edge-triggered always-statement should use
non-blocking signal assignments "&lt;=".
Nevertheless - modeling pure combinational logic inside an
edge-triggered always statement is a little bit tricky. ;-) Usually one
models combinational logic _plus_ the final flipflop(s).


Ralf
 
It is matter for simulation only. For synthesizer it is the same.
 
Ralf Hildebrandt followed-up on my comments with:
I agree with you and your examples are very nice, but there is one
point to mention - Cummings' guideline #5: "Don't mix blocking and
non-blocking signal assignments in one always statement."

Well - mixing both assignments for _one_ signal is forbidden. But if
there is more than one signal in an always statement?
I must admit that I haven't recently reviewed Cummings' rules. The
point of the Cummings' rules (like all good design rules) are to keep
one out of trouble. One of my mentors once said, never put something
in a coding standard unless you can identify the problem it solves.
Therefore, if you follow Cliff Cummings' rules, you can be reasonably
certain that when you violate a rule, there is some pitfall you must
steer around. That doesn't mean that there aren't other ways to avoid
those same pitfalls (i.e. different sets of rules that have the same
effect).

In fact, my examples were driven by what our in-house cycle-based
simulator allow our designers to do. They codify the rules that we
have laid down to keep our designers out of trouble. As a designer,
one can either just learn and follow the rules, or learn what the
rules are protecting you from and avoid the underlying problems. I
took the initial posters question as leaning that direction. I would
like to think that my examples provided a glimpse into one way of
thinking about the problem.

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 
Jan Decaluwe wrote:


Let's try it for rule #5. Can you identify the problem it solves?
Probably not, because you violate it in your own examples.
I can't either. (I can merely identify the problems it *causes*.)

Of course, Mr. Cummings himself should provide the answer. Here
is the quote from the original paper, talking about mixing
blocking and nonblocking assignments:

"Although this will work, the author discourages this coding style".

That's it. No arguments, technical or other, nothing. It works,
but I don't like it and so you shouldn't do it.

Sorry, but I cannot take this seriously.
Nice interpretation. I would follow it.

I guess this guideline #5 is given to avoid blocking and non-blocking
signal assignments to _one_ signal inside one always statement. (This
simulates, but synthesis tools refuse to synthesize this.)

Ralf
 
Chris F Clark wrote:
Ralf Hildebrandt followed-up on my comments with:

I agree with you and your examples are very nice, but there is one
point to mention - Cummings' guideline #5: "Don't mix blocking and
non-blocking signal assignments in one always statement."

I must admit that I haven't recently reviewed Cummings' rules.
Always be careful when making recommendations - you may have to
follow them yourself :)

You examples demonstrate the synchronous always block (or process)
style. This means that by default you map all hardware behavior
in an edge-triggered always block. You use both blocking
and non-blocking assignments, to get the behavior you want.

It's a great coding style. In many cases, it provides elegant coding
solutions that would be much harder (if not impossible) in a different
(lower level) coding style. And it synthesizes perfectly.

All fine - except that, if you believe Cummings' rule #5, you
can't do it. Which is why I recommend to ignore that rule.

One of my mentors once said, never put something
in a coding standard unless you can identify the problem it solves.
Good principle.

Therefore, if you follow Cliff Cummings' rules, you can be reasonably
certain that when you violate a rule, there is some pitfall you must
steer around.
Wait a moment, are you sure those rules adhere to the principle above?

Let's try it for rule #5. Can you identify the problem it solves?
Probably not, because you violate it in your own examples.
I can't either. (I can merely identify the problems it *causes*.)

Of course, Mr. Cummings himself should provide the answer. Here
is the quote from the original paper, talking about mixing
blocking and nonblocking assignments:

"Although this will work, the author discourages this coding style".

That's it. No arguments, technical or other, nothing. It works,
but I don't like it and so you shouldn't do it.

Sorry, but I cannot take this seriously.

Regards,

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
 
Jan Decaluwe contributed the following to the discussion:

J&gt; You examples demonstrate the synchronous always block (or process)
J&gt; style. This means that by default you map all hardware behavior
J&gt; in an edge-triggered always block. You use both blocking
J&gt; and non-blocking assignments, to get the behavior you want.
....
J&gt; All fine - except that, if you believe Cummings' rule #5, you
J&gt; can't do it. Which is why I recommend to ignore that rule.

and I had written:
C&gt; Therefore, if you follow Cliff Cummings' rules, you can be reasonably
C&gt; certain that when you violate a rule, there is some pitfall you must
C&gt; steer around.

Jan again:
J&gt; Wait a moment, are you sure those rules adhere to the principle above?

J&gt; Let's try it for rule #5. Can you identify the problem it solves?
J&gt; Probably not, because you violate it in your own examples.
J&gt; I can't either. (I can merely identify the problems it *causes*.)

While I'd hate to put words in Cliff Cummings' mouth, I believe that he
is trying to avoid a problem that we solve another way.

The issue is that if one has a blocking assignment to a signal in an
edge triggered block and a use of that signal in another edge
triggered block, then the ordering of the two blocks can cause a race
condition which may or may not simulate and/or synthesize to what you
want. In fact, in the worse case, it simulates to what you want (due
to artifacts of the particular simulator you are using, but
synthesizes to something that doesn't work).

If you don't put blocking assignments in edge triggered blocks, you
will never have that problem. If you follow Cummings' rule 5 (in
conjunction with his other rules), you won't ever put a blocking
assignement in an edge triggered block, because you won't use an edge
triggered block for combinatorial or latch logic, and if you have a
non-blocking assignment representing a flop in your edge triggered
block, you won't put any combinatorial gates using blocking
assignments in that block. Thus, everything driven out of an edge
triggered block, will be a flop, and will be assigned by a
non-blocking assignment which will prevent the race described above.

Now, as I said, where I work, we solve this a different way. Our rule
is, you cannot use the result of a blocking assignment in an edge
triggered always block outside of that always block. Somewhere, I
even recall someone posting the suggestion that one should use named
begin blocks and local variables to enforce that rule. Not a bad
idea.

We enforce this by tools in our design and validation flow, so that we
are certain designers don't violate the rules. However, if one didn't
have tools to enforce it, one might be tempted to put something
simpler in place. Cliff Cummings' rules are "simpler" in that way.
You simply cannot write dangerous code where a signal assigned by a
blocking assignment in one edge triggered block is used in another,
because you cannot assign to a signal with a blocking assignment in an
edge triggered block.

Note that we considered making the same prohibition. We just decided
that we could safely loosen that rule, if we could check assignments
against uses. And, since we have to deal with imported IP written
outside our group and not adhering to our rules, it is best if we can
make the rules as non-stringent as possible, so that we have less
issues with in the imported IP.

If I were in Cliff Cummings' shoes and potentially teaching very
junior engineers, I might stick to his rule 5 as it is simpler to
remember. In fact, I would probably stick to blocking assignments
only in always @* blocks and non-blocking assignments only in edge
triggered always blocks. The only problem is then the junior coders
might see a design with more liberal rules and start doing that
without knowing when it is safe.

In the end, the good engineer tries to learn why the rules are in
place, and what they are trying to prevent. Then, you will know when
you can bend the rules, and when you shouldn't.

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 
Ralf Hildebrandt wrote:
Jan Decaluwe wrote:


Let's try it for rule #5. Can you identify the problem it solves?
Probably not, because you violate it in your own examples.
I can't either. (I can merely identify the problems it *causes*.)

Of course, Mr. Cummings himself should provide the answer. Here
is the quote from the original paper, talking about mixing
blocking and nonblocking assignments:

"Although this will work, the author discourages this coding style".

That's it. No arguments, technical or other, nothing. It works,
but I don't like it and so you shouldn't do it.

Sorry, but I cannot take this seriously.


Nice interpretation. I would follow it.

I guess this guideline #5 is given to avoid blocking and non-blocking
signal assignments to _one_ signal inside one always statement. (This
simulates, but synthesis tools refuse to synthesize this.)
No, that is not correct. The guideline very clearly targets all
cases, in particular the one in which the blocking and non-blocking
assignments are made to different regs. Actually, the phrase "although
this will work" clearly targets this case, and acknowledges
that it will work for both simulation and synthesis. See the paper.

The other case - using a blocking and a non-blocking assignment
on the same reg - deserves more consideration. It is also
mentioned in the paper, showing that leading synthesis tools will
treat this as an error. I believe that is the proper thing to do.
In fact, I believe Verilog itself should not allow this.
[Possible exception: initialization syntax at declaration time]

To put it more strongly, I consider the fact that Verilog doesn't
distinguish between 'variables' and 'signals' as a language
flaw. If it would, the latter case would no longer exist
and the useful, former case would confuse nobody (well, you
never know.) Anyway, one should never have to give up on a
superior design style because of a language flaw.

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
 
Chris F Clark wrote:

While I'd hate to put words in Cliff Cummings' mouth, I believe that he
is trying to avoid a problem that we solve another way.

The issue is that if one has a blocking assignment to a signal in an
edge triggered block and a use of that signal in another edge
triggered block, then the ordering of the two blocks can cause a race
condition which may or may not simulate and/or synthesize to what you
want.
[No need to put words in his mouth - he attempted to rationalize the
guideline himself in a later paper. His arguments are different, and
yours is better, by the way. But I must conclude that few people
actually read his papers (granted, they are boring at times), or are
interested in his arguments and lack thereof. Which doesn't prevent
us from referring to what he calls "guidelines" (to his credit)
as "rules", and treating him as if he were Mozes or Mohamed.]

That is a real issue - in Verilog. To solve it you could either
use a different language (best solution), use linting tools (second
best), or design discipline, such as using only local variables
(as you refer to.) But applying guideline 5 to solve this is really
a cure that's worse than the disease, as it would ban an essential
design paradigm.

If I were in Cliff Cummings' shoes and potentially teaching very
junior engineers, I might stick to his rule 5 as it is simpler to
remember.
I would try to teach good design principles right from the start,
so I would introduce the synchronous always block paradigm right away.
You seem to suggest that this would be "too difficult" for
junior engineers. But it isn't: it just approaches the hardware
design problem from a different angle, that is, the one of using
a language and synthesis. (Note that guideline 5 essentially
bans the use of variables - rather strange when you are familiar
with other programming languages). Better yet, it even has
advantages in terms of simulation speed (less events) and
synthesis (no problems with incomplete sensitivity lists
and unwanted latches).

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
 
Ralf Hildebrandt wrote:
Mahurshi Akilla wrote:

2. if it goes under always @(posedge clk), i am assuming, we'll use "="
for that comb. logic, is that a safe assumption?


No. Everything inside a an edge-triggered always-statement should use
non-blocking signal assignments "&lt;=".
I wouldn't know why.

Nevertheless - modeling pure combinational logic inside an
edge-triggered always statement is a little bit tricky. ;-) Usually one
models combinational logic _plus_ the final flipflop(s).
What the OP refers to is how that combinational logic can be
modeled, and whether it's OK to use '=' assigns to hold
intermediate results. And that is true.

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
 
Chris F Clark wrote:

Now, as I said, where I work, we solve this a different way. Our rule
is, you cannot use the result of a blocking assignment in an edge
triggered always block outside of that always block. Somewhere, I
even recall someone posting the suggestion that one should use named
begin blocks and local variables to enforce that rule. Not a bad
idea.
Thanks. Note that one way I can meet your rule
is to use only one block per module with as
many regs as I need.

-- Mike Treseler
 
On 05 Mar 2006 17:12:39 -0500, Chris F Clark
&lt;cfc@shell01.TheWorld.com&gt; wrote:

I wrote:

C&gt; Now, as I said, where I work, we solve this a different way. Our rule
C&gt; is, you cannot use the result of a blocking assignment in an edge
C&gt; triggered always block outside of that always block. Somewhere, I
C&gt; even recall someone posting the suggestion that one should use named
C&gt; begin blocks and local variables to enforce that rule. Not a bad
C&gt; idea.

Mike Treseler added:

M&gt; Thanks. Note that one way I can meet your rule
M&gt; is to use only one block per module with as
M&gt; many regs as I need.

Other than the modularity issue (i.e. does your one always block get
too large to read and comprehend), I'm not sure that one always block
per module is a bad idea, expecially if it is sensitive only to one
clock (and maybe a reset and enable), as in:

always @(posedge clock or negedge reset or posedge enable)
begin
if (reset == 0)
begin
// lots of code explaining what to do on reset
end
else if (enable == 1) and (clock == 1)
begin
// lots of code explaining what to do in the enabled clock case
end
end
Are you sure that's what you mean? You have described a system with a
gated clock, rather than a clock enable.

Changing this line:

always @(posedge clock or negedge reset or posedge enable)
to this:

always @(posedge clock or negedge reset)
will give you a true clock enable. This will match the hardware
available in (e.g.) FPGAs.


Another point: many coding standards require that active low signals
be identified as such. You use an active low reset called 'reset'
rather than resetb, resetn, or whatever.

Regards,
Allan
 
Chris F Clark wrote:


always @ (posedge clk)
begin
a = a + 1; // note that I used a blocking assign here
if (b == 0) c &lt;= a; // c gets the new value of a, not the old
end
I agree with you and your examples are very nice, but there is one point
to mention - Cummings' guideline #5: "Don't mix blocking and
non-blocking signal assignments in one always statement."

Well - mixing both assignments for _one_ signal is forbidden. But if
there is more than one signal in an always statement?

I personally have to say, that I like the way of coding like shown in
your example. It is similar to VHDL: Everything, what is a VHDL
variable, gets blocking signal assignment "=", everything, what is a
VHDL signal gets non-blocking signal assignment "&lt;=" with one exception:
After the "assign" command only blocking signal assignments are possible.
This simple rule reduces all the guidelines to this compact form and
makes translations between VHDL and Verilog much simpler.

But this is personal opinion and I am doubtful, if I did not miss an
important fact.
I know, that the rule of not mixing both assignments collides with my rules.
I know, that using non-blocking signal assignments in pure combinational
always statements make it necessary to have _all_ signals that are read
in the sensitivity list, which may lead to increased simulation time
because of triggering the always statement again. (Cummings' guideline #3)
But is there a trap, I miss?

Ralf
 
Ralf Hildebrandt wrote:
Mahurshi Akilla wrote:

2. if it goes under always @(posedge clk), i am assuming, we'll use "="
for that comb. logic, is that a safe assumption?


No. Everything inside a an edge-triggered always-statement should use
non-blocking signal assignments "&lt;=".
I wouldn't know why.

Nevertheless - modeling pure combinational logic inside an
edge-triggered always statement is a little bit tricky. ;-) Usually one
models combinational logic _plus_ the final flipflop(s).
What the OP refers to is how that combinational logic can be
modeled, and whether it's OK to use '=' assigns to hold
intermediate results. And that is true.

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
 
Jan Decaluwe wrote:


No. Everything inside a an edge-triggered always-statement should use
non-blocking signal assignments "&lt;=".

I wouldn't know why.

Nevertheless - modeling pure combinational logic inside an
edge-triggered always statement is a little bit tricky. ;-) Usually
one models combinational logic _plus_ the final flipflop(s).

What the OP refers to is how that combinational logic can be
modeled, and whether it's OK to use '=' assigns to hold
intermediate results. And that is true.
Accepted - my fault.
I don't know why I forgot intermediate values (variables). Sorry.

always @(negedge reset or posedge clock)
begin
if (reset == 1'b0) begin
flipflop = 0;
end else /*if posedge clock*/ begin
temp = some_signal; // blocking for the variable
flipflop &lt;= temp; // non-blocking the result
end //if
end //always

Nevertheless, this coding style (which is like) violates the rule of not
mixing the signal assignments in one always statement. Some company
design rules are very strict to not violate this rule.


Ralf
 
I wrote:

C&gt; Now, as I said, where I work, we solve this a different way. Our rule
C&gt; is, you cannot use the result of a blocking assignment in an edge
C&gt; triggered always block outside of that always block. Somewhere, I
C&gt; even recall someone posting the suggestion that one should use named
C&gt; begin blocks and local variables to enforce that rule. Not a bad
C&gt; idea.

Mike Treseler added:

M&gt; Thanks. Note that one way I can meet your rule
M&gt; is to use only one block per module with as
M&gt; many regs as I need.

Other than the modularity issue (i.e. does your one always block get
too large to read and comprehend), I'm not sure that one always block
per module is a bad idea, expecially if it is sensitive only to one
clock (and maybe a reset and enable), as in:

always @(posedge clock or negedge reset or posedge enable)
begin
if (reset == 0)
begin
// lots of code explaining what to do on reset
end
else if (enable == 1) and (clock == 1)
begin
// lots of code explaining what to do in the enabled clock case
end
end

That looks a whole lot like you can just read the code and tell what
the state to next-state transitions are on each clock cycle. Again,
that might not be modular enough, as the code to transition from one
state to the next can be complex and you might want to break it down
into parts. However, the basic idea behind wriiting coode like that
seems reasonable.

BTW, I should put out that the rule that the target of a blocking
assignment cannot be used outside an always block is not our only
coding rule. We also prohibit the loop-around case, where you assign
the to variable with a blocking assignment in one pass through the
always block and then later reenter the always block and use the value
that was assigned on the previous pass. That is we make the following
code illegal:

always @(posedge clock)
begin
t = a + 1; // use of a
// more code
a = b; // non-blocking assignment that can "reach" the above use
// the next time this block is executed
end

There is no inherent problem with the above code and it will both
synthesize and simulate correctly. However, a is now a register,
latch, or flop of some type. We don't want our coders "accidently"
coding state devices that way, so we prohibit it. We "require" that
state devices (memories) be coded by non-blocking assignments and
combinatorial devices be coded by blocking assigns. The flaw we are
trying to avoid there is the creation of memories in the chip that the
designer hasn't anticipated. The designer is supposed to understand
the design and know where memories are located. Any place where a
memory is put that the designer hasn't planned represents a lack of
understanding on the designers part.

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 

Welcome to EDABoard.com

Sponsor

Back
Top