OpenCores
URL https://opencores.org/ocsvn/16x2_lcd_controller/16x2_lcd_controller/trunk

Subversion Repositories 16x2_lcd_controller

[/] [16x2_lcd_controller/] [trunk/] [lcd16x2_ctrl.vhd] - Blame information for rev 10

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 stachelsau
-------------------------------------------------------------------------------
2
-- Title      : 16x2 LCD controller
3
-- Project    : 
4
-------------------------------------------------------------------------------
5
-- File       : lcd16x2_ctrl.vhd
6
-- Author     :   <stachelsau@T420>
7
-- Company    : 
8
-- Created    : 2012-07-28
9 10 stachelsau
-- Last update: 2012-11-28
10 7 stachelsau
-- Platform   : 
11
-- Standard   : VHDL'93/02
12
-------------------------------------------------------------------------------
13
-- Description: The controller initializes the display when rst goes to '0'.
14
--              After that it writes the contend of the input signals
15
--              line1_buffer and line2_buffer continously to the display.
16
-------------------------------------------------------------------------------
17
-- Copyright (c) 2012 
18
-------------------------------------------------------------------------------
19
-- Revisions  :
20
-- Date        Version  Author  Description
21
-- 2012-07-28  1.0      stachelsau      Created
22
-------------------------------------------------------------------------------
23
 
24
library ieee;
25
use ieee.std_logic_1164.all;
26
 
27
entity lcd16x2_ctrl is
28
 
29
  generic (
30
    CLK_PERIOD_NS : positive := 20);    -- 50MHz
31
 
32
  port (
33
    clk          : in  std_logic;
34
    rst          : in  std_logic;
35
    lcd_e        : out std_logic;
36
    lcd_rs       : out std_logic;
37
    lcd_rw       : out std_logic;
38
    lcd_db       : out std_logic_vector(7 downto 4);
39
    line1_buffer : in  std_logic_vector(127 downto 0);  -- 16x8bit
40
    line2_buffer : in  std_logic_vector(127 downto 0));
41
 
42
end entity lcd16x2_ctrl;
43
 
44
architecture rtl of lcd16x2_ctrl is
45
 
46
  constant DELAY_15_MS   : positive := 15 * 10**6 / CLK_PERIOD_NS + 1;
47
  constant DELAY_1640_US : positive := 1640 * 10**3 / CLK_PERIOD_NS + 1;
48
  constant DELAY_4100_US : positive := 4100 * 10**3 / CLK_PERIOD_NS + 1;
49
  constant DELAY_100_US  : positive := 100 * 10**3 / CLK_PERIOD_NS + 1;
50
  constant DELAY_40_US   : positive := 40 * 10**3 / CLK_PERIOD_NS + 1;
51
 
52
  constant DELAY_NIBBLE     : positive := 10**3 / CLK_PERIOD_NS + 1;
53
  constant DELAY_LCD_E      : positive := 230 / CLK_PERIOD_NS + 1;
54
  constant DELAY_SETUP_HOLD : positive := 40 / CLK_PERIOD_NS + 1;
55
 
56
  constant MAX_DELAY : positive := DELAY_15_MS;
57
 
58
  -- this record describes one write operation
59
  type op_t is record
60
    rs      : std_logic;
61
    data    : std_logic_vector(7 downto 0);
62
    delay_h : integer range 0 to MAX_DELAY;
63
    delay_l : integer range 0 to MAX_DELAY;
64
  end record op_t;
65 10 stachelsau
  constant default_op      : op_t := (rs => '1', data => X"00", delay_h => DELAY_NIBBLE, delay_l => DELAY_40_US);
66 7 stachelsau
  constant op_select_line1 : op_t := (rs => '0', data => X"80", delay_h => DELAY_NIBBLE, delay_l => DELAY_40_US);
67
  constant op_select_line2 : op_t := (rs => '0', data => X"C0", delay_h => DELAY_NIBBLE, delay_l => DELAY_40_US);
68
 
69
  -- init + config operations:
70
  -- write 3 x 0x3 followed by 0x2
71
  -- function set command
72
  -- entry mode set command
73
  -- display on/off command
74
  -- clear display
75
  type config_ops_t is array(0 to 5) of op_t;
76
  constant config_ops : config_ops_t
