[SOLVED] Need help for driving an 16x2 lcd

Status
Not open for further replies.

gv260ea

Newbie level 3
Joined
Jun 27, 2013
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
29
Couple of days ago i got an Xilinx Spartan 3E Starter board. I thought it would be a good board to start with FPGAS:grin:. I did couple of examples without copying the code as I want to learn vhdl and not to copy. Then i wanted to write the character H to the on board 16x2 lcd display. I screwed around for a whole day and. I got nothing:-?. Could someone figure out what's wrong with this code and what sould be fixed. Other than beeing untidy.
Here is the code. Thank you for helping me.
Code:
----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    11:00:06 06/27/2013 
-- Design Name: 
-- Module Name:    LCD - Behavioral 
-- 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 LCDS is
	port(
	   CLK : in STD_LOGIC;
		LCD_E : out STD_LOGIC := '0';
		LCD_RS : out STD_LOGIC := '0';
		LCD_RW : out STD_LOGIC := '0';
		SF_D : out STD_LOGIC_VECTOR(11 downto 8) := "0000"
			);
end LCDS;

architecture Behavioral of LCDS is
	type Init is (W413, W2003, W43,W42,Done);
	type Conf is(FS40,EMS,DOF,DOF2,DOF3,Done);
	type LCD is (Writing,Ready);
	type PDelay is (US1,US200,MS5,none);
	type Chars is (H,Done);
	signal Chars_s : Chars := H;
	signal PDelay_s : PDelay := none ;
	signal Init_s : Init := W413 ;
	signal Conf_s : Conf := FS40 ;
	signal LCD_s : LCD := Writing ;
	signal Counter : STD_LOGIC_VECTOR(26 downto 0);
	signal PCounter : STD_LOGIC_VECTOR(1 downto 0);
	begin
		Display : Process (CLK)			
			begin
			if rising_edge(CLK) then
				if PDelay_s = none then
					Counter <= (others => '0');				
					if not(init_s = Done) then
						Case Init_s is
							when W413 =>
							LCD_RS <= '0';
							SF_D <= X"3";
							PDelay_s <= MS5;
							Init_s <= W2003;
							when W2003 =>
							SF_D <= "0000";
							PDelay_s <= US200;						
							Init_s <= W43;
							SF_D <= X"3";
							when W43 => 
							SF_D <= "0000";
							PDelay_s <= US200;						
							Init_s <= W42;
							SF_D <= X"3";
							when W42 =>
							SF_D <= "0000";
							PDelay_s <= US200;						
							Init_s <= Done;
							SF_D <= X"2";
							when others => NULL;
						End Case;		
					End if;
					if not(Conf_s = Done) then
						Case Conf_s is
							when FS40 => 		
							if PCounter = "00" then
							LCD_E <= '0';
							LCD_RS <= '0';
							SF_D <= X"8";
							LCD_E <= '1';
							PDelay_s <= US1;
							PCounter <= "01";
							elsif PCounter = "01"then
							LCD_E <= '0';
							PDelay_s <= MS5;
							PCounter <= "10";
							elsif PCounter = "10" then
							SF_D <= X"2";
							PDelay_s <= US1;
							PCounter <= "11";
							elsif PCounter = "11" then
							LCD_E <= '0';
							PCounter <= "00";
							PDelay_s <= MS5;
							Conf_s <= EMS;
							End if;
							when EMS =>
							if PCounter = "00" then
							LCD_E <= '0';
							LCD_RS <= '0';
							SF_D <= X"8";
							LCD_E <= '1';
							PDelay_s <= US1;
							PCounter <= "01";
							elsif PCounter = "01"then
							LCD_E <= '0';
							PDelay_s <= MS5;
							PCounter <= "10";
							elsif PCounter = "10" then
							SF_D <= X"0";
							PDelay_s <= US1;
							PCounter <= "11";
							elsif PCounter = "11" then
							LCD_E <= '0';
							PCounter <= "00";
							PDelay_s <= MS5;
							Conf_s <= DOF;
							End if;
							-------
							when DOF =>
							if PCounter = "00" then
							LCD_E <= '0';
							LCD_RS <= '0';
							SF_D <= X"1";
							LCD_E <= '1';
							PDelay_s <= US1;
							PCounter <= "01";
							elsif PCounter = "01"then
							LCD_E <= '0';
							PDelay_s <= MS5;
							PCounter <= "10";
							elsif PCounter = "10" then
							SF_D <= X"0";
							PDelay_s <= US1;
							PCounter <= "11";
							elsif PCounter = "11" then
							LCD_E <= '0';
							PCounter <= "00";
							PDelay_s <= MS5;
							Conf_s <= DOF2;
							End if;
							-----
							when DOF2 =>
							if PCounter = "00" then
							LCD_E <= '0';
							LCD_RS <= '0';
							SF_D <= X"6";
							LCD_E <= '1';
							PDelay_s <= US1;
							PCounter <= "01";
							elsif PCounter = "01"then
							LCD_E <= '0';
							PDelay_s <= MS5;
							PCounter <= "10";
							elsif PCounter = "10" then
							SF_D <= X"0";
							PDelay_s <= US1;
							PCounter <= "11";
							elsif PCounter = "11" then
							LCD_E <= '0';
							PCounter <= "00";
							PDelay_s <= MS5;
							Conf_s <= DOF3;
							End if;
							-------
							when DOF3 =>
							if PCounter = "00" then
							LCD_E <= '0';
							LCD_RS <= '0';
							SF_D <= X"C";
							LCD_E <= '1';
							PDelay_s <= US1;
							PCounter <= "01";
							elsif PCounter = "01"then
							LCD_E <= '0';
							PDelay_s <= MS5;
							PCounter <= "10";
							elsif PCounter = "10" then
							SF_D <= X"0";
							PDelay_s <= US1;
							PCounter <= "11";
							elsif PCounter = "11" then
							LCD_E <= '0';
							PCounter <= "00";
							PDelay_s <= MS5;
							Conf_s <= Done;
							End if;
							when others => NULL;							
							End Case; 
							End if;
						if LCD_s =  Writing then
						  Case Chars_s is
						   when H =>
							if PCounter = "00" then
							LCD_E <= '0';
							LCD_RS <= '0';
							SF_D <= X"3";
							LCD_E <= '1';
							PDelay_s <= US1;
							PCounter <= "01";
							elsif PCounter = "01"then
							LCD_E <= '0';
							PDelay_s <= US200;
							PCounter <= "10";
							elsif PCounter = "10" then
							SF_D <= X"2";
							PDelay_s <= US1;
							PCounter <= "11";
							elsif PCounter = "11" then
							LCD_E <= '0';
							PCounter <= "00";
							PDelay_s <= US200;
							LCD_s <= Ready;
							End if;
							When others => NULL;
							End Case;
							End if;
				 else
					Case PDelay_s is 
						When US1 =>
						 if Counter < "110010" then
							Counter <= Counter + 1;
						 else 
						 Counter <= (others => '0');
						  PDelay_s <= none;
						 End if;
						 When US200 =>
						 if Counter < "1111101000" then
							Counter <= Counter + 1;
						 else 
						 Counter <= (others => '0');
						  PDelay_s <= none;
						 End if;
						 When MS5 =>
						 if Counter < "111101000010010000" then
							Counter <= Counter + 1;
						 else 
						 Counter <= (others => '0');
						  PDelay_s <= none;
						 End if;
						 
						 
						 when others => NULL;
					 End Case;	 
				 End if;
			End if;
			
			
		End Process;
		LCD_RW <= '0';
