Using FSMs to control data flow

M

mamu

Hello,

when writing FSMs (I like the 2 process approach) I find it convenient
to assign outputs directly in the different states. E.g. :

case current_state is
when state1 =>
data_out <= data_in1;
when state2 =>
data_out <= data_in2;
when state3....
-- some more states...
end case;

However, I've read somewhere (in the Xilinx timing improvement wizard,
I believe) that I should keep the dataflow out of the FSMs and use
control signals for the muxes instead.

To me this only seems like more typing and more signals in the design.
Will the synthesis tools (XST in my case) handle the two approaches
differently?
 
K

KJ

Hello,

when writing FSMs (I like the 2 process approach)

I don't, but that's OK.
I find it convenient
to assign outputs directly in the different states. E.g. :

case current_state is
when state1 =>
data_out <= data_in1;
when state2 =>
data_out <= data_in2;
when state3....
-- some more states...
end case;

However, I've read somewhere (in the Xilinx timing improvement wizard,
I believe) that I should keep the dataflow out of the FSMs and use
control signals for the muxes instead.

To me this only seems like more typing and more signals in the design.
Will the synthesis tools (XST in my case) handle the two approaches
differently?

The two process approach also takes more typing...but that's another
discussion. In any case, what you write will get synthesized to the
logical equivalent. If not, you open a web case but you likely won't
need to.

The reason for the recommendation is likely because, for the most
part, data does not need to be made a function of all of the states in
a state machine, many times it doesn't care about the state at all,
other times it depends only weakly on the state (i.e. data_out <=
data_in when (state = this) else "00"). By putting data path stuff
inside the state machine it is easier to make the logic
unintentionally more complex than it should be (which will use up more
logic and likely slow down the worst case timing path). Having said
that though, if you are diligent about it the logic will reduce to the
exact same thing whether you assign 'data_out' inside the state
machine or outside of it.

Kevin Jennings
 
M

mamu

Thanks for your answer Kevin.

So would it be wise to set data_out <= (others => '-') for all the
other states (as a default above the case statement)?

Im not sure how you write FSMs, but wouldn't you have to use a
synchronous process so that all outputs will be registers?
 
K

KJ

Thanks for your answer Kevin.

So would it be wise to set data_out <= (others => '-') for all the
other states (as a default above the case statement)?

Yes, either that or (others => '0'), whatever default value you
prefer. If you use '-' then you get a synthesis warning that it is
converting your '-' to a '0', since it can't synthesize a '-', but
that's OK, so you can ignore it. When simulating it can be useful
though to see '-' just to see that nothing else breaks since many
times such a break is indicative of a design error of some sort.
Im not sure how you write FSMs, but wouldn't you have to use a
synchronous process so that all outputs will be registers?

Yes, I write the state machines as a single clocked process so all of
the outputs and state are clocked. If I do happen to need an output
not be clocked, I would have it outside the process in a concurrent
statement something like this...

some_out <= a and b when (current_state = Do_Something) else '0';

The drawback there is if the conditions on when you want to set
'some_out' are more complicated then just a simple state decoding as
shown above and you end up basically wanting to replicate if/then/else/
case/whatever logic that is also quite likely in the state machine as
well. That is 'bad' in the sense that you're copying stuff and have
to manually make sure that you've really got the same logic now in two
places...gets harder to maintain such code.

One way around that is to use variables inside your process and then
at the end assign signals to the values of those variables. Mike
Tressler uses that approach extensively, Google around for his web
site and he has some examples. That approach still maintains the
single clocked process approach, rather than the two process state
machine model proposed mainly by academics who don't have to design/
support real designs but it also allows for clocked and unclocked
outputs of the state machine and from a simple 'here is a simple
method to follow that works' approach is hard to beat.

Another way around is to simply add another state and use the
concurrent assignment as I demonstrated above. Many times this is
actually more effective since the complicated logic that you don't
want to copy/paste (from a maintenance/support perspective) will
typically also result in long combinatorial logic chains that now end
up being your critical timing path.

Kevin Jennings
 
M

Mike Treseler

mamu said:
So would it be wise to set data_out <= (others => '-') for all the
other states (as a default above the case statement)?

Not for a single process.
Just update changes.
Im not sure how you write FSMs, but wouldn't you have to use a
synchronous process so that all outputs will be registers?

Yes.
 

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