基于FPGA状态机的自动售货机功能实现
用FPGA制作一个简单的自动售货机
这篇博客讲了如何用FPGA模拟实现自动售卖机的功能。
文章目录
- 用FPGA制作一个简单的自动售货机
- 1. 程序功能和总体框架详解
- 2.Divider分频模块
- 3.Debounce模块,按键去抖
- 4.FSM状态机
- 5.Seg显示模块
- 6.Siren蜂鸣器报警模块
- 7. Led灯闪烁模块
- 总结
1. 程序功能和总体框架详解
程序功能:
- 按键K3为复位信号,led0,led1控制led等,siren控制蜂鸣器,seg_sel和seg_led分别控制数码管的片选和位选信号
- 有两个商品cnt_40和cnt_50,分别价值40元和50元,K1,K2连接按键,每按一下,代表要购买的cnt_40和cnt_50加1,例如:买2个cnt_40,1个cnt_50,则按2下K1和1下K2,选好商品后,按K4确认;
- 确认后开始投币,投币时K1,K2分别代表投入10元硬币和20元硬币,按K4确认;
- 用4个数码管分别显示2个商品购买个数和2种硬币投入个数
- 若硬币价钱和商品价钱相等,则出货:两个led灯的闪烁次数表示两个商品的出货个数
- 若不相等,蜂鸣器报警
整体框架的代码如下所示:
module top(input k1,input k2,input k4,input k3,input clk,output led1,output led2,output [5:0] seg_sel,output [7:0] seg_led,output siren);
wire key1,key2,key4,le,sir,f1hz;
wire [3:0] cnt_40;
wire [3:0] cnt_50;
wire [3:0] coin_10;
wire [3:0] coin_20;
wire [2:0] cnt;
wire [15:0] data;
assign data={cnt_40[3:0],cnt_50[3:0],coin_10[3:0],coin_20[3:0]};
debounce d1 (.rst(k3),.clock(clk),.noisy(k1),.clean(key1)); //Debounce模块
debounce d2 (.rst(k3),.clock(clk),.noisy(k2),.clean(key2));
debounce d3 (.rst(k3),.clock(clk),.noisy(k4),.clean(key4));
fsm f1(.clock(f1hz),.k1(key1),.k2(key2),.k3(k3),.k4(key4),.led(le),.siren(sir),.cnt_40(cnt_40),.cnt_50(cnt_50),.coin_10(coin_10),.coin_20(coin_20));
divider di1(.clock(clk),.rst(k3),.wave(f1hz)); //对应图中FSM模块
led l1(.clk(clk),.cnt_40(cnt_40),.cnt_50(cnt_50),.led(le),.rst(k3),.wave(f1hz),.led1(led2),.led0(led1));
siren si(.clk(clk),.rst(k3),.start(sir),.sir(siren));
display dx(.clk(clk),.rst(k3), .data(data),.seg_sel(seg_sel),.seg_led(seg_led));//对应图中Seg模块
endmodule
clk为时钟信号,下面是各个模块的解析和代码
实物效果图如下:
2.Divider分频模块
我使用的FPGA开发板的时钟频率为25Mhz,通过这个程序分频,得到一个1hz的时钟信号,led闪烁时,闪太快我们人眼看不出来,所以需要一个1hz的时钟信号,来让它闪慢一点。
module divider(input clock,input rst,output reg wave);
reg [30:0] cnt;
always@(posedge clock or negedge rst)
if(!rst)
begin
cnt<=0;
wave<=0;
end
else if(cnt==25000000)
begin
cnt<=0;
wave<=!wave;
end
else
begin
wave<=wave;
cnt<=cnt+1;
end
endmodule
3.Debounce模块,按键去抖
确保按键按一次,只会产生一个下降沿,因此需要一个去抖动模块
module debounce #(parameter DELAY=500000)(input rst, clock, noisy,output reg clean);reg [19:0] count;reg new;always @(posedge clock)if (!rst)begincount <= 0;new <= noisy;clean <= noisy;endelse if (noisy != new)beginnew <= noisy;count <= 0;endelse if (count == DELAY)clean <= new;elsecount <= count+1;
endmodule
4.FSM状态机
有4种状态,
- Pay状态读取购物信息
- BIJIAO状态来比较货物价值和投入硬币价值是否相等
- SIREN_ON状态控制蜂鸣器报警
- CHUHUO控制出货(led闪烁)
module fsm(input clock,input k1,input k2,input k3,input k4,output reg led,output reg siren,output reg [3:0] cnt_40,output reg [3:0] cnt_50,output reg [3:0] coin_10,output reg [3:0] coin_20);parameter PRICE = 0;parameter PAY = 1;//jie shou zhi fu shu liangparameter BIJIAO = 2;//pan duanparameter SIREN_ON = 3;//bao jingparameter CHUHUO = 4;//chu huoreg [2:0] state;always @ (posedge clock or negedge k3 )if (!k3) //复位beginstate <= PRICE;cnt_40<=0;cnt_50<=0;coin_20<=0; coin_10<=0;
endelse begincase (state)PRICE: begin //K1和K2按键决定cnt_40和cnt_50的购买数量,并输出到数码管显示;led <= 0; //k4按键确认时,进入投币付费状态PAYsiren <= 0;if(!k1)begincnt_40 <= cnt_40 + 1;endif(!k2)begincnt_50 <= cnt_50 + 1;endif(!k4)beginstate <= PAY;endelsestate<=state;endPAY: begin //投币付费状态,K1,K2按键决定10和20的硬币投入数量,并输出到数码管显示if(!k1) //K4按键确认后,进入比较状态BIJIAO begincoin_10 <= coin_10 + 1;endelse if(!k2)begincoin_20 <= coin_20 + 1;endelse if(!k4)state<=BIJIAO;elsestate<=state;endBIJIAO: begin //比较输入的货物价值和投入硬币价值是否相等,若相等,出货CHUHUO状态,否则报警状态SIREN_ONif((4 * cnt_40+ 5 * cnt_50) == (2*coin_20 + coin_10))beginstate <= CHUHUO;endelsebeginstate <= SIREN_ON;endendCHUHUO: begin //出货,led=1使能LED模块,LED模块后面介绍,开启两个led闪烁,闪烁次数等于两个货物的数量led <= 1;siren <= 0;endSIREN_ON: begin //报警,siren控制SIREN模块,使蜂鸣器报警led <= 0;siren <= 1;enddefault: state <= PRICE;endcase
endendmodule
5.Seg显示模块
接受来自状态机FSM的货物数量信号cnt_40,cnt_50,和投入10元20元硬币数量coin_10和coin_20;并使用4个数码管将其显示出来;
数码管显示的程序讲解已经有很多了,这里就不赘述了
module display(input clk,input rst,input [15:0] data,output reg [5:0] seg_sel,output reg [7:0] seg_led
);localparam CLK_DIVIDE = 4'd10 ;
localparam MAX_NUM = 13'd5000 ;reg [3:0] clk_cnt ;
reg dri_clk ;
reg [12:0] cnt0 ;
reg flag ;
reg [2:0] cnt_sel ;
reg [3:0] num_disp ; always @(posedge clk or negedge rst) beginif(!rst) beginclk_cnt <= 4'd0;dri_clk <= 1'b1;endelse if(clk_cnt >= CLK_DIVIDE/2 - 1'd1) beginclk_cnt <= 4'd0;dri_clk <= ~dri_clk;endelse beginclk_cnt <= clk_cnt + 1'b1;dri_clk <= dri_clk;end
endalways @ (posedge dri_clk or negedge rst) beginif (rst == 1'b0) begincnt0 <= 13'b0;flag <= 1'b0;endelse if (cnt0 < MAX_NUM - 1'b1) begincnt0 <= cnt0 + 1'b1;flag <= 1'b0;endelse begincnt0 <= 13'b0;flag <= 1'b1;end
endalways @ (posedge dri_clk or negedge rst) beginif (rst == 1'b0)cnt_sel <= 3'b0;else if(flag) beginif(cnt_sel < 3'd4)cnt_sel <= cnt_sel + 1'b1;elsecnt_sel <= 3'b0;endelsecnt_sel <= cnt_sel;
endalways @ (posedge dri_clk or negedge rst) beginif(!rst) beginseg_sel <= 6'b111111;num_disp <= 4'b0; endelse begincase (cnt_sel)3'd0 :beginseg_sel <= 6'b111101;num_disp <= data[3:0] ; end3'd1 :beginseg_sel <= 6'b111011;num_disp <= data[7:4] ;end3'd2 :beginseg_sel <= 6'b110111;num_disp <= data[11:8];end3'd3 :beginseg_sel <= 6'b101111;num_disp <= data[15:12];enddefault :beginseg_sel <= 6'b111111;num_disp <= 4'b0;endendcaseend
end
always @ (posedge clk or negedge rst) beginif (!rst)seg_led <= 8'b0;else begincase (num_disp)4'h0 : seg_led <= 8'b1100_0000;4'h1 : seg_led <= 8'b1111_1001;4'h2 : seg_led <= 8'b1010_0100;4'h3 : seg_led <= 8'b1011_0000;4'h4 : seg_led <= 8'b1001_1001;4'h5 : seg_led <= 8'b1001_0010;4'h6 : seg_led <= 8'b1000_0010;4'h7 : seg_led <= 8'b1111_1000;4'h8 : seg_led <= 8'b1000_0000;4'h9 : seg_led <= 8'b1001_0000;4'ha : seg_led <= 8'b1000_1000;4'hb : seg_led <= 8'b1000_0011;4'hc : seg_led <= 8'b1100_0110;4'hd : seg_led <= 8'b1010_0001;4'he : seg_led <= 8'b1000_0110;4'hf : seg_led <= 8'b1000_1110;default : seg_led <= 8'b1100_0000;endcaseend
endendmodule
6.Siren蜂鸣器报警模块
蜂鸣器报警没什么好讲的,低电平就不响,高电平就响,以一定的频率开关蜂鸣器,能产生不同的声音,该蜂鸣器模块功能:
- start信号为1时,开启蜂鸣器报警
- 开启蜂鸣器报警时,蜂鸣器以一定的频率发出声音
module siren(input clk,input rst,input start,output reg sir);
reg [24:0] T;
reg [24:0] cnt;
reg [24:0] cnt1;
reg clk1;
always@(posedge clk)
if(cnt1>1000_0000)
begin
cnt1<=0;
clk1<=!clk1;
end
else
cnt1<=cnt1+1;always@(posedge clk1)
if(!rst)
T<=0;
else if(T<50000 || T>100000)
begin
T<=50000;
end
else begin
T<=T+10000;
endalways@(posedge clk or negedge rst)
if(!rst)
begin
sir<=0;
cnt<=0;
end
else if(start==1 && cnt<T)
cnt<=cnt+10;
else if(start==1)
begin
cnt<=0;
sir<=!sir;
end
else begin
sir<=0;
cnt<=0;
end
endmodule
7. Led灯闪烁模块
该模块功能:
- 控制信号为1时,控制两个led灯闪烁
- 闪烁的次数等于输入的两个信号代表的数量
module led(input clk,input [3:0] cnt_40,input [3:0] cnt_50,input led,input rst,input wave,output reg led1,output reg led0);
reg led0_twinkle;
reg led1_twinkle;
reg [3:0] num1;
reg [3:0] num2;
always@(posedge clk or negedge rst)if(!rst)beginled0 <=1'b0;led1 <=1'b0;endelse if(!led)beginled0 <=1'b0;led1 <=1'b0;endelsebeginled0 <=led0_twinkle;led1 <=led1_twinkle;endalways@(posedge wave)
if(!rst)
begin
led0_twinkle <=0;
num1<=0;
end
else if (led==1 && num1<2*cnt_40)
begin
led0_twinkle <=!led0_twinkle;
num1<=num1+1;
end
else
begin
led0_twinkle <=0;
num1<=num1;
endalways@(posedge wave)
if(!rst)
begin
led1_twinkle <=0;
num2<=0;
end
else if (led==1 && num2<2*cnt_50)
begin
led1_twinkle <=!led1_twinkle;
num2<=num2+1;
end
else
begin
led1_twinkle <=0;
num2<=num2;
endendmodule
总结
这里对文章进行总结,这篇博客用FPGA的状态机的概念,做了一个自动售货机,并详细介绍了各个模块的功能及代码,仅供参考。
基于FPGA状态机的自动售货机功能实现相关推荐
- FPGA系统性学习笔记连载_Day15【状态机、自动售货机】 【原理及verilog仿真】篇
FPGA系统性学习笔记连载_Day15[状态机.自动售货机] [原理及verilog仿真]篇 本系列为FPGA系统性学习学员学习笔记整理分享,如有学习或者购买开发板意向,可加交流群联系群主. 连载&l ...
- 基于verlog的简单自动售货机设计
课程设计:基于verlog的简单自动售货机设计 1.设计目的: (1)了解DE2-70开发板的硬件构成: (2)熟悉开发板可用资源的硬件电路: (3)掌握EDA开发流程: (4)熟悉Quartus I ...
- 基于AT89C51单片机的自动售货机系统设计(附仿真+C程序+原理图+论文等)
注意:获取全套设计,请见文末说明- 概述 本文设计了一款以AT89C51单片机为核心的自动售货机系统,并且着重详细地介绍了自动售货机的整体系统设计方案.硬件选择基础.软件使用方法及技巧.以AT89C5 ...
- 自动售货机 顺序图_基于UML的饮料自动售货机系统设计
基于 UML 的饮料自动售货机系统设计 1 . 问题描述 1.1 关于自动售货机 自动售货机像磁卡电话.银行柜员机一样,以方便.新颖.文明.昼夜服务等特点, 成为发达国 家不可缺少的便民配套设施.如今 ...
- 连载《叁芯智能fpga设计与研发-第15天》 【状态机、自动售货机】 【原理及verilog仿真】
一.状态机基本概念 状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调 相关信号动作.完成特定操作的控制中心.有限状态机简写为FSM(Finite State ...
- 基于51单片机的自动售货机系统设计
目录 一.自动售货机的控制子系统概述 二.自动售货机的功能简介 1 自动售货机的功能概述 2 自动售货机的设计思路 三.自动售货机的硬件设计 1. 80C51的简介 (1) 80C51的基本概述 (2 ...
- 基于AM5728 DSP+ARM自动售货机智能控制单元
自动售货机智能控制单元 信迈推出的自动售货机控制单元是一款集自动售货机的控制.通讯与显示等功能于一体的嵌入式一体化产品.使用本 控制单元可以帮助您快速搭建出自动售货机的成套方案. 快速搭建 ,不应 ...
- 状态机——饮料自动售货机
一. 状态模式概述 1.1 什么是状态模式 状态模式是在不同状态下,执行相同的方法,具有不同的实现方式.而每个不同的状态会被封装为一个类,这个类实现了不同状态间共同的方法,只是方法的实现方式各不相同. ...
- 基于51单片机的自动售货机Proteus仿真(源码+仿真+设计报告)
资料编号:137 视频讲解: 137-基于51单片机的自动售货机Proteus仿真(源码+仿真+设计报告) 功能介绍: 基本原理:通过矩阵键盘来选择货物的种类与数量过后自动售货机提示投币.自动售货机的 ...
最新文章
- sqlserver 获取当前年_CVE-2020-0618: 微软 SQL Server 远程代码执行漏洞通告
- LeetCode 6 Z 字形变换
- dnscat2搭建dns隧道
- 洛谷P4762: [CERC2014]Virus synthesis(PAM)
- 【转】Dynamics 365Online 如何启用手机端APP的离线功能
- 有关单元测试的 5 个建议
- vue项目打包部署到Tomcat上,一刷新就报错404
- 《光剑文集》春心沁透: 99首
- excel合并两列内容_比Excel公式快10倍,史上最牛合并表格工具来了!!
- 也许黎曼猜想是错误的
- Ogre 3DMax导出插件的制作
- 北京跑步入夏--妞妞跑步长大
- QRCode.js:使用 JavaScript 生成二维码
- 苟富贵倒萨忽然他确实
- IMPL1. all_fanin/all_fanout命令解析
- 机电和计算机专业怎么选,计算机专业怎么选城口_竟成学校
- 对称加密 非对称加密
- 脚注交叉引用序号不一样_不为人知的Word交叉引用设置
- 2019 NIPS | Variational graph recurrent neural network
- 如何看待区块链游戏,避免陷入区块链游戏骗局
热门文章
- 浅析Flash游戏架构
- 创建了steam服务器无响应,steam打不开没反应怎么办_steam打不开没反应解决方法 - 系统家园...
- 送给她超浪漫的表白信——她感动哭了(.html)
- 解决冲突(避免冲突)
- 博基计划(5)---模型交叉验证方法讨论
- 匿名信V1.4.5.1版本更新“数据大屏”功能
- 面对前端六年历史代码,如何接入并应用ES6解放开发效率
- ThreadLocal作用、原理以及问题
- 【Docker】安装Docker以及配置阿里云Docker镜像仓库
- C++ std::string 转换为 UTF-8 编码