state machine reset

R

rickman

Yes moore macines are prefered,http://nibz.googlecode.comis a mealy
machine at present, but the signal which makes it so would be driven
by synchronous logic in a full design, making it finalize as a moore
machine.

I know you mean well, but making your inputs registered, does not
change a FSM from Mealy to Moore, unless of course you are considering
the entire design to be a single Moore FSM.

The difference in the two FSMs is that the Mealy model defines the
outputs in terms of both the inputs and the state (or you can say the
transitions) while the Moore model defines the outputs in terms of
just the state.

The only thing that registering your inputs buys you is avoidance of
metastability issues in the FSM.
 
W

Wolfgang Grafen

KJ said:
Exactly as it should be, the clock causes state transitions, flip
flops to update, etc.


You only have difficulty if you compute other signals based on
'next_state', rather than 'state'. Personally I haven't had any
difficulty debugging without the 'next_state' signal.

Typically other signals/variable that are a function of the state
machine's state I compute based on the current state (i.e. the signal
'state' in this example) not on what the next state is going to be.
Typically this leads to higher clock cycle performance of the design
since the combinatorial logic that is needed to compute 'next_state'
does not roll into the logic needed to compute the output (or other
signal).
next_state will not generate logic, though :)
Readability would not necessarily be a function of whether there was
an explicit 'next_state' signal/variable or not. Either form can be
just as readable. For those cases, where duplication of code would
have to take place, I would have a variable 'next_state' for assigning
to those signals that would benefit from it. That's why I said "Most
times the only time..." 'most times' does not mean 'all times', it
means 'usually the case'.
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;
I modify state in the state machine. There is no need to have an
intermediate signal/variable to compute the 'next_state', just so that
it can be synchronously assigned to a signal called 'state'. There is
one clocked process of the following general form:

process(clk)
begin
if rising_edge(clk) then
if (reset = '1') then
current_state <= idle;
else
case current_state is
when idle => current_state <= Michigan;
when Michigan => current_state <= California;
when California => current_state <= Hawaii;
end case;
end if;
end if;
end process;
This is a super simple state machine. Read over state machines filling
several pages, and lots of calculations within every state...
Just as easy looking for 'current_state'.


Actually you'll likely have more trouble explaining the state machine
then the counter. For example, let's say this design is for some form
of memory controller. Let's say that after issuing a read command to
the memory device you need to wait 40 ns for the data to be valid,
let's also assume that the clock period is 10 ns. One might be
tempted to make a state machine that has the proper number of states
so that 4 clock cycles after the read command is issued that data gets
sampled. Your design will be very fragile (in my opinion) because of
the implicit constants (i.e. the number of states) that are really a
function of the following parameters:
- Clock period
- Memory access time
Using a counter approach, one would have constants (actually I'd use
generic inputs on the entity) for both of these and they would be
defined in units of time and I'd define the upper end of the counter
to be the ceil() of the ratio of memory access time divided by clock
period. So it would be painfully clear where the design error is that
needs fixing when I find that the board was built with 60ns access
time parts instead of 40ns, the 'fix' would be to simply change the
generic parameter input to the entiy from 40ns to 60ns and rebuild.
With the state machine approach you'd have to modify a bunch more than
that and have a much higher risk of getting it wrong the first time.

Linking parameters that you have no control over in your design (in
this case the memory access time) so that they properly parameterize
the design will naturally lead to using counters. Hard coding in a
calculated number of states that depends on this uncontrolled
parameter (or pulse time requirement) in the form of states in a state
machine is a mistake. Although both designs will work, one will be
much more fragile and less likely to be able to be modified correctly
in the future...but that's just my 2 cents.
It depends on the problem. Where a counter is more readable use a
counter, otherwise use a state machine ...
And my method has worked just as perfectly.


You're the one who brought up lazy, not me.
I am lazy I know :)

Best regards

Wolfgang
 
W

Wolfgang Grafen

rickman said:
On Aug 15, 8:34 am, Wolfgang Grafen <[email protected]>
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.

Best regards

Wolfgang
 
M

Mike Treseler

jacko said:
Yes moore macines are prefered, http://nibz.googlecode.com is a mealy
machine at present, but the signal which makes it so would be driven
by synchronous logic in a full design, making it finalize as a moore
machine.

I didn't say that, Svenn did.
I use a clocked process model and input synchronization.
This eliminates the "advantages" of either of these models.

Well said.
I agree with this guy ;)


-- Mike Treseler

Thread recursion is getting out of hand.
Time to exit...
 
J

jacko

Yes a nice product of all enumerations, reduce by all inaccessable
enummrative combinations.
one hot via decode or register all. Bingo!

cheers
jacko

