?? lcd.v
字號:
module lcd(clk,rst,lcd_e,lcd_rw,lcd_rs,data);
input clk,rst;
output lcd_e,lcd_rw,lcd_rs;
output [7:0] data;
reg lcd_e,lcd_rw,lcd_rs;
reg [7:0] datain;
reg [7:0] data;
reg [10:0] state;
reg flag;
reg [5:0] address;
reg [6:0] counter;
reg [3:0] divcounter;
parameter IDLE =11'b00000000000;
parameter CLEAR =11'b00000000001; //清屏
parameter RETURNCURSOR =11'b00000000010; //歸home位
parameter SETMODE =11'b00000000100;
//輸入方式設置,讀寫數據后ram地址增/減1;畫面動/不動
parameter SWITCHMODE =11'b00000001000;
//顯示狀態設置,顯示開/關;光標開/關;閃爍開/關
parameter SHIFT =11'b00000010000;
//光標畫面滾動 畫面/光標平移一位;左/右平移一位
parameter SETFUNCTION =11'b00000100000;
//工作方式設置 1:8/1:4位數據接口;兩行/一行顯示;5x10/5x7點陣
parameter SETCGRAM =11'b00001000000; //設置CGRAM
parameter SETDDRAM1 =11'b00010000000; //設置DDRAM
parameter SETDDRAM2 =11'b00011000000; //設置DDRAM
parameter READFLAG =11'b00100000000; //
parameter WRITERAM =11'b01000000000; //寫RAM
parameter READRAM =11'b10000000000; //讀RAM
parameter cur_inc =1;
parameter cur_dec =0;
parameter cur_shift =1;
parameter cur_noshift =0;
parameter open_display =1;
parameter open_cur =0;
parameter blank_cur =0;
parameter shift_display =1;
parameter shift_cur =0;
parameter right_shift =1;
parameter left_shift =0;
parameter datawidth8 =1;
parameter datawidth4 =0;
parameter twoline =1;
parameter oneline =0;
parameter font5x10 =1;
parameter font5x7 =0;
reg [20:0] clkcnt;
always @ (posedge clk)
if(!rst)
clkcnt<=21'b00000_0000_0000_0000_0000;
else
begin
if(clkcnt==21'b01001_1100_0100_0000_0000)
clkcnt<=21'b00000_0000_0000_0000_0000;
else
clkcnt<=clkcnt+1;
end
wire tc_clkcnt;
assign tc_clkcnt=(clkcnt==21'b01001_1100_0100_0000_0000)?1:0;
reg clkdiv;
always @ (posedge tc_clkcnt)
if(!rst)
clkdiv<=0;
else
clkdiv<=~clkdiv;
reg clk_int;
always @ (posedge clkdiv)
if(rst==0)
clk_int<=0;
else
clk_int<=~clk_int;
always @ (negedge clkdiv)//下降沿lcd_e輸出
if(!rst)
lcd_e<=0;
else
lcd_e<=~lcd_e;
always @ (posedge clk_int or negedge rst)
begin
if(!rst)
begin
state<=IDLE;
flag<=0;
counter<=0;
divcounter<=0;
address<=0;
end
else
begin
case(state)
IDLE :begin
if(!flag)
begin
state<=SETFUNCTION;
flag<=1'b1;
counter<=0;
divcounter<=0;
end
else if(divcounter<4'd8)//改變移動速度
begin
divcounter<=divcounter+1;
state<=IDLE;
lcd_rw <=1'b1;
end
else
begin
divcounter<=0;
state<=SHIFT;
end
end
CLEAR :begin lcd_rs<=0;lcd_rw<=0;data<=8'b0000_0001;
state<=SETMODE;end
SETMODE :begin lcd_rs<=0;lcd_rw<=0;data[7:2]<=6'b000001;data[1]<=cur_inc;data[0]<=cur_noshift;
state<=SETDDRAM1;end
RETURNCURSOR :begin lcd_rs<=0;lcd_rw<=0;data<=8'b00000010;
state<=WRITERAM;end
SWITCHMODE :begin lcd_rs<=0;lcd_rw<=0;data[7:3]<=5'b00001;data[2]<=open_display;data[1]<=open_cur;data[0]<=blank_cur;
state<=CLEAR;end
SHIFT :begin lcd_rs<=0;lcd_rw<=0;data[7:4]<=4'b0001;data[3]<=shift_display;data[2]<=left_shift;data[1:0]<=2'b00;
state<=IDLE;end
SETFUNCTION :begin lcd_rs<=0;lcd_rw<=0;data[7:5]<=3'b001;data[4]<=datawidth8;data[3]<=twoline;data[2]<=font5x10;data[1:0]<=2'b00;
state<=SWITCHMODE;end
SETCGRAM :begin lcd_rs<=0;lcd_rw<=0;data<=8'b01000000;state<=IDLE;end
SETDDRAM1 :begin
lcd_rs<=0;
lcd_rw<=0;
state<=WRITERAM;
if(counter==0)
data<=8'b1000_0000;
else
data<=8'b1100_0000;
end
SETDDRAM2 :begin lcd_rs<=0;lcd_rw<=0;data<=8'b10000000;state<=WRITERAM;end//0x80顯示在第一行
WRITERAM :begin
lcd_rs<=1;
lcd_rw<=0;
data<=datain;
if(counter<7'd40)
begin
address = counter+1;
counter=counter+1;
state<=WRITERAM;
end
else if(counter==7'd40)//1602lcd第一行能顯示40個字符,可通過左移分別顯示出來
begin
state<=SETDDRAM1;
counter<=counter+1;
end
else if(counter<7'd73)
begin
address=counter-'d41+'d8;//-41表示所有字符重新顯示在第二行,從第8個字符開始顯示
counter=counter+1;
state=WRITERAM;
end
else if(counter<7'd81)
begin
address=counter-7'd81+7'd8;
counter=counter+1;
state<=WRITERAM;
end
else
begin
data<=8'd87;//"W"的ASCII值
state<=SHIFT;
end
end
endcase
end
end
char_ram charram(.address(address),.data(datain));
endmodule
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -