Sie sind auf Seite 1von 22

Interfacing FPGA to LCD 16x2

Problem and Solution

Akhmad Hendriawan
hendri@eepis-its.edu

You are free:


to Share to copy, distribute and transmit the work
Under the following conditions:
Attribution You must attribute the work in the manner specified by the author or
licensor (but not in any way that suggests that they endorse you or your use of the
work).
Noncommercial You may not use this work for commercial purposes.
No Derivative Works You may not alter, transform, or build upon this work.

Block Diagram

Pin Description

Write Timing Diagram

LCD Command

LCD initialize Procedure from Datasheet

Implement to FPGA

NET "en" LOC = P62;


NET "dataLCD<0>" LOC = P72;
NET "dataLCD<1>" LOC = P73;
NET "dataLCD<2>" LOC = P83;
NET "dataLCD<3>" LOC = P84;
NET "rs" LOC = p61;
NET "clock" LOC = P43;
NET "reset" LOC = P44;

Recommendate Data sheet


Init LCD

Behaviour Simulation

Post Route Simulation

It shown that thereis many unknown data that differ from behaviour simulation

Post route Simulation

Unknown Condition

My testbench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

-- Instantiate the Unit Under Test (UUT)


uut: LCDTest PORT MAP (

-- Uncomment the following library declaration if using

dataLCD => dataLCD,

-- arithmetic functions with Signed or Unsigned values

en => en,

--USE ieee.numeric_std.ALL;

rs => rs,
ENTITY LCDTestBench IS

reset => reset,

END LCDTestBench;

clock => clock


);

ARCHITECTURE behavior OF LCDTestBench IS

-- Clock process definitions

-- Component Declaration for the Unit Under Test (UUT)

clock_process :process
COMPONENT LCDTest
PORT(
dataLCD : OUT std_logic_vector(3 downto 0);
en : OUT std_logic;
rs : OUT std_logic;
reset : IN std_logic;

begin
clock <= '0';
wait for clock_period/2;
clock <= '1';
wait for clock_period/2;
end process;

clock : IN std_logic
);
END COMPONENT;

-- Stimulus process
stim_proc: process

--Inputs

begin

signal reset : std_logic := '0';

-- hold reset state for 100 ns.

signal clock : std_logic := '0';

--

wait for 100 ns;

--

wait for clock_period*10;

--Outputs
signal dataLCD : std_logic_vector(3 downto 0);
signal en : std_logic;
signal rs : std_logic;

-- insert stimulus here

-- Clock period definitions


constant clock_period : time := 83.3 ns;
BEGIN

--

wait;
wait for 500ns;

reset <= '1';


end process;
END;

Onother approach(succeed)

Using 8 bit Data-line(pin) instead


of 4 bit
ROM based model. Before that I
used State machine model.

LCD Initializations
8 bit instead of 4 bit

TestBench Simulation

Test with Logic Analyzer

Testing LCD controller with logic analyzer I've got good Result

OK

VHDL
library IEEE;

begin

use IEEE.STD_LOGIC_1164.ALL;

PSC : process(clk)

use IEEE.std_logic_unsigned.all;

variable prescaller : integer range 0 to 60000 := 0;


begin

-- Uncomment the following library declaration if using

