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.

VHDL LCD Display - Simulation error using Xilinx ISE

Status
Not open for further replies.

Peter_L

Junior Member level 1
Joined
Apr 20, 2007
Messages
15
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,406
vhdl lcd module ascii

Hello All,

I currently have a Spartan3A DDR2 development kit. I am trying to create VHDL code to turn on a single LED from LED(0) to LED(8) and display a message to the LCD screen everytime a combination of switches are toggled switch(0) to switch(2). I am using multiple process's, but I keep getting an error when I simulate. I have tried many ways to get rid of this error, but nothign ahs worked. I hope that someone can help! Attached is a picture of simulation error and VHDL code.

Code:
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 instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity decoder is
   Port ( sel : in  STD_LOGIC_VECTOR (2 downto 0); -- selector switch used to toggle LED
			 y : out  STD_LOGIC_VECTOR (7 downto 0); -- output to 8 LEDs
			 LCD_DB : inout std_logic_vector (7 downto 0):="00000000";
			 LCD_RWS : inout std_logic_vector (1 downto 0):="00";
			 LCD_E : out STD_LOGIC:= '0');
end decoder;
---------------------------------------------------------------------------------------------------

architecture Behavioral of decoder is
	signal lcd_clr_s, lcd_e_disable_s: std_logic:='0';
begin

	
	decoder: process (sel)
	begin
		case sel is
			when "000" => y <= "00000001";
			when "001" => y <= "00000010";
			when "010" => y <= "00000100";
			when "011" => y <= "00001000";
			when "100" => y <= "00010000";
			when "101" => y <= "00100000";
			when "110" => y <= "01000000";
			when others => y <= "10000000";
		end case;
		lcd_clr_s <= not lcd_clr_s;
	end process decoder;
--------------------------------------------

	lcd_clr: process (lcd_clr_s)
	begin
		lcd_rws <= "00";				--Clear LCD Display
		lcd_e <= '1';
		lcd_db <= "00000001";
		
		lcd_e_disable_s <= not lcd_e_disable_s;
	end process lcd_clr;
--------------------------------------------------	
	lcd_e_disable: process (lcd_e_disable_s)
	begin 
	
		lcd_e <= '0';
		lcd_db <="00000000";
		
	end process lcd_e_disable;
	
end architecture behavioral;
 

lcd display simulator

Your screen image looks very familiar. Are you still trying to solve the uninitialized 'X' state?


You haven't shown enough code to reproduce the simulation, or enough simulation trace to see why the two signals changed to 'X'. I'm guessing the culprit is in a higher level module or the test bench.
 

design stopwatch using xilinx

Hi Echo, I'm still trying to solve my problem. I took your advice and assigned initial values in my vhdl code for the behavior of my fpga, but that did not solve the problem. I will attach the testbench code that the Xilinx ISE generated. Please let me know if you see anything wrong.

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_TEXTIO.ALL;
USE STD.TEXTIO.ALL;

ENTITY decoder_tb2 IS
END decoder_tb2;

ARCHITECTURE testbench_arch OF decoder_tb2 IS
    FILE RESULTS: TEXT OPEN WRITE_MODE IS "results.txt";

    COMPONENT decoder
        PORT (
            sel : In std_logic_vector (2 DownTo 0);
            y : Out std_logic_vector (7 DownTo 0);
            LCD_DB : InOut std_logic_vector (7 DownTo 0);
            LCD_RWS : InOut std_logic_vector (1 DownTo 0);
            LCD_E : Out std_logic
        );
    END COMPONENT;

    SIGNAL sel : std_logic_vector (2 DownTo 0) := "000";
    SIGNAL y : std_logic_vector (7 DownTo 0) := "00000000";
    SIGNAL LCD_DB : std_logic_vector (7 DownTo 0) := "ZZZZZZZZ";
    SIGNAL LCD_RWS : std_logic_vector (1 DownTo 0) := "ZZ";
    SIGNAL LCD_E : std_logic := '0';

    BEGIN
        UUT : decoder
        PORT MAP (
            sel => sel,
            y => y,
            LCD_DB => LCD_DB,
            LCD_RWS => LCD_RWS,
            LCD_E => LCD_E
        );

        PROCESS
            BEGIN
                -- -------------  Current Time:  600ns
                WAIT FOR 600 ns;
                sel <= "001";
                -- -------------------------------------
                -- -------------  Current Time:  1200ns
                WAIT FOR 600 ns;
                sel <= "011";
                -- -------------------------------------
                -- -------------  Current Time:  1300ns
                WAIT FOR 100 ns;
                sel <= "010";
                -- -------------------------------------
                WAIT FOR 1700 ns;

            END PROCESS;

    END testbench_arch;
 

