Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > Timing problem with HD44780 LCD controller on FPGA using VHDL

Reply
Thread Tools

Timing problem with HD44780 LCD controller on FPGA using VHDL

 
 
BlackHelicopter BlackHelicopter is offline
Junior Member
Join Date: Jun 2010
Posts: 14
 
      02-27-2011
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;
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
FPGA BOARD FOR NEWBIE TO FPGA TheRightInfo VHDL 1 02-02-2011 11:19 AM
VHDL to Control HD44780 (want to read busy flag) BlackHelicopter VHDL 0 12-09-2010 05:52 AM
FPGA Central eNewsletter - LinkedIn, Write Articles, Post FREE Jobs,FPGA for Mobiles Vikram VHDL 0 07-24-2008 07:37 PM
Program LCD HD44780 with 68HC11 in Handyboard r_spaargaren@hotmail.com C Programming 2 10-27-2007 05:04 PM
Lcd Block Diagram - Vhdl - On Fpga.. help! meshoshow VHDL 3 12-15-2006 09:55 PM



Advertisments