基于FPGA的多功能电子万年历设计
- 格式:doc
- 大小:447.31 KB
- 文档页数:28
FPGA-CPLD原理及应用课程设计报告题目:万年历设计学院: 信息与电子工程学院专业: 电子信息工程学号: XXXXXXXX姓名: XXXXXX指导老师: XXXXXX时间: 2015.12.20-2015.12.23一、摘要设计从系统硬件出发,由CPU、总线、RAM、外接设备等构成SOPC Builder 的硬件系统,通过Nios II DE2开发的嵌入式软件编写并嵌入SOPC Builder的硬件中实现万年历的整体开发。
通过应用SoPC Builder开发工具,设计者可以摆脱传统的、易于出错的软硬件设计细节,从而达到加快项目开发、缩短开发周期、节约开发成本的目的并具有高集成度、设计灵活和可移植性较好。
关键词:万年历 SOPC SOPC Builder Nios II DE2二、设计要求用Nios II DE2 开发板的LCD显示电子钟的日期和时间。
LCD分两行显示,第1行显示年、月、日;第2行显示时、分、秒。
用输入BUTTON[0]来控制LCD 行的修改,同时让Nios II DE2开发板上的绿色发光二极管亮灭来表示这个选择。
当BUTTON[0]按一下后,LEDG3亮,可以修改年、月和日的数字;再按一下BUTTON[0]后,LEDG3灭,可以修改时、分和秒的数字。
另外用输入按钮BUTTON[3]来控制日期和时间的修改,当处于日期修改方式时,每次按动一次BUTTON[3],依次更换“年”、“月”和“日”的修改。
当处于时间修改方式时,每次按动一次BUTTON[3],依次更换“时”、“分”和“秒”的修改。
修改对象被选中后,按动BUTTON[2]输入按钮可以增加显示的数字;按动BUTTON[1]输入按钮可以减少显示的数字。
三、设计内容1、按键信息BUTTON[3]:“年”、“月”、“日”或“时”、“分”、“秒”切换键BUTTON[2]:+键BUTTON[1]:-键BUTTON[0]:“年”、“月”、“日”与“时”、“分”、“秒”切换键显示信息LCD_Line1:显示“年”、“月”、“日”LCD_Line1:显示“时”、“分”、“秒”2、SOPC Builder 硬件建立SOPC Builder是在Quartus II里的SOPC Builder进行的,先建立工程,在SOPC Builder里添加硬件,包括CPU ,jtag_uart ,RAM,LCD,PIO,按键,LED,以及LCD_ON。
论文题目:基于FPGA的多功能电子万年历专业:电子信息工程学生:周勉签名:_______指导老师:王静签名:_______摘要多功能电子万年历能够显示年、月、日、星期、时、分、秒,能够全面的提供时间信息并能独立校对,还具有整点报时以及闹钟功能,具有功能全面、计时准确、使用方便等优点,电子万年历在家庭日常生活中已逐渐成为最主要的计时产品。
本文重点介绍了基于FPGA的多功能电子万年历的功能及实现。
本设计通过利用QUARTUS II软件来设计实现,使用verilog HDL语言进行编程设计。
论文主要对计年、计月、计日、计星期、计时、计分、计秒、整点报时以及闹钟等关键模块的设计及仿真分析进行了介绍。
此外。
基于开发板进行了下载测试,多种功能的测试结果表明了本设计的正确性。
【关键词】FPGA,QUARTUS II,verilog HDL,万年历【论文类型】应用型Title: Multi function electronic calendar based on FPGAMajor: Electronic Information EngineeringName:Mian Zhou Signature :_______ Supervisor: Jing Wang Signature :_______ABSTRACTMulti function electronic calendar can display year, month, day, week, hours, minutes and seconds, time can provide comprehensive information and independent proof, also with the whole point timekeeping, alarm clock function, has the function of comprehensive, accurate timing, convenient use, electronic calendar in daily life at home has gradually become the main the timing of product.This paper focuses on the function and implementation of multi-functional electronic calendar based on FPGA. The design through the use of QUARTUS II software design and implementation, using Verilog HDL programming language design. The paper mainly introduces the design and simulation analysis of the key modules such as year, month, day, week, time, score, seconds, clock, alarm clock and so on. Besides. The download test is carried out based on the development board, and the test results of several functions show the correctness of the design.【Key words】FPGA,QUARTUS II,verilog HDL,calendar【Type of Thesis】Applied目录摘要 (I)ABSTRACT (II)目录 (III)1 绪论 (1)1.1课题研究背景 (1)1.2 EDA及FPGA技术介绍 (1)1.2.1 EDA 技术介绍及现状 (1)1.2.2 FPGA技术简介 (2)1.3 Quartus II开发环境概述 (3)1.4 硬件描述语言Verilog HDL简介 (3)1.5论文内容简介 (4)2 多功能电子万年历的总体设计方案 (5)2.1系统主要功能 (5)2.2 系统设计方案与步骤 (5)2.3主要器件 (6)2.4系统整体框图 (8)3 各模块设计方案与波形仿真 (9)3.1 分频器模块 (9)3.2 时分秒模块 (9)3.3 年月日星期模块 (10)3.4 闹钟模块 (11)3.5蜂鸣器模块 (13)3.6 主控制模块 (13)3.7校时选择模块 (14)3.8 显示选择模块 (15)3.9 数码管显示模块 (16)4 硬件检测及调试 (17)总结与展望 (21)致谢 (22)附录 (23)参考文献 (36)1 绪论1.1课题研究背景进入21世纪以来,电子技术在人们的日常生活、生产中,扮演着越来越重要的角色。
郑州大学西亚斯国际学院本科毕业论文(设计)题目基于FPGA的万年历的设计指导教师周晓平职称讲师学生姓名陈重学号20111521131 专业电子信息工程班级电信(1)班院(系)电子信息工程学院完成时间2015年4月7号基于FPGA的万年历的设计摘要基于FPGA的万年历的设计,基本功能是用来显示年月日时分秒及时间修改功能。
数字日历是采用数字电路实现对ho、mi、se计时的装置,主要包括组合逻辑电路与时序电路,主要完成的功能是使用VerilogHDL语言,在QuartusII上完成电路设计,模拟程序开发,基本功能是能够显示/修改ho、mi、se,主要有:主要遥控模块、时间及其数据显示调设、时间多路选择、显示调整、日期的自动工作与设置、秒表计时模块、钟表模块、频率选取模块、译码器组成万年历的系统电路设计。
软件模拟直接在FPGA软件上进行编译仿真与实验开发板共同完成。
对于程序的编写使用VerilogHDL语言,根据不同模块的功能和各个模块之间的相互作用控制关系进行编译仿真。
电子万年历是采用的是以秒表计时显示时间的工具,大量运用于居室、办公室、商场、汽车站、火车站等场合。
与古老的钟表进行比较拥有较好的精准性、灵活性、美观性、并拥有较长的使用年限。
数字万年历主要包括组合逻辑电路与时序电路,还能展现自动报警、定时广播信息等功能。
数字电子万年历采用软件开发模拟,使开发生产的成本大大降低,而且功能上有很强的灵活性,如果想改变它的功能只需要在软件上进行修改就能完成。
相对于老式钟表来讲精度大大增加,并且维修改动更为方便,也不用像日历一样每天翻页,使人们的的生活更加方便。
因此研究数字万年历有非常重要现实意义,匹配当前电子仪器的开发优势,对于当前市场也有相当大的潜力。
关键词FPGA /万年历/VerilogHDL/QuartusIIBASED ON THE DESIGN OF THECALENDARFPGA CIRCULTABSTRACTCalendar design based on FPGA, which basic function is to display date with the change of time. Digital calendar is realized by using digital circuit to record time . Digital circuits mainly includes the combinational logic and sequential circuits , Its main task is to use VerilogHDL language to complete circuit design and simulation on the QuartusII .its basic function is to be able to display or modify time Circuit is divided into combination logic andsequential,mainlyincludefrequency division ,control ,adjustment of time display ,date ,time ,display control ,code translator.software simulation directly conducted on QuartusII and FPGA adaptor .For the writing of the program use VerilogHDL language ,according to the features of different modules and interaction control of the relationship between various modules compiled simulation.The digital Calendar is realized by using digital circuit minutes and seconds for timing device .it is widely used in home .office shopping malls ,railway stations etc .Compared with the old clock has better accuracy ,flexibility ,beautiful and has a longer life ,The digital calendar mainly includes the assembly logic circuit and sequential circuits ,also can show the function such as automatic alarm, timing ,broadcast , information. The digital calendar adopts the model of software develop the modifications will finish on the software ,it makes the cost greatly reduced and the function has a strong flexibility .If you want to change its function as long as modifying on the software.Relative to the old clock precision is greatly precision and the maintenance is more convenient to change ,also need not every day turn over a calendar page ,making people’s life more convenient .So significance to research the digital calendar its application has a broad market prospect.KEYWORDS FPGA ,C alendar ,VerilogHDL ,QuartusII目录中文摘要 (Ⅰ)英文摘要 (II)1 FPGA及数字电子万年历简介 (3)1.1 FPGA简介 (3)1.2 数字电子万年历的未来发展 (4)2 数字电子万年历的工作原理 (5)3 数字电子万年历各功能模块的实现 (6)3.1 时钟类型 (6)3.2 数字电子万年历的主要系统 (8)3.3 数字电子万年历主控制模块 (8)3.4 时间及其数据设置模块 (9)3.4.1 时间模块 (9)3.4.2 时间设置模块 (11)3.4.3 时间数据与时间设置数据多路选择模块 (12)3.5 时间显示动态位选模块 (14)3.6 显示模块 (15)3.7 秒表模块 (16)3.8 日期显示设置模块 (17)3.8.1 日期自动工作模块 (17)3.8.2 日期设置模块 (18)3.9 闹钟模块 (19)3.10 分频模块 (20)致谢 (23)参考文献 (24)附录 (25)1 FPGA及数字电子万年历简介1.1FPGA简介FPGA是现场可编程门列阵(Field programmable gates array)的简单缩写,是CPLD、PAL等数字元器件原有上的进步,是由可编程模块组成的专用进制式线路,属于半定制的电路。
基于FPGA的电子万年历的设计与实现
李承铭;王佳欣;柯骏;李丝天;李翔;陈初侠
【期刊名称】《电脑知识与技术》
【年(卷),期】2024(20)4
【摘要】文章基于FPGA芯片EP4CE6E22C8设计了一款电子万年历。
首先根据设计要求,将电子万年历分成多个底层电路并用VerilogHDL语言对其进行设计和仿真,然后调用已设计好的各底层电路采用原理图方式设计顶层电路,最后对设计好的顶层电路进行管脚锁定并下载到FPGA芯片中进行硬件验证。
结果表明,所设计的电子万年历能实现秒、分、时、星期、日、月、年的显示、时间的设置和整点报时功能,集多功能于一体,具有较好的实用性。
【总页数】4页(P106-109)
【作者】李承铭;王佳欣;柯骏;李丝天;李翔;陈初侠
【作者单位】巢湖学院电子工程学院
【正文语种】中文
【中图分类】TP29
【相关文献】
1.基于AT89S52单片机的电子万年历设计与实现
2.基于LED点阵显示的电子万年历的设计与实现
3.基于I2C总线电子万年历的设计与实现
4.基于FPGA的电子万年历设计
5.一种电子万年历的设计与实现
因版权原因,仅展示原文概要,查看原文内容请购买。
接着我的上一篇博文,终于完善好了,前几天太忙了,没有及时上传,呵呵,今天晚上刚比较早刚好凌晨,及时上传一下,实现了从0000---9999年的时钟,其实万年历和十万年历,都是差不多,等到地球能转到9999年再改代码也不迟,哈哈!!我这里有顶层和底层文件,顶层主要是调用模块和做按键处理,具体按键防抖动原理,参见偶的以前的博文,我写完这个万年历的代码,还没来得及优化,占用了太多了逻辑门,可以进一步优化。
大致思路是:第一次按下KEY1 的时候,所有计时停止,再按KEY1,年就闪烁,按下KEY2和KEY3 进行加减。
再按KEY1,月就闪烁,按下KEY2和KEY3 进行加减........依次为调年-月-日-星期-时分秒,再次按一下KEY1,进入正常运行模式。
好了先上顶层模块module LCD(rst,clk,rw,rs,en,data,key1,key2,key3);input clk,rst;input key1,key2,key3;output rs,en,rw;output [7:0] data;reg key1_out,key2_out,key3_out;wire clk,rst;wire rs,en,rw;wire [7:0] data;disp U1(.clk(clk),.rst(rst),.rs(rs),.en(en),.rw(rw),.data(data),.key1(key1_out),.key2(key2_out),.key3(key3_out));//=============key1,key2,key3 按键防抖动================// reg key1_reg1,key1_reg2;reg key2_reg1,key2_reg2;reg key3_reg1,key3_reg2;reg [31:0] count;always @(posedge clk)begincount<=count+1;if(count==500000)begincount<=0;key1_reg1<=key1;key2_reg1<=key2;key3_reg1<=key3;endkey1_reg2<=key1_reg1;key2_reg2<=key2_reg1;key3_reg2<=key3_reg1;key1_out <= key1_reg2 & (!key1_reg1);key2_out <= key2_reg2 & (!key2_reg1);key3_out <= key3_reg2 & (!key3_reg1);endendmodule底层模块:module disp(rst,clk,rw,rs,en,data,key1,key2,key3);input clk,rst;input key1,key2,key3;output rs,en,rw;output [7:0] data;reg rs,en_sel;reg [7:0] data;reg [14:0] year;reg [7:0] shi,fen,miao,month,dat;reg [31:0]count,count1; //LCD CLK 分频计数器reg lcd_clk;//2行32个数据寄存器reg [7:0]one_1,one_2,one_3,one_4,one_5,one_6,one_7,one_8,one_9,one_10,one_11,one_12,on e_13,one_14,one_15,one_16;reg [7:0]two_1,two_2,two_3,two_4,two_5,two_6,two_7,two_8,two_9,two_10,two_11,two_12,two_ 13,two_14,two_15,two_16;reg [7:0] next;parameter state0 =8'h00, //设置8位格式,2行,5*7 8'h38;state1 =8'h01, //整体显示,关光标,不闪烁8'h0C 闪烁8'h0estate2 =8'h02, //设定输入方式,增量不移位8'h06state3 =8'h03, //清除显示8'h01state4 =8'h04, //显示第一行的指令80Hstate5 =8'h05, //显示第二行的指令80H+40Hscan =8'h06,nul =8'h07;parameter data0 =8'h10, //2行32个数据状态data1 =8'h11,data2 =8'h12,data3 =8'h13,data4 =8'h14,data5 =8'h15,data6 =8'h16,data7 =8'h17,data8 =8'h18,data9 =8'h19,data10 =8'h20,data11 =8'h21,data12 =8'h22,data13 =8'h23,data14 =8'h24,data15 =8'h25,data16 =8'h26,data17 =8'h27,data18 =8'h28,data19 =8'h29,data20 =8'h30,data21 =8'h31,data22 =8'h32,data23 =8'h33,data24 =8'h34,data25 =8'h35,data26 =8'h36,data27 =8'h37,data28 =8'h38,data29 =8'h39,data30 =8'h40,data31 =8'h41;initialbegin//第一行显示年-月-日星期//Mon Tue Wed Thur Fri Sat Sunone_1<=" "; one_2<=" "; one_3<=" "; one_4<=" "; one_5<="-"; one_6<=" "; one_7<=" "; one_8<="-";one_9<=" ";one_10<=" ";one_11<=" ";one_12<=" ";one_13<=" ";one_14<="";one_15<=" ";one_16<=" ";//第二行显示Clock:00-00-00two_1<="C"; two_2<="l"; two_3<="o"; two_4<="c"; two_5<="k"; two_6<=":"; two_7<=" "; two_8<=" ";two_9<="-";two_10<=" ";two_11<=" ";two_12<="-";two_13<=" ";two_14<="";two_15<=" ";two_16<=" ";shi<=8'd0;fen<=8'd0;miao<=8'd0;end//======================产生LCD 时序脉冲=========================== always @ (posedge clk ) //获得LCD时钟begincount<=count+1;if(count==32'd50000)begincount<=32'b0;lcd_clk<=~lcd_clk;endend//=====================产生闪烁扫描时钟===========================reg [31:0] count2;reg scan_flag;always @ (posedge clk or negedge rst) //获得校准时间选中闪烁状态beginif(!rst)beginscan_flag<=1'b0;endelsebegincount2<=count2+1;if(count2==32'd1*******)begincount2<=32'b0;scan_flag<=~scan_flag;endendend//====================产生按键标志位================================= reg [3:0] flag;always @ (posedge clk or negedge rst )beginif(!rst)beginflag<=4'b0;endelseif(key1)beginflag<=flag+1'b1;if(flag==4'b1000)flag<=4'b0000;endend//===================计时以及校准=======================================reg[3:0] week;reg[7:0] dat_flag;always @ (posedge clk or negedge rst ) //时钟计数器beginif(!rst)begin //初始化显示第一行2012-05-19 Sat 第二行:Clock:00-00-00 shi<=8'b0;fen<=8'b0;miao<=8'b0;month<=8'd5;dat<=8'd19;year<=16'd2012;week<=4'd5;count1<=1'b0;two_7<= (shi/8'd10)+8'b00110000;two_8<= (shi%8'd10)+8'b00110000;two_10<=(fen/8'd10)+8'b00110000;two_11<=(fen%8'd10)+8'b00110000;two_13<=(miao/8'd10)+8'b00110000;two_14<=(miao%8'd10)+8'b00110000;one_1<=(year/16'd1000)+8'b00110000;one_2<=((year%16'd1000)/16'd100)+8'b00110000;one_3<=((year%16'd100)/8'd10)+8'b00110000;one_4<=(year%8'd10)+8'b00110000;one_6<=(month/8'd10)+8'b00110000;one_7<=(month%8'd10)+8'b00110000;one_9<=(dat/8'd10)+8'b00110000;one_10<=(dat%8'd10)+8'b00110000;endelsebegintwo_7<= (shi/8'd10)+8'b00110000;two_8<= (shi%8'd10)+8'b00110000;two_10<=(fen/8'd10)+8'b00110000;two_11<=(fen%8'd10)+8'b00110000;two_13<=(miao/8'd10)+8'b00110000;two_14<=(miao%8'd10)+8'b00110000;one_1<=(year/16'd1000)+8'b00110000;one_2<=((year%16'd1000)/16'd100)+8'b00110000;one_3<=((year%16'd100)/8'd10)+8'b00110000;one_4<=(year%8'd10)+8'b00110000;one_6<=(month/8'd10)+8'b00110000;one_7<=(month%8'd10)+8'b00110000;one_9<=(dat/8'd10)+8'b00110000;one_10<=(dat%8'd10)+8'b00110000;// 判断是否为31天的月份if(month==8'd1||month==8'd3||month==8'd5||month==8'd7||month==8'd8||month==8'd10|| month==8'd12)dat_flag<=8'd31;// 判断是否为30天的月份else if(month==8'd4||month==8'd6||month==8'd9||month==8'd11)dat_flag<=8'd30;// 判断是否为闰年和平年else if(month==8'd2)beginif(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)dat_flag<=28;else dat_flag<=27;endcase (week)//星期//Mon Tue Wed Thu Fri Sat Sun4'b0000 : //1beginone_13<="M";one_14<="o";one_15<="n";end4'b0001 : //2beginone_13<="T";one_14<="u";one_15<="e";end4'b0010 : //3beginone_13<="W";one_14<="e";one_15<="d"; end4'b0011 : //4beginone_13<="T";one_14<="h";one_15<="u"; end4'b0100 : //5beginone_13<="F";one_14<="r";one_15<="i"; end4'b0101 : //6beginone_13<="S";one_14<="a";one_15<="t"; end4'b0110 : //7beginone_13<="S";one_14<="u";one_15<="n"; endendcasecase(flag)4'b0000 :beginen_sel<=1'b1;count1<=count1+1'b1;if(count1==32'd4*******)begincount1<=1'b0;miao<=miao+1'b1;if(miao==8'd59)beginmiao<=1'b0;fen<=fen+1'b1;if(fen==8'd59)beginfen<=1'b0;shi<=shi+1'b1;if(shi==8'd23)beginshi<=1'b0;dat<=dat+1'b1;week<=week+1'b1;if(week==4'b0110)week<=1'b1;if(dat==dat_flag)begindat<=8'd1;month<=month+1'b1;if(month==8'd12)beginmonth<=8'd1;year<=year+1'b1;if(year==16'd9999)year<=16'd0; //可以计1万年endendendendendendend4'b0001 :begincount1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;year<=year;month<=month;dat<=dat;week<=week;end4'b0010 : //调年begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_1<=8'd20;one_2<=8'd20;one_3<=8'd20;one_4<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginyear<=year+1'b1;if(year==16'd9999)year<=16'd0;endif(key3) //减数beginyear<=year-1'b1;if(year==16'd0)year<=16'd9999;endend4'b0011 : //调月begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_6<=8'd20;one_7<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endcaseif(key2) //加数beginmonth<=month+1'b1;if(month==8'd12)month<=8'd0;endif(key3) //减数beginmonth<=month-1'b1;if(month==8'd0)month<=8'd12;endend4'b0100 : //调日begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_9<=8'd20;one_10<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数begindat<=dat+1'b1;if(dat==dat_flag)dat<=8'd0;endif(key3) //减数dat<=dat-1'b1;if(dat==8'd0)dat<=dat_flag;endend4'b0101 : //调星期begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_13<=8'd20;one_14<=8'd20;one_15<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginweek<=week+1'b1;if(week==4'd6)week<=4'd0;endif(key3) //减数beginweek<=week-1'b1;if(week==4'd0)week<=4'd7;endend4'b0110 : //调时begincase(scan_flag)begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;two_7<= 8'd20;two_8<= 8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginshi<=shi+8'b00000001;if(shi==8'd23)shi<=8'b0;endif(key3) //减数beginshi<=shi-8'b00000001;if(shi==8'b0)shi<=23;endend4'b0111 : //调分begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;two_10<=8'd20;two_11<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginfen<=fen+8'b00000001;if(fen==8'd59)fen<=8'b0;endif(key3) //减数beginfen<=fen-8'b00000001;if(fen==8'b0)fen<=59;endend4'b1000 : //调秒begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;two_13<=8'd20;two_14<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginmiao<=miao+8'b00000001;if(miao==8'd59)miao<=8'b0;endif(key3) //减数beginmiao<=miao-8'b00000001;if(miao==8'b0)miao<=59;endendendcaseendendalways @(posedge lcd_clk )begincase(next)state0 :begin rs<=1'b0; data<=8'h38; next<=state1; endstate1 :begin rs<=1'b0; data<=8'h0e; next<=state2; endstate2 :begin rs<=1'b0; data<=8'h06; next<=state3; endstate3 :begin rs<=1'b0; data<=8'h01; next<=state4; endstate4 :begin rs<=1'b0; data<=8'h80; next<=data0; end //显示第一行data0 :begin rs<=1'b1; data<=one_1; next<=data1 ; enddata1 :begin rs<=1'b1; data<=one_2; next<=data2 ; enddata2 :begin rs<=1'b1; data<=one_3; next<=data3 ; enddata3 :begin rs<=1'b1; data<=one_4; next<=data4 ; enddata4 :data5 :begin rs<=1'b1; data<=one_6; next<=data6 ; enddata6 :begin rs<=1'b1; data<=one_7; next<=data7 ; enddata7 :begin rs<=1'b1; data<=one_8; next<=data8 ; enddata8 :begin rs<=1'b1; data<=one_9; next<=data9 ; enddata9 :begin rs<=1'b1; data<=one_10; next<=data10 ; enddata10 :begin rs<=1'b1; data<=one_11; next<=data11 ; enddata11 :begin rs<=1'b1; data<=one_12; next<=data12 ; enddata12 :begin rs<=1'b1; data<=one_13; next<=data13 ; enddata13 :begin rs<=1'b1; data<=one_14; next<=data14 ; enddata14 :begin rs<=1'b1; data<=one_15; next<=data15 ; enddata15 :begin rs<=1'b1; data<=one_16; next<=state5 ; endstate5:begin rs<=1'b0;data<=8'hC0; next<=data16; end //显示第二行data16 :begin rs<=1'b1; data<=two_1; next<=data17 ; enddata17 :begin rs<=1'b1; data<=two_2; next<=data18 ; enddata18 :begin rs<=1'b1; data<=two_3; next<=data19 ; enddata19 :begin rs<=1'b1; data<=two_4; next<=data20 ; enddata20 :data21 :begin rs<=1'b1; data<=two_6; next<=data22 ; enddata22 :begin rs<=1'b1; data<=two_7; next<=data23 ; enddata23 :begin rs<=1'b1; data<=two_8; next<=data24 ; enddata24 :begin rs<=1'b1; data<=two_9; next<=data25 ; enddata25 :begin rs<=1'b1; data<=two_10; next<=data26 ; end data26 :begin rs<=1'b1; data<=two_11; next<=data27 ; end data27 :begin rs<=1'b1; data<=two_12; next<=data28 ; end data28 :begin rs<=1'b1; data<=two_13; next<=data29 ; end data29 :begin rs<=1'b1; data<=two_14; next<=data30 ; end data30 :begin rs<=1'b1; data<=two_15; next<=data31 ; end data31 :begin rs<=1'b1; data<=two_16; next<=scan ; endscan : //交替更新第一行和第二行数据beginnext<=state4;enddefault: next<=state0;endcaseendassign en=lcd_clk && en_sel;assign rw=1'b0;endmodule。
library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity clock isport(rst:in std_logic;clk:in std_logic;clr:in std_logic;display_mode: in std_logic;inc:in std_logic;mode:in std_logic;seg8:out std_logic_vector(7 downto 0);scan:out std_logic_vector(7 downto 0);led:out std_logic_vector(3 downto 0) );end;architecture one of clock is--signal state:std_logic_vector(2 downto 0);--signal dis_mode:std_logic_vector(1 downto 0);signal state:integer range 0 to 7;signal dis_mode:integer range 0 to 3;--signal qhh,qhl,qmh,qml,qsh,qsl,qy1,qy2,qy3,qy4,qm1,qm2,qd1,qd2:std_logic_vector(3 downto 0);signal qhh,qhl,qmh,qml,qsh,qsl,qy1,qy2,qy3,qy4,qmonl,qmonh,qdl,qdh:integer range 0 to 15; signal data:integer range 0 to 15 ;signal cnt:integer range 0 to 7;signal clk1khz,clk1hz,clk2hz,clk5ms:std_logic;--signal blink:std_logic_vector(2 downto 0);--signal inc_reg:std_logic;signal sec,min:integer range 0 to 59;signal hour:integer range 0 to 23;signal year:integer range 1 to 9999;signal month:integer range 1 to 12;signal day,day_limit:integer range 1 to 31;beginprocess(clk)variable count:integer range 0 to 30000;beginif clk'event and clk='1' thenif count=25000 then clk1khz<=not clk1khz;count:=0;else count:=count+1;end if;end if;end process;-------------------------------------------------------process (clk)variable cnte:integer range 0 to 30000000;beginif clk'event and clk ='1' thenif cnte=25000000 then clk1hz<=not clk1hz; cnte:=0;else cnte:=cnte+1;end if ;end if ;end process ;-----------------------------------------------------process (clk)variable cnt2:integer range 0 to 25000000;beginif clk'event and clk='1' thenif cnt2=12500000 then clk2hz<=clk2hz;cnt2:=0;else cnt2:=cnt2+1;end if ;end if ;end process;-----------------------------------------------------process(clk)variable cnnt:integer range 0 to 600000;beginif clk'event and clk='1' thenif cnnt=500000 then clk5ms<=clk5ms;cnnt:=0;else cnnt:=cnnt+1;end if ;end if ;end process;-----------------------------------------------------------------------------------------process(display_mode , clk1hz)beginif display_mode'event and display_mode='0' then dis_mode<=dis_mode+1;if dis_mode=1 thendis_mode<=0;end if;end if;end process;-------------------------------------------process(clk)beginyear<=year;month<= month;day<=day;hour<=hour;min<=min;sec<=sec;end process;-----------------------------------------process(mode , clr,clk1hz)beginif clr='0' thenstate<=0;elsif mode'event and mode='0' thenstate<=state+1;if state=6 thenstate<=0;end if;end if ;end process;----------------------------------------------------------------------------------- process(clk1hz,state,dis_mode,inc,clr,hour,sec,min,rst,year,month,day) beginif rst='0' thenyear<=2000;month<=2;day<=25;hour<=0;min<=0;sec<=0;--state<=0;--dis_mode<=0;elsif clr='0' thenhour<=23;min<=59;sec<=55;year<=4164;month<=1;day<=25;elsif clk1hz'event and clk1hz='1' thencase state iswhen 0 => led<="0000";if((month=1)or(month=3)or(month=5)or(month=7)or(month=8)or(month=10)or(month=12)) thenday_limit<=31;end if;if month=2 then----if((year%4==0&&year%100!=0)||(year%400==0))if ((((year rem 4)=0) and ((year rem 100)/=0)) or ((year rem 400=0))) thenday_limit<=29;elseday_limit<=28;end if;end if;if((month=4)or(month=6)or(month=9)or(month=11)) thenday_limit<=30;end if;sec<=sec+1;if sec=59 thensec<=0;min<=min+1;if min=59 thenmin<=0;hour<=hour+1;if hour =23 thenhour<=0;day<=day+1;if day=day_limit thenday<=1;month<=month+1;if month=12 thenmonth<=1;year<=year+1;if year=9999 thenyear<=1;end if;end if;end if;end if;end if;end if;--if sec=59 then sec<=0;--if min=59 then min<=0;--if hour=23 then hour<=0;--else--hour<=hour+1;--end if;--else--min<=min+1;--end if;--else--sec<=sec+1;--end if;when 1=> led<="0001";if inc='0' thenif hour=23 thenhour<=0;else hour<=hour+1;end if;end if;when 2=>led<="0010" ;if inc='0' thenif min=59 thenmin<=0;elsemin<=min+1;end if;end if;when 3=>led<="0011" ;if inc='0' thenif sec=59 thensec<=0;elsesec<=sec+1;end if;end if;when 4 =>led<="0100";if inc='0' thenif year=9999 thenyear<=1;elseyear<=year+1;end if;end if;when 5=> led <="0101";if inc='0' thenif month=12 thenmonth<=1;elsemonth<=month+1;end if;end if;when 6 =>led <="0110";if inc='0' thenif day=day_limit thenday<=1;elseday<=day+1;end if;end if;when others =>null;end case;end if;--end if;end process;---------------------------------------------------------------------- process(sec)begincase sec iswhen 0|10|20|30|40|50 => qsl<=0;when 1|11|21|31|41|51 => qsl<=1;when 2|12|22|32|42|52 => qsl<=2;when 3|13|23|33|43|53 => qsl<=3;when 4|14|24|34|44|54 => qsl<=4;when 5|15|25|35|45|55 => qsl<=5;when 6|16|26|36|46|56 => qsl<=6;when 7|17|27|37|47|57 => qsl<=7;when 8|18|28|38|48|58 => qsl<=8;when 9|19|29|39|49|59 => qsl<=9;when others =>null;end case;case sec iswhen 0|1|2|3|4|5|6|7|8|9 => qsh<=0;when 10|11|12|13|14|15|16|17|18|19 => qsh<=1;when 20|21|22|23|24|25|26|27|28|29 => qsh<=2;when 30|31|32|33|34|35|36|37|38|39 => qsh<=3;when 40|41|42|43|44|45|46|47|48|49 => qsh<=4;when 50|51|52|53|54|55|56|57|58|59 => qsh<=5;when others =>null;end case;end process;-------------------------------------------------------------------- process(min)begincase min iswhen 0|10|20|30|40|50 => qml<=0;when 1|11|21|31|41|51 => qml<=1;when 2|12|22|32|42|52 => qml<=2;when 3|13|23|33|43|53 => qml<=3;when 4|14|24|34|44|54 => qml<=4;when 5|15|25|35|45|55 => qml<=5;when 6|16|26|36|46|56 => qml<=6;when 7|17|27|37|47|57 => qml<=7;when 8|18|28|38|48|58 => qml<=8;when 9|19|29|39|49|59 => qml<=9;when others =>null;end case;case min iswhen 0|1|2|3|4|5|6|7|8|9 => qmh<=0;when 10|11|12|13|14|15|16|17|18|19 => qmh<=1;when 20|21|22|23|24|25|26|27|28|29 => qmh<=2;when 30|31|32|33|34|35|36|37|38|39 => qmh<=3;when 40|41|42|43|44|45|46|47|48|49 => qmh<=4;when 50|51|52|53|54|55|56|57|58|59 => qmh<=5;when others =>null;end case;end process;----------------------------------------------------------------------- process(hour)begincase hour iswhen 0|10|20 => qhl<=0;when 1|11|21 => qhl<=1;when 2|12|22 => qhl<=2;when 3|13|23 => qhl<=3;when 4|14 => qhl<=4;when 5|15 => qhl<=5;when 6|16 => qhl<=6;when 7|17 => qhl<=7;when 8|18 => qhl<=8;when 9|19 => qhl<=9;when others =>null;end case;case hour iswhen 0|1|2|3|4|5|6|7|8|9 => qhh<=0;when 10|11|12|13|14|15|16|17|18|19 => qhh<=1;when 20|21|22|23 => qhh<=2;when others => null;end case;end process;---------------------------------------------------------------process(year)beginqy1<=year/1000;qy2<=(year rem 1000)/100;qy3<=((year rem 1000)rem 100)/10;qy4<=((year rem 1000)rem 100) rem 10;--qy1<=year/1000;--qy2<=(year rem 1000)/100;--qy3<=((year-(year/1000)*1000)-((year-(year/1000)*1000)/100)*100)/10; --qy4<=((year rem 1000)rem 100)rem 10;end process;----------------------------------------------------------------process(month)beginqmonh<=month/10;qmonl<=month rem 10;end process;-----------------------------------------------------------------process(day)beginqdh<=day/10;qdl<=day rem 10;end process;----------------------------------------------------------------process(clk1khz)beginif clk1khz'event and clk1khz='1' thenif cnt=7 thencnt<=0;else cnt<=cnt+1;end if;end if;end process;----------------------------------------------------------process (cnt,qhh,qhl,qmh,qml,qsh,qsl,dis_mode)begincase dis_mode iswhen 0 => case cnt iswhen 0 => data<=qsl; scan<="11111110";when 1 => data<=qsh; scan<="11111101";when 2 => data<=15 ; scan<="11111111";when 3 => data<=qml; scan<="11110111";when 4 => data<=qmh; scan<="11101111";when 5 => data<=15; scan<="11111111";when 6 => data<=qhl; scan<="10111111";when 7 => data<=qhh; scan<="01111111";when others => null;end case;when 1=> case cnt iswhen 0 => data<=qdl; scan<="11111110";when 1 => data<=qdh; scan<="11111101";when 2 => data<=qmonl ; scan<="11111011";when 3 => data<=qmonh; scan<="11110111";when 4 => data<=qy4; scan<="11101111";when 5 => data<=qy3; scan<="11011111";when 6 => data<=qy2; scan<="10111111";when 7 => data<=qy1; scan<="01111111";when others =>null;end case;when others => null;end case;end process;----------------------------------------------------------------------------------process(data)begincase data iswhen 0 =>seg8<="11000000";when 1 =>seg8<="11111001";when 2 =>seg8<="10100100";when 3 =>seg8<="10110000";when 4 =>seg8<="10011001";when 5 =>seg8<="10010010";when 6 =>seg8<="10000010";when 7 =>seg8<="11111000";when 8 =>seg8<="10000000";when 9 =>seg8<="10010000";when others =>seg8<="11111111";end case ;end process;end;。
基于FPGA的多功能万年历1. 绪论现代科技在不断进步电子技术在不断发展,电子产品设计复杂程度也在不断增加。
而且电子产品的更新换代也越来越快,现在只靠传统的纯硬件的设计方法已经不能满足现代人们的要求。
EDA就是典型的硬件设计软件化的设计平台。
EDA是一项非常先进的技术,它有许多别的技术没有的优点:像单片机需要先画出硬件图再编写相对应的程序,而EDA是先编好程序再画图的,而且模块化的编程还会在软件中生成相应的封装元件,使最后画原理图变的更加简单;可以编好程序就直接仿真,程序出现错误可以在源文件内部直接改;并且设计好的总系统可以集成在一个体积小、功耗低、可靠性高的芯片上。
本设计采用VHDL语言,VHDL语言是一种全方位的数字系统设计和测试的硬件描述。
它支持原理图输入方法以及传统的文件输入方。
对于前者适用于小规模的数字集成电路,并进行模拟仿真。
而对于大规模的、复杂的系统,如果用纯原理图设计方法的话的,由于种种条件和环境制约,会导致工作效率底而且容易出错的等缺点。
在信息技术的今天,集成电路逐渐的趋向于系统化、微尺寸化、低功耗高集成化,因此,高密度可编程逻辑器件和VHDL越来越得到设计者的青睐。
它具有极强的描述能力,支持结构、数据流、行为三种描述形式的混合的设计方式,描覆盖面广、抽象能力强。
它能支持系统行为级、逻辑门级和寄存器传输级三个不同层次的设计。
在本设计中用到的FPGA是特殊的ASIC芯片,ASIC是一种带有逻辑处理的加速处理器的专用的系统集成电路。
它具有功耗低、速度快、集成度、设计制造成本低等优点。
本设计是研究基于FPGA的多功能万年历的设计,主要实现以下功能:能够显示年、月、日、时、分、秒,时间采用24小时制。
当时间不准确时还可以手动校准。
本系统还能实时的显示当前的温度,扩展了万年历的功能。
我采用的是数字温度传感器DS18B20和FPGA组成的温度采集系统,此系统具有硬件电路简单,抗干扰能力强等优点。
大连海事大学毕业论文Array二○一四年六月VHDL设计FPGA数字系统:电子万年历专业班级: 电子信息工程10-2班姓名: 牛舒雅指导老师: 严飞信息科学技术学院摘要随着EDA(电子设计自动化)技术的发展和应用领域的扩大,EDA技术在电子信息、通信、自动化控制及计算机应用领域的重要性日益突出。
钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能,诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、定时启闭路灯等。
所有这些,都是以钟表数字化为基础的。
因此,研究基于FPGA的电子万年历及扩大其应用,有非常现实的意义。
EDA的关键技术之一是用形式化方法来描述数字系统的硬件电路、即用所谓的硬件描述语言来描述硬件电路。
本设计是用VHDL语言编程实现基于FPGA的电子万年历。
在设计中,首先介绍了万年历的设计思路,确定各功能模块,而后在Quartus II开发环境中用VHDL语言对各模块进行编程,编译成功后完成仿真,并逐一调试程序使各模块达到设计目的。
然后,将各模块生成的元器件连接起来,形成顶层原理图文件,进行系统仿真。
最后,对顶层原理图进行引脚设定,并下载到试验箱验证,证明系统的可行性。
关键字:EDA;VHDL ;万年历;Quartus IIABSTRACTWith the development of EDA (electronic design automation) technology and expansion of application fields ,the importance of EDA technology in electronic information, communication, auto control, and computer applications is becoming increasingly prominent. EDA technology is the core of the modern electronic design techniques, which rely on powerful computers . In EDA tools software platform, computer automatically completes logic simplification,logical partitions, logic synthesis , logic optimization ,logical simulation and other functions until the electronic circuit system achieves the stated performance. However, the realization of these function bases on the description of the system using the hardware description language HDL (Hardware Description language) . One of the key technologies of the EDA is to use formal methods to describe digital systems hardware circuit, which uses the so-called hardware description language to describe the hardware circuit.The design is the calendar based on VHDL language. Firstly, in which ,I introduce ideas about designing the calendar. In addition, I compile and simulate the program of different modules in the Quartus II development environment and debug one by one to make different modules meet objectives of the design. Secondly, I take advantage of all components,which is created according to program to generate top-level file . Finally, I make pin settings and download to the test chamber to prove the feasibility of the system.Key words: EDA;VHDL ;calendar;Quartus II目录第1章绪论 (1)1.1钟的起源 (1)1.2钟的现状以及发展 (1)1.3电子万年历的简介 (1)1.4VHDL设计FPGA数字系统:电子万年历的设计要求 (2)1.5 本章小结 (2)第2章开发技术基础 (3)2.1 EDA技术简介 (3)2.1.1 EDA技术基本概述 (3)2.1.2EDA技术发展与发展方向 (3)2.2FPGA基本介绍 (4)2.2.1FPGA简介 (4)2.2.1FPGA组成 (5)2.3VHDL语言概述 (5)2.3.1VHDL语言特点 (6)2.3.2VHDL语言结构 (7)2.4Quartus II软件介绍 (7)2.5ZY11EDA13BE实验系统介绍 (8)2.5.1 ZY11EDA13BE实验系统的特点 (8)2.5.2ZY11EDA13BE实验系统主板组成 (8)2.6本章小结 (9)第3章电子万年历的设计 (10)3.1设计思想 (10)3.2 设计框图 (11)3.3 设计流程图 (12)3.4 本章小结 (15)第4章电子万年历的设计、仿真与展示 (16)4.1 模块分析 (16)4.1.1 秒与分的计数器模块 (16)4.1.3 日计数器模块 (18)4.1.4月计数器模块 (21)4.1.5年低位计数器模块 (22)4.1.6年高位计数器模块 (23)4.1.7校准模块 (24)4.1.8 显示以及显示内容切换模块 (26)4.2顶层原理图 (27)4.3 管脚锁定 (29)4.4电子万年历的展示 (29)4.5本章小结 (30)第5章总结 (31)参考文献 (32)致谢 (33)第1章绪论1.1钟的起源中国古代很早就用日晷计时。
接着我的上一篇博文,终于完善好了,前几天太忙了,没有及时上传,呵呵,今天晚上刚比较早刚好凌晨,及时上传一下,实现了从0000---9999年的时钟,其实万年历和十万年历,都是差不多,等到地球能转到9999年再改代码也不迟,哈哈!!我这里有顶层和底层文件,顶层主要是调用模块和做按键处理,具体按键防抖动原理,参见偶的以前的博文,我写完这个万年历的代码,还没来得及优化,占用了太多了逻辑门,可以进一步优化。
大致思路是:第一次按下KEY1 的时候,所有计时停止,再按KEY1,年就闪烁,按下KEY2和KEY3 进行加减。
再按KEY1,月就闪烁,按下KEY2和KEY3 进行加减........依次为调年-月-日-星期-时分秒,再次按一下KEY1,进入正常运行模式。
好了先上顶层模块module LCD(rst,clk,rw,rs,en,data,key1,key2,key3);input clk,rst;input key1,key2,key3;output rs,en,rw;output [7:0] data;reg key1_out,key2_out,key3_out;wire clk,rst;wire rs,en,rw;wire [7:0] data;disp U1(.clk(clk),.rst(rst),.rs(rs),.en(en),.rw(rw),.data(data),.key1(key1_out),.key2(key2_out),.key3(key3_out));//=============key1,key2,key3 按键防抖动================// reg key1_reg1,key1_reg2;reg key2_reg1,key2_reg2;reg key3_reg1,key3_reg2;reg [31:0] count;always @(posedge clk)begincount<=count+1;if(count==500000)begincount<=0;key1_reg1<=key1;key2_reg1<=key2;key3_reg1<=key3;endkey1_reg2<=key1_reg1;key2_reg2<=key2_reg1;key3_reg2<=key3_reg1;key1_out <= key1_reg2 & (!key1_reg1);key2_out <= key2_reg2 & (!key2_reg1);key3_out <= key3_reg2 & (!key3_reg1);endendmodule底层模块:module disp(rst,clk,rw,rs,en,data,key1,key2,key3);input clk,rst;input key1,key2,key3;output rs,en,rw;output [7:0] data;reg rs,en_sel;reg [7:0] data;reg [14:0] year;reg [7:0] shi,fen,miao,month,dat;reg [31:0]count,count1; //LCD CLK 分频计数器reg lcd_clk;//2行32个数据寄存器reg [7:0]one_1,one_2,one_3,one_4,one_5,one_6,one_7,one_8,one_9,one_10,one_11,one_12,on e_13,one_14,one_15,one_16;reg [7:0]two_1,two_2,two_3,two_4,two_5,two_6,two_7,two_8,two_9,two_10,two_11,two_12,two_ 13,two_14,two_15,two_16;reg [7:0] next;parameter state0 =8'h00, //设置8位格式,2行,5*7 8'h38;state1 =8'h01, //整体显示,关光标,不闪烁8'h0C 闪烁8'h0estate2 =8'h02, //设定输入方式,增量不移位8'h06state3 =8'h03, //清除显示8'h01state4 =8'h04, //显示第一行的指令80Hstate5 =8'h05, //显示第二行的指令80H+40Hscan =8'h06,nul =8'h07;parameter data0 =8'h10, //2行32个数据状态data1 =8'h11,data2 =8'h12,data3 =8'h13,data4 =8'h14,data5 =8'h15,data6 =8'h16,data7 =8'h17,data8 =8'h18,data9 =8'h19,data10 =8'h20,data11 =8'h21,data12 =8'h22,data13 =8'h23,data14 =8'h24,data15 =8'h25,data16 =8'h26,data17 =8'h27,data18 =8'h28,data19 =8'h29,data20 =8'h30,data21 =8'h31,data22 =8'h32,data23 =8'h33,data24 =8'h34,data25 =8'h35,data26 =8'h36,data27 =8'h37,data28 =8'h38,data29 =8'h39,data30 =8'h40,data31 =8'h41;initialbegin//第一行显示年-月-日星期//Mon Tue Wed Thur Fri Sat Sunone_1<=" "; one_2<=" "; one_3<=" "; one_4<=" "; one_5<="-"; one_6<=" "; one_7<=" "; one_8<="-";one_9<=" ";one_10<=" ";one_11<=" ";one_12<=" ";one_13<=" ";one_14<="";one_15<=" ";one_16<=" ";//第二行显示Clock:00-00-00two_1<="C"; two_2<="l"; two_3<="o"; two_4<="c"; two_5<="k"; two_6<=":"; two_7<=" "; two_8<=" ";two_9<="-";two_10<=" ";two_11<=" ";two_12<="-";two_13<=" ";two_14<="";two_15<=" ";two_16<=" ";shi<=8'd0;fen<=8'd0;miao<=8'd0;end//======================产生LCD 时序脉冲=========================== always @ (posedge clk ) //获得LCD时钟begincount<=count+1;if(count==32'd50000)begincount<=32'b0;lcd_clk<=~lcd_clk;endend//=====================产生闪烁扫描时钟===========================reg [31:0] count2;reg scan_flag;always @ (posedge clk or negedge rst) //获得校准时间选中闪烁状态beginif(!rst)beginscan_flag<=1'b0;endelsebegincount2<=count2+1;if(count2==32'd1*******)begincount2<=32'b0;scan_flag<=~scan_flag;endendend//====================产生按键标志位================================= reg [3:0] flag;always @ (posedge clk or negedge rst )beginif(!rst)beginflag<=4'b0;endelseif(key1)beginflag<=flag+1'b1;if(flag==4'b1000)flag<=4'b0000;endend//===================计时以及校准=======================================reg[3:0] week;reg[7:0] dat_flag;always @ (posedge clk or negedge rst ) //时钟计数器beginif(!rst)begin //初始化显示第一行2012-05-19 Sat 第二行:Clock:00-00-00 shi<=8'b0;fen<=8'b0;miao<=8'b0;month<=8'd5;dat<=8'd19;year<=16'd2012;week<=4'd5;count1<=1'b0;two_7<= (shi/8'd10)+8'b00110000;two_8<= (shi%8'd10)+8'b00110000;two_10<=(fen/8'd10)+8'b00110000;two_11<=(fen%8'd10)+8'b00110000;two_13<=(miao/8'd10)+8'b00110000;two_14<=(miao%8'd10)+8'b00110000;one_1<=(year/16'd1000)+8'b00110000;one_2<=((year%16'd1000)/16'd100)+8'b00110000;one_3<=((year%16'd100)/8'd10)+8'b00110000;one_4<=(year%8'd10)+8'b00110000;one_6<=(month/8'd10)+8'b00110000;one_7<=(month%8'd10)+8'b00110000;one_9<=(dat/8'd10)+8'b00110000;one_10<=(dat%8'd10)+8'b00110000;endelsebegintwo_7<= (shi/8'd10)+8'b00110000;two_8<= (shi%8'd10)+8'b00110000;two_10<=(fen/8'd10)+8'b00110000;two_11<=(fen%8'd10)+8'b00110000;two_13<=(miao/8'd10)+8'b00110000;two_14<=(miao%8'd10)+8'b00110000;one_1<=(year/16'd1000)+8'b00110000;one_2<=((year%16'd1000)/16'd100)+8'b00110000;one_3<=((year%16'd100)/8'd10)+8'b00110000;one_4<=(year%8'd10)+8'b00110000;one_6<=(month/8'd10)+8'b00110000;one_7<=(month%8'd10)+8'b00110000;one_9<=(dat/8'd10)+8'b00110000;one_10<=(dat%8'd10)+8'b00110000;// 判断是否为31天的月份if(month==8'd1||month==8'd3||month==8'd5||month==8'd7||month==8'd8||month==8'd10|| month==8'd12)dat_flag<=8'd31;// 判断是否为30天的月份else if(month==8'd4||month==8'd6||month==8'd9||month==8'd11)dat_flag<=8'd30;// 判断是否为闰年和平年else if(month==8'd2)beginif(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)dat_flag<=28;else dat_flag<=27;endcase (week)//星期//Mon Tue Wed Thu Fri Sat Sun4'b0000 : //1beginone_13<="M";one_14<="o";one_15<="n";end4'b0001 : //2beginone_13<="T";one_14<="u";one_15<="e";end4'b0010 : //3beginone_13<="W";one_14<="e";one_15<="d"; end4'b0011 : //4beginone_13<="T";one_14<="h";one_15<="u"; end4'b0100 : //5beginone_13<="F";one_14<="r";one_15<="i"; end4'b0101 : //6beginone_13<="S";one_14<="a";one_15<="t"; end4'b0110 : //7beginone_13<="S";one_14<="u";one_15<="n"; endendcasecase(flag)4'b0000 :beginen_sel<=1'b1;count1<=count1+1'b1;if(count1==32'd4*******)begincount1<=1'b0;miao<=miao+1'b1;if(miao==8'd59)beginmiao<=1'b0;fen<=fen+1'b1;if(fen==8'd59)beginfen<=1'b0;shi<=shi+1'b1;if(shi==8'd23)beginshi<=1'b0;dat<=dat+1'b1;week<=week+1'b1;if(week==4'b0110)week<=1'b1;if(dat==dat_flag)begindat<=8'd1;month<=month+1'b1;if(month==8'd12)beginmonth<=8'd1;year<=year+1'b1;if(year==16'd9999)year<=16'd0; //可以计1万年endendendendendendend4'b0001 :begincount1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;year<=year;month<=month;dat<=dat;week<=week;end4'b0010 : //调年begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_1<=8'd20;one_2<=8'd20;one_3<=8'd20;one_4<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginyear<=year+1'b1;if(year==16'd9999)year<=16'd0;endif(key3) //减数beginyear<=year-1'b1;if(year==16'd0)year<=16'd9999;endend4'b0011 : //调月begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_6<=8'd20;one_7<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endcaseif(key2) //加数beginmonth<=month+1'b1;if(month==8'd12)month<=8'd0;endif(key3) //减数beginmonth<=month-1'b1;if(month==8'd0)month<=8'd12;endend4'b0100 : //调日begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_9<=8'd20;one_10<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数begindat<=dat+1'b1;if(dat==dat_flag)dat<=8'd0;endif(key3) //减数dat<=dat-1'b1;if(dat==8'd0)dat<=dat_flag;endend4'b0101 : //调星期begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_13<=8'd20;one_14<=8'd20;one_15<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginweek<=week+1'b1;if(week==4'd6)week<=4'd0;endif(key3) //减数beginweek<=week-1'b1;if(week==4'd0)week<=4'd7;endend4'b0110 : //调时begincase(scan_flag)begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;two_7<= 8'd20;two_8<= 8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginshi<=shi+8'b00000001;if(shi==8'd23)shi<=8'b0;endif(key3) //减数beginshi<=shi-8'b00000001;if(shi==8'b0)shi<=23;endend4'b0111 : //调分begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;two_10<=8'd20;two_11<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginfen<=fen+8'b00000001;if(fen==8'd59)fen<=8'b0;endif(key3) //减数beginfen<=fen-8'b00000001;if(fen==8'b0)fen<=59;endend4'b1000 : //调秒begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;two_13<=8'd20;two_14<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginmiao<=miao+8'b00000001;if(miao==8'd59)miao<=8'b0;endif(key3) //减数beginmiao<=miao-8'b00000001;if(miao==8'b0)miao<=59;endendendcaseendendalways @(posedge lcd_clk )begincase(next)state0 :begin rs<=1'b0; data<=8'h38; next<=state1; endstate1 :begin rs<=1'b0; data<=8'h0e; next<=state2; endstate2 :begin rs<=1'b0; data<=8'h06; next<=state3; endstate3 :begin rs<=1'b0; data<=8'h01; next<=state4; endstate4 :begin rs<=1'b0; data<=8'h80; next<=data0; end //显示第一行data0 :begin rs<=1'b1; data<=one_1; next<=data1 ; enddata1 :begin rs<=1'b1; data<=one_2; next<=data2 ; enddata2 :begin rs<=1'b1; data<=one_3; next<=data3 ; enddata3 :begin rs<=1'b1; data<=one_4; next<=data4 ; enddata4 :data5 :begin rs<=1'b1; data<=one_6; next<=data6 ; enddata6 :begin rs<=1'b1; data<=one_7; next<=data7 ; enddata7 :begin rs<=1'b1; data<=one_8; next<=data8 ; enddata8 :begin rs<=1'b1; data<=one_9; next<=data9 ; enddata9 :begin rs<=1'b1; data<=one_10; next<=data10 ; enddata10 :begin rs<=1'b1; data<=one_11; next<=data11 ; enddata11 :begin rs<=1'b1; data<=one_12; next<=data12 ; enddata12 :begin rs<=1'b1; data<=one_13; next<=data13 ; enddata13 :begin rs<=1'b1; data<=one_14; next<=data14 ; enddata14 :begin rs<=1'b1; data<=one_15; next<=data15 ; enddata15 :begin rs<=1'b1; data<=one_16; next<=state5 ; endstate5:begin rs<=1'b0;data<=8'hC0; next<=data16; end //显示第二行data16 :begin rs<=1'b1; data<=two_1; next<=data17 ; enddata17 :begin rs<=1'b1; data<=two_2; next<=data18 ; enddata18 :begin rs<=1'b1; data<=two_3; next<=data19 ; enddata19 :begin rs<=1'b1; data<=two_4; next<=data20 ; enddata20 :data21 :begin rs<=1'b1; data<=two_6; next<=data22 ; enddata22 :begin rs<=1'b1; data<=two_7; next<=data23 ; enddata23 :begin rs<=1'b1; data<=two_8; next<=data24 ; enddata24 :begin rs<=1'b1; data<=two_9; next<=data25 ; enddata25 :begin rs<=1'b1; data<=two_10; next<=data26 ; end data26 :begin rs<=1'b1; data<=two_11; next<=data27 ; end data27 :begin rs<=1'b1; data<=two_12; next<=data28 ; end data28 :begin rs<=1'b1; data<=two_13; next<=data29 ; end data29 :begin rs<=1'b1; data<=two_14; next<=data30 ; end data30 :begin rs<=1'b1; data<=two_15; next<=data31 ; end data31 :begin rs<=1'b1; data<=two_16; next<=scan ; endscan : //交替更新第一行和第二行数据beginnext<=state4;enddefault: next<=state0;endcaseendassign en=lcd_clk && en_sel;assign rw=1'b0;endmodule。
基于FPGA的多功能电子万年历电子万年历可以显示日期、星期、时间以及其他的一些信息。
近几年,随着FPGA技术的发展,基于FPGA的电子万年历已经被广泛使用。
基于FPGA的电子万年历除了具备传统电子万年历的基本功能外,还具有诸多的优点。
采用FPGA做万年历,集成度高、抗电磁干扰性能好、可编程性强,且易于扩展。
本文将主要讲述基于FPGA的多功能电子万年历的设计原理、实现细节以及相关应用。
设计原理基于FPGA的多功能电子万年历主要由FPGA芯片、时钟模块、数码管显示模块以及按键扫描模块组成。
1.FPGA芯片:大体上分为输入、输出、内存和运算4个部分。
通过采用FPGA芯片可以实现逻辑门的优化布局和资源分配,从而实现万年历的多种功能。
2.时钟模块:利用时钟模块产生震荡脉冲,驱动万年历的各种操作。
时钟模块还可以产生各种频率的时钟信号,如秒钟、分频、时钟、日历等,从而实现多种功能。
3.显示模块:显示模块主要通过数码管来显示日期、星期、时间等信息。
具体实现方法是将数码管的数码码表和时序参数存储在内存中,通过编程控制数码管的显示方式,实现数据的输出。
4.按键扫描模块:按键扫描模块主要通过扫描键盘来接受用户的输入,并根据用户的操作控制万年历的功能。
实现细节基于FPGA的多功能电子万年历的实现细节主要包括万年历的功能实现、按键扫描和电路部署。
1.万年历的功能实现多功能电子万年历主要支持年、月、日的日期显示、星期显示、时间显示、时钟多种功能。
具体实现方法是每秒读取系统时间,并将时间转换成5V逻辑电平数据,然后通过编程控制数码管的显示方式,实现数据的输出。
2.按键扫描按键扫描模块主要通过接收按下按键后输出电平并进行数值编码,与计算机进行数值比对,然后根据用户的操作控制万年历的功能。
比如,按下设置键后,进入设置模式,按一次将秒数置零,按2次进行月日年设置,按3次进行时间设置,按4次重新返回当前时间界面。
3.电路部署电路部署主要包括FPGA芯片与其他模块、模块与模块之间的连接。
一、电子万年历简介 (1)二、电子万年历的工作原理 (1)三、多功能电子万年历各功能模块实现 (3)3.1时钟问题 (3)3.2电子万年历的控制系统 (5)3.3主控制模块maincontrol (6)3.4时间及其设置模块time_auto_and_set (7)3.3时间显示动态位选模块time_disp_select (12)3.4显示模块disp_data_mux (13)3.5秒表模块stopwatch (14)3.6日期显示与设置模块date_main (15)3.7闹钟模块alarmclock (17)3.8分频模块fdiv (18)四、附录 (20)附录一电子万年历系统的Verilog HDL语言程序 (20)一、电子万年历简介钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能,诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、定时启闭路灯等。
所有这些,都是以钟表数字化为基础的。
因此,研究电子万年历及扩大其应用,有非常现实的意义。
数字钟是一种用数字电路技术实现时、分、秒计时的装置,与机械式时钟相比具有更高的准确性和直观性,且无机械装置,具有更长的使用寿命,因此得到了广泛的使用。
电子万年历从原理上讲是一种典型的数字电路,其中包括了组合逻辑电路和时序电路。
本次所设计的电子万年历能显示日期、星期、时间,具有闹钟功能。
二、电子万年历的工作原理◆功能键用来选择不同的工作模式:时间正常显示功能、时间调整与显示、秒表功能、闹钟设置与查看、日期显示、日期调整与设置。
◆调整键1:主要用于闹钟设置、日期显示与调整、秒表、时间调整与设置中的位置选择按钮,与功能键配合使用。
●2号键功能模式,即时间调整与设置时,用作时、分、秒的移位,按一下,将会实现“时-分-秒”的依次移位,便于在特定位置进行调整;●4号键功能模式,即闹钟设置与查看时,同样用作时、分、秒的移位,按一下,将会实现“时-分-秒”的依次移位,便于在特定位置进行调整;●6号键功能模式,即日期调整与设置时,用作月、日的移位,按一下,将会实现“月-日”的依次移位,便于在特定位置进行调整。
◆调整键2:主要用于闹钟设置、日期显示与调整、秒表、时间调整与设置中的调整按钮,与功能键配合使用。
●2号键功能模式,即时间调整与设置时,用作时、分、秒的调整,按一下,将会使得当前调整键1选择的位置数字增加1;●4号键功能模式,即闹钟设置与查看时,同样用作时、分、秒的调整,按一下,将会使得当前调整键1选择的位置数字增加1;●6号键功能模式,即日期调整与设置时,用作月、日的移位,按一下,将会使得当前调整键1选择的位置数字增加1。
三、多功能电子万年历各功能模块实现3.1时钟问题无论是用离散逻辑、可编程逻辑,还是用全定制器件实现任何数字电路,设计不良的时钟在极限温度、电压或制造工艺存在偏差的情况下将导致系统错误的行为,所以可靠的时钟设计是非常关键的。
在FPGA设计时通常采用四种时钟:全局时钟、门控时钟、多级逻辑时钟和波动式时钟,多时钟系统是这四种时钟类型的任意组合。
3.1.1全局时钟对于一个设计项目来说,全局时钟(或同步时钟)是最简单和最可预测的时钟。
在FPGA设计中最好的时钟方案是:由专用的全局时钟输入引脚驱动单个主时钟去控制设计项目中的每一个触发器。
FPGA 一般都具有专门的全局时钟引脚,在设计项目时应尽量采用全局时钟,它能够提供器件中最短的时钟到输出的延时。
3.1.2门控时钟在许多应用中,整个设计项目都采用外部的全局时钟是不可能或不实际的,所以通常用阵列时钟构成门控时钟。
门控时钟常常同微处理器接口有关,例如用地址线去控制写脉冲。
每当用组合逻辑来控制触发器时,通常都存在着门控时钟。
在使用门控时钟时,应仔细分析时钟函数,以避免毛刺的影响。
如果设计满足下述两个条件,则可以保证时钟信号不出现危险的毛刺,门控时钟就可以像全局时钟一样可靠工作:◆驱动时钟的逻辑必须只包含一个“与门”或一个“或门”,如果采用任何附加逻辑,就会在某些工作状态下出现由于逻辑竞争而产生的毛刺。
◆逻辑门的一个输入作为实际的时钟,而该逻辑门的所有其他输入必须当成地址或控制线,它们遵守相对于时钟的建立和保持时间的约束。
3.1.3多级逻辑时钟当产生门控时钟的组合逻辑超过一级,即超过单个的“与门”或“或门”时,该设计项目的可靠性将变得很差。
在这种情况下,即使样机或仿真结果没有显示出静态险象,但实际上仍然可能存在危险,所以我们不应该用多级组合逻辑区作为触发器的时钟端。
不同的系统需要采用不同的方法消除多级时钟,并没有一个固定的模式。
3.1.4波动式时钟许多系统要求在同一设计内采用多时钟,最常见的例子是两个异步微处理器之间的接口,或微处理器和异步通信通道的接口。
由于两个时钟信号之间要求一定的建立和保持时间,所以上述应用引进了附加的定时约束条件,它们会要求将某些异步信号同步化。
而在许多应用中只将异步信号同步化还是不够的,当系统中有两个或两个以上非同源时钟时,数据的建立和保持时间很难得到保证,设计人员将面临复杂的时间分析问题。
最好的方法是将所有非同源时钟同步化。
使用FPGA内部的锁相环(PLL)是一个效果很好的方法,但并不是所有FPGA都带有PLL,而且带有PLL功能的芯片大多价格昂贵。
这时就需要使用带使能端的D触发器,并引入一个高频时钟来实现信号的同步化。
稳定可靠的时钟是保证系统可靠工作的重要条件,设计中不能够将任何可能含有毛刺的输出作为时钟信号,并且尽可能只使用一个全局时钟,对多时钟系统要特别注意异步信号和非同源时钟的同步问题。
为了获得高驱动能、低抖动时延、稳定的占空比的时钟信号,一般使用FPGA内部的专用时钟资源产生同步时序电路的主工作时钟。
专用时钟资源主要指两部分,一部分是布线资源,包括全局时钟布线资源和长线资源等,另一部分则是FPGA内部的PLL。
3.2电子万年历的控制系统此电子万年历系统主要有8个模块分别设计仿真,分别是以下8个模块:1.主控制模块 maincontrol2.时间及其设置模块 timepiece_main3.时间显示动态位选模块 time_disp_select4.显示模块 disp_data_mux5.秒表模块 stopwatch6.日期显示与设置模块 date_main7.闹钟模块 alarmclock8.分频模块 fdiv3.3主控制模块maincontrol该模块实现对各个功能模块的整体控制,包括对时间显示与调整、日期显示与调整、闹钟显示与调整、秒表操作等的控制,结构功能图如3-1所示,波形仿真图如3-2所示。
图3-1主控制模块的结构功能图图3-2 主控制模块的波形仿真图SW3是功能键,从波形图中可知,SW3每出现一次上升沿,输出都会发生相应的变化,即按照Timepiece_EN(时钟自动显示使能),TimeSet_EN(时钟设置与调整使能),Stopwatch_EN(秒表功能使能),Alarmclock_EN(闹钟时间设置使能),Date_EN(日期显示使能),DateSet_EN(日期显示与设置使能)的顺序依次输出有效波形“1”,对相应的模块输入有效使能,从而实现相应的功能。
3.4时间及其设置模块time_auto_and_set时间及其设置模块主要完成时间的自动正常运行与显示,以及在相应的功能号下,实现时间的调整与设置。
3.2.1时间模块timepiece_main该模块主要完成时间的自动增加与显示功能,即为正常的自动模式运行,其结构功能图如3-3所示,波形仿真图如3-4所示。
图3-3时间及其设置模块的结构功能图图3-4 时间模块的结构功能图◆秒自动计时子模块 second_counter,结构功能图如3-5所示,图3-5 秒自动计时子模块的结构功能图◆分自动计时子模块 minute_counter,结构功能图如3-6示。
图3-6分自动计时子模块的结构功能图◆小时自动计时子模块 hour_counter,结构功能图如3-7所示。
图3-7小时自动计时子模块的结构功能图图3-8 时间模块的波形仿真图当Timepiece_EN为1时,即处于时间自动工作状态,即每出现一次时钟信号clk,计数一次,先计数second0,当计数到1001(即十进制的9)时,向second1发出一个计数信号,此时second1进行一次计数,类推,second1计数到0101(即十进制的5),且second0计数到1001(即十进制的9)时,minute0则进行一次计数,按照此规律进行时间的计数。
当计满24小时,向day_EN发出一个计数信号,即此使能端输出有效信号1,进行日期的计数。
3.2.2 时间设置模块timeset该模块主要完成对时间的设置相关的闪烁显示控制以及时间中的小时、分钟、秒等数据的改变,流程图如3-9所示,结构功能图如3-10所示,波形仿真图如3-11所示。
图3-9 时间设置模块的流程图图3-10 时间设置模块的结构功能图图3-11 时间设置模块的波形仿真图表3-12 时间设置模块的端口说明输入端口功能TimeSet_EN 时间设置使能,当其电平为高时,时间设置有效SW1,SW2 调整键1与调整键2输入信号hour1,hour0 当前时间的小时数输入minute1,minute0 当前时间的分钟数输入second0,second1 当前时间的秒数输入输出端口功能hour_set1,hour_set0 设置时间后的小时数minute_set1,minute_set0 设置时间后的分钟数second_set1,second_set0 设置时间后的秒数disp_drive 设置中的闪烁显示设置当Timeset_EN为1时,即实现时间设置功能。
SW1实现时间格式中小时高、低位,分钟高、低位,秒钟高、低位的位选,即每出现一个SW1上升沿,disp_drive的相应数值加1(选择具体的需要调整的位置)。
SW2实现相应得位的数值得调整,即每出现一个SW2上升沿,相应位的数值增加1。
3.2.3时间数据与时间设置数据多路选择模块 time_mux该模块用来分时向显示单元传输显示数据,流程图如3-13所示,结构功能图如3-14所示,波形仿真图如3-15所示。
图3-13 多路选择模块的结构功能图图 3 -14 多路选择模块的流程图开 始依输入条件,判断是自动显示时间,或显示调整后的时间Timeset_EN=1?显示设置后的时间显示自动模式时的时间结 束图3-15 多路选择模块的波形仿真图输入端口功能TimeSet_EN 时间设置使能信号hour1,hour0 自动模式中当前时间的小时数输入minute1,minute0 自动模式中当前时间的分钟数输入second0,second1 自动模式中当前时间的秒数输入hour_set1,hour_set0 时间设置后的小时数输入minute_set1,minute_set0时间设置后的分钟数输入second_set1,second_set0 时间设置后的秒数输入输入端口功能hour_1,hour_0 当前需要显示的小时输出minute_1,minute_0 当前需要显示的分钟输出second_0,second_1当前需要显示的秒输出表3-16 多路选择模块的端口说明3.3时间显示动态位选模块time_disp_select该模块用来分时显示时间数据,但是在选择合适的时间间隔下,人眼并不能分辨出是分时显示的,这样显示的方式可以降低功耗,结构功能图如3-17所示,波形仿真图如3-18所示。