xilinx i/o delays vhdl

I can now reproduce the problem. I'm not very good at VHDL, but I think I see the culprit . . .

Signals lcd_clr_s and lcd_e_disable_s change simultaneously, so the two processes are simultaneously trying to update lcd_e and lcd_db with unequal values. The result of the conflict is 'X', the unknown state.

I can't suggest a good solution, because I don't know how those various signals need to behave in your application. Maybe someone else is familiar with your LCD timing.
 

lcd driver open source vhdl

Thanks again Echo for your reply, i definately appreciate your help.

What you are saying makes sense, but I have designed the processes so that each is run sequentially. Why are both "lcd_clr" and "lcd_e_disable" processes being run simultaniously? Does this happen during the first run when signals "lcd_clr_s" and "lcd_e_disable_s" are initialized, therefore causing both processes to run simultanioiusly?

If so, how do I get around this problem? Help from anyone with insight to this problem woudl be much appreciated.

Also, I would love to see a sample of VHDL code written to display to a LCD display. My method may not be the most efficient, but this is how i imagine it to work. If anyone has this, please post it here.
 

xilinx lcd vhdl

Hello,

to tell you the truth, I can't imagine, that your method of generating LCD control signals would ever work, neither in simulation nor in synthesizable ccode. The simple thing is: the LCD controller needs a timing and you can't have a timing without a clock that schedules a sequence of control signals.

A usual way would be to have a basic clock, a state machine and a delay counter for states that need to be extended to a interval defined in the datsheet.

I didn't yet use a LCD controller with a FPGA, so I can't give you example code.
Dit you check the forum for similar topics with a solution?

Regards,
Frank
 

open source ddr2 vhdl

I agree with FvM's concerns. The overall asynchronous design seems suspicious, but I guessed that the LCD timing signals may be coming from a not-shown external sequencer through the I/O ports. But if that's not true, then there's no timing for the design to work. The best way to design a project like this is with clocked synchronous logic.

The two processes are triggered by transitions in signals lcd_clr_s and lcd_e_disable_s. Those signals toggle simultaneously (see my ModelSim display), so the two processes run simultaneously.

Some time ago, I wrote a simple crude Verilog (not VHDL) module that displays "Hello World!" on the Lumex LCM-S01602DTR/M LCD that's used on some Xilinx development boards. I don't know if that LCD is similar to your LCD, but maybe my code will help you. It is near the bottom of this very long discussion:
#852813
 

vhdl display

Thanks guys. I was able to find VHDL code written to display to a LCD. I used it as a guide explaining some of concepts echo47 and FVM spoke of previously.

I've attached it here for anyone who is interested.
 

lcd character code xilinx

Thanks to the help from many people on this board, I've almost completed my first FPGA project. One more hurdle and I'm at the finish line.

I have created VHDL code to display to the LCD. I believe that there is a timing issue within my code, but i have checked with two different LCD datasheets and the timing seems to correspond (I am working with the Spartan3A DDR2 Dev kit). Simulation shows that the logic in my code is fine. I've spent a few days trying to fix this problem and tried many things, but I haven't yet been successful, so I am hoping someone here with experience can help me out. Attached is the source code in VHDL.

PS. I have noticed that there is something called f_osc of 250khz within the LCD datasheets. The explanation of f_osc is not very good. Should f_osc be affecting my code any way? If so, can someone explain f_osc?

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

