Estoy tratando de escribir una máquina de estado muy simple que implemente un bloqueo combinado.
El código es: Switch1 -> Switch2 -> Switch3 -> Switch4
Me doy cuenta de que es Switch 7, 6, 5, 4 en consecuencia en el código.
Si no se hace en ese orden, da el estado de error (incorrecto).
El problema que tengo es que aunque state
es state_start
(como lo veo en los LED) no cambiará state_1_right
y en su lugar simplemente bombeará el archivo error_state
. Sé que entra en esa declaración if porque cambié a else
y state <= "00001010";
muestra eso.
¿Qué estoy haciendo mal? No veo ningún error en mi lógica (a menos que haya algún cambio de rebote extraño).
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 la sugerencia de un reloj. Tuve que agregar algo de lógica adicional en las declaraciones if ya que el reloj recorre el bloque de casos rápidamente y el estado podría permanecer 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;
La otra respuesta es correcta acerca de necesitar un reloj.
Pero ignore el ejemplo de dos procesos al que se vinculó: busque en los lugares habituales "máquina de estado de proceso único VHDL" para obtener una mejor solución.
http://www.openhdl.com/vhdl/664-vhdl-tip-single-process-vhdl-state-machine-design.html para uno.
Quizás necesite un reloj para sincronizar los cambios de estado.
Podría ser un cambio de rebote, pero si el primero estuviera rebotando, parece que volvería a start_state, no a state_error, creo. ¿Estás usando interruptores físicos?
Reimprimo el código de ejemplo de aquí http://esd.cs.ucr.edu/labs/tutorial/fsm.vhd como ejemplo de sincronización con el reloj para los cambios de estado.
-----------------------------------------------------
-- 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;
-----------------------------------------------------
geométrico
multinivel