HD44780 LCD Probleme - Altera DE2-115

Gast #2711636
Lesenswert?

Halle zusammen,

ich bin ziemlich neu in VHDL und FPGA und habe die Tage versucht meinen 
ersten FPGA zu programmieren. Leider hat die Freude nicht lange 
angehalten, denn irgendwie kann ich das Ding einfach nicht ansteuern.

Ich habe mit Modelsim eine Simulation gestartet (alles ok...), alle 
Settings für die IO-Pins gecheckt und das Board (DE2-115) via Control 
Panel auf Funktionen getestet. Alles vollkommen in Ordnung, in der 
Simulation werden auch alle Bits richtig gesetzt...

Es ist ein Code (denn ich hier bei mc gefunden habe), denn ich ein wenig 
modifiziert habe.

Die Funktion des Programms:
- Über 7 Switchs werden die binären Codes für die Zeichen definiert, die 
auf dem LCD angezeigt werden sollen.

Nachdem ich das Programm auf den FPGA übertragen habe, kommt nur die 
Standart-Anzeige des LCDs. Er reagiert kein bisschen auf Veränderungen 
der Switchs...

Habe dem Code einige Kommentare hinzugefügt, damit er für euch schneller 
zu verstehen ist.

Ich bin für jeden noch so kleinen Hinweis sehr dankbar...

