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.