I am trying to write a very simple state machine that implements a combinational lock.
The code is: Switch1 -> Switch2 -> Switch3 -> Switch4
I realize that it is Switch 7, 6, 5, 4 accordingly in the code.
If it is not done in that order then it gives the error(incorrect) state.
The problem I am having is that even though state is state_start (as I see it on the LEDs) it will not change to state_1_right and instead will just pump out the error_state. I know it does go into that if statement because I changed the else to state <= "00001010"; and it displays that.
What am I doing wrong? I do not see any error in my logic (unless there is some weird switch bounce).
Here is the code I am trying now:
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;
Thank you to Brian Drummond for finding the error in my logic and suggestion of a clock. I had to add some extra logic in the if statements since the clock cycles through the case block rapidly and the state could stay the same.
Here is the updated code that solves the issue:
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;

