源自於 http://www.haogongju.net/art/1532697
//程序實現的功能:在LCD1602液晶上顯示字符;
module lcd_1602(CLOCK_50,KEY,LCD_DATA,LCD_EN,LCD_RS,LCD_RW,LCD_ON,LCD_BLON);
input CLOCK_50;
input [3:0]KEY;
output [7:0] LCD_DATA;
output LCD_EN;
output LCD_RS;
output LCD_RW;
output LCD_ON;
output LCD_BLON;
// (sysclk, rst_n, lcd_en, lcd_rs, lcd_rw, lcd_data );
//input sysclk; //系統時鐘 50MHZ
//input rst_n; //復位信號,低電平有效;
//output lcd_en; //讀寫使能信號,高電平有效;
//output lcd_rs; //數據命令選擇端(H/L);
//output lcd_rw; //讀寫選擇端(H/L);
//output[7:0] lcd_data; //8位數據口;
wire sysclk;
assign sysclk=CLOCK_50;
wire rst_n;
assign rst_n=KEY[0];
assign LCD_ON=1'b1;
wire LCD_EN;
wire LCD_RW;
reg LCD_RS;
reg[7:0] LCD_DATA;
parameter [127:0]row1=" hello world!";
//因為lcd1602每一行可顯示16個字符,一個字符占8位;
parameter [127:0]row2=" I like FPGA!";
//所以每一行一共有16*8=128位;
reg [15:0] time_cnt;
always @(posedge sysclk or negedge rst_n)
begin
if(!rst_n)
time_cnt<=16'h0;
else
time_cnt<=time_cnt+16'b1;
end
assign LCD_RW=1'b0;
assign LCD_EN=time_cnt[15];
wire state_flag ;
//狀態標誌位 ,因為FPGA的運算速度比LCD1602要快的多,
//所以必須要等到LCD1602穩定後才往裏面寫數據;
assign state_flag=(time_cnt==16'h7fff)?1'b1:1'b0 ;
//lcd_en最小值500ns ,所以lcd_en的頻率應維持在2MHZ以內;
parameter IDLE=8'h00; //lcd1602 initial;
parameter INI_SET=8'h01; //顯示工作模式設置;
parameter INI_CLR=8'h02; //清屏顯示;
parameter CURSOR_SET1=8'h03; // 光標設置1;
parameter CURSOR_SET2=8'h04; //光標設置2;
//display line 1;
parameter LINE1_ADDER=8'h05;
parameter LINE1_0=8'h06;
parameter LINE1_1=8'h07;
parameter LINE1_2=8'h08;
parameter LINE1_3=8'h09;
parameter LINE1_4=8'h0A;
parameter LINE1_5=8'h0B;
parameter LINE1_6=8'h0C;
parameter LINE1_7=8'h0D;
parameter LINE1_8=8'h0E;
parameter LINE1_9=8'h0F;
parameter LINE1_A=8'h10;
parameter LINE1_B=8'h11;
parameter LINE1_C=8'h12;
parameter LINE1_D=8'h13;
parameter LINE1_E=8'h14;
parameter LINE1_F=8'h15;
// display line 2;
parameter LINE2_ADDER=8'h16;
parameter LINE2_0=8'h17;
parameter LINE2_1=8'h18;
parameter LINE2_2=8'h19;
parameter LINE2_3=8'h1A;
parameter LINE2_4=8'h1B;
parameter LINE2_5=8'h1C;
parameter LINE2_6=8'h1D;
parameter LINE2_7=8'h1E;
parameter LINE2_8=8'h1F;
parameter LINE2_9=8'h20;
parameter LINE2_A=8'h21;
parameter LINE2_B=8'h22;
parameter LINE2_C=8'h23;
parameter LINE2_D=8'h24;
parameter LINE2_E=8'h25;
parameter LINE2_F=8'h26;
//------------------------------------------------//
reg[7:0] state;
reg[7:0] next_state;
always @ (posedge sysclk or negedge rst_n)
begin
if(!rst_n)
state<=IDLE;
else if(state_flag)
state<=next_state;
end
always @ (*)
begin case(state) //display line1;
IDLE : next_state=INI_SET;
INI_SET : next_state=INI_CLR;
INI_CLR : next_state=CURSOR_SET1;
CURSOR_SET1 : next_state=CURSOR_SET2;
CURSOR_SET2 : next_state=LINE1_ADDER;
LINE1_ADDER : next_state=LINE1_0;
LINE1_0 : next_state=LINE1_1;
LINE1_1 : next_state=LINE1_2;
LINE1_2 : next_state=LINE1_3;
LINE1_3 : next_state=LINE1_4;
LINE1_4 : next_state=LINE1_5;
LINE1_5 : next_state=LINE1_6;
LINE1_6 : next_state=LINE1_7;
LINE1_7 : next_state=LINE1_8;
LINE1_8 : next_state=LINE1_9;
LINE1_9 : next_state=LINE1_A;
LINE1_A : next_state=LINE1_B;
LINE1_B : next_state=LINE1_C;
LINE1_C : next_state=LINE1_D;
LINE1_D : next_state=LINE1_E;
LINE1_E : next_state=LINE1_F;
LINE1_F : next_state=LINE2_ADDER;
//display line2;
LINE2_ADDER : next_state=LINE2_0;
LINE2_0 : next_state=LINE2_1;
LINE2_1 : next_state=LINE2_2;
LINE2_2 : next_state=LINE2_3;
LINE2_3 : next_state=LINE2_4;
LINE2_4 : next_state=LINE2_5;
LINE2_5 : next_state=LINE2_6;
LINE2_6 : next_state=LINE2_7;
LINE2_7 : next_state=LINE2_8;
LINE2_8 : next_state=LINE2_9;
LINE2_9 : next_state=LINE2_A;
LINE2_A : next_state=LINE2_B;
LINE2_B : next_state=LINE2_C;
LINE2_C : next_state=LINE2_D;
LINE2_D : next_state=LINE2_E;
LINE2_E : next_state=LINE2_F;
LINE2_F : next_state=LINE1_ADDER;
default : next_state=IDLE;
endcase
end
always @ (posedge sysclk or negedge rst_n)
begin
if(!rst_n)
begin
LCD_RS <= 1'h0;
LCD_DATA <= 8'hxx;
end
else if(state_flag)
begin
case (next_state)
IDLE: LCD_RS <= 1'h0;
INI_SET: LCD_RS <= 1'h0;
INI_CLR: LCD_RS <= 1'h0;
CURSOR_SET1 : LCD_RS <= 1'h0;
CURSOR_SET2 : LCD_RS <= 1'h0;
// line1
LINE1_ADDER : LCD_RS <= 1'h0;
LINE1_0 : LCD_RS <= 1'h1;
LINE1_1 : LCD_RS <= 1'h1;
LINE1_2 : LCD_RS <= 1'h1;
LINE1_3 : LCD_RS <= 1'h1;
LINE1_4 : LCD_RS <= 1'h1;
LINE1_5 : LCD_RS <= 1'h1;
LINE1_6 : LCD_RS <= 1'h1;
LINE1_7 : LCD_RS <= 1'h1;
LINE1_8 : LCD_RS <= 1'h1;
LINE1_9 : LCD_RS <= 1'h1;
LINE1_A : LCD_RS <= 1'h1;
LINE1_B : LCD_RS <= 1'h1;
LINE1_C : LCD_RS <= 1'h1;
LINE1_D : LCD_RS <= 1'h1;
LINE1_E : LCD_RS <= 1'h1;
LINE1_F : LCD_RS <= 1'h1;
// line2
LINE2_ADDER : LCD_RS <=1'h0;
LINE2_0 : LCD_RS <=1'h1;
LINE2_1 : LCD_RS <=1'h1;
LINE2_2 : LCD_RS <=1'h1;
LINE2_3 : LCD_RS <=1'h1;
LINE2_4 : LCD_RS <=1'h1;
LINE2_5 : LCD_RS <=1'h1;
LINE2_6 : LCD_RS <=1'h1;
LINE2_7 : LCD_RS <=1'h1;
LINE2_8 : LCD_RS <=1'h1;
LINE2_9 : LCD_RS <=1'h1;
LINE2_A : LCD_RS <=1'h1;
LINE2_B : LCD_RS <=1'h1;
LINE2_C : LCD_RS <=1'h1;
LINE2_D : LCD_RS <=1'h1;
LINE2_E : LCD_RS <=1'h1;
LINE2_F : LCD_RS <=1'h1;
endcase
case(next_state)
IDLE : LCD_DATA <=8'hxx;
INI_SET : LCD_DATA <=8'h38;
//設置16*2顯示,5*7點陣,8位數據接口;
INI_CLR : LCD_DATA <=8'h01; //清屏顯示;
CURSOR_SET1 : LCD_DATA <=8'h06;
//寫一個字符後地址指針加一;
CURSOR_SET2 : LCD_DATA <=8'h0c;
//設置開顯示,不顯示光標;
//line1
LINE1_ADDER : LCD_DATA <=8'h80;
//LCD1602第一行 首地址;
LINE1_0 : LCD_DATA <=row1[127:120];
LINE1_1 : LCD_DATA <=row1[119:112];
LINE1_2 : LCD_DATA <=row1[111:104];
LINE1_3 : LCD_DATA <=row1[103:96];
LINE1_4 : LCD_DATA <=row1[95:88];
LINE1_5 : LCD_DATA <=row1[87:80];
LINE1_6 : LCD_DATA <=row1[79:72];
LINE1_7 : LCD_DATA <=row1[71:64];
LINE1_8 : LCD_DATA <=row1[63:56];
LINE1_9 : LCD_DATA <=row1[55:48];
LINE1_A : LCD_DATA <=row1[47:40];
LINE1_B : LCD_DATA <=row1[39:32];
LINE1_C : LCD_DATA <=row1[31:24];
LINE1_D : LCD_DATA <=row1[23:16];
LINE1_E : LCD_DATA <=row1[15:8];
LINE1_F : LCD_DATA <=row1[7:0];
//line2
LINE2_ADDER : LCD_DATA <=8'hC0;
//LCD1602第二行首地址(8'h80+8'h40=8'hC0)
LINE2_0 : LCD_DATA <=row2[127:120];
LINE2_1 : LCD_DATA <=row2[119:112];
LINE2_2 : LCD_DATA <=row2[111:104];
LINE2_3 : LCD_DATA <=row2[103:96];
LINE2_4 : LCD_DATA <=row2[95:88];
LINE2_5 : LCD_DATA <=row2[87:80];
LINE2_6 : LCD_DATA <=row2[79:72];
LINE2_7 : LCD_DATA <=row2[71:64];
LINE2_8 : LCD_DATA <=row2[63:56];
LINE2_9 : LCD_DATA <=row2[55:48];
LINE2_A : LCD_DATA <=row2[47:40];
LINE2_B : LCD_DATA <=row2[39:32];
LINE2_C : LCD_DATA <=row2[31:24];
LINE2_D : LCD_DATA <=row2[23:16];
LINE2_E : LCD_DATA <=row2[15:8];
LINE2_F : LCD_DATA <=row2[7:0];
endcase
end
end
endmodule
沒有留言:
張貼留言