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