Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

headache with 2 process state machine

Hi everyone,

below is the code from a state machine. It is a intended emulate one part of a system to test the other part, so all it is doing is sending rows and columns of data (and looking for some special cases while its at it) to the system downstream

nearly all of the signals are reported as having unsafe behaviour, and, although it builds, it doesn't work

(as well as unsafe behavior, it is throwing up inferred latches all over the place)

I think this is probably relatively elementary to those who are wiser than me in this field,

Am I trying to do too much in each of the states, should I be creating some other code to do the donkey work?

Hope one of you can steer me back on right path- I think I have been here before, but was a simpler system

I have tried changing to a one process machine, but that didn't especially help

Regards

Pete B

(code attached)

process (nReset,Clock50)

begin

if (nReset ='0') then

CurrentState <= InReset;

elsif (rising_edge (Clock50)) then

CurrentState <= NextState;

end if;

end process;

process (CurrentState)

begin

case CurrentState is

------------------------

when InReset =>

CurrentFreqBin<="00000";

TargetBin<="00000";

TargBinInt<=0;

index <= 0;

InterFrameDelay<="000000000000000000000000";

----------------------

NextState <= StartCol;

------------------------

------------------------

when StartCol =>

TargBinInt<=FreqTable(index);

--my_slv <= std_logic_vector(to_unsigned(my_integer, my_slv'length)); -- if

TargetBin <= std_logic_vector(to_unsigned(TargBinInt,5));

-----------------------

NextState <= WriteFreq;

------------------------

------------------------

when WriteFreq =>

FreqSlot<=CurrentFreqBin;

if (CurrentFreqBin=TargetBin) then

Amplitude<="11111111";

else

Amplitude<="00000000";

end if;

Strobe<='1';

----------------------

NextState <= StrobeOff;

------------------------

------------------------

when StrobeOff =>

Strobe<='0';

CurrentFreqBin<=CurrentFreqBin+1;

if (CurrentFreqBin="00000") then

NextState <= ColumnFinished;

else

NextState <= WriteFreq;

end if;

------------------------

------------------------

when ColumnFinished =>

ColumnDone<='1';

index<=index+1;

NextState <= ColFinStrobeOff;

------------------------

------------------------

when ColFinStrobeOff =>

if (index = 256) then

NextState <= AllDone;

InterFrameDelay <="000001111010000100100000";

else

NextState <=StartCol;

ColumnDone<='0';

end if;

------------------------

------------------------

when AllDone =>

ColumnDone<='1';

NextState <= AllDoneLoop;

------------------------

------------------------

when AllDoneLoop =>

ColumnDone<='0';

InterFrameDelay <=InterFrameDelay-1;

if (InterFrameDelay < "000000000000000000000010") then

NextState <= AllDone;

else

NextState <= AllDoneLoop;

end if;

------------------------

end case;

end process;

7 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The latch issue is brought up by assigning other signals than NextState in the asynchronous process, and assigning them only in some of the states. Besides generating a lot of warnings, you can be rather sure that constructs like "index<=index+1;" will never work based on latches.

    A simple solution, although not usually suggested in the text books is to change the design to a single synchronous process state machine, simply merging both processes.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    you might want to restrict your async process for only state transition. for the rest of the stuffs, write them under clocked process.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks to you both for replying,

    FvM - I had tried single process solution, but will revisit this, perhaps also moving some functionality outside

    jacklsw86 - this additional clocked process, would this be the same clock as drives the state changer (or, indeed, somewhat blasphemous, the falling edge of the same clock) or should it be something else altogether?

    thanks again for your help, will advise how I get on
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    you could write another process with the same clock edge.

    besides that, you might wanna look for more example codes to get familiar with other people's coding style.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi jacklsw and FvM

    so this is working (sufficiently for my purpose)

    I went down jacklsw route (mostly because in my post I did ask

    'Am I trying to do too much in each of the states, should I be creating some other code to do the donkey work?' :rolleyes: s

    but I do think FvM is (part of) the more formal way to write this sort of stuff,

    So I guess, my working code (below-- yes, is still a bit scruffy, but its not getting released into the wild, its my test) might be called a three process state machine? Or is it really two process, as the third is doing work rather than managing?

    Any comments on the code are welcome, and indeed gratefully recieved, if you have the time to look,

    (note added InterFrameDelay to sensitivity list - Im pretty sure that just a simulation thing, and it would work 'in the real world' without it

    Thanks so much (again)

    Pete B

    begin

    process (nReset,Clock50)

    begin

    if (nReset ='0') then

    CurrentState <= InReset;

    elsif (rising_edge (Clock50)) then

    CurrentState <= NextState;

    end if;

    end process;

    process (CurrentState,InterFrameDelay)

    begin

    case CurrentState is

    when InReset =>

    NextState <= StartCol;

    when StartCol =>

    NextState <= WriteFreq;

    when WriteFreq =>

    NextState <= StrobeOff;

    when StrobeOff =>

    if (CurrentFreqBin="00000") then

    NextState <= ColumnFinished;

    else

    NextState <= WriteFreq;

    end if;

    when ColumnFinished =>

    NextState <= ColFinStrobeOff;

    when ColFinStrobeOff =>

    if (index = 256) then

    NextState <= AllDone;

    else

    NextState <=StartCol;

    end if;

    when AllDone =>

    NextState <= AllDoneLoop;

    when AllDoneLoop =>

    if interFrameDelay<"000000000000000000000010")

    then

    NextState <= AllDone;

    else

    NextState <= AllDoneLoop;

    end if;

    end case;

    end process;

    ---------------------------------------------------------------------------

    process (CurrentState,Clock50)

    begin

    if (Rising_edge (Clock50)) then

    case CurrentState is

    when InReset =>

    CurrentFreqBin<="00000";

    TargetBin<="00000";

    TargBinInt<=0;

    index <= 0;

    InterFrameDelay<="000000000000000000000000";

    ------------------------

    when StartCol =>

    TargBinInt<=FreqTable(index);

    TargetBin <= std_logic_vector(to_unsigned(TargBinInt,5));

    -----------------------

    when WriteFreq =>

    FreqSlot<=CurrentFreqBin;

    if (CurrentFreqBin=TargetBin) then

    Amplitude<="11111111";

    else

    Amplitude<="00000000";

    end if;

    Strobe<='1';

    ----------------------

    when StrobeOff =>

    Strobe<='0';

    CurrentFreqBin<=CurrentFreqBin+1;

    ------------------------

    when ColumnFinished =>

    ColumnDone<='1';

    index<=index+1;

    ------------------------

    when ColFinStrobeOff =>

    if (index = 256) then

    ColumnDone<='1';

    else

    ColumnDone<='0';

    end if;

    ------------------------

    when AllDone =>

    InterFrameDelay <="000000000000000000100000";

    ColumnDone<='1';

    ------------------------

    when AllDoneLoop =>

    ColumnDone<='0';

    InterFrameDelay <=InterFrameDelay-'1';

    -------------

    end case;

    end if;

    end process;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks,

    looks like our postings crossed!

    but I did use same clock edge

    Thanks again
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    your asynchronous process' sensitivity list isn't complete either. you got to put all signals which affects the outcome in the sensitivity list, usually the signals in if-else statement.

    for synchronous process, usually it is sufficient to put just clock signal in the sensitivity list. unless you want to add some async signal in it.

    eg. registers with async reset

    
    process (clk, reset)
    if (reset = '1') then
    ...
    elsif rising_edge(clk)
    ..
    end process;