VHDL+FPGA自动售货机

实机演示

代码如下

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;

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值