Forum: FPGA, VHDL & Co. HD44780 LCD Probleme - Altera DE2-115


von Mike (Gast)


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;

von Duke Scarring (Gast)


Lesenswert?

Mike schrieb:
> USE  IEEE.STD_LOGIC_ARITH.all;
> USE  IEEE.STD_LOGIC_UNSIGNED.all;
Siehe: Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"

Mike schrieb:
> Modelsim eine Simulation gestartet
Kannst Du uns auch die Testbench zur Verfügung stellen?
Dann läßt sich das Problem leichter nachvollziehen.

Duke

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


Lesenswert?

> [QUOTE]...[/QUOTE]
Nimm statt "QOUTE" besser mal "vhdl", dann klappt das mit dem 
Syntax-Higlighting besser. So also (ohne Leerzeichen):
[ vhdl ]...[ /vhdl ]

von Mike (Gast)


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?

von PittyJ (Gast)


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?

von Mike (Gast)


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...

von Duke Scarring (Gast)


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

von PittyJ (Gast)


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.

von PittyJ (Gast)


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.

von Mike (Gast)


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... )

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


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

von Mike (Gast)


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...

von Duke Scarring (Gast)


Lesenswert?

Mike schrieb:
> Was genau bedeutet "H, H" ?
Kannst Du uns den Link zum Datenblatt mal geben?

Duke

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


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... 
;-)

von Mike (Gast)


Angehängte Dateien:

Lesenswert?

Hey Duke,

Datenblatt hier gerade hochgeladen...

LG Mike

von Duke Scarring (Gast)


Lesenswert?

Mike schrieb:
> Chip enable signal H, H --> L
Sieht in der Tat etwas ominös aus.
Weiter hinten sind ja aber die konkreten Timings angegeben (230 ns/500 
ns).

Duke

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.