Estoy intentando escribir una máquina de estado muy simple que implementa un bloqueo de combinación.
El código es: Switch1 - > Switch2 - > Switch3 - > Switch4
Me doy cuenta de que es el Switch 7, 6, 5, 4 en consecuencia en el código.
Si no se realiza en ese orden, da el estado de error (incorrecto).
El problema que tengo es que, a pesar de que state
es state_start
(como lo veo en los LED), no cambiará a state_1_right
y en su lugar solo bombeará error_state
. Sé que entra en esa declaración if porque cambié el else
a state <= "00001010";
y lo muestra.
¿Qué estoy haciendo mal? No veo ningún error en mi lógica (a menos que haya algún rebote extraño del interruptor).
Aquí está el código que estoy intentando ahora:
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;
Gracias a Brian Drummond por encontrar el error en mi lógica y sugerir un reloj. Tuve que agregar un poco de lógica adicional en las sentencias if, ya que el reloj recorre rápidamente el bloque de casos y el estado podría seguir igual.
Aquí está el código actualizado que resuelve el problema:
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;