Synthesizable FSM

Jason Zheng wrote:

But I'm not sure what the RTL behavior is to start with. Aside from
mixing the blocking and non-blocking assignments, I thought anything
assigned in clock-triggered always blocks are automatically sequential.
Show me a page in Verilog language manual that says blocking assignments
in sequential blocks gives you combinational logic?
There has to be combinatorial logic for intermediate results generated
by the various blocking assignments to the same reg. You could view
the situation such that the assignments to comb_v are combinatorial to
temporary variables and comb_v as seen in a simulator's VCD file
updates in zero time on the upclock of clk. In real life, there are
setup/hold constraints so comb_v (or some prelatched copy) needs to be
ready before the upclock, otherwise q2's d pin wouldn't be happy.

For kicks I just ran that verilog of Mike's through a synthesizer for a
cycle simulator I wrote many years ago. In order to preserve the
rising edge semantics of that block, comb_v is the output of a dflop
that is equivalent to q2 (but both are fed by the same combinatorial
temporary variable). Nothing uses comb_v's value from the upclock, so
setting the synthesizer up to strip out unused latches generates pretty
much exactly the same circuit in Mike's PDF file with the exception
that comb_v vaporizes and in its place is a temp variable.

Nice example, Mike. If you also make comb_v an output, does your
synthesizer simply wire it to q2 in order to save the extra latch? It
doesn't seem like it can legally remain combinatorial when you qualify
it with @(posedge clk) if you use it outside of that block.

-t
 
bybell@rocketmail.com wrote:

For kicks I just ran that verilog of Mike's through a synthesizer for a
cycle simulator I wrote many years ago. In order to preserve the
rising edge semantics of that block, comb_v is the output of a dflop
that is equivalent to q2 (but both are fed by the same combinatorial
temporary variable). Nothing uses comb_v's value from the upclock, so
setting the synthesizer up to strip out unused latches generates pretty
much exactly the same circuit in Mike's PDF file with the exception
that comb_v vaporizes and in its place is a temp variable.
Yes. The Quartus HDL viewer is very kind to keep the label
and number the gates that result from each blocking (local variable)
assignment, comb_v-0 and comb_v-1.

Nice example, Mike.
Thanks for trying it out.

If you also make comb_v an output, does your
synthesizer simply wire it to q2 in order to save the extra latch?
I can only do local (blocking) assignments on comb_v.

It doesn't seem like it can legally remain combinatorial when
you qualify it with @(posedge clk) if you use it
outside of that block.
Exactly. That's Renaud Pacalet's golden rule of verilog synthesis:

"Use blocking on local variables
and nonblocking on global variables."

Nothing to it.

-- Mike Treseler
 
Jason Zheng wrote:
Interesting points, Jan.

Jan Decaluwe wrote:

Jason Zheng wrote:

I've never seen coding style like this before. Are you sure that comb_v
will be combinational?



Wrong question. The correct one is: What should a synthesis tool do to
match the RTL behavior?


But I'm not sure what the RTL behavior is to start with.
You'll have to fix that with learning how Verilog, not synthesis, works.
First things first.

Aside from
mixing the blocking and non-blocking assignments, I thought anything
assigned in clock-triggered always blocks are automatically sequential.
In that case, Verilog would not work as it does (as you can learn
from the language manual).

Show me a page in Verilog language manual that says blocking assignments
in sequential blocks gives you combinational logic?
I cannot. Fortunately, because it's not (generally) true :)

I insist. The right question is: what should a synthesis tool do to
match the RTL behavior?

Let me refer to a reg assigned with blocking assigns as a "variable".
A variable may be implemented as combinatorial logic. Or as a
flip-flop, if it may be read before it is assigned. (Historical
note: this was first supported in Synopsys synthesis around 1990).
Or - this will confuse you - as *both* at the same time.

The simple truth is that there is no one-to-one mapping between a
variable and an implementation. It all depends on how a variable
is used in the code.

How you react to this observation depends our your mindset.
Let me distinguish between the "think hardware" and the "think code"
mindset.

The reaction of someone with a "think hardware" mindset will be
one of rejection. As it is not immediately clear how the corresponding
hardware will look like, he will (incorrectly) conclude that a
synthesis tool will be confused or inefficient also. He may then
try to rationalize this conclusion by inventing or following rules that
avoid the possibility altogether.

