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

Subversion Repositories hd44780_driver

[/] [hd44780_driver/] [trunk/] [lcd_driver_hd44780_module.vhd] - Diff between revs 2 and 3

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 2 Rev 3
-- Filename:     lcd_driver_hd44780_module.vhd
-- Filename:     lcd_driver_hd44780_module.vhd
-- Filetype:     VHDL Source Code
-- Filetype:     VHDL Source Code
-- Date:         26 oct 2012
-- Date:         26 oct 2012
-- Update:       -
-- Update:       -
-- Description:  VHDL Description for driving an HD44780 based LCD driver
-- Description:  VHDL Description for driving an HD44780 based LCD driver
-- Author:       J. op den Brouw
-- Author:       J. op den Brouw
-- State:        Demo
-- State:        Demo
-- Error:        -
-- Error:        -
-- Version:      1.2alpha
-- Version:      1.2alpha
-- Copyright:    (c)2012, De Haagse Hogeschool
-- Copyright:    (c)2012, De Haagse Hogeschool
 
 
-- This file contains a VHDL description for driving an HD44780 based LCD
-- This file contains a VHDL description for driving an HD44780 based LCD
-- driver, see for a standard information of such a display:
-- driver, see for a standard information of such a display:
-- https://decibel.ni.com/content/servlet/JiveServlet/download/2741-3-3217/hd44780.pdf
-- https://decibel.ni.com/content/servlet/JiveServlet/download/2741-3-3217/hd44780.pdf
--
--
-- Currently, this driver uses the 8-bit databus mode. This is not a big problem
-- Currently, this driver uses the 8-bit databus mode. This is not a big problem
-- for most FPGA's because of the numerous pins.
-- for most FPGA's because of the numerous pins.
--
--
-- Please note that there are a lot of almost-the-same displays available, so
-- Please note that there are a lot of almost-the-same displays available, so
-- it's not guaranteed to work with all displays available. Also, timing may differ.
-- it's not guaranteed to work with all displays available. Also, timing may differ.
--
--
-- This code is tested on a Terasic DE0-board with an optional
-- This code is tested on a Terasic DE0-board with an optional
-- LCD display. See the weblinks
-- LCD display. See the weblinks
-- http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=56&No=364
-- http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=56&No=364
-- http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=78&No=396
-- http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=78&No=396
-- for more info. The display used has only two lines.
-- for more info. The display used has only two lines.
--
--
-- The VHDL description can both be simulated and synthesized.
-- This VHDL description can both be simulated and synthesized.
--
--
-- This driver has a User Side and a LCD Side. The user is to interface at the User Side
-- This driver has a User Side and a LCD Side. The user is to interface at the User Side
-- and has a number of "routines" at her disposal. The User Side implements the following
-- and has a number of "routines" at her disposal. The User Side implements the following
-- inputs/routines in order of priority:
-- inputs/routines in order of priority:
--
--
-- Command inputs:
-- Command inputs:
--     init:   a logic 1 initializes the display
--     init:   a logic 1 initializes the display
--     cls:    a logic 1 clears the display (and goes to home)
--     cls:    a logic 1 clears the display (and goes to home)
--     home:   a logic 1 sets the cursor to row 0, column 0
--     home:   a logic 1 sets the cursor to row 0, column 0
--     goto10: a logic 1 sets the cursor to row 1, column 0
--     goto10: a logic 1 sets the cursor to row 1, column 0
--     goto20: a logic 1 sets the cursor to row 2, column 0
--     goto20: a logic 1 sets the cursor to row 2, column 0
--     goto30: a logic 1 sets the cursor to row 3, column 0
--     goto30: a logic 1 sets the cursor to row 3, column 0
--     wr:     a logic 1 writes a character to the display
--     wr:     a logic 1 writes a character to the display
--
--
-- Data inputs:
-- Data inputs:
--
--
--     data:   an 8-bit data to be written to the display
--     data:   an 8-bit data to be written to the display
--
--
-- The user has one observable output:
-- The user has one observable output:
--
--
--     busy:   a logic 1 indicates that the driver is currently
--     busy:   a logic 1 indicates that the driver is currently
--             busy driving the display, a logic 0 indicates that
--             busy driving the display, a logic 0 indicates that
--             the driver waits for the next command.
--             the driver waits for the next command.
--
--
-- The user can supply the next generics, which are processed at
-- The user can supply the next generics, which are processed at
-- instantiation of the module:
-- instantiation of the module:
--
--
--          freq:   the clock frequency at which the hardware has to run.
--          freq:   the clock frequency at which the hardware has to run.
--             this frequency is mandatory because of internal delays
--             this frequency is mandatory because of internal delays
--             calculated, defaults to 50 MHz.
--             calculated, defaults to 50 MHz.
--     areset_pol:
--     areset_pol:
--             the polarity of the reset signal, defaults to High (1)
--             the polarity of the reset signal, defaults to High (1)
--     time_init1:
--     time_init1:
--             the time to wait after Vcc > 4.5 V 
--             the time to wait after Vcc > 4.5 V 
--     time_init2:
--     time_init2:
--             the time to wait after first "contact"
--             the time to wait after first "contact"
--     time_init3:
--     time_init3:
--             the time to wait after the second contact
--             the time to wait after the second contact
--     time_tas:
--     time_tas:
--             the RW and RS signal setup time with respect to the positive
--             the RW and RS signal setup time with respect to the positive
--             edge of the E pulse
--             edge of the E pulse
--     time_cycle_e:
--     time_cycle_e:
--             the complete cycle time
--             the complete cycle time
--     time_pweh:
--     time_pweh:
--             the E pulse width high time
--             the E pulse width high time
--     time_no_bf:
--     time_no_bf:
--             time to wait before command completion if no Busy Flag reading is done,
--             time to wait before command completion if no Busy Flag reading is done,
--             some designs connect RW to logic 0, so reading from the LCD is not
--             some designs connect RW to logic 0, so reading from the LCD is not
--             possible, saves a pin.
--             possible, saves a pin.
--     cursor_on:
--     cursor_on:
--             true to set the cursor on at the display, false for no cursor
--             true to set the cursor on at the display, false for no cursor
--     blink_on:
--     blink_on:
--             true to let the cursor blink, false for no blink (just a underscore)
--             true to let the cursor blink, false for no blink (just a underscore)
--     use_bf: true if Busy Flag reading is to be used, false for no BF reading
--     use_bf: true if Busy Flag reading is to be used, false for no BF reading
--
--
-- Note: it's not possible to write command codes to the display.
-- Note: it's not possible to write command codes to the display.
--
--
-- Changes to v1.0:  LCD_E is renamed to LCD_EN
-- Changes to v1.0:  LCD_E is renamed to LCD_EN
--                   LCD_DB is renamed to LCD_DATA
--                   LCD_DB is renamed to LCD_DATA
--                   busy is now registered
--                   busy is now registered
--                   removed hardware simulation architecture
--                   removed hardware simulation architecture
--
--
-- Changes to v1.1:  added timing generics for better steering of the E pulse cycle
-- Changes to v1.1:  added timing generics for better steering of the E pulse cycle
--                   implemented cursor on/off/blink with generic parameters
--                   implemented cursor on/off/blink with generic parameters
--
--
-- Changes to v1.2:  added Busy Flag reading mode, selectable at instantiation time
-- Changes to v1.2:  added Busy Flag reading mode, selectable at instantiation time
--                   LCD_EN changes back to LCD_E
--                   LCD_EN changes back to LCD_E
--                   LCD_DATA changed back to LCD_DB
--                   LCD_DATA changed back to LCD_DB
--
--
-- To do:            use 4-bit mode or 8-bit mode at instantiation time
-- To do:            use 4-bit mode or 8-bit mode at instantiation time
--
--
 
 
-- The libraries to use.
-- The libraries to use.
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
 
 
-- The entity of the LCD Driver Module.
-- The entity of the LCD Driver Module.
entity lcd_driver_hd44780_module is
entity lcd_driver_hd44780_module is
        generic (freq         : integer := 50000000;
        generic (freq         : integer := 50000000;
                                areset_pol   : std_logic := '1';
                                areset_pol   : std_logic := '1';
                                time_init1   : time := 40 ms;
                                time_init1   : time := 40 ms;
                                time_init2   : time := 4100 us;
                                time_init2   : time := 4100 us;
                                time_init3   : time := 100 us;
                                time_init3   : time := 100 us;
                                time_tas     : time := 60 ns;
                                time_tas     : time := 60 ns;
                                time_cycle_e : time := 1000 ns;
                                time_cycle_e : time := 1000 ns;
                                time_pweh    : time := 500 ns;
                                time_pweh    : time := 500 ns;
                                time_no_bf   : time := 2 ms;
                                time_no_bf   : time := 2 ms;
                                cursor_on    : boolean := false;
                                cursor_on    : boolean := false;
                                blink_on     : boolean := false;
                                blink_on     : boolean := false;
                                use_bf       : boolean := true
                                use_bf       : boolean := true
                          );
                          );
        port      (clk      : in std_logic;
        port      (clk      : in std_logic;
                           areset   : in std_logic;
                           areset   : in std_logic;
                           -- User site
                           -- User site
                           init     : in std_logic;
                           init     : in std_logic;
                           data     : in std_logic_vector(7 downto 0);
                           data     : in std_logic_vector(7 downto 0);
                           wr       : in std_logic;
                           wr       : in std_logic;
                           cls      : in std_logic;
                           cls      : in std_logic;
                           home     : in std_logic;
                           home     : in std_logic;
                           goto10   : in std_logic;
                           goto10   : in std_logic;
                           goto20   : in std_logic;
                           goto20   : in std_logic;
                           goto30   : in std_logic;
                           goto30   : in std_logic;
                           busy     : out std_logic;
                           busy     : out std_logic;
                           -- LCD side
                           -- LCD side
                           LCD_E    : out std_logic;
                           LCD_E    : out std_logic;
                           LCD_RS   : out std_logic;
                           LCD_RS   : out std_logic;
                           LCD_RW   : out std_logic;
                           LCD_RW   : out std_logic;
                           LCD_DB   : inout std_logic_vector(7 downto 0)
                           LCD_DB   : inout std_logic_vector(7 downto 0)
                          );
                          );
