OpenCores
URL https://opencores.org/ocsvn/z80soc/z80soc/trunk

Subversion Repositories z80soc

[/] [z80soc/] [trunk/] [V0.7.3/] [DE2115/] [vhdl/] [lcd.vhd] - Rev 46

Compare with Previous | Blame | View Log

-- VHDL CODE by Gerry O'Brien - HD44780 LCD Controller STATE_MACHINE
--==================================================--
--
-- VHDL Architecture DE2_LCD_lib.TOP_LCD_DE2.LCD_DISPLAY_arch
--
-- Created:
--          by - Gerry O'Brien 
--          WWW.DIGITAL-CIRCUITRY.COM
--          at - 15:30:18 26/03/2015
-- 
-- using Mentor Graphics HDL Designer(TM) 2010.3 (Build 21)
--
LIBRARY IEEE;
USE  IEEE.STD_LOGIC_1164.all;
USE  IEEE.STD_LOGIC_ARITH.all;
USE  IEEE.STD_LOGIC_UNSIGNED.all;
 
 
ENTITY LCD IS
 
   PORT( 
		reset             : IN     std_logic;  -- Map this Port to a Switch within your [Port Declarations / Pin Planer]  
		CLOCK_50          : IN     std_logic;  -- Using the DE2 50Mhz Clk, in order to Genreate the 400Hz signal... clk_count_400hz reset count value must be set to:  <= x"0F424"
		LCD_RS            : OUT    std_logic;
		LCD_EN            : OUT    std_logic;
		LCD_RW            : OUT    std_logic;
		LCD_ON            : OUT    std_logic;
		LCD_BLON          : OUT    std_logic;
		LCD_DATA          : INOUT 	STD_LOGIC_VECTOR(7 DOWNTO 0);
		lcd_on_sig		  : IN		STD_LOGIC;
		next_char		  : IN 		STD_LOGIC_VECTOR(7 DOWNTO 0);
		char_count        : OUT 	STD_LOGIC_VECTOR(4 downto 0);
		clk400hz	      : OUT		STD_LOGIC
   );
 
END LCD ;
 
--
ARCHITECTURE RTL OF LCD IS
 
  type state_type is (hold, func_set, display_on, mode_set, print_string,
                      line2, return_home, drop_LCD_EN, reset1, reset2,
                       reset3, display_off, display_clear);
 
  signal state, next_command         : state_type;
 
  signal data_bus_value				 : STD_LOGIC_VECTOR(7 downto 0);
  signal clk_count_400hz             : STD_LOGIC_VECTOR(19 downto 0);
  signal char_count_sig              : STD_LOGIC_VECTOR(4 downto 0);
  signal clk_400hz_enable,LCD_RW_int : std_logic; 
  signal data_bus                    : STD_LOGIC_VECTOR(7 downto 0);	
  signal LCD_CHAR_ARRAY              : STD_LOGIC_VECTOR(3 DOWNTO 0);
 
BEGIN
 
LCD_DATA 	<= data_bus;
data_bus 	<= data_bus_value when LCD_RW_int = '0' else "ZZZZZZZZ";
LCD_RW 		<= LCD_RW_int;
char_count	<= char_count_sig;
clk400hz		<= clk_400hz_enable;
 
--======================= CLOCK SIGNALS ============================--  
process(CLOCK_50)
begin
      if (rising_edge(CLOCK_50)) then
         if (reset = '0') then
            clk_count_400hz <= x"00000";
            clk_400hz_enable <= '0';
         else
            if (clk_count_400hz <= x"0F424") then          -- If using the DE2 50Mhz Clock,  use clk_count_400hz <= x"0F424"  (50Mhz/400hz = 12500 converted to HEX = 0F424 )   
                   clk_count_400hz <= clk_count_400hz + 1; --  In Theory for a 27Mhz Clock,  use clk_count_400hz <= x"01A5E"  (27Mhz/400hz = 6750  converted to HEX = 01A5E )                                       
                   clk_400hz_enable <= '0';                --  In Theory for a 25Mhz Clock.  use clk_count_400hz <= x"0186A"  (25Mhz/400hz = 6250  converted to HEX = 0186A )
            else
                   clk_count_400hz <= x"00000";
                   clk_400hz_enable <= '1';
            end if;
         end if;
      end if;
end process;  
--==================================================================--    
 
--======================== LCD DRIVER CORE ==============================--   
--                     STATE MACHINE WITH RESET                          -- 
--===================================================-----===============--  
process (CLOCK_50, reset)
begin
        if reset = '0' then
           state <= reset1;
           data_bus_value <= x"38"; -- RESET
           next_command <= reset2;
           LCD_EN <= '1';
           LCD_RS <= '0';
           LCD_RW_int <= '0';
 
        elsif rising_edge(CLOCK_50) then
             if clk_400hz_enable = '1' then  
 
 
 
              --========================================================--                 
              -- State Machine to send commands and data to LCD DISPLAY
              --========================================================--
                 case state is
                 -- Set Function to 8-bit transfer and 2 line display with 5x8 Font size
                 -- see Hitachi HD44780 family data sheet for LCD command and timing details
 
 
 
