2012年11月21日 星期三

LAB06 LCD Display "Hello Word I like FPGA"

LAB06 LCD Display "Hello Word I like FPGA" 適用於DE2-70

源自於 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

沒有留言:

張貼留言

Messaging API作為替代方案

  LINE超好用功能要沒了!LINE Notify明年3月底終止服務,有什麼替代方案? LINE Notify將於2025年3月31日結束服務,官方建議改用Messaging API作為替代方案。 //CHANNEL_ACCESS_TOKEN = 'Messaging ...