FPGA电梯控制系统
通信本科,专业综合课程设计题目,基于FPGA的电梯控制系统。
硬件平台:FPGA 黑金开发平台 AX4010。参考资料
软件平台:quartus13.1(参考正点原子)
百度网盘下载地址 提取码: jxpe
破解地址所实现的功能:
- 显示部分:六位数码管第一位显示用户设置的目标楼层数,最后一位显示电梯当前的楼层。
- 按键部分:第一个按键增加用户设置的目标楼层数,第二个按键减小用户设置的目标楼层数,第三个按键用户确认目标楼层。
- 控制部分:用户输入楼层并确定,程序将电梯楼层和目标楼层进行比较,如果不相等,电梯运行,如果相等,对应的led闪烁。
- 整体测试:
代码如下(参考了正点原子的按键和数码管)
- 顶层文件
module elevator(input sys_clk , // 全局时钟信号input sys_rst_n, // 复位信号(低有效)input [2:0] key, // 独立按键输入output beep, // 蜂鸣器//seg_led interfaceoutput [5:0] seg_sel , // 数码管位选信号output [7:0] seg_led , // 数码管段选信号output [3:0] led // led指示灯
);//wire define
wire [19:0] data; // 数码管显示的数值
wire [ 5:0] point; // 数码管小数点的位置
wire sign_confirm; // 确定信号
wire sign_up; // 电梯上升信号
wire sign_down; // 电梯下降信号
wire [19:0] level; // 用户所在楼层
wire [ 3:0] number; // 电梯当前运行楼层
wire flag; // 电梯到达标志
assign data = level+(number%4'd10); // 数码管显示目标值和当前值
//*****************************************************
//** main code
//*****************************************************//数码管动态显示模块
seg_led u_seg_led(.clk (sys_clk ), // 时钟信号.rst_n (sys_rst_n), // 复位信号.data (data ), // 显示的数值.point (point ), // 小数点具体显示的位置,高电平有效.sign (sign ), // 符号位,高电平显示负号(-).seg_sel (seg_sel ), // 位选.seg_led (seg_led ) // 段选
);//按键输入模块
key_test u_key_test(.clk (sys_clk), // 时钟信号.rst (sys_rst_n), // 复位信号.key_h (key), // 按键输入.flag (flag), // 电梯到达标志.num (level), // 用户所在楼层值输出.sign (sign_confirm) // 确认信号输出);//电梯控制模块
control u_control(.clk (sys_clk), // 时钟信号.rst (sys_rst_n), // 复位信号.level (level), // 用户所在楼层.led (led), // 电梯所在楼层指示灯.number (number), // 电梯当前楼层.sign_up (sign_up), // 电梯上升信号.sign_down (sign_down), // 电梯下降信号.flag (flag), // 电梯到达标志.sign_confirm (sign_confirm), // 电梯确认信号.beep (beep) // 蜂鸣器输出); endmodule
- 按键输入模块
module key_test(input clk, //外部输入50MHz时钟信号input rst, //外部输入复位信号,低电平有效input [2:0] key_h, //3个独立按键输入,未按下为高电平,按下后为低电平input flag, //电梯到达标志output reg [19:0] num=17'd100000, //用户所在楼层数output reg sign //确认信号);/***********************************************************第一部分:检测按键的上升沿或者下降沿************************************************************/wire key; //所有按键值相与的结果,用于按键触发判断reg[3:0] keyr; //按键值key的缓存寄存器//三个键中,任何一个被按下,key都会变为0;除非全都未按下,key才为1。assign key = key_h[0] & key_h[1] &key_h[2];always @(posedge clk or negedge rst)if (!rst) keyr <= 4'b1111;else keyr <= {keyr[2:0],key};/*因为要连续4个时钟才可以将keyr的4位都赋值为出现过的key值,并且是使用的最后两个key值,也即keyr的3、4两位,所以必须要按键按下至少四个周期才能检测到上升沿和下降沿,起到了初步防止误触的效果。*/wire key_neg = ~keyr[2] & keyr[3]; //有按键被按下 wire key_pos = keyr[2] & ~keyr[3]; //有按键被释放/***********************************************************第二部分:定时计数20ms时间,用于对按键的消抖************************************************************/reg[19:0] cnt; //按键消抖定时计数器always @ (posedge clk or negedge rst)if (!rst) cnt <= 20'd0; //不管上升沿还是下降沿都要重新计数,只有当cnt计数到指定值才开始采集此时的键值//这么做就是为了实现消抖,只有按键下降沿或者上升沿发生后高低电平稳定20ms,//才认为此时的键值是有效的,也即此时才开始采集键值。else if(key_pos || key_neg) cnt <= 20'd0;else if(cnt < 20'd999_999) cnt <= cnt + 1'b1;else cnt <= 20'd0;reg[2:0] key_value[1:0];//定时采集按键值always @(posedge clk or negedge rst)if (!rst) beginkey_value[0] <= 4'b1111;key_value[1] <= 4'b1111;endelse begin key_value[1] <= key_value[0];//因为只有当计时到20ms才可以采集键值,//所以下一次再次采集键值至少还的是20ms后 if(cnt == 20'd999_999) key_value[0] <= key_h;//定时键值采集else ; end//对于检测下降沿的信号,(前一clk的数据)&(后一clk的数据取反),结果若为1,//则表示检测到了下降沿,否则就没有。此时key_press的四个位对应的四个按键,//当为1时表示按键被按下,为0就表示此时按键没有被按下。//消抖后按键值变化标志位wire[3:0] key_press = key_value[1] & ~key_value[0]; /***********************************************************第三部分:按键输入输出************************************************************/always @ (posedge clk or negedge rst)if (!rst) beginnum<=17'd100000;sign<= 1'b0;endelse if(key_press[0]) num <= num+17'd100000; //用户所在楼层数加else if(key_press[1]) num <= num-17'd100000; //用户所在楼层数减else if(key_press[2]&&flag) sign <= 1'b1; //确认信号else if(flag) sign <= 1'b0; //复位确认信号else ;endmodule
- 显示模块
module seg_led(input clk , // 时钟信号input rst_n , // 复位信号input [19:0] data , // 6位数码管要显示的数值input [5:0] point , // 小数点具体显示的位置,从高到低,高电平有效input sign , // 符号位(高电平显示"-"号)output reg [5:0] seg_sel, // 数码管位选,最左侧数码管为最高位output reg [7:0] seg_led // 数码管段选);//parameter define
localparam CLK_DIVIDE = 4'd10 ; // 时钟分频系数
localparam MAX_NUM = 13'd5000 ; // 对数码管驱动时钟(5MHz)计数1ms所需的计数值
reg en=1;
//reg define
reg [ 3:0] clk_cnt ; // 时钟分频计数器
reg dri_clk ; // 数码管的驱动时钟,5MHz
reg [23:0] num ; // 24位bcd码寄存器
reg [12:0] cnt0 ; // 数码管驱动时钟计数器
reg flag ; // 标志信号(标志着cnt0计数达1ms)
reg [2:0] cnt_sel ; // 数码管位选计数器
reg [3:0] num_disp ; // 当前数码管显示的数据
reg dot_disp ; // 当前数码管显示的小数点//wire define
wire [3:0] data0 ; // 十万位数
wire [3:0] data1 ; // 万位数
wire [3:0] data2 ; // 千位数
wire [3:0] data3 ; // 百位数
wire [3:0] data4 ; // 十位数
wire [3:0] data5 ; // 个位数//*****************************************************
//** main code
//*****************************************************//提取显示数值所对应的十进制数的各个位
assign data0 = data % 4'd10; // 个位数
assign data1 = data / 4'd10 % 4'd10 ; // 十位数
assign data2 = data / 7'd100 % 4'd10 ; // 百位数
assign data3 = data / 10'd1000 % 4'd10 ; // 千位数
assign data4 = data / 14'd10000 % 4'd10; // 万位数
assign data5 = data / 17'd100000; // 十万位数//对系统时钟10分频,得到的频率为5MHz的数码管驱动时钟dri_clk
always @(posedge clk or negedge rst_n) beginif(!rst_n) 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
end//将20位2进制数转换为8421bcd码(即使用4位二进制数表示1位十进制数)
always @ (posedge dri_clk or negedge rst_n) beginif (!rst_n)num <= 24'b0;else beginif (data5 || point[5]) begin //如果显示数据为6位十进制数,num[23:20] <= data5; //则依次给6位数码管赋值num[19:16] <= data4;num[15:12] <= data3;num[11:8] <= data2;num[ 7:4] <= data1;num[ 3:0] <= data0;endelse begin if (data4 || point[4]) begin //如果显示数据为5位十进制数,则给低5位数码管赋值num[19:0] <= {data4,data3,data2,data1,data0};if(sign) num[23:20] <= 4'd11; //如果需要显示负号,则最高位(第6位)为符号位elsenum[23:20] <= 4'd10; //不需要显示负号时,则第6位不显示任何字符endelse begin //如果显示数据为4位十进制数,则给低4位数码管赋值if (data3 || point[3]) beginnum[15: 0] <= {data3,data2,data1,data0};num[23:20] <= 4'd10; //第6位不显示任何字符if(sign) //如果需要显示负号,则最高位(第5位)为符号位num[19:16] <= 4'd11;else //不需要显示负号时,则第5位不显示任何字符num[19:16] <= 4'd10;endelse begin //如果显示数据为3位十进制数,则给低3位数码管赋值if (data2 || point[2]) beginnum[11: 0] <= {data2,data1,data0};//第6、5位不显示任何字符num[23:16] <= {2{4'd10}};if(sign) //如果需要显示负号,则最高位(第4位)为符号位num[15:12] <= 4'd11;else //不需要显示负号时,则第4位不显示任何字符num[15:12] <= 4'd10;endelse begin //如果显示数据为2位十进制数,则给低2位数码管赋值if (data1 || point[1]) beginnum[ 7: 0] <= {data1,data0};//第6、5、4位不显示任何字符num[23:12] <= {3{4'd10}};if(sign) //如果需要显示负号,则最高位(第3位)为符号位num[11:8] <= 4'd11;else //不需要显示负号时,则第3位不显示任何字符num[11:8] <= 4'd10;endelse begin //如果显示数据为1位十进制数,则给最低位数码管赋值num[3:0] <= data0;//第6、5位不显示任何字符num[23:8] <= {4{4'd10}};if(sign) //如果需要显示负号,则最高位(第2位)为符号位num[7:4] <= 4'd11;else //不需要显示负号时,则第2位不显示任何字符num[7:4] <= 4'd10;endendendendendend
end//每当计数器对数码管驱动时钟计数时间达1ms,输出一个时钟周期的脉冲信号
always @ (posedge dri_clk or negedge rst_n) beginif (rst_n == 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
end//cnt_sel从0计数到5,用于选择当前处于显示状态的数码管
always @ (posedge dri_clk or negedge rst_n) beginif (rst_n == 1'b0)cnt_sel <= 3'b0;else if(flag) beginif(cnt_sel < 3'd5)cnt_sel <= cnt_sel + 1'b1;elsecnt_sel <= 3'b0;endelsecnt_sel <= cnt_sel;
end//控制数码管位选信号,使6位数码管轮流显示
always @ (posedge dri_clk or negedge rst_n) beginif(!rst_n) beginseg_sel <= 6'b111111; //位选信号低电平有效num_disp <= 4'b0; dot_disp <= 1'b1; //共阳极数码管,低电平导通endelse beginif(en) begincase (cnt_sel)3'd0 :beginseg_sel <= 6'b111110; //显示数码管最低位num_disp <= num[3:0] ; //显示的数据dot_disp <= ~point[0]; //显示的小数点end
/* 3'd1 :beginseg_sel <= 6'b111101; //显示数码管第1位num_disp <= num[7:4] ;dot_disp <= ~point[1];end3'd2 :beginseg_sel <= 6'b111011; //显示数码管第2位num_disp <= num[11:8];dot_disp <= ~point[2];end3'd3 :beginseg_sel <= 6'b110111; //显示数码管第3位num_disp <= num[15:12];dot_disp <= ~point[3];end3'd4 :beginseg_sel <= 6'b101111; //显示数码管第4位num_disp <= num[19:16];dot_disp <= ~point[4];end */3'd5 :beginseg_sel <= 6'b011111; //显示数码管最高位num_disp <= num[23:20];dot_disp <= ~point[5];enddefault :beginseg_sel <= 6'b111111;num_disp <= 4'b0;dot_disp <= 1'b1;endendcaseendelse beginseg_sel <= 6'b111111; //使能信号为0时,所有数码管均不显示num_disp <= 4'b0;dot_disp <= 1'b1;endend
end//控制数码管段选信号,显示字符
always @ (posedge dri_clk or negedge rst_n) beginif (!rst_n)seg_led <= 8'hc0;else begincase (num_disp)4'd0 : seg_led <= {dot_disp,7'b1000000}; //显示数字 04'd1 : seg_led <= {dot_disp,7'b1111001}; //显示数字 14'd2 : seg_led <= {dot_disp,7'b0100100}; //显示数字 24'd3 : seg_led <= {dot_disp,7'b0110000}; //显示数字 34'd4 : seg_led <= {dot_disp,7'b0011001}; //显示数字 44'd5 : seg_led <= {dot_disp,7'b0010010}; //显示数字 54'd6 : seg_led <= {dot_disp,7'b0000010}; //显示数字 64'd7 : seg_led <= {dot_disp,7'b1111000}; //显示数字 74'd8 : seg_led <= {dot_disp,7'b0000000}; //显示数字 84'd9 : seg_led <= {dot_disp,7'b0010000}; //显示数字 94'd10: seg_led <= 8'b11111111; //不显示任何字符4'd11: seg_led <= 8'b10111111; //显示负号(-)default: seg_led <= {dot_disp,7'b1000000};endcaseend
endendmodule
- 控制模块
module control(clk,rst,level,led,number,sign_up,sign_down,flag,sign_confirm,beep);input clk; //时钟信号input rst; //外部输入复位信号,低电平有效input [19:0] level; //用户所在楼层(数码管显示的值:100000~400000)input sign_confirm; //确认信号output reg [3:0] led=4'b0001; //电梯指示灯output reg [3:0] number; //电梯当前楼层output sign_up,sign_down; //电梯上升下降信号output reg flag=1'b1; //电梯到达标志output reg beep = 1'b1; //蜂鸣器reg sign_up_reg = 0;reg sign_down_reg = 0; assign sign_up = sign_up_reg;assign sign_down = sign_down_reg;reg [26:0] cnt; //延时参数reg [ 3:0] level_target; //用户所在楼层值转换值(1~4)always@(posedge clk or negedge rst) beginif (!rst) beginled <= 4'b0001;cnt <= 24'd0;number <=4'b1;level_target <= 4'b1;endelse if(sign_confirm == 1'b1) level_target = level / 17'd100000;else if (cnt < 27'd25_000_000) cnt <= cnt + 1'b1;else if (cnt == 27'd25_000_000) beginif(level_target>number) beginsign_up_reg<=1;sign_down_reg<=0;led <= led << 1'b1;number<=number+4'd1;flag <=1'b0;endelse if(level_target<number) beginsign_up_reg<=0;sign_down_reg<=1;led <= led >> 1'b1;number<=number-4'd1;flag <=1'b0;endelse beginsign_up_reg<=0;sign_down_reg<=0;led[level_target-1] <= ~led[level_target-1];case(flag)1'b0: beep = 1'b0;1'b1: beep = 1'b1;endcaseflag <=1'b1;endcnt <= 27'd0; endend
endmodule
FPGA电梯控制系统相关推荐
- FPGA编程,verilog实现简易电梯控制系统,某大学数电实验课设
开发环境:Vivado 2020.1 使用编程语言:Verilog 开发板芯片:xc7a35tftg256-1(具体开发板型号未知,不同版本的开发板可能某些元件的引脚电平会不同,可能需要根据自己手上的 ...
- 【电梯控制系统】基于VHDL语言和状态机实现的电梯控制系统的设计,使用了状态机
1.软件版本 quartusii/Maxplusii 2.系统概述 电梯作为高层建筑物的重要交通工具与人们的工作和生活日益紧密联系. 电梯的三种主要控制方式中,继电器控制系统由于故障率高.可靠性差.控 ...
- 计算机原理电梯控制系统设计,《智能电梯控制系统的实现》-毕业论文(设计).doc...
PAGE 精品 题目:基于FPGA的智能电梯控制系统的实现 年 12 月 07 日 摘要 智能电梯控制系统的设计思想 智能电梯的编写的过程也不是一帆风顺的.而且我试过好多种方法去实现电梯的状态的转移. ...
- 【51单片机练习3——智能电梯控制系统1】
任务需求 2019年安徽省机器人大赛单片机与嵌入式系统应用技能竞赛试题 设计并制作智能电梯控制系统,开机后屏幕第一行显示"ZNDTKZQ",第二行显示四位数字,并自下而上滚动,3秒 ...
- 【51单片机练习3——智能电梯控制系统2】
书接上回,我们完成了步进电机和按键扫描的组合,接下来就是要实现智能电梯控制系统的各相任务需求了. 为了方便阅读,硬件介绍和软硬件原理图我再Ctrl C V一下(并没有水字数). 任务需求 2019年安 ...
- 单片机课程设计电梯(c语言),单片机课程设计之电梯控制系统.docx
PAGE \* MERGEFORMAT 23 JIANGSU UNIVERSITY OF TECHNOLOGY 单片机应用系统设计 电梯控制器 学 院: 电气信息工程学院 专 业: 测控技术与仪器 班 ...
- 电梯门禁系统服务器一般在哪,电梯控制系统与门禁系统有区别吗
随着高楼大厦的不断增多,电梯逐渐成为人们上下班必不可少的工具之一,但电梯里拥挤.复杂的乘梯环境可能会影响人们的心情,使人心情烦躁,那么怎么才可以使人们的乘梯环境有所改善呢?电梯控制系统的使用就很好的解 ...
- 电梯门禁系统服务器一般在哪,电梯控制系统与门禁系统的区别
原标题:电梯控制系统与门禁系统的区别 随着高楼大厦的不断增多,电梯逐渐成为人们上下班必不可少的工具之一,但电梯里拥挤.复杂的乘梯环境可能会影响人们的心情,使人心情烦躁,那么怎么才可以使人们的乘梯环境有 ...
- 电梯控制系统的实现(代码简洁优质、易懂)
目录 设计目的与要求 设计原理及方案 下面是设计的细节,再这里,笔者的注释都写得很清楚,因此不会啰嗦的一段段解释,只介绍关键的部分,其余的详见代码注释即可(此处建议直接看代码更好,上面的知识一个框架而 ...
- 电梯控制系统的设计与实现
电梯控制系统的设计与实现 1.设计目的 掌握8086CPU.电路板.可编程接口芯片以及8086汇编语言的应用 能够构建一个较完整的微型计算机控制系统 具备微机系统的设计能力.电子产品的制作能力和汇编语 ...
最新文章
- Android studio Day02-1
- 根号分治 ---- D. Mr. Kitayuta‘s Colorful Graph(根号均摊复杂度 + 数据结构维护)
- 整数的二进制表达中有多少个1
- 深度学习练手项目(一)-----利用PyTorch实现MNIST手写数字识别
- C++虚函数的实现原理(最通俗但并不想专业的解释)
- JQuery使用deferreds串行多个ajax请求
- php 置多条cookie,php 在cookie存储多个的简单示例
- 高斯正反算 java_高斯投影正反算的代码
- android有用代码片段 (一)
- HTML5 input新增属性
- linux自动实现项目跑,利用Linux中的crontab实现分布式项目定时任务功能
- 跨界合作成潮流 智能家居竞争升级
- maven依赖c3p0_springboot 使用c3p0数据库连接池的方法
- 电商系统中商品模型与类目体系设计
- php格式化 货币,php – 使用numberFormatter格式化货币
- java里面default是什么意思_default_default是什么意思???
- vs2015下载路径
- 免费外链资源列表汇总
- ros学习笔记13——unknown package [sensor_msgs] on search path [{{‘ros_to_deepstream
- 饥荒联机云服务器_饥荒(Don't Starve Together)腾讯云服务器搭建(unbuntu篇)