state machine reset

On Sun, 17 Aug 2008 01:07:51 -0700 (PDT), rickman <gnuarm@gmail.com>
wrote:

On Aug 17, 1:23 am, Mike Treseler <mtrese...@gmail.com> wrote:

The version below is still silly, but is readable.


process (Clk)
variable q1_v : std_ulogic;
variable q2_v : std_ulogic;
begin
if rising_edge(Clk) then
q1_v := A and B; -- right before left
q2_v := q1_v and C; -- means no regs here
end if;
Q1 <= q1_v; -- output register
Q2 <= q2_v; -- output register
end process;

This still is not clear to me. Why are the signal assignments outside
of the clocked if condition? But they are inside the clocked
process! To me, this is un-synthesizable as it is describing a
register clocked on both edges.
Mike's defense of it makes sense, but I still agree with you. It works
but on a casual read, obscures the meaning; this to my mind
overcomes any advantage of using variables over signals.

(It works because the variable assignments take place immediately; the
signal assignments follow them, and therefore happen in the SAME delta
cycle, not the next time the process wakes)

Confusing the reader is bad. However I think I also managed to confuse
Xilinx ISE 7.1 through 9.2 where this style is combined with expressions
involving both signals and variables. I need to simplify the case in
question until the evidence is clear (and see what ISE 10.1 does with
it) before I say more.

(On a vaguely related topic, namely confusing the reader; I managed to
pin down my unease with the conditional operator, a?b:c which we
discussed recently. I didn't learn it in Verilog, but in a weird
language that doesn't even have a boolean type, and requires 'a' to be
some species of integer. This makes me want the cases 0 and 1 to appear
in ascending order for some reason; I have to force myself to read them
in descending order. YMMV and probably does.)

In favour of variables is their local status, and their semantics
resembling conventional programming language assignment to variables.

Against them is (a) some uses can be confusing as above and (b) if you
use them for registers in a pipeline, you have to describe the pipeline
backwards.

So I normally use them for intermediate results, and (with apologies to
Mike T) use signals for my pipeline registers.

- Brian
 
Brian Drummond wrote:

Mike's defense of it makes sense, but I still agree with you. It works
but on a casual read, obscures the meaning; this to my mind
overcomes any advantage of using variables over signals.
Just to be clear, I wasn't attempting to defend that particular
example, just the concept of picking a process template
and sticking to it for synthesis of registers from variables.

Also, I failed to point out that the example becomes ...

process (Clk)
variable q1_v : std_ulogic;
variable q2_v : std_ulogic;
begin
if rising_edge(Clk) then
q1_v := A and B; -- left before left
q2_v := q1_v and C; -- means no regs here

Q1 <= q1_v; -- output register
Q2 <= q2_v; -- output register
end if;
end process;

.... if I use the second template instead of the first.
I agree that this template is easier to read
and less confusing.

In my designs, I use the template
to convert large single process entities to three
procedures. If the template itself is not touched
and no signals other than ports are referenced,
I can forget about it, and synthesis just works.

Confusing the reader is bad. However I think I also managed to confuse
Xilinx ISE 7.1 through 9.2 where this style is combined with expressions
involving both signals and variables. I need to simplify the case in
question until the evidence is clear (and see what ISE 10.1 does with
it) before I say more.
Single process entities based on my templates
work for ise 9.1 and quartus synthesis.

Referencing variables and signals
in the same process makes this method more trouble
than it is worth to me. This is why I banish signal
references in my single-process entities and use
structural port maps to wire things up.

In favour of variables is their local status, and their semantics
resembling conventional programming language assignment to variables.
This is the entire upside for me.
Certainly not worth the trouble otherwise.

Against them is (a) some uses can be confusing as above and (b) if you
use them for registers in a pipeline, you have to describe the pipeline
backwards.
This is true. Simulation and tracing code is critical.

So I normally use them for intermediate results, and (with apologies to
Mike T) use signals for my pipeline registers.
No apologies needed.
I am explaining my style, not judging others.
Style is up to the designer.

-- Mike Treseler
 
On Aug 14, 3:03 am, yii...@gmail.com wrote:
Hi all,

I'm new tovhdland trying to reset a state machine to state 0 when
the incoming signal x changes state. How can I combine the two
processes below and not resulting in multiple sources error?

