The Ring programming language version 1.3 book - Part 59 of 88
FPGA Tutorial - LCD Interface
1. Interfacing FPGA to LCD 16x2
Problem and Solution
Akhmad Hendriawan
hendri@eepis-its.edu
2. 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.
9. 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;
14. 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
--USE ieee.numeric_std.ALL; en => en,
rs => rs,
ENTITY LCDTestBench IS reset => reset,
END LCDTestBench; clock => clock
);
ARCHITECTURE behavior OF LCDTestBench IS
-- Component Declaration for the Unit Under Test (UUT) -- Clock process definitions
clock_process :process
COMPONENT LCDTest begin
PORT( clock <= '0';
dataLCD : OUT std_logic_vector(3 downto 0);
wait for clock_period/2;
en : OUT std_logic;
clock <= '1';
rs : OUT std_logic;
reset : IN std_logic; wait for clock_period/2;
clock : IN std_logic end process;
);
END COMPONENT;
-- Stimulus process
stim_proc: process
--Inputs
signal reset : std_logic := '0'; begin
signal clock : std_logic := '0'; -- hold reset state for 100 ns.
-- wait for 100 ns;
--Outputs
signal dataLCD : std_logic_vector(3 downto 0);
-- wait for clock_period*10;
signal en : std_logic;
signal rs : std_logic;
-- insert stimulus here
-- Clock period definitions
constant clock_period : time := 83.3 ns; -- wait;
wait for 500ns;
BEGIN
reset <= '1';
end process;
END;
15. Onother approach(succeed)
● Using 8 bit Data-line(pin) instead
of 4 bit
● ROM based model. Before that I
used State machine model.
20. 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 <= not pscOut;
library UNISIM; end if;
use UNISIM.VComponents.all; end if;
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, -- Clock buffer output
En : out STD_LOGIC; I => pscOut -- Clock buffer input
clk : in STD_LOGIC); );
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;
21. elsif (cntOut /= 22) then
cntOut <= cntOut + 1; when 11 => --display clear
end if; En<='1'; Rs <= '0'; dataOut <= "00000001";
end if;
when 12 => --display clear
end process MYCNT;
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 14 => --entry mode
when 0 => --delay
En<='0'; Rs <= '0'; dataOut <= "00000110";
En<='1'; Rs <= '0'; dataOut <= "00110000";
when 15 => --display on
when 1 => --function set 1
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
when 17 => -- 'O'
En<='1'; Rs <= '0'; dataOut <= "00110000";
when 4 => --function set 1
En<='1'; Rs <= '1'; dataOut <= "01001111";
En<='0'; Rs <= '0'; dataOut <= "00110000"; when 18 => -- 'O'
En<='0'; Rs <= '1'; dataOut <= "01001111";
when 5 => --function set 1
En<='1'; Rs <= '0'; dataOut <= "00110000";
when 19 => -- 'K'
when 6 => --function set 1
En<='1'; Rs <= '1'; dataOut <= "01001011";
En<='0'; Rs <= '0'; dataOut <= "00110000";
when 20 => -- 'K'
when 7 => --function set 8 bit En<='0'; Rs <= '1'; dataOut <= "01001011";
En<='1'; Rs <= '0'; dataOut <= "00111001";
when 8 => --function set 8 bit when others =>
En<='0'; Rs <= '0'; dataOut <= "00111001";
dataOut <= "00000000";
end case;
when 9 => --display off
En<='1'; Rs <= '0'; dataOut <= "00001000"; end if;
when 10 => --display off end process ROM;
En<='0'; Rs <= '0'; dataOut <= "00001000";
end Behavioral;
22. elsif (cntOut /= 22) then
cntOut <= cntOut + 1; when 11 => --display clear
end if; En<='1'; Rs <= '0'; dataOut <= "00000001";
end if;
when 12 => --display clear
end process MYCNT;
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 14 => --entry mode
when 0 => --delay
En<='0'; Rs <= '0'; dataOut <= "00000110";
En<='1'; Rs <= '0'; dataOut <= "00110000";
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
when 17 => -- 'O'
En<='1'; Rs <= '0'; dataOut <= "00110000";
when 4 => --function set 1 En<='1'; Rs <= '1'; dataOut <= "01001111";
En<='0'; Rs <= '0'; dataOut <= "00110000"; when 18 => -- 'O'
En<='0'; Rs <= '1'; dataOut <= "01001111";
when 5 => --function set 1
En<='1'; Rs <= '0'; dataOut <= "00110000";
when 19 => -- 'K'
when 6 => --function set 1
En<='1'; Rs <= '1'; dataOut <= "01001011";
En<='0'; Rs <= '0'; dataOut <= "00110000";
when 20 => -- 'K'
when 7 => --function set 8 bit En<='0'; Rs <= '1'; dataOut <= "01001011";
En<='1'; Rs <= '0'; dataOut <= "00111001";
when 8 => --function set 8 bit
when others =>
En<='0'; Rs <= '0'; dataOut <= "00111001";
dataOut <= "00000000";
when 9 => --display off end case;
En<='1'; Rs <= '0'; dataOut <= "00001000"; end if;
when 10 => --display off end process ROM;
En<='0'; Rs <= '0'; dataOut <= "00001000";
end Behavioral;