1. 程式人生 > >Verilog自動售貨機設計

Verilog自動售貨機設計

我們實習的內容,設計一個自動售貨機的控制器,實現以下功能:

a.   機器只接受1元硬幣和5元紙幣;

b.   機器共提供4種貨物,價格分別為2元、2元、3元、3元;

c.   顧客先選擇需要的一種或者多種貨物,再確認所選貨物後,進入投幣狀態。當顧客選擇的貨物賣光時,本實驗中,只需在顧客確認貨物之時,提示顧客貨物賣光,並返回初始狀態即可。(每種貨物數量初始值為63。顧客確認貨物時,需提供確認選擇和重新選擇兩個選項。)

d.    若等待60s,顧客不投幣,則返回初始狀態;顧客投幣後,系統自動計算所投錢幣。若投幣夠,則出貨找零。若自客戶確認貨物之後60s,投幣不夠,則退幣並返回初始狀態。(本實驗中,退幣過程只需將記錄顧客投入錢幣清零即可)。

主要是運用有限狀態機

的方法。

狀態描述表
狀態 S0 S1 S2 S3 S4 S5 S6 S7 S8
狀態描述 初始化狀態 選擇貨物 確認選擇 判斷是否賣光 是否在60s內投幣 投幣金額是否足夠 是否需要找零 找零 出貨

自動售貨機程式碼:

//Vending Machine
module VendingMac (clk,money_input,select,confirm,init,left1,left2,left3,left4,change,out);
  input clk;
  input [2:0] money_input;
  input [1:4] select;
  input confirm,init;
  input [5:0] left1,left2,left3,left4;
  output integer change;
  output reg [1:4] out;
  reg [1:4] select_sta;
  reg [3:0] sta;
  reg isSelled;
  reg timeCnting;
  reg [8:0] time_cnt;
  reg [1:0] opt;
  integer money_sum;
  
  parameter S_select=4'b0000,S_confirm=4'b0001,S_allselled=4'b0010,S_60sec=4'b0011,
            S_enough=4'b0100,S_requirechange=4'b0101,S_change=4'b0110,S_out=4'b0111,
            S_init=4'b1000;
  
  initial
  begin
    sta=S_init;
  end
  
  always @(posedge clk)
  begin
    if(clk && timeCnting)
      time_cnt=time_cnt+1;
    if(timeCnting==0)
      time_cnt=0;
  end
  
  always @(posedge init or posedge clk)
  begin
    if(clk)
      begin
        case(sta)
          S_init:
          begin
            select_sta=4'b0000;
            timeCnting=0;
            money_sum=0;
            change=0;
            out=0;
            opt=0;
            
            sta=S_select;
          end
          S_select:
          begin
            select_sta=select|select_sta;
            if(confirm || init)
              begin
                opt={confirm,init};
                sta=S_confirm;
              end
          end
          S_confirm:
          begin
            if(opt==2'b10 || opt==2'b11)
              sta=S_allselled;
            else if(opt==2'b01)
              begin
                //select_sta=4'b0000;
                sta=S_init;
              end
          end
          S_allselled:
          begin
            isSelled=0;
            if(select_sta[1]==1 && left1<=0)
              isSelled=1;
            if(select_sta[2]==1 && left2<=0)
              isSelled=1;
            if(select_sta[3]==1 && left3<=0)
              isSelled=1;
            if(select_sta[4]==1 && left4<=0)
              isSelled=1;
            
            if(isSelled)
              begin
                //select_sta=4'b0000;
                sta=S_init;
              end
            else
              begin
                timeCnting=1;
                sta=S_60sec;
              end
          end
          S_60sec:
          begin
            if(time_cnt<500)//wait 10000 timepiece
              begin
                if(money_input!=0)//wait 10000 timepiece
                  begin
                    money_sum=money_sum+money_input;
                  end
              end
            else if(time_cnt==500)
              if(money_sum!=0)
                sta=S_enough;
            else
              sta=S_init;
          end
          S_enough:
          begin
            if(select_sta[1]==1)
              money_sum=money_sum-2;
            if(select_sta[2]==1)
              money_sum=money_sum-2;
            if(select_sta[3]==1)
              money_sum=money_sum-3;
            if(select_sta[4]==1)
              money_sum=money_sum-3;
              
            if(money_sum>=0)
              sta=S_requirechange;
            else
              sta=S_init;
          end
          S_requirechange:
          begin
            if(money_sum==0)
              sta=S_out;
            else if(money_sum>0)
              sta=S_change;
          end
          S_change:
          begin
            change=money_sum;
            sta=S_out;
          end
          S_out:
          begin
            out=select_sta;
            sta=S_init;
          end
        endcase
      end
  end
endmodule
測試程式碼:
`timescale 1ns/1ns
`include "./VendingMac.v"

module VendingMac_top;
  reg clk;
  reg [2:0] money_input;
  reg [3:0] select;
  reg confirm,init;
  reg [5:0] left1,left2,left3,left4;
  wire [2:0] change;
  wire [3:0] out;
  
  initial
  begin
    clk=0;
    select=4'b0000;
    confirm=0;
    init=0;
    money_input=0;
    left1=63;
    left2=63;
    left3=63;
    left4=63;
  end
  
  always
  begin
    #10 clk=~clk;
    #10 clk=~clk;
  end
  
  initial
  begin
    #40
    #10 select=4'b0100;//posedge1
    #10 select=4'b0000;
    #10 select=4'b0001;//posedge2
    #10 select=4'b0000;
    #10 confirm=1;
    #10 confirm=0;
    #60
    #10 money_input=1;
    #10 money_input=0;
    #10 money_input=5;
    #10 money_input=0;
    #10 money_input=5;
    #10 money_input=0;
  end
  
  initial
  begin
    $monitor($time,,,"select=%b,money_input=%d,confirm=%d,init=%d,out=%b,change=%d",select,money_input,confirm,init,out,change);
    #60000 $finish;
  end
  
  VendingMac v1(clk,money_input,select,confirm,init,left1,left2,left3,left4,change,out);
endmodule