【设计开发】 玩转FPGA (DE2-115) - 1602 LCD接口设计

1、前言spa

  闲来无事,在X宝上搜寻了一套DE2-115的FPGA开发板以丰富业余生活。虽附带光盘里包含各外设及组件驱动及接口样例,但本着“不捣腾不痛快”的折腾精神,将DE2-115的各个外设从新整理并玩转一遍。设计

  DE2-115全貌见下图,LCD1602是一个简单、实用的显示交互界面;DE2-115中的1602不支持中文字库。code

  

 

2、接口说明blog

  1602 LCD模块接口以下图所示,对几个信号作简要说明:接口

  #4 (RS) - DB内容指示信号:0-当前DB数据为命令数据;1-当前DB数据为显示数据。ip

  #5 (RW)- 读写指示信号:0-当前进行写操做;1-当前进行读操做。ci

  #6 (E)- 片选使能指示信号:0-片选无效;1-片选有效。  开发

  #7~#14 (DB0~DB7)- 显示或命令读写数据。input

  

 

3、接口时序cmd

  写时序以下图所示:因为LCD 1602配置接口没有时钟,接口时序须要严格遵照。

  

  读时序

  

 

4、接口设计

  1 //--====================================================================================--
  2 // THIS FILE IS PROVIDED IN SOURCE FORM FOR FREE EVALUATION, FOR EDUCATIONAL USE OR FOR 
  3 // PEACEFUL RESEARCH.  DO NOT USE IT IN A COMMERCIAL PRODUCT . IF YOU PLAN ON USING THIS 
  4 // CODE IN A COMMERCIAL PRODUCT, PLEASE CONTACT JUSTFORYOU200@163.COM TO PROPERLY LICENSE 
  5 // ITS USE IN YOUR PRODUCT. 
  6 // 
  7 // Project      : Verilog Common Module
  8 // File Name    : lcd_reg_intf.v
  9 // Creator(s)   : justforyou200@163.com
 10 // Date         : 2015/12/01
 11 // Description  : A Reg Timing for LCD1602
 12 //
 13 // Modification :
 14 // (1) Initial design  2015-12-01
 15 //
 16 //
 17 //--====================================================================================--
 18 
 19 module LCD_REG_INTF
 20     (  
 21         clk           ,
 22         rst_n         ,
 23         write         ,     
 24         read          ,
 25         wdata         ,
 26         reg_sel       ,
 27         rdata         ,
 28         ready         ,
 29         lcd_rs        ,
 30         lcd_rw        ,
 31         lcd_en        ,
 32         lcd_db_out    ,
 33         lcd_db_oen    ,
 34         lcd_db_in     
 35     );
 36  
 37 //PARA   DECLARATION
 38 parameter LCD_EN_SETUP_MIN = 16'd40   ; 
 39 parameter LCD_EN_WIDTH_MIN = 16'd230  ; 
 40 parameter LCD_EN_HOLD_MIN  = 16'd230  ; 
 41 
 42 parameter LCD_EN_CYCLE_MIN = (LCD_EN_SETUP_MIN + LCD_EN_WIDTH_MIN + LCD_EN_HOLD_MIN)  ; 
 43 
 44 //INPUT  DECLARATION
 45 input                           clk          ; //LCD clock 
 46 input                           rst_n        ; //LCD clock reset (0: reset)
 47 input                           write        ; //LCD write enable(1: enable), only one clock pulse
 48 input                           read         ; //LCD read  enable(1: enable), only one clock pulse
 49 input                           reg_sel      ; //LCD DATA SEL: 0-COMMAND | 1-DATA; 
 50 input   [7:0]                   wdata        ; //LCD write data
 51 input   [7:0]                   lcd_db_in    ; //LCD INTF SIGNAL
 52 
 53 //OUTPUT DECLARATION
 54 output  [7:0]                   rdata        ; //LCD READ data
 55 output                          ready        ; //LCD ACCESS Ready
 56 output                          lcd_rs       ; //LCD INTF SIGNAL
 57 output                          lcd_rw       ; //LCD INTF SIGNAL
 58 output                          lcd_en       ; //LCD INTF SIGNAL
 59 output  [7:0]                   lcd_db_out   ; //LCD INTF SIGNAL
 60 output                          lcd_db_oen   ; //LCD INTF SIGNAL
 61 
 62 //--========================MODULE SOURCE CODE==========================--
 63 reg     [15:0]                  lcd_timing_cnt  ;
 64 wire                            lcd_wr_cmd      ;
 65 wire                            lcd_cmd_idle    ;
 66 reg                             lcd_rs          ;
 67 reg                             lcd_rw          ;
 68 reg                             lcd_db_oen      ;
 69 reg                             lcd_en          ;
 70 reg     [7:0]                   lcd_db_out      ;
 71 reg     [7:0]                   rdata           ;
 72 
 73 //--=========================================--
 74 // LCD TIMING COUNT :
 75 // Initial Value LCD_EN_CYCLE_MIN ; It count 
 76 // from 0 to LCD_EN_CYCLE_MIN when one access.
 77 //--=========================================--
 78 assign lcd_wr_cmd   = (write | read); 
 79 assign lcd_cmd_idle = (lcd_timing_cnt >= LCD_EN_CYCLE_MIN) ;
 80 
 81 always @(posedge clk or negedge rst_n)
 82 begin
 83     if(rst_n == 1'b0)
 84         lcd_timing_cnt <= LCD_EN_CYCLE_MIN ;
 85     else if (lcd_wr_cmd & lcd_cmd_idle)
 86         lcd_timing_cnt <= 16'b0 ;
 87     else if (lcd_timing_cnt < LCD_EN_CYCLE_MIN)    
 88         lcd_timing_cnt <= lcd_timing_cnt + 16'b1 ;       
 89 end
 90 
 91 //--=========================================--
 92 // LCD INTERFACE SIGNAL :
 93 // RS   : 0-COMMAND | 1-DATA; 
 94 // RW   : 0-WRITE   | 1-READ; 
 95 // E    : 0-Disable | 1-ENABLE;
 96 //--=========================================--
 97 always @(posedge clk or negedge rst_n)
 98 begin
 99     if(rst_n == 1'b0)
100         lcd_rs <= 1'b0 ;  
101     else if (lcd_wr_cmd & lcd_cmd_idle)
102         lcd_rs <= reg_sel ;           
103 end
104 
105 always @(posedge clk or negedge rst_n)
106 begin
107     if(rst_n == 1'b0) 
108     begin
109         lcd_rw     <= 1'b0 ; 
110         lcd_db_oen <= 1'b1 ;    
111     end        
112     else if (write  & lcd_cmd_idle)
113     begin
114         lcd_rw     <= 1'b0 ; 
115         lcd_db_oen <= 1'b0 ;    
116     end          
117     else if (read  & lcd_cmd_idle)
118     begin
119         lcd_rw     <= 1'b1 ; 
120         lcd_db_oen <= 1'b1 ;    
121     end                 
122 end
123 
124 always @(posedge clk or negedge rst_n)
125 begin
126     if(rst_n == 1'b0)
127         lcd_en <= 1'b0 ;  
128     else if (lcd_timing_cnt <= LCD_EN_SETUP_MIN)
129         lcd_en <= 1'b0 ;  
130     else if (lcd_timing_cnt >= LCD_EN_SETUP_MIN + LCD_EN_WIDTH_MIN)
131         lcd_en <= 1'b0 ;          
132     else
133         lcd_en <= 1'b1 ;            
134 end
135 
136 //--=========================================--
137 // lcd_db_out :
138 // Update wdata when write enbale and keep it 
139 // till en cycle end.
140 //--=========================================--
141 always @(posedge clk or negedge rst_n)
142 begin
143     if(rst_n == 1'b0)
144         lcd_db_out <= 8'b0 ;
145     else if (write  & lcd_cmd_idle)
146         lcd_db_out <= wdata;   
147     else if (lcd_timing_cnt >= LCD_EN_CYCLE_MIN)
148         lcd_db_out <= 8'b0 ;               
149 end
150 
151 //--=========================================--
152 // rdata :
153 // Update rdata when lcd en cycle end.
154 //--=========================================--
155 always @(posedge clk or negedge rst_n)
156 begin
157     if(rst_n == 1'b0)
158         rdata <= 8'h0 ;
159     else if (read  & lcd_cmd_idle) //Specify an Error Code here.
160         rdata <= 8'hFF;   
161     else if (lcd_timing_cnt >= LCD_EN_CYCLE_MIN)
162         rdata <= lcd_db_in ;               
163 end
164 
165 endmodule
166 
167