Search code examples
vhdlvivadofsm

FSM enters impossible state


I have a FSM consisting of 3 states: STATIC, UP and DOWN.

The FSM starts in the STATIC state and if I press the up arrow key, it will move to the UP state, thereafter returning to the STATIC state. Same thing for DOWN.

At first the FSM works well but suddenly after a random amount of key presses it will enter an unspecified state. The FSM consists of two processes:

type ALL_STATES is (STATIC, UP, DOWN);
signal STATE, NEXT_STATE: ALL_STATES;
signal posBarraYTOP, posBarraYBOT: std_logic_vector(11 downto 0);
signal movTeclado: std_logic_vector(1 downto 0);

-- ...
Keybd: keyboard port map (input, movTeclado); -- keyboard output
-- ...

bar_FSM_sincrono: process(CLK, RST) -- CLK is the FPGA's clock
begin
    if RST='1' then
        STATE <= STATIC;
    elsif (CLK'event and CLK = '1') then
        STATE <= NEXT_STATE; -- in each CLK cycle we move to the next state.
    end if;    
end process bar_FSM_sincrono;

bar_FSM_cambioest: process(STATE)
begin
    case STATE is
        when STATIC=> 
            seg <= "1001001";
            if (movTeclado = "01" and posBarraYTOP > 20) then
                NEXT_STATE <= UP;
            elsif (movTeclado = "10" and posBarraYBOT < 980) then
                NEXT_STATE <= DOWN;
            else
                NEXT_STATE <= STATIC;
            end if;
        when UP | DOWN =>
            NEXT_STATE <= STATIC;
            seg <= "1111110";
        when others =>
            NEXT_STATE <= STATIC;
            seg <= "0110111";
    end case;
end process bar_FSM_cambioest;

movTeclado is a 2-bit signal that shows when the user presses the up 01 or down 10 key. It's 00 if no key is pressed. movTeclado doesn't give me any problems.

posBarraYTOP and posBarraYBOT are two signals to describe a boundary, and these conditions are always met.

I use seg as a signal for the 7-segment display to debug and find out in what state the FSM is at. At first it always displays the STATIC seg, as it should since UP seg and DOWN seg are only displayed for one cycle. But then when the error happens it's when it starts displaying the others seg, as well as the STATIC seg. It's a back-and-forth between STATIC and others, which I don't understand since when STATE = STATIC, it should only transition to UP or DOWN.

Thank you for reading this far, does anyone know what's going on?


Solution

  • As other comments have suggested, you should never drive a signal from more than one process block. Personally I don't like writing state machines like this, with 2 process blocks, because I find it confusing.

    But regardless, your 2nd process block (the combinational one) should only be assigning NEXT_STATE, it should never make an assignment to STATE since that's taken care of by the first process block.