p.s. I say use an enumeration where possible (i.e. when bit vector
value can be any differing one).
 
A

Andy

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.

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.

Andy
 
R

rickman

There are reasons to compute other signals based on next_state. For
example this is how a Moore FSM can change the output without waiting
for decoding of the current state and without glitches. The clock may
run slower, perhaps, but the output can be obtained faster.

However, it is not common for speed to be the real issue in designing
a FSM. Typically readability and maintainability is often the primary
goal of FSM design. This is facilitated by other factors having to do
with coding to match your application typically.

next_state will not generate logic, though :)

I have no idea what that means. If it doesn't produce logic, then you
can omit it, no?

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.

That is the point. There is nothing inherently more readable about
the separated processes. I think you are just used to that. On the
other hand, the combined process has less clutter and is more concise
describing a register and the logic driving it. You don't separate
the logic for a counter from the counter register do you? I see this
as the same.
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;

You have omitted the duplicated overhead of the two processes
including the need for maintaining an accurate sensitivity list. If
you over simplify the example then all coding becomes the same.

This is a super simple state machine. Read over state machines filling
several pages, and lots of calculations within every state...

Yes, and those calculations are no different if done in one process or
two. Look at the changes needed to combine processes. It is truly a
simple job and eliminates the need for duplicating the process
overhead and maintaining a sensitivity list.

It depends on the problem. Where a counter is more readable use a
counter, otherwise use a state machine ...




I am lazy I know :)

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.

Rick
 
R

rickman

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...

Rick
 
J

jacko

Yes a nice product of all enumerations, reduce by all inaccessable
enummrative combinations.
one hot via decode or register all. Bingo!

cheers
jacko

p.s. I say use an enumeration where possible (i.e. when bit vector
value can be any differing one).

And ask programmer to supply all virtual inaccessable state reductions
to valid states in radio-hardened designs.

cheers
jacko
 
K

kennheinrich

For what it's worth, I'm with Mike and company about using a single
process for state machines. In my experience, if a state machine is
so complex that you can't maintain, change, or debug it (and you think
you want to debug it using a separate next_state variable), you have a
very basic problem: that your state machine is too complex. In that
case, you need to look at factoring the state machine into interacting
sub-machines, or taking a step back and rethinking how your design
works, or do something else creative. In some cases, the machine
really *is* a beast from hell, and you might want to generate the
state machine transitions from another higher level of synthesis (a C
program or a script, assuming you know how) where you can abstract and
express the design intent more clearly, or even use one of those
dreaded fancy GUI tools (shudder...). Or whatever gets you to a
simpler, more understandable, easier to maintain design.

Now indulge me while I rant a little bit about the two process vs one
process approaches.

It makes a lot of sense to me, that the two-process machine is a
throwback to a slavish adherence to the Moore/Mealy behaviour
dichotomy that came out of 1950's era mathematics. And I think it was
done wrong, way back in the 1980's, at the beginning of VHDL tutorials
and examples. However, I can see how separating the next state and
output computation from the clocking process makes sense, but *not* in
the naive two-process "digital design 101" style.

Consider a machine with inputs Xin and current state Q, which computes
outputs Yout and next state Q'. In a Moore machine, Yout is a
function of Q, while in a Mealy, it's a function of Q and Xin.

The textbook two-process Moore approach looks like this (taking some
liberties with VHDL syntax)

-- two-process approach
process1 (clk)
Q <= Q'; -- clocked

process2 -- combinatorial
Q' <= f_next(Q,Xin);
Y <= f_out(Q);
-- end two-process approach

To simplify the code, I could simply write it as

-- one process approach
process1 (clk)
Q <= f_next(Q,Xin);
Yout <= f'_out(Q,Xin); -- where f'_out is derived from f_out above
-- end one-process approach

which is the essence of the single-process camp. Here, Xin,Yout, and Q
could be multiple signals, say bundled into a record or an array.

I can move Y from process 1 to process 2 by changing Q to Q', and
fiddling with how I define f_out. The two are more or less isomorphic
modulo some minor timing constraints - half of the arguments on this
thread are about whether they are isomorphic or not, depending on what
assumptions you make about undefined cases.

The key idea here is separating f_next from the process1 assignment.
One reason I want to do this, is to support one critical speed
optimization that I might want to do, which is to handle multiple
inputs on a single clock cycle. In the context of a reactive state
machine, where you can't take liberties with time, this makes little
or no sense. But consider a state machine which decodes MPEG VLC
(Huffman codes) or operates sequentially on an independent input
stream, like a DSP stream processor. If you can handle multiple inputs
per clock, you come out ahead (modulo the act of increased
combinatorial complexity delay affecting minimum clock cycle time).