To reaction of someone with a "think code" mindset will be the
opposite. (In my case, it was actually an aha-erlebnis - 1990).
He will see the opportunity to solve more problems with
clear and elegant code, leaving more implementation details to
the tool.

At least by now you should know that you had a choice :)

Regards,

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
Electronic design with Python:
http://myhdl.jandecaluwe.com
 
Mike Treseler wrote:
output q1, q2;
input clk, a, b, c;
reg comb_v; // combinational node
reg q1, q2; // registered outputs
always @(posedge clk) begin
I really ought to declare reg comb_v
local to the block like this:

// http://home.comcast.net/~mike_treseler/single_block.pdf
module single_block
(clk, a, b, c, q1, q2);
output q1, q2;
input clk, a, b, c;
reg q1, q2; // module declaration
always @(posedge clk)
begin: local
reg comb_v; // local declaration
comb_v = a & b;
q1 <= comb_v & c;
if (c) comb_v = ~comb_v;
q2 <= comb_v;
end // local
endmodule
//

This synthesizes the same, but makes
the design intention a little clearer.
It might be important if
there were more than one block.

-- Mike Treseler
 
Jason Zheng wrote:
Mike Treseler wrote:
Jason Zheng wrote:

My combined block would be a synchronous one
where outA and outB would become internal
combinational "regs" (local variables)
driving all of the registered module outputs
(not shown in your example) that need to use
these nodes. This might be a big block.

-- Mike Treseler


Mike,
Care to show an example? I'm a little confused here.


// http://home.comcast.net/~mike_treseler/single_process.pdf
module single_block
(clk, a, b, c, q1, q2);
output q1, q2;
input clk, a, b, c;
reg comb_v; // combinational node
reg q1, q2; // registered outputs
always @(posedge clk) begin
comb_v = a & b;
q1 <= comb_v & c;
if (c) comb_v = ~comb_v;
q2 <= comb_v;
end
endmodule
Mike,

I've never seen coding style like this before. Are you sure that comb_v
will be combinational? It also seems that you went against many people's
advice of NOT combining blocking and non-blocking statements in one
always block.
Mike's example is very much worth understanding.

One way to look at it is as follows: comb_v is shorthand (a macro,
somewhat, if you will), so everywhere you see comb_v on the
right-hand-side of an assignment in that block, you can substitute a &
b.

This notation is useful when you have a large equation forming the D
inputs to some flops and you'd like to break it up for readability.

This works only if the assignment to comb_v is blocking. This forces
the simulation tool to do the assignments to comb_v immediately (and
sequentially); the non-blocking assignments to q1 and q2 occur only
after everything on the right-hand side is evaluated.

-a
 
On Mon, 10 Oct 2005 11:08:30 -0700, Mike Treseler
<mike_treseler@comcast.net> wrote:

I really ought to declare reg comb_v
local to the block like this:

// http://home.comcast.net/~mike_treseler/single_block.pdf
module single_block
(clk, a, b, c, q1, q2);
output q1, q2;
input clk, a, b, c;
reg q1, q2; // module declaration
always @(posedge clk)
begin: local
reg comb_v; // local declaration
comb_v = a & b;
q1 <= comb_v & c;
if (c) comb_v = ~comb_v;
q2 <= comb_v;
end // local
endmodule
//

This synthesizes the same, but makes
the design intention a little clearer.
It might be important if
there were more than one block.
I agree 100%.

However, advocates of this kind of coding style in Verilog
need to be aware of the cultural obstacles they face:

1) The last time I looked, at least one lame-brained
synthesis tool rejected any synchronous block
that contained a mixture of blocking and nonblocking
assignments.
2) Some well-known Verilog gurus explicitly demand
that clocked always blocks contain only nonblocking
assignments, on the grounds that it's easier to
understand what you're doing that way and it reduces
the risk that you will make a silly error and create
races that give rise to sim/synth mismatch.
3) The popular OpenMore coding guidelines similarly
forbid any mixture of blocking and nonblocking
assignments in a single block.

All three are just simply wrong, but they are widely
accepted and respected.

