I am trying to create a FSM in VHDL that should act as the control for starting an engine. The engine should start when buttons A and B are pressed in the correct order, A-B-B, U1=1. When pressed in incorrect order U2=1. The reset button should be pressed when incorrect order occurs and then correct order can be entered.
The problem I am running into is that one input during multiple clock cycles is read as multiple inputs. I feel like I am maybe misunderstanding something. How do I make it so that only one input is read? I have written the following:
entity engine is
Port ( ab : in STD_LOGIC_VECTOR(1 downto 0);
clock : in STD_LOGIC;
ut : out STD_LOGIC_VECTOR(1 downto 0);
reset : in STD_LOGIC);
end engine;
architecture Behavioral of engine is
type state_type is (S0, S1, S2, S3, S4);
signal state, next_state : state_type;
begin
process(clock, reset)
begin
if reset = '1' then
next_state <= S0;
elsif rising_edge(clock) then
state <= next_state;
case state is
when S0 =>
if ab = "10" then -- press A
next_state <= S1;
end if;
when S1 =>
if ab = "01" then -- press B
next_state <= S2;
end if;
when S2 =>
if ab = "01" then -- press B
next_state <= S3;
elsif ab = "10" then
next_state <= S4;
end if;
when S3 =>
next_state <= S3;
when S4 =>
next_state <= S4;
end case;
end if;
end process;
process(state)
begin
case state is
when S0 =>
ut <= "00";
when S1 =>
ut <= "00";
when S2 =>
ut <= "00";
when S3 =>
ut <= "10";
when S4 =>
ut <= "01";
end case;
end process;
end Behavioral;
And the test bench:
ENTITY egninetest IS
END egninetest;
ARCHITECTURE behavior OF egninetest IS
COMPONENT engine
PORT(
ab : IN std_logic_vector(1 downto 0);
clock : IN std_logic;
ut : OUT std_logic_vector(1 downto 0);
reset : IN std_logic
);
END COMPONENT;
--Inputs
signal ab : std_logic_vector(1 downto 0) := (others => '0');
signal clock : std_logic := '0';
signal reset : std_logic := '0';
--Outputs
signal ut : std_logic_vector(1 downto 0);
-- Clock period definitions
constant clock_period : time := 15 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: engine PORT MAP (
ab => ab,
clock => clock,
ut => ut,
reset => reset
);
-- Clock process definitions
clock_process :process
begin
clock <= '0';
wait for clock_period;
clock <= '1';
wait for clock_period;
end process;
-- Stimulus process
stim_proc: process
begin
reset <= '1';
wait for 40 ns;
reset <= '0';
ab <= "01"; -- wrong input
wait for 55 ns;
reset <= '1'; -- test reset function
wait for 40 ns;
reset <= '0';
ab <= "10"; -- try correct input
wait for 40 ns;
ab <= "01";
wait;
end process;
END;
Please ask if something is unclear, I know I might not be making sense.
Add intermediate states to your state machine that represent the states between the key presses.
For example (with your current names of states):
This way A and B can be pressed over many clock cycles without advancing the state.