Discussion:
Verilog Counter Glitch
(too old to reply)
Amr
2008-02-22 21:14:36 UTC
Permalink
Hello all,

I wrote the following counter module in Verilog as a learning
exercise:

module pixel_counter(
input clock,
output reg [6:0] count,
output reg rollover);

always @ (posedge clock)
begin
count=count+1;
if (count==0)
rollover=1;
else
rollover=0;
end

endmodule

Now, when I came to simulate it using Quartus II, I found that the
counter worked fine but there was some strange glitches occurring
quite frequently that caused the output of the counter to change even
when the clock was stable. Screenshots of the glitches can be found at
Loading Image... and
Loading Image....

The interesting thing is that I downloaded a few examples of Verilog
counters online, including one from Altera (http://www.altera.com/
support/examples/verilog/ver-counter.html) and even those examples had
the same glitch.

I was wondering whether this glitch is caused by the Verilog code or
whether this is something inherent in the FPGA hardware (a Cyclone III
EP3C25F324 FPGA)? How can I fix it?

Thanks

--Amr
Jonathan Bromley
2008-02-22 22:30:34 UTC
Permalink
On Fri, 22 Feb 2008 13:14:36 -0800 (PST),
Post by Amr
I wrote the following counter module in Verilog as a learning
module pixel_counter(
input clock,
output reg [6:0] count,
output reg rollover);
begin
count=count+1;
if (count==0)
rollover=1;
else
rollover=0;
end
endmodule
Now, when I came to simulate it using Quartus II, I found that the
counter worked fine but there was some strange glitches occurring
I was wondering whether this glitch is caused by the Verilog code or
whether this is something inherent in the FPGA hardware (a Cyclone III
EP3C25F324 FPGA)? How can I fix it?
Let me answer this in two stages.

First, I'll answer your question. The simulation you're running
is, I suspect, simulating the FPGA logic that was derived from your
code. The counter has 7 flip-flops, of course. Each of these FFs
has a *different* propagation delay from the clock. So, on a clock
transition that increments the counter, some of the FFs will change
their value just a little before some others. That gives you a
"glitch". In fact, it's just the counter outputs settling; your
logic will use this counter output to do something on the NEXT
clock edge, by which time everything will be nicely settled.
This kind of glitch just happens with synchronous logic. If
you are truly desperate to avoid it you can design a Gray-code
counter, but that is almost certainly unnecessary.

Second, allow me to tell you why your code is crap. You have
made the fatal error of using BLOCKING Verilog assignment (=)
to the outputs of a clocked "always" block. When you write
a clocked "always":

always @(posedge clock) begin ...

you MUST arrange that the outputs of that block are given their
values by NONBLOCKING assignment using the <= operator:

