Forum: FPGA, VHDL & Co. Digilent Genesys Virtex 5 EvalBoard LCD Ansteuerung


von Benjamin K. (halunke86)


Lesenswert?

Hallo,

ich versuche mit z.Z. daran, ein LCD-Display auf dem oben genannten 
Evalboard anzusteuern. In der Simulation funktionieren die Timings 
soweit auch ohne Probleme, jedoch passiert in der Realität noch rein gar 
nichts.
Zum einfacheren Verständnis noch ein paar Erklärungen zum Code:

Init-Sequenz :
40ms Idle-> Function set -> 37us Idle -> Display On/Off Control -> 37us 
Idle -> Display Clear -> 1.52ms Idle -> Entry Mode Set -> 37us Idle

Zeichen in Speicher schreiben:
-Enable bleibt high für twdsu, danach low
- RW und die zu schreibenden Daten bleiben nach twdsu noch für die Zeit 
th auf low
-Nach dem schreiben der Daten in den Speicher geht das Programm in einen 
Idle-Zustand über

1
----------------------------------------------------------------------------------
2
-- Company: 
3
-- Engineer: 
4
-- 
5
-- Create Date:    10:01:07 02/27/2012 
6
-- Design Name: 
7
-- Module Name:    fsm - Behavioral 
8
-- Project Name: 
9
-- Target Devices: 
10
-- Tool versions: 
11
-- Description: 
12
--
13
-- Dependencies: 
14
--
15
-- Revision: 
16
-- Revision 0.01 - File Created
17
-- Additional Comments: 
18
--
19
----------------------------------------------------------------------------------
20
library IEEE;
21
use IEEE.STD_LOGIC_1164.ALL;
22
23
-- Uncomment the following library declaration if using
24
-- arithmetic functions with Signed or Unsigned values
25
use IEEE.NUMERIC_STD.ALL;
26
27
-- Uncomment the following library declaration if instantiating
28
-- any Xilinx primitives in this code.
29
--library UNISIM;
30
--use UNISIM.VComponents.all;
31
32
entity fsm is
33
    Port ( clk : in  STD_LOGIC;
34
           res_n : in  STD_LOGIC;
35
           lcd_e : out  STD_LOGIC;
36
           lcd_rs : out  STD_LOGIC;
37
           lcd_rw : out  STD_LOGIC;
38
           lcd_db : inout  STD_LOGIC_VECTOR (7 downto 0));
39
end fsm;
40
41
architecture Behavioral of fsm is
42
43
constant delay_40ms     : integer := 4000000;
44
constant delay_37us    : integer := 3700;
45
constant delay_1520us  : integer := 152000;
46
constant tsu        : integer := 0;        -- RS, R/W setup time (min. 0ns)
47
constant twdsu        : integer := 8;         -- Write data setup time (min. 80ns)
48
constant tdh         : integer := 30;         -- Data hold time (min. 300ns)
49
constant th         : integer := 1;         -- RS, R/W hold time (min. 10ns)
50
51
type state_type is (boot, function_set1, function_set2, disp_ctr, disp_clr, disp_entr, write_letter,idle);
52
signal current_state : state_type := boot;
53
signal cnt : integer range 0 to delay_40ms := 0;
54
55
begin
56
57
process(clk) is
58
59
begin
60
  if rising_edge(clk) then
61
  case current_state is
62
    when boot =>        if cnt < delay_40ms then
63
                      cnt <= cnt + 1;
64
                      current_state <= boot;
65
                    else
66
                      cnt <= 0;
67
                      current_state <= function_set1;
68
                    end if;
69
    
70
    when function_set1 =>   lcd_rs <= '0';
71
                    lcd_rw <= '0';
72
                    lcd_db <= "001110" & '-' & '-';
73
                    
74
                    if cnt < delay_37us then
75
                      cnt <= cnt + 1;
76
                      current_state <= function_set1;
77
                    else