process (clk, rst)
begin
if rst = '1' then
state <= s0;
elsif rising_edge (clk) then
state <= next_state;
end if;
end process;

process (x0, x1)
begin
state <= s0;
end process;

Thanks...
-------------------------------------------------------------------
hi this is marlinx
try out this code it may work... otherwise if u give full code i can
rectify that..

process(clk,rst)then

if(rst = '1')then

state <= s0;

elsif rising_edge(clk)then
state <= next_state;

end if;

end process;
process(state,x0,x1)

begin

case state is
when s0 =>
'reset counter outputs';

when s1 =>

if(x0'event and x0 = '1') then

state <= s0

else

next_state <= state + 1;

end if;

when s2 =>









when s0 =>
 
rickman schrieb:
On Aug 15, 2:45 pm, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
rickman schrieb:

On Aug 15, 8:34 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
Rickman,

of course for a counter describing a counter is most easy and readable
way. Describing a state machine as I did can serve as a template for
much bigger ones with some good benefits.

I'm still waiting for a description of those "good benefits". The
coding is identical other than eliminating the superfluous text. You
just type less of it...

I did that somewhere here in the threads. Write for readability and
testability and leave the rest for the compiler. They are good enough...

/Wolfgang
 
rickman schrieb:

I don't get why you think this is any easier than one process. I
think you have done this for a long time and are just used to it. I
have my own style of indentation and I am used to it. But I don't say
it is better than any other. I just like it that way.

I was talking about one clocked process for the complete state machine.
Sorry that you mis-interpreted my example. It is an extract of it...

Wolfgang
 
Andy schrieb:
On Aug 15, 1:41 pm, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
Well, the interesting thing is when you change a state for the next
transition. Allowing only one assignment to state and using next_state
for searching and looking over the text makes it more readable and
useable IMO.

state <= s8;
if state == s1 then
state <= s2;
elsif state = s2 then
state <= s3;
elsif state <= s3 then
state = s4;

or

next_state := s8;
if state == s1 then
next_state := s2;
elsif state = s2 then
next_state := s3;
elsif state = s3 then
next_state := s4;
.
.
state <= next_state;


If you enjoy the needless extra coding of a nested if-then-else tree
for a state machine, then I suppose all the extra references to state
would be a hindrance to readability.
It is somehow syntax sugar. You are right, case could be a little
better, but this was not my point.
But the solution to readability (and better/safer code too) is to use
the case statement for state machines. Then all but the original
reference to state are assignments to it, the same as all but the
final reference to next_state are assignments to it in your example.

I quit using variable/signal pairs for 'd' and 'q' years ago, and
have never wanted them back.
Sure, intermediate variables are usually not needed for signal
assignments unless you want compute a derived signal.

Best regards

Wolfgang
 
On Aug 18, 9:10 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com>
wrote:
rickman schrieb:

On Aug 15, 2:45 pm, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
rickman schrieb:

On Aug 15, 8:34 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
Rickman,

of course for a counter describing a counter is most easy and readable
way. Describing a state machine as I did can serve as a template for
much bigger ones with some good benefits.

I'm still waiting for a description of those "good benefits". The
coding is identical other than eliminating the superfluous text. You
just type less of it...

I did that somewhere here in the threads. Write for readability and
testability and leave the rest for the compiler. They are good enough...
Yes, and I replied to those comments. I have not seen any
*substantiated* reasons for separating the sequential and
combinatorial portions of a FSM. Just stating that it is better
because it is better is not justification.

Rick
 
rickman schrieb:
On Aug 18, 9:10 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
rickman schrieb:

On Aug 15, 2:45 pm, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
rickman schrieb:
On Aug 15, 8:34 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
Rickman,
of course for a counter describing a counter is most easy and readable
way. Describing a state machine as I did can serve as a template for
much bigger ones with some good benefits.
I'm still waiting for a description of those "good benefits". The
coding is identical other than eliminating the superfluous text. You
just type less of it...
I did that somewhere here in the threads. Write for readability and
testability and leave the rest for the compiler. They are good enough...

Yes, and I replied to those comments. I have not seen any
*substantiated* reasons for separating the sequential and
combinatorial portions of a FSM. Just stating that it is better
because it is better is not justification.
I don't do, either. If I said so - sorry for the misunderstanding.
I use only one process for one state machine ;)

