lcd_controller.vhd


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;