基于fpga的LCD显示万年历.docx
- 文档编号:8240587
- 上传时间:2023-01-30
- 格式:DOCX
- 页数:13
- 大小:18.21KB
基于fpga的LCD显示万年历.docx
《基于fpga的LCD显示万年历.docx》由会员分享,可在线阅读,更多相关《基于fpga的LCD显示万年历.docx(13页珍藏版)》请在冰豆网上搜索。
基于fpga的LCD显示万年历
接着我的上一篇博文,终于完善好了,前几天太忙了,没有及时上传,呵呵,今天晚上刚比较早刚好凌晨,及时上传一下,实现了从0000---9999年的时钟,其实万年历和十万年历,都是差不多,等到地球能转到9999年再改代码也不迟,哈哈!
!
我这里有顶层和底层文件,顶层主要是调用模块和做按键处理,具体按键防抖动原理,参见偶的以前的博文,我写完这个万年历的代码,还没来得及优化,占用了太多了逻辑门,可以进一步优化。
大致思路是:
第一次按下KEY1的时候,所有计时停止,再按KEY1,年就闪烁,按下KEY2和KEY3进行加减。
再按KEY1,月就闪烁,按下KEY2和KEY3进行加减........依次为调年-月-日-星期-时分秒,再次按一下KEY1,进入正常运行模式。
好了先上顶层模块
moduleLCD
(
rst,
clk,
rw,
rs,
en,
data,
key1,key2,key3
);
inputclk,rst;
inputkey1,key2,key3;
outputrs,en,rw;
output[7:
0]data;
regkey1_out,key2_out,key3_out;
wireclk,rst;
wirers,en,rw;
wire[7:
0]data;
dispU1
(
.clk(clk),
.rst(rst),
.rs(rs),
.en(en),
.rw(rw),
.data(data),
.key1(key1_out),
.key2(key2_out),
.key3(key3_out)
);
//=============key1,key2,key3按键防抖动================//
regkey1_reg1,key1_reg2;
regkey2_reg1,key2_reg2;
regkey3_reg1,key3_reg2;
reg[31:
0]count;
always@(posedgeclk)
begin
count<=count+1;
if(count==500000)
begin
count<=0;
key1_reg1<=key1;
key2_reg1<=key2;
key3_reg1<=key3;
end
key1_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);
end
endmodule
底层模块:
moduledisp
(
rst,
clk,
rw,
rs,
en,
data,
key1,key2,key3
);
inputclk,rst;
inputkey1,key2,key3;
outputrs,en,rw;
output[7:
0]data;
regrs,en_sel;
reg[7:
0]data;
reg[14:
0]year;
reg[7:
0]shi,fen,miao,month,dat;
reg[31:
0]count,count1;//LCDCLK分频计数器
reglcd_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,one_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;
parameterstate0=8'h00,//设置8位格式,2行,5*78'h38;
state1=8'h01,//整体显示,关光标,不闪烁8'h0C闪烁8'h0e
state2=8'h02,//设定输入方式,增量不移位8'h06
state3=8'h03,//清除显示8'h01
state4=8'h04,//显示第一行的指令80H
state5=8'h05,//显示第二行的指令80H+40H
scan=8'h06,
nul=8'h07;
parameterdata0=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;
initial
begin
//第一行显示年-月-日星期//MonTueWedThurFriSatSun
one_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-00
two_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@(posedgeclk)//获得LCD时钟
begin
count<=count+1;
if(count==32'd50000)
begin
count<=32'b0;
lcd_clk<=~lcd_clk;
end
end
//=====================产生闪烁扫描时钟===========================
reg[31:
0]count2;
regscan_flag;
always@(posedgeclkornegedgerst)//获得校准时间选中闪烁状态
begin
if(!
rst)
begin
scan_flag<=1'b0;
end
else
begin
count2<=count2+1;
if(count2==32'd10000000)
begin
count2<=32'b0;
scan_flag<=~scan_flag;
end
end
end
//====================产生按键标志位=================================
reg[3:
0]flag;
always@(posedgeclkornegedgerst)
begin
if(!
rst)
begin
flag<=4'b0;
end
else
if(key1)
begin
flag<=flag+1'b1;
if(flag==4'b1000)
flag<=4'b0000;
end
end
//===================计时以及校准=======================================
reg[3:
0]week;
reg[7:
0]dat_flag;
always@(posedgeclkornegedgerst)//时钟计数器
begin
if(!
rst)
begin//初始化显示第一行2012-05-19Sat第二行:
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;
end
else
begin
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;
//判断是否为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天的月份
elseif(month==8'd4||month==8'd6||month==8'd9||month==8'd11)
dat_flag<=8'd30;
//判断是否为闰年和平年
elseif(month==8'd2)
begin
if(year%4==0&&year%100!
=0||year%400==0)
dat_flag<=28;
elsedat_flag<=27;
end
case(week)
//星期//MonTueWedThuFriSatSun
4'b0000:
//1
begin
one_13<="M";one_14<="o";one_15<="n";
end
4'b0001:
//2
begin
one_13<="T";one_14<="u";one_15<="e";
end
4'b0010:
//3
begin
one_13<="W";one_14<="e";one_15<="d";
end
4'b0011:
//4
begin
one_13<="T";one_14<="h";one_15<="u";
end
4'b0100:
//5
begin
one_13<="F";one_14<="r";one_15<="i";
end
4'b0101:
//6
begin
one_13<="S";one_14<="a";one_15<="t";
end
4'b0110:
//7
begin
one_13<="S";one_14<="u";one_15<="n";
end
endcase
case(flag)
4'b0000:
begin
en_sel<=1'b1;
count1<=count1+1'b1;
if(count1==32'd49999999)
begin
count1<=1'b0;
miao<=miao+1'b1;
if(miao==8'd59)
begin
miao<=1'b0;
fen<=fen+1'b1;
if(fen==8'd59)
begin
fen<=1'b0;
shi<=shi+1'b1;
if(shi==8'd23)
begin
shi<=1'b0;
dat<=dat+1'b1;
week<=week+1'b1;
if(week==4'b0110)
week<=1'b1;
if(dat==dat_flag)
begin
dat<=8'd1;
month<=month+1'b1;
if(month==8'd12)
begin
month<=8'd1;
year<=year+1'b1;
if(year==16'd9999)
year<=16'd0;//可以计1万年
end
end
end
end
end
end
end
4'b0001:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;year<=year;month<=month;dat<=dat;week<=week;
end
4'b0010:
//调年
begin
case(scan_flag)
1'b0:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
one_1<=8'd20;one_2<=8'd20;one_3<=8'd20;one_4<=8'd20;
end
1'b1:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
end
endcase
if(key2)//加数
begin
year<=year+1'b1;
if(year==16'd9999)
year<=16'd0;
end
if(key3)//减数
begin
year<=year-1'b1;
if(year==16'd0)
year<=16'd9999;
end
end
4'b0011:
//调月
begin
case(scan_flag)
1'b0:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
one_6<=8'd20;one_7<=8'd20;
end
1'b1:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
end
endcase
if(key2)//加数
begin
month<=month+1'b1;
if(month==8'd12)
month<=8'd0;
end
if(key3)//减数
begin
month<=month-1'b1;
if(month==8'd0)
month<=8'd12;
end
end
4'b0100:
//调日
begin
case(scan_flag)
1'b0:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
one_9<=8'd20;one_10<=8'd20;
end
1'b1:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
end
endcase
if(key2)//加数
begin
dat<=dat+1'b1;
if(dat==dat_flag)
dat<=8'd0;
end
if(key3)//减数
begin
dat<=dat-1'b1;
if(dat==8'd0)
dat<=dat_flag;
end
end
4'b0101:
//调星期
begin
case(scan_flag)
1'b0:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
one_13<=8'd20;one_14<=8'd20;one_15<=8'd20;
end
1'b1:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
end
endcase
if(key2)//加数
begin
week<=week+1'b1;
if(week==4'd6)
week<=4'd0;
end
if(key3)//减数
begin
week<=week-1'b1;
if(week==4'd0)
week<=4'd7;
end
end
4'b0110:
//调时
begin
case(scan_flag)
1'b0:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
two_7<=8'd20;
two_8<=8'd20;
end
1'b1:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
end
endcase
if(key2)//加数
begin
shi<=shi+8'b00000001;
if(shi==8'd23)
shi<=8'b0;
end
if(key3)//减数
begin
shi<=shi-8'b00000001;
if(shi==8'b0)
shi<=23;
end
end
4'b0111:
//调分
begin
case(scan_flag)
1'b0:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
two_10<=8'd20;
two_11<=8'd20;
end
1'b1:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
end
endcase
if(key2)//加数
begin
fen<=fen+8'b00000001;
if(fen==8'd59)
fen<=8'b0;
end
if(key3)//减数
begin
fen<=fen-8'b00000001;
if(fen==8'b0)
fen<=59;
end
end
4'b1000:
//调秒
begin
case(scan_flag)
1'b0:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
two_13<=8'd20;
two_14<=8'd20;
end
1'b1:
begin
count1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;
end
endcase
if(key2)//加数
begin
miao<=miao+8'b00000001;
if(miao==8'd59)
miao<=8'b0;
end
if(key3)//减数
begin
miao<=miao-8'b00000001;
if(miao==8'b0)
miao<=59;
end
end
endcase
end
end
always@(posedgelcd_clk)
begin
case(next)
state0:
be
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 fpga LCD 显示 万年历