Best regards

Wolfgang
 
On 18 Aug, 15:11, rickman <gnu...@gmail.com> wrote:
On Aug 18, 9:10 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:





rickman schrieb:

On Aug 15, 2:45 pm, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
rickman schrieb:

On Aug 15, 8:34 am, Wolfgang Grafen <wolfgang.gra...@ericsson.com
wrote:
Rickman,

of course for a counter describing a counter is most easy and readable
way. Describing a state machine as I did can serve as a template for
much bigger ones with some good benefits.

I'm still waiting for a description of those "good benefits".  The
coding is identical other than eliminating the superfluous text.  You
just type less of it...

I did that somewhere here in the threads. Write for readability and
testability and leave the rest for the compiler. They are good enough....

Yes, and I replied to those comments.  I have not seen any
*substantiated* reasons for separating the sequential and
combinatorial portions of a FSM.  Just stating that it is better
because it is better is not justification.

Rick- Hide quoted text -

- Show quoted text -
It's a power saving hint

example

process(ir)
begin
blah blah;
end process;

Now if ir is sequentially assigned, then the write enable of the
signal ir can also be the write enable of the created 'registered
signal copies' of all the inputs to the process not in the sensitivity
list. This makes lower power consumption, as the register effect holds
the logic values still when they could be going all over the shop, but
not needed.

cheers
jacko

p.s. yes I know this interpretation makes my nibz code flawed, as
registering what is assigned to the signal post is not a good idea, as
often it is not valid at the time, and is just a routing. din would be
an example of this (but it is not syncronously assigned), but c is an
example of something which would be valid and is synchronously
assigned, but being registered anyhow (re-registration would have no
major effect appart from duplication of registers). Simulation behaves
as though such registration is used. Well maybe I do a final edit
today.
 
On Mon, 18 Aug 2008 11:29:03 -0700 (PDT), Andy wrote:

"the proper synthesis template" ???

