URL
https://opencores.org/ocsvn/z80soc/z80soc/trunk
Subversion Repositories z80soc
[/] [z80soc/] [trunk/] [V0.7.3/] [DE2115/] [vhdl/] [lcd.vhd.bak] - 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';
-- roni LCD_ON <= '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;