If I want to handle two symbols per clock, and I have already
separated my design into *functions*, I can almost trivially rewrite
my state machine thus:

process1(clk) -- clocked
Q <= f_next(f_next(Q,Xin1), Xin2);
Yout1 <= f_out(Q,Xin1);
Yout2 <= f_out(f_next(Q), Xin2);
-- all done!

This is a little trickier with Mealy machines, and of course, in some
cases it's not apparent what multiple output events (Y1 and Y2) mean,
but that's a different problem. The idea I'm trying to convey is that
I can string together output functions and next state functions to
modify the behaviour of the machine easily, at a very high level (for
example,doing a one-input per clock to a two-input per clock change).

The key idea is that the computation of f_next and f_out, and the
actual flop assignments, are separated. In my case one in functions
and one in a process. In the two-process approach, by two processes in
which the functions f_next and f_out are still hard-coded.

Clearly, you can't ignore the combinatorial complexity and hence the
time penalty per clock cycle that may come from this. And I'll admit
that this example is a little contrived, but it makes perfect sense
when related to the mathematical viewpoint of automata, from which the
Moore/Mealy dichotomy developed. This is just the VHDL version of
"lifting" the state transition function from a single symbol in an
input alphabet to finite-length strings on the the alphabet.

In my humble opinion, this is how the separation of concerns *ought*
to be presented: as one process, with functions. Then view the single
process approach as writing the function bodies in-line. The two-
process approach is a bastard stepchild of the single-process, more
functional approach. But the ugly stepchild has been allowed to breed
and corrupt the young people of today nonetheless :)

OK, I'll shut up now :) Soapbox mode off.

- Kenn
 
R

rickman

process (clk)
variable Q: state_type;
Q := f_next(Q,Xin);
Y <= f_out(Q); -- NOTE f_out, NOT f'_out
end process;

Without getting into the whole issue of state machine descriptions, I
want to understand your use of variables better.

I have not found the need to use variables in the past to any degree
as I try to work simply and use a minimum subset of the language to
facilitate code reuse and ease of maintenance (by others as well as
myself). But I can see where variables may have some useful
applications.

Looking at your code, it see where it appears that it would produce
the registers you describe, and at that same time allow the input to
the register Q to be used in the expression for Y. But when I look at
one of my books, I see a very different example.

architecture version1 of circuit is
signal Q1, Q2: std_logic;
begin
process (Clk)
variable tmp1, tmp2: std_logic;
begin
if rising_edge(Clk) then
tmp1 := A and B; -- the definition of A and B in the port
definition is assumed
tmp2 := Q1 and C;
end if;
Q1 <= tmp1;
Q2 <= tmp2;
end process;
end version1;

I find this example to be very difficult to understand. I don't
understand why the assignments to Q1 and Q2 are done outside of the
clocked if structure. I would have expected tmp2 to be tmp1 and C,
not Q1 and C. The logic diagram shown for this example shows tmp1
(combinatorial logic which is the input to register Q1) as an input to
tmp2. Considering that Q1 is a signal and does not get updated until
the process exits, I don't see how this can produce the logic shown.

I found in another book that "For synthesis, it would not matter if
the assignments to Var1 and Var2 were swapped over"...

Var2 := Var1 and D;
Y1 <= not Var2;
Var1 := A and B and C; - A, B, C and D are inputs, Y1 is an output to
the entity

I would think that this reversed order of assigning and using Var1
would produce a register, but then it is not a clocked process so I
guess it will be a latch, no?

I think this is why I don't use variables. If I don't use a feature a
lot, I don't remember the details and then get it messed up when I do
try to use it.

Rick
 
M

Mike Treseler

Jonathan said:
Unfortunately, deriving f'_out from a traditional state
diagram is troublesome and you lose the nice isomorphism
between the state diagram and the code. I don't want to
treat state diagrams as some kind of sacred cow, but there's
no doubt that they provide a very useful tool for thinking -
a stepping-stone on the path from timing diagrams to VHDL code.

It was an very useful tool for manual synthesis
and simulation in the previous century.
It is much less compelling now,
when I can trace code, edit the offending line,
and rerun simulation waveforms or assertions
in less than a minute.

....
Which leads me to a scheme
that I've proposed here before, but not so elegantly
as Kenn's exposition: MAKE Q BE A VARIABLE, not a signal,

Now you've let the cat out of the bag.
If designers learn that C-like variables can make
registers, this newsgroup will become a ghost town ;)


-- Mike Treseler
 
J

jacko

Hi

I've only ever used variables indirectly with generate, or maybe these
are generics or parameters, or indexes, or just plain symbolic things.
I have never used variables.

