Перейти к содержанию
    

LCD-Display

Доброе время суток,

 

помогите разобраться почему описаная схема по управлению лцд-дисплеем отказывается работать в железе...

 

Компелятор не ругаеться, в симуляторе тоже все хорошо выглядит. Я с начала думал что паузы между командами слишком маленькие, увеличил, всеравно не работает, но не так чтобы совсем не работает, не пишит текст. Инициализацию принемает, а текст не пишит

 

 

Reset.png

 

Initialisation_end.png

 

Data_1.png

 

ну и сам Код:

 

library ieee;

use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

 

 

entity lcd_v5 is port

(

clk : in std_logic; -- System clk

-- daten_bereit : in std_logic;

-- data_input : in std_logic_vector(7 downto 0);

busy : out std_logic := '1'; -- busy Flag

rs : out std_logic := '0'; -- data or instruction, instruction = '0', data = '1'

rw : out std_logic := '0'; -- read or write, read = '1', write = '0'

enable_lcd : out std_logic := '0'; -- enable for read of write

data : out std_logic_vector(7 downto 0) := (others => '0') -- daten

);

end entity;

 

architecture beh of lcd_v5 is

 

 

type zustaende is (begining, waitx, ini_data_send, lcd_enable, lcd_desable, ini_loop, ready);

 

signal zustand : zustaende := begining;

 

 

type mem_data is array(0 to 11) of std_logic_vector(7 downto 0);

constant daten : mem_data :=

(

x"30", -- data_reset(0) "0011 0000"

x"30", -- data_reset(1) "0011 0000"

x"30", -- data_reset(2) "0011 0000"

x"3c", -- data_ini_1(3) "0011 1100"

x"0f", -- data_ini_2(4) "0000 1111"

x"07", -- data_ini_3(5) "0000 0111"

x"01", -- data_ini_4(6) "0000 0001"

 

x"59", -- Y(7)

x"65", -- e(8)

x"61", -- a(9)

x"21", -- !(10)

x"00" -- (11)

);

 

 

 

type delay_type is array(0 to 6) of std_logic_vector(23 downto 0);

constant delay : delay_type :=

(

x"4c4b40", -- 100 ms(0)

x"033450", -- 4.2ms(1)

x"0013ba", -- 101us(2)

x"0009c4", -- delay_50us(3)

x"000032", -- delay_1us(4)

x"2625a0", -- delay_50ms(5)

x"030d40" -- delay_4ms(6)

);

 

 

signal addr_delay : integer range 0 to 6 := 0;

signal addr_delay_i : integer range 0 to 6 := 0;

signal addr_data : integer range 0 to 11 := 0;

 

 

signal counter : std_logic_vector(23 downto 0) := (others => '0');

signal cnt_en : std_logic := '0';

signal cnt_fert : boolean := false;

signal initialisierung : boolean := false;

signal pause_halten : boolean := true;

signal daten_gesendet : std_logic_vector(1 downto 0) := "00";

signal versions_nr : boolean := false;

signal load : std_logic := '0';

signal data_out : std_logic_vector(7 downto 0) := (others => '0');

 

begin

 

 

process(clk)

variable cnt_intern : integer range -2 to 5000000 := 2;

begin

 

if rising_edge(clk) then

 

if cnt_en = '1' then

 

if load = '1' then

 

cnt_intern := to_integer(unsigned(counter));

 

else

 

cnt_intern := cnt_intern - 1;

cnt_fert <= false;

 

end if;

 

if cnt_intern = 0 then

cnt_fert <= true;

end if;

end if;

end if;

end process;

 

 

 

-- automat --

 

process(clk)

variable durchlauf : integer range 0 to 12 := 0;

begin

 

if (rising_edge(clk)) then

 

case zustand is

 

 

when begining => counter <= delay(addr_delay);

cnt_en <= '1';

load <= '1';

rw <= '0';

busy <= '1';

zustand <= waitx;

 

if versions_nr = true then

rs <= '1';

else

rs <= '0';

end if;

 

when waitx => load <= '0';

 

if cnt_fert = true then

 

if initialisierung = false then

 

case daten_gesendet is

 

when "01" => zustand <= lcd_enable;

cnt_en <= '0';

 

when "10" => cnt_en <= '0';

zustand <= lcd_desable;

 

when others => data_out <= (others => '0');

 

if pause_halten = true then

enable_lcd <= '0';

cnt_en <= '0';

pause_halten <= false;

zustand <= ini_data_send;

else

cnt_en <= '0';

enable_lcd <= '0';

addr_delay <= addr_delay_i;

zustand <= ini_loop;

durchlauf := durchlauf + 1;

end if;

end case;

else

