Forum Discussion

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

Modling a State Machine in VHDL ... with trouble memorizing variables

Hi,

I'm trying to make a state-machine wich remains in one of the states until one of the variables goes from zero to one three times. I assume it should be quite simple, but after some days I can't succeed. I have tried to save the number of changes both in variables and signals, but no result.

To make a simple test, I just made one simple state-machine with two states. It remains on the first one till the signal_to_monitor =1. Then it goes to second state and the idea is to get out of that state after three transitions 0-1 of the signal we are monitoring.

The code used is:

architecture ctrl_machine of machine is

type possible_states is (first_st,second_st);

signal next_state,state: possibles_states;

signal accumulate : integer range 0 to 5;

begin

RefreshState : process (clk,reset)

begin

if (reset='1') then

estat <= idle;

elsif (clk'event and clk='1') then

estat <= seguent_estat;

end if;

end process RefreshState;

NextState : process (state,signal_to_monitor)

begin

next_state <= state;

case state is

when first_st =>

if (signal_to_monitor ='1') then

next_state <= second_st;

else

accumulate <=0;

next_state <= first_st;

end if;

when second_st =>

next_state <= buidant_calaix;

if (signal_to_monitor = '1') then

accumulate <=accumulate +1;

end if;

if (accumulate = 3) then

next_state<=first_state;

end if;

end case;

end process;

output_proc : process (state)

begin

case (state) is

when first_st => output <='0';

when second_st => output <='1';

end case;

end process ;

(...)

I assume it should be a conceptual error but can't find it! The signal (accumulate) gets mad and begins to flip-flop without control (suppose due to accumulate=accumulate+1 but don't know how to accomplish this simple goal!).

Any ideas?

Thanks!!!

Carlos

6 Replies

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

    Your code is unreadable, because you're mixing original spanish and translated signal and state names. Please post either your original or another consistent code.

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

    Sorry! I tried to translate the code for a better understanding. I resend it with the necessary corrections (and in fact the full code I'm working with). I attach also the simulation result (why does the accumulate signal - and so the output - go from 0 to 1 without control????):

    library ieee;

    use ieee.std_logic_1164.all;

    use ieee.std_logic_arith.all;

    use ieee.std_logic_unsigned.all;

    entity Counter is

    -- counts three ticks of the signal signal_to_monitor -or thats what I wish

    -- the output signal is integer just to show the evolution in the waveform simulator

    port(

    clk: in std_logic;

    reset,signal_to_monitor: in std_logic;

    output: out integer

    );

    end Counter;

    architecture Behavioral of Counter is

    constant NUM_TICKS : integer := 3;

    type possible_states is (first_st,second_st);

    signal next_state,state: possible_states;

    signal accumulate: integer range 0 to 2;

    begin

    RefreshState : process (clk,reset)

    begin

    if (reset='1') then

    state <= first_st;

    elsif (clk'event and clk='1') then

    state <= next_state;

    end if;

    end process RefreshState;

    process (state,signal_to_monitor)

    begin

    next_state <= state;

    case state is

    when first_st =>

    -- no ticks yet

    if (signal_to_monitor ='1') then

    -- count one tick and go to the 'counting' state

    accumulate<=accumulate+1;

    next_state <= second_st;

    else

    accumulate <=0;

    next_state <= first_st;

    end if;

    when second_st =>

    -- if the signal goes to one again, count one more till you arrive to NUM_TICKS

    -- then fall back to first_state

    if (signal_to_monitor = '1') then

    accumulate <=accumulate +1;

    end if;

    if (accumulate = NUM_TICKS) then

    --

    next_state<=first_st;

    end if;

    end case;

    -- just to have a look at the waveform I generate the output here

    output <= accumulate;

    end process;

    process (state)

    begin

    --do nothing as the output has been generated just for debugging purposes

    end process ;

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

    You can't place a counter in the combinational process. The output gets simply unpredictable this way. The accumulator must be assigned under control of an edge sensitive condition, similar to the state variable.

    accumulate<=accumulate+1;

    Also I don't see how the state machine can work with just two states.

    I have difficulties to guess the exact intended behaviour. I suggest to sketch a waveform and use a different state for each step.

    Care must be taken, if signal_to_monitor is unrelated to the system clock domain, e.g. an external signal. In this case, it's necessary to synchronize it by a clocked register and make the register output control the state machine.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks. I did not know I could not use it inside the combinational process. But - as far as I have seen - I can not do it either making a control like:

    if (signal_to_monitor'event and signal_to_monitor='1') then accumulate<=accumulate+1 ;end if;

    (I include a sample code at the end)

    The intended behaviour I tried was just to 'stay in one state till the signal makes a number of changes (three in the example)'. It has no other application. So, I wanted to stay in the first state till the signal goes from 0 to 1. Then stay in second_st till 3 changes have been made in the signal (from 0 to 1). Once that happens (accumulate=3), return to first state and reset accumulate.

    How can I do this? (the only solution is creating additional states like one_change, two_changes and three_changes? ) (if so, what if I needed 50 changes??? :( )

    Thanks!

    --

    process (state,signal_to_monitor)

    begin

    next_state <= state;

    if (signal_to_monitor'event and signal_to_monitor='1') then accumulate<=accumulate+1 ;end if;

    case state is

    when first_st =>

    -- no ticks yet

    if ( signal_to_monitor ='1') then

    -- count one tick and go to the 'counting' state

    next_state <= second_st;

    else

    accumulate <=0;

    next_state <= first_st;

    end if;

    when second_st =>

    -- if the signal goes to one again, count one more till you arrive to NUM_TICKS

    -- then fall back to first_state

    if (accumulate = NUM_TICKS) then

    --

    next_state<=first_st;

    end if;

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

    Apart from the "how to count" problem, you'll need at least two "counting" states that reflects a high respectively low input state. Then the transition to the counting_high state can also advance the counter. The counter would be incremented under rising_edge(clk).

    Personally I prefer a more compact form of a state machine, that has only one, edge sensitive process. You can easily add things like the said counting action to it.