end Behavioral;
 

A silly idea regarding a solution outside of the predefined box you have worked yourself into.

1 - add a simple MCU to the system
2 - use ChibiOS/GFX to handle all your hd44780 fun (it's bound to be a hd44780, right )
3 - implement a simple SPI statemachine to send high level commands to your mcu.
4 - profit
5 - stand amazed how easy that was, and how low the development cost of the working system is.
6 - goto 4

Personally I do exactly this with an stm32, but chibios is available for quite a few mcu's. Hell, if you insist on MUST HAVE FPGA ONLY! @_@ then you can also run it on a NIOS II softcore for example.
 

I know this sounds idiotic but i still need it my way as my misson is to learn vhdl.
 

Then you also should learn when to use HDL and when to use something else.

An lcd like that with a lot of relatively slow sequential control is a far better match to something like an mcu. Not that it's impossible to do in HDL, far from it. Just a poor allocation of resources (aka your development time).

But feel free to learn vhdl through a hammer shaped nail detector.
 

I noticed that the board also has a CoolRunner II Cpld. Should i use it for driving the lcd.
 

If you insist on using the fpga, then the next most sensible use of time is to use a microblaze or picoblaze core. That way you can program your lcd control in C or asm. And if you don't like that either, grab a piece of paper and start drawing that statemachine. If that is out as well I suggest a change of career. Strawberry farmer in a nice climate always appeals to me when I've had it with this electronics stuff.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…