Templates are useful in describing a typical mapping of code structure
to gates and registers, but should not be used as exclusive examples
of good code/design.
I don't dispute that. A little context: my day job is to train
people in the use of VHDL (and Verilog, and SystemVerilog, and...)
with complete vendor neutrality. So it is very important to me
to know what the "lowest common denominator" is for synthesis
support; I want to find the boundaries of industry-wide support,
and explore how to do interesting stuff within those boundaries.
"Proper synthesis template" is my lazy shorthand for "what I
can confidently encourage people to use, secure in the knowledge
that it is supported by tools today and (probably) into the future".
The results I posted recently ("Mixed clocked/combinational coding
style") will probably change my established position on precisely
what does and doesn't work across tools.

If users (and tools, some of which already have) quit focusing on code
templates, and start understanding (and implementing) clock-cycle
behavior, then there will be less confusion.
That's fair, but users (especially beginners) need reliable guidance
that will continue to be useful to them as their technique matures;
a set of coding templates is not a bad place to start for that.

It also leaves more room
for optimization. For example, if register retiming optimizations are
used, the structure of registers and logic will change from what was
literally described anyway.
Of course there is a spectrum from RTL to true behavioural synthesis,
and most real synthesis tools today are some way along it. But I
still need to be confident that the wrapper in which I enclose my
behavioural description - the process template - is sure to describe
something synthesisable.

Only when the structure of the
implementation is functionally important (e.g. in synchronization
boundaries) should we focus on structurally clear coding styles, along
with disabling such optimizations.

Take the following example:

signal s1, s2...
...
process (clk) is
variable v1...
begin
if rising_edge(clk) then
v1 := f1(v1, s2);
end if;
s1 <= f2(v1);
end process;

In the example above, s1 is the combinatorial output of the f2
function of a registered v1, or

s1 = f2(registered(v1));

If the assignment to s1 is moved inside the clocked if clause, then s1
becomes the registered f2 of the combinatorial versions of v1.

s1 = registered(f2(v1));

In either case, without an asynchronous reset, the cycle based
behavior is the same, but the implementation is slightly different. I
have even seen Synplify optimize two signals assigned to the same
function, one inside and the other outside the clocked clause,
optimized into the same register and function, which is still
functionally (on a clock cycle basis) correct.
Fully agreed. In your hands (and, I suspect, mine) that's
fine. However, a less experienced user might be tempted
to write

process (clk) is
variable v1...
begin
if rising_edge(clk) then
v1 := f1(v1, s2);
end if;
s1 <= f2(v1, s2); -- attempt at Mealy logic
end process;

Now we have very curious sampling of s2. Our lovely cycle-
based Moore-machine description has, by a small and (to a
beginner) innocent change, curdled into something very
nasty indeed.

As Mike T aptly pointed out, asynchronous reset creates a meaningful
difference between the two styles (if s1 is assigned inside the
clocked clause, it must also be reset in the reset clause, whereas if
it is after the clocked clause, it need not be included in the reset
clause.)
Yes. Indeed, that opens the lid on a rather large can of worms:
dealing with reset in behavioural descriptions can be quite
troublesome.

Thanks for the interesting discussion. I think we're in
"violent agreement", but perhaps I wasn't as clear as I
might have been.

Re-reading your post and this response to it, I wonder
if there's another angle worth considering: What one might
regard as "classical RTL", with its restricted set of
process templates, has the interesting property that it
not only gives an unambiguous cycle-by-cycle description
of behaviour, but it also can be directly interpreted -
both by tools and by users - as a structural description.
The kind of thing you are describing has a much less obvious
relationship to structure (the relationship is there, of course,
or else synthesis wouldn't work) and it is unhelpful for users
to try to write such code if they are starting from a structural
picture of the desired hardware in their heads. To use it well,
you must be prepared to reason about the cycle-by-cycle
behaviour, without giving much thought to the structure.
For many users that goes against the grain - and, indeed,
it's easy to find design examples where it may be unhelpful.

All of which gives me, as a trainer, quite a lot to chew on :)
--
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
jonathan.bromley@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.
 
On Aug 17, 3:19 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:
I am aware that synthesis tools have not always done
the necessary register merging in this situation,
and I suspect that putting the final signal assignments
outside the if statement is effectively a hack to give
the synthesis tool an appropriate hint. But it means
that Q1 and Q2 no longer follow the proper synthesis
template.
"the proper synthesis template" ???

Templates are useful in describing a typical mapping of code structure
to gates and registers, but should not be used as exclusive examples
of good code/design.

If users (and tools, some of which already have) quit focusing on code
templates, and start understanding (and implementing) clock-cycle
behavior, then there will be less confusion. It also leaves more room
for optimization. For example, if register retiming optimizations are
used, the structure of registers and logic will change from what was
literally described anyway. Only when the structure of the
implementation is functionally important (e.g. in synchronization
boundaries) should we focus on structurally clear coding styles, along
with disabling such optimizations.

Take the following example:

signal s1, s2...
....
process (clk) is
variable v1...
begin
if rising_edge(clk) then
v1 := f1(v1, s2);
end if;
s1 <= f2(v1);
end process;

In the example above, s1 is the combinatorial output of the f2
function of a registered v1, or

s1 = f2(registered(v1));

If the assignment to s1 is moved inside the clocked if clause, then s1
becomes the registered f2 of the combinatorial versions of v1.

s1 = registered(f2(v1));

In either case, without an asynchronous reset, the cycle based
behavior is the same, but the implementation is slightly different. I
have even seen Synplify optimize two signals assigned to the same
function, one inside and the other outside the clocked clause,
optimized into the same register and function, which is still
functionally (on a clock cycle basis) correct.

As Mike T aptly pointed out, asynchronous reset creates a meaningful
difference between the two styles (if s1 is assigned inside the
clocked clause, it must also be reset in the reset clause, whereas if
it is after the clocked clause, it need not be included in the reset
clause.)

Naturally, if you need a combinatorial output from registered logic,
this example is the only way to do it in the same process with the
clocked logic, avoiding the need for "public" signals for the
registers. Jonathan B's use of this style for state machine outputs is
another unique and useful application.

Andy
 
On Aug 18, 2:29 pm, Andy <jonesa...@comcast.net> wrote:
On Aug 17, 3:19 am, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com
wrote:

I am aware that synthesis tools have not always done
the necessary register merging in this situation,
and I suspect that putting the final signal assignments
outside the if statement is effectively a hack to give
the synthesis tool an appropriate hint. But it means
that Q1 and Q2 no longer follow the proper synthesis
template.

"the proper synthesis template" ???

Templates are useful in describing a typical mapping of code structure
to gates and registers, but should not be used as exclusive examples
of good code/design.

If users (and tools, some of which already have) quit focusing on code
templates, and start understanding (and implementing) clock-cycle
behavior, then there will be less confusion. It also leaves more room
for optimization. For example, if register retiming optimizations are
used, the structure of registers and logic will change from what was
literally described anyway. Only when the structure of the
implementation is functionally important (e.g. in synchronization
boundaries) should we focus on structurally clear coding styles, along
with disabling such optimizations.
I can't say I completely agree with that, especially in the context of
your example below. HDL says Hardware Description Language. So I
describe the hardware when I code an HDL. I am not writing
programs.


Take the following example:

signal s1, s2...
...
process (clk) is
variable v1...
begin
if rising_edge(clk) then
v1 := f1(v1, s2);
end if;
s1 <= f2(v1);
end process;

In the example above, s1 is the combinatorial output of the f2
function of a registered v1, or

s1 = f2(registered(v1));

If the assignment to s1 is moved inside the clocked if clause, then s1
becomes the registered f2 of the combinatorial versions of v1.

s1 = registered(f2(v1));
Sorry, but these are not the same. If the tools are allowed to do
that it can break designs.

Your example should have been...

s1 = registered(f2(f1(v1,s2));

If s2 is an input that is asynchronous to the clock, you now have a
race condition that can result in inconsistent states between s1 and
v1.


In either case, without an asynchronous reset, the cycle based
behavior is the same, but the implementation is slightly different. I
have even seen Synplify optimize two signals assigned to the same
function, one inside and the other outside the clocked clause,
optimized into the same register and function, which is still
functionally (on a clock cycle basis) correct.
Given my objection above, I suspect that they are doing something to
recognize when it is ok to do this and when it is not ok.

As Mike T aptly pointed out, asynchronous reset creates a meaningful
difference between the two styles (if s1 is assigned inside the
clocked clause, it must also be reset in the reset clause, whereas if
it is after the clocked clause, it need not be included in the reset
clause.)

Naturally, if you need a combinatorial output from registered logic,
this example is the only way to do it in the same process with the
clocked logic, avoiding the need for "public" signals for the
registers. Jonathan B's use of this style for state machine outputs is
another unique and useful application.

Andy
 
On Aug 18, 4:10 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:

So it is very important to me
to know what the "lowest common denominator" is for synthesis
support; I want to find the boundaries of industry-wide support,
and explore how to do interesting stuff within those boundaries.
This lowest common denominator as a function of tools and vendors will
always then be a moving target, defined not by well-understood
standards but by experience and time. That's not necessarily a bad
thing, but those standards need to be understood as a dynamic,
evolving goal, and not taken as absolute immortal truth. While I
understand your need and motivation as a consultant for discovering
these basic limits, the same drive can be (and sadly, usually is)
perverted by less knowledgeable users in industry. Hence the evolution
of the coding style "folklore", or "cargo-cult coding". I have a
mental image of medieval peasants in a dark cave, huddled around the
smoky fire, telling ghost stories: "Avert thine eyes from the lure of
variables, my son, for they shall leadest thou into the fires of
damnation...".

Whereas Andy had written:
If users (and tools, some of which already have) quit focusing on code
templates, and start understanding (and implementing) clock-cycle
behavior, then there will be less confusion.
I agree in principle, and this is in exactly what you need to do to be
able to *read* code - see it execute in your head, rather than try to
map it to "style 1" or "style 2", because you only understand what
style 1 or style 2 do. This is definitely what the *users* need to
learn to do.

But in defense of the synthesis templates, the problem of writing a
synthesis tool that understands _everything_ is obviously a pretty
difficult task. That's what something like IEEE-1076.6 (guidelines for
RTL synthesis) is supposed to help with - give you the lowest common
denominator in a nutshell. However, it's fundamentally impossible to
constrain a user, especially a novice user, to write code that stays
within the strict subset of the guidelines. This gets more and more
difficult as code gets more complex, if-statements and their matching
ends span more and more lines, and and many fumbling fingers get
involved in its development. So, to borrow a comment I've heard about
the C language, VHDL still gives you enough rope to hang yourself. The
problem is to teach you not to actually do it.

- Kenn
 

Welcome to EDABoard.com

Sponsor

Back
Top