VHDL Functions

U

utauta

Guest
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?
 
utauta wrote:

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
 
On Jul 23, 11:23 pm, Mike Treseler <mtrese...@gmail.com> wrote:
utauta wrote:
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

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?
 
On Jul 24, 1:57 am, utauta <NetbeansSo...@gmail.com> wrote:
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
 
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?
 
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?
 
On Wed, 23 Jul 2008 22:57:57 -0700 (PDT), utauta
<NetbeansSound@gmail.com> wrote:

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.
More likely, create a function within a state machine...

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)
This suggests you are coming from a C background?

if input1 -- minor point: brackets round expressions are harmless
-- but redundant; maybe they give a C programmer a comfortable feeling

if (input 1)
function(argument 1)
elsif
Functions in VHDL are commonly used to abstract over messy details, such
as type conversions or complex expressions.

But unlike C, they ALWAYS return a value; and unlike C, you MUST always
use the return value. In this code fragment you probably don't want a
function, you want a procedure.

What is the best way to implement this?
As KJ suggests, a state machine is a separate process, and he has good
suggestions how to start.

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

If declared locally (i.e. within the process) they have visibility of
all the previously declared signals, variables, constants etc, and a
procedure can update the variables and signals. (A function can't; you
assign its return value to a variable or signal).

You can also pass some inputs (and outputs, for a procedure) as
parameters. Then you can hook up the parameters to different actual
parameters in the call, as with C etc. (However you have different
parameter passing modes; much more useful than C which only has mode IN,
and forces you to use & and * in weird convoluted error-prone ways to
simulate the other modes)

Alternatively, procedures and functions can be declared externally,
usually within a package, and re-used in other designs. Then all
connections should be through parameters (or function return).
(Glossing over shared variables, which are best avoided outside
testbenches)

If you can find Mike Treseler's examples, they will give you good
examples of these points.

http://mysite.verizon.net/miketreseler/

His "Synthesis template" and others
http://mysite.verizon.net/miketreseler/sync_template.vhd
shows how to use local procedures in a process to remove complexity from
the main loop in a process.

His "Remote Testbench Procedure"
http://mysite.verizon.net/miketreseler/proc_overload.vhd
shows a very good use of external procedures, with connections made
through parameters (arguments).

In this case the procedure from the package is overloaded within the
process, to hookup a locally visible signal (visible to the local,
overloadING, procedure) to the external procedure.

This is not strictly necessary but a nice touch; the call to "set_bit"
in the process main loop is less cluttered. Which looks unnecessary in
this simple example but will reduce headaches in a more complex one
(e.g. a state machine with 50 states).

Don't worry about "procedure call overhead" - if you're doing it right,
the "call overhead" synthesises away to nothing.

More than that; one consequence of the restrictions on functions is that
very often, the entire function body synthesises away to nothing! A good
example is a function involving floating point arithmetic, scaling, and
conversion to integer, assigned to an array of constants to generate a
lookup table (e.g. of square roots).

- Brian
 
utauta wrote:

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
 
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.
 

Welcome to EDABoard.com

Sponsor

Back
Top