78
                      cnt <= 0;
79
                      current_state <= function_set2;
80
                    end if;
81
                    
82
    when function_set2 =>    lcd_rs <= '0';
83
                    lcd_rw <= '0';
84
                    lcd_db <= "001110" & '-' & '-';  
85
                    if cnt < delay_37us then
86
                      cnt <= cnt + 1;
87
                      current_state <= function_set2;
88
                    else
89
                      cnt <= 0;
90
                      current_state <= disp_ctr;
91
                    end if;
92
                    
93
    when disp_ctr =>       lcd_rs <= '0';
94
                    lcd_rw <= '0';
95
                    lcd_db <= "00001111";  
96
                    if cnt < delay_37us then
97
                      cnt <= cnt + 1;
98
                      current_state <= disp_ctr;
99
                    else
100
                      cnt <= 0;
101
                      current_state <= disp_clr;
102
                    end if;  
103
    
104
    when disp_clr =>       lcd_rs <= '0';
105
                    lcd_rw <= '0';
106
                    lcd_db <= "00000001";  
107
                    if cnt < delay_1520us then
108
                      cnt <= cnt + 1;
109
                      current_state <= disp_clr;
110
                    else
111
                      cnt <= 0;
112
                      current_state <= disp_entr;
113
                    end if;  
114
    when disp_entr =>     lcd_rs <= '0';
115
                    lcd_rw <= '0';
116
                    lcd_db <= "00000110";
117
                    if cnt < delay_37us then
118
                      cnt <= cnt + 1;
119
                      current_state <= disp_entr;
120
                    else
121
                      cnt <= 0;
122
                      current_state <= write_letter;
123
                    end if;  
124
    when write_letter =>   if cnt < twdsu then
125
                      lcd_e <= '1';
126
                      lcd_rw <= '0';
127
                      lcd_rs <= '1';
128
                      lcd_db <= "01000001";
129
                      cnt <= cnt + 1;
130
                    elsif cnt = twdsu then
131
                      lcd_e <= '0';
132
                      cnt <= cnt + 1;
133
                    elsif cnt < twdsu + th then
134
                      cnt <= cnt + 1;
135
                    elsif cnt = twdsu + th then
136
                      lcd_rw <= '1';
137
                      cnt <= cnt + 1;
138
                    else
139
                      cnt <= 0;
140
                      current_state <= idle;
141
                    end if;
142
                    
143
    when idle =>        lcd_e <= '1';
144
                    lcd_rw <= '1';
145
                    lcd_db <= "--------";
146
                    
147
                    current_state <= idle;
148
  end case;
149
  end if;
150
end process f;
151
152
end Behavioral;

Hier noch die User Constraints für das Board:
1
NET "clk" TNM_NET = clk;
2
TIMESPEC TS_clk = PERIOD "clk" 10 ns HIGH 50%;
3
4
# LOC constraints
5
NET "clk" LOC = "AG18";
6
NET "res_n" LOC = "G6";
7
NET "lcd_rs" LOC = "V7";
8
NET "lcd_rw" LOC = "W6";
9
NET "lcd_e" LOC ="AA5";
10
NET "lcd_db(0)" LOC = "Y8";
11
NET "lcd_db(1)" LOC = "AB7";
12
NET "lcd_db(2)" LOC = "AB5";
13
NET "lcd_db(3)" LOC = "AC4";
14
NET "lcd_db(4)" LOC = "AB6";
15
NET "lcd_db(5)" LOC = "AC5";
16
NET "lcd_db(6)" LOC = "AC7";
17
NET "lcd_db(7)" LOC = "AD7";

Erkennt jemand, was ich falsch mache?

Vielen Dank schonmal im Voraus.

Gruß Benny

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Benjamin K. schrieb:
> In der Simulation funktionieren die Timings soweit auch ohne Probleme,
> jedoch passiert in der Realität noch rein gar nichts.
Wie stellst du das fest? Mit dem Oszi?

