Synthesis of multiple wait statements per VHDL-200X

C

Colin Beighley

Hello,

I'm trying to write a state machine in VHDL using code like the below,
so that I can use for loops in the state machine. This code implements
an asynchronous reset. However, in ISE the synthesizer gives me the
error :

ERROR:HDLCompiler:609 : Multiple signals in event expression is not
synthesizable.

============CODE===============

state_machine : process
begin
state_machine_loop : loop

wait until (rising_edge(CLOCK) or RST = '1');
if RST = '1' then
do_reset_stuff;
next state_machine_loop;
end if;

internal_loop : for i in 0 to SOME_VALUE loop
do_internal_loop_stuff;
wait until (rising_edge(CLOCK) or RST = '1');
if RST = '1' then
do_reset_stuff;
next state_machine_loop;
end if;
end loop;

end loop;
end process;

============END CODE===========

So I figured, okay, I'll make a state machine with a synchronous
reset, as shown below. However, now I get this error:

ERROR:HDLCompiler:926 : Multiple wait statements in one process are
not supported in this case.

============CODE===============

state_machine : process
begin
state_machine_loop : loop

wait until rising_edge(CLOCK);
if RST = '1' then
do_reset_stuff;
next state_machine_loop;
end if;

internal_loop : for i in 0 to SOME_VALUE loop
do_internal_loop_stuff;
wait until rising_edge(CLOCK);
if RST = '1' then
do_reset_stuff;
next state_machine_loop;
end if;
end loop;

end loop;
end process

============END CODE===========

I'm reading in my copy of The Designers Guide to VHDL : Third Edition
that these state machine coding styles ARE part of the IEEE 1076.6-
VHDL-200X synthesis standard. I posted this on the Xilinx forum and
was told the same thing that the tool told me : multiple wait
statements are not supported for synthesis. Are there any other tools
that will synthesize this or a similar coding style? I mean, in theory
there is nothing un-synthesizable about this code.

Thanks,
Colin
 
L

logic_guy

Do you really need a loop? Maybe something like this will do what you
need:

state_machine : PROCESS
variable do_internal_loop : boolean;
BEGIN
WAIT until rising_edge(CLOCK);
IF RST = '1' THEN
do_reset_stuff;
ELSE
IF do_internal_loop THEN
do_internal_loop_stuff;
IF some_end_condition THEN
do_internal_loop := false;
END IF;
ELSE
do_non_internal_loop_stuff;
IF some_start_condition THEN
do_internal_loop := true;
END IF;
END IF;
END IF;
END PROCESS;

The process will execute once per clock cycle. Various conditional
statements decide what to do on each cycle.

A process with one WAIT statement as I have shown is definitely
synthesizable.

Charles Bailey
 
C

Colin Beighley

Do you really need a loop?  Maybe something like this will do what you
need:

state_machine : PROCESS
variable do_internal_loop : boolean;
BEGIN
    WAIT until rising_edge(CLOCK);
    IF RST = '1' THEN
      do_reset_stuff;
    ELSE
      IF do_internal_loop THEN
        do_internal_loop_stuff;
        IF some_end_condition THEN
          do_internal_loop := false;
        END IF;
      ELSE
        do_non_internal_loop_stuff;
        IF some_start_condition THEN
          do_internal_loop := true;
        END IF;
      END IF;
    END IF;
END PROCESS;

The process will execute once per clock cycle.  Various conditional
statements decide what to do on each cycle.

A process with one WAIT statement as I have shown is definitely
synthesizable.

Charles Bailey

Unfortunately the example I provided is pretty boiled down. In reality
I need three nested for loops, which starts to get hairy.
 
Joined
Jul 14, 2011
Messages
2
Reaction score
0
It looks like the error stems from your multiple waits on the reset signal within the single process. A process can only be evaluated on a change in one of the signals in its sensitivity list. It is redundant to have two 'wait until' statements. Try sticking a single reset statement at the start of the process. That way it is evaluated first on each change of the clock. Logic_guys example was pretty good. Just have the nested for loops within each if loop. Or, make it clearer with a case statement :)

Hope this helped.


when
 
A

Andreas Ehliar

I'm reading in my copy of The Designers Guide to VHDL : Third Edition
that these state machine coding styles ARE part of the IEEE 1076.6-
VHDL-200X synthesis standard. I posted this on the Xilinx forum and
was told the same thing that the tool told me : multiple wait
statements are not supported for synthesis. Are there any other tools
that will synthesize this or a similar coding style? I mean, in theory
there is nothing un-synthesizable about this code.

I've been able to synthesize similar state machines in Precision.

However, I have not yet jumped ship to this style of FSM design yet.
The reason being that it is not possible to do Mealy style state
machines in it (AFAIK). Another is that it is quite tedious to handle
the reset signal.

This posting also implies that Synplify can handle such state machines
but I haven't tested this myself: http://www.parallelpoints.com/node/69

regards
/Andreas
 
L

logic_guy

Do you really need a loop? Maybe something like this will do what you
need:

