package AUTO_TYPES is type TVstup is (c0, c1, c2, c5); -- input: coins type TVystup is (c0, c1, c2); -- coins to be returned end AUTO_TYPES; -- ---------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use work.AUTO_TYPES.all; -- Moore Finite State Machine (output = f(state)) -- Coffee machine: accept coins 1,2,5 and produce coffee that costs 7$, return -- coins 0,1 entity Automaton is port ( mince : in TVstup; -- inserted coin CLK : in std_logic; -- clock ASYNCH_RESET : in std_logic; vrat : out TVystup; -- coin to be returned vydej_napoj : out boolean; -- coffee is ready otevreno : buffer std_logic; -- the coin input is opened hotovo : out std_logic); -- done end Automaton; architecture Automaton_body of Automaton is type TState is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, return2); -- states of the FSA type TOutputSignals is record -- Set of the output signals vrat : TVystup; -- coins to be returned vydej_napoj : boolean; -- coffe ready otevreno : std_logic; -- coins are accepted hotovo : std_logic; -- done end record; type TTransitionTable is array (TState, TVstup) of TState; -- next state table type TOutputTable is array (TState) of TOutputSignals; signal state : TState := s0; -- current state of the FSA signal next_state : TState := s0; -- the next state constant transitionTable : TTransitionTable := ( -- row = state, column = input -- inserted coin (mince) is -- 0 | 1 | 2 | 5 ( s0, s1, s2, s5 ), -- s0 ( s1, s2, s3, s6 ), -- s1 ( s2, s3, s4, s7 ), -- s2 ( s3, s4, s5, s8 ), -- s3 ( s4, s5, s6, s9 ), -- s4 ( s5, s6, s7, s10), -- s5 ( s6, s7, s8, s11), -- s6 -- >= 7 have been inserted -- the next state is independent of input, for no more coins are accepted ( s0, s0, s0, s0 ), -- s7 ( s0, s0, s0, s0 ), -- s8 ( s0, s0, s0, s0 ), -- s9 ( return2, return2, return2, return2 ), -- s10 ( return2, return2, return2, return2 ), -- s11 ( s0, s0, s0, s0 ) -- return2 ); constant outputTable : TOutputTable := ( -- row = state -- vrat -- | vydej_napoj -- | | otevreno -- | | | hotovo ( (c0, false, '1', '1' ) ), -- s0 ( (c0, false, '1', '0' ) ), -- s1 ( (c0, false, '1', '0' ) ), -- s2 ( (c0, false, '1', '0' ) ), -- s3 ( (c0, false, '1', '0' ) ), -- s4 ( (c0, false, '1', '0' ) ), -- s5 ( (c0, false, '1', '0' ) ), -- s6 -- >= 7 have been inserted ( (c0, true, '0', '0' ) ), -- s7 ( (c1, true, '0', '0' ) ), -- s8 ( (c2, true, '0', '0' ) ), -- s9 ( (c1, true, '0', '0' ) ), -- s10 & goto return2 ( (c2, true, '0', '0' ) ), -- s11 & goto return2 ( (c2, false, '0', '0' ) ) -- return2 ); begin -- Automaton_body -- purpose: Set the current state (next => current) or reset -- type : sequential -- inputs : CLK, ASYNCH_RESET -- outputs: state P_NextState : process (CLK, ASYNCH_RESET) begin -- process P_NextState if ASYNCH_RESET = '1' then -- asynchronous reset (active high) state <= s0; elsif CLK'event and CLK = '1' then -- rising clock edge state <= next_state; end if; end process P_NextState; -- purpose: Based on the current state, produce an output -- type : combinational -- inputs : State (it changes only when clock becomes to 1 or reset) -- outputs: vrat, vydej_napoj, otevreno, hotovo P_Output : process ( state ) begin -- process P_Output vrat <= outputTable( state ).vrat; vydej_napoj <= outputTable( state ).vydej_napoj; otevreno <= outputTable( state ).otevreno; hotovo <= outputTable( state ).hotovo; end process P_Output; -- purpose: Based on input the current state set a next state -- type : combinational -- inputs : state, mince -- outputs: next_state P_ProcessInput : process ( state, mince ) variable accepted_coin : TVstup := c0; -- either = mince or = c0 begin -- process P_ProcessInput -- Do not accept any coins if otevreno == 0: if otevreno = '1' then accepted_coin := mince; end if; next_state <= transitionTable( state, accepted_coin ); end process P_ProcessInput; end Automaton_body; -- ---------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use work.AUTO_TYPES.all; entity Tester_automaton is end Tester_automaton; architecture Tester_automaton_body of Tester_automaton is signal mince : TVstup; signal CLK : std_logic; signal ASYNCH_RESET : std_logic; signal otevreno, hotovo : std_logic; signal vrat : TVystup; signal vydej_napoj : boolean; component Automaton port ( mince : in TVstup; CLK : in std_logic; ASYNCH_RESET : in std_logic; vrat : out TVystup; vydej_napoj : out boolean; otevreno : buffer std_logic; hotovo : out std_logic); end component; begin -- Tester_automaton_body -- component FSA : Automaton port map ( mince, CLK, ASYNCH_RESET, vrat, vydej_napoj, otevreno, hotovo); -- processes -- purpose: Insert coins -- type : sequential TEST : process (CLK) begin -- process TEST mince <= c5; end process TEST; -- purpose: simulate the clock CLOCK : process (CLK) begin -- process CLOCK if CLK = 'U' then CLK <= '1'; else CLK <= not CLK after 10 ns; end if; end process CLOCK; end Tester_automaton_body;