基于DE2-115的LCD1602应用

来源:互联网 发布:第比利斯事件知乎 编辑:程序博客网 时间:2024/04/29 03:35

module LCD(clk,rst,LCD_E,LCD_RW,LCD_RS,LCD_DATA);  input clk;              //时钟信号,50Mhz  input rst;              //复位信号,低电平进行复位  output LCD_E;           //1602使能引脚,1时读取信息,1->0(下降沿)执行命令  output LCD_RS;          //1602数据——H/命令——L  选择端  output LCD_RW;          //1602写——L/读——H  选择端  output [7:0] LCD_DATA;  //1602数据传输端口  wire LCD_E;  reg [8:0] count;  reg clk_div1;       //500个clk的周期,20ns*500=10us  reg clk_div2;       //1000个,20us  reg [7:0] count1;   //250个clk_div2的周期,20us*250=5000u=5ms  reg clk_buf;  //******************  //-----分频模块-----  //****************** 

always @(posedge clk or negedge rst)  begin      if(!rst)    //rst=0          count<=0;      else          begin              if(count<250)        //2500                  begin                      clk_div1<=0;                      count<=count+1'b1;                  end              else if(count>=500-1)        //5000                  count<=0;              else                  begin                      clk_div1<=1;                      count<=count+1'b1;                  end                       end  end 

