1 | --------------------------------------------------------------------------------
|
2 | --
|
3 | -- FileName: lcd_controller.vhd
|
4 | -- Dependencies: none
|
5 | -- Design Software: Quartus II 32-bit Version 11.1 Build 173 SJ Full Version
|
6 | --
|
7 | -- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
|
8 | -- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
9 | -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
10 | -- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
|
11 | -- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
|
12 | -- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
|
13 | -- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
|
14 | -- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
|
15 | -- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
|
16 | --
|
17 | -- Version History
|
18 | -- Version 1.0 6/2/2006 Scott Larson
|
19 | -- Initial Public Release
|
20 | -- Version 2.0 6/13/2012 Scott Larson
|
21 | --
|
22 | -- CLOCK FREQUENCY: to change system clock frequency, change Line 65
|
23 | --
|
24 | -- LCD INITIALIZATION SETTINGS: to change, comment/uncomment lines:
|
25 | --
|
26 | -- Function Set
|
27 | -- 2-line mode, display on Line 93 lcd_data <= "00111100";
|
28 | -- 1-line mode, display on Line 94 lcd_data <= "00110100";
|
29 | -- 1-line mode, display off Line 95 lcd_data <= "00110000";
|
30 | -- 2-line mode, display off Line 96 lcd_data <= "00111000";
|
31 | -- Display ON/OFF
|
32 | -- display on, cursor off, blink off Line 104 lcd_data <= "00001100";
|
33 | -- display on, cursor off, blink on Line 105 lcd_data <= "00001101";
|
34 | -- display on, cursor on, blink off Line 106 lcd_data <= "00001110";
|
35 | -- display on, cursor on, blink on Line 107 lcd_data <= "00001111";
|
36 | -- display off, cursor off, blink off Line 108 lcd_data <= "00001000";
|
37 | -- display off, cursor off, blink on Line 109 lcd_data <= "00001001";
|
38 | -- display off, cursor on, blink off Line 110 lcd_data <= "00001010";
|
39 | -- display off, cursor on, blink on Line 111 lcd_data <= "00001011";
|
40 | -- Entry Mode Set
|
41 | -- increment mode, entire shift off Line 127 lcd_data <= "00000110";
|
42 | -- increment mode, entire shift on Line 128 lcd_data <= "00000111";
|
43 | -- decrement mode, entire shift off Line 129 lcd_data <= "00000100";
|
44 | -- decrement mode, entire shift on Line 130 lcd_data <= "00000101";
|
45 | --
|
46 | --------------------------------------------------------------------------------
|
47 |
|
48 | LIBRARY ieee;
|
49 | USE ieee.std_logic_1164.ALL;
|
50 |
|
51 | ENTITY lcd_controller IS
|
52 | PORT(
|
53 | clk : IN STD_LOGIC; --system clock
|
54 | reset_n : IN STD_LOGIC; --active low reinitializes lcd
|
55 | lcd_enable : IN STD_LOGIC; --latches data into lcd controller
|
56 | lcd_bus : IN STD_LOGIC_VECTOR(9 DOWNTO 0); --data and control signals
|
57 | busy : OUT STD_LOGIC := '1'; --lcd controller busy/idle feedback
|
58 | rw, rs, e : OUT STD_LOGIC; --read/write, setup/data, and enable for lcd
|
59 | lcd_data : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --data signals for lcd
|
60 | mr_debug : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
|
61 | );
|
62 | END lcd_controller;
|
63 |
|
64 | ARCHITECTURE controller OF lcd_controller IS
|
65 | TYPE CONTROL IS(power_up, initialize, ready, send);
|
66 | SIGNAL state : CONTROL;
|
67 | CONSTANT freq : INTEGER := 50; --system clock frequency in MHz
|
68 | BEGIN
|
69 | PROCESS(clk)
|
70 | VARIABLE clk_count : INTEGER := 0; --event counter for timing
|
71 | BEGIN
|
72 | IF(clk'EVENT and clk = '1') THEN
|
73 |
|
74 | CASE state IS
|
75 |
|
76 | --wait 50 ms to ensure Vdd has risen and required LCD wait is met
|
77 | WHEN power_up =>
|
78 | busy <= '1';
|
79 | IF(clk_count < (5 * freq)) THEN --wait 50 ms (50000 * freq))
|
80 | clk_count := clk_count + 1;
|
81 | state <= power_up;
|
82 | lcd_data <= "00000001";
|
83 | ELSE --power-up complete
|
84 | clk_count := 0;
|
85 | rs <= '0';
|
86 | rw <= '0';
|
87 | lcd_data <= "00110000";
|
88 | state <= initialize;
|
89 | END IF;
|
90 |
|
91 | --cycle through initialization sequence
|
92 | WHEN initialize =>
|
93 | busy <= '1';
|
94 | clk_count := clk_count + 1;
|
95 | IF(clk_count < (10 * freq)) THEN --function set
|
96 | lcd_data <= "00111100"; --2-line mode, display on
|
97 | --lcd_data <= "00110100"; --1-line mode, display on
|
98 | --lcd_data <= "00110000"; --1-line mdoe, display off
|
99 | --lcd_data <= "00111000"; --2-line mode, display off
|
100 | e <= '1';
|
101 | state <= initialize;
|
102 | ELSIF(clk_count < (1 * freq)) THEN --wait 50 us (60 * freq))
|
103 | lcd_data <= "00000000";
|
104 | e <= '0';
|
105 | state <= initialize;
|
106 | ELSIF(clk_count < (1 * freq)) THEN --display on/off control < (70 * freq))
|
107 | lcd_data <= "00001100"; --display on, cursor off, blink off
|
108 | --lcd_data <= "00001101"; --display on, cursor off, blink on
|
109 | --lcd_data <= "00001110"; --display on, cursor on, blink off
|
110 | --lcd_data <= "00001111"; --display on, cursor on, blink on
|
111 | --lcd_data <= "00001000"; --display off, cursor off, blink off
|
112 | --lcd_data <= "00001001"; --display off, cursor off, blink on
|
113 | --lcd_data <= "00001010"; --display off, cursor on, blink off
|
114 | --lcd_data <= "00001011"; --display off, cursor on, blink on
|
115 | e <= '1';
|
116 | state <= initialize;
|
117 | ELSIF(clk_count < (1 * freq)) THEN --wait 50 us (120 * freq))
|
118 | lcd_data <= "00000000";
|
119 | e <= '0';
|
120 | state <= initialize;
|
121 | ELSIF(clk_count < (1 * freq)) THEN --display clear (130 * freq))
|
122 | lcd_data <= "00000001";
|
123 | e <= '1';
|
124 | state <= initialize;
|
125 | ELSIF(clk_count < (1 * freq)) THEN --wait 2 ms (2130 * freq))
|
126 | lcd_data <= "00000000";
|
127 | e <= '0';
|
128 | state <= initialize;
|
129 | ELSIF(clk_count < (1 * freq)) THEN --entry mode set (2140 * freq))
|
130 | lcd_data <= "00000110"; --increment mode, entire shift off
|
131 | --lcd_data <= "00000111"; --increment mode, entire shift on
|
132 | --lcd_data <= "00000100"; --decrement mode, entire shift off
|
133 | --lcd_data <= "00000101"; --decrement mode, entire shift on
|
134 | e <= '1';
|
135 | state <= initialize;
|
136 | ELSIF(clk_count < (1 * freq)) THEN --wait 60 us (2200 * freq))
|
137 | lcd_data <= "00000000";
|
138 | e <= '0';
|
139 | state <= initialize;
|
140 | ELSE --initialization complete
|
141 | clk_count := 0;
|
142 | busy <= '0';
|
143 | state <= ready;
|
144 | END IF;
|
145 |
|
146 | --wait for the enable signal and then latch in the instruction
|
147 | WHEN ready =>
|
148 | IF(lcd_enable = '1') THEN
|
149 | busy <= '1';
|
150 | rs <= lcd_bus(9);
|
151 | rw <= lcd_bus(8);
|
152 | lcd_data <= lcd_bus(7 DOWNTO 0);
|
153 | clk_count := 0;
|
154 | state <= send;
|
155 | ELSE
|
156 | busy <= '0';
|
157 | rs <= '0';
|
158 | rw <= '0';
|
159 | lcd_data <= "00000000";
|
160 | clk_count := 0;
|
161 | state <= ready;
|
162 | END IF;
|
163 |
|
164 | --send instruction to lcd
|
165 | WHEN send =>
|
166 | busy <= '1';
|
167 | IF(clk_count < (50 * freq)) THEN --do not exit for 50us
|
168 | busy <= '1';
|
169 | IF(clk_count < freq) THEN --negative enable
|
170 | e <= '0';
|
171 | ELSIF(clk_count < (14 * freq)) THEN --positive enable half-cycle
|
172 | e <= '1';
|
173 | ELSIF(clk_count < (27 * freq)) THEN --negative enable half-cycle
|
174 | e <= '0';
|
175 | END IF;
|
176 | clk_count := clk_count + 1;
|
177 | state <= send;
|
178 | ELSE
|
179 | clk_count := 0;
|
180 | state <= ready;
|
181 | END IF;
|
182 |
|
183 | END CASE;
|
184 |
|
185 | --reset
|
186 | IF(reset_n = '0') THEN
|
187 | state <= power_up;
|
188 | END IF;
|
189 |
|
190 | --mr Debug
|
191 | IF (state = Power_up) THEN
|
192 | mr_debug <="0001";
|
193 | ELSIF (state = initialize) THEN
|
194 | mr_debug <="0010";
|
195 | ELSIF (state = ready) THEN
|
196 | mr_debug <="0100";
|
197 | ELSIF (state = send) THEN
|
198 | mr_debug <="1000";
|
199 | END IF;
|
200 |
|
201 | END IF;
|
202 | END PROCESS;
|
203 | END controller;
|