end entity lcd_driver_hd44780_module;
end entity lcd_driver_hd44780_module;
 
 
-- This architecture drives the LCD.
-- This architecture drives the LCD.
architecture hardware_driver of lcd_driver_hd44780_module is
architecture hardware_driver of lcd_driver_hd44780_module is
 
 
-- Delays... Please note that if the frequency is (too) low,
-- Delays... Please note that if the frequency is (too) low,
-- some of the delays will 0. The code will take care of that.
-- some of the delays will 0. The code will take care of that.
-- Converting time to integer is problematic. Please note the use of
-- Converting time to integer is problematic. Please note the use of
-- the simulator time step in the calculations.
-- the simulator time step in the calculations.
-- The simulator timestep
-- The simulator timestep
constant simulator_timestep : time := 1 ns;
constant simulator_timestep : time := 1 ns;
-- Number of simulator timesteps per second.
-- Number of simulator timesteps per second.
constant sim_steps_per_sec : real := real(1 sec/simulator_timestep);
constant sim_steps_per_sec : real := real(1 sec/simulator_timestep);
 
 
constant delay_init1   : integer := integer( real(freq) * real(time_init1/simulator_timestep) / sim_steps_per_sec);
constant delay_init1   : integer := integer( real(freq) * real(time_init1/simulator_timestep) / sim_steps_per_sec);
constant delay_init2   : integer := integer( real(freq) * real(time_init2/simulator_timestep) / sim_steps_per_sec);
constant delay_init2   : integer := integer( real(freq) * real(time_init2/simulator_timestep) / sim_steps_per_sec);
constant delay_init3   : integer := integer( real(freq) * real(time_init3/simulator_timestep) / sim_steps_per_sec);
constant delay_init3   : integer := integer( real(freq) * real(time_init3/simulator_timestep) / sim_steps_per_sec);
constant delay_tas     : integer := integer( real(freq) * real(time_tas/simulator_timestep) / sim_steps_per_sec);
constant delay_tas     : integer := integer( real(freq) * real(time_tas/simulator_timestep) / sim_steps_per_sec);
constant delay_cycle_e : integer := integer( real(freq) * real(time_cycle_e/simulator_timestep) / sim_steps_per_sec);
constant delay_cycle_e : integer := integer( real(freq) * real(time_cycle_e/simulator_timestep) / sim_steps_per_sec);
constant delay_pweh    : integer := integer( real(freq) * real(time_pweh/simulator_timestep) / sim_steps_per_sec);
constant delay_pweh    : integer := integer( real(freq) * real(time_pweh/simulator_timestep) / sim_steps_per_sec);
constant delay_no_bf   : integer := integer( real(freq) * real(time_no_bf/simulator_timestep) / sim_steps_per_sec);
constant delay_no_bf   : integer := integer( real(freq) * real(time_no_bf/simulator_timestep) / sim_steps_per_sec);
 
 
-- The next statements do work in Quartus but not in (32 bit) ModelSim...
-- The next statements do work in Quartus but not in (32 bit) ModelSim...
--constant delay_init1   : integer := integer(real(freq)*real(time'pos(time_init1)) / real(time'pos(1 sec)));
--constant delay_init1   : integer := integer(real(freq)*real(time'pos(time_init1)) / real(time'pos(1 sec)));
--constant delay_init2   : integer := integer(real(freq)*real(time'pos(time_init2)) / real(time'pos(1 sec)));
--constant delay_init2   : integer := integer(real(freq)*real(time'pos(time_init2)) / real(time'pos(1 sec)));
--constant delay_init3   : integer := integer(real(freq)*real(time'pos(time_init3)) / real(time'pos(1 sec)));
--constant delay_init3   : integer := integer(real(freq)*real(time'pos(time_init3)) / real(time'pos(1 sec)));
--constant delay_tas     : integer := integer(real(freq)*real(time'pos(time_tas)) / real(time'pos(1 sec)));
--constant delay_tas     : integer := integer(real(freq)*real(time'pos(time_tas)) / real(time'pos(1 sec)));
--constant delay_cycle_e : integer := integer(real(freq)*real(time'pos(time_cycle_e)) / real(time'pos(1 sec)));
--constant delay_cycle_e : integer := integer(real(freq)*real(time'pos(time_cycle_e)) / real(time'pos(1 sec)));
--constant delay_pweh    : integer := integer(real(freq)*real(time'pos(time_pweh)) / real(time'pos(1 sec)));
--constant delay_pweh    : integer := integer(real(freq)*real(time'pos(time_pweh)) / real(time'pos(1 sec)));
--constant delay_no_bf   : integer := integer(real(freq)*real(time'pos(time_no_bf)) / real(time'pos(1 sec)));
--constant delay_no_bf   : integer := integer(real(freq)*real(time'pos(time_no_bf)) / real(time'pos(1 sec)));
 
 
-- Time the E signal must be low following E high
-- Time the E signal must be low following E high
constant delay_pwel    : integer := delay_cycle_e-delay_pweh;
constant delay_pwel    : integer := delay_cycle_e-delay_pweh;
 
 
-- Counter for the delays. Timer would be a better choice.
-- Counter for the delays. Timer would be a better choice.
-- Range should be to the longest delay.
-- Range should be to the longest delay.
signal delay_counter : integer range 0 to delay_init1;
signal delay_counter : integer range 0 to delay_init1;
 
 
-- Should we use Busy Flag reading?
-- Should we use Busy Flag reading?
signal use_bf_int : std_logic;
signal use_bf_int : std_logic;
 
 
-- The states of the state machine.
-- The states of the state machine.
type state_type is (reset, command_init, command_init_1, command_init_2, command_init_3,
type state_type is (reset, command_init, command_init_1, command_init_2, command_init_3,
                                                  command_init_4, command_init_5, command_init_6, command_init_7, command_init_8,
                                                  command_init_4, command_init_5, command_init_6, command_init_7, command_init_8,
                                                  command_init_9, command_init_10, command_init_11, command_init12,
                                                  command_init_9, command_init_10, command_init_11, command_init12,
                                                  wait_for_command,
                                                  wait_for_command,
                                                  command_cls, command_home,
                                                  command_cls, command_home,
                                                  command_goto10, command_goto20, command_goto30, command_wr,
                                                  command_goto10, command_goto20, command_goto30, command_wr,
                                                  pulse_e, pulse_e_1, pulse_e_2, pulse_e_3, pulse_e_4,
                                                  pulse_e, pulse_e_1, pulse_e_2, pulse_e_3, pulse_e_4,
                                                  pulse_busy_flag, pulse_busy_flag_1, pulse_busy_flag_2, pulse_busy_flag_3,
                                                  pulse_busy_flag, pulse_busy_flag_1, pulse_busy_flag_2, pulse_busy_flag_3,
                                                  pulse_busy_flag_4, pulse_busy_flag_5);
                                                  pulse_busy_flag_4, pulse_busy_flag_5);
 
 
 
 
