代码如下
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity vending_machine is
port (
clk: in std_logic;
reset_in: in std_logic;
coin_10_in: in std_logic;
coin_5_in: in std_logic;
confirm_in: in std_logic;
cancel: in std_logic;
go: in std_logic;
drink_1,drink_2:in std_logic;
add_in:in std_logic;
less_in:in std_logic;
segment_out : out STD_LOGIC_VECTOR (6 downto 0);
segment_out1 : out STD_LOGIC_VECTOR (6 downto 0);
sweep : out STD_LOGIC_VECTOR (6 downto 0);
led_1,led_2,led_3,led_4: out std_logic;
led1,led2,led3,led4,led5,led6,led7: out std_logic
);
end entity vending_machine;
architecture behavioral of vending_machine is
signal temp_reset,reset:std_logic;
signal div:std_logic_vector(30 downto 0) := (others=>'0');
signal clkdiv,clksw : std_logic;
signal count : std_logic_vector(6 downto 0) := "0000001";
signal cnt0,cnt1,cnt2,cnt3,cnt4,cnt5,cnt6,seg_7_s : std_logic_vector(3 downto 0);
signal stock_1out,stock_2out: signed(3 downto 0);
signal quantity_out: signed(3 downto 0);
signal coins_inserted_out: signed(7 downto 0);
signal coins_required_out: signed(7 downto 0);
signal coins_returned_out: signed(7 downto 0);
signal count1,count2,count3,count4,count5:integer;--计数
signal add,less,confirm,coin_10,coin_5: std_logic;
begin
--按键消抖
process(clk)
begin
if(clk'event and clk='1') then--上升沿
if(add_in='1') then--按键初始为0
count1<=count1+1;
if(count1=2000000) then--对应现实20ms
add<='1';--判断是否有一段持续20ms的'0'状态,若有即代表按下
else
add<='0';--若无代表没按下
end if;
else
count1<=0;
end if;
end if;
end process;
process(clk)
begin
if(clk'event and clk='1') then--上升沿
if(less_in='1') then--按键初始为0
count2<=count2+1;
if(count2=2000000) then--对应现实20ms
less<='1';--判断是否有一段持续20ms的'1'状态,若有即代表按下
else
less<='0';--若无代表没按下
end if;
else
count2<=0;
end if;
end if;
end process;
process(clk)
begin
if(clk'event and clk='1') then--上升沿
if(confirm_in='1') then--按键初始为0
count3<=count3+1;
if(count3=2000000) then--对应现实20ms
confirm<='1';--判断是否有一段持续20ms的'1'状态,若有即代表按下
else
confirm<='0';--若无代表没按下
end if;
else
count3<=0;
end if;
end if;
end process;
process(clk)
begin
if(clk'event and clk='1') then--上升沿
if(coin_10_in='1') then--按键初始为0
count4<=count4+1;
if(count4=2000000) then--对应现实20ms
coin_10<='1';--判断是否有一段持续20ms的'1'状态,若有即代表按下
else
coin_10<='0';--若无代表没按下
end if;
else
count4<=0;
end if;
end if;
end process;
process(clk)
begin
if(clk'event and clk='1') then--上升沿
if(coin_5_in='1') then--按键初始为0
count5<=count5+1;
if(count5=2000000) then--对应现实20ms
coin_5<='1';--判断是否有一段持续20ms的'1'状态,若有即代表按下
else
coin_5<='0';--若无代表没按下
end if;
else
count5<=0;
end if;
end if;
end process;
--产生异步复位信号
p1:PROCESS(clk,reset_in)
BEGIN
IF(reset_in='1')THEN
temp_reset<='0';
ELSIF(clk'event AND clk='1')THEN
temp_reset<='1';
END IF;
END PROCESS p1;
p2:PROCESS(clk,reset_in)
BEGIN
IF(reset_in='1')THEN
reset<='0';
ELSIF(clk'event AND clk='1')THEN
reset<=temp_reset;
END IF;
END PROCESS p2;
--状态机
process(reset,coin_10,coin_5,drink_1,drink_2,add,less,confirm,cancel,go)is
type state_type is (idle, check_stock, select_quantity, accept_coins, confirm_purchase, cancel_purchase, return_change);
variable state: state_type:=idle;
variable stock_1,stock_2: signed(3 downto 0);
variable quantity: signed(3 downto 0);
variable coins_inserted: signed(7 downto 0);
variable coins_required: signed(7 downto 0);
variable coins_returned: signed(7 downto 0);
variable coin_flag:std_logic;
constant price_1:signed(3 downto 0):="0011";--代表15元
constant price_2:signed(3 downto 0):="0100";--代表20元
begin
if (reset='1' )then
state:=idle;
elsif(clk'event AND clk='1')then
case state is
when idle=>--初始状态 s1
stock_1:="0010";--两罐
stock_2:="0011";--三罐
coins_inserted:="00000000";
coins_required:="00000000";
coins_returned:="00000000";
led_1<='0';
led_2<='0';
led_3<='0';
led_4<='0';
quantity:="0000";
led1<='1';
led2<='0';
led3<='0';
led4<='0';
led5<='0';
led6<='0';
led7<='0';
if confirm='1' then
state:=check_stock;
else
state:=idle;
end if;
when check_stock=>--检查存量 s2
if stock_1>0 then
led_1<='1';
else
led_1<='0';
end if;
if (stock_2>0) then
led_2<='1';
else
led_2<='0';
end if;
coins_inserted:="00000000";
coins_required:="00000000";
coins_returned:="00000000";
coin_flag:='0';
quantity:="0000";
led_3<='0';
led_4<='0';
led1<='0';
led2<='1';
led3<='0';
led4<='0';
led5<='0';
led6<='0';
led7<='0';
if (drink_1='1' or drink_2='1')then
quantity:="0001";
state:=select_quantity;
else state:=check_stock;
end if;
when select_quantity=>--选择数量 s3
if (drink_1='1')then
if (add='1')then
quantity:=quantity + 1;
elsif (less='1') then
quantity:=quantity - 1;
else
quantity:=quantity;
end if;
if (quantity > stock_1) then
led_4<='1';--提醒超出存量
else led_4<='0';
end if;
end if;
if (drink_2='1')then
if (add='1')then
quantity:=quantity + 1;
elsif (less='1' )then
quantity:=quantity - 1;
else
quantity:=quantity;
end if;
if (quantity > stock_2) then
led_4<='1';--提醒超出存量
else led_4<='0';
end if;
end if;
led1<='0';
led2<='0';
led3<='1';
led4<='0';
led5<='0';
led6<='0';
led7<='0';
if (drink_1='1')then
coins_required:=quantity * price_1;
elsif (drink_2='1')then
coins_required:=quantity*price_2;
else
coins_required:=coins_required;
end if;
if (coin_5= '1' ) then
coins_inserted:=coins_inserted+1;
state:=accept_coins;
elsif (coin_10='1') then
coins_inserted:=coins_inserted+2;
state:=accept_coins;
else state:=select_quantity;
end if;
when accept_coins=>--接收硬币 s4
if (coin_5='1' )then
coins_inserted:=coins_inserted+1;
elsif (coin_10='1') then
coins_inserted:=coins_inserted+2;
end if;
led1<='0';
led2<='0';
led3<='0';
led4<='1';
led5<='0';
led6<='0';
led7<='0';
if (confirm='1') then
state:=confirm_purchase;
elsif (cancel='1' )then
state:=cancel_purchase;
else state:=accept_coins;
end if;
when confirm_purchase=>--确认购买 s5
if (drink_1='1')then
if (coins_inserted>=coins_required and stock_1>0 ) then
coin_flag:='1';--代表付款足够
led_3<='1';--代表出货成功
led_4<='0';
stock_1:=stock_1-quantity;
coins_returned:=coins_inserted-coins_required;
coins_inserted:="00000000";
else led_4<='1';--代表出货失败
end if;
elsif (drink_2='1') then
if (coins_inserted>=coins_required and stock_2>0 ) then
coin_flag:='1';--代表付款足够
led_3<='1';--代表出货成功
led_4<='0';
stock_2:=stock_2-quantity;
coins_returned:=coins_inserted-coins_required;
coins_inserted:="00000000";
else led_4<='1';--代表出货失败
end if;
end if;
led1<='0';
led2<='0';
led3<='0';
led4<='0';
led5<='1';
led6<='0';
led7<='0';
if (coin_flag='1') then
state:=return_change;
else
state:=accept_coins;
end if;
when cancel_purchase=>--取消购买 s6
coins_returned:=coins_inserted;
coins_inserted:="00000000";
led_4<='1';
led1<='0';
led2<='0';
led3<='0';
led4<='0';
led5<='0';
led6<='1';
led7<='0';
state:=return_change;
when return_change=>--找零 s7
led1<='0';
led2<='0';
led3<='0';
led4<='0';
led5<='0';
led6<='0';
led7<='1';
if stock_1>0 then
led_1<='1';
else
led_1<='0';
end if;
if (stock_2>0) then
led_2<='1';
else
led_2<='0';
end if;
if (go='1') then
state:=check_stock;
else
state:=return_change;
end if;
end case;
--传递数码管信号
cnt0<=CONV_STD_LOGIC_VECTOR(stock_1,4);
cnt1<=CONV_STD_LOGIC_VECTOR(stock_2,4);
cnt2<=CONV_STD_LOGIC_VECTOR(quantity,4);
cnt3<=CONV_STD_LOGIC_VECTOR(CONV_INTEGER(coins_inserted)*5/10,4);
cnt4<=CONV_STD_LOGIC_VECTOR(CONV_INTEGER(coins_inserted)*5 rem 10,4);
cnt5<=CONV_STD_LOGIC_VECTOR(CONV_INTEGER(coins_returned)*5/10,4);
cnt6<=CONV_STD_LOGIC_VECTOR(CONV_INTEGER(coins_returned)*5 rem 10,4);
end if;
end process ;
--实现数码管显示
process(clk)
begin
if rising_edge(clk) then
div<=div+1;
if div>=19999999 then
div<=(others=>'0');
end if;
if div>=9999999 then
clkdiv<='1';
else
clkdiv<='0';
end if;
end if;
end process;
clksw<=div(16);
process(clksw)
begin
if rising_edge(clksw) then
count<=count (5 downto 0)&count(6);
end if;
case count is
when "00000001" =>seg_7_s<=cnt0;
when "00000010" =>seg_7_s<=cnt1;
when "00000100" =>seg_7_s<=cnt2;
when "00001000" =>seg_7_s<=cnt3;
when "00010000" =>seg_7_s<=cnt4;
when "00100000" =>seg_7_s<=cnt5;
when "01000000" =>seg_7_s<=cnt6;
when others =>seg_7_s<="0000";
end case;
end process;
sweep<=count;
with seg_7_s select
segment_out <= "0000110" when "0001", --1
"1011011" when "0010", --2
"1001111" when "0011", --3
"1100110" when "0100", --4
"1101101" when "0101", --5
"1111101" when "0110", --6
"0000111" when "0111", --7
"1111111" when "1000", --8
"1101111" when "1001", --9
"0111111" when others; --0
with seg_7_s select
segment_out1<= "0000110" when "0001", --1
"1011011" when "0010", --2
"1001111" when "0011", --3
"1100110" when "0100", --4
"1101101" when "0101", --5
"1111101" when "0110", --6
"0000111" when "0111", --7
"1111111" when "1000", --8
"1101111" when "1001", --9
"0111111" when others; --0
end architecture behavioral;