von Benjamin K. (halunke86)


Lesenswert?

Nein, aber ich kann auf dem Display nichts erkennen... Ich habe im 
Moment keine Möglichkeit, mit dem Oszi zu messen, ich gehe aber auch 
davon aus dass der Fehler eher im Code liegen sollte (das Display 
funktioniert auf jedenfall, da es bei einem Testprogramm von Digilent 
etwas anzeigt...)

Gruß Benny

EDIT: ich bin gerade dran, mich in ChipScope einzuarbeiten.... 
Vielleicht weiß ich danach mehr. Falls jemand jedoch doch noch einen 
Fehler erkennt bzw. einen Tip hat, darf er es hier gerne loswerden...

von Ralf (Gast)


Lesenswert?

Irgendwie fehlt doch zwischen den ganzen
States die Datenuebernahme an das LCD.
D.h. du musst doch den E  Pin irgendwie
noch toggeln.

Gruss

Ralf

von Benjamin K. (halunke86)


Lesenswert?

Vielen Dank Ralf,

das ist des Problems Lösung... Die Dokumentation ist diesbezüglich 
leider nicht die beste.... Aber jetzt funktioniert es!

einen schönen abend nohc

gruß benny

von Benjamin K. (halunke86)


Lesenswert?

So, ich habe es zwar jetzt geschafft, das LCD zu initialisieren, jedoch 
bekomme ich es einfach nicht hin, einen Buchstaben auf's Display zu 
bekommen.
Nach dem letzten Init-Schritt (Entry Mode Set) setze ich das Enable-Bit 
für 480ns auf high (wie im Datenblatt angegeben) und parallel dazu RS, 
R/W und DB... Danach wird Enable auf low gesetzt. Laut dem Datenblatt 
muss ich den low-Status dann für mindestens 1200ns-480ns = 720ns auf low 
lassen, ich gehe jedoch direkt in einen idle-modus und verharre da (ich 
will testweise nur einen buchstaben schreiben).
Die kritischen Zeiten für die Daten halte ich meiner Meinung nach ein, 
denn die write-data-setup-time beträgt 80ns, ich setze die zu 
schreibenden daten jedoch schon mit dem Enable-bit (welches ja für 480ns 
an ist), und im idle-modus liegen die Daten weiterhin an (somit ist die 
data hold time von 300ns auch erfüllt).

hat jemand eine idee warum mir das display - abgesehen vom cursor - 
nichts anzeigt?

vielen dank schonmal im voraus

gruß benny
1
when disp_entr =>     lcd_rs <= '0';
2
                    lcd_rw <= '0';
3
                    lcd_db <= DB_DISPENTR;
4
                    if cnt < delay_37us then
5
                      cnt <= cnt + 1;
6
                      current_state <= disp_entr;
7
                    elsif cnt = delay_37us then
8
                      cnt <= cnt + 1;
9
                      lcd_e <= '1';
10
                      current_state <= disp_entr;
11
                    else
12
                      lcd_e <= '0';
13
                      cnt <= 0;
14
                      current_state <= word1;
15
                    end if;  
16
    when word1 =>         lcd_rw <= '0';
17
                    lcd_rs <= '1';
18
                    lcd_db <= H_ASCII;
19
                    if cnt < tpw then
20
                      lcd_e <= '1';
21
                      cnt <= cnt + 1;
22
                      current_state <= word1;
23
                    elsif cnt >= twdsu and cnt < tc  then
24
                      lcd_e <= '0';
25
                      cnt <= cnt + 1;
26
                      current_state <= word1;
27
                    else
28
                      cnt <= 0;
29
                      current_state <= idle;
30
                    end if;
31
                    
32
    when idle =>         current_state <= idle;

Bem. zum Code:

tpw = "480ns" (ist eine Konstante welche bei einer taktdauer von 10ns 
dieser Zeit entspricht)
tc = "720ns"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.