State Machine Output

  • Thread starter Jonathan Bromley
  • Start date
J

Jonathan Bromley

I have a state machine which is coded like so:

if rising_edge(CLK) then
case state is
when xyz =>
OUT <= '1';
state <= xyxyxy;
when xyxyxy =>
OUT <= '0';
etc
The problem is the output doesn't seem to happen in the state it should,

Yes it does - but it doesn't happen in the state you WANT :)
instead it seems to happen in the next state. So in the above example the
signal OUT is set to 1 in state xyxyxy.

Yup. That's what you asked for.
Does anyone have any idea on what I'm doing wrong? How can I make the
output change in the state?

I guess you want the output to be a function of the state.
But that's not what you wrote. Think about...
case state is
when xyz =>
OUT <= '1';
state <= xyxyxy;

This code is executed at the moment of a clock edge.
"case state" is testing "state" as it was JUST BEFORE
the clock edge; but assignments to "state" and "OUT"
are scheduling an update to those signals that will take
place JUST AFTER the clock edge (the "next state" values).
Not surprisingly, when you look at the code, "OUT" will
transition to '1' at exactly the same time that "state"
transitions to xyxyxy.

There are numerous solutions. Here are three of the
most familiar:

(1) Set up your value of OUT at the same time as you
transition INTO a state. That way, OUT is active
in the same clock as the chosen state. But it's
horrible to write, because you have to locate
every transition into the state, everywhere in
the state machine.
(2) Take the assignments to OUT right outside the
clocked state machine block, and create a separate
COMBINATIONAL process to decode outputs from the state.
This is the classic "Moore" architecture, but it has
the disadvantage that there is now some intervening
combinational logic between registers and outputs.
(3) Arrange the state values to be named constants of
std_logic_vector type (instead of enumerations). Now
you can set up the bit-patterns of the state values
so that some of the state bits are exactly your
required output bits. This is cute because your main
state machine code doesn't have to worry about outputs
at all - they come along for the ride, together with
the state value - but it's a little hard to maintain,
and you have to choose all the state values yourself
instead of leaving it to the synthesis tool.

And here's a less familiar version, which I think is
rather nice...

process (clock, reset)
type StateType is (state, names, here);
variable state: StateType;
begin
if reset = '1' then
-- reset everything
state := IDLE;
OUT <= '0';
elsif rising_edge(clock) then

-- We do this in two stages.

-- First, update the state variable:
case state is
when xyz =>
if Trigger then
state := pqr;
end if;
when pqr => ......
end case;

-- Now that the state variable ALREADY has its new
-- (next-state) value, we can decode it to provide
-- registered outputs:
case state is
when xyz =>
OUT <= '1'; -- OUT will be set during state xyz
when others =>
OUT <= '0';
end case;

end if; -- clocked logic
end process;

This approach has some nice advantages. The state
type and variable are hidden within the state machine
process, and don't pollute the rest of the architecture
body. Because "state" is a variable, VHDL updates it
immediately on assignment; hence, in the second part
of the clocked process, "state" is in fact representing
the next-state value (state register D inputs) rather
than the current state register value. This "sneak
preview" of the next state allows you to set up
registered outputs in a nice clear way. And of course
you don't need to mess around creating yet another
signal to hold the next-state value.

HTH
--
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, Hampshire, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail: (e-mail address removed)
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.
 
S

Simon

Hi

I have a state machine which is coded like so:

if rising_edge(CLK) then
case state is
when xyz =>
OUT <= '1';
state <= xyxyxy;
when xyxyxy =>
OUT <= '0';
etc
etc
etc


The problem is the output doesn't seem to happen in the state it should,
instead it seems to happen in the next state. So in the above example the
signal OUT is set to 1 in state xyxyxy.

Does anyone have any idea on what I'm doing wrong? How can I make the
output change in the state?

Thanks in advance.
 
M

Mike Treseler

