How to simulate a finite state machine in vhdl

71 views Asked by At

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.

1

There are 1 answers

0
the busybee On

Add intermediate states to your state machine that represent the states between the key presses.

For example (with your current names of states):

  • S0: wait for A to be pressed
  • S0_B: wait for A to be released
  • S1: wait for B to be pressed
  • S1_B: wait for B to be released
  • and so on...

This way A and B can be pressed over many clock cycles without advancing the state.