cnt_en <= '0';

zustand <= ready;

durchlauf := 0;

end if;

 

else

zustand <= waitx;

end if;

 

when ini_data_send => data_out <= daten(addr_data);

addr_delay <= 4;

daten_gesendet <= "01";

zustand <= begining;

 

when lcd_enable => addr_delay <= 4;

enable_lcd <= '1';

zustand <= begining;

daten_gesendet <= "10";

 

when lcd_desable => enable_lcd <= '0';

zustand <= begining;

daten_gesendet <= "00";

 

when ini_loop => data_out <= (others => '0');

 

if durchlauf > 2 then

 

addr_data <= addr_data + 1;

addr_delay_i <= 3;

addr_delay <= 3;

pause_halten <= true;

zustand <= begining;

 

if durchlauf = 7 then

 

versions_nr <= true;

addr_data <= addr_data + 1;

addr_delay <= 5;

addr_delay_i <= 5;

pause_halten <= true;

zustand <= begining;

end if;

else

addr_delay <= addr_delay + 1;

addr_delay_i <= addr_delay_i + 1;

addr_data <= addr_data + 1;

pause_halten <= true;

zustand <= begining;

end if;

 

if durchlauf >= 11 then

 

durchlauf := 0;

addr_data <= addr_data + 1;

addr_delay <= 6;

initialisierung <= true;

zustand <= begining;

end if;

 

when ready => zustand <= ready;

 

end case;

end if;

end process;

data <= data_out;

end beh;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот что сильно путает, так это вложенность Ifов друг в друга при проверке одной и той же переменной

.....
if durchlauf > 2 then
   addr_data <= addr_data + 1;
   addr_delay_i <= 3;
   addr_delay <= 3;
   pause_halten <= true;
   zustand <= begining;
   if durchlauf = 7 then
      .....

Получается железу надо проверить что durchlauf больше 2, а в каких то случаях при этом еще и равно 7.

На мой взгляд, лучше разбить проверку на две части

1) значение больше 2, но меньше 7

2) значение равно 7.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Доброе время суток,

 

помогите разобраться почему описаная схема по управлению лцд-дисплеем отказывается работать в железе...

 

Компелятор не ругаеться, в симуляторе тоже все хорошо выглядит.

У Вас очень сложный и неправильный путь для написания кода. Могу рассказать как надо... По скайпу...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У Вас очень сложный и неправильный путь для написания кода. Могу рассказать как надо... По скайпу...

 

очень хорошая идея, давайте, напишите когда вам позвонить

 

А какой LCD?

 

1602a-1 v1.3

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

очень хорошая идея, давайте, напишите когда вам позвонить

Да хоть завтра, после 11-ти... Как увидите мою машину в сети, так и звоните...

а сейчас можете прислать запрос на включение в адресную книгу...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот что сильно путает, так это вложенность Ifов друг в друга при проверке одной и той же переменной

.....
if durchlauf > 2 then
   addr_data <= addr_data + 1;
   addr_delay_i <= 3;
   addr_delay <= 3;
   pause_halten <= true;
   zustand <= begining;
   if durchlauf = 7 then
      .....

Получается железу надо проверить что durchlauf больше 2, а в каких то случаях при этом еще и равно 7.

На мой взгляд, лучше разбить проверку на две части

1) значение больше 2, но меньше 7

2) значение равно 7.

 

Дело в том что только при "durchlauf = 7" должна произойти задержка в 50мс (т.е. когда цепь "durchlauf = 7" это значит что инитиализазия закончина и начинается текст который должен выдаваться при каждом включении), потом должна опять выполняться цепь "durchlauf > 2" пока не достигнет "durchlauf >= 11".

 

Инитиализацию он понимает, а вот текст не пишит

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

может пример поможет, также смотрим state flow

 

 

--   LCD INITIALIZATION SETTINGS: to change, comment/uncomment lines:
--
--   Function Set  
--	  2-line mode, display on			 Line 93	lcd_data <= "00111100";
--	  1-line mode, display on			 Line 94	lcd_data <= "00110100";
--	  1-line mode, display off			Line 95	lcd_data <= "00110000";
--	  2-line mode, display off			Line 96	lcd_data <= "00111000";
--   Display ON/OFF
--	  display on, cursor off, blink off   Line 104   lcd_data <= "00001100";
--	  display on, cursor off, blink on	Line 105   lcd_data <= "00001101";
--	  display on, cursor on, blink off	Line 106   lcd_data <= "00001110";
--	  display on, cursor on, blink on	 Line 107   lcd_data <= "00001111";
--	  display off, cursor off, blink off  Line 108   lcd_data <= "00001000";
--	  display off, cursor off, blink on   Line 109   lcd_data <= "00001001";
--	  display off, cursor on, blink off   Line 110   lcd_data <= "00001010";
--	  display off, cursor on, blink on	Line 111   lcd_data <= "00001011";
--   Entry Mode Set
--	  increment mode, entire shift off	Line 127   lcd_data <= "00000110";
--	  increment mode, entire shift on	 Line 128   lcd_data <= "00000111";
--	  decrement mode, entire shift off	Line 129   lcd_data <= "00000100";
--	  decrement mode, entire shift on	 Line 130   lcd_data <= "00000101";
--	
--------------------------------------------------------------------------------

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;

 