always @(posedge clk_div1 or negedge rst)  begin      if(!rst)          clk_div2<=0;      else          clk_div2<=~clk_div2;  end  always @(posedge clk_div2 or negedge rst)     begin      if(!rst)    //rst=0          begin              count1<=0;              clk_buf<=0;      //          end      else          begin              if(count1<125)       //2500                  begin                      clk_buf<=0;                      count1<=count1+1'b1;                  end              else if(count1>=250-1)       //5000                  count1<=0;              else                  begin                      clk_buf<=1;                      count1<=count1+1'b1;                  end                       end  end  assign LCD_E=clk_buf;    //**********************  //-----显示控制模块-----  //**********************  reg [4:0] state;        //当前状态寄存器  ,10个状态  reg [5:0] address;      //地址的位置,0~31,  reg [7:0] LCD_DATA;  reg LCD_RW,LCD_RS;  parameter             IDLE             = 4'd0,    //空闲           CLEAR            = 4'd1,          SET_FUNCTION     = 4'd2,    //工作方式设置指令            SWITCH_MODE      = 4'd3,     //开关控制指令            SET_MODE         = 4'd4,    //输入方式设置            SET_DDRAM1       = 4'd5,    //设定第一行DDRAM地址指令            WRITE_RAM1       = 4'd6,    //向第一行写入的数码            SET_DDRAM2       = 4'd7,    //设定第2行DDRAM地址指令            WRITE_RAM2       = 4'd8,    //向第2行写入的数码            SHIFT            = 4'd9,    //设定显示屏或光标移动方向指令          STOP             = 4'd10;                reg [7:0] Data_First [15:0];  reg [7:0] Data_Second [15:0];  initial      begin          Data_First[0] =  " ";          Data_First[1] =  "W";          Data_First[2] =  "W";          Data_First[3] =  "W";          Data_First[4] =  ".";          Data_First[5] =  "N";          Data_First[6] =  "B";          Data_First[7] =  "U";          Data_First[8] =  ".";          Data_First[9] =  "E";          Data_First[10]=  "D";          Data_First[11]=  "U";          Data_First[12]=  ".";          Data_First[13]=  "C";          Data_First[14]=  "N";          Data_First[15]=  " ";                    Data_Second[0] =   " ";          Data_Second[1] =   " ";          Data_Second[2] =   " ";          Data_Second[3] =   "X";          Data_Second[4] =   "I";          Data_Second[5] =   "N";          Data_Second[6] =   "-";          Data_Second[7] =   "X";          Data_Second[8] =   "I";          Data_Second[9] =   "-";          Data_Second[10]=   "4";          Data_Second[11]=   "1";          Data_Second[12]=   "1";          Data_Second[13]=   " ";          Data_Second[14]=   " ";          Data_Second[15]=   " ";   

    end  //-----状态控制-----  always @(posedge clk_buf or negedge rst)        // clk_div1 clk_buf  begin      if(!rst)          begin              state<=IDLE;              address<=6'd0;              LCD_DATA<=8'b0000_0000;              LCD_RS<=0;              LCD_RW<=0;          end      else          begin              case(state)                  IDLE:       //空闲状态                              begin                                  LCD_DATA<=8'bzzzz_zzzz;      //8'bzzzz_zzzz                                  state<=CLEAR;                              end                  CLEAR:      //清屏指令                                  begin                                      LCD_RS<=0;                                      LCD_RW<=0;                                      LCD_DATA<=8'b0000_0001;  //指令                                      state<=SET_FUNCTION;                                                           end                  SET_FUNCTION:       //工作方式设置                                  begin                                      LCD_RS<=0;                                      LCD_RW<=0;                                      LCD_DATA<=8'b0011_1100;      //38h                                      //第4位DL:0=数据总线为4位;1=数据总线为8位★★★                                      //第3位N:0=显示1行;1=显示2行★★★                                        //第2位F:0=5×7点阵/每字符;1=5×10点阵/每字符★★★                                      state<=SWITCH_MODE;                                        end                  SWITCH_MODE:        //显示开关控制指令                                  begin                                      LCD_RS<=0;                                      LCD_RW<=0;                                      LCD_DATA<=8'b0000_1111;      //0Fh                                      //第2位D:0=显示功能关;1=显示功能开★★★                                      //第1位C:0=无光标;1=有光标★★★                                        //第0位B:1=光标闪烁; 0=光标不闪烁★★★                                      state<=SET_MODE;                                  end                  SET_MODE:       //设定显示屏或光标移动方向指令                                    begin                                      LCD_RS<=0;                                      LCD_RW<=0;                                      LCD_DATA<=8'b0000_0110;  //06h                                      //第1位N:0=读或者写一个字符后,地址指针-1,光标-1                                      //        1=读或者写一个字符后,地址指针+1,光标+1★★★                                      //第0位S:0=当写一个字符,整屏显示不移动★★★                                      //        1=当写一个字符,整屏显示左移(N=1)或者右移(N=0),以得到光标不移动而屏幕移动的效果                                      state<=SHIFT;                                   end                               SHIFT:      //设定显示屏或光标移动方向指令                                    begin                                      LCD_RS<=0;                                      LCD_RW<=0;                                      LCD_DATA<=8'b0001_0100;                                        //第3位S/C;第2位R/L                                      //     S/C   R/L     设定情况                                        //      0      0      光标左移1格,且地址指针值减1                                        //      0      1      光标右移1格,且地址指针值加1  ★★★                                      //      1      0      显示器上字符全部左移一格,但光标不动                                        //      1      1      显示器上字符全部右移一格,但光标不动                                      state<=SET_DDRAM1;                                   end                  SET_DDRAM1:     //设定第一行DDRAM地址指令                                  begin                                        LCD_RS<=0;                                      LCD_RW<=0;                                                //-----写入第一行显示起始地址:-----                   //  1   2  3  4   5   6   7  8  9  10  11  12  13  14  15  16                  // 00  01 02  03  04  05 06 07 08  09  0A  0B  0C  0D  0E  0F   第一行                                      LCD_DATA<=8'h80+8'd0; //第一行第1个位置                                                                             address<=2'd0;                                      state<=WRITE_RAM1;   //                                  Data_First_Buf<=Data_First;                                    end                  WRITE_RAM1:     //向第一行写入的数码                                  begin                                      if(address<=15)          //表示写第一行                                          begin                                              LCD_RS<=1;                                              LCD_RW<=0;                                              LCD_DATA<=Data_First[address];  //                                          Data_First_Buf<=(Data_First_Buf<<8);   //左移                                              address<=address+1'b1;                                              state<=WRITE_RAM1;                                          end                                      else                                          begin                                              LCD_RS<=0;                                              LCD_RW<=0;                                              LCD_DATA<=8'h80+address;                                              state<=SET_DDRAM2;                                          end                                  end                  SET_DDRAM2:     //设定第2行DDRAM地址指令                                  begin                                        LCD_RS<=0;                                      LCD_RW<=0;                                                //-----写入第2行显示起始地址:-----                   //  1   2  3  4   5   6   7  8  9  10  11  12  13  14  15  16                  // 40  41 42  43  44  45 46 47 48  49  4A  4B  4C  4D  4E  4F   第二行                                      LCD_DATA<=8'hC0+8'd0; //第2行第1个位置                                                                      state<=WRITE_RAM2;   //                                  Data_Second_Buf<=Data_Second;                                        address<=6'd0;                                  end                  WRITE_RAM2:     //向第2行写入的数码                              begin                                  if(address<=15)          //表示写第一行                                          begin                                              LCD_RS<=1;                                              LCD_RW<=0;                                              LCD_DATA<=Data_Second[address];  //                                          Data_Second_Buf<=(Data_Second_Buf<<8);                                               address<=address+1'b1;                                              state<=WRITE_RAM2;                                          end                                      else                                          begin                                              LCD_RS<=0;                                              LCD_RW<=0;                                              LCD_DATA<=8'hC0+address;                                              state<=STOP;                                          end                              end                  STOP:                                     begin                                              state<=STOP;                                              address<=6'd0;                                              LCD_RW<=1;                              end                  default:                              state<=CLEAR;              endcase                       end  end        endmodule

0 0
原创粉丝点击