Timing problem with HD44780 LCD controller on FPGA using VHDL

Discussion in 'VHDL' started by BlackHelicopter, Feb 27, 2011.

  1. BlackHelicopter

    BlackHelicopter

    Joined:
    Jun 3, 2010
    Messages:
    14
    Hi

    I made an HD44780 LCD controller for a DE2-70 development board. According to the datasheet for the HD44780, it appears the max operating frequency is limited by T_enable_cycle of 500ns (or 2MHz). When I run my code the fastest enable period I can run is roughly 2us or 500kHz without it behaving erratically(delay_500ns count = 100, not my intended 25). For instance, if I try to go any faster than 500kHz, it misses characters or shifts the letters to random positions on the screen. Also there's an unintended space in the beginning(in addition to my first space) which I can't figure out how to get rid of.

    Does anyone have any idea what might be wrong?

    Also I'm rather new to VHDL so this might not be the coded the best. If anyone has any tips or pointers or see any areas of improvement please let me know!

    Thanks!

    Code:
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity HD44780_controller is
    port (clk		: in std_logic;
    	  reset		: in std_logic := '1';
    	  pb		: in std_logic := '1';
    	  lcd_on	: out std_logic := '1';
    	  en		: out std_logic := '0';
    	  rs		: out std_logic := '0';
    	  rw		: out std_logic := '0';
    --	  bf 		: out std_logic := '0';
    	  db		: inout std_logic_vector (7 downto 0));  -- inout
    end HD44780_controller;
    
    architecture arch of HD44780_controller is
    	type state_type is (init, disp_on, wr_ddram, clr_disp, en_h, chk_bf, home);
    	signal state, next_state : state_type;
    	constant delay_15ms 	 : integer := 750000;  -- 750000
    	constant delay_4ms 		 : integer := 205000;  -- 205000
    	constant delay_100us 	 : integer := 5000;  -- 5000
    	constant delay_40ns 	 : integer := 1;  -- 1
    	constant delay_240ns 	 : integer := 12; -- 12
    	constant delay_500ns 	 : integer := 100; -- 24 (100?)
    	signal delay_count  	 : unsigned(19 downto 0);
    	signal init_cmd 		 : unsigned(2 downto 0);
    	SUBTYPE ascii IS STD_LOGIC_VECTOR(7 DOWNTO 0);
    	TYPE charArray IS array(1 to 16) OF ascii;
    	CONSTANT line1: charArray := (x"20",x"46",x"50",x"47",x"41",x"20",x"52",x"4F",x"43",x"4B",x"60",x"53",x"20",x"20",x"20",x"20");
    	signal count 			 : integer := 0; --  unsigned(3 downto 0) := "0001";
    	signal check_bf_f		 : std_logic;
    	signal rw_reg			 : std_logic;
    	signal db_in, db_out	 : std_logic_vector (7 downto 0);
    	
    begin
    
    --================================================
    -- outputs
    --================================================
    lcd_on <= '1';
    rw <= rw_reg;
    db <= db_out when rw_reg = '0' else (others => 'Z');  -- write: rw ='0', read: rw = '1' 
    db_in <= db;
    	   
    process (clk, reset, delay_count, init_cmd, state, check_bf_f, db_in)
    begin
    	if reset = '0' then
    		delay_count <= (others => '0');
    		init_cmd <= (others => '0');
    		count <= 0;
    		db_out <= (others => '0');
    		en <= '0';
    		rs <= '0';
    		rw_reg <= '0';
    		state <= init;
    		next_state <= init;
    	elsif clk'event and clk = '1' then
    		delay_count <= delay_count + 1;
    		en <= '0';
    		case state is
    --================================================
    -- power up
    --================================================
    			when init =>
    				check_bf_f <= '0';
    				rs <= '0';
    				rw_reg <= '0';
    				if (delay_count = delay_15ms and init_cmd = "000") then  -- delay_15ms --4
    					delay_count <= (others => '0');
    					check_bf_f <= '1';
    					init_cmd <= init_cmd + 1;
    					db_out <= x"38";
    					state <= en_h;
    					next_state <= init;
    				elsif (delay_count = delay_4ms and init_cmd = "001") then  -- delay_4ms -- 2
    					delay_count <= (others => '0');
    					check_bf_f <= '1';
    					init_cmd <= init_cmd + 1;
    					db_out <= x"38";
    					state <= en_h;
    					next_state <= init;
    				elsif (delay_count = delay_100us and init_cmd = "010") then  -- delay_100us -- 1
    					delay_count <= (others => '0');
    					check_bf_f <= '1';
    					init_cmd <= init_cmd + 1;
    					db_out <= x"38";
    					state <= en_h;
    					next_state <= init;
    				elsif (init_cmd = "011") then		-- start checking busy flag
    					delay_count <= (others => '0');
    					init_cmd <= init_cmd + 1;
    					db_out <= x"38";
    					state <= en_h;
    					next_state <= init;
    				elsif (init_cmd = "100") then  -- DISP OFF
    					delay_count <= (others => '0');
    					init_cmd <= init_cmd + 1;
    					db_out <= x"08";
    					state <= en_h;
    					next_state <= init;
    				elsif (init_cmd = "101") then  -- DISP CLEAR (can take > 1s to execute)
    					delay_count <= (others => '0');
    					init_cmd <= init_cmd + 1;
    					db_out <= x"01";
    					state <= en_h;
    					next_state <= init;
    				elsif (init_cmd = "110") then   -- ENT_MODE_SET
    					delay_count <= (others => '0');
    					db_out <= x"06";
    					state <= en_h;
    					next_state <= disp_on; -- disp_on
    				end if;
    --================================================
    -- commands
    --================================================
    			when disp_on =>
    				delay_count <= (others => '0');
    				rs <= '0';
    				rw_reg <= '0';
    				db_out <= x"0F";
    				state <= en_h;
    				next_state <= wr_ddram;
    				
    			when wr_ddram =>				-- unintended muxes instantiated?
    				delay_count <= (others => '0');
    				rs <= '1';
    				rw_reg <= '0';
    				count <= count + 1;
    				if (count <= 16) then
    					db_out <= line1(count);
    					state <= en_h;
    					next_state <= wr_ddram;
    				else
    					count <= 0;
    					state <= home;
    					next_state <= home;
    				end if;	
    				
    			when clr_disp =>
    				delay_count <= (others => '0');
    				db_out <= x"01";  -- clr disp ~1.58ms, can take > 1s to execute
    				rs <= '0';
    				rw_reg <= '0';
    				state <= en_h;
    				next_state <= home;					
    						
    			when home =>
    				delay_count <= (others => '0');					
    				if (pb = '0') then
    					state <= clr_disp;
    					next_state <= home;
    				elsif (pb = '1') then
    					state <= home;
    					next_state <= home;
    				end if;
    					
    --================================================
    -- enable controller
    --================================================
    			when en_h =>
    				if delay_count < delay_500ns then  -- N = 25 (~500ns period) or (maybe 24)
    					if (delay_count >= delay_40ns and delay_count <= delay_240ns) then	
    						en <= '1';
    						if delay_count = delay_240ns-1 and rw_reg = '1' then
    							if db_in(7) = '0' then
    								check_bf_f <= '1';	
    							else 
    								check_bf_f <= '0';
    							end if;
    						end if;
    					end if;
    				else
    					delay_count <= (others => '0');
    					if check_bf_f = '1' then
    						check_bf_f <= '0';
    						rw_reg <= '0';
    						state <= next_state;
    					else
    						state <= chk_bf;
    					end if;
    				end if;
    				
    --================================================
    -- check busy flag
    --================================================
    			when chk_bf =>
    				delay_count <= (others => '0');
    				rs <= '0';
    				rw_reg <= '1';
    				state <= en_h;
    		end case;
    	end if;
    end process;
    end arch;
    BlackHelicopter, Feb 27, 2011
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. cehon
    Replies:
    1
    Views:
    2,392
    ALuPin@web.de
    Sep 15, 2005
  2. meshoshow
    Replies:
    3
    Views:
    5,531
    Mike Treseler
    Dec 15, 2006
  3. r_spaargaren@hotmail.com

    Program LCD HD44780 with 68HC11 in Handyboard

    r_spaargaren@hotmail.com, Oct 26, 2007, in forum: C Programming
    Replies:
    2
    Views:
    629
    Mark McIntyre
    Oct 27, 2007
  4. vx100miles
    Replies:
    1
    Views:
    1,778
    vx100miles
    Nov 21, 2008
  5. BlackHelicopter
    Replies:
    0
    Views:
    1,098
    BlackHelicopter
    Dec 9, 2010
Loading...

Share This Page