State Machine utilisant Case obtient un résultat inattendu

MLM

State Machine utilisant Case obtient un résultat inattendu


J’essaie d’écrire une machine d’état très simple qui implémente un verrou combinatoire.

Le code est: Switch1 -> Switch2 -> Switch3 -> Switch4

Je me rends compte que c’est le commutateur 7, 6, 5, 4 en conséquence dans le code.

Si cela n’est pas fait dans cet ordre, cela donne l’état d’erreur (incorrect).

Le problème que j’ai est que même si stateest state_start(comme je le vois sur les LED) , il ne changera pas à state_1_rightet au lieu pompera juste le error_state. Je sais que cela entre dans cette instruction if parce que j’ai changé le elseen state <= "00001010";et il l’affiche.

Qu’est-ce que je fais mal? Je ne vois aucune erreur dans ma logique (sauf s’il y a un rebond de commutateur étrange).

Voici le code que j’essaie maintenant:

entity CombinationLockFSM is
    Port(
        Switches: in std_logic_vector(7 downto 0);
        LEDs: out std_logic_vector(7 downto 0)
    );
end CombinationLockFSM;

architecture Behavioral of CombinationLockFSM is
    constant state_start: std_logic_vector(7 downto 0) := "10000000";
    constant state_1_right: std_logic_vector(7 downto 0) := "01000000";
    constant state_2_right: std_logic_vector(7 downto 0) := "00100000";
    constant state_3_right: std_logic_vector(7 downto 0) := "00010000";
    constant state_error: std_logic_vector(7 downto 0) := "00001111";

    signal state: std_logic_vector(7 downto 0) := (others => '0');
begin

    LEDs <= state;

    process(Switches)
    begin
        case Switches is
            when "00000000" => 
                state <= state_start;
            when "10000000" => 
                if state = state_start then
                    state <= state_1_right;
                else
                    state <= state_error;
                end if;
            when "11000000" => 
                if state = state_1_right then
                    state <= state_2_right;
                else
                    state <= state_error;
                end if;
            when "11100000" => 
                if state = state_2_right then
                    state <= state_3_right;
                else
                    state <= state_error;
                end if;
            when "11110000" => 
                if state = state_3_right then
                    state <= "11110000";
                else
                    state <= state_error;
                end if;


            when others =>
                state <= state_error;
        end case;

    end process;

end Behavioral;

Merci à Brian Drummond d’ avoir trouvé l’erreur dans ma logique et la suggestion d’une horloge. J’ai dû ajouter une logique supplémentaire dans les instructions if, car l’horloge parcourt rapidement le bloc de cas et l’état pourrait rester le même.

Voici le code mis à jour qui résout le problème:

entity CombinationLockFSM is
    Port(
        mclk: in std_logic;
        sw: in std_logic_vector(7 downto 0);
        Led: out std_logic_vector(7 downto 0)
    );
end CombinationLockFSM;

architecture Behavioral of CombinationLockFSM is
    constant state_start: std_logic_vector(7 downto 0) := "10000000";
    constant state_1_right: std_logic_vector(7 downto 0) := "01000000";
    constant state_2_right: std_logic_vector(7 downto 0) := "00100000";
    constant state_3_right: std_logic_vector(7 downto 0) := "00010000";
    constant state_4_right: std_logic_vector(7 downto 0) := "11110000";
    constant state_error: std_logic_vector(7 downto 0) := "00001111";

    signal state: std_logic_vector(7 downto 0) := (others => '0');
begin

    Led <= state;

    process(mclk)
    begin
        if rising_edge(mclk) then
            case sw is
                when "00000000" => 
                    state <= state_start;
                when "10000000" => 
                    if state = state_start or state = state_1_right then
                        state <= state_1_right;
                    else
                        state <= state_error;
                    end if;
                when "11000000" => 
                    if state = state_1_right or state = state_2_right then
                        state <= state_2_right;
                    else
                        state <= state_error;
                    end if;
                when "11100000" => 
                    if state = state_2_right or state = state_3_right then
                        state <= state_3_right;
                    else
                        state <= state_error;
                    end if;
                when "11110000" => 
                    if state = state_3_right or state = state_4_right then
                        state <= state_4_right;
                    else
                        state <= state_error;
                    end if;


                when others =>
                    state <= state_error;
            end case;
        end if;

    end process;

end Behavioral;
geometrikal

Comment connectez-vous les LED? Longue vue, mais peut-être que tout est inversé, donc par exemple si les LED indiquent 10000000, c’est en fait 01111111

MLM