I understand that the benefits are:
Localization: No signals in architecture body, and name reuse
confusion possibilities.
Automatic Registration: Use before assign, register reduction to latch
on non-clocked (lots of unsafe latch behaviour warnings, data and
enable driven by same logic).

In some ways the use of a process body, is unnecessay as signal
assignment works outside processes. for generate complains if I place
it in a process. Process is basically an encapsulation. functions are
another kind of encapsulation for shortening common expressions. I was
really suprised to find I could not declare local signals in a
process.

Just a convinience to convert software algorithms to hardware.

cheers
jacko
 
K

KJ

Mike Treseler said:
Jonathan Bromley wrote:
...

Now you've let the cat out of the bag.
If designers learn that C-like variables can make
registers, this newsgroup will become a ghost town ;)

I doubt it will become a ghost town, there will just be something else to be
used and misused.

It will just add a new topic to go along with the favorites...
- Two (or three) process vs one process state machine
- Mealy and Moore vs Larry, Curly, Moe
- Async vs. sync resets
- std_logic_arith

KJ
 
M

Mike Treseler

rickman said:
I find this example to be very difficult to understand.

I agree. It's just two gates and two flops!

Some reasons why

[] the example declares and uses unneeded signals
[] example does not demonstrate a single advantage to using variables
[] variables are poorly named
[] variables are used only as wires (left before right)

The version below is still silly, but is readable.

library ieee;
use ieee.std_logic_1164.all;
entity var is
port (Clk : in std_ulogic;
A : in std_ulogic;
B : in std_ulogic;
C : in std_ulogic;
Q1 : out std_ulogic;
Q2 : out std_ulogic);
end entity var;
architecture synth0 of var is
begin
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;
end synth0;

A better example would make use of the fact
that variable values can be used immediately:

http://mysite.verizon.net/miketreseler/stack.vhd

-- Mike Treseler
 
M

Mike Treseler

Mike said:
if rising_edge(Clk) then
q1_v := A and B; -- right before left
---------------------------------- left before right!!!
q2_v := q1_v and C; -- means no regs here

Dooh.
Make that
1. left before right means no register.
2. right before left" infers a register.

Not a very convincing argument about how easy this is ;)
I think of [2] as "save the value for next time"

Now, note that if I reverse these two variable assignments,
that q1_v becomes a register output and the
and gates are pipelined, making the example
slightly more interesting.

-- Mike Treseler
 
R

rickman

rickman said:
I find this example to be very difficult to understand.

I agree. It's just two gates and two flops!

Some reasons why

[] the example declares and uses unneeded signals
[] example does not demonstrate a single advantage to using variables
[] variables are poorly named
[] variables are used only as wires (left before right)

The version below is still silly, but is readable.

library ieee;
use ieee.std_logic_1164.all;
entity var is
port (Clk : in std_ulogic;
A : in std_ulogic;
B : in std_ulogic;
C : in std_ulogic;
Q1 : out std_ulogic;
Q2 : out std_ulogic);
end entity var;
architecture synth0 of var is
begin
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;
end synth0;

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. I guess the fact that the variables
which are the register inputs are only updated on the rising edge
means the signals can only change on the rising edge as well, but it
just looks "bad" to me. But like you said, it does not illustrate a
reason to use variables. I guess it was just intended as a minimal
example to show how variables work, but still, I don't understand this
construct.

Another book is a little better, but a third is nearly as poor showing
only two trivial examples with no info on *why* they should be used.
A fourth focuses on the mechanics of how a variable differs from a
signal showing the updating with time and delta delays, but again
nothing on the *why*.

Rick
 
M

Mike Treseler

rickman said:
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.

No. It may waste some sim cycles, but since
I only put port wires here, the fact
that the assignment is updated unnecessarily
on the falling clock, does not change any outputs.
The reason for the odd placement does not
make any sense until you try to add reset.

I explain this in the comments of my reference
design. When I add an asynch reset,
I have two choices for a template the works for
both the clock edge and the reset level.
The first template avoids having to duplicate
the port update code. The second is easier to read.

----------------------------------------------------------
procedure template_v_rst is
begin -- equivalent to a_rst below for synthesis.
if reset = '1' then
init_regs;
elsif rising_edge(clock) then
update_regs;
end if;
update_ports;
end procedure template_v_rst;
----------------------------------------------------------
procedure template_a_rst is
begin -- equivalent to v_rst for synthesis.
if reset = '1' then
init_regs;
update_ports;
elsif rising_edge(clock) then
update_regs;
update_ports;
end if;
end procedure template_a_rst;


Since I write "update_ports" as a procedure
anyway, I guess I have no good reason for preferring
the first template.

-- Mike Treseler
 
M

Mike Treseler

Brian said:
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
 
L

lings.23

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 =>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top