Vending machine controller
Suppose we have a vending machine that sells soda cans that costs a 2$ each. Moreover, we
have only 3 types of coins: 1$, 2$ and 5$. Our objective is to design a state machine that
determines when to dispense a can, how to return the change.
Note: in this design we will ignore the capacity of the stock, which means, we’ll assume that
there will always be can in the vending machine. Also, we can assume that only one action
could be made in every “clock cycle” or state.
RULES:
first give back the change then dispense the can
Understanding the possibilities :
there are quite few options:
1) entering no money
2)putting 1$ followed by another 1$ => getting the can
3)putting 1$ followed by 2$ => receiving change => getting a can
4)putting 1$ followed by 5$ => receiving change => getting a can
5)putting 2$ and getting the can
6)putting 5$ => receiving change => getting a can.
Above, is the “big picture” of the options or states of the machine, note that if you put a sum
of money which is more or equal to 2$, you can’t put more money (since it would be
meaningless, no?!)
FSM diagram:
Basically, what we’ll do now is translating the options we stated above into a flow chart/FSM
diagram:
*Note: 0$ = “00”, 1$ = “01”, 2$=”10″, 5$ = “11”
explaining the states :
1)put_money: this is the first state after ‘idle’, here the customer puts in the coins.
2)in_5: If the customer put 5$, the machine moves to this state. Pay attention that the machine gives
back a 2$ change without dispensing the can yet.
3)change_1: after giving a 2$ change for the customer who paid 5$we need to give back another 1$
change. Here, in this state we do exactly that. again, note that the can still has not been dispensed yet!
4)in_1, in_3, in_6: we get to those states depending on the sum of money that been inserted
by the customer.
5)soda_out: dispensing out the soda can!
VHDL code for vending machine controller
library ieee;
use IEEE.std_logic_1164.all;
entity FSM is
port (CLK : in std_logic; --Clock, active high
RSTn : in std_logic; --Async. Reset, active low
CoinIn : in std_logic_vector (1 downto 0); --Which coin was inserted
Soda : out std_logic; --Is Soda dispensed ?
CoinOut : out std_logic_vector (1 downto 0) --Which coin is dispensed?
);
end entity;
architecture behavior of FSM is
-- add your code here
type state_type is (idle, --start state/reset
put_money, --waiting to enter money
in_1,in_3,in_6,in_5, --represent the current sum of money after returning
change
change_1, --should return change of 1$
soda_out --dispence soda can.
); --type of state machine.
signal current_s,next_s: state_type; --current and next state declaration.
begin
process(CLK,RSTn)
begin
if(RSTn = '0') then
current_s <= idle; --defualt state is on RESET
elsif(clk'event and clk = '1') then
current_s <= next_s;
end if;
end process;
--------------------
--FSM process:
process(current_s,CoinIn)
begin
case current_s is
when idle => --state reset or idle
Soda <= '0';
CoinOut <= "00";
next_s <= put_money;
------------------------------------------------------
when put_money => --wait for money to be entered
if(CoinIn = "00")then
Soda <= '0';
CoinOut <= "00";
next_s <= put_money;
elsif(CoinIn = "01")then --insert 1$
Soda <= '0';
CoinOut <= "00";
next_s <= in_1;
elsif(CoinIn = "10")then --insert 2$
Soda <= '0';
CoinOut <= "00";
next_s <= soda_out;
elsif(CoinIn = "11")then --insert 5$
Soda <= '0';
CoinOut <= "00";
next_s <= in_5;
end if;
------------------------------------------------------
when in_1 =>
if(CoinIn = "00") then--stay on the same state
Soda <= '0';
CoinOut <= "00";
next_s <= in_1;
elsif(CoinIn = "01") then--inserted another 1$
Soda <= '0';
CoinOut <= "00";
next_s <= soda_out;
elsif(CoinIn = "10") then--inserted another 2$
Soda <= '0';
CoinOut <= "00";
next_s <= in_3;
elsif(CoinIn = "11") then
Soda <= '0';
CoinOut <= "10";
next_s <= in_6;
end if;
------------------------------------------------------
when in_3 =>
Soda <= '0';
CoinOut <= "01";
next_s <= soda_out;
------------------------------------------------------
when in_6 =>
Soda <= '0';
CoinOut <= "01";
next_s <= in_5;
------------------------------------------------------
when in_5 => -- input = 5 coin
Soda <= '0';
CoinOut <= "10";
next_s <= change_1;
------------------------------------------------------
when change_1 => -- input = 5 coin
Soda <= '0';
CoinOut <= "01";
next_s <= soda_out;
------------------------------------------------------
when soda_out =>
Soda <= '1';
CoinOut <= "00";
next_s <= put_money;
end case;
end process;
end behavior;