state_machine : PROCESS
variable do_internal_loop : boolean;
BEGIN
WAIT until rising_edge(CLOCK);
IF RST = '1' THEN
do_reset_stuff;
ELSE
IF do_internal_loop THEN
do_internal_loop_stuff;
IF some_end_condition THEN
do_internal_loop := false;
END IF;
ELSE
do_non_internal_loop_stuff;
IF some_start_condition THEN
do_internal_loop := true;
END IF;
END IF;
END IF;
END PROCESS;

The process will execute once per clock cycle. Various conditional
statements decide what to do on each cycle.

A process with one WAIT statement as I have shown is definitely
synthesizable.

Charles Bailey
Unfortunately the example I provided is pretty boiled down. In reality
I need three nested for loops, which starts to get hairy.

LOOPs in a clocked process are normally used when you need to operate on
multiple elements of an array in a single clock cycle. If the
operations span multiple clock cycles then you need to define your own
counter variable to keep track of what happens on each clock cycle. By
expanding on the example I've show, you should be able to do anything
you want, and do it with just one WAIT statement.

Charles Bailey
 
C

Colin Beighley

LOOPs in a clocked process are normally used when you need to operate on
multiple elements of an array in a single clock cycle.  If the
operations span multiple clock cycles then you need to define your own
counter variable to keep track of what happens on each clock cycle.  By
expanding on the example I've show, you should be able to do anything
you want, and do it with just one WAIT statement.

Charles Bailey

Yes, you can use one WAIT statement and synthesize your state machine
thus, but you don't gain anything over the : if rst elsif
rising_edge(clk) end if : model. However, the benefit of using the
WAIT UNTIL RISING_EDGE(CLK) at various places within your process is
that you can describe a state machine in a much more abstract, easily
understood manner. It's quite a mystery to me that HDL's are still so
primitive in some respects - there simply MUST be a better way to do,
for instance, nested for loops than keeping track of the variables
with the two-process case statement.

I've wondered if FPGA bitstreams were not proprietary would there be
open-source toolchains that would spring forth and better HDL's as a
result?
 
C

Colin Beighley

Yes, you can use one WAIT statement and synthesize your state machine
thus, but you don't gain anything over the : if rst elsif
rising_edge(clk) end if : model. However, the benefit of using the
WAIT UNTIL RISING_EDGE(CLK) at various places within your process is
that you can describe a state machine in a much more abstract, easily
understood manner. It's quite a mystery to me that HDL's are still so
primitive in some respects - there simply MUST be a better way to do,
for instance, nested for loops than keeping track of the variables
with the two-process case statement.

I've wondered if FPGA bitstreams were not proprietary would there be
open-source toolchains that would spring forth and better HDL's as a
result?

P.S. : gcc, gdb, and a number of microcontrollers spring to mind as an
example
 
K

KJ

Yes, you can use one WAIT statement and synthesize your state machine
thus, but you don't gain anything over the : if rst elsif
rising_edge(clk) end if : model.

It's not clear to me just what you think you gain with your model
either. There's nothing inherently wrong about being different, but
different is not neccessarily better (assuming that's what you mean by
'don't gain anything...')
However, the benefit of using the
WAIT UNTIL RISING_EDGE(CLK) at various places within your process is
that you can describe a state machine in a much more abstract, easily
understood manner.

I disagree, see (1) at the end of this post for how I manipulated your
original process into a form that is synthesizable and at least as
clear as your process. Repeating things over and over again is error
prone which is far worse than what you think may be 'easily
understood'. For example, if you start having several conditions
tacked on, and then you change those over time as you develop the code
both of the following lines of code (separated by large amounts of
text) are 'easily understood', but are they both correct or did the
designer forget a condition?
wait until rising_edge(clock) and (this = '1') and (that /= 5) and
(moon = rising);
wait until rising_edge(clock) and (this = '1') and (moon = rising);
It's quite a mystery to me that HDL's are still so
primitive in some respects - there simply MUST be a better way to do,
for instance, nested for loops than keeping track of the variables

Keeping track of the variables boils down to the following.
Preferring one over the other simply says you like the looks of a
'for' statement rather than an 'if'...but that preference is up to
anyone to have and is simply cosmetic
for i in 0 to SOME_VALUE loop (your method)
if i <= SOME_VALUE then (currently synthesizable method)

The currently synthesizable method with the 'if' statement has some
baggage:
- Loop variable must be declared
- Loop variable increment is explicit

What you're proposing has some baggage:
- Global conditions (like checking that Reset = '1' and what to do
under that condition) must be physically repeated in the code...that
is best accomplished via copy/paste which is not good practice in
hardly any language
- More local condition checking gets problematic. By this I mean
conditions that are not quite as global as 'Reset = 1' but are not
specific to a single code branch. Now you're copying code in certain
areas. Again, copy/paste will be your friend but copy/paste is not
good practice.

with the two-process case statement.

Ummmm...nobody should be using two-process. Use a single clocked
process and a concurrent statement to pick up the unclocked outputs.

Kevin Jennings
----
(1) Synthesizable version of the process from your original post.
state_machine : process
variable i: integer range 0 to SOME_VALUE + 1;
begin
wait until (rising_edge(CLOCK) or RST = '1');
if RST = '1' then
do_reset_stuff;??
next state_machine_loop; --KJ: What do you mean here??
i := 0;
else
if i <= SOME_VALUE then
do_internal_loop_stuff;
i := i + 1;
end if;
end if;
end process;
 

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,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top