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 2x16 LCD module

Status
Not open for further replies.

rmadd95

Newbie level 3
Joined
Apr 20, 2017
Messages
3
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
33
This is my first post so i'm not sure if i'm in the right place or not, but i'm trying to take a 7 bit vector to define a character array and then display it to a 2x16 lcd screen. I think my states are screwed up but i don't know how to fix them. When I try to run it on the prototype board the screen clears as it should but then nothing shows up. Any help would be appreciated. I am also very new to VHDL so my code may not seem very refined haha.

Code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

ENTITY lcd_disp IS
	PORT (
		reset, take, vend, l1, l2, clock : IN STD_LOGIC;
		total : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
		lcd_data : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
		lcd_on, lcd_blon, lcd_en, lcd_rs, lcd_rw, led1, led2 : OUT STD_LOGIC
	);
END lcd_disp;
ARCHITECTURE behave OF lcd_disp IS

	TYPE state_type IS (s1, s2, s3, s4, s5, s6, s7);
	SIGNAL state : state_type;

	SUBTYPE char IS std_logic_vector(7 DOWNTO 0);
	TYPE moneychar IS ARRAY (1 TO 8) OF char;
	SIGNAL amount : moneychar;
	SIGNAL count : INTEGER := 1;
	SIGNAL init_count : INTEGER := 1;
	CONSTANT initcodes : moneychar := (x"38", x"38", x"38", x"38", x"06", x"0E", x"01", x"FE");
BEGIN
display : PROCESS (total, reset, take, vend, clock)
BEGIN
	lcd_on <= '1';
	lcd_blon <= '1';

	IF (total = "0000000") THEN
		amount <= (x"24", x"30", x"2E", x"30", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "0000101") THEN
		amount <= (x"24", x"30", x"2E", x"30", x"35", x"FE", x"FE", x"FE");
	ELSIF (total = "0001010") THEN
		amount <= (x"24", x"30", x"2E", x"31", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "0001111") THEN
		amount <= (x"24", x"30", x"2E", x"31", x"35", x"FE", x"FE", x"FE");
	ELSIF (total = "0010100") THEN
		amount <= (x"24", x"30", x"2E", x"32", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "0011001") THEN
		amount <= (x"24", x"30", x"2E", x"32", x"35", x"FE", x"FE", x"FE");
	ELSIF (total = "0011110") THEN
		amount <= (x"24", x"30", x"2E", x"33", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "0100011") THEN
		amount <= (x"24", x"30", x"2E", x"33", x"35", x"FE", x"FE", x"FE");
	ELSIF (total = "0101000") THEN
		amount <= (x"24", x"30", x"2E", x"34", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "0101101") THEN
		amount <= (x"24", x"30", x"2E", x"34", x"35", x"FE", x"FE", x"FE");
	ELSIF (total = "0110010") THEN
		amount <= (x"24", x"30", x"2E", x"35", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "0110111") THEN
		amount <= (x"24", x"30", x"2E", x"35", x"35", x"FE", x"FE", x"FE");
	ELSIF (total = "0111100") THEN
		amount <= (x"24", x"30", x"2E", x"36", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "1000001") THEN
		amount <= (x"24", x"30", x"2E", x"36", x"35", x"FE", x"FE", x"FE");
	ELSIF (total = "1000110") THEN
		amount <= (x"24", x"30", x"2E", x"37", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "1001011") THEN
		amount <= (x"24", x"30", x"2E", x"37", x"35", x"FE", x"FE", x"FE");
	ELSIF (total = "1010000") THEN
		amount <= (x"24", x"30", x"2E", x"38", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "1010101") THEN
		amount <= (x"24", x"30", x"2E", x"38", x"35", x"FE", x"FE", x"FE");
	ELSIF (total = "1011010") THEN
		amount <= (x"24", x"30", x"2E", x"39", x"30", x"FE", x"FE", x"FE");
	ELSIF (total = "1011111") THEN
		amount <= (x"24", x"30", x"2E", x"39", x"35", x"FE", x"FE", x"FE");
	ELSE
		amount <= (x"24", x"31", x"2E", x"30", x"30", x"FE", x"FE", x"FE");
	END IF;
	IF (reset = '0') THEN
		init_count <= 1;
		count <= 1;
		state <= s1;
 
	ELSIF (clock'EVENT AND clock = '1') THEN
		CASE state IS

			WHEN s1 => 
				lcd_data <= initcodes(init_count);
				lcd_en <= '1';
				lcd_rs <= '0';
				lcd_rw <= '0';
				state <= s2;
 
			WHEN s2 => 
				lcd_en <= '0';
				init_count <= init_count + 1;
				IF (count <= initcodes'length) THEN
					state <= s1;
				ELSE
					state <= s3;
				END IF;
 
			WHEN s3 => 
				lcd_data <= x"80";
				lcd_en <= '1';
				lcd_rs <= '0';
				lcd_rw <= '0';
				state <= s4;
 
			WHEN s4 => 
				lcd_en <= '0';
				lcd_rs <= '1';
				state <= s5;
 
			WHEN s5 => 
				lcd_data <= amount(count);
				lcd_en <= '1';
				lcd_rs <= '1';
				lcd_rw <= '0';
				state <= s6;
 
			WHEN s6 => 
				lcd_en <= '0';
				state <= s7;
 
			WHEN s7 => 
				lcd_en <= '1';
				count <= count + 1;
				IF (count <= amount'length) THEN
					state <= s3;
				ELSE 
					state <= s1;
				END IF;

				led1 <= l1;
				led2 <= l2; 
 
		END CASE;
	END IF;
END PROCESS;
END behave;
 

First of all don't use the same process for both sequential and combonational code, separate the two.

Have you tried running a simulation on the code with a testbench to observe what your FSM does after the init?
 

That makes it a little easier to understand... the problem is that this is for the final project in my digital logic class and we've basically never touched lcds before. The logic before this is solid but aside from displaying a static word on the display we don't know what to do. Ill follow that page and report back if I still cant get it.
 

So I got the display working a little bit, but there are some issues. We tried to make a counter module that feeds an integer into the display modules and it then outputs the value. It works but only for the first count and never refreshes... We tried using reset on the display to see if that would update to the new value but then it gets stuck in the power up case and never makes it to initialize. Here is what im working with...
Code:
library ieee;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

Entity data_converter is
Port(
		internal : in integer;
		clk : in std_logic;
		rw, rs, e : out std_logic;
		lcd_data : out std_logic_vector (7 downto 0)
	 );
end entity data_converter;

architecture behave of data_converter is

signal lcd_enable : std_logic;
signal lcd_bus : std_logic_vector (9 downto 0);
signal lcd_busy : std_logic;
component lcd_controller is
	Port(
			clk : in std_logic;
			reset_n : in std_logic;
			lcd_enable : in std_logic;
			lcd_bus : in std_logic_vector (9 downto 0);
			busy : out std_logic;
			rw, rs, e : out std_logic;
			lcd_data : out std_logic_vector (7 downto 0)
		 );
		end component;
begin
	
	dut: lcd_controller
		Port Map(clk => clk, reset_n => '1', lcd_enable => lcd_enable, lcd_bus => lcd_bus,
					busy => lcd_busy, rw => rw, rs => rs, e => e, lcd_data => lcd_data);
	
	converter : process(internal,clk)
		variable p00n : integer range 0 to 6:= 0;
		begin
		if (clk'event and clk = '1') then
			if (lcd_busy = '0' and lcd_enable = '0') then
				lcd_enable <= '1';
				if (p00n < 6) then
					p00n := p00n + 1;
				end if;
				if (internal = 0) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110000";
						when 5 =>
							lcd_bus <= "1000110000";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 5) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110000";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 10) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110001";
						when 5 =>
							lcd_bus <= "1000110000";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 15) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110001";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 20) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110010";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 25) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110010";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 30) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110011";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 35) then 
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110011";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 40) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110100";
						when 5 =>
							lcd_bus <= "1000110000";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 45) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110100";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 50) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110101";
						when 5 =>
							lcd_bus <= "1000110000";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 55) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110101";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 60) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110110";
						when 5 =>
							lcd_bus <= "1000110000";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 65) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110110";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 70) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110111";
						when 5 =>
							lcd_bus <= "1000110000";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 75) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110111";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 80) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000111000";
						when 5 =>
							lcd_bus <= "1000110000";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 85) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000111000";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 90) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000111001";
						when 5 =>
							lcd_bus <= "1000110000";
						when others =>
							lcd_enable <= '0';
					end case;
				elsif (internal = 95) then
					case p00n is 
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110000";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000111001";
						when 5 =>
							lcd_bus <= "1000110101";
						when others =>
							lcd_enable <= '0';
					end case;
				else
					case p00n is
						when 1 =>
							lcd_bus <= "1000100100";
						when 2 =>
							lcd_bus <= "1000110001";
						when 3 =>
							lcd_bus <= "1000101110";
						when 4 =>
							lcd_bus <= "1000110000";
						when 5 =>
							lcd_bus <= "1000110000";
						when others =>
							lcd_enable <= '0';
					end case;
				end if;
			else 
				lcd_enable <= '0';
			end if;
		end if;
	end process;
end behave;
This is where we store each of our cases regarding the current count of the integer it is reading.

Code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY lcd_controller IS
  PORT(
    clk        : IN    STD_LOGIC;  --system clock
    reset_n    : IN    STD_LOGIC;  --active low reinitializes lcd
    lcd_enable : IN    STD_LOGIC;  --latches data into lcd controller
    lcd_bus    : IN    STD_LOGIC_VECTOR(9 DOWNTO 0);  --data and control signals
    busy       : OUT   STD_LOGIC := '1';  --lcd controller busy/idle feedback
    rw, rs, e  : OUT   STD_LOGIC;  --read/write, setup/data, and enable for lcd
    lcd_data   : OUT   STD_LOGIC_VECTOR(7 DOWNTO 0)); --data signals for lcd
END lcd_controller;

ARCHITECTURE controller OF lcd_controller IS
  TYPE CONTROL IS(power_up, initialize, ready, send);
  SIGNAL    state      : CONTROL;
  CONSTANT  freq       : INTEGER := 50; --system clock frequency in MHz
BEGIN
  PROCESS(clk)
    VARIABLE clk_count : INTEGER := 0; --event counter for timing
  BEGIN
  IF(clk'EVENT and clk = '1') THEN
    
      CASE state IS
        
        --wait 50 ms to ensure Vdd has risen and required LCD wait is met
        WHEN power_up =>
          busy <= '1';
          IF(clk_count < (50000 * freq)) THEN    --wait 50 ms
            clk_count := clk_count + 1;
            state <= power_up;
          ELSE                                   --power-up complete
            clk_count := 0;
            rs <= '0';
            rw <= '0';
            lcd_data <= "00110000";
            state <= initialize;
          END IF;
          
        --cycle through initialization sequence  
        WHEN initialize =>
          busy <= '1';
          clk_count := clk_count + 1;
          IF(clk_count < (10 * freq)) THEN       --function set
            lcd_data <= "00111100";      --2-line mode, display on
            --lcd_data <= "00110100";    --1-line mode, display on
            --lcd_data <= "00110000";    --1-line mdoe, display off
            --lcd_data <= "00111000";    --2-line mode, display off
            e <= '1';
            state <= initialize;
          ELSIF(clk_count < (60 * freq)) THEN    --wait 50 us
            lcd_data <= "00000000";
            e <= '0';
            state <= initialize;
          ELSIF(clk_count < (70 * freq)) THEN    --display on/off control
            lcd_data <= "00001100";      --display on, cursor off, blink off
            --lcd_data <= "00001101";    --display on, cursor off, blink on
            --lcd_data <= "00001110";    --display on, cursor on, blink off
            --lcd_data <= "00001111";    --display on, cursor on, blink on
            --lcd_data <= "00001000";    --display off, cursor off, blink off
            --lcd_data <= "00001001";    --display off, cursor off, blink on
            --lcd_data <= "00001010";    --display off, cursor on, blink off
            --lcd_data <= "00001011";    --display off, cursor on, blink on            
            e <= '1';
            state <= initialize;
          ELSIF(clk_count < (120 * freq)) THEN   --wait 50 us
            lcd_data <= "00000000";
            e <= '0';
            state <= initialize;
          ELSIF(clk_count < (130 * freq)) THEN   --display clear
            lcd_data <= "00000001";
            e <= '1';
            state <= initialize;
          ELSIF(clk_count < (2130 * freq)) THEN  --wait 2 ms
            lcd_data <= "00000000";
            e <= '0';
            state <= initialize;
          ELSIF(clk_count < (2140 * freq)) THEN  --entry mode set
            lcd_data <= "00000110";      --increment mode, entire shift off
            --lcd_data <= "00000111";    --increment mode, entire shift on
            --lcd_data <= "00000100";    --decrement mode, entire shift off
            --lcd_data <= "00000101";    --decrement mode, entire shift on
            e <= '1';
            state <= initialize;
          ELSIF(clk_count < (2200 * freq)) THEN  --wait 60 us
            lcd_data <= "00000000";
            e <= '0';
            state <= initialize;
          ELSE                                   --initialization complete
            clk_count := 0;
            busy <= '0';
            state <= ready;
          END IF;    
       
        --wait for the enable signal and then latch in the instruction
        WHEN ready =>
          IF(lcd_enable = '1') THEN
            busy <= '1';
            rs <= lcd_bus(9);
            rw <= lcd_bus(8);
            lcd_data <= lcd_bus(7 DOWNTO 0);
            clk_count := 0;            
            state <= send;
          ELSE
            busy <= '0';
            rs <= '0';
            rw <= '0';
            lcd_data <= "00000000";
            clk_count := 0;
            state <= ready;
          END IF;
        
        --send instruction to lcd        
        WHEN send =>
        busy <= '1';
        IF(clk_count < (50 * freq)) THEN  --do not exit for 50us
           busy <= '1';
           IF(clk_count < freq) THEN      --negative enable
            e <= '0';
           ELSIF(clk_count < (14 * freq)) THEN  --positive enable half-cycle
            e <= '1';
           ELSIF(clk_count < (27 * freq)) THEN  --negative enable half-cycle
            e <= '0';
           END IF;
           clk_count := clk_count + 1;
           state <= send;
        ELSE
          clk_count := 0;
          state <= ready;
        END IF;

      END CASE;    
    
      --reset
      IF(reset_n = '0') THEN
          state <= power_up;
      END IF;
    
    END IF;
  END PROCESS;
END controller;
and this is what initializes and writes to the lcd
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top