always @ (posedge clock)
begin
count <= count+1;
if (count==7'b1111111)
rollover <= 1;
else
rollover <= 0;
end

Note, now, that I must test count==all-ones instead of count==0,
because the nonblocking assignment does NOT update its output
variable until after the following statements have executed.

Please don't try to argue with me about this. Just don't EVER
do what you did in the example code you posted. The reasoning
behind this is too lengthy to list here, but you can easily
find Cliff Cummings's paper on it:

http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf

As I've mentioned here on numerous occasions, there are
things Cliff says in this paper that I think are wrong,
but it remains truly excellent advice for beginners and
it's still the most thorough discussion of the problem
that you're likely to find.

Fixing this will not remove your simulation glitch,
but it will stop your design being broken.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
***@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Mike Treseler
2008-02-23 00:42:57 UTC
Permalink
Post by Jonathan Bromley
Just don't EVER
do what you did in the example code you posted.
Forever is a long time.
I would say avoid the '=' assignment
in a synchronous block until you understand
the upside and downside of such usage
and the design rules and checks that
can make it safe.

-- Mike Treseler
Jonathan Bromley
2008-02-23 12:07:20 UTC
Permalink
Post by Mike Treseler
Post by Jonathan Bromley
Just don't EVER
do what you did in the example code you posted.
Forever is a long time.
I would say avoid the '=' assignment
in a synchronous block until you understand
the upside and downside of such usage
and the design rules and checks that
can make it safe.
Understood, but I don't think I plan to retract my
stipulation that you should *never* - really,
not ever - use blocking assignment to an *output*
of a clocked always block in a synthesisable design.

Internal variables used only within the block are,
of course, another matter entirely. And there are
situations in a testbench where I can make use of
the shared-variable semantics of blocking assignment
from a clocked procedural block. But, as you say,
such usage needs careful thought and a reasonably
good understanding of the way Verilog works.

It's unfortunate that the SystemVerilog always_ff
construct doesn't enforce the appropriate rules
about blocking and nonblocking assignment. Tools
are free to add such checks and issue warnings,
but I'm not aware of any simulators that do so.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
***@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Mike Treseler
2008-02-23 15:32:45 UTC
Permalink
Post by Jonathan Bromley
Understood, but I don't think I plan to retract my
stipulation that you should *never* - really,
not ever - use blocking assignment to an *output*
of a clocked always block in a synthesisable design.
On page 11, Cliff hits the nail on the head:

"If an engineer is willing to limit all modules
to a single always block, blocking assignments can be used
to correctly model, simulate and synthesize the desired logic."

I am willing.
In fact I prefer to describe all logic
this way because it lets me use C-like
variables for logic description, like this:
http://home.comcast.net/~mike_treseler/count_enable.v


-- Mike Treseler
Jonathan Bromley
2008-02-23 16:44:55 UTC
Permalink
Post by Mike Treseler
"If an engineer is willing to limit all modules
to a single always block, blocking assignments can be used
to correctly model, simulate and synthesize the desired logic."
I am willing.
In fact I prefer to describe all logic this way
Whoa! There's a little too much reading-between-lines
going on here, and a slightly worrying error in your
example (see the last two paragraphs of this post).

Let me begin by saying that I totally understand your
position, Mike: you want to write a software-like description
of functionality, with software-like variable update semantics,
and have the synth tool do whatever it takes to make hardware
out of that. Great stuff.

Note, though, that (if I'm not mistaken) you reached this
viewpoint based on a *VHDL* coding style. In VHDL, variables -
with their immediate-update semantics - simply cannot leak out
of a process; the language doesn't permit it. (Yes, I know about
shared variables; most synth tools won't handle them, which is
just as well. Let's put them to one side for the time being.)
So you write your sequential software-like process, doing all
your work with variables; and then, at the last possible moment,
you drive some of those variables' values out on to signals
so that they can flow out of the process and be used in other
processes, possibly in other module (entity) instances.
Signals have delayed update semantics that guarantee
race-free behaviour of multiple processes triggered by the
same clock, whether those two processes are in the same
module instance or in widely separated locations in the
module hierarchy.

So far, so good. What's more, you can very easily replicate
this VHDL coding style in Verilog clocked processes by....

- making BLOCKING assignment to variables declared locally
within the clocked process, ensuring that those variables
are not referenced by any other process;
- making NONBLOCKING assignment to variables declared outside
the process, which therefore can be referenced/read in other
processes.

Sadly, Cliff Cummings rejects this possibility out-of-hand
(see Example 24 on page 17 of the paper) without giving any
good reasoning. In this respect he is simply wrong. Provided
the variables that you write with blocking assignment are
strictly localised to the process, all is well.
Post by Mike Treseler
"If an engineer is willing to limit all modules
to a single always block, blocking assignments can be used
to correctly model, simulate and synthesize the desired logic."
is also just plain wrong. If a variable written in a clocked
process by blocking assignment is read in ANY other process
clocked by the same clock, whether it's in the same module
or a different one, then there is a read/write simulation race.

[In fairness to Cliff, that was a throw-away line in the paper
and his ultimate conclusion is perfectly clear: in clocked
processes, use nonblocking assignment for all writes.]

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It's this last consideration that leads me to believe that
there is an error in your Verilog example 'count_enable.v'.
The "update_port" block ought to make *nonblocking* assignments
to q_a, q_b, q_c, but you have written them using *blocking*
assignment. If those signals are read in any other process
clocked by (posedge clock) then there will be a read/write race
on them in simulation. I know that you intend there should be
no such process elsewhere in the same module, but it seems very
likely that there may be other modules in the design that have
processes triggered by the same clock. Synthesis, by contrast,
will reliably respect your design intent, because synthesis
infers logic from each process separately.

In your equivalent example in VHDL this problem does
not arise, because the ports q_a/q_b/q_c are signals
with their delayed (i.e. nonblocking) update semantics.
It's important to emulate this behaviour correctly when
migrating to Verilog.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
***@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Mike Treseler
2008-02-23 19:11:49 UTC
Permalink
Post by Jonathan Bromley
Whoa! There's a little too much reading-between-lines
going on here, and a slightly worrying error in your
example (see the last two paragraphs of this post).
Thanks for taking the time to read my code.
My link now shows the corrected port assignments.
Post by Jonathan Bromley
If a variable written in a clocked
process by blocking assignment is read in ANY other process
clocked by the same clock, whether it's in the same module
or a different one, then there is a read/write simulation race.
Thanks for your detailed diagnosis.
In a full design, there would certainly be
other modules *reading* that port.
I stand corrected, but I have at least provided
further evidence that you original advice
to Amr was on the money ;)

I fell into this trap while eliminating
warning messages from synthesis.
The '<=' port assignment causes
an extraneous warning "can't infer register for assignment"
even though the synthesis is done correctly in either case.

You are also correct that I came to this
verilog style from a vhdl point of view.
I use it mainly to translate vhdl to verilog.
Post by Jonathan Bromley
In your equivalent example in VHDL this problem does
not arise, because the ports q_a/q_b/q_c are signals
with their delayed (i.e. nonblocking) update semantics.
It's important to emulate this behaviour correctly when
migrating to Verilog.
I get it. Thanks.

-- Mike Treseler
Jan Decaluwe
2008-02-23 20:35:16 UTC
Permalink
Post by Jonathan Bromley
Post by Mike Treseler
"If an engineer is willing to limit all modules
to a single always block, blocking assignments can be used
to correctly model, simulate and synthesize the desired logic."
is also just plain wrong. If a variable written in a clocked
process by blocking assignment is read in ANY other process
clocked by the same clock, whether it's in the same module
or a different one, then there is a read/write simulation race.
... the confusion goes on forever :-)