--------------------------------------
entity LED_LCD_Display is
--------------------------------------
   port
   (	
		clk   : in std_logic;									-- 50 Mhz clock signal      
     
-- LCD_Display process used ports
--------------------------------------
		LCD_RWS : inout std_logic_vector (1 downto 0);		-- LCD RWS in/out
		LCD_DB : inout std_logic_vector (7 downto 0);	-- LCD output DB (0 - 7)
		LCD_E : inout std_logic);									-- LCD Enable
end entity LED_LCD_Display;

-----------------------------------------
architecture rtl of LED_LCD_Display is
-----------------------------------------

-- Beginning of "LCD_DISPLAY" Process constants
-----------------------------------------------
	constant delay_40ms: integer:= 8000000; 	-- 40ms delay assuming 50Mhz clokc (> 2000000 for 50Mhz clk)
	constant delay_37us: integer:= 2000000;	-- Wait time of minimum 37us (>1850) assuming 50Mhz Clock
	constant delay_1d52ms: integer:= 2000000;	-- Minimum waith time of 1.52ms (>76000) assuming 50Mhz clock
	constant delay_4d1ms: integer:= 2000000;	-- Wait for more than 4.1ms (> 205000) (after first function set)
	constant delay_tr: integer:= 10;				-- rise time delay for "LCD_E" max of 20ns (> 1 for 50Mhz clk) (OV 2)
	constant delay_tpw: integer:= 100;			-- hold time for "E" to be high min of 230ns (> 12 for 50Mhz clk) (OV 7)
	constant delay_tf: integer:=10;				-- fall time delay for signal "LCD_E" max of 20ns (> 1 for 50Mhz clk)(OV 2)
	constant delay_th: integer:= 2;				-- Data hold time for signal "LCD_db" min of 10ns (= 1 for 50Mhz clk) (OV 1)


--Beginning of "LCD_DISPLAY" Process used variables and Signals
--------------------------------------------------------------
	type State_type is (Boot, FunctionSet, FunctionSetTwo, FunctionSetThree, Display, DisplayClr, EntryModeSet, WriteChar, HomeCursor, EndState);
	signal State : State_type:= Boot;
	signal count_LCD: integer range 0 to delay_40ms:= 0;
	signal count_Char: integer:= 0;													-- counter for displaying characters
	

-- LCD instructions used in "LCD_DISPLAY" process
--------------------------------------------------------------
	constant off_DB: std_logic_vector (7 downto 0):= "00000000";
	constant off_RWs: std_logic_vector (1 downto 0):= "00";
	
	constant functionset_DB: std_logic_vector (7 downto 0):= "00111100";
	constant functionset_RWS: std_logic_vector (1 downto 0):= "00";

	constant Display_DB: std_logic_vector (7 downto 0):= "00001111";
	constant Display_RWS: std_logic_vector (1 downto 0):= "00";
	
	constant DisplayClr_DB: std_logic_vector (7 downto 0):= "00000001";
	constant DisplayClr_RWS: std_logic_vector (1 downto 0):= "00";
	
	constant EntryModeSet_DB: std_logic_vector (7 downto 0):= "00000111";
	constant EntryModeSet_RWS: std_logic_vector (1 downto 0):= "00";
	
	constant HomeCursor_DB: std_logic_vector (7 downto 0):= "00000010";
	constant HomeCursor_RWS: std_logic_vector (1 downto 0):= "00"; 
	
	constant WriteChar_RWS: std_logic_vector (1 downto 0):= "10";
	signal WriteChar_DB: std_logic_vector (7 downto 0):= "00000000";
	
	
