学习笔记fpga设计电子时钟12864显示.docx
《学习笔记fpga设计电子时钟12864显示.docx》由会员分享,可在线阅读,更多相关《学习笔记fpga设计电子时钟12864显示.docx(22页珍藏版)》请在冰豆网上搜索。
学习笔记fpga设计电子时钟12864显示
fpga设计电子时钟(12864显示)
设计心得:
1,进行分块设计,类似调用函数,脉冲使能
2,充分了解fpga的并行特性(c程序的串行特性,不能并行处理,线性:
只有完成了当前任务,才能进行下一个任务)
设计问题:
1,似乎读有问题,在char_LR=1时,写的数据为汉字
(程序中时间没有更改,主要为了调试看波形)
实际板子验证时,将LCD_clk模块中的分频调为50到100kHz左右
整体架构
功能模块
液晶初始化时序
parameterIdle=8'b0000_0001,
Basic_com=8'b0000_0010,//basicinstruction:
0x30
Disp_set=8'b0000_0100,//setshowcursebling
DDRAM_clear=8'b0000_1000,//colunmaddressX
Wait_clear=8'b0001_0000,
Point_set=8'b0010_0000,
Show_on=8'b0100_0000,
Stop=8'b1000_0000;
写字符的时序
由于字符属于半宽字形,且DDRAM形式下,每行只有8个地址,而字符可以写16个,因此用下面三个来表示写的地址:
input[1:
0]Y,//row0-3
input[2:
0]X,//clunm0-7
inputLR,//0/1
因此当LR=0时,直接写地址,然后写一个字符编码即可
LR=1时,先写地址,读出高位数据,然后写入两个字节(读出的数据,要写的数据)
parameterIdle=8'b0000_0001,
DDRAM=8'b0000_0010,//drawingmode
W_addr=8'b0000_0100,//rowaddressY
Dummy=8'b0000_1000,//notreallyreading
R_data=8'b0001_0000,//readinghighbytedata
W0_data=8'b0010_0000,
W1_data=8'b0100_0000,
Stop=8'b1000_0000;
#t1:
0t2:
2305,T:
10,n_init:
38
#t1:
2305t2:
2665,T:
10,n_char:
6
#t1:
2665t2:
3265,T:
10,n_char:
10
完成了上述工作,就可以设计一个简单的电子时钟,其要求如下:
在屏幕上显示时间00:
00:
00
要动态走
(主要就是控制脉冲信号的产生)
设计思路:
1,按下复位键,系统复位,时间变为00:
00:
00
2,每一秒中时分秒数据更改
3,一秒钟时间到,产生8个字符写的脉冲,LCD更新数据显示
00:
00:
01
00:
01:
59
1代码
/*
sign.v
//creatthecontrolsign
clockh:
m:
s
*/
modulesign(
//moduleLED(
inputlcd_clk,//100kHz
inputsys_rst,
outputreglcd_char_en,
outputreglcd_init_en,
outputreg[7:
0]char_data,
outputreg[2:
0]char_X,
outputreg[1:
0]char_Y,
outputregchar_LR
);
parameterT_w_char=5,
T_lcd_init=40;
reg[47:
0]time_out;
/*1s*/
reg[16:
0]cnt_s;
reg[5:
0]cnt0_clk;
reg[3:
0]cnt1_clk;
reg[2:
0]cnt_char;
reg[5:
0]sec,min;
reg[4:
0]hour;
regflag_s,flag_init;
always@(posedgelcd_clkornegedgesys_rst)begin//100kHz
if(!
sys_rst)
begin
cnt_s<=0;
cnt0_clk<=0;
cnt1_clk<=0;
cnt_char<=0;
sec<=0;
min<=0;
hour<=0;
flag_s<=0;
flag_init<=1'b1;
char_Y<=2'b10;
end
else
begin
if(cnt_s==(40-1))
begin
cnt_s<=0;
flag_s<=1'b1;
data_deal;//task
end
else
cnt_s<=cnt_s+1'b1;
if(flag_init)
begin
cnt0_clk<=cnt0_clk+1'b1;
case(cnt0_clk)
1:
beginlcd_init_en<=1'b0;end
2:
beginlcd_init_en<=1'b1;end
3:
beginlcd_init_en<=1'b1;end
4:
beginlcd_init_en<=1'b0;end
T_lcd_init:
begin
flag_init<=0;
cnt0_clk<=0;
end
default:
lcd_init_en<=0;
endcase
end
else
if(flag_s)
begin
cnt1_clk<=cnt1_clk+1'b1;
case(cnt1_clk)
1:
beginlcd_char_en<=1'b0;end
2:
beginlcd_char_en<=1'b1;end
3:
beginlcd_char_en<=1'b1;end
4:
beginlcd_char_en<=1'b0;end
T_w_char:
begin
if(cnt_char==3'b111)
begincnt_char<=0;flag_s<=0;end
else
cnt_char<=cnt_char+1'b1;
cnt1_clk<=0;
end
default:
lcd_char_en<=0;
endcase
case(cnt_char)//2345
0:
beginchar_X<=3'b000;char_LR<=0;char_data<=time_out[47:
40];end//x0:
00:
00
1:
beginchar_X<=3'b001;char_LR<=0;char_data<=time_out[39:
32];end//0x:
00:
00
2:
beginchar_X<=3'b010;char_LR<=0;char_data<=8'h3a;end//:
ascii058
3:
beginchar_X<=3'b011;char_LR<=0;char_data<=time_out[31:
24];end//00:
x0:
00
4:
beginchar_X<=3'b100;char_LR<=0;char_data<=time_out[23:
16];end//00:
0x:
00
5:
beginchar_X<=3'b101;char_LR<=0;char_data<=8'h3a;end//:
ascii058
6:
beginchar_X<=3'b110;char_LR<=0;char_data<=time_out[15:
8];end//00:
00:
x0
7:
beginchar_X<=3'b111;char_LR<=0;char_data<=time_out[7:
0];end
endcase
end
end
end
taskdata_deal;
begin
if(sec==59)
if(min==59)
if(hour==23)
beginhour<=0;min<=0;sec<=0;end
else
beginhour<=hour+1'b1;min<=0;sec<=0;end
else
beginmin<=min+1'b1;sec<=0;end
else
sec<=sec+1'b1;
time_out[47:
40]<=8'h30+(hour/10);
time_out[39:
32]<=8'h30+(hour%10);
time_out[31:
24]<=8'h30+(min/10);
time_out[23:
16]<=8'h30+(min%10);
time_out[15:
8]<=8'h30+(sec/10);
time_out[7:
0]<=8'h30+(sec%10);
end
endtask
endmodule
2代码
moduleLCD_init(
//moduleLED(
inputlcd_clk,
inputsys_clk,
inputlcd_en,//1isactived
outputregLCD_RS,
outputregLCD_RW,
outputregLCD_EN,
inout[7:
0]LCD_DATA,
outputregACK
);
regflag;
reg[7:
0]lcd_data;
reg[7:
0]State;
reglink_rs;
reglink_data;
parameterIdle=8'b0000_0001,
Basic_com=8'b0000_0010,//basicinstruction:
0x30
Disp_set=8'b0000_0100,//setshowcursebling
DDRAM_clear=8'b0000_1000,//colunmaddressX
Wait_clear=8'b0001_0000,
Point_set=8'b0010_0000,
Show_on=8'b0100_0000,
Stop=8'b1000_0000;
reg[9:
0]cnt;//16*2*32=2^10byte(8bits)
/*LCD_RWLCD_DATA*/
assignLCD_DATA=link_data?
lcd_data:
8'hzz;
/*LCD_RWLCD_EN*/
always@(posedgesys_clk)begin
if(flag)
begin
LCD_RW=0;
LCD_EN=lcd_clk;
end
else
begin
LCD_RW=1'bz;
LCD_EN=1'bz;
end
end
/*LCD_RS*/
always@(posedgelcd_clk)begin
if(link_rs)
LCD_RS<=1'b0;
else
LCD_RS<=1'bz;
end
/*-Mainstatetranster-*/
always@(posedgelcd_clk)begin
case(State)
Idle:
begin
if(lcd_en)
beginlink_rs=1;State<=Basic_com;end
else
State<=Idle;
ACK=0;
flag<=1'b0;
lcd_data<=8'hzz;
cnt<=0;
end
Basic_com:
begin
flag<=1'b1;
link_data=1'b1;
cnt<=cnt+1'b1;
if(cnt==1)
State<=Disp_set;
else
State<=Basic_com;
lcd_data<=8'h30;
end
Disp_set:
begin
State<=DDRAM_clear;
lcd_data<=8'h0c;//showcurseblinkisoff
end
DDRAM_clear:
begin
State<=Wait_clear;
lcd_data<=8'h01;
end
Wait_clear:
begin
cnt<=cnt+1'b1;
link_data=1'b0;
flag<=0;
lcd_data<=8'hzz;
if(cnt==30)
State<=Point_set;
else
State<=Wait_clear;
end
Point_set:
begin
flag<=1'b1;
link_data=1'b1;
State<=Show_on;
lcd_data<=8'h06;//point+1automatically,screenmoveoff
end
Show_on:
begin
State<=Stop;
lcd_data<=8'h0c;
end
Stop:
begin
State<=Idle;
flag<=1'b0;
link_data=1'b0;
ACK<=1'b1;
lcd_data<=8'hzz;
cnt<=0;
link_rs=0;
end
default:
beginACK=0;State<=Idle;end
endcase
end
endmodule
3代码
//moduleLCD_top(
moduleLED(
inputsys_clk,
inputsys_rst,
outputLCD_RS,
outputLCD_RW,
outputLCD_EN,
inout[7:
0]LCD_DATA,
outputBUSY
);
wire[7:
0]char_data;
wire[2:
0]char_X;
wire[1:
0]char_Y;
signsingb(
.lcd_clk(lcd_clk),//100kHz
.sys_rst(sys_rst),
.lcd_char_en(lcd_char_en),
.lcd_init_en(lcd_init_en),
.char_data(char_data),
.char_X(char_X),
.char_Y(char_Y),
.char_LR(char_LR)
);
LCD_initlcd_init(
.lcd_clk(lcd_clk),
.sys_clk(sys_clk),
.lcd_en(lcd_init_en),//1isactived
.LCD_RS(LCD_RS),
.LCD_RW(LCD_RW),
.LCD_EN(LCD_EN),
.LCD_DATA(LCD_DATA),
.ACK(init_ack)
);
LCD_characa(
.lcd_clk(lcd_clk),
.sys_clk(sys_clk),
.lcd_en(lcd_char_en),//1isactived
.Y(char_Y),//row0-3
.X(char_X),//clunm0-7
.LR(char_LR),//0/1
.data_disp(char_data),
.LCD_RS(LCD_RS),
.LCD_RW(LCD_RW),
.LCD_EN(LCD_EN),
.LCD_DATA(LCD_DATA),
.ACK(init_ack)
);
LCD_clkclk1(
.sys_clk(sys_clk),
.lcd_clk(lcd_clk)
);
endmodule
4代码
moduleLCD_clk(
//moduleLED(
inputsys_clk,
outputreglcd_clk
);
/*-creatthe25kHzclock-*/
reg[11:
0]lcd_cnt;
always@(posedgesys_clk)begin
if(lcd_cnt==2)//100kHz
begin
lcd_cnt=0;
lcd_clk<=~lcd_clk;
end
else
lcd_cnt=lcd_cnt+1'b1;
end
initialbeginlcd_clk=0;lcd_cnt=0;end
endmodule
5代码
/*todisplaycharacter*/
moduleLCD_charac(
//moduleLED(
inputlcd_clk,
inputsys_clk,
inputlcd_en,//1isactived
input[1:
0]Y,//row0-3
input[2:
0]X,//clunm0-7
inputLR,//0/1
input[7:
0]data_disp,
outputregLCD_RS,
outputregLCD_RW,
outputregLCD_EN,
inout[7:
0]LCD_DATA,
outputregACK
);
reg[7:
0]lcd_data;
reg[7:
0]R_buff;
reg[7:
0]State;
parameterIdle=8'b0000_0001,
DDRAM=8'b0000_0010,//drawingmode
W_addr=8'b0000_0100,//rowaddressY
Dummy=8'b0000_1000,//notreallyreading
R_data=8'b0001_0000,//readinghighbytedata
W0_data=8'b0010_0000,
W1_data=8'b0100_0000,
Stop=8'b1000_0000;
regflag,cnt;
reglink_data;
regflag0;
/*LCD_DATA*/
assignLCD_DATA=link_data?
lcd_data:
8'hzz;
/*LCD_EN*/
always@(posedgesys_clk)begin
if(flag==1'b1)
LCD_EN<=lcd_clk;
else
LCD_EN<=1'bz;
end
/*LCD_RW*/
always@(posedgelcd_clk)begin
if(flag0)
if(State==Dummy||State==R_data)
LCD_RW<=1'b1;
else
LCD_RW<=1'b0;
else
LCD_RW<=1'bz;
end
/*LCD_RS*/
always@(posedgelcd_clk)begin
if(flag0)
if(State==W0_data||State==W1_data||State==Dummy||State==R_data)
LCD_RS<=1'b1;
else
LCD_RS<=1'b0;
else
LCD_RS<=1'bz;
end
/*-Mainstatetranster-*/
always@(posedgelcd_clk)begin
case(State)
Idle:
begin
if(lcd_en)
beginState<=DDRAM;link_data=1;flag0=1'b1;end
else
beginState<=Idle;flag0=1'b0;end
flag<=1'b0;
lcd_data<=8'hzz;
ACK<=0;
end
DDRAM:
begin//hereflagischanged,notIdle,causesys_clk
flag<=1'b1;
State<=W_addr;
link_data=1;
lcd_data<=8'h30;
end
W_addr:
begin
if(!
cnt)
begin
if(LR)
State<=Dummy;
else
State<=W0_data;
cnt=1'b1;
end
else
State<=W0_data;
case(Y)
2'b00:
lcd_data<=8'h80+X;
2'b01:
lcd_data<=8'h90+X;
2'b10:
lcd_data<=8'h88+X;
2'b11:
lcd_