Jonathan said:
And here's a less familiar version, which I think is
rather nice...

Familiar to some, "nice" and logical.

-- Now that the state variable ALREADY has its new
-- (next-state) value, we can decode it to provide
-- registered outputs:

Yes. Using process variables makes synthesis do some
work and allows the designer to follow value changes
by just looking at the code.
case state is
when xyz =>
OUT <= '1'; -- OUT will be set during state xyz
when others =>
OUT <= '0';
end case;

end if; -- clocked logic
end process;

This approach has some nice advantages. The state
type and variable are hidden within the state machine
process, and don't pollute the rest of the architecture
body.

Yes. Nice and logical. The designer can fearlessly use
variable names like i, n, state, count, etc without
interacting with other processes. While variable values
are hidden to other processes, they can be viewed
as simulation waveforms.
Because "state" is a variable, VHDL updates it
immediately on assignment; hence, in the second part
of the clocked process, "state" is in fact representing
the next-state value (state register D inputs) rather
than the current state register value. This "sneak
preview" of the next state allows you to set up
registered outputs in a nice clear way. And of course
you don't need to mess around creating yet another
signal to hold the next-state value.

Well said. Process variables are the most logical
way to describe state information.

-- Mike Treseler
 
N

Nicolas Matringe

Mike Treseler a écrit:
[...]

Well said. Process variables are the most logical
way to describe state information.

Indeed. I like it very much.
I wonder why nobody ever tought this to me... It was always the same old
two processes scheme.
Thanks a lot Jonathan.
 
J

Jan Decaluwe

Nicolas said:
Mike Treseler a écrit:
[...]


Well said. Process variables are the most logical
way to describe state information.


Indeed. I like it very much.
I wonder why nobody ever tought this to me... It was always the same old
two processes scheme.

Here's my take on possible reasons for that one:

- lack of "software" talent in the hardware design community.

Many hardware designers refuse to appreciate the full value
of nice code and powerful synthesis tools. They want to see
their registers, muxes and adders jumping right out of their code.
This sad attitude is called "hardware thinking" and is used
as an excuse to avoid having to understand what a synthesis tool
can do.

The EDA vendors didn't help, as their software talent is
in tool development, not applications engineering.

- bad influence of Verilog.

The most popular HDL on the planet doesn't make the distinction
between variables and signals. Combined with the absence of a
decent delta cycle mechanism, the result is eternal confusion
about the semantics of "blocking" and "non-blocking" assignments,
to newbies and experts alike.