@geometrikal LEDs est très bien et même si c’était à l’envers l’erreur est de 4 lumières d’affilée donc vous ne pouvez pas vraiment le gâcher.

Réponses


 Brian Drummond

L’autre réponse est correcte sur le besoin d’une horloge.

Mais ignorez l’exemple à deux processus auquel il est lié: recherchez dans les endroits habituels une « machine d’état à processus unique VHDL » pour une meilleure solution.

http://www.openhdl.com/vhdl/664-vhdl-tip-single-process-vhdl-state-machine-design.html
pour un.

MLM

J’ai ajouté une horloge et j’ai mis la déclaration de rehaussement autour de mon cas, mais il n’y a aucun changement.

geometrikal

vous n’auriez pas besoin de commutateurs dans sa propre instruction de processus, sinon il passerait directement à l’état d’erreur.

Brian Drummond

@MLM: (1) et « clk » est-il la seule chose dans la liste de sensibilité? ça devrait être. (2) Bug dans votre logique: après avoir atteint l’état 1 avec le modèle de commutateur correct, vous devez y rester jusqu’à ce que les commutateurs changent. Compte tenu de cet indice, il est facile de changer l’expression « si ». Il en va de même pour les autres États …

MLM

@BrianDrummond Je l’ai essayé avec juste le clk dans la liste de sensibilité et il n’y a aucun changement. Vous restez sur state_1 jusqu’à ce que vous vous trompiez ou que vous passiez à state_2. Bien que je ne puisse même pas arriver à state_1. Je ne suis même pas sûr d’avoir besoin d’une horloge …

Brian Drummond

Simulez-le. La meilleure façon de voir ce qu’il fait vraiment … Il existe plusieurs simulateurs gratuits, y compris ghdl.


 geometrikal

Vous avez peut-être besoin d’une horloge pour synchroniser les changements d’état.

Cela pourrait être un rebond de commutateur, mais si le premier rebondissait, il semblerait que cela reviendrait à start_state et non à state_error, je pense. Utilisez-vous des commutateurs physiques?

Je réimprime un exemple de code à partir d’ici http://esd.cs.ucr.edu/labs/tutorial/fsm.vhd par exemple de synchronisation sur l’horloge pour les changements d’état.

-----------------------------------------------------
-- VHDL FSM (Finite State Machine) modeling
-- (ESD book Figure 2.7)
-- by Weijun Zhang, 04/2001
--
-- FSM model consists of two concurrent processes
-- state_reg and comb_logic
-- we use case statement to describe the state 
-- transistion. All the inputs and signals are
-- put into the process sensitive list.  
-----------------------------------------------------

library ieee ;
use ieee.std_logic_1164.all;

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

entity seq_design is
port(   a:      in std_logic;
    clock:      in std_logic;
    reset:      in std_logic;
    x:      out std_logic
);
end seq_design;

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

architecture FSM of seq_design is

    -- define the states of FSM model

    type state_type is (S0, S1, S2, S3);
    signal next_state, current_state: state_type;

begin

    -- cocurrent process#1: state registers
    state_reg: process(clock, reset)
    begin

    if (reset='1') then
            current_state <= S0;
    elsif (clock'event and clock='1') then
        current_state <= next_state;
    end if;

    end process;                          

    -- cocurrent process#2: combinational logic
    comb_logic: process(current_state, a)
    begin

    -- use case statement to show the 
    -- state transistion

    case current_state is

        when S0 =>  x <= '0';
            if a='0' then
                next_state <= S0;
            elsif a ='1' then
                next_state <= S1;
            end if;

        when S1 =>  x <= '0';
            if a='0' then 
                next_state <= S1;
            elsif a='1' then 
                next_state <= S2;
            end if;

        when S2 =>  x <= '0';
            if a='0' then
                next_state <= S2;
            elsif a='1' then
                next_state <= S3;
            end if;

        when S3 =>  x <= '1';
            if a='0' then 
                next_state <= S3;
            elsif a='1' then 
                next_state <= S0;
            end if;

        when others =>
            x <= '0';
            next_state <= S0;

    end case;

    end process;

end FSM;

-----------------------------------------------------
MLM

J’utilise des commutateurs physiques sur la carte. J’examinerai l’ajout d’une horloge de synchronisation, mais je ne sais pas pourquoi vous en auriez besoin dans cette situation.

MLM

J’ai ajouté une horloge et j’ai mis la déclaration de rehaussement autour de mon cas, mais il n’y a aucun changement.

 

Case:, inattendu, Machine, obtient, résultat, State, un, utilisant

 

google

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *