------------------------------------------------------------- -- LCD Driver -- Course : EE 552 -- Project : Wired CDMA -- Author : Jessamyn Smith -- Student ID : 0384675 -- Date : November 11, 2000 -- File Name : lcd.vhd -- Architecture : Behavioural -- Description : This module initializes the lcd and outputs -- the inputdata in a creative form. This is -- for demonstration purposes only; it is assumed -- that the user will modify the data input and -- displayed data to suit the project. ------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity lcd is generic ( asciiwidth : positive := 8); port ( clk : in std_logic; reset : in std_logic; -- active low data_valid : in std_logic; -- enables lcd to start new write cycle when high mode : in std_logic; -- data taken from input1 (if 0) or input2 (if 1) inputdata : in std_logic_vector(asciiwidth*2-1 downto 0); lcd_data : out std_logic_vector(asciiwidth-1 downto 0); lcd_select : out std_logic; -- selects data(0) or instruction(1) lcd_rw : out std_logic; -- read (1) or write (0) data lcd_enable : out std_logic; -- must be pulsed (at clock frequency done : out std_logic); -- set high during write cycle, low if ready for new data end lcd; -- results are unpredictable if data is changed when done is high architecture behavioural of lcd is constant countwidth : positive := 3; type state_type is (warmup, setfunc, dispoff, clear, setmode, home, idle, write); signal state : state_type; signal rw_int, enable_int : std_logic; signal count : std_logic_vector(countwidth downto 0); signal last_mode : std_logic; -- used to track rising edge on mode signal finished : std_logic; -- set high if done write cycle signal write_mode : std_logic; -- stores whether to enter write cycle after clearing display signal last_data_valid : std_logic; -- used to track rising edge on valid begin lcd_rw <= rw_int; lcd_enable <= enable_int; enable_int <= not clk; -- this is very important! if enable is not pulsed, lcd will not write state_set: process (clk, reset) begin if reset = '0' then count <= (others => '0'); write_mode <= '1'; last_mode <= mode; state <= setfunc; elsif (clk'event and clk = '1') then case state is when warmup => last_mode <= mode; lcd_select <= '0'; rw_int <= '0'; done <= '0'; -- stop controller from sending data lcd_data <= "00000000"; -- do nothing if count = "0111" then count <= (others => '0'); state <= setfunc; else count <= count + '1'; state <= warmup; end if; when setfunc => lcd_data <= "00110000"; if count = "1111" then state <= dispoff; else count <= count + '1'; state <= setfunc; end if; when dispoff => lcd_data <= "00001000"; count <= (others => '0'); state <= clear; when clear => lcd_data <= "00000001"; -- clear display if count = "0100" then state <= setmode; else count <= count + '1'; state <= clear; end if; when setmode => lcd_data <= "00000110"; count <= (others => '0'); state <= home; when home => lcd_data <= "00001111"; if count = "0100" then if write_mode = '0' then done <= '1'; state <= idle; else done <= '0'; count <= (others => '0'); finished <= '0'; state <= write; end if; else count <= count + '1'; state <= home; end if; when idle => if (last_mode /= mode) then last_mode <= mode; lcd_select <= '0'; rw_int <= '0'; done <= '0'; -- stop controller from sending data lcd_data <= "00000000"; -- do nothing count <= (others => '0'); write_mode <= '1'; state <= clear; elsif data_valid = '1' and last_data_valid = '0' then last_data_valid <= '1'; count <= (others => '0'); finished <= '0'; done <= '0'; write_mode <= '1'; state <= clear; else if data_valid = '0' then last_data_valid <= '0'; end if; lcd_data <= (others => '0'); done <= '1'; state <= idle; end if; when write => if finished = '1' then lcd_select <= '0'; write_mode <= '0'; state <= idle; else if mode = '0' then CASE count IS WHEN "0000" => lcd_data <= "01000101"; -- 'E' WHEN "0001" => lcd_data <= "01111000"; -- 'x' WHEN "0010" => lcd_data <= "01100001"; -- 'a' WHEN "0011" => lcd_data <= "01101101"; -- 'm' WHEN "0100" => lcd_data <= "01110000"; -- 'p' WHEN "0101" => lcd_data <= "01101100"; -- 'l' WHEN "0110" => lcd_data <= "01100101"; -- 'e' WHEN "0111" => lcd_data <= "00111010"; -- ':' WHEN "1001" => lcd_data <= inputdata(asciiwidth*2-1 downto asciiwidth); WHEN "1011" => lcd_data <= inputdata(asciiwidth-1 downto 0); WHEN "1111" => lcd_data <= "10100000"; -- ' ' finished <= '1'; -- needed to set done low before valid data is gone WHEN OTHERS => lcd_data <= "10100000"; -- ' ' END CASE; elsif mode = '1' then CASE count IS WHEN "0000" => lcd_data <= inputdata(asciiwidth*2-1 downto asciiwidth); WHEN "0010" => lcd_data <= inputdata(asciiwidth-1 downto 0); WHEN "0100" => lcd_data <= "01010100"; -- 'T' WHEN "0101" => lcd_data <= "01100101"; -- 'e' WHEN "0110" => lcd_data <= "01110011"; -- 's' WHEN "0111" => lcd_data <= "01110100"; -- 't' WHEN "1000" => lcd_data <= "01101001"; -- 'i' WHEN "1001" => lcd_data <= "01101110"; -- 'n' WHEN "1010" => lcd_data <= "01100111"; -- 'g' WHEN "1011" => lcd_data <= "00101110"; -- '.' WHEN "1100" => lcd_data <= "00101110"; -- '.' WHEN "1101" => lcd_data <= "00101110"; -- '.' WHEN "1111" => lcd_data <= "10100000"; -- ' ' finished <= '1'; -- needed to set done low before valid data is gone WHEN OTHERS => lcd_data <= "10100000"; -- ' ' END CASE; end if; lcd_select <= '1'; count <= count + '1'; state <= write; end if; end case; end if; end process; end behavioural;