Synthesis of multiple wait statements per VHDL-200X

Discussion in 'VHDL' started by Colin Beighley, Jul 13, 2011.

  1. 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
    Colin Beighley, Jul 13, 2011
    #1
    1. Advertising

  2. Colin Beighley

    logic_guy Guest

    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
    logic_guy, Jul 14, 2011
    #2
    1. Advertising

  3. On Jul 13, 9:44 pm, "logic_guy" <> wrote:
    > 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.
    Colin Beighley, Jul 14, 2011
    #3
  4. Colin Beighley

    julianm

    Joined:
    Jul 14, 2011
    Messages:
    2
    Location:
    Sydney, Australia
    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
    julianm, Jul 14, 2011
    #4
  5. On 2011-07-13, Colin Beighley <> wrote:
    > 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
    Andreas Ehliar, Jul 14, 2011
    #5
  6. Colin Beighley

    logic_guy Guest

    "Colin Beighley" <> wrote in message
    news:...
    On Jul 13, 9:44 pm, "logic_guy" <> wrote:
    > 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
    logic_guy, Jul 15, 2011
    #6
  7. On Jul 15, 7:44 am, "logic_guy" <> wrote:
    > "Colin Beighley" <> wrote in message
    >
    > news:...
    > On Jul 13, 9:44 pm, "logic_guy" <> wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > 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


    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?
    Colin Beighley, Jul 15, 2011
    #7
  8. On Jul 15, 10:23 am, Colin Beighley <> wrote:
    > On Jul 15, 7:44 am, "logic_guy" <> wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > "Colin Beighley" <> wrote in message

    >
    > >news:...
    > > On Jul 13, 9:44 pm, "logic_guy" <> wrote:

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

    >
    > 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
    Colin Beighley, Jul 15, 2011
    #8
  9. Colin Beighley

    KJ Guest

    On Jul 15, 1:23 pm, Colin Beighley <> wrote:
    >
    > 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;
    KJ, Jul 15, 2011
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. walala
    Replies:
    4
    Views:
    1,172
    Technology Consultant
    Sep 9, 2003
  2. Ivan C.
    Replies:
    4
    Views:
    919
    David Bishop
    Nov 21, 2004
  3. Replies:
    6
    Views:
    1,906
    Divyang M
    Dec 14, 2004
  4. Replies:
    2
    Views:
    523
  5. Replies:
    6
    Views:
    845
Loading...

Share This Page