1
------------------------------------------------------------------- 
2
--                        ASCII HEX TABLE
3
--  Hex            Low Hex Digit
4
-- Value  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
5
------\----------------------------------------------------------------
6
--H  2 |  SP  !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
7
--i  3 |  0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
8
--g  4 |  @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
9
--h  5 |  P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
10
--   6 |  `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
11
--   7 |  p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~ DEL
12
-----------------------------------------------------------------------
13

14
LIBRARY IEEE;
15
USE  IEEE.STD_LOGIC_1164.all;
16
USE  IEEE.STD_LOGIC_ARITH.all;
17
USE  IEEE.STD_LOGIC_UNSIGNED.all;
18

19
entity lcd_control is
20
  port
21
  (
22
    trigger,trigger2, clk     : in  std_logic;
23
    ascii                     : in  std_logic_vector(7 downto 0);
24
    lcd_rs, lcd_e, lcd_rw      : out  std_logic;
25
    lcd_data                 : out std_logic_vector(7 downto 0);
26
    lcd_an                : out std_logic
27

28
    );
29
end lcd_control;
30

31
architecture behv of lcd_control is
32

33
type state_type is ( START, START_WAIT, FUNC_SET_WAIT, DISP_ON_WAIT,
34
                    DROP_E, HOLD,
35
                    FUNC_SET, DISP_ON, DISP_CLEAR, MODE_SET,
36
                    WAIT_CHAR, DISP_CLEAR_WAIT,
37
                    WAIT_TRIGGER_RESET,
38
                    CHK_CNT, LINE2, HOME);
39
                    
40
signal state, next_command : state_type;
41
signal char_cnt : std_logic_vector(5 downto 0);
42
signal wait_cnt : std_logic_vector(7 downto 0);
43
  
44
begin
45

46

47

48
    
49
   process(clk)      
50
  begin
51

52
  if trigger2='1' then      -- a switch to turn the lcd on and off
53
  lcd_an<='1';  
54
  lcd_rw<='0';           -- setting the rw permenantly to 1
55
   else  
56
  lcd_an<='0';
57
  end if;
58
  
59
  state <= START;
60

61
    case state is
62

63
      when START =>       
64
      
65
        lcd_e <= '1';
66
        lcd_rs <= '0';
67
        lcd_data <= X"38";                 -- set the lcd to 8 bit lenght
68
        wait_cnt<=X"00";
69
        state <= DROP_E;                   -- function of DROP_E: just sets lcd_e to '1' and state goes to next_command      
70
        next_command <= START_WAIT;
71
        
72
        when START_WAIT =>                 -- waiting for a few msec 
73
         if wait_cnt < X"10" then       
74
          wait_cnt <= wait_cnt +1;
75
          state <= START_WAIT;
76
        else
77
          state <= FUNC_SET;            
78
          wait_cnt <= X"00";          
79
        end if;
80
        
81
        
82
        
83
      when FUNC_SET =>
84
        lcd_e <= '1';
85
        lcd_rs <= '0';
86
        lcd_data <= X"38";
87
        state <= DROP_E;            
88
        next_command <= FUNC_SET_WAIT;
89
        
90

91
        when FUNC_SET_WAIT =>
92
         if wait_cnt < X"10" then         
93
          wait_cnt <= wait_cnt +1;
94
          state <= FUNC_SET_WAIT;
95
        else
96
          state <= DISP_ON;            
97
          wait_cnt <= X"00";          
98
        end if;
99
        
100
        
101
        
102
      when DISP_ON =>
103
        lcd_e <= '1';
104
        lcd_rs <= '0';
105
        lcd_data <= X"0F";                   -- set the lcd to Display on, Cursor is displayed, Blinking enable, 
106
        state <= DROP_E;            
107
        next_command <= DISP_ON_WAIT;
108
        
109
        
110
        when DISP_ON_WAIT =>
111
         if wait_cnt < X"10" then    
112
          wait_cnt <= wait_cnt +1;
113
          state <= DISP_ON_WAIT;
114
        else
115
          state <= DISP_CLEAR;        
116
          wait_cnt <= X"00";          
117
        end if;
118
        
119
        
120
      when DISP_CLEAR =>
121
      
122
        lcd_e <= '1';
123
        lcd_rs <= '0';
124
        lcd_data <= X"01";                -- command: clear the display 
125
        wait_cnt <= X"00";
126
        state <= DROP_E;            
127
        next_command <= DISP_CLEAR_WAIT;
128
        
129
      
130
        
131
      when DISP_CLEAR_WAIT =>
132
      
133
         if wait_cnt < X"10" then    
134
          wait_cnt <= wait_cnt +1;
135
          state <= DISP_CLEAR_WAIT;
136
        else
137
          state <= MODE_SET;            
138
          wait_cnt <= X"00";          
139
        end if;
140
        
141
      when MODE_SET =>
142
        lcd_e <= '1';
143
        lcd_rs <= '0';
144
        lcd_data <= X"06";               -- Cursor moves right, Display shift enabled.
145
        state <= DROP_E;
146
        next_command <= WAIT_CHAR;
147
        
148
---------------- initialization done, Loop of writing begins -------------------------------------------
149

150
--   WAIT_CHAR -> DROP_E -> HOLD -> WAIT_TRIGGER_RESET -> CHK_CNT -> LINE2 -> DROP_E -> HOLD -> |
151
--                                                                |                              |
152
--        ^                                                       -> HOME  -> DROP_E -> HOLD -> |
153
--        |                                                       |                              |
154
--        |                                                       v                             v
155
--        |----------------------------------------<<-------------------------------------------|
156

157
-------------------------------------------------------------------------------------------------
158
        
159
      when WAIT_CHAR =>
160
        if trigger = '0' then               -- trigger is set to a switch
161
            
162
          lcd_e <= '1';
163
          lcd_rs <= '1';
164
          lcd_data <= ascii;                -- ascii is defined through 7 switchs
165
          char_cnt <= char_cnt +1;          -- a counter for the written letters
166
          state <= DROP_E;
167
          next_command <= WAIT_TRIGGER_RESET;
168
        else
169
          next_command <= WAIT_CHAR;
170
        end if;
171
        
172
      when WAIT_TRIGGER_RESET =>              -- loop, waiting for an change at the switch
173
        if trigger = '0' then
174
           state <= WAIT_TRIGGER_RESET;
175
        else
176
          state <= CHK_CNT;
177
        end if;
178
        
179
      when CHK_CNT =>                         -- checking if the first line is full of letters, 
180
        if char_cnt = X"10" then
181
          state <= LINE2;                
182
        elsif char_cnt = X"20" then
183
          state <= HOME;                     -- clears the display 
184
        else
185
          state <= WAIT_CHAR;
186
        end if;
187
        
188
        
189
      when LINE2 =>                            -- starts writing at the secound line
190
        lcd_e <= '1';
191
        lcd_rs <= '0';
192
        lcd_data <= X"C0";                    -- sets the DDRAM-Adress to '1000000'
193
        state <= DROP_E;
194
        next_command <= WAIT_CHAR;
195
        
196
      when HOME =>
197
         lcd_e <= '1';
198
        lcd_rs <= '0';
199
        lcd_data <= X"80";                    -- sets the DDRAM-adress to '0000000'
200
        char_cnt <= "000000";
201
        state <= DROP_E;
202
        next_command <= WAIT_CHAR;
203
              
204
      when DROP_E =>      
205
        lcd_e <= '1';
206
        state <= HOLD;
207
      
208
      when HOLD =>
209
        state <= next_command;
210
      
211
    end case;
212

213
  end process;
214
  
215

216
end behv;
Gast #2711708
Lesenswert?

Hi Duke...

Wollt gerade die Simalation unter "File"--> "Export"--> "Waveform" 
exportieren, nur ist "Waveform" nicht auswählbar. Und als Image ist das 
Wavebild zu klein.

Was mach ich bei meinem Export-Versuch falsch?
Gast #2711784
Lesenswert?

Diese Clock
   clk     : in  std_logic;
wie schnell ist sie getaktet?
Der DE2-115 läuft mit 50MHz. Die Wartezeit muss aber mehrere 
Millisekunden sein.
Da kommt man doch mit einem 8-Bit Wartezähler
  signal wait_cnt : std_logic_vector(7 downto 0);
gar nicht weit?

Bei mir mußte ich gerade die Reset- und Schreib-Zeiten sehr genau 
einhalten.

Ausserdem fehlt mir so etwas wie
if rising_edge(clk)

Wo wird das gemacht?
Gast #2711911
Lesenswert?

Hey PittyJ,

oh man, klar... Die Clock läuft mit 50 Mhz, da war meine Wartezeit wohl 
etwas kurz. Habe das nun den Zähler (vielleicht nicht auf die feine Art) 
auf 500.000 "Warte-Takte" anstatt 56 gesetzt, aber dennoch tun sich 
nichts auf der Anzeige.

Brauche ich denn die rising_edge(clk) für meinen Fall überhaupt?

Danke schonmal für die schnelle Unterstützung...
Gast #2711912
Lesenswert?

Mike schrieb:
> Wollt gerade die Simalation unter "File"--> "Export"--> "Waveform"
> exportieren, nur ist "Waveform" nicht auswählbar. Und als Image ist das
> Wavebild zu klein.
Ich wollte eigentlich nicht die Waveforms haben, sondern die Testbench, 
die die Stimuli erzeugt. Wie erzeugst Du die Stimuli?

Duke
Gast #2711927
Lesenswert?

>>Brauche ich denn die rising_edge(clk) für meinen Fall überhaupt?

Also ich mache nur Prozesse, die von einer rising_edge abhängen. 
Zumindest, wenn ich etwas synthetisieren möchte.

Die Profis hier schaffen das wohl auch ohne, nur wir als Anfänger 
sollten das beachten. Auch in sämtlicher einschlägiger Literatur habe 
ich das so gesehen.
Gast #2711933
Lesenswert?

Noch ein Tipp:
Versuche es auf dem Board erst einmal mit einer blinkenden LED.
Da bekommt man schon ein Gefühl, wir groß die Zähler sein müssen, hat 
nur 2 States und nur eine Ausgabeleitung. Und trotzdem gibt es da noch 
genug Fallstricke für Neulinge.
Gast #2711955
Lesenswert?

naja, ich habe das File mit ModelSim von Altera simuliert und mir die 
Wave angeschaut, ob das Programm irgendwo nicht das macht, was es 
eigentlich soll...

Wenn du mir genau beschreibst, wie ich die Testbench auslesen und zu 
Verfügung stellen kann, dann kann ich sie hier natürlich noch posten...

(Sorry, ist alles noch relativ neu für mich... )
Moderator (Firma: Titel) Persönliche Seite #2712032
Lesenswert?

Mike schrieb:
> oh man, klar... Die Clock läuft mit 50 Mhz, da war meine Wartezeit wohl
> etwas kurz.
Genau sowas sollte man mit einer Testbench aber herausfinden...

Mike schrieb:
> wie ich die Testbench auslesen und zu Verfügung stellen kann,
Eine Testbench liest du nicht aus, sondern du schreibst sie passend zu 
deinem Projekt...
Das wichtigste Merkmal einer Testbench: sie hat keine Ports nach 
aussen, also keine Ein- oder Ausgnänge.

Sieh dir mal das da mit der blinkenden LED und der passenden Testbench 
an:
http://www.lothar-miller.de/s9y/archives/80-Hello-World!.html
Gast #2713598
Lesenswert?

Ok, ich habe nun mein Problem gelöst, an dem ich seit Tagen dran bin.

Problem
NR.1: Ich habe die Zeit aus dem Datenblatt nicht eingehalten.

Nr.2: In vielen Programmen und Beispielen haben ich im Code gesehen, 
dass das enable-Bit von 0 auf 1 wechseln muss, damit das LCD die Daten 
verarbeitet.
Ich dachte, dass das in jedem LCD HD44780 so Standart ist... Anscheinend 
nicht...

In meinem Datenblatt des LCDs steht nämlich folgendes:

Chip enable signal H, H --> L

Nachdem ich mein enable-Signal im Code invertiert habe, klappt jetzt 
alles...

Meine letzte Frage:
Was genau bedeutet "H, H" ? Ist damit gemeint, dass das chip enable 
signal zwei Clock-Zyklen auf H sein udn dann auf L fallen muss, damit 
das LCD meine Daten verarbeitet?


Vielen Dank für die vielen (sehr hilfreichen) Antworten...
Moderator (Firma: Titel) Persönliche Seite #2714288
Lesenswert?

Mike schrieb:
> Nr.2: In vielen Programmen und Beispielen haben ich im Code gesehen,
> dass das enable-Bit von 0 auf 1 wechseln muss, damit das LCD die Daten
> verarbeitet.
> Ich dachte, dass das in jedem LCD HD44780 so Standart ist... Anscheinend
> nicht...
Üblicherweise werden die Daten bei der fallenden Flanke übernommen 
(z.B. auch bei SRAMs usw...), und deshalb bei den meisten 
Softwarelösungen der Enable-Pin bei stabil anliegenden Daten einmal 
komplett getoggelt. Die Softies haben dann auch kein Problem, weil 
sowieso immer alles nacheinander passiert:
1. Daten anlegen
2. Enable auf High
3. Enable auf Low
4. Weiter bei 1.
Du hast bei der Hardware aber den "Vorteil", dass du alles 
gleichzeitig machen kannst. Das wird dir noch öfter zu denken geben... 
;-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren