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.

lcd initialization vhdl code problem

Status
Not open for further replies.

waqar86

Junior Member level 2
Joined
Nov 5, 2010
Messages
20
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,435
i m trying to initialize a tft lcd which has the following pinouts

chip select active-low
read active low read strobe
write active low write strobe
register select 0 = write command, 1 =write data
dataoutput(8-bits)

at the rising edge of 'write', command or data is latched.

Now i have written the following code, but LCD keeps white display, can i see anything happening on the lcd with this code, need ur opinions and correction,
Code:
entity lcd_driver is
generic(datawidth: positive:= 8);
port( clock: in std_logic; -- slow clock from clock divider.
reset: in std_logic; -- system reset.
lcd_select: out std_logic; -- lcd register select signal.
lcd_data: inout std_logic_vector(datawidth-1 downto 0); -- output to LCD.
lcd_r: out std_logic; -- output to LCD.
lcd_w: out std_logic; -- output to LCD.
lcd_cs: out std_logic -- output to LCD.

);
end lcd_driver;

architecture Display of lcd_driver is

-- Display ON command given in datasheet 
constant D_ON: std_logic_vector(datawidth-1 downto 0) := "00101001";

-- No operation command.
constant NIL: std_logic_vector(datawidth-1 downto 0) := "00000000";

signal w_temp: std_logic;
begin

lcd_cs<='0';
lcd_r<='1';
lcd_select<='0';
lcd_w<=w_temp;

P1: process (clock)
variable count: integer range 0 to 1;
begin
if rising_edge(clock) then
count:=count + 1;
if count=1 then
count:=0;
if w_temp='0' then
w_temp<='1';

else

w_temp<='0';
end if;
end if;
end if;
end process P1;

P2: process(w_temp)

constant temp: integer :=0;
begin

if rising_edge(w_temp) then
if temp=0 then
lcd_data <= D_ON;
else
lcd_data <= NIL;
end if;
end if;
end process P2;

end display;
 

Just some remarks about the coding (not necessarily about if this code does what expected or not).

First, using 'w_temp' as a derived clock is generally not a good idea. In general, clocked processes use the same clock source.

Using the 'count' variable in the process does not do anything (I dont' think the value is persistent between activations of the process; i think it always start at zero when the process is started). You probably need a 'signal' for this.

If 'w_temp' is the latch signal for the data for the LCD, then be aware that data typically needs to be stable when the latching signal occurs.
If the latching occurs on the falling edge, then the data is stable at that point (since the rising edge changed the data).
For a latching on a rising edge this code does not has the data stable at that point (since the data changes on the rising edge).

The 'w_temp' process always writes D_ON, since 'temp' is always 0.
 
Thnx for in depth reply. actually i m new to vhdl so the approach might not be good or it can be wrong aswell.

i have to send the data on the rising edge of lcd_w, so i derived a signal w_temp. because lcd_w(output port) cannot be directly used to make other signals dependant on lcd_w. this is wht i know (may be wrong). Now can u tell me how can i make a simpler and better code for this.

i used 'temp' and 'count' just to make the code synthesizable. because when i didnt use these variables ..the code becomes unsynthesizable.

Now what can i do to make data stable for latching at the rising edge of 'w_temp'.

again thnx for ur help
 

>> Now what can i do to make data stable for latching at the rising edge of 'w_temp'. <<

I suggest using a state machine.
There are complete books written about it (RTL hardware design using VHDL from Pong. P. Chu is an example).

The simplest kind of state machine, I think, is a clocked state machine that uses a simple counter.


Just keep in mind the following:
. All code inside the process use the signal levels as they were when the process was triggered.
A signal changed in the process is not 'activated' until the process ends.


Code:
signal State: std_logic_vector(3 downto 0);

process Sample(Clk)
  if (reset = '1') then
    State <= X"0";
    lcd_data <= "ZZZZZZZZ";
    w_temp   <= '1';
  else
    if rising_edge(Clk) then
      case State is
        when X"0" => lcd_data <= D_ON;
                     w_temp   <= '1';
                     State    <= X"1";
        when X"1" => lcd_data <= D_ON;
                     w_temp   <= '0';
                     State    <= X"2";
        when X"2" => lcd_data <= D_ON;
                     w_temp   <= '1';
                     State    <= X"3";
        when X"3" => lcd_data <= NIL;
                     w_temp   <= '1';
                     State    <= X"4";
        when X"4" => lcd_data <= NIL;
                     w_temp   <= '0';
                     State    <= X"5";
        when X"5" => lcd_data <= NIL;
                     w_temp   <= '1';
                     State    <= X"6";
        when X"6" => lcd_data <= "ZZZZZZZZ";
                     w_temp   <= '1';
                     State    <= X"6";
        when others  lcd_data <= "ZZZZZZZZ";
                     w_temp   <= '1';
                     State    <= X"6";
      end case;
    end if;  
  end if;
end process;

Above code is just to illustrate it and is by no means 'good practice'. Typically state machines
are not implemented as a counter, but as an enumerated type (the compiler then can optimize
things and such).

In above code, when state is '0' the data D_ON is put on the bus, the write signale is not active, and the next state will be '1'.
At the next clock the state is '1' and the same data is put on the bus, but now the write signal is asserted and the next state will be '2'.
At the next clock the state is '2' and the same data is put on the bus, and the write signal is de-asserted and the next state will be '3'.
etc, etc, etc

Basically we have written a small program that is executed every clock. In every state we indicate what each signal should be.
Instead of indicating in each state what a signal should be, you can also use 'default' settings, and only indicate in each state
what the differences from the default signal should be, like in code below.
Remember that a process is not processed sequentially ....

Code:
process Sample(Clk)
  if (reset = '1') then
    State <= X"0";
    lcd_data <= "ZZZZZZZZ";
    w_temp   <= '1';
  else
    if rising_edge(Clk) then
      -- Default values
      State    <= State + 1;
      lcd_data <= "ZZZZZZZZ";
      w_temp   <= '1';
      case State is
        when X"0" => lcd_data <= D_ON;
        when X"1" => lcd_data <= D_ON;
                     w_temp   <= '0';
        when X"2" => lcd_data <= D_ON;
        when X"3" => lcd_data <= NIL;
        when X"4" => lcd_data <= NIL;
                     w_temp   <= '0';
        when X"5" => lcd_data <= NIL;
        when X"6" => State    <= X"6";
        when others  State    <= X"6";
      end case;
    end if;  
  end if;
end process;
 
i really really appreciate help from ur side..such detailed guidance must have taken alot of ur time...i will try to implement it like u told. n will be back here..

thanks alot
 

i have written this code,,give me ur comments on this one plz
Code:
architecture Display of lcd_driver is

	type state_type is (display, initial, sleepout);
	-- Display ON, 2 lines no cursor.
	constant D_ON:  	std_logic_vector(datawidth-1 downto 0) := "00101001";
			-- No operation command.
	constant NIL:     std_logic_vector(datawidth-1 downto 0) := "00000000";
--	signal w_temp: std_logic;
	signal count: integer range 0 to 1;
	signal state: state_type; 
	constant large_delay : integer := 500;
	constant delay : integer :=  30;
	constant reg_setup: integer := 1;

begin
	lcd_cs<='0';
	lcd_select<='0';
  --lcd_w<=w_temp;
	lcd_r<='1';

process(clock, reset)

		variable count: integer range 0 to large_delay;

	begin

		if reset = '0' then
			state <= initial;
			count := 0;

		elsif rising_edge(clock) then

			case state is

			when initial =>
	--			input_ready <= '0';
	--			finish <= '0';
		
					if count = reg_setup then
					lcd_w <= '0';
					else
					lcd_w <= '1';
				end if;
		
				lcd_data <= NIL;
				if count = delay then
					state <= display;
					count := 0;
				else
					state <= initial;
					count := count + 1;
				end if;

			when display =>
			--	input_ready <= '0';
			--	finish <= '0';
			 if count = reg_setup then
					lcd_w <= '0';
						else
					lcd_w <= '1';
			end if;	
				lcd_data <= D_ON;
				if count = delay then
					state <= sleepout;
					count := 0;
				else
					state <= display;
					count := count + 1;
				end if;
				
			when sleepout =>
			--	input_ready <= '0';
			--	finish <= '0';
			if count = reg_setup then
					lcd_w <= '0';
						else
					lcd_w <= '1';
			end if;	
				lcd_data <= "00010001";
				if count = large_delay then
					state <= initial;
					count := 0;
				else
					state <= sleepout;
					count := count + 1;
				end if;	
		end case;
		end if;
	end process;
end display;
 
Last edited:

First of all, it reads easier when you format your code (use [ code ] / [ /code ]) ;-)

Well, I think you misunderstand the way a variable works.
A variable is typically used to 'describe' to the compiler how to implement things,
and mostly to help us type in less characters.
For example, when we use a variable in a loop:
Code:
  for index := 0 to 7
    output[index] <= '0';
  end for;

This does not mean that a 'loop' is implemented in the hardware!
Instead the compiler translates it into single instructions:
Code:
  output[0] <= '0';
  output[1] <= '0';
  ..
  output[7] <= '0';

The variable in a process does not 'retain' it's value. When the process
ends, the variable is 'lost'. Remember, a variable is not implemented in
hardware itself, unlike a 'signal'.

In you case you have to declare counter as a signal in the architecture part.
Something like:
signal count: integer range 0 to large_delay;

The remaining of the code seems reasonable to me (I have not looked at it
in specific detail).
Keep in mind that 'lcd_w' will only be '1' for one 'clk' cycle. Sometimes
the connected hardware can not run at the same speed as the FPGA does, and
signals like a write signal might have to 'extended'.
Check the datasheet for this.
 

if u can give me ur email or something where we can talk in runtime.that would be really helpful 4 me,,thanks
 

Sorry, can't/won't do. No matter what method, I will typically check/read/answer a post only once a day.
 

i came back here just to thanku marcel majoor. Due to ur extensive help i was successful in completing the project. thanks alot
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top