A popular "solution" in the Verilog community is to simply ban the
discussed coding style altogether! (In Verilog speaky-speaky,
this would sound "you shouldn't mix blocking and non-blocking
assignments in the same always block.")

Therefore, suppose you would code the example in Verilog and
post it to comp.lang.verilog as an example of good style. Here's
what might happen. You may be insulted to be a junior designer
without the slightest clue on hardware design. You may be
bombarded with links to award winning papers by Cliff Cummings
that will help you to overcome your bad habits. You may be urged
to take a training course ("Advanced Verilog Techniques
For Ex-VHDL Designers").

On the other hand, the chance of an enthusiastic reaction such
as yours, from someone that has seen the light, is very low,
I believe. Makes you wonder where the multimillion dollar
mistake exactly is.

Regards, Jan
 
J

Jonathan Bromley

Here's my take on possible reasons for that one:

- lack of "software" talent in the hardware design community.

"Insight" rather than "talent", maybe? Many people don't
feel as strongly as they should about notions of locality
and self-sufficiency in programming, and these are ideas that
are quite hard to explain and exemplify.
- bad influence of Verilog.
The most popular HDL on the planet doesn't make the distinction
between variables and signals.

Well... it can be asked so to do, by a very simple ruse:

* signals are implemented either as nets, or as regs defined
at the module level. Such regs must be assigned-to using
nonblocking assignments within a clocked process if they
represent flip-flops, but using delayless blocking
assignments within a combinational process.
* variables are implemented as regs assigned-to using
delayless blocking assignment within a named begin..end;
such regs may never be accessed from outside their
named begin..end scope.
A popular "solution" in the Verilog community is to simply ban the
discussed coding style altogether! (In Verilog speaky-speaky,
this would sound "you shouldn't mix blocking and non-blocking
assignments in the same always block.")

In fairness, there are plenty of VHDL authors/trainers who
similarly aim to ban such coding style.

The Openmore standard, and several in-house standards,
mandate this "solution"; it's equivalent to denying a
VHDL programmer the use of variables. Grrr. Sadly,
at least one ASIC synthesis tool won't accept the
"variable-like" Verilog style at all, so the forces of
darkness think that they have justification for their
prejudices.
Therefore, suppose you would code the example in Verilog and
post it to comp.lang.verilog as an example of good style. Here's
what might happen. You may be insulted by a junior designer
without the slightest clue on hardware design. You may be
bombarded with links to award winning papers by Cliff Cummings
that will help you to overcome your bad habits. You may be urged
to take a training course ("Advanced Verilog Techniques
For Ex-VHDL Designers").

Tee hee.

--

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, Hampshire, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail: (e-mail address removed)
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.
 
C

Charles M. Elias

Simon said:
Hi

I have a state machine which is coded like so:

if rising_edge(CLK) then
case state is
when xyz =>
OUT <= '1';
state <= xyxyxy;
when xyxyxy =>
OUT <= '0';
etc
etc
etc


The problem is the output doesn't seem to happen in the state it should,
instead it seems to happen in the next state. So in the above example the
signal OUT is set to 1 in state xyxyxy.

Does anyone have any idea on what I'm doing wrong? How can I make the
output change in the state?

Thanks in advance.

Simon,

I almost always use two-process state machines (very simple example
below). If I want a clocked output (say a d flip-flop) I use a flop
external to the state machine and control it from the state machine.
I have also controlled counters in a similar manner. This is a very
flexible way of doing it at the cost of some added complexity in the
code--not necessarily in the synthesized result.

Charles

-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-- State Machine A clocking and initialization
-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
a_clking : process( a_clk, clr_l, a_next_state )
begin
if rising_edge( a_clk ) then
if clr_l = '0' then
a_pres_state <= a_state1;
else
a_pres_state <= a_next_state;
end if;
end if;
end process a_clking;
-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-- State Machine A state transition and output control
-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
-- ffa_q is the output of d flip-flop a
-- d_ffa is the d input of d flip-flop a

a_trans : process( a_pres_state, ffa_q, some_input )
begin
case a_pres_state is
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
when a_state1 =>
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cycle_machine_b <= '0';
a_state_num <= 1;
d_ffa <= 0; --clr d flop a

a_next_state <= a_state2;
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
when a_state2 =>
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cycle_machine_b <= '0';
a_state_num <= 2;

if some_input = '1' then
d_ffa <= '1'; --set flop a
a_next_state <= a_state3;
else
d_ffa <= '0'; --clr d flop a
a_next_state <= a_state2;
end if;
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
when a_state3 =>
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cycle_machine_b <= '0';
a_state_num <= 3;
d_ffa <= ffa_q;--hold flop a

a_next_state <= a_state4;
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
when a_state4 =>
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cycle_machine_b <= '0';
a_state_num <= 4;
d_ffa <= ffa_q; --hold flop a

a_next_state <= a_state5;
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
when a_state5 =>
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cycle_machine_b <= '1';
a_state_num <= 5;
d_ffa <= '0'; --clr flop a

a_next_state <= a_state1;
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
when others =>
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
a_next_state <= a_state1;
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end case;
end process a_trans;
 
J

jussi l

Hi,

Id like to add one possible reason, which was the lack of proper education
in the old days. Pretty much everybody who was involved with HDL till about
10 years ago was self-taught. And while design sizes grew rapidly, the
methodologies stayed the same, to put it shortly. But, I wouldn't give that
much credit to the software people either, in my experience they have made
gazillion more unforgivable errors with poor code than hardware guys ever
will :)

regards,
juza


Jan Decaluwe said:
Nicolas said:
Mike Treseler a écrit:
[...]


Well said. Process variables are the most logical
way to describe state information.


Indeed. I like it very much.
I wonder why nobody ever tought this to me... It was always the same old
two processes scheme.

Here's my take on possible reasons for that one:

- lack of "software" talent in the hardware design community.

Many hardware designers refuse to appreciate the full value
of nice code and powerful synthesis tools. They want to see
their registers, muxes and adders jumping right out of their code.
This sad attitude is called "hardware thinking" and is used
as an excuse to avoid having to understand what a synthesis tool
can do.

The EDA vendors didn't help, as their software talent is
in tool development, not applications engineering.

- bad influence of Verilog.

The most popular HDL on the planet doesn't make the distinction
between variables and signals. Combined with the absence of a
decent delta cycle mechanism, the result is eternal confusion
about the semantics of "blocking" and "non-blocking" assignments,
to newbies and experts alike.

A popular "solution" in the Verilog community is to simply ban the
discussed coding style altogether! (In Verilog speaky-speaky,
this would sound "you shouldn't mix blocking and non-blocking
assignments in the same always block.")

Therefore, suppose you would code the example in Verilog and
post it to comp.lang.verilog as an example of good style. Here's
what might happen. You may be insulted to be a junior designer
without the slightest clue on hardware design. You may be
bombarded with links to award winning papers by Cliff Cummings
that will help you to overcome your bad habits. You may be urged
to take a training course ("Advanced Verilog Techniques
For Ex-VHDL Designers").

On the other hand, the chance of an enthusiastic reaction such
as yours, from someone that has seen the light, is very low,
I believe. Makes you wonder where the multimillion dollar
mistake exactly is.

Regards, Jan

--
Jan Decaluwe - Resources bvba - http://jandecaluwe.com
Losbergenlaan 16, B-3010 Leuven, Belgium
Bored with EDA the way it is? Check this:
http://jandecaluwe.com/Tools/MyHDL/Overview.html
 
J

Jan Decaluwe

jussi said:
Hi,

Id like to add one possible reason, which was the lack of proper education
in the old days. Pretty much everybody who was involved with HDL till about
10 years ago was self-taught. And while design sizes grew rapidly, the
methodologies stayed the same, to put it shortly.

If that were the case, one could reasonably expect the situation to be
better now. But it isn't. Most books, papers, methodolodogy guides
and training courses are "hardware thinking" (in the bad sense) centric,
and therefore quite boring and unimaginative. At least in the old days,
there was some room for experimentation - a freedom that you may
no longer have now (if you want the job).

To verify/falsify this claim, try to provide me with a link to an
educational reference that advocates the coding style that was
proposed in this thread (using variables for process state). Then
compare it with the number of references that advocate a coding style
that would make the former one impossible.

As my count stands at approximately 1 against (all - 1), I'll stick
to my original 2 reasons for now.

Regards, Jan
 
Joined
Feb 27, 2008
Messages
2
Reaction score
0
modelsim is confused by vars

While this method is giving me excellent results with the XST synthesizer, Modelsim doesn't seem to recognize the code as an FSM. This is ruining my RTL simulation and making it very difficult to debug this design. I have to add a test std_logic_vector and change its value in each state to get enough info for debug. (The FSM state vars don't show up.)
 
Joined
Feb 27, 2008
Messages
2
Reaction score
0
While this method is giving me excellent results with the XST synthesizer, Modelsim doesn't seem to recognize the code as an FSM. This is ruining my RTL simulation and making it very difficult to debug this design. I have to add a test std_logic_vector and change its value in each state to get enough info for debug. (The FSM state vars don't show up.)
 

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,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top