Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Need help debuging - VHDL and 2x16 LCD

Status
Not open for further replies.

is41985

Newbie level 2
Joined
Dec 29, 2009
Messages
2
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,283
Activity points
1,299
Hi,
for the past few days I've been playing around with a Spartan 3-AN Starter Kit Board. I'm interested in learning as much as I can, but now I'm stuck, and need a fresh pair of eyes to look over my code, and correct me where I made a mistake...

I'm trying to initialize and write something to the 2x16 LCD display that comes on the board (S6A0069), and have been following the instructions found in the board's datasheet (can't post a link to the datasheet because edaboard won't let me yet, but: chapter 5, page 43).

Below is my code. When the FPGA is configured, there is nothing on the screen, but when I simulate the design using Multisim, all changes happen in timely manner. LED's are used for debugging purposes only. This is the second design I've created, the first was done using a state machine, with the same result. I'm guessing that this might be a hardware thing (rising/falling time)? The display is working properly, tested it with the design that comes preconfigured from Xilinx.

This might not be the best way of coding, but I'm pretty new at this, so all suggestions are welcome :)

Code:
----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    13:27:19 09/03/2010 
-- Design Name: 
-- Module Name:    lcdDriver
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity lcdDriver is
    Port ( clk : in  STD_LOGIC;
	reset: in STD_LOGIC;
           led : out  STD_LOGIC_VECTOR (7 downto 0);
           lcdDB : inout  STD_LOGIC_VECTOR (7 downto 0);
           lcdE : out  STD_LOGIC;
           lcdRS : out  STD_LOGIC;
           lcdRW : out  STD_LOGIC);
end lcdDriver;

