VHDL Functions

U

utauta

I'm using a state machine for a simple project and wanted to know if I
can create a state machine within a function in order to shorten code.

For example: If I have 6 different input combinations and need to go
through the same sequence of states except for a few small
modifications pertaining to input values.

Long version:

if (input 1)
state 1 > state 2 > state custom, state 4, state 5, state 6
elsif (input 2)
state 1 > state 2 > state custom, state 4, state 5, state 6
elsif (input 3)
state 1 > state 2 > state custom, state 4, state 5, state 6
elsif (input 4)
state 1 > state 2 > state custom, state 4, state 5, state 6
end if;

Short version:

function(argument):
state 1 > state 2 > state custom, state 4, state 5, state 6
end function

if (input 1)
function(argument 1)
elsif (input 2)
function(argument 2)
elsif (input 3)
function(argument 3)
elsif (input 4)
function(argument 4)
end if;

What is the best way to implement this?
 
M

Mike Treseler

utauta said:
For example: If I have 6 different input combinations and need to go
through the same sequence of states except for a few small
modifications pertaining to input values.
What is the best way to implement this?

A counter?

-- Mike Treseler
 
U

utauta

A counter?

-- Mike Treseler


Well I am using a counter to change from the current state to the
next, but what I meant was if I had a 50 state sequence (for example)
with 6 inputs each having to go through a slightly modified version of
the sequence, is it possible to create a function to simplify this? Or
will I have to type out 50 states 6 times?
 
K

KJ

I'm using a state machine for a simple project and wanted to know if I
can create a state machine within a function in order to shorten code.

No, because functions have no memory. However, a function can be used
to compute a next state from a current one (more later).
For example: If I have 6 different input combinations and need to go
through the same sequence of states except for a few small
modifications pertaining to input values.

Long version:

if (input 1)
state 1 > state 2 > state custom, state 4, state 5, state 6
elsif (input 2)
state 1 > state 2 > state custom, state 4, state 5, state 6
elsif (input 3)
state 1 > state 2 > state custom, state 4, state 5, state 6
elsif (input 4)
state 1 > state 2 > state custom, state 4, state 5, state 6
end if;

Short version:

function(argument):
state 1 > state 2 > state custom, state 4, state 5, state 6
end function

The following process implements what you've described. I'm assuming
that there are actually 4 'state custom' states, one responding to
each of the inputs.

process(Clock)
if rising_edge(Clock) then
case Current_State is
when state1 => Current_State <= state2;
when state2 =>
if (input1 = '1') then Current_State <= state_custom1;
elsif (input2 = '1') then Current_State <= state_custom2;
elsif (input3 = '1') then Current_State <= state_custom3;
elsif (input4 = '1') then Current_State <= state_custom4;
end if;
when state4 => Current_State <= state5;
when state5 => Current_State <= state6;
when state6 => Current_State <= state1; -- Back to the start?
when others => Current_State <= state4;
end case;
end if;
end process;

The only thing you can do with a function in this case is to use it to
compute the next state. That function would have to be of the form

function Compute_Next_State(Current_State: t_states; input1, input2,
input3, input4:std_ulogic) return t_states;

The body for the function would be everything from the process that is
inside the "if rising_edge(Clock)" section of code. That reduces the
'state machine' code to being

process(Clock)
if rising_edge(Clock) then
Current_State <= Compute_Next_State(Current_State, input1, input2,
input3, input4);
end if;
end process;

But all you've done by doing so is moved the code from one place (the
body of the process) to another (the body of the function), it doesn't
make for any less work (there is actually slightly more). It is not
any easier to maintain. I'm guessing it would likely be somewhat less
maintainable since state machines usually do more than just compute
their next state, which means that there would be other signal
outputs. Those output signals, being a function of the current state
as well would then have their own separate case statements so now
you're creating yet more code to replicate case statements and reset
logic.

Since there must be some reason for the 'state customs' states, this
must apply in your situation as well since you must be doing
'something' different in those custom states otherwise there would be
no reason for them.

Far better in my opinion to have a single case statement where the
next state and the relevant outputs are handled. That way it is
easier to see by simple inspection that when you're in a particular
state what is happening with the next state and the outputs.

i.e.

case Current_State is
when state1 =>
if (Something_Marvelous = '1') then
Current_State <= Hawaii;
Job <= FALSE;
Money <= TRUE;
Life <= Good;
end if;
when state2 =>
....