if (clk'event and clk = '1') then

-- arithmetic functions with Signed or Unsigned values

if prescaller < 60000 then

--use IEEE.NUMERIC_STD.ALL;

prescaller := prescaller + 1;
else

-- Uncomment the following library declaration if instantiating

prescaller := 0;

-- any Xilinx primitives in this code.

pscOut

library UNISIM;

end if;

use UNISIM.VComponents.all;

end if;

<= not pscOut;

end process PSC;


entity ROM is
Port(dataOut : out STD_LOGIC_VECTOR(7 downto 0);

BUFG_inst : BUFG

reset : in std_logic;

port map(

Rs

: out STD_LOGIC;

O => pscClk,

En

: out STD_LOGIC;

I => pscOut

clk

: in STD_LOGIC);

);

-- Clock buffer output


-- Clock buffer input

end ROM;
MYCNT : process(pscClk,reset)
architecture Behavioral of ROM is

begin

signal cntOut : integer := 0;

if (pscClk'event and pscClk = '1') then

signal pscOut : std_logic

:= '0';

if (reset = '0') then

signal pscClk : std_logic

:= '0';

cntOut <= 0;

elsif (cntOut /= 22) then


cntOut <= cntOut + 1;

when 11 => --display clear

end if;

En<='1'; Rs <= '0'; dataOut <= "00000001";

end if;
end process MYCNT;

when 12 => --display clear


En<='0'; Rs <= '0'; dataOut <= "00000001";

ROM : process(pscClk, cntOut)


begin

when 13 => --entry mode

if (pscClk'event and pscClk = '1') then

En<='1'; Rs <= '0'; dataOut <= "00000110";

case cntOut is
when 0 => --delay

when 14 => --entry mode

En<='1'; Rs <= '0'; dataOut <= "00110000";

En<='0'; Rs <= '0'; dataOut <= "00000110";

when 1 => --function set 1

when 15 => --display on

En<='1'; Rs <= '0'; dataOut <= "00110000";

En<='1'; Rs <= '0'; dataOut <= "00001110";

when 2 => --function set 1

when 16 => --display on

En<='0'; Rs <= '0'; dataOut <= "00110000";

En<='0'; Rs <= '0'; dataOut <= "00001110";

when 3 => --function set 1


En<='1'; Rs <= '0'; dataOut <= "00110000";

when 17 => -- 'O'

when 4 => --function set 1

En<='1'; Rs <= '1'; dataOut <= "01001111";

En<='0'; Rs <= '0'; dataOut <= "00110000";

when 18 => -- 'O'

when 5 => --function set 1

En<='0'; Rs <= '1'; dataOut <= "01001111";

En<='1'; Rs <= '0'; dataOut <= "00110000";


when 6 => --function set 1

when 19 => -- 'K'

En<='0'; Rs <= '0'; dataOut <= "00110000";

En<='1'; Rs <= '1'; dataOut <= "01001011";

when 7 => --function set 8 bit


En<='1'; Rs <= '0'; dataOut <= "00111001";

when 20 => -- 'K'


En<='0'; Rs <= '1'; dataOut <= "01001011";

when 8 => --function set 8 bit


En<='0'; Rs <= '0'; dataOut <= "00111001";

when others =>


dataOut <= "00000000";

when 9 => --display off


En<='1'; Rs <= '0'; dataOut <= "00001000";
when 10 => --display off
En<='0'; Rs <= '0'; dataOut <= "00001000";

end case;
end if;
end process ROM;
end Behavioral;

elsif (cntOut /= 22) then


cntOut <= cntOut + 1;

when 11 => --display clear

end if;

En<='1'; Rs <= '0'; dataOut <= "00000001";

end if;
end process MYCNT;

when 12 => --display clear


En<='0'; Rs <= '0'; dataOut <= "00000001";

ROM : process(pscClk, cntOut)


begin
if (pscClk'event and pscClk = '1') then
case cntOut is

when 13 => --entry mode


En<='1'; Rs <= '0'; dataOut <= "00000110";

when 0 => --delay

when 14 => --entry mode

En<='1'; Rs <= '0'; dataOut <= "00110000";

En<='0'; Rs <= '0'; dataOut <= "00000110";

when 1 => --function set 1

when 15 => --display on

En<='1'; Rs <= '0'; dataOut <= "00110000";

En<='1'; Rs <= '0'; dataOut <= "00001110";

when 2 => --function set 1


En<='0'; Rs <= '0'; dataOut <= "00110000";

when 16 => --display on


En<='0'; Rs <= '0'; dataOut <= "00001110";

when 3 => --function set 1


En<='1'; Rs <= '0'; dataOut <= "00110000";
when 4 => --function set 1
En<='0'; Rs <= '0'; dataOut <= "00110000";
when 5 => --function set 1

when 17 => -- 'O'


En<='1'; Rs <= '1'; dataOut <= "01001111";
when 18 => -- 'O'
En<='0'; Rs <= '1'; dataOut <= "01001111";

En<='1'; Rs <= '0'; dataOut <= "00110000";


when 6 => --function set 1
En<='0'; Rs <= '0'; dataOut <= "00110000";

when 19 => -- 'K'


En<='1'; Rs <= '1'; dataOut <= "01001011";

when 7 => --function set 8 bit

when 20 => -- 'K'

En<='1'; Rs <= '0'; dataOut <= "00111001";

En<='0'; Rs <= '1'; dataOut <= "01001011";

when 8 => --function set 8 bit


En<='0'; Rs <= '0'; dataOut <= "00111001";

when others =>

when 9 => --display off

dataOut <= "00000000";

En<='1'; Rs <= '0'; dataOut <= "00001000";

end case;

when 10 => --display off

end if;

En<='0'; Rs <= '0'; dataOut <= "00001000";

end process ROM;


end Behavioral;

Das könnte Ihnen auch gefallen