--
--   Prints "123456789" on a HD44780 compatible 8-bit interface character LCD 
--   module using the lcd_controller.vhd component.
--
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY lcd_example IS
 PORT(
  clk	   : IN  STD_LOGIC;  --system clock
  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_example;

ARCHITECTURE behavior OF lcd_example 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; --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; --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 COMPONENT;
BEGIN

 --instantiate the lcd controller
 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);

 PROCESS(clk)
VARIABLE char  :  INTEGER RANGE 0 TO 10 := 0;
 BEGIN
IF(clk'EVENT AND clk = '1') THEN
  IF(lcd_busy = '0' AND lcd_enable = '0') THEN
	lcd_enable <= '1';
	IF(char < 10) THEN
	  char := char + 1;
	END IF;
	CASE char IS
	  WHEN 1 => lcd_bus <= "1000110001";
	  WHEN 2 => lcd_bus <= "1000110010";
	  WHEN 3 => lcd_bus <= "1000110011";
	  WHEN 4 => lcd_bus <= "1000110100";
	  WHEN 5 => lcd_bus <= "1000110101";
	  WHEN 6 => lcd_bus <= "1000110110";
	  WHEN 7 => lcd_bus <= "1000110111";
	  WHEN 8 => lcd_bus <= "1000111000";
	  WHEN 9 => lcd_bus <= "1000111001";
	  WHEN OTHERS => lcd_enable <= '0';
	END CASE;
  ELSE
	lcd_enable <= '0';
  END IF;
END IF;
 END PROCESS;

END behavior;

post-24839-1473056420_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

может пример поможет, также смотрим state flow

 

 

--   LCD INITIALIZATION SETTINGS: to change, comment/uncomment lines:
--
--   Function Set  
--	  2-line mode, display on			 Line 93	lcd_data <= "00111100";
--	  1-line mode, display on			 Line 94	lcd_data <= "00110100";
--	  1-line mode, display off			Line 95	lcd_data <= "00110000";
--	  2-line mode, display off			Line 96	lcd_data <= "00111000";
--   Display ON/OFF
--	  display on, cursor off, blink off   Line 104   lcd_data <= "00001100";
--	  display on, cursor off, blink on	Line 105   lcd_data <= "00001101";
--	  display on, cursor on, blink off	Line 106   lcd_data <= "00001110";
--	  display on, cursor on, blink on	 Line 107   lcd_data <= "00001111";
--	  display off, cursor off, blink off  Line 108   lcd_data <= "00001000";
--	  display off, cursor off, blink on   Line 109   lcd_data <= "00001001";
--	  display off, cursor on, blink off   Line 110   lcd_data <= "00001010";
--	  display off, cursor on, blink on	Line 111   lcd_data <= "00001011";
--   Entry Mode Set
--	  increment mode, entire shift off	Line 127   lcd_data <= "00000110";
--	  increment mode, entire shift on	 Line 128   lcd_data <= "00000111";
--	  decrement mode, entire shift off	Line 129   lcd_data <= "00000100";
--	  decrement mode, entire shift on	 Line 130   lcd_data <= "00000101";
--	
--------------------------------------------------------------------------------

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;

 

--
--   Prints "123456789" on a HD44780 compatible 8-bit interface character LCD 
--   module using the lcd_controller.vhd component.
--
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY lcd_example IS
 PORT(
  clk	   : IN  STD_LOGIC;  --system clock
  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_example;

ARCHITECTURE behavior OF lcd_example 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; --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; --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 COMPONENT;
BEGIN

 --instantiate the lcd controller
 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);

 PROCESS(clk)
VARIABLE char  :  INTEGER RANGE 0 TO 10 := 0;
 BEGIN
IF(clk'EVENT AND clk = '1') THEN
  IF(lcd_busy = '0' AND lcd_enable = '0') THEN
	lcd_enable <= '1';
	IF(char < 10) THEN
	  char := char + 1;
	END IF;
	CASE char IS
	  WHEN 1 => lcd_bus <= "1000110001";
	  WHEN 2 => lcd_bus <= "1000110010";
	  WHEN 3 => lcd_bus <= "1000110011";
	  WHEN 4 => lcd_bus <= "1000110100";
	  WHEN 5 => lcd_bus <= "1000110101";
	  WHEN 6 => lcd_bus <= "1000110110";
	  WHEN 7 => lcd_bus <= "1000110111";
	  WHEN 8 => lcd_bus <= "1000111000";
	  WHEN 9 => lcd_bus <= "1000111001";
	  WHEN OTHERS => lcd_enable <= '0';
	END CASE;
  ELSE
	lcd_enable <= '0';
  END IF;
END IF;
 END PROCESS;

END behavior;

 

 

спасибо

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

может пример поможет, также смотрим state flow

 

 

--   LCD INITIALIZATION SETTINGS: to change, comment/uncomment lines:
--
--   Function Set  
--	  2-line mode, display on			 Line 93	lcd_data <= "00111100";
--	  1-line mode, display on			 Line 94	lcd_data <= "00110100";
--	  1-line mode, display off			Line 95	lcd_data <= "00110000";
--	  2-line mode, display off			Line 96	lcd_data <= "00111000";
--   Display ON/OFF
--	  display on, cursor off, blink off   Line 104   lcd_data <= "00001100";
--	  display on, cursor off, blink on	Line 105   lcd_data <= "00001101";
--	  display on, cursor on, blink off	Line 106   lcd_data <= "00001110";
--	  display on, cursor on, blink on	 Line 107   lcd_data <= "00001111";
--	  display off, cursor off, blink off  Line 108   lcd_data <= "00001000";
--	  display off, cursor off, blink on   Line 109   lcd_data <= "00001001";
--	  display off, cursor on, blink off   Line 110   lcd_data <= "00001010";
--	  display off, cursor on, blink on	Line 111   lcd_data <= "00001011";
--   Entry Mode Set
--	  increment mode, entire shift off	Line 127   lcd_data <= "00000110";
--	  increment mode, entire shift on	 Line 128   lcd_data <= "00000111";
--	  decrement mode, entire shift off	Line 129   lcd_data <= "00000100";
--	  decrement mode, entire shift on	 Line 130   lcd_data <= "00000101";
--	
--------------------------------------------------------------------------------

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;

 

--
--   Prints "123456789" on a HD44780 compatible 8-bit interface character LCD 
--   module using the lcd_controller.vhd component.
--
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY lcd_example IS
 PORT(
  clk	   : IN  STD_LOGIC;  --system clock
  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_example;

ARCHITECTURE behavior OF lcd_example 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; --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; --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 COMPONENT;
BEGIN

 --instantiate the lcd controller
 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);

 PROCESS(clk)
VARIABLE char  :  INTEGER RANGE 0 TO 10 := 0;
 BEGIN
IF(clk'EVENT AND clk = '1') THEN
  IF(lcd_busy = '0' AND lcd_enable = '0') THEN
	lcd_enable <= '1';
	IF(char < 10) THEN
	  char := char + 1;
	END IF;
	CASE char IS
	  WHEN 1 => lcd_bus <= "1000110001";
	  WHEN 2 => lcd_bus <= "1000110010";
	  WHEN 3 => lcd_bus <= "1000110011";
	  WHEN 4 => lcd_bus <= "1000110100";
	  WHEN 5 => lcd_bus <= "1000110101";
	  WHEN 6 => lcd_bus <= "1000110110";
	  WHEN 7 => lcd_bus <= "1000110111";
	  WHEN 8 => lcd_bus <= "1000111000";
	  WHEN 9 => lcd_bus <= "1000111001";
	  WHEN OTHERS => lcd_enable <= '0';
	END CASE;
  ELSE
	lcd_enable <= '0';
  END IF;
END IF;
 END PROCESS;

END behavior;

 

 

Ошибку нашел :-), проблема была в неправильной комбинации при инициализации. Оказывается что уже давно все работало, из-за такой мелочи сидел почти месяц...

Хотел выставить видео, но оно оказалось слишком большое (43 мб).

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ошибку нашел :-), проблема была в неправильной комбинации при инициализации. Оказывается что уже давно все работало, из-за такой мелочи сидел почти месяц...

Хотел выставить видео, но оно оказалось слишком большое (43 мб).

 

Даже добавлю. То что "Оказывается.." совсем не удивляет, ибо способ разработки совсем не лучший. А удивляет то, что я предлагаю показать как работать без ошибок, а Вы отказываетесь...

Но это уже Ваше дело...

Посмотрите хотя бы у меня в "Кратком Курсе" раздел "Дополнительно об автоматах"...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...