首页 > 代码库 > verilog写的LCD1602 显示

verilog写的LCD1602 显示

在读本文之前,请先阅读 LCD1602 的 datasheet(百度到处都是) ,熟悉有关的11条指令集。

LCD1602的11个指令集链接 http://www.cnblogs.com/aslmer/p/5801363.html(这是我总结的11条指令集,中英文结合)


1、LCD1602基础知识

 技术分享

 

 (2)LCD1602操作流程

 技术分享

 


 2、代码:

module lcd_1602_driver(                clk    ,                rst_n  ,                lcd_en ,                lcd_rw ,                lcd_rs ,                lcd_data              );input        clk    ;input        rst_n  ;output       lcd_en ;output       lcd_rw ;output       lcd_rs ;output [7:0] lcd_data;wire         clk ;wire         rst_n  ;wire         lcd_en ;wire         lcd_rw;reg  [7:0]   lcd_data;reg          lcd_rs  ;reg [5:0]    c_state ;reg [5:0]    n_state ;wire  [127:0]  row_1;wire  [127:0]  row_2;assign row_1 ="i am liu xiao yi" ;assign row_2 ="happy everyday !";//----------------------------------------------------------------------//initialize//first step is waitng more than 20 ms.parameter TIME_15MS = 1000_000 ; //20000000/20=1000_000//parameter TIME_15MS = 9‘h100 ; //just for testparameter TIME_500HZ= 100_000  ; ////parameter TIME_500HZ= 4‘hf;  //just for test//use gray codeparameter         IDLE=    8h00  ;                             parameter SET_FUNCTION=    8h01  ;parameter     DISP_OFF=    8h03  ;parameter   DISP_CLEAR=    8h02  ;parameter   ENTRY_MODE=    8h06  ;parameter   DISP_ON   =    8h07  ;parameter    ROW1_ADDR=    8h05  ;parameter       ROW1_0=    8h04  ;parameter       ROW1_1=    8h0C  ;parameter       ROW1_2=    8h0D  ;parameter       ROW1_3=    8h0F  ;parameter       ROW1_4=    8h0E  ;parameter       ROW1_5=    8h0A  ;parameter       ROW1_6=    8h0B  ;parameter       ROW1_7=    8h09  ;parameter       ROW1_8=  8h08  ;parameter       ROW1_9=    8h18  ;parameter       ROW1_A=    8h19  ;parameter       ROW1_B=    8h1B  ;parameter       ROW1_C=    8h1A  ;parameter       ROW1_D=    8h1E  ;parameter       ROW1_E=    8h1F  ;parameter       ROW1_F=    8h1D  ;parameter    ROW2_ADDR=    8h1C  ;parameter       ROW2_0=    8h14  ;parameter       ROW2_1=    8h15  ;parameter       ROW2_2=    8h17  ;parameter       ROW2_3=    8h16  ;parameter       ROW2_4=    8h12  ;parameter       ROW2_5=    8h13  ;parameter       ROW2_6=    8h11  ;parameter       ROW2_7=    8h10  ;parameter       ROW2_8=    8h30  ;parameter       ROW2_9=    8h31  ;parameter       ROW2_A=    8h33  ;parameter       ROW2_B=    8h32  ;parameter       ROW2_C=    8h36  ;parameter       ROW2_D=    8h37  ;parameter       ROW2_E=    8h35  ;parameter       ROW2_F=    8h34  ;reg [19:0] cnt_15ms ;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1b0)begin        cnt_15ms<=0;    end    else if(cnt_15ms == TIME_15MS -1)begin        cnt_15ms<=cnt_15ms;    end    else        cnt_15ms<=cnt_15ms + 1 ;endwire delay_done = (cnt_15ms==TIME_15MS-1)? 1b1 : 1b0 ;//----------------------------------------------------------------------//500nsreg [19:0] cnt_500hz;always  @(posedge clk or negedge rst_n)begin    if(rst_n==1b0)begin        cnt_500hz <= 0;    end    else if(delay_done==1)begin        if(cnt_500hz== TIME_500HZ - 1)            cnt_500hz<=0;        else            cnt_500hz<=cnt_500hz + 1 ;    end    else        cnt_500hz<=0;endassign lcd_en = (cnt_500hz>(TIME_500HZ-1)/2)? 1b0 : 1b1;  //下降沿assign write_flag = (cnt_500hz==TIME_500HZ - 1) ? 1b1 : 1b0 ;//set_function ,display off ,display clear ,entry mode set//----------------------------------------------------------------------always  @(posedge clk or negedge rst_n)begin    if(rst_n==1b0)begin        c_state <= IDLE    ;    end    else if(write_flag==1) begin        c_state<= n_state  ;    end    else        c_state<=c_state   ;endalways  @(*)begin    case (c_state)        IDLE: n_state = SET_FUNCTION ;SET_FUNCTION: n_state = DISP_OFF     ;    DISP_OFF: n_state = DISP_CLEAR   ;  DISP_CLEAR: n_state = ENTRY_MODE   ;  ENTRY_MODE: n_state = DISP_ON      ;  DISP_ON   : n_state = ROW1_ADDR    ;   ROW1_ADDR: n_state = ROW1_0       ;      ROW1_0: n_state = ROW1_1       ;      ROW1_1: n_state = ROW1_2       ;      ROW1_2: n_state = ROW1_3       ;      ROW1_3: n_state = ROW1_4       ;      ROW1_4: n_state = ROW1_5       ;      ROW1_5: n_state = ROW1_6       ;      ROW1_6: n_state = ROW1_7       ;      ROW1_7: n_state = ROW1_8       ;      ROW1_8: n_state = ROW1_9       ;      ROW1_9: n_state = ROW1_A       ;      ROW1_A: n_state = ROW1_B       ;      ROW1_B: n_state = ROW1_C       ;      ROW1_C: n_state = ROW1_D       ;      ROW1_D: n_state = ROW1_E       ;      ROW1_E: n_state = ROW1_F       ;      ROW1_F: n_state = ROW2_ADDR    ;   ROW2_ADDR: n_state = ROW2_0       ;      ROW2_0: n_state = ROW2_1       ;      ROW2_1: n_state = ROW2_2       ;      ROW2_2: n_state = ROW2_3       ;      ROW2_3: n_state = ROW2_4       ;      ROW2_4: n_state = ROW2_5       ;      ROW2_5: n_state = ROW2_6       ;      ROW2_6: n_state = ROW2_7       ;      ROW2_7: n_state = ROW2_8       ;      ROW2_8: n_state = ROW2_9       ;      ROW2_9: n_state = ROW2_A       ;      ROW2_A: n_state = ROW2_B       ;      ROW2_B: n_state = ROW2_C       ;      ROW2_C: n_state = ROW2_D       ;      ROW2_D: n_state = ROW2_E       ;      ROW2_E: n_state = ROW2_F       ;      ROW2_F: n_state = ROW1_ADDR    ;     default: n_state = n_state      ;   endcase    end      assign lcd_rw = 0;   always  @(posedge clk or negedge rst_n)begin       if(rst_n==1b0)begin           lcd_rs <= 0 ;   //order or data  0: order 1:data       end       else if(write_flag == 1)begin           if((n_state==SET_FUNCTION)||(n_state==DISP_OFF)||              (n_state==DISP_CLEAR)||(n_state==ENTRY_MODE)||              (n_state==DISP_ON ) ||(n_state==ROW1_ADDR)||              (n_state==ROW2_ADDR))begin           lcd_rs<=0 ;           end            else  begin           lcd_rs<= 1;           end       end       else begin           lcd_rs<=lcd_rs;       end        end                      always  @(posedge clk or negedge rst_n)begin       if(rst_n==1b0)begin           lcd_data<=0 ;       end       else  if(write_flag)begin           case(n_state)                 IDLE: lcd_data <= 8hxx;         SET_FUNCTION: lcd_data <= 8h38; //2*16 5*8 8位数据             DISP_OFF: lcd_data <= 8h08;           DISP_CLEAR: lcd_data <= 8h01;           ENTRY_MODE: lcd_data <= 8h06;           DISP_ON   : lcd_data <= 8h0c;  //显示功能开,没有光标,且不闪烁,            ROW1_ADDR: lcd_data <= 8h80; //00+80               ROW1_0: lcd_data <= row_1 [127:120];               ROW1_1: lcd_data <= row_1 [119:112];               ROW1_2: lcd_data <= row_1 [111:104];               ROW1_3: lcd_data <= row_1 [103: 96];               ROW1_4: lcd_data <= row_1 [ 95: 88];               ROW1_5: lcd_data <= row_1 [ 87: 80];               ROW1_6: lcd_data <= row_1 [ 79: 72];               ROW1_7: lcd_data <= row_1 [ 71: 64];               ROW1_8: lcd_data <= row_1 [ 63: 56];               ROW1_9: lcd_data <= row_1 [ 55: 48];               ROW1_A: lcd_data <= row_1 [ 47: 40];               ROW1_B: lcd_data <= row_1 [ 39: 32];               ROW1_C: lcd_data <= row_1 [ 31: 24];               ROW1_D: lcd_data <= row_1 [ 23: 16];               ROW1_E: lcd_data <= row_1 [ 15:  8];               ROW1_F: lcd_data <= row_1 [  7:  0];            ROW2_ADDR: lcd_data <= 8hc0;      //40+80               ROW2_0: lcd_data <= row_2 [127:120];               ROW2_1: lcd_data <= row_2 [119:112];               ROW2_2: lcd_data <= row_2 [111:104];               ROW2_3: lcd_data <= row_2 [103: 96];               ROW2_4: lcd_data <= row_2 [ 95: 88];               ROW2_5: lcd_data <= row_2 [ 87: 80];               ROW2_6: lcd_data <= row_2 [ 79: 72];               ROW2_7: lcd_data <= row_2 [ 71: 64];               ROW2_8: lcd_data <= row_2 [ 63: 56];               ROW2_9: lcd_data <= row_2 [ 55: 48];               ROW2_A: lcd_data <= row_2 [ 47: 40];               ROW2_B: lcd_data <= row_2 [ 39: 32];               ROW2_C: lcd_data <= row_2 [ 31: 24];               ROW2_D: lcd_data <= row_2 [ 23: 16];               ROW2_E: lcd_data <= row_2 [ 15:  8];               ROW2_F: lcd_data <= row_2 [  7:  0];           endcase                            end       else              lcd_data<=lcd_data ;   endendmodule

 


3、testbench

 

`timescale 1 ns/1 nsmodule lcd1602_tb();//时钟和复位reg clk  ;reg rst_n;wire lcd_en ;wire lcd_rs ;wire lcd_rw ;wire [7:0] lcd_data;        //时钟周期,单位为ns,可在此修改时钟周期。        parameter CYCLE    = 20;        //复位时间,此时表示复位3个时钟周期的时间。        parameter RST_TIME = 3 ;        //待测试的模块例化       lcd_1602_driver u1_lcd_1602_driver(               .clk     (clk     ),               .rst_n   (rst_n   ),               .lcd_en  (lcd_en  ),               .lcd_rw  (lcd_rw  ),               .lcd_rs  (lcd_rs  ),               .lcd_data(lcd_data)              );            //生成本地时钟50M            initial begin                clk = 0;                forever                #(CYCLE/2)                clk=~clk;            end            //产生复位信号            initial begin                rst_n = 1;                #2;                rst_n = 0;                #(CYCLE*RST_TIME);                rst_n = 1;            end            endmodule

 


4、modesim 仿真

技术分享


 5、结果展示

 

 技术分享

verilog写的LCD1602 显示