77
    := (5 => (rs => '0', data => X"33", delay_h => DELAY_4100_US, delay_l => DELAY_100_US),
78
        4 => (rs => '0', data => X"32", delay_h => DELAY_40_US, delay_l => DELAY_40_US),
79
        3 => (rs => '0', data => X"28", delay_h => DELAY_NIBBLE, delay_l => DELAY_40_US),
80
        2 => (rs => '0', data => X"06", delay_h => DELAY_NIBBLE, delay_l => DELAY_40_US),
81
        1 => (rs => '0', data => X"0C", delay_h => DELAY_NIBBLE, delay_l => DELAY_40_US),
82
 
83
 
84
  signal this_op : op_t;
85
 
86
  type op_state_t is (IDLE,
87
                      WAIT_SETUP_H,
88
                      ENABLE_H,
89
                      WAIT_HOLD_H,
90
                      WAIT_DELAY_H,
91
                      WAIT_SETUP_L,
92
                      ENABLE_L,
93
                      WAIT_HOLD_L,
94
                      WAIT_DELAY_L,
95
                      DONE);
96
 
97
  signal op_state      : op_state_t := DONE;
98
  signal next_op_state : op_state_t;
99
  signal cnt           : natural range 0 to MAX_DELAY;
100
  signal next_cnt      : natural range 0 to MAX_DELAY;
101
 
102
  type state_t is (RESET,
103
                   CONFIG,
104
                   SELECT_LINE1,
105
                   WRITE_LINE1,
106
                   SELECT_LINE2,
107
                   WRITE_LINE2);
108
 
109
  signal state      : state_t               := RESET;
110
  signal next_state : state_t;
111
  signal ptr        : natural range 0 to 15 := 0;
112
  signal next_ptr   : natural range 0 to 15;
113
 
114
begin
115
 
116
  proc_state : process(state, op_state, ptr, line1_buffer, line2_buffer) is
117
  begin
118
    case state is
119
      when RESET =>
120 10 stachelsau
        this_op    <= default_op;
121 7 stachelsau
        next_state <= CONFIG;
122
        next_ptr   <= config_ops_t'high;
123
 
124
      when CONFIG =>
125
        this_op    <= config_ops(ptr);
126
        next_ptr   <= ptr;
127
        next_state <= CONFIG;
128
        if op_state = DONE then
129
          next_ptr <= ptr - 1;
130
          if ptr = 0 then
131
            next_state <= SELECT_LINE1;
132
          end if;
133
        end if;
134
 
135
      when SELECT_LINE1 =>
136
        this_op  <= op_select_line1;
137
        next_ptr <= 15;
138
        if op_state = DONE then
139
          next_state <= WRITE_LINE1;
140
        else
141
          next_state <= SELECT_LINE1;
142
        end if;
143
 
144
      when WRITE_LINE1 =>
145 10 stachelsau
        this_op      <= default_op;
146 7 stachelsau
        this_op.data <= line1_buffer(ptr*8 + 7 downto ptr*8);
147
        next_ptr     <= ptr;
148
        next_state   <= WRITE_LINE1;
149
        if op_state = DONE then
150
          next_ptr <= ptr - 1;
151
          if ptr = 0 then
152
            next_state <= SELECT_LINE2;
153
          end if;
154
        end if;
155
 
156
      when SELECT_LINE2 =>
157
        this_op  <= op_select_line2;
158
        next_ptr <= 15;
159
        if op_state = DONE then
160
          next_state <= WRITE_LINE2;
161
        else
162
          next_state <= SELECT_LINE2;
163
        end if;
164
 
165
      when WRITE_LINE2 =>
166 10 stachelsau
        this_op      <= default_op;
167 7 stachelsau
        this_op.data <= line2_buffer(ptr*8 + 7 downto ptr*8);
168
        next_ptr     <= ptr;
169
        next_state   <= WRITE_LINE2;
170
        if op_state = DONE then
171
          next_ptr <= ptr - 1;
172
          if ptr = 0 then
173
            next_state <= SELECT_LINE1;
174
          end if;
175
        end if;
176
 
177
    end case;
178
  end process proc_state;
179
 
180
  reg_state : process(clk)
181
  begin
182
    if rising_edge(clk) then
183
      if rst = '1' then
184
        state <= RESET;
185
        ptr   <= 0;
186
      else
187
        state <= next_state;
188
        ptr   <= next_ptr;
189
      end if;
190
    end if;
191
  end process reg_state;
192
 
193
  -- we never read from the lcd
194
  lcd_rw <= '0';
195
 
196
  proc_op_state : process(op_state, cnt, this_op) is
197
  begin
198
    case op_state is
199
      when IDLE =>
200
        lcd_db        <= (others => '0');
201
        lcd_rs        <= '0';
202
        lcd_e         <= '0';
203
        next_op_state <= WAIT_SETUP_H;
204
        next_cnt      <= DELAY_SETUP_HOLD;
205
 
206
      when WAIT_SETUP_H =>
207
        lcd_db <= this_op.data(7 downto 4);
208
        lcd_rs <= this_op.rs;
209
        lcd_e  <= '0';
210
        if cnt = 0 then
211
          next_op_state <= ENABLE_H;
212
          next_cnt      <= DELAY_LCD_E;
213
        else
214
          next_op_state <= WAIT_SETUP_H;
215
          next_cnt      <= cnt - 1;
216
        end if;
217
 
218
      when ENABLE_H =>
219
        lcd_db <= this_op.data(7 downto 4);
220
        lcd_rs <= this_op.rs;
221
        lcd_e  <= '1';
222
        if cnt = 0 then
223
          next_op_state <= WAIT_HOLD_H;
224
          next_cnt      <= DELAY_SETUP_HOLD;
225
        else
226
          next_op_state <= ENABLE_H;
227
          next_cnt      <= cnt - 1;
228
        end if;
229
 
230
      when WAIT_HOLD_H =>
231
        lcd_db <= this_op.data(7 downto 4);
232
        lcd_rs <= this_op.rs;
233
        lcd_e  <= '0';
234
        if cnt = 0 then
235
          next_op_state <= WAIT_DELAY_H;
236
          next_cnt      <= this_op.delay_h;
237
        else
238
          next_op_state <= WAIT_HOLD_H;
239
          next_cnt      <= cnt - 1;
240
        end if;
241
 
242
      when WAIT_DELAY_H =>
243
        lcd_db <= (others => '0');
244
        lcd_rs <= '0';
245
        lcd_e  <= '0';
246
        if cnt = 0 then
247
          next_op_state <= WAIT_SETUP_L;
248
          next_cnt      <= DELAY_SETUP_HOLD;
249
        else
250
          next_op_state <= WAIT_DELAY_H;
251
          next_cnt      <= cnt - 1;
252
        end if;
253
 
254
      when WAIT_SETUP_L =>
255
        lcd_db <= this_op.data(3 downto 0);
256
        lcd_rs <= this_op.rs;
257
        lcd_e  <= '0';
258
        if cnt = 0 then
259
          next_op_state <= ENABLE_L;
260
          next_cnt      <= DELAY_LCD_E;
261
        else
262
          next_op_state <= WAIT_SETUP_L;
263
          next_cnt      <= cnt - 1;
264
        end if;
265
 
266
      when ENABLE_L =>
267
        lcd_db <= this_op.data(3 downto 0);
268
        lcd_rs <= this_op.rs;
269
        lcd_e  <= '1';
270
        if cnt = 0 then
271
          next_op_state <= WAIT_HOLD_L;
272
          next_cnt      <= DELAY_SETUP_HOLD;
273
        else
274
          next_op_state <= ENABLE_L;
275
          next_cnt      <= cnt - 1;
276
        end if;
277
 
278
      when WAIT_HOLD_L =>
279
        lcd_db <= this_op.data(3 downto 0);
280
        lcd_rs <= this_op.rs;
281
        lcd_e  <= '0';
282
        if cnt = 0 then
283
          next_op_state <= WAIT_DELAY_L;
284
          next_cnt      <= this_op.delay_l;
285
        else
286
          next_op_state <= WAIT_HOLD_L;
287
          next_cnt      <= cnt - 1;
288
        end if;
289
 
290
      when WAIT_DELAY_L =>
291
        lcd_db <= (others => '0');
292
        lcd_rs <= '0';
293
        lcd_e  <= '0';
294
        if cnt = 0 then
295
          next_op_state <= DONE;
296
          next_cnt      <= 0;
297
        else
298
          next_op_state <= WAIT_DELAY_L;
299
          next_cnt      <= cnt - 1;
300
        end if;
301
 
302
      when DONE =>
303
        lcd_db        <= (others => '0');
304
        lcd_rs        <= '0';
305
        lcd_e         <= '0';
306
        next_op_state <= IDLE;
307
        next_cnt      <= 0;
308
 
309
    end case;
310
  end process proc_op_state;
311
 
312
  reg_op_state : process (clk) is
313
  begin
314
    if rising_edge(clk) then
315
      if state = RESET then
316
        op_state <= IDLE;
317
      else
318
        op_state <= next_op_state;
319
        cnt      <= next_cnt;
320
      end if;
321
    end if;
322
  end process reg_op_state;
323
 
324
 
325
end architecture rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.