Aktuální adresář: FITkit /
trunk /
fpga /
ctrls /
lcd /
lcd_ctrl_high.vhd
1 -- keyboard.vhd: Keyboard simulation file
2 -- Author(s): Tomas Martinek <martinto at fit.vutbr.cz>
3 --
4 library ieee;
5 use ieee.std_logic_1164.all;
6 use ieee.std_logic_arith.all;
7 use ieee.std_logic_unsigned.all;
8 use ieee.numeric_std.all;
9
10 -- ----------------------------------------------------------------------------
11 -- Entity declaration
12 -- ----------------------------------------------------------------------------
13 entity lcd_ctrl_high is
14 port(
15 CLK : in std_logic;
16 RESET : in std_logic;
17
18 -- user interface
19 DATA : in std_logic_vector(7 downto 0);
20 WRITE : in std_logic;
21 CLEAR : in std_logic;
22
23 -- lcd interface
24 LRS : out std_logic;
25 LRW : out std_logic;
26 LE : out std_logic;
27 LD : inout std_logic_vector(7 downto 0)
28 );
29 end entity lcd_ctrl_high;
30
31 -- ----------------------------------------------------------------------------
32 -- Architecture declaration
33 -- ----------------------------------------------------------------------------
34 architecture behavioral of lcd_ctrl_high is
35
36 constant ITEMS : integer := 32;
37 type t_fifo is array(9 downto 0) of std_logic_vector(ITEMS-1 downto 0);
38 type t_state is (INIT, CLEAR_DISPLAY, CLEAR_CURSOR, SET_FUNCTION,
39 CURSOR_OFF, SET_CURSOR_DIR, WAIT_FOR_REQ, WRITE_ADDR,
40 WRITE_DATA);
41
42 signal cnt_addr : std_logic_vector(3 downto 0);
43 signal cnt_addr_ce : std_logic;
44 signal cnt_addr_ld : std_logic;
45 signal lcd_busy : std_logic;
46 signal change_addr : std_logic;
47 signal write_req : std_logic;
48 signal clear_req : std_logic;
49
50 signal present_state, next_state : t_state;
51 signal fsm_cnt_ce : std_logic;
52 signal fsm_cnt_clr : std_logic;
53 signal fsm_lcd_rs : std_logic;
54 signal fsm_fifo_rd : std_logic;
55 signal fsm_lcd_write : std_logic;
56 signal fsm_lcd_data : std_logic_vector(7 downto 0);
57 signal mx_lcd_addr : std_logic_vector(7 downto 0);
58 signal lcd_data : std_logic_vector(7 downto 0);
59 signal busy : std_logic;
60
61 signal fifo : t_fifo;
62 signal fifo_din : std_logic_vector(9 downto 0);
63 signal fifo_dout : std_logic_vector(9 downto 0);
64 signal fifo_rd : std_logic;
65 signal fifo_wr : std_logic;
66 signal fifo_empty : std_logic;
67 signal fifo_full : std_logic;
68 signal cnt_fifo_addr : std_logic_vector(4 downto 0);
69 signal cnt_fifo_count : std_logic_vector(5 downto 0);
70 signal cnt_fifo_addr_ce : std_logic;
71 signal cnt_fifo_addr_updw : std_logic;
72
73 begin
74
75 -- cnt_addr counter
76 cnt_addr_ld <= fsm_cnt_clr;
77 cnt_addr_ce <= fsm_cnt_ce or fsm_cnt_clr;
78 process(RESET, CLK)
79 begin
80 if (RESET = '1') then
81 cnt_addr <= (others => '0');
82 elsif (CLK'event AND CLK = '1') then
83 if (cnt_addr_ce = '1') then
84 if (cnt_addr_ld = '1') then
85 cnt_addr <= (others => '0');
86 else
87 cnt_addr <= cnt_addr + 1;
88 end if;
89 end if;
90 end if;
91 end process;
92
93 change_addr <= '1' when (cnt_addr(2 downto 0)="000") else '0';
94 mx_lcd_addr <= X"80" when (cnt_addr(3) = '0') else X"C0";
95
96 -- ------------------------------------------------------------------
97 -- FIFO Block
98 -- ------------------------------------------------------------------
99 fifo_din <= CLEAR & WRITE & DATA;
100 fifo_wr <= WRITE or CLEAR;
101 fifo_rd <= fsm_fifo_rd;
102
103 cnt_fifo_addr_ce <= (fifo_wr and (not fifo_rd)) or (fifo_rd and (not fifo_wr));
104 cnt_fifo_addr_updw <= fifo_rd;
105
106 -- cnt_fifo_addr counter
107 process(RESET, CLK)
108 begin
109 if (RESET = '1') then
110 cnt_fifo_addr <= (others => '1');
111 cnt_fifo_count <= (others => '0');
112 elsif (CLK'event AND CLK = '1') then
113 if (cnt_fifo_addr_ce = '1') then
114 if (cnt_fifo_addr_updw = '1') then
115 cnt_fifo_addr <= cnt_fifo_addr - 1;
116 cnt_fifo_count <= cnt_fifo_count - 1;
117 else
118 cnt_fifo_addr <= cnt_fifo_addr + 1;
119 cnt_fifo_count <= cnt_fifo_count + 1;
120 end if;
121 end if;
122 end if;
123 end process;
124
125 -- full/empty flag setting
126 fifo_full <= '1' when (cnt_fifo_count = conv_std_logic_vector(ITEMS,
127 cnt_fifo_count'length)) else '0';
128 fifo_empty <= '1' when (cnt_fifo_count = conv_std_logic_vector(0,
129 cnt_fifo_count'length)) else '0';
130
131 -- fifo memory
132 FIFO_U : for i in 0 to 9 generate
133 process(CLK)
134 begin
135 if (CLK'event and CLK='1') then
136 if (fifo_wr='1') then
137 fifo(i) <= fifo(i)(ITEMS-2 downto 0) & fifo_din(i);
138 end if;
139 end if;
140 end process;
141 fifo_dout(i) <= fifo(i)(conv_integer(cnt_fifo_addr));
142 end generate;
143
144 lcd_data <= fifo_dout(7 downto 0);
145 write_req <= fifo_dout(8);
146 clear_req <= fifo_dout(9);
147
148 -- ------------------------------------------------------------------
149 -- LCD controller
150 -- ------------------------------------------------------------------
151 lcd_u : entity work.lcd_ctrl_rw
152 port map (
153 RESET => RESET,
154 CLK => CLK,
155
156 -- interni rozhrani
157 READ => '0',
158 WRITE => fsm_lcd_write,
159 RS => fsm_lcd_rs,
160 DIN => fsm_lcd_data,
161 DOUT => open,
162 DV => open,
163 BUSY => busy,
164
165 --- rozhrani LCD displeje
166 LRS => LRS,
167 LRW => LRW,
168 LE => LE,
169 LD => LD
170 );
171
172 lcd_busy <= busy;
173 -- ------------------------------------------------------------------
174 -- Finite State Machine
175 -- ------------------------------------------------------------------
176
177 -- -------------------------------------------------------
178 sync_logic : process(RESET, CLK)
179 begin
180 if (RESET = '1') then
181 present_state <= INIT;
182 elsif (CLK'event AND CLK = '1') then
183 present_state <= next_state;
184 end if;
185 end process sync_logic;
186
187 -- -------------------------------------------------------
188 next_state_logic : process(present_state, lcd_busy, change_addr, write_req,
189 clear_req, fifo_empty)
190 begin
191 case (present_state) is
192 -- - - - - - - - - - - - - - - - - - - - - - -
193 when INIT =>
194 next_state <= CLEAR_CURSOR;
195 -- - - - - - - - - - - - - - - - - - - - - - -
196 when CLEAR_CURSOR =>
197 next_state <= CLEAR_CURSOR;
198 if (lcd_busy = '0') then
199 next_state <= SET_FUNCTION;
200 end if;
201 -- - - - - - - - - - - - - - - - - - - - - - -
202 when SET_FUNCTION =>
203 next_state <= SET_FUNCTION;
204 if (lcd_busy = '0') then
205 next_state <= CURSOR_OFF;
206 end if;
207 -- - - - - - - - - - - - - - - - - - - - - - -
208 when CURSOR_OFF =>
209 next_state <= CURSOR_OFF;
210 if (lcd_busy = '0') then
211 next_state <= SET_CURSOR_DIR;
212 end if;
213 -- - - - - - - - - - - - - - - - - - - - - - -
214 when SET_CURSOR_DIR =>
215 next_state <= SET_CURSOR_DIR;
216 if (lcd_busy = '0') then
217 next_state <= CLEAR_DISPLAY;
218 end if;
219 -- - - - - - - - - - - - - - - - - - - - - - -
220 when CLEAR_DISPLAY =>
221 next_state <= CLEAR_DISPLAY;
222 if (lcd_busy = '0') then
223 next_state <= WAIT_FOR_REQ;
224 end if;
225 -- - - - - - - - - - - - - - - - - - - - - - -
226 when WAIT_FOR_REQ =>
227 next_state <= WAIT_FOR_REQ;
228 if (fifo_empty = '0') then
229 if (write_req = '1') then
230 if (change_addr = '1') then
231 next_state <= WRITE_ADDR;
232 else
233 next_state <= WRITE_DATA;
234 end if;
235 elsif (clear_req = '1') then
236 next_state <= CLEAR_DISPLAY;
237 end if;
238 end if;
239 -- - - - - - - - - - - - - - - - - - - - - - -
240 when WRITE_ADDR =>
241 next_state <= WRITE_ADDR;
242 if (lcd_busy = '0') then
243 next_state <= WRITE_DATA;
244 end if;
245 -- - - - - - - - - - - - - - - - - - - - - - -
246 when WRITE_DATA =>
247 next_state <= WRITE_DATA;
248 if (lcd_busy = '0') then
249 next_state <= WAIT_FOR_REQ;
250 end if;
251 -- - - - - - - - - - - - - - - - - - - - - - -
252 when others =>
253 end case;
254 end process next_state_logic;
255
256 -- -------------------------------------------------------
257 output_logic : process(present_state, lcd_busy, lcd_data,
258 mx_lcd_addr, fifo_empty, clear_req)
259 begin
260 fsm_cnt_ce <= '0';
261 fsm_cnt_clr <= '0';
262 fsm_lcd_rs <= '0';
263 fsm_lcd_write <= '0';
264 fsm_fifo_rd <= '0';
265 fsm_lcd_data <= (others => '0');
266
267 case (present_state) is
268 -- - - - - - - - - - - - - - - - - - - - - - -
269 when INIT =>
270 -- - - - - - - - - - - - - - - - - - - - - - -
271 when CLEAR_CURSOR =>
272 if (lcd_busy = '0') then
273 fsm_lcd_write <= '1';
274 fsm_lcd_data <= X"02";
275 end if;
276 -- - - - - - - - - - - - - - - - - - - - - - -
277 when SET_FUNCTION =>
278 if (lcd_busy = '0') then
279 fsm_lcd_write <= '1';
280 fsm_lcd_data <= X"38";
281 end if;
282 -- - - - - - - - - - - - - - - - - - - - - - -
283 when CURSOR_OFF =>
284 if (lcd_busy = '0') then
285 fsm_lcd_write <= '1';
286 fsm_lcd_data <= X"0C";
287 end if;
288 -- - - - - - - - - - - - - - - - - - - - - - -
289 when SET_CURSOR_DIR =>
290 if (lcd_busy = '0') then
291 fsm_lcd_write <= '1';
292 fsm_lcd_data <= X"06";
293 end if;
294 -- - - - - - - - - - - - - - - - - - - - - - -
295 when CLEAR_DISPLAY =>
296 if (lcd_busy = '0') then
297 fsm_lcd_write <= '1';
298 fsm_lcd_data <= X"01";
299 fsm_cnt_clr <= '1';
300 end if;
301 -- - - - - - - - - - - - - - - - - - - - - - -
302 when WAIT_FOR_REQ =>
303 if (fifo_empty = '0' and clear_req = '1') then
304 fsm_fifo_rd <= '1';
305 end if;
306 -- - - - - - - - - - - - - - - - - - - - - - -
307 when WRITE_ADDR =>
308 if (lcd_busy = '0') then
309 fsm_lcd_write <= '1';
310 fsm_lcd_data <= mx_lcd_addr;
311 end if;
312 -- - - - - - - - - - - - - - - - - - - - - - -
313 when WRITE_DATA =>
314 if (lcd_busy = '0') then
315 fsm_lcd_write <= '1';
316 fsm_cnt_ce <= '1';
317 fsm_lcd_rs <= '1';
318 fsm_fifo_rd <= '1';
319 fsm_lcd_data <= lcd_data;
320 end if;
321 -- - - - - - - - - - - - - - - - - - - - - - -
322 when others =>
323 end case;
324 end process output_logic;
325
326 end architecture behavioral;
327
328