-- The current state and one for the return state (to facilitate return to the caller).
-- The current state and one for the return state (to facilitate return to the caller).
signal current_state, return_state : state_type;
signal current_state, return_state : state_type;
begin
begin
 
 
        -- The state machine ;-)
        -- The state machine ;-)
        nsl_state: process (clk, areset) is
        nsl_state: process (clk, areset) is
                -- Function to translate a boolean to std_logic
                -- Function to translate a boolean to std_logic
                function bool_to_stdlogic(l: boolean) return std_logic is
                function bool_to_stdlogic(l: boolean) return std_logic is
                begin
                begin
        if l then
        if l then
                                return('1');
                                return('1');
                        else
                        else
                                return('0');
                                return('0');
                        end if;
                        end if;
                end function bool_to_stdlogic;
                end function bool_to_stdlogic;
        begin
        begin
                if (areset = '1' and areset_pol = '1') or (areset = '0' and areset_pol = '0') then
                if (areset = '1' and areset_pol = '1') or (areset = '0' and areset_pol = '0') then
                        current_state <= reset;
                        current_state <= reset;
                        delay_counter <= 0;
                        delay_counter <= 0;
                        busy <= '1';
                        busy <= '1';
                        LCD_DB <= (others => 'Z');
                        LCD_DB <= (others => 'Z');
                        LCD_E  <= '0';
                        LCD_E  <= '0';
                        LCD_RS <= '0';
                        LCD_RS <= '0';
                        LCD_RW <= '0';
                        LCD_RW <= '0';
                        use_bf_int <= '0';
                        use_bf_int <= '0';
                elsif rising_edge(clk) then
                elsif rising_edge(clk) then
                        -- Default is busy
                        -- Default is busy
                        busy <= '1';
                        busy <= '1';
                        -- Default values of the LCD side
                        -- Default values of the LCD side
                        LCD_E  <= '0';
                        LCD_E  <= '0';
                        LCD_RW <= '0';
                        LCD_RW <= '0';
                        case current_state is
                        case current_state is
                                when reset|command_init =>
                                when reset|command_init =>
                                        -- The logic is reset. Start initialization routine.
                                        -- The logic is reset. Start initialization routine.
                                        LCD_DB <= (others => 'Z');
                                        LCD_DB <= (others => 'Z');
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        use_bf_int <= '0';
                                        use_bf_int <= '0';
                                        delay_counter <= delay_init1;
                                        delay_counter <= delay_init1;
                                        current_state <= command_init_1;
                                        current_state <= command_init_1;
                                when command_init_1 =>
                                when command_init_1 =>
                                        -- Wait until Vcc > 4.5 V...
                                        -- Wait until Vcc > 4.5 V...
                                        LCD_DB <= (others => 'Z');
                                        LCD_DB <= (others => 'Z');
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        use_bf_int <= '0';
                                        use_bf_int <= '0';
                                        -- If done write 0x30 to the LCD
                                        -- If done write 0x30 to the LCD
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                LCD_DB <= "00110000";  -- 0x30
                                                LCD_DB <= "00110000";  -- 0x30
                                                current_state <= pulse_e;
                                                current_state <= pulse_e;
                                                return_state <= command_init_2;
                                                return_state <= command_init_2;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
                                when command_init_2 =>
                                when command_init_2 =>
                                        -- Next, set up wait for 4.1 ms
                                        -- Next, set up wait for 4.1 ms
                                        LCD_DB <= (others => 'Z');
                                        LCD_DB <= (others => 'Z');
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        use_bf_int <= '0';
                                        use_bf_int <= '0';
                                        delay_counter <= delay_init2;
                                        delay_counter <= delay_init2;
                                        current_state <= command_init_3;
                                        current_state <= command_init_3;
                                when command_init_3 =>
                                when command_init_3 =>
                                        -- Wait...
                                        -- Wait...
                                        LCD_DB <= (others => 'Z');
                                        LCD_DB <= (others => 'Z');
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        use_bf_int <= '0';
                                        use_bf_int <= '0';
                                        -- If done write 0x30 to the LCD
                                        -- If done write 0x30 to the LCD
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                LCD_DB <= "00110000";  -- 0x30
                                                LCD_DB <= "00110000";  -- 0x30
                                                current_state <= pulse_e;
                                                current_state <= pulse_e;
                                                return_state <= command_init_4;
                                                return_state <= command_init_4;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
                                when command_init_4 =>
                                when command_init_4 =>
                                        -- Next, set up wait for 100 us
                                        -- Next, set up wait for 100 us
                                        LCD_DB <= (others => 'Z');
                                        LCD_DB <= (others => 'Z');
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        use_bf_int <= '0';
                                        use_bf_int <= '0';
                                        delay_counter <= delay_init3;
                                        delay_counter <= delay_init3;
                                        current_state <= command_init_5;
                                        current_state <= command_init_5;
                                when command_init_5 =>
                                when command_init_5 =>
                                        -- Wait...
                                        -- Wait...
                                        LCD_DB <= (others => 'Z');
                                        LCD_DB <= (others => 'Z');
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        use_bf_int <= '0';
                                        use_bf_int <= '0';
                                        -- If done write 0x30 to the LCD
                                        -- If done write 0x30 to the LCD
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                LCD_DB <= "00110000";  -- 0x30
                                                LCD_DB <= "00110000";  -- 0x30
                                                current_state <= pulse_e;
                                                current_state <= pulse_e;
                                                return_state <= command_init_6;
                                                return_state <= command_init_6;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
                                when command_init_6 =>
                                when command_init_6 =>
                                        -- Power up is now done, so let's enter some reasonable values...
                                        -- Power up is now done, so let's enter some reasonable values...
                                        LCD_DB <= "00110000";
                                        LCD_DB <= "00110000";
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        use_bf_int <= bool_to_stdlogic(use_bf);
                                        use_bf_int <= bool_to_stdlogic(use_bf);
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= command_init_7;
                                        return_state <= command_init_7;
                                when command_init_7 =>
                                when command_init_7 =>
                                        -- 8-bit bus, 2(?) lines, 5x7 characters
                                        -- 8-bit bus, 2(?) lines, 5x7 characters
                                        LCD_DB <= "00111100";  -- 0x3C
                                        LCD_DB <= "00111100";  -- 0x3C
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= command_init_8;
                                        return_state <= command_init_8;
                                when command_init_8 =>
                                when command_init_8 =>
                                        -- Display off
                                        -- Display off
                                        LCD_DB <= "00001000";  -- 0x08
                                        LCD_DB <= "00001000";  -- 0x08
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= command_init_9;
                                        return_state <= command_init_9;
                                when command_init_9 =>
                                when command_init_9 =>
                                        -- Display clear
                                        -- Display clear
                                        LCD_DB <= "00000001";  -- 0x01
                                        LCD_DB <= "00000001";  -- 0x01
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= command_init_10;
                                        return_state <= command_init_10;
                                when command_init_10 =>
                                when command_init_10 =>
                                        -- Display on, cursor and blink...
                                        -- Display on, cursor and blink...
                                        LCD_DB <= "000011" & bool_to_stdlogic(cursor_on) & bool_to_stdlogic(blink_on);  -- 0x0C + ...
                                        LCD_DB <= "000011" & bool_to_stdlogic(cursor_on) & bool_to_stdlogic(blink_on);  -- 0x0C + ...
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= command_init_11;
                                        return_state <= command_init_11;
                                when command_init_11 =>
                                when command_init_11 =>
                                        -- Mode set, increment cursor address, cursor shift
                                        -- Mode set, increment cursor address, cursor shift
                                        LCD_DB <= "00000110";  -- 0x06
                                        LCD_DB <= "00000110";  -- 0x06
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= wait_for_command;
                                        return_state <= wait_for_command;
 
 
                                -- The command dispatcher! This state waits for one of
                                -- The command dispatcher! This state waits for one of
                                -- the command inputs to be logic '1' and 'starts' the
                                -- the command inputs to be logic '1' and 'starts' the
                                -- accompanying routine. Note the priority encoding!
                                -- accompanying routine. Note the priority encoding!
                                when wait_for_command =>
                                when wait_for_command =>
                                        LCD_DB <= (others => 'Z');
                                        LCD_DB <= (others => 'Z');
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        busy <= '0';
                                        busy <= '0';
                                        if init = '1' then
                                        if init = '1' then
                                                busy <= '1';
                                                busy <= '1';
                                                current_state <= command_init;
                                                current_state <= command_init;
                                        elsif cls = '1' then
                                        elsif cls = '1' then
                                                busy <= '1';
                                                busy <= '1';
                                                current_state <= command_cls;
                                                current_state <= command_cls;
                                        elsif home = '1' then
                                        elsif home = '1' then
                                                busy <= '1';
                                                busy <= '1';
                                                current_state <= command_home;
                                                current_state <= command_home;
                                        elsif goto10 = '1' then
                                        elsif goto10 = '1' then
                                                busy <= '1';
                                                busy <= '1';
                                                current_state <= command_goto10;
                                                current_state <= command_goto10;
                                        elsif goto20 = '1' then
                                        elsif goto20 = '1' then
                                                busy <= '1';
                                                busy <= '1';
                                                current_state <= command_goto20;
                                                current_state <= command_goto20;
                                        elsif goto30 = '1' then
                                        elsif goto30 = '1' then
                                                busy <= '1';
                                                busy <= '1';
                                                current_state <= command_goto30;
                                                current_state <= command_goto30;
                                        elsif wr = '1' then
                                        elsif wr = '1' then
                                                -- Read in data! Do NOT forget that here!
                                                -- Read in data! Do NOT forget that here!
                                                LCD_DB <= data;
                                                LCD_DB <= data;
                                                busy <= '1';
                                                busy <= '1';
                                                current_state <= command_wr;
                                                current_state <= command_wr;
                                        end if;
                                        end if;
 
 
                                when command_cls =>
                                when command_cls =>
                                        -- Display clear
                                        -- Display clear
                                        LCD_DB <= "00000001";
                                        LCD_DB <= "00000001";
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= wait_for_command;
                                        return_state <= wait_for_command;
 
 
                                when command_home =>
                                when command_home =>
                                        -- Cursor home
                                        -- Cursor home
                                        LCD_DB <= "00000010";
                                        LCD_DB <= "00000010";
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= wait_for_command;
                                        return_state <= wait_for_command;
 
 
                                when command_goto10 =>
                                when command_goto10 =>
                                        -- Cursor to beginning of line 2nd line...
                                        -- Cursor to beginning of line 2nd line...
                                        LCD_DB <= "11000000";   --0x80+0x40;
                                        LCD_DB <= "11000000";   --0x80+0x40;
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= wait_for_command;
                                        return_state <= wait_for_command;
 
 
                                when command_goto20 =>
                                when command_goto20 =>
                                        -- Cursor to beginning of line 3rd line...
                                        -- Cursor to beginning of line 3rd line...
                                        LCD_DB <= "10010000";   --0x80+0x10;
                                        LCD_DB <= "10010000";   --0x80+0x10;
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= wait_for_command;
                                        return_state <= wait_for_command;
 
 
                                when command_goto30 =>
                                when command_goto30 =>
                                        -- Cursor to beginning of line 4th line...
                                        -- Cursor to beginning of line 4th line...
                                        LCD_DB <= "11010000";   --0x80+0x50;
                                        LCD_DB <= "11010000";   --0x80+0x50;
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= wait_for_command;
                                        return_state <= wait_for_command;
 
 
                                when command_wr =>
                                when command_wr =>
                                        -- Start character write cycle
                                        -- Start character write cycle
                                        -- Do NOT set data here!
                                        -- Do NOT set data here!
                                        LCD_RS <= '1';
                                        LCD_RS <= '1';
                                        current_state <= pulse_e;
                                        current_state <= pulse_e;
                                        return_state <= wait_for_command;
                                        return_state <= wait_for_command;
 
 
                                -- --   
                                -- --   
                                -- Provide E strobing for data transfer.
                                -- Provide E strobing for data transfer.
                                -- Writes data byte to the LCD.
                                -- Writes data byte to the LCD.
                                -- Please note, DATA and RS are set by the caller!
                                -- Please note, DATA and RS are set by the caller!
                                when pulse_e =>
                                when pulse_e =>
                                        -- wait 60 ns before E -> 1 (tAS)
                                        -- wait 60 ns before E -> 1 (tAS)
                                        delay_counter <= delay_tas;
                                        delay_counter <= delay_tas;
                                        current_state <= pulse_e_1;
                                        current_state <= pulse_e_1;
                                when pulse_e_1 =>
                                when pulse_e_1 =>
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                -- timer set: E = 1 for 500 ns (PWeh)
                                                -- timer set: E = 1 for 500 ns (PWeh)
                                                delay_counter <= delay_pweh;
                                                delay_counter <= delay_pweh;
                                                current_state <= pulse_e_2;
                                                current_state <= pulse_e_2;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
                                when pulse_e_2 =>
                                when pulse_e_2 =>
                                        LCD_E <= '1';
                                        LCD_E <= '1';
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                -- timer set: E = 0 for 500 ns (tCycleE-PWeh)
                                                -- timer set: E = 0 for 500 ns (tCycleE-PWeh)
                                                delay_counter <= delay_pwel;
                                                delay_counter <= delay_pwel;
                                                current_state <= pulse_e_3;
                                                current_state <= pulse_e_3;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
                                when pulse_e_3 =>
                                when pulse_e_3 =>
                                        LCD_E <= '0';
                                        LCD_E <= '0';
                                        -- Command completion, check for use busy flag
                                        -- Command completion, check for use busy flag
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                -- If no busy flag used, wait for a amount of time.
                                                -- If no busy flag used, wait for a amount of time.
                                                if use_bf_int = '0' then
                                                if use_bf_int = '0' then
                                                        delay_counter <= delay_no_bf;
                                                        delay_counter <= delay_no_bf;
                                                        current_state <= pulse_e_4;
                                                        current_state <= pulse_e_4;
                                                else -- BF used
                                                else -- BF used
                                                        current_state <= pulse_busy_flag;
                                                        current_state <= pulse_busy_flag;
                                                end if;
                                                end if;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
                                when pulse_e_4 =>
                                when pulse_e_4 =>
                                        -- Wait for the delay to finsh and then return to the caller.
                                        -- Wait for the delay to finsh and then return to the caller.
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                current_state <= return_state;
                                                current_state <= return_state;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
 
 
                                -- Let's read the busy flag, see if the module is busy...
                                -- Let's read the busy flag, see if the module is busy...
                                when pulse_busy_flag =>
                                when pulse_busy_flag =>
                                        LCD_DB <= (others => 'Z');
                                        LCD_DB <= (others => 'Z');
                                        LCD_RW <= '1';
                                        LCD_RW <= '1';
                                        LCD_RS <= '0';
                                        LCD_RS <= '0';
                                        -- wait 60 ns before E -> 1 (tAS)
                                        -- wait 60 ns before E -> 1 (tAS)
                                        delay_counter <= delay_tas;
                                        delay_counter <= delay_tas;
                                        current_state <= pulse_busy_flag_1;
                                        current_state <= pulse_busy_flag_1;
                                when pulse_busy_flag_1 =>
                                when pulse_busy_flag_1 =>
                                        LCD_RW <= '1';
                                        LCD_RW <= '1';
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                -- timer set: E = 1 for 500 ns (tPWeh)
                                                -- timer set: E = 1 for 500 ns (tPWeh)
                                                delay_counter <= delay_pweh;
                                                delay_counter <= delay_pweh;
                                                current_state <= pulse_busy_flag_2;
                                                current_state <= pulse_busy_flag_2;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
                                when pulse_busy_flag_2 =>
                                when pulse_busy_flag_2 =>
                                        LCD_E <= '1';
                                        LCD_E <= '1';
                                        LCD_RW <= '1';
                                        LCD_RW <= '1';
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                -- timer set: E = 0 for 500 ns (tPWel)
                                                -- timer set: E = 0 for 500 ns (tPWel)
                                                delay_counter <= delay_pwel;
                                                delay_counter <= delay_pwel;
                                                current_state <= pulse_busy_flag_3;
                                                current_state <= pulse_busy_flag_3;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
                                when pulse_busy_flag_3 =>
                                when pulse_busy_flag_3 =>
                                        LCD_E <= '0';
                                        LCD_E <= '0';
                                        LCD_RW <= '1';
                                        LCD_RW <= '1';
                                        if LCD_DB(7) = '0' then
                                        if LCD_DB(7) = '0' then
                                                -- operation ended
                                                -- operation ended
                                                current_state <= pulse_busy_flag_4;
                                                current_state <= pulse_busy_flag_4;
                                        else
                                        else
                                                -- operation in progress
                                                -- operation in progress
                                                current_state <= pulse_busy_flag_5;
                                                current_state <= pulse_busy_flag_5;
                                        end if;
                                        end if;
                                when pulse_busy_flag_4 =>
                                when pulse_busy_flag_4 =>
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                -- Operation ended, return caller
                                                -- Operation ended, return caller
                                                current_state <= return_state;
                                                current_state <= return_state;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
                                when pulse_busy_flag_5 =>
                                when pulse_busy_flag_5 =>
                                        if delay_counter = 0 or delay_counter = 1 then
                                        if delay_counter = 0 or delay_counter = 1 then
                                                -- Operation in progress, read BF again
                                                -- Operation in progress, read BF again
                                                current_state <= pulse_busy_flag;
                                                current_state <= pulse_busy_flag;
                                        else
                                        else
                                                delay_counter <= delay_counter-1;
                                                delay_counter <= delay_counter-1;
                                        end if;
                                        end if;
 
 
                                when others => null;
                                when others => null;
                        end case;
                        end case;
                end if;
                end if;
 
 
        end process;
        end process;
 
 
end architecture hardware_driver;
end architecture hardware_driver;
 
 

powered by: WebSVN 2.1.0

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