--------------------------------------------------------------- -- LCD driver -- EE 552 project -- Audio Processing Unit -- February, 2003 -- -- FILE NAME: lcd_driver.vhd -- -- DESCRIPTION: This module initializes the display and then -- waits for a character to be sent. Once the character -- is sent it is desplayed on the LCD, the cusor is then -- incremented, and then wait mode is re-entered. --------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library work; use work.interface.all; entity lcd_driver is generic(datawidth: positive:= 8); port( clock: in std_logic; -- slow clock. reset: in std_logic; -- system reset. message: in std_logic_vector (datawidth-1 downto 0); -- input from outside. lcd_select: out std_logic; -- lcd register select signal. input_ready : out std_logic; -- signal if ready for input. lcd_data: out std_logic_vector(datawidth-1 downto 0); -- output to LCD. lcd_rw: out std_logic; -- output to LCD. lcd_enable: out std_logic; -- output to LCD. enable: in std_logic; -- detect if there is any incoming message. finish: out std_logic -- indicate that the character has been recieved and printed. ); end lcd_driver; architecture Display of lcd_driver is type state_type is (initial, display, entry_mode, clear, address_set, waiting, print_char, home_cursor, carrage_return); SIGNAL state : state_type; -- Function set for 8-bit data transfer and 2-line display constant F_SET: std_logic_vector(datawidth-1 downto 0) := "00111000"; -- Set Entry Mode to increment cursor automatically after each character is displayed. constant EM_SET: std_logic_vector(datawidth-1 downto 0) := "00000110"; -- Display ON, 2 lines no cursor. constant D_ON: std_logic_vector(datawidth-1 downto 0) := "00001100"; -- Clear screen. constant CLR: std_logic_vector(datawidth-1 downto 0) := "00000001"; -- DD RAM address set. constant DDRAS: std_logic_vector(datawidth-1 downto 0) := "10000000"; -- Home cursor. constant HOME: std_logic_vector(datawidth-1 downto 0) := "00000010"; -- Carrage return. constant CR: std_logic_vector(datawidth-1 downto 0) := "11000000"; -- No operation command. constant NIL: std_logic_vector(datawidth-1 downto 0) := "00000000"; constant large_delay : integer := 500; constant delay : integer := 15; constant reg_setup: integer := 1; begin process(clock, reset) variable count: integer range 0 to large_delay; begin if reset = '0' then state <= initial; count := 0; elsif rising_edge(clock) then case state is when initial => input_ready <= '0'; finish <= '0'; if count = reg_setup then lcd_enable <= '1'; else lcd_enable <= '0'; end if; lcd_data <= F_SET; lcd_select <= '0'; lcd_rw <= '0'; if count = delay then state <= display; count := 0; else state <= initial; count := count + 1; end if; when display => input_ready <= '0'; finish <= '0'; if count = reg_setup then lcd_enable <= '1'; else lcd_enable <= '0'; end if; lcd_data <= D_ON; lcd_select <= '0'; lcd_rw <= '0'; if count = delay then state <= entry_mode; count := 0; else state <= display; count := count + 1; end if; when entry_mode => input_ready <= '0'; finish <= '0'; if count = reg_setup then lcd_enable <= '1'; else lcd_enable <= '0'; end if; lcd_data <= EM_SET; lcd_select <= '0'; lcd_rw <= '0'; if count = delay then state <= clear; count := 0; else state <= entry_mode; count := count + 1; end if; when clear => input_ready <= '0'; finish <= '0'; if count = reg_setup then lcd_enable <= '1'; else lcd_enable <= '0'; end if; lcd_data <= CLR; lcd_select <= '0'; lcd_rw <= '0'; if count = large_delay then state <= address_set; count := 0; else state <= clear; count := count + 1; end if; when home_cursor => input_ready <= '0'; if count = reg_setup then lcd_enable <= '1'; else lcd_enable <= '0'; end if; lcd_data <= HOME; lcd_select <= '0'; lcd_rw <= '0'; finish <= '0'; if count = large_delay then state <= address_set; count := 0; else state <= home_cursor; count := count + 1; end if; when address_set => input_ready <= '0'; if count = reg_setup then lcd_enable <= '1'; else lcd_enable <= '0'; end if; lcd_data <= DDRAS; lcd_select <= '0'; lcd_rw <= '0'; if count = delay then state <= waiting; count := 0; else state <= address_set; count := count + 1; end if; when carrage_return => input_ready <= '0'; finish <= '0'; if count = reg_setup then lcd_enable <= '1'; else lcd_enable <= '0'; end if; lcd_data <= CR; lcd_select <= '0'; lcd_rw <= '0'; if count = delay then state <= waiting; count := 0; else state <= carrage_return; count := count + 1; end if; when waiting => lcd_data <= NIL; lcd_select <= '0'; lcd_rw <= '0'; finish <= '0'; if enable = '1' then input_ready <= '0'; state <= print_char; else input_ready <= '1'; state <= waiting; end if; when print_char => input_ready <= '0'; case message(7 downto 0) is when "00000001" => state <= clear; finish <= '1'; when "00000010" => state <= carrage_return; finish <= '1'; when "00000011" => state <= home_cursor; finish <= '1'; when others => if count = reg_setup then lcd_enable <= '1'; finish <= '1'; else lcd_enable <= '0'; finish <= '0'; end if; lcd_data <= message; lcd_select <= '1'; lcd_rw <= '0'; if count = delay then state <= waiting; count := 0; else state <= print_char; count := count + 1; end if; end case; end case; end if; end process; end Display;