Verilog自動售貨機設計
阿新 • • 發佈:2019-02-20
我們實習的內容,設計一個自動售貨機的控制器,實現以下功能:
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