There was a time when Cliff was right on that point.

I know this because I designed a chip in that style, in 1990.
We had to, because non-blocking assignments were *not available*.
(I'm not sure this was from the language, or from Synopsys DC.)

Inside modules, you had races. But between modules,
there were no races. You had "signal-like" behavior.
(This was with Verilog-XL of course: there was nothing else!)

It couldn't have been otherwise, or else Verilog and synthesis
would simply have been unusable at that time. (Guess what
that would have meant for Synopsys.)

Some years later I found out that the above behavior had been
"relaxed" under the influence of competing "optimizing" simulators.
As a result, the *only* race-free coding style available in 1990
was torn to pieces. I was very angry about this:

http://groups.google.com/groups/search?q=horrible+truth+about+verilog&qt_s=Search+Groups

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
Jonathan Bromley
2008-02-23 21:15:40 UTC
Permalink
On Sat, 23 Feb 2008 21:35:16 +0100,
Post by Jan Decaluwe
... the confusion goes on forever :-)
Depressingly, yes.
Post by Jan Decaluwe
I know this because I designed a chip in that style, in 1990.
We had to, because non-blocking assignments were *not available*.
(I'm not sure this was from the language, or from Synopsys DC.)
Language, I believe. My 2nd-edition copy of Thomas & Moorby
doesn't mention NBA at all. I'm not sure when it was added,
but it was certainly there by the time OVI (Open Verilog
International, later to become Accellera) had published
their Verilog 1.0 LRM in November 1991. The front-matter
of my copy of that document says...

The information contained in this draft manual
represents the definition of the Verilog hardware
description language as it existed at the time
Cadence Design Systems, Inc. transferred the language
and its documentation to Open Verilog International
(OVI). This manual does not contain any language
changes or additions developed or approved by OVI.
This information constitutes the basis from which
OVI may make refinements and/or additions to the language.

Clause 8.2.2 of that document describes NBAs in pretty much
exactly the form they took in IEEE Verilog-1995, and still
have today.
Post by Jan Decaluwe
Inside modules, you had races. But between modules,
there were no races. You had "signal-like" behavior.
(This was with Verilog-XL of course: there was nothing else!)
Was that *ever* documented? Anywhere? If so, how on earth
was it explained-away?
Post by Jan Decaluwe
It couldn't have been otherwise, or else Verilog and synthesis
would simply have been unusable at that time.
Tiresome, yes; unusable, no. You could have arranged that all
signals going away from a process were driven on to wires with
a small inertial delay (but NOT #0 !!!!).
Post by Jan Decaluwe
Some years later I found out that the above behavior had been
"relaxed" under the influence of competing "optimizing" simulators.
As a result, the *only* race-free coding style available in 1990
Given the chaotic nature of Verilog in its early days, it's
utterly astonishing that it achieved such dominance over VHDL.
The general nonsense about NBAs and simulation races must have
cost the IC industry untold millions of dollars in lost
time-to-market over the lifespan of Verilog. But despite this,
despite VHDL's obvious superiority as an RTL design language,
it was possible to say in 1995 that "VHDL was a $400 million
mistake" and have most people believe it...

Today, though, the chaos is contained within well-defined
boundaries, and anyone who's prepared to invest a little
effort in learning appropriate coding idioms (or invest a
lot of cash in a good linting tool) can use Verilog with
complete confidence for RTL design.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
***@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Jan Decaluwe
2008-02-23 22:33:13 UTC
Permalink
Post by Jonathan Bromley
Post by Jan Decaluwe
Inside modules, you had races. But between modules,
there were no races. You had "signal-like" behavior.
(This was with Verilog-XL of course: there was nothing else!)
Was that *ever* documented? Anywhere? If so, how on earth
was it explained-away?
Post by Jan Decaluwe
It couldn't have been otherwise, or else Verilog and synthesis
would simply have been unusable at that time.
Tiresome, yes; unusable, no. You could have arranged that all
signals going away from a process were driven on to wires with
a small inertial delay (but NOT #0 !!!!).
Post by Jan Decaluwe
Some years later I found out that the above behavior had been
"relaxed" under the influence of competing "optimizing" simulators.
As a result, the *only* race-free coding style available in 1990
Given the chaotic nature of Verilog in its early days, it's
utterly astonishing that it achieved such dominance over VHDL.
The general nonsense about NBAs and simulation races must have
cost the IC industry untold millions of dollars in lost
time-to-market over the lifespan of Verilog. But despite this,
despite VHDL's obvious superiority as an RTL design language,
it was possible to say in 1995 that "VHDL was a $400 million
mistake" and have most people believe it...
Today, though, the chaos is contained within well-defined
boundaries, and anyone who's prepared to invest a little
effort in learning appropriate coding idioms (or invest a
lot of cash in a good linting tool) can use Verilog with
complete confidence for RTL design.
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
Jan Decaluwe
2008-02-23 22:48:50 UTC
Permalink
Post by Jonathan Bromley
On Sat, 23 Feb 2008 21:35:16 +0100,
Post by Jan Decaluwe
Inside modules, you had races. But between modules,
there were no races. You had "signal-like" behavior.
(This was with Verilog-XL of course: there was nothing else!)
Was that *ever* documented? Anywhere? If so, how on earth
was it explained-away?
I suspect it was never documented explicitly. But given the work
we had to do, and the tools we had, we had to believe in something.
I recall that my mental model was: "Ports are special".
Post by Jonathan Bromley
Tiresome, yes; unusable, no. You could have arranged that all
signals going away from a process were driven on to wires with
a small inertial delay (but NOT #0 !!!!).
I'm not sure inertial delays were supported by Synopsys synthesis
at the time. I'm sure that neither the issue nor the technique were
mentioned in the synthesis manuals at the time.

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
From Python to silicon:
http://myhdl.jandecaluwe.com
Mike Treseler
2008-02-23 22:53:30 UTC
Permalink
Post by Jan Decaluwe
Post by Mike Treseler
"If an engineer is willing to limit all modules
to a single always block, blocking assignments can be used
to correctly model, simulate and synthesize the desired logic."
There was a time when Cliff was right on that point.
I know this because I designed a chip in that style, in 1990.
We had to, because non-blocking assignments were *not available*.
(I'm not sure this was from the language, or from Synopsys DC.)
Inside modules, you had races. But between modules,
there were no races. You had "signal-like" behavior.
(This was with Verilog-XL of course: there was nothing else!)
I have only worked with single block modules on
quartus, ise and modelsim, but I have yet to
produce an example of incorrect synthesis
or a simulation mismatch using '=' assignments
exclusively. I would be interested to hear
from someone who has. I find it hard to believe
that a vendor that supports mixed simulation
would "put the race back in" for verilog modules.

With my design template, port assignments
are a very small deal, so I will switch to
'<=' for these, and ignore the synthesis warnings.
Post by Jan Decaluwe
Some years later I found out that the above behavior had been
"relaxed" under the influence of competing "optimizing" simulators.
As a result, the *only* race-free coding style available in 1990
http://groups.google.com/groups/search?q=horrible+truth+about+verilog&qt_s=Search+Groups
Thanks for the history lesson.
Verilog has certainly lived in interesting times.
vhdl history is much more boring.

-- Mike Treseler
Jason Zheng
2008-02-24 03:48:02 UTC
Permalink
On Sat, 23 Feb 2008 14:53:30 -0800
Mike Treseler <***@comcast.net> wrote:

<snip>
Post by Mike Treseler
Post by Jan Decaluwe
Inside modules, you had races. But between modules,
there were no races. You had "signal-like" behavior.
(This was with Verilog-XL of course: there was nothing else!)
I have only worked with single block modules on
quartus, ise and modelsim, but I have yet to
produce an example of incorrect synthesis
or a simulation mismatch using '=' assignments
exclusively. I would be interested to hear
from someone who has. I find it hard to believe
that a vendor that supports mixed simulation
would "put the race back in" for verilog modules.
The recommendation to use non-blocking instead of block assign
statements is mainly because of principle and belief. Blocking
assignments immediately generate new update events to put back in the
active event queue in the current simulation time. Non-blocking
assignments generateds new update events in the INACTIVE event queue,
delaying any new update events until the current time has passed. The
non-blocking assignment functionally maps to a flip-flop.

You said you want an example where blocking assignments can fail, here's
an example:

always @ (posedge clk)
a <= din;

always @ (posedge clk)
b <= a;

Without a doubt, the above two blocks generates a pipelined design.

always @ (posedge clk)
a = din;

always @ (posedge clk)
b = a;

While these two blocks may also synthesize to a pipelined design, in
simulation, how ever, you might get something completely different,
depending on which always block is executed by the simulator first. If
the first one is executed first, then b and a are no longer in
pipeline, instead they would be equal at all times. If the second
always block is executed first, then b is one clock behind a. What's
even worse is if the order of execution is not static, though I haven't
seen an simulator that does that.

I'm not sure how mixed-mode simulators work with two different kinds of
event queues, but I can't imagine having a merged/unified event queue.
I'd imagine that race conditions are resolved within separate Verilog
and VHDL event queues, then reconciled at the end of every time tick?

Mike, I know you are a VHDL guy, and VHDL doesn't have confusing
concepts like blocking and non-blocking assignments, and that you are
probably very careful yourself to not get caught by it when using
Verilog. However, for all that are new to Verilog, I believe it is
important to iron this concept in their minds: USE NON-BLOCKING
ASSIGNMENTS FOR FLIPFLOPS!

~Jason Zheng
Jonathan Bromley
2008-02-24 10:10:27 UTC
Permalink
On Sat, 23 Feb 2008 19:48:02 -0800, Jason Zheng
Post by Jason Zheng
You said you want an example where blocking assignments
Here's an even better one, where there is CERTAIN to be
a sim/synth mismatch if you use blocking assignment:

always @(posedge clock or posedge reset)
if (reset)
Q0 = 0;
else
Q0 = Q1;

always @(posedge clock or posedge reset)
if (reset)
Q1 = 0;
else
Q1 = ~Q0;

Synthesis will build a 2-bit twisted ring counter.

Simulation is obliged to execute one of the always-blocks
before the other, and therefore one of the blocks must
of necessity use the updated rather than the old value
of its input.

Caveat scriptor...
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
***@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Mike Treseler
2008-02-24 14:26:59 UTC
Permalink
Jason Zheng wrote:
...
Post by Jason Zheng
a = din;
b = a;
While these two blocks may also synthesize to a pipelined design, in
simulation, how ever, you might get something completely different,
depending on which always block is executed by the simulator first.
Thanks. This makes perfect sense to me.

The case I actually use is
a local register in a single block module A
writing to the single block module B through a module port.
It is much harder to demonstrate a simulation race
in this case.

-- Mike Treseler
Jason Zheng
2008-02-24 15:45:16 UTC
Permalink
On Sun, 24 Feb 2008 06:26:59 -0800
Post by Mike Treseler
...
Post by Jason Zheng
a = din;
b = a;
While these two blocks may also synthesize to a pipelined design, in
simulation, how ever, you might get something completely different,
depending on which always block is executed by the simulator first.
Thanks. This makes perfect sense to me.
The case I actually use is
a local register in a single block module A
writing to the single block module B through a module port.
It is much harder to demonstrate a simulation race
in this case.
-- Mike Treseler
Use of local variables can cause troubles too if that local variable is
assigned within the always block as the flip-flop, and that local
variable is shared by other blocks. Here's an example from Stuart
Sutherland's website (sorry can't find perm. links):

module weird_logic
(input wire [7:0] a, b,
input wire clock,
output reg [7:0] q2
);
reg [7:0] q1;

always @(posedge clock) begin
if (mode) q1 = a + b
else q1 = a - b;
q2 <= q1 | (q2<< 2);
end
endmodule

If q1 is never used outside the always block, then it synthesizes to
combinational logic that feeds q2. However if q1 is ever used outside
that block, it would be turned into a flip-flop, and you end up with a
pipelined q1 and q2.

~Jason Zheng
--
Nirvana? That's the place where the powers that be and their friends
hang out. -- Zonker Harris
Jonathan Bromley
2008-02-24 16:17:50 UTC
Permalink
Post by Jason Zheng
Use of local variables can cause troubles too if that local variable is
assigned within the always block as the flip-flop, and that local
variable is shared by other blocks.
Was what I wrote so very unclear?

<quote>
[...]
replicate this VHDL coding style in Verilog
clocked processes by....
- making BLOCKING assignment to variables declared locally
within the clocked process, ensuring that those variables
are not referenced by any other process;
- making NONBLOCKING assignment to variables declared outside
the process, which therefore can be referenced/read in other
processes.
</quote>

and just in case you missed it...

...BLOCKING assignment to variables
***** declared locally within the clocked process *****

Because they're declared locally, it is very unlikely that
you could mistakenly reference them from another process;
and, indeed, impossible when you come to synthesis.

THIS IS NOT HARD. It's merely necessary to follow a few
simple rules to make up for the fact that Verilog's
concurrent programming model is absurdly ill-controlled.
There is no need to appeal to "principles and belief"
as you put it in an earlier post; it's safer to know
what you're doing. And there is no need to stay within
Cliff Cummings's strait-jacket of "NBA to all variables
in a clocked process".

For Verilog bigots, the use of mixed blocking and nonblocking
assignment I described is painfully close to admitting that
VHDL got it right all along, because it is effectively the
same model that VHDL uses: variables in a process, signals
to communicate between processes.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
***@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Jason Zheng
2008-02-24 16:57:29 UTC
Permalink
On Sun, 24 Feb 2008 16:17:50 +0000
Post by Jonathan Bromley
Post by Jason Zheng
Use of local variables can cause troubles too if that local variable
is assigned within the always block as the flip-flop, and that local
variable is shared by other blocks.
Was what I wrote so very unclear?
Sorry, I missed your original posting on this.
Post by Jonathan Bromley
and just in case you missed it...
...BLOCKING assignment to variables
***** declared locally within the clocked process *****
Because they're declared locally, it is very unlikely that
you could mistakenly reference them from another process;
and, indeed, impossible when you come to synthesis.
I thought this is not possible, at least in Verilog 1995 style.
Post by Jonathan Bromley
For Verilog bigots, the use of mixed blocking and nonblocking
assignment I described is painfully close to admitting that
VHDL got it right all along, because it is effectively the
same model that VHDL uses: variables in a process, signals
to communicate between processes.
I agree with you 100%. However, for the new-comers of Verilog, I have
to say Cliff's guidelines are much easier to follow.

~Jason Zheng
--
Nirvana? That's the place where the powers that be and their friends
hang out. -- Zonker Harris
Mike Treseler
2008-02-24 17:24:11 UTC
Permalink
Post by Jason Zheng
Post by Jonathan Bromley
Because they're declared locally, it is very unlikely that
you could mistakenly reference them from another process;
and, indeed, impossible when you come to synthesis.
I thought this is not possible, at least in Verilog 1995 style.
1995 and 2001 works for me.
Post by Jason Zheng
... However, for the new-comers of Verilog, I have
to say Cliff's guidelines are much easier to follow.
This thread is good evidence for that opinion.
Sorry to stir things up, but I am incurable synthesis wonk
and I find this stuff fascinating.

-- Mike Treseler

Mike Treseler
2008-02-24 17:17:37 UTC
Permalink
Jason Zheng wrote:
...
Post by Jason Zheng
If q1 is never used outside the always block, then it synthesizes to
combinational logic that feeds q2. However if q1 is ever used outside
that block, it would be turned into a flip-flop, and you end up with a
pipelined q1 and q2.
Thanks. I don't describe combinational logic, but that example
is close enough that I will concede the point and use '<=' on my port
assignments. However I will continue to use local '=' assignments
according to the the rules well described by Mr. Bromley elsewhere
in this thread to translate my single-process vhdl designs to verilog.

-- Mike Treseler
Jonathan Bromley
2008-02-24 10:03:49 UTC
Permalink
On Sat, 23 Feb 2008 14:53:30 -0800,
Post by Mike Treseler
I have yet to
produce an example of incorrect synthesis
or a simulation mismatch using '=' assignments
exclusively.
I don't think you will ever find incorrect *synthesis*.
Synthesis certainly treats each module independently,
and probably treats each process independently (at least
from the point of view of register inference). So even
with the blocking assignments to output ports, your
design would synthesise the way you want it.

Simulation is a trickier matter. For Jason's example
of a pipeline-that-might-not-be-a-pipeline

always @(posedge clock)
a = b;
always @(posedge clock)
b = c;

it is fairly easy to get most simulators to exhibit
either the intended (2-stage shifter) and unintended
(shoot-through on 'b') behaviour, simply by juggling
the lexical order of the two always-blocks. Ports,
though, are another matter. A Verilog unidirectional
port acts exactly like a continuous assignment:

assign wire_on_the_outside = instance.its_output_port;

and it's quite likely that simulators may batch-up all
always-blocks that are ready for execution, execute them,
and then execute any assigns that were triggered by
the always-blocks' outputs. This gives you Jan's "ports
are special" behaviour, and Mike's observation that he's
never seen this go wrong in practice.

Once again, though: there is NO guarantee that simulators
will behave in that manner. If two always-blocks are
readied for execution by the same clock edge, and the
block that happens to execute first then triggers a
continuous assign statement to execute, the simulator
is entirely within its rights to pre-empt the second
always-block (and, indeed, even the first one) and
go off and execute the continuous assignment. Any
attempt to rely on a particular ordering of these
executions is both erroneous and dangerous. Some
simulators perform extremely aggressive serialisation
optimisations to reduce the amount of costly process
switching they need to do, and the Verilog LRM
explicitly gives them the freedom to re-order the
execution of concurrently active code in any way
they choose.
Post by Mike Treseler
With my design template, port assignments
are a very small deal, so I will switch to
'<=' for these, and ignore the synthesis warnings.
I'm sure this is the properly paranoid way to proceed.
Post by Mike Treseler
Verilog has certainly lived in interesting times.
vhdl history is much more boring.
I'll take "boring" in preference to "perpetual fear
of losing my sanity" any day, thanks :-)
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
***@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Amr
2008-02-23 10:20:10 UTC
Permalink
Post by Jonathan Bromley
On Fri, 22 Feb 2008 13:14:36 -0800 (PST),
Post by Amr
I wrote the following counter module in Verilog as a learning
module pixel_counter(
input clock,
output reg [6:0] count,
output reg rollover);
begin
count=count+1;
if (count==0)
rollover=1;
else
rollover=0;
end
endmodule
Now, when I came to simulate it using Quartus II, I found that the
counter worked fine but there was some strange glitches occurring
I was wondering whether this glitch is caused by the Verilog code or
whether this is something inherent in the FPGA hardware (a Cyclone III
EP3C25F324 FPGA)? How can I fix it?
Let me answer this in two stages.
First, I'll answer your question. The simulation you're running
is, I suspect, simulating the FPGA logic that was derived from your
code. The counter has 7 flip-flops, of course. Each of these FFs
has a *different* propagation delay from the clock. So, on a clock
transition that increments the counter, some of the FFs will change
their value just a little before some others. That gives you a
"glitch". In fact, it's just the counter outputs settling; your
logic will use this counter output to do something on the NEXT
clock edge, by which time everything will be nicely settled.
This kind of glitch just happens with synchronous logic. If
you are truly desperate to avoid it you can design a Gray-code
counter, but that is almost certainly unnecessary.
Second, allow me to tell you why your code is crap. You have
made the fatal error of using BLOCKING Verilog assignment (=)
to the outputs of a clocked "always" block. When you write
you MUST arrange that the outputs of that block are given their
begin
count <= count+1;
if (count==7'b1111111)
rollover <= 1;
else
rollover <= 0;
end
Note, now, that I must test count==all-ones instead of count==0,
because the nonblocking assignment does NOT update its output
variable until after the following statements have executed.
Please don't try to argue with me about this. Just don't EVER
do what you did in the example code you posted. The reasoning
behind this is too lengthy to list here, but you can easily
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
As I've mentioned here on numerous occasions, there are
things Cliff says in this paper that I think are wrong,
but it remains truly excellent advice for beginners and
it's still the most thorough discussion of the problem
that you're likely to find.
Fixing this will not remove your simulation glitch,
but it will stop your design being broken.
--
Jonathan Bromley, Consultant
DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services
Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
Hello all,

Thanks very much for your replies and for confirming that the glitches
are nothing to worry about. Also, thanks for pointing out the usage of
the <= and = operators - I'll keep it in mind!

--Amr
Mike Treseler
2008-02-22 22:31:22 UTC
Permalink
Post by Amr
I was wondering whether this glitch is caused by the Verilog code or
whether this is something inherent in the FPGA hardware (a Cyclone III
EP3C25F324 FPGA)? How can I fix it?
It looks like a normal transition to me.
The bits can't change at exactly the same time.
Note that the value is stable at the rising clock edge.
That's all that matters.

-- Mike Treseler
Loading...