architecture RTL of lcdDriver is
	signal clkPeriods: STD_LOGIC_VECTOR (31 downto 0) := X"00000000";
	signal usClock: STD_LOGIC := '0';

	signal delayCount: STD_LOGIC_VECTOR(31 downto 0) := X"0000_0000";
	signal delayOK: STD_LOGIC := '0';

	signal ledStateDisplay: STD_LOGIC_VECTOR(5 downto 0) := "000000";

	type lcdCommandType is array(integer range <>) of STD_LOGIC_VECTOR(10 downto 0);
	type delayListType is array(integer range <>) of STD_LOGIC_VECTOR(31 downto 0);
	
	constant delayListInit: delayListType := (	0	=>	X"000B_71B0",			-- Wait for 15ms or longer (750000 clock cycles 50MHz = X"000B_71B0")
																1	=> X"0000_000C",			--	Write for 12 clock cycles (X"0000_000C")
																2	=>	X"0003_20C8",			-- Wait for 4.1ms or longer (205000 clock cycles = X"0003_20C8")
																3	=>	X"0000_000C",			--	Write for 12 clock cycles (X"0000_000C")
																4	=>	X"0000_1388",			-- Wait for 100us or longer (5000 clock cycles = X"0000_1388")
																5	=>	X"0000_000C",			--	Write for 12 clock cycles (X"0000_000C")
																6	=>	X"0000_07D0",			-- Wait for 40us or longer (2000 clock cycles = X"0000_07D0")
																7	=>	X"0000_000C",			--	Write for 12 clock cycles (X"0000_000C")
																8	=>	X"0000_07D0",			-- Wait for 40us or longer (2000 clock cycles = X"0000_07D0")
																
																9	=>	X"0000_07D0",			-- Function Set delay (40us)
																10	=>	X"0000_07D0",			--	Entry Mode delay (40us)
																11	=>	X"0000_07D0",			-- Display On/Off delay (40us);
																12	=>	X"0000_C350",			-- Clear Display delay (82us - 1.64ms, 1ms chosen)
																13	=>	X"0001_4050",			-- Allow at least 1.64ms after issuing Clear Display command (82000 clock cycles = X"0001_4050")
																14	=>	X"0000_1388",			-- Return home for 40us - 1.6ms (80us = 5000 clock cycles = X"0000_1388")
																
																15	=>	X"0000_07D0",			-- Set DD RAM delay (40us)
																
																16	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																17	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																18	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																19	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																20	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																21	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																22	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																23	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																24	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																25	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																26	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																27	=>	X"0000_07D0",			--	Write Data to DD RAM delay (40us)
																
																28	=>	X"0000_07D0"			-- NOP delay (something I just put there, used for the last command)
																);

	constant lcdCommandListInit: lcdCommandType := (	0	=>	"000"&X"00",			-- Wait 15ms or longer
																		1	=> "100"&X"30",			-- Write LCD_DB<7:4> = 0x3, and pulse LCD_E High for 12 clock cycles
																		2	=>	"000"&X"00",			-- Wait 4.1ms or longer
																		3	=>	"100"&X"30",			-- Write LCD_DB<7:4> = 0x3, and pulse LCD_E High for 12 clock cycles
																		4	=>	"000"&X"00",			-- Wait 100us or longer
																		5	=>	"100"&X"30",			-- Write LCD_DB<7:4> = 0x3, and pulse LCD_E High for 12 clock cycles
																		6	=>	"000"&X"00",			-- Wait 40us or longer
																		7	=>	"100"&X"20",			-- Write LCD_DB<7:4> = 0x3, and pulse LCD_E High for 12 clock cycles
																		8	=>	"000"&X"00",			-- Wait 40us or longer
																		
																		9	=>	"100"&X"28",			-- Function Set
																		10	=>	"100"&X"06",			-- Entry Mode Set
																		11	=>	"100"&X"0F",			-- Display On/Off
																		12	=>	"100"&X"01",			--	Clear Display
																		13	=> "000"&X"00",			-- Nothing
																		14	=>	"100"&X"02",			-- Return Home (cursor)
																		
																		15	=>	"100"&X"80",			-- Set DD RAM Address, address is equal to 0
																		
																		16	=>	"110"&X"48",			-- Write Data to DD RAM (letter H)
																		17	=>	"110"&X"65",			-- Write Data to DD RAM (letter e)
																		18	=>	"110"&X"6C",			-- Write Data to DD RAM (letter l)
																		19	=>	"110"&X"6C",			-- Write Data to DD RAM (letter l)
																		20	=>	"110"&X"6F",			-- Write Data to DD RAM (letter o)
																		21	=>	"110"&X"20",			-- Write Data to DD RAM (letter ' ')
																		22	=>	"110"&X"77",			-- Write Data to DD RAM (letter w)
																		23	=>	"110"&X"6F",			-- Write Data to DD RAM (letter o)
																		24	=>	"110"&X"72",			-- Write Data to DD RAM (letter r)
																		25	=>	"110"&X"6C",			-- Write Data to DD RAM (letter l)
																		26	=>	"110"&X"64",			-- Write Data to DD RAM (letter d)
																		27	=>	"110"&X"21",			-- Write Data to DD RAM (letter !)
																		
																		28	=>	"000"&X"00"			-- NOP operation (something I just put there, used for the last command)
																		);

	signal commandPointer: integer range 0 to (delayListInit'HIGH + 1) := 0;
	
begin

	led(5 downto 0) <= ledStateDisplay;
	led(7) <= '1';
	led(6) <= '0';
	
	-- delay counter
	process(clk)
	begin
		if (rising_edge(clk)) then
			if (reset = '1') then
				delayCount <= X"0000_0000";
			else
				if (delayOK = '1') then
					delayCount <= X"0000_0000";
				else
					delayCount <= delayCount + X"0000_0001";
				end if;
			end if;
		end if;
	end process;
	
	-- the delayOK variable should only be equal to '1' if current delayCount is equal to the desired delay
	delayOK <= '1' when (delayCount >= (delayListInit(commandPointer)-1))
						else '0';

	-- go through all commands (incrementing the command pointer when a delay related to that command has elapsed)
	process(clk, delayOK)
	begin
		if (rising_edge(clk)) then
			if (reset = '1') then
				commandPointer <= 0;
			else
				if (delayOK = '1') then
--					commandPointer <= nextCommand;
					if (commandPointer < delayListInit'HIGH) then
						commandPointer <= commandPointer + 1;
					end if;
				end if;
			end if;
		end if;
	end process;
	
	-- execute current command
	lcdRS <= lcdCommandListInit(commandPointer)(9);
	lcdRW <= lcdCommandListInit(commandPointer)(8);
	lcdDB <= lcdCommandListInit(commandPointer)(7 downto 0);
	lcdE	<= lcdCommandListInit(commandPointer)(10);

	ledStateDisplay <= conv_std_logic_vector(commandPointer, 6);
	
end RTL;
 

Solved!

Turns out that the LCD_E signal should be driven high one clock cycle before and one clock cycle after setting up the data lines. In that period, it should be equal to '0'. Also, I've prolonged some of the wait periods. Will put the working code in case anyone else ever needs it, as soon as I clean it up a bit.


ivan
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top