VHDL doesn't suffer this problem because of its clear
and robust distinction between signals and variables.
Mike's local declaration of a reg that's updated
using only blokcing assignment is exactly analogous
to a VHDL variable, although it lacks the latter's
strict guarantee of invisibility outside the block
(Verilog variables in a named block can be referenced
from outside the block using an hierarchical name).
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail:jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Jonathan Bromley wrote:

However, advocates of this kind of coding style in Verilog
need to be aware of the cultural obstacles they face . . .
Thanks for the confirmation and the warning.
My intention was to answer Jason's question
and I hope I didn't get him into much trouble.

I am quite used to noting and politely ignoring
the popular consensus. The single block/process
synthesis style I use (but do not advocate)
gets similar reactions on the vhdl side.
What intrigues me here is the possibility
of a rather straightforward translation of
my vhdl stuff into verilog.

(Verilog variables in a named block can be referenced
from outside the block using an hierarchical name).
Yikes! Thanks for the tip.

Back to the salt mines . . .

-- Mike Treseler
 
On Tue, 11 Oct 2005 07:42:39 -0700, "Mike Treseler"
<mike_treseler@comcast.net> wrote:

My intention was to answer Jason's question
and I hope I didn't get him into much trouble.
At my age, you stop worrying about that ;-D

I am quite used to noting and politely ignoring
the popular consensus. The single block/process
synthesis style I use (but do not advocate)
gets similar reactions on the vhdl side.
Yes.

What intrigues me here is the possibility
of a rather straightforward translation of
my vhdl stuff into verilog.
Yup; almost mechanical, for synthesisable VHDL.
VHDL variable -> Verilog local reg assigned by =.
Indeed, the smart guys at Syosil in Denmark have
a fully-automatic translator from synthesisable VHDL
to synthesisable SystemVerilog; stretching to System
Verilog gives them multi-dimensional arrays, records
and enumerations and therefore covers the full
synthesisable VHDL subset.

(Verilog variables in a named block can be referenced
from outside the block using an hierarchical name).

Yikes! Thanks for the tip.
Don't worry - synth tools won't accept the hierarchical
names, so the variable-hiding is robust for synthesis.

Back to the salt mines . . .
Quite so.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail:jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Mike Treseler wrote:
Jonathan Bromley wrote:

However, advocates of this kind of coding style in Verilog
need to be aware of the cultural obstacles they face . . .


Thanks for the confirmation and the warning.
My intention was to answer Jason's question
and I hope I didn't get him into much trouble.
Who should he fear? The thought police?

I am quite used to noting and politely ignoring
the popular consensus. The single block/process
synthesis style I use (but do not advocate)
gets similar reactions on the vhdl side.
I don't get it. You hardly miss an opportunity to suggest
using your coding style, backed up with very reasonable arguments.

If that's not advocating, what is it? And if it's not advocating
then what's the point? Why waste valuable time - yours in the first
place - if you don't care to make a difference?

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
Electronic design with Python:
http://myhdl.jandecaluwe.com
 
Jan Decaluwe wrote:

Who should he fear? The thought police?
Sorry. Sarcasm was intended.
I will brush up on my emoticons.

I don't get it. You hardly miss an opportunity to suggest
using your coding style, backed up with very reasonable arguments.
I do present my side of the story to those who
ask a related question. However, I see no
point in arguing about questions of style.

Why waste valuable time - yours in the first
place - if you don't care to make a difference?
I do it because I enjoy it and learn from it.
If I have changed someone's coding style
I am flattered, but it's really the new
ideas I hear in passing that keeps me on line.

-- Mike Treseler
 
At my client's site any combination of blocking and non-blocking
assignments in either a combinational or sequential blocks gets
rejected no matter how much designers or contractors argue AND all code
gets eventually code checked...

RAUL
 
raul wrote:
At my client's site any combination of blocking and non-blocking
assignments in either a combinational or sequential blocks gets
rejected no matter how much designers or contractors argue AND all code
gets eventually code checked...
That is indeed unfortunate, but it
does not change the fact that the
design style I outlined works fine
for simulation and synthesis as long as
blocking assignments are only
applied to regs declared in the block.

I expect that your client already
has design rules more complicated
than that.

-- Mike Treseler
 

Welcome to EDABoard.com

Sponsor

Back
Top