- Joined
- Jun 2, 2010
- Messages
- 14
- Reaction score
- 0
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!
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;