State Machine with single cycle pulsed outputs?

M

M. Norton

I like the basic approach in Jonathan's example, for clarity.

I do too and might start working that into the next development,
though I think I also like the addition of a current_state signal in
addition to next_state variable.

But, it looks very readable and maintainable.

And thank you and Kevin for the RTL/synthesizing notes. It is
encouraging to have language features actually be of some concrete use
other than just syntactical scenarios. Another prod to try this out
sometime and see how it works.

Mark
 
A

Andy

Alright, I've been following this because typically for RTL I rarely
use variables.  I have had, in the past, issues where I want signals
asserted at state transitions and, using signals, it requires some
jiggerypokery and has never been as entirely clear as I liked.  So
this is interesting stuff to see the difference.  I knew there had to
be something more clever than my edge detect ;-).

So I can see that we get the pulse asserted on the rising clock edge
for one cycle, and running also starts on the rising clock edge,
everything seems nicely synchronous.

My only question is, do synthesizers respect this distinction between
variable and signal updates and generate appropriately?

Best regards,
Mark Norton

I appreciate JB's two-case-statement approach, and for some complex
state machines, it would be very beneficial. I have from time to time,
to make the cycle-based timing work out, needed to specify an output
in every transition to a given state, and on large/complex FSMs, JB's
example is a better way, while still having registered outputs.

As to the synthesis tool's treatment of the differences between
variable and signal update behavior, yes, most tools handle it fine. I
use Synplify for most of my work, and have had only one problem, a
couple of years ago, that was quickly fixed. The way I see it, a
synthesis tool's job is to create hardware that will, on a clock cycle
basis, replicate the behavior of the RTL code. Most tools ignore the
impact of sensitivity lists, but other than that, do a pretty good
job.

To me, variables represent the most flexible way to represent cycle-
based behavior. If the behavior has a clock cycle delay, then the
hardware will too (by using a register). If not, it won't. We
typically think of any signal assigned in a clocked process as being
registered. With variables, it is the reference to the variable,
relative to when it was last written, that determines a registered or
combinatorial implementation. In JB's example, the first case
statement's reference to 'state' is registered, since state was not
previously assigned in that clock cycle (forcing storage of previous
value, accomplished with the register). References to state in the
second case statement are combinatorial, because state may have been
updated, and at least a mux is required to choose between the input
and output of the state register. Note that even in those situations
where state is not explicitly assigned in the first case statement,
the second case statement uses the same next state logic (feedback
mux) that was implemented for the first case statement.

Andy
 
A

Analog_Guy

This is another reason for using a state variable: this kind of thing
is elegant and easy to code.  Here's a very simple FSM with 2 states.
There's an idle (do-nothing) state, and a Run state.
When in Idle you stay there until you see the Go input
asserted; then transition to Run.  At this point you would like
a Start output asserted for just one clock, but you also have
a Running output that remains asserted all the time you're in Run.
You then wait until Go becomes false; at this point you transition
back to Idle and assert a Stop signal for one cycle.  Here's the
code (many declarations missing):

  process (Clock) is
    variable state: state_type; -- enum (Idle, Run)
  begin
    if rising_edge(Clock) then
      if Synch_Reset='1' then
        state := Idle;
        Start <= '0';
        Stop <= '0';
        Running <= '0';
      else
        -- All outputs are defaulted here.
        Start <= '0';
        Stop <= '0';
        Running <= '0';
        -- Transition actions, compute next-state
        -- and single-clock (edge detect) outputs
        case state is
          when Idle =>
            if Go = '1' then
              state := Run;
              Start <= '1'; -- asserted for 1 clock only
            end if;
          when Run =>
            if Go = '0' then
              state := Idle;
              Stop <= '0'; -- asserted for 1 clock only
            end if;
        end case;
        -- Now "state" contains the next-state value,
        -- use it to compute Moore (state-dependent) outputs
        case state is
          when Run =>
            Running <= '1';
          when others =>
            null;
        end case;
      end if;
    end if;
  end process;

No edge detectors, no extra states, just a clear
distinction between things that happen on a
state transition and things that happen when
you're in a certain state.

It works for me; YMMV.

Thanks for the response. That definately defines what I am trying to
accomplish. I'll have to do a little more reading on the
one/two/three process state machine implementations and the use of
variables. Up until now, I have used HDL Designer to graphically
define SMs (three process approach). However, now I am moving to a
fully text based approach. Thanks again for the help.
 
M

m

Is there an easy method of creating a state machine to output control
signals that are only one clock cylce wide (i.e. upon entering a
state), no matter how long the state machine resides in that single
state?  I like to use pulsed "start" and "stop" commands to control
functionality in other processes.

Just assert your control signal when you make the decision to change
states. De-assert it immediately upon entering the state. It doesn't
have to be any more complicated than that. If you want the control
signal to happen one clock cycle after entering the new state simply
run it through a F/F.


-Martin
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top