--======================= INITIALIZATION START ============================--
                       when reset1 =>
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"38"; -- EXTERNAL RESET
                            state <= drop_LCD_EN;
                            next_command <= reset2;
                            char_count_sig <= "00000";
 
                       when reset2 =>
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"38"; -- EXTERNAL RESET
                            state <= drop_LCD_EN;
                            next_command <= reset3;
 
                       when reset3 =>
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"38"; -- EXTERNAL RESET
                            state <= drop_LCD_EN;
                            next_command <= func_set;
 
 
                       -- Function Set
                       --==============--
                       when func_set =>                
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"38";  -- Set Function to 8-bit transfer, 2 line display and a 5x8 Font size
                            state <= drop_LCD_EN;
                            next_command <= display_off;
 
 
 
                       -- Turn off Display
                       --==============-- 
                       when display_off =>
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"08"; -- Turns OFF the Display, Cursor OFF and Blinking Cursor Position OFF.......(0F = Display ON and Cursor ON, Blinking cursor position ON)
                            state <= drop_LCD_EN;
                            next_command <= display_clear;
 
 
                       -- Clear Display 
                       --==============--
                       when display_clear =>
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"01"; -- Clears the Display    
                            state <= drop_LCD_EN;
                            next_command <= display_on;
 
 
 
                       -- Turn on Display and Turn off cursor
                       --===================================--
                       when display_on =>
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"0C"; -- Turns on the Display (0E = Display ON, Cursor ON and Blinking cursor OFF) 
                            state <= drop_LCD_EN;
                            next_command <= mode_set;
 
 
                       -- Set write mode to auto increment address and move cursor to the right
                       --====================================================================--
                       when mode_set =>
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"06"; -- Auto increment address and move cursor to the right
                            state <= drop_LCD_EN;
                            next_command <= print_string; 
 
 
--======================= INITIALIZATION END ============================--                          
 
 
 
 
--=======================================================================--                           
--               Write ASCII hex character Data to the LCD
--=======================================================================--
                       when print_string =>          
                            state <= drop_LCD_EN;
                            LCD_EN <= '1';
                            LCD_RS <= '1';
                            LCD_RW_int <= '0';
 
 
                               -- ASCII character to output
                               if (next_char(7 downto 4) /= x"0") then
                                  data_bus_value <= next_char;
                               else
 
                                    -- Convert 4-bit value to an ASCII hex digit
                                    if next_char(3 downto 0) >9 then 
 
                                    -- ASCII A...F
                                      data_bus_value <= x"4" & (next_char(3 downto 0)-9); 
                                    else 
 
                                    -- ASCII 0...9
                                      data_bus_value <= x"3" & next_char(3 downto 0);
                                    end if;
                               end if;
 
                            state <= drop_LCD_EN; 
 
 
 
                            -- Loop to send out 32 characters to LCD Display (16 by 2 lines)
                               if (char_count_sig < 31) AND (next_char /= x"fe") then
                                   char_count_sig <= char_count_sig +1;                            
                               else
                                   char_count_sig <= "00000";
                               end if;
 
 
 
                            -- Jump to second line?
                               if char_count_sig = 15 then 
                                  next_command <= line2;
 
 
 
                            -- Return to first line?
                               elsif (char_count_sig = 31) or (next_char = x"fe") then
                                     next_command <= return_home;
                               else 
                                     next_command <= print_string; 
                               end if; 
 
 
 
                       -- Set write address to line 2 character 1
                       --======================================--
                       when line2 =>
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"c0";
                            state <= drop_LCD_EN;
                            next_command <= print_string;      
 
 
                       -- Return write address to first character position on line 1
                       --=========================================================--
                       when return_home =>
                            LCD_EN <= '1';
                            LCD_RS <= '0';
                            LCD_RW_int <= '0';
                            data_bus_value <= x"80";
                            state <= drop_LCD_EN;
                            next_command <= print_string; 
 
 
 
                       -- The next states occur at the end of each command or data transfer to the LCD
                       -- Drop LCD E line - falling edge loads inst/data to LCD controller
                       --============================================================================--
                       when drop_LCD_EN =>
                            LCD_EN <= '0';
                            state <= hold;
 
                       -- Hold LCD inst/data valid after falling edge of E line
                       --====================================================--
                       when hold =>
                            state <= next_command;
                            LCD_BLON <= '1';
									 LCD_ON <= lcd_on_sig;
                       end case;
 
 
 
 
             end if;-- CLOSING STATEMENT FOR "IF clk_400hz_enable = '1' THEN"
 
      end if;-- CLOSING STATEMENT FOR "IF reset = '0' THEN" 
 
end process;                                                            
 
END ARCHITECTURE RTL;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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