fpga5110.docx
《fpga5110.docx》由会员分享,可在线阅读,更多相关《fpga5110.docx(18页珍藏版)》请在冰点文库上搜索。
fpga5110
//Description:
诺基亚5110液晶中文显示,每行显示5个字,显3行。
//clk——时钟输入(1位)
//sel——数码管位选信号输出,不同的数位(8位)
//data——数码管某一位上的数字输出(8位)
//**************************************************/
modulenokia5110(sys_clk,reset,lcd_rst,lcd_sce,lcd_dc,lcd_sdin,lcd_sclk);
inputsys_clk;//系统时钟
inputreset;//时钟复位,为0进行复位,为1正常运行
outputlcd_rst;//输出信号到51i10的复位引脚,低电平进行复位
outputlcd_sclk;//输出信号到5110的时钟信号引脚
outputlcd_sce;//输出信号到5110的片选信号引脚,低电平芯片选通
outputlcd_sdin;
outputlcd_dc;
//-----内部寄存器-----
reg[7:
0]cnt;//分频计数器reg[6:
0]cnt;
regclk;//分频时钟
reglcd_sce;//5110片选信号,低电平选通芯片
reglcd_dc;//数据命令切换脚,1为数据,0为命令
reglcd_sdin;//串行数据输入
reg[1:
0]state1;//状态机1
reg[3:
0]state2;//状态机2
reg[3:
0]state_back;//状态返回
parameterclk_l=2'd0;
parameterclk_h=2'd1;
parameterclk_rising_edge=2'd2;
parameterclk_falling_edge=2'd3;
parameteridle=4'd0;//状态机2的初始状态
parametershift_data=4'd1;
parametershift_data1=4'd2;
parameterclear_screen=43'd3;
parameterset_xy=4'd4;
parameterdisp_char=4'd5;
parameterset_xy2=4'd6;
parameterdisp_char2=4'd7;
parameterset_xy3=4'd8;
reg[7:
0]data_reg;//数据寄存器
reg[3:
0]cnt2;//串行传输data_reg时的移位计数器
reg[15:
0]cnt3;//状态机2的运行步骤计数器,25步reg[4:
0]cnt3;
reg[8:
0]cnt4;//显示位置计数器
reg[6:
0]char_reg;//字符寄存器
reg[2:
0]y_reg;//y坐标寄存器,Y:
0~5(3’b101)
reg[6:
0]x_reg;//x坐标寄存器,X:
0~83(7'b1010011)
reg[0:
255]men[5:
0];//字符库,为menory变量,第一个[每个存储单元深度],第二个[存储器的深度]
reg[0:
255]temp;//字符暂存寄存器
parameterONN=1'b0;
parameterOFF=1'b1;
parameterCMD=1'b0;
parameterDATA=1'b1;
//-----字符库,每个字符占8行6列-----
initial
begin
//空白
men[0]={8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,
8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00,8'h00};
/*--文字:
力反宋体12--现调整为:
宽度x高度=16x16*/
men[1]={8'hFF,8'hEF,8'hEF,8'hEF,8'hEF,8'hEF,8'h00,8'hEF,
8'hEF,8'hEF,8'hEF,8'hEF,8'h0F,8'hFF,8'hFF,8'hFF,
8'hFF,8'h7F,8'hBF,8'hDF,8'hE7,8'hF9,8'hFE,8'hFF,
8'hDF,8'hBF,8'h7F,8'hBF,8'hC0,8'hFF,8'hFF,8'hFF};
/*--文字:
虎宋体12--现调整为:
宽度x高度=16x16*/
men[2]={8'h00,8'h00,8'hF8,8'h08,8'h48,8'h48,8'h48,8'hFF,
8'h4A,8'h2A,8'h2A,8'h0A,8'hCA,8'h18,8'h00,8'h00,
8'h80,8'h60,8'h1F,8'h80,8'h40,8'h20,8'h1C,8'h04,
8'h05,8'h05,8'h7D,8'h81,8'h81,8'hE0,8'h00,8'h00};
men[3]={8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,
8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,
8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,
8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF,8'hFF};
/*--文字:
雄楷体12--现调整为:
宽度x高度=16x16-*/
men[4]={8'h00,8'h40,8'h60,8'hE0,8'hFC,8'hBC,8'hA0,8'hE0,
8'hF8,8'hFC,8'h4C,8'hFC,8'hF8,8'hA0,8'h20,8'h00,
8'h10,8'h1C,8'h0F,8'h0F,8'h0F,8'h0F,8'h0F,8'h2C,
8'h7F,8'h7F,8'h15,8'h1F,8'h1F,8'h1A,8'h1A,8'h00};
/*--文字:
起楷体12--现调整为:
宽度x高度=16x16-*/
men[5]={8'h00,8'h00,8'h00,8'h40,8'hFC,8'hFC,8'hFC,8'hA0,
8'hA0,8'hB0,8'hF0,8'hF0,8'hF0,8'h10,8'h00,8'h00,
8'h21,8'h31,8'h3F,8'h0F,8'h0F,8'h1F,8'h1F,8'h34,
8'h37,8'h2F,8'h6C,8'h6C,8'h66,8'h66,8'h24,8'h20};
//men[0]={8'h00,8'h42,8'h42,8'h42,8'h42,8'hFE};//0sp
//men[1]={8'h42,8'h42,8'h42,8'h42,8'h00,8'h00};//1!
//men[2]={8'h08,8'h08,8'h08,8'h08,8'h08,8'h0F};//3#
//men[3]={8'h08,8'h08,8'h08,8'h08,8'h08,8'h00};//4$
end
//-----
assignlcd_sclk=clk;//slck:
5110的同步时针输入=分频时钟
assignlcd_rst=1;//lcd_rst:
5110的复位信号输出,低电平进行复位
//-----时钟分频-----
always@(posedgesys_clk)
begin
if(!
reset)cnt<=0;//rest=0,进行时钟复位
else
begin
cnt<=cnt+1;
if(cnt==49)cnt<=0;//50*20ns=1000ns=1us,产生频率为1Mhz的时钟
if(cnt<25)clk<=0;//占空比调整50%
elseclk<=1;
end
end
//-----切换状态机1:
模拟clk的状态-----
always@(posedgesys_clk)
begin
if(!
reset)
p<=clk_l;//状态机p1=clk_l=2'd0=0
else
case(p)
clk_l:
begin
if(clk)p<=clk_rising_edge;//clk为高电平,p变成上升沿
elsep<=clk_l;//clk为低电平,p变成低电平
end
clk_rising_edge:
p<=clk_h;//p在上升沿后变成高电平
clk_h:
begin
if(!
clk)p<=clk_falling_edge;//clk为低电平,p变成下降沿
elsep<=clk_h;//clk为高电平,p变成高电平
end
clk_falling_edge:
p<=clk_l;//p在下降沿后变成低电平
default;
endcase;
end
//-----切换状态机2-----
always@(posedgesys_clk)
begin
if(!
reset)
begin
p2<=idle;//idle=3'd0;
lcd_sce<=OFF;//OFF=1'b1;lcd_sce:
片选信号,低电平,该芯片工作
cnt3<=0;//cnt3:
16位的状态计数器
end
else
case(p2)
//-----------------------------------------------
idle:
//p2为idle状态
begin
lcd_sce<=OFF;
cnt3<=cnt3+1;
case(cnt3)
//-----data_reg:
8位数据寄存器---lcd_dc:
数据命令切换脚---状态机2的状态------状态返回
0:
begindata_reg<=8'h21;//8'b0010_0001表示命令集的功能设置,
//第2位PD=0,芯片是活动的;PD=1芯片处于掉电模式;
//第1位V=0,水平寻址;V=1垂直寻址模式
//第0位H=1,使用扩展指令集;H=0使用基本指令集
lcd_dc<=CMD;
p2<=shift_data;
p_back<=idle;end
1:
begindata_reg<=8'hc8;//8'b1100_1000设置液晶偏置电压V_op寄存器
//V_op6=1V_op5=0V_op4=0V_op3=1V_op2=0V_op1=0V_op0=0
lcd_dc<=CMD;
p2<=shift_data;
p_back<=idle;end
2:
begindata_reg<=8'h06;//8'b0000_0110温度控制,温度校正
//第1位TC_1=1
//第0位TC_0=0整个表示选用温度系数2
lcd_dc<=CMD;
p2<=shift_data;
p_back<=idle;end
3:
begindata_reg<=8'h13;//8‘b0001_0011设置偏置系统
//第2为BS_2=0第1位BS_1=1第0位BD_0=1;
lcd_dc<=CMD;
p2<=shift_data;
p_back<=idle;end
4:
begindata_reg<=8'h20;//8'b0010_0000表示命令集的功能设置
//第2位PD=0,芯片是活动的;PD=1芯片处于掉电模式;
//第1位V=0,水平寻址;V=1垂直寻址模式
//第0位H=0,使用扩展指令集;H=0使用基本指令集
lcd_dc<=CMD;
p2<=shift_data;
p_back<=idle;end
5:
beginp2<=clear_screen;//p2状态由shift_data换成clear_screen
p_back<=clear_screen;end
6:
begindata_reg<=8'h0c;//8'b0000_1100设定显示模式,正常显示
//第2位D=1,
//第0位E=0,DE=01表示普通模式
lcd_dc<=CMD;
p2<=shift_data;
p_back<=idle;end
//-----设置显示坐标-----
7:
beginp2<=set_xy;//p2状态变成set_xy
p_back<=set_xy;//返回状态也变成set_xy
y_reg<=0;//y坐标为0(范围为0-5)
x_reg<=0;//x坐标为2(范围为0-83)
end
//-----显示字符-----
8:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=4;//雄
end
9:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=0;//空白
end
10:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=3;//黑块
end
11:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=1;//力
end
//-----设置显示坐标-----
12:
beginp2<=set_xy;//p2状态变成set_xy
p_back<=set_xy;//返回状态也变成set_xy
y_reg<=2;//y坐标为0(范围为0-5)
x_reg<=0;//x坐标为2(范围为0-83)
end
13:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=1;//力
end
14:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=4;//雄
end
15:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=0;//空格
end
16:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=5;//起
end
17:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=4;//雄
end
//-----设置显示坐标-----
18:
beginp2<=set_xy;//p2状态变成set_xy
p_back<=set_xy;//返回状态也变成set_xy
y_reg<=4;//y坐标为0(范围为0-5)
x_reg<=32;//x坐标为2(范围为0-83)
end
19:
beginp2<=disp_char;//p2状态变成显示字符
p_back<=disp_char;
char_reg<=4;//雄
end
20:
begincnt3<=20;//执行完后,在这进行停止
end
default;
endcase;
end
//------------------------------------------------
shift_data:
//p2为传输数据状态
begin
if(p==clk_falling_edge)//在下降沿进行数据传输
begin
if(cnt2==8)
begin
cnt2<=0;
p2<=p_back;
end
else
begin
p2<=shift_data1;
lcd_sce<=ONN;
lcd_sdin<=data_reg[7];//将数据寄存器的最高位发送
end
end
else
p2<=shift_data;
end
//-----------------------------------------------
shift_data1:
begin
if(p==clk_rising_edge)//上升沿数据进行移位
begin
data_reg<={data_reg[6:
0],data_reg[7]};//进行数据高位移位
cnt2<=cnt2+1;
p2<=shift_data;
end
elsep2<=shift_data1;
end
//-------------------------------------------------
clear_screen:
//清屏
begin
data_reg<=8'h00;
cnt4<=cnt4+1;
lcd_sce<=OFF;
lcd_dc<=DATA;
if(cnt4==504)//6行*84列=504
begin
cnt4<=0;
p2<=idle;
end
else
p2<=shift_data;
end
//-------------------------------------------------
set_xy:
//设置X,y方向坐标
begin
cnt4<=cnt4+1;
lcd_sce<=OFF;
lcd_dc<=CMD;
case(cnt4)
0:
begindata_reg<=(8'b0100_0000|y_reg);
p2<=shift_data;end
1:
begindata_reg<=(8'b1000_0000|x_reg);
p2<=shift_data;end
2:
beginp2<=idle;
cnt4<=0;end
default;
endcase;
end
//-------------------------------------------------
disp_char:
//字符从字符库读入
begin
cnt4<=cnt4+1;
lcd_sce<=OFF;
lcd_dc<=DATA;
if(cnt4==16)//需要修改
begin
p2<=set_xy2;
p_back<=set_xy2;//返回状态也变成set_xy
y_reg<=y_reg+1;
end
else
begin
temp=men[char_reg];
case(cnt4)
0:
data_reg<=temp[0:
7];
1:
data_reg<=temp[8:
15];
2:
data_reg<=temp[16:
23];
3:
data_reg<=temp[24:
31];
4:
data_reg<=temp[32:
39];
5:
data_reg<=temp[40:
47];
6:
data_reg<=temp[48:
55];
7:
data_reg<=temp[56:
63];
8:
data_reg<=temp[64:
71];
9:
data_reg<=temp[72:
79];
10:
data_reg<=temp[80:
87];
11:
data_reg<=temp[88:
95];
12:
data_reg<=temp[96:
103];
13:
data_reg<=temp[104:
111];
14:
data_reg<=temp[112:
119];
15:
data_reg<=temp[120:
127];
default;
endcase;
p2<=shift_data;
end
end
//-------------------------------------------------
set_xy2:
//设置X,y方向坐标
begin
cnt4<=cnt4+1;
lcd_sce<=OFF;
lcd_dc<=CMD;
case(cnt4)
17:
begindata_reg<=(8'b0100_0000|y_reg);
p2<=shift_data;end
18:
begindata_reg<=(8'b1000_0000|x_reg);
p2<=shift_data;end
19:
beginp2<=disp_char2;
p_back<=disp_char2;
cnt4<=0;end
default;
endcase;
end
//--------------------------------------------------
disp_char2:
//字符从字符库读入
begin
cnt4<=cnt4+1;
lcd_sce<=OFF;
lcd_dc<=DATA;
if(cnt4==16)
begin
p2<=set_xy3;
p_back<=set_xy3;//返回状态也变成set_xy
y_reg<=y_reg-1;
x_reg<=x_reg+16;
cnt4<=0;
end
else
begin
case(cnt4)