標(biāo)題:
FPGA自動(dòng)售貨機(jī)設(shè)計(jì) 僅供交流
[打印本頁]
作者:
dgsggpga
時(shí)間:
2020-7-3 15:42
標(biāo)題:
FPGA自動(dòng)售貨機(jī)設(shè)計(jì) 僅供交流
本帖最后由 dgsggpga 于 2020-7-3 15:45 編輯
1.總體設(shè)計(jì)
采用FPGA來設(shè)計(jì)的原理圖如圖1.1所示.它由控制輸入電路、FPGA、顯示電路電路組成。
圖1.1 采用FPGA設(shè)計(jì)的自動(dòng)售貨機(jī)原理方框圖
控制輸入電路主要是為用戶設(shè)計(jì)的,起到一個(gè)輸入控制的作用。FPGA是現(xiàn)場可編程邏輯器件,也是本設(shè)計(jì)方案的核心內(nèi)容,它是實(shí)現(xiàn)自動(dòng)售貨機(jī)運(yùn)作的主要控制模塊。將編寫好的HDL程序燒制到現(xiàn)場可編程邏輯器件FPGA中,然后通過控制輸入電路把信號(hào)輸入到FPGA,由八個(gè)開關(guān)控制輸入信號(hào)即消費(fèi)者選擇商品和消費(fèi)者投幣及確認(rèn)消費(fèi),動(dòng)態(tài)數(shù)碼管顯示輸出信號(hào)即找零環(huán)節(jié)和所選擇的商品、消費(fèi)者投幣。
2、設(shè)計(jì)說明
本設(shè)計(jì)是以現(xiàn)場可編程邏輯器件(FPGA)為核心的自動(dòng)售貨機(jī),利用Modesim軟件編寫verilog硬件描述語言程序以實(shí)現(xiàn)自動(dòng)售貨功能。
1.1、系統(tǒng)設(shè)計(jì)描述
(1)用四個(gè)發(fā)光二極管分別模擬售出價(jià)值為2元、5元、7元和10元的商品,購買者可以通過開關(guān)選擇任意一種標(biāo)價(jià)中的小商品;
(2)燈亮?xí)r表示該小商品售出;
(3)用開關(guān)分別模擬1元、5元,10元和20元貨幣投入,用四支發(fā)光二極管代表投入的貨幣的面值;
(4)每次只能售出一種小商品,當(dāng)所投硬幣達(dá)到或超過購買者所選面值時(shí),售出貨物并找回剩余的硬幣,回到初始狀態(tài);
(5)當(dāng)所投硬幣值不足面值時(shí),可通過一個(gè)復(fù)位鍵退回所投硬幣,回到初始狀態(tài)。
系統(tǒng)框圖如圖1.1所示:
圖1.1 系統(tǒng)
3、詳細(xì)狀態(tài)描述
3.1 初始狀態(tài)
rst為復(fù)位鍵,低電平有效,實(shí)現(xiàn)系統(tǒng)復(fù)位。
3.2 選商品狀態(tài)
分別有價(jià)格為2元、5元、7元和10元的商品,每次選擇商品前,設(shè)置一個(gè)標(biāo)志位btn_sel_goods表示選擇商品狀態(tài)。此自動(dòng)售貨機(jī)每一次售貨時(shí)只能一次選擇一種商品,當(dāng)同時(shí)選擇兩種以上時(shí),選擇商品無效,數(shù)碼管顯示清零,重新進(jìn)行商品選擇。選擇商品后,數(shù)碼管顯示所選商品價(jià)格。
3.3 投幣狀態(tài)
當(dāng)選好商品后,開始投幣。同樣有一標(biāo)志位btn_price表示投幣金額。投幣口只接受面值為1元、5元10元和20元的貨幣,可以同時(shí)投入多種面值錢幣。投完幣后,先有一個(gè)確認(rèn)買商品的過程,若投了幣但又不購買商品了,就將全部投幣金額退回;若確認(rèn)購買商品,則進(jìn)入下一狀態(tài)。
3.4 找零狀態(tài)
投完幣,并確認(rèn)購買商品后,進(jìn)入找零狀態(tài)。首先要將所投的金額與所選商品的價(jià)格做比較,若所投金額小于商品價(jià)格,則退回所投錢幣;若大于等于商品價(jià)格,則兩者做差,得到需要找零的錢。
4、仿真結(jié)果分析
設(shè)置測試程序各參數(shù),運(yùn)行tb文件,仿真結(jié)果如下圖3.1、3.2所示。
圖3.1
圖3.1所示,商品價(jià)格選擇為7元,即btn_sel_goods=2'b10,投幣總額大于商品價(jià)格的情況,上圖中btn_mony從右到左依次代表投幣1元、10元、20元、10元、20元、1元、20元和10元,共92元。red燈實(shí)時(shí)顯示所投貨幣的面值。dis_price顯示為0000001_0001111,對(duì)應(yīng)數(shù)碼管顯示數(shù)字為07,即7元。 dis_mony為0000000_0100100,對(duì)應(yīng)數(shù)碼管顯示數(shù)字為85?梢钥闯觯瑢(shí)驗(yàn)結(jié)果很理想,說明代碼符合設(shè)計(jì)要求。
圖3.2
圖3.2所示,商品價(jià)格選擇為7元,即btn_sel_goods=2'b10,投幣總額小于商品價(jià)格的情況,上圖中btn_mony從右到左依次代表投幣1元、5元,共6元。red燈實(shí)時(shí)顯示所投貨幣的面值。dis_price顯示為0000001_0001111,對(duì)應(yīng)數(shù)碼管顯示數(shù)字為07,即7元。 dis_mony為0000001_0100000,對(duì)應(yīng)數(shù)碼管顯示數(shù)字為06,即6元,可以看出,實(shí)驗(yàn)結(jié)果很理想,說明代碼符合設(shè)計(jì)要求。
附錄:
/////////////////////////////////////////////////
//自動(dòng)售貨機(jī)
//btn_sel_goods 為所選商品,由于實(shí)驗(yàn)條件的限制,本實(shí)驗(yàn)中只給出4種價(jià)格的商品
//btn_ok 購買確認(rèn)鍵
//led[3:0] 客戶單次投幣幣值
//beep 客戶所投金額或購買商品后剩余金額大于所選商品價(jià)格時(shí),該燈亮,表示可以繼續(xù)購買
//led_warn 客戶所投金額或購買商品后剩余金額小于所選商品價(jià)格時(shí),該燈亮,表示不可以繼續(xù)購買
//charge 找零按鍵,按下后找零
/////////////////////////////////////////////////
`timescale 1ns / 1ps
module auto_machine(rst,clk,charge,dis_mony,dis_price,
btn_ok,btn_mony,btn_sel_goods,led_warn,led,beep);
input clk,rst;
input charge,btn_ok; //找零/確定
input [3:0] btn_mony; //選擇放入的錢1元5元10元20元
input [1:0] btn_sel_goods; //選擇2元5元7元10元商品
output [3:0] led; //分別顯示投入的是1元5元10元還是20元貨幣
output led_warn; //錢不足,指示燈
output [13:0] dis_mony; //數(shù)碼管顯示投入總金額
output [13:0] dis_price; //數(shù)碼管顯示價(jià)錢
output beep; //交易完成提醒
reg [3:0] led;
reg led_warn;//投入錢幣不夠時(shí)警告
reg [13:0] dis_mony;
reg [13:0] dis_price;
reg beep;
parameter S2=2'b00,S5=2'b01,S7=2'b10,S10=2'b11;
parameter M1=4'b0001,M5=4'b0010,M10=4'b0100,M20=4'b1000;
wire[3:0] btn_mony_buf0;
wire[3:0] btn_mony_buf1;
wire btn_ok_b0;
wire btn_ok_b1;
wire[1:0] btn_sel_goods_b;
wire charge_buf;
reg [6:0] price,price_all;
key_down uut4(.rst(rst),.clk(clk),.det(btn_mony[0]),.key_don(btn_mony_buf0[0]));
key_down uut5(.rst(rst),.clk(clk),.det(btn_mony[1]),.key_don(btn_mony_buf0[1]));
key_down uut6(.rst(rst),.clk(clk),.det(btn_mony[2]),.key_don(btn_mony_buf0[2]));
key_down uut7(.rst(rst),.clk(clk),.det(btn_mony[3]),.key_don(btn_mony_buf0[3]));
edge_det uut0(.rst(rst),.clk(clk),.det(btn_mony_buf0[0]),.pos_edge(btn_mony_buf1[0]));
edge_det uut1(.rst(rst),.clk(clk),.det(btn_mony_buf0[1]),.pos_edge(btn_mony_buf1[1]));
edge_det uut2(.rst(rst),.clk(clk),.det(btn_mony_buf0[2]),.pos_edge(btn_mony_buf1[2]));
edge_det uut3(.rst(rst),.clk(clk),.det(btn_mony_buf0[3]),.pos_edge(btn_mony_buf1[3]));
key_down uut8(.rst(rst),.clk(clk),.det(btn_ok),.key_don(btn_ok_b0));
edge_det uut9(.rst(rst),.clk(clk),.det(btn_ok_b0),.pos_edge(btn_ok_b1));
key_down uut10(.rst(rst),.clk(clk),.det(btn_sel_goods[0]),.key_don(btn_sel_goods_b[0]));
key_down uut11(.rst(rst),.clk(clk),.det(btn_sel_goods[1]),.key_don(btn_sel_goods_b[1]));
key_down uut12(.rst(rst),.clk(clk),.det(charge),.key_don(charge_buf));
always @(negedge rst or posedge clk)
begin
if(!rst)
begin
led <= 4'b0;
led_warn <=1'b0;
beep <=1'b0;
price_all =7'd0;
price <= 7'd0;
dis_mony <=14'h3fff;
dis_price <=14'h3fff;
end
else
begin
case(btn_mony_buf1)
M1: //所投錢幣+1
price_all =price_all + 7'd1;
M5: //所投錢幣+5
price_all =price_all + 7'd5;
M10: //所投錢幣+10
price_all =price_all+ 7'd10;
M20: //所投錢幣+20
price_all =price_all + 7'd20;
default: led <= 4'b0;
endcase
case(btn_mony)
M1: //顯示所投錢幣幣值
led <= M1;
M5:
led <= M5;
M10:
led <= M10;
M20:
led <= M20;
default:
led <= 4'b0;
endcase
case(btn_sel_goods_b)
S2:begin price <= 7'd2;
end
S5:begin price <= 7'd5;
end
S7:begin price <= 7'd7;
end
S10:begin price <= 7'd10;
end
default:begin price <= 7'd0;
end
endcase
if(!charge_buf)
price_all = 7'd0; //退回零錢
else
begin
if(btn_ok_b1)
begin
if(price_all < price)
led_warn = 1'b1;
else
price_all = price_all-price;
end
else
begin
led_warn <= 1'b0;
beep <= 1'b0;
end
end
if(price_all<price)
led_warn <= 1'b1; //投幣差額小于商品價(jià)格時(shí)警告
else
begin
led_warn <= 1'b0;
beep <= 1'b1; //所投金額大于商品價(jià)格時(shí),亮燈表示可以購買
end
dis_mony[6:0] <= led7(price_all%10);//找零金額個(gè)位顯示
dis_mony[13:7] <= led7(price_all/10);//找零金額十位顯示
dis_price[6:0] <= led7(price%10);//商品價(jià)格個(gè)位顯示
dis_price[13:7] <= led7(price/10);//商品價(jià)格十位顯示
end
end
/*數(shù)碼管段碼表*/
function [6:0] led7;
input [6:0] dis_input;
begin
case (dis_input)
0 : led7 = 7'b1000000;
1 : led7 = 7'b1111001;
2 : led7 = 7'b0100100;
3 : led7 = 7'b0110000;
4 : led7 = 7'b0011001;
5 : led7 = 7'b0010010;
6 : led7 = 7'b0000011;
7 : led7 = 7'b1111000;
8 : led7 = 7'b0000000;
9 : led7 = 7'b0011000;
default : led7 = 7'b111_1111;
endcase
end
endfunction
endmodule
/////////////////////////////////////
//實(shí)現(xiàn)邊沿檢測的功能
//det為原輸入需檢測信號(hào)
//pos_edge為輸出的一個(gè)脈沖長度的上升沿信號(hào)
//
/////////////////////////////////////
module edge_det(rst,clk,det,pos_edge);
input rst,clk;
input det;
output pos_edge;
wire pos_edge;
reg p_edge1;
reg p_edge2;
assign pos_edge = (!p_edge1 & p_edge2);
always @(negedge rst or posedge clk)
begin
if (!rst)
begin
p_edge1<=1'b0;
p_edge2<=1'b0;
end
else
begin
p_edge1<= det;
p_edge2<=p_edge1;
end
end
endmodule
/////////////////////////////////////
//實(shí)現(xiàn)按鍵消抖工功能
//det為原輸入信號(hào)
//key_don為輸出確認(rèn)信號(hào)
//
//CONT實(shí)現(xiàn)計(jì)數(shù),經(jīng)過CONT個(gè)脈沖的延時(shí)
//
/////////////////////////////////////
module key_down(rst,clk,det,key_don);
input rst,clk;
input det; //
output key_don; //
reg p_edge1;
reg p_edge2;
reg[24:0] cont;
parameter CONT = 25'd050;
assign key_don = (det & p_edge1 & p_edge2);
always @(negedge rst or posedge clk)
begin
if (!rst)
begin
p_edge1<=1'b0;
p_edge2<=1'b0;
cont<=25'b0;
end
else
begin
if(cont==CONT)
begin
cont<=0;
p_edge1 <= det;
p_edge2 <=p_edge1;
end
else
cont<=cont+1'b1;
end
end
endmodule
///////////////////////////////////////////////////////////////////////
//tb文件
///////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
module tb_mb;
reg clk,rst,btn_ok;
reg [3:0] btn_mony; //選擇放入的錢1元5元10元20元
reg [1:0] btn_sel_goods; //選擇商品2、5、7、10元
wire [3:0] led; //led_5,led_10,led_15,led_20
wire led_warn; //錢不足,指示燈
wire [6:0] dis_mony; //數(shù)碼管顯示投入面值
wire [6:0] dis_price; //數(shù)碼管顯示價(jià)錢
wire beep;
auto_machine uut(.clk,.rst,.dis_mony,.dis_price,
.btn_ok,.btn_mony,.btn_sel_goods,
.led_warn,.led,.beep);
initial begin
clk = 1'b0;
rst = 1'b0;
btn_ok=1'b0;
#20 rst=1;
#10 btn_sel_goods=2'b10;
#20 btn_mony=4'b0001;
#30 btn_mony=4'b0100;
#50 btn_mony=4'b0010;
#100 btn_ok=1'b1;
end
always #2 clk=~clk;
endmodule
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1