The other thing to note is that the state machine you've described has
no reset input, so I've not implemented it in the above. Obviously
you would need to fix that. But take a look now at what that fix
would entail since it is tweaks and changes like this that get to what
is meant by maintainability.

- Process approach:
1. Simply add the 'if reset = '1' then...' code.

- Function approach:
1. Modify the function to accept a new input (i.e. 'reset')
2. Modify the process that calls the function to add the reset input.

Now you can't argue that the process approach doesn't take less work,
you can only quibble that the function approach doesn't take 'too
much' extra work. But even for that little bit more work, you've got
nothing better to show for the effort and from a maintainability
standpoint I think you have less. The code is less clear (since the
output and next state logic have been separated), there is likely code
duplication between the functions that compute next state and outputs
which implies that there is a greater chance for introducing design
errors by not duplicating changes to the logic that occur after the
initial copy/paste that splits the function into multiples.

Lastly, as Mike already pointed out, a simple counter might be an even
better approach depending on what all else is going on with the design
that the state machine is a part of.
What is the best way to implement this?

Your pseudo code of the state transitions in the 'function' was
actually quite close to describing how to implement it, you seem to
have been derailed though in thinking that any copy/pasting would be
necessary which then led down the dead end of pondering how to use a
function to avoid the copy/paste. Had the copy/paste actually been
necessary, then a function would be appropriate to avoid the copy/
paste but in the instance that you described with the state machine
there really is no need for anything like that. Notice that I didn't
need to do anything fancy to implement what you described.

Kevin Jennings
 
S

Stef

In comp.lang.vhdl,
utauta said:
Well I am using a counter to change from the current state to the
next, but what I meant was if I had a 50 state sequence (for example)
with 6 inputs each having to go through a slightly modified version of
the sequence, is it possible to create a function to simplify this? Or
will I have to type out 50 states 6 times?

So you have a state machine with 50 states and the sequence depends on
the input signals? Then add those input signals to your next-state
logic and you have a single state machine with the required behaviour.
If your machine should only use the input state that was present at
the start of the sequence, register that input state and use the
registered version in your next-state logic.


--
Stef (remove caps, dashes and .invalid from e-mail address to reply by mail)

"I always avoid prophesying beforehand because it is much better
to prophesy after the event has already taken place. " - Winston
Churchill
 
U

utauta

Thanks for the helpful replies.

I used the method KJ and Stef mentioned: A single state machine where
the current state modifies the next state and its corresponding
outputs.

I'm using if statements within each state to re-loop to reused states
for each specific input.

Just another question: How common are functions used in VHDL? And do
most designs (90%) use state machines?
 
U

utauta

Thanks for the helpful replies.

I used the method KJ and Stef mentioned: A single state machine where
the current state modifies the next state and its corresponding
output.

What I did is re-loop to reused states for each different input.

A few questions about VHDL:

How often are functions used?

and

Do most (90%) of FPGA designs use state machines?
 
M

Mike Treseler

utauta said:
How often are functions used?

That is up to the designer.

For synthesis I use functions and procedures
to collect repeated expressions
for uniformity and clarity.

For simulation, I use them to break
complex tests into understandable chunks.

See the reference design and testbench here for examples.
http://mysite.verizon.net/miketreseler/
Do most (90%) of FPGA designs use state machines?

100% of FPGA designs use gates and registers.

"State machine" is text book notion for manual synthesis.
HDL synthesis is about updating registers every clock cycle.
I use vhdl variables to represent registers
and vhdl functions or expressions to represent
the gates that handle the updating.

If I declare a numeric register type and update it
using the function '+',
the textbook might call that a counter.

If I declare an enumeration type and update it
with an if or case expression,
the textbook might call that a 'state machine'.

In a complex hdl design, these academic distinctions
are so mashed together that they become less useful
than the more subtle distinctions built in to the
vhdl language for the description of a clocked process.

-- Mike Treseler
 
U

utauta

Brian,
You can use functions and procedures in that process to simplify the
process.

Thanks for the clarifications on the use of functions and
procedures(new to me). Right now I'm not using any functions/
procedures. I have two processes: one processes the input and contains
case statements for the different states, the other processes the
clock input and modifies the current state to the next. I'll try
modifying my code with procedures to see if it will help with code
simplicity.


Mike,

Thanks for the help. I had always though that the definition of a
'State Machine' was case statements where the current state was
updated by a clock in a separate process. I've only been exposed to
basic vhdl code so far, so your vhdl examples are very helpful.
 

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,774
Messages
2,569,596
Members
45,135
Latest member
VeronaShap
Top