begin

	LCD_display: process (clk) 
	
	begin
		if rising_edge(clk) then
	
			case state is
				when Boot =>	-- wait 40ms
					if count_LCD < delay_40ms then
						count_LCD <= count_LCD + 1;
					elsif count_LCD >= delay_40ms then
						State <= FunctionSet;
						count_LCD <= 0;
					end if;
					
			
				when FunctionSet => -- Set function
					lcd_rws <= functionset_rws;
					lcd_db <= functionset_db;
					if count_LCD < delay_37us then
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_37us then
						lcd_e <= '1';
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_37us + delay_tr + delay_tpw then
						lcd_e <= '0';
						count_LCD <= count_LCD + 1;
					elsif count_LCD > delay_37us + delay_tr + delay_tpw + delay_tf + delay_th then
						count_LCD <= 0;
						State <= FunctionSetTwo;
					else
						count_LCD <= count_LCD + 1;
					end if;
					
				when FunctionSetTwo =>			-- Sets Function again
					lcd_rws <= functionset_rws;
					lcd_db <= functionset_db;
					if count_LCD < delay_4d1ms then
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_4d1ms then
						lcd_e <= '1';
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_4d1ms + delay_tr + delay_tpw then
						lcd_e <= '0';
						count_LCD <= count_LCD + 1;
					elsif count_LCD > delay_4d1ms + delay_tr + delay_tpw + delay_tf + delay_th then
						count_LCD <= 0;
						State <= FunctionSetThree;
					else 
						count_LCD <= count_LCD + 1;
					end if;
					
				when FunctionSetThree =>			-- Sets Function again
					lcd_rws <= functionset_rws;
					lcd_db <= functionset_db;
					if count_LCD < delay_4d1ms then
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_4d1ms then
						lcd_e <= '1';
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_4d1ms + delay_tr + delay_tpw then
						lcd_e <= '0';
						count_LCD <= count_LCD + 1;
					elsif count_LCD > delay_4d1ms + delay_tr + delay_tpw + delay_tf + delay_th then
						count_LCD <= 0;
						State <= Display;
					else 
						count_LCD <= count_LCD + 1;
					end if;
				
				when display =>
					lcd_rws <= display_rws;
					lcd_db <= display_db;
					if count_LCD < delay_4d1ms then
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_4d1ms then
						lcd_e <= '1';
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_4d1ms + delay_tr + delay_tpw then
						lcd_e <= '0';
						count_LCD <= count_LCD + 1;
					elsif count_LCD > delay_4d1ms + delay_tr + delay_tpw + delay_tf + delay_th then
						count_LCD <= 0;			
						State <= DisplayClr;	
					else
						count_LCD <= count_LCD + 1;
					end if;
					
				when DisplayClr =>
					lcd_rws <= DisplayClr_RWS;
					lcd_db <= DisplayClr_DB;
					if count_LCD < delay_37us then
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_37us then
						lcd_e <= '1';
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_37us + delay_tr + delay_tpw then
						lcd_e <= '0';
						count_LCD <= count_LCD + 1;
					elsif count_LCD > delay_37us + delay_tr + delay_tpw + delay_tf + delay_th then
						count_LCD <= 0;			
						State <= EntryModeSet;	
					else
						count_LCD <= count_LCD + 1;
					end if;
					
					when EntryModeSet =>
					lcd_rws <= EntryModeSet_RWS;
					lcd_db <= EntryModeSet_DB;
					if count_LCD < delay_1d52ms then
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_1d52ms then
						lcd_e <= '1';
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_1d52ms + delay_tr + delay_tpw then
						lcd_e <= '0';
						count_LCD <= count_LCD + 1;
					elsif count_LCD > delay_1d52ms + delay_tr + delay_tpw + delay_tf + delay_th then
						count_LCD <= 0;
						State <= HomeCursor;	
					else
						count_LCD <= count_LCD + 1;
					end if;
					
					when HomeCursor =>
					lcd_rws <= HomeCursor_RWS;
					lcd_db <= HomeCursor_DB;
					if count_LCD < delay_1d52ms then
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_1d52ms then
						lcd_e <= '1';
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_1d52ms + delay_tr + delay_tpw then
						lcd_e <= '0';
						count_LCD <= count_LCD + 1;
					elsif count_LCD > delay_1d52ms + delay_tr + delay_tpw + delay_tf + delay_th then
						count_LCD <= 0;
						State <= WriteChar;	
					else
						count_LCD <= count_LCD + 1;
					end if;
					
					when WriteChar =>
						case count_Char is						-- Chooses which ASCII character to write to the LCD
							when 0 =>
								writeChar_DB <= "01001000";	-- ASCII for "H"
							when 1 =>
								WriteChar_DB <= "01100101"; 	-- ASCII for "e"
							when 2 =>
								WriteChar_DB <= "01101100";	-- ASCII for "l"
							when 3 =>
								WriteChar_DB <= "01101100";	-- ASCII for "l"
							when 4 =>
								WriteChar_DB <= "01101111";	-- ASCII for "o"
							when 5 =>
								WriteChar_DB <= "01001110";	-- ASCII for "N"
							when 6 =>
								WriteChar_DB <= "01111001";	-- ASCII for "y"
							When 7 =>
								WriteChar_DB <= "01110100";	-- ASCII for "t"
							when 8 =>
								WriteChar_DB <= "01110010";	-- ASCII for "r"
							when 9 =>
								WriteChar_DB <= "01101001";	-- ASCII for "i"
							when others =>
								WriteChar_DB <= "01100011";	-- ASCII for "c"
						end case count_Char;
						
					lcd_rws <= WriteChar_RWS;
					lcd_db <= WriteChar_DB;		
					if count_LCD < delay_1d52ms then
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_1d52ms then
						lcd_e <= '1';
						count_LCD <= count_LCD + 1;
					elsif count_LCD = delay_1d52ms + delay_tr + delay_tpw then
						lcd_e <= '0';
						count_LCD <= count_LCD + 1;
					elsif count_LCD > delay_1d52ms + delay_tr + delay_tpw + delay_tf + delay_th then
						count_LCD <= 0;
						count_Char <= count_Char + 1;
						State <= WriteChar;
						if count_Char >= 10 then
							State <= EndState;
						end if;
					else
						count_LCD <= count_LCD + 1;
					end if;
					
				when EndState =>
			
			end case state;
		end if;
	end process lcd_display;
		
end rtl;

Here is the User Constraint File.


NET "LCD_DB<0>" LOC = Y13;
NET "LCD_DB<4>" LOC = AA12;
NET "LCD_DB<3>" LOC = AB12;
NET "LCD_RWS<0>" LOC = W13;
NET "LCD_RWS<1>" LOC = Y14;
NET "LCD_DB<7>" LOC = Y15;
NET "LCD_E" LOC = AB4;
NET "LCD_DB<5>" LOC = Y16;
NET "LCD_DB<6>" LOC = AB16;
NET "LCD_DB<1>" LOC = AB18;
NET "LCD_DB<2>" LOC = AB17;
NET "led<0>" LOC = R20;
NET "led<1>" LOC = T19;
NET "led<2>" LOC = U20;
NET "led<3>" LOC = U19;
NET "led<4>" LOC = V19;
NET "led<5>" LOC = V20;
NET "led<6>" LOC = Y22;
NET "led<7>" LOC = W21;
NET "sw<0>" LOC = V8;
NET "sw<1>" LOC = U10;
NET "sw<2>" LOC = U8;
NET "clk" LOC = E12;
 

xilinx ise tutorial

Hi

I'm trying to use VHDL to display on the LCD of Spartan 3E. Appreciate if Peter or anyone can provide me some resources too. Thanks.
 

vhdl lcd driver

Hello Drifterz,

A really good resource is looking at hte datasheet for the lcd display. It goes over the sequence of commands required to display to the LCD. The Spartan3A uses the Sitronix ST7066U LCD display driver. I have sample VHDL code in previous replies that give you an idea how to write commands to the LCD.

Unfortunately I am not the best person to talk to since my code does not consistently display to the LCD. I am still working on this problem. If you are successful in displaying to the LCD please post your results here and if possible, let me know what I have done wrong.
 

module lcd for vhdl

Hi Peter_L,

I'm still trying out as I'm totally new to VHDL and FPGA.
Do let me know if you have figured out. Thanks.
 

xilinx ise hello world

Hi Drifterz,

If you're using the Xilinx FPGA with the Xinlinx ISE editor, I've found a great tutorial on the Xilinx web page (search for "xilinx ise tutorial"). It's a step by step tutorial in VHDL or Verilog (depending on which your comfortable with) which goes through the steps of designing a Stop Watch using the Spartan3A Development board. This tutorial goes through using counters and displaying to the LCD display. Check it out! I'm working on it now and i've learnt a few things already.

Good luck. Keep me updated on how it goes. It's always good to know that I'm not hte only one who's new to FPGA's! =)
 

thank you al people that trying to help. your example codes and suggestions were helpful for me.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top