Hallo,
nach dem ich mich jetzt ein wenig mit der Entwicklungsumgebung vertraut
gemacht habe, möchte ich neben dem VHDL lernen an sich, auch nebenbei
ein kleines Projekt anfangen. Für den Anfang hätte ich da an eine Uhr
gedacht.
Leider bin ich noch nicht so mit der Herangehensweise der FPGA
Entwicklung vertraut.
Ich habe mir das jetzt grob so überlegt. Mir stehen 4 7-Segment anzeigen
zur Verfügung. Davon würde ich je zwei zusammenfassen, und diese zwei
wiederum in ein Modul "Anzeige" packen. Dieses Modul bietet 2 Eingänge
an (5 und 6 Bit breit).
Die Uhr als solche würde ich dann wieder in ein extra Modul packen und
dort dann die anfallenden "Berechnungen" durchführen. Und damit die
Anzeige ansteuern.
Die Sekunden würde ich binär über LEDs ausgeben.
Was haltet ihr von dem Ansatz, oder habt ihr noch bessere Vorschläge?
Viele Grüße
Florentin S. schrieb:> habt ihr noch bessere Vorschläge?
Zähl jede Stelle einzeln...
> Mir stehen 4 7-Segment anzeigen zur Verfügung.
Also Stunder 10er, Stunden 1er sowie Minuten 10er und 1er.
Also würde ich einfach die Minuten 1er hochzählen bis zum Überlauf, dann
die Minuten 10er usw.
Dann hast du nicht die (recht aufwendige) Trennung in 10er und 1er
Stellen extra zu machen...
> Und damit die Anzeige ansteuern.
Ist die Anzeige gemultiplext?
Die vier 7-Segment Anzeigen sind gemultiplext. Deswegen war es ja meine
Idee, die Anzeigenansteuerung, und die eigentliche Uhr zu separieren.
Also würdest du vorschlagen, die Ansteuerung der Anzeigen, und die Uhr
quasi in eine Architektur zu packen, und dort immer nur die Stellen bis
zum Überlauf zählen?
So ich habe mich gerade mal an die Ansteuerung der gemultiplexten
7-Segment Anzeige gemacht, und vermutlich alles falsch gemacht, was man
als Anfänger nur falsch machen kann :-).
Der Code ist im Anhang.
D. I. schrieb:> Man sollte nur nicht mehr die alten Libs verwenden.
Ok. Da ist wohl mein Buch nicht mehr ganz auf dem neusten Stand. Was
wären denn hier die aktuellen?
D. I. schrieb:> Hier ein Vorschlag von mir
Danke. Aber da sind leider noch zu viele Sachen dabei, die ich noch
nicht kenne. Da muss ich mich erst einmal weiter mit der Theorie
beschäftigen.
Noch eine Allgemeine Frage, bezogen auf den Code von mir. Ich habe ja
jetzt für jede Anzeige ein Eingangssignal inpx. Nun würde ich gerne noch
ein Modul "Zeitgeber" o.ä. anlegen, der die Stellen durch zählt, und
dann den Zeitgeber und die Anzeige beispielsweise im Modul "Uhr"
instanziieren.
Dazu ein paar Fragen. Muss ich für jedes entity samt architecture eine
eigene Datei anlegen?
Dem "Zeitgeber" würde ich erst einmal 4 Ausgangsports geben. Diese
möchte ich zum testen erst einmal mit konstanten Werten belegen. Das
hatte auch geklappt. Nur irgendwie gab es ein Problem mit der Modul
"Uhr", in dem ich die beiden Sachen instanziiert und verbunden habe.
Könnte mir eventuell jemand dafür eine Grobstruktur geben? Ich werde es
jetzt auch noch einmal probieren, und dann den Code hier posten.
Florentin S. schrieb:> Ok. Da ist wohl mein Buch nicht mehr ganz auf dem neusten Stand.
Ja, das ist schade, was da so alles an Literatur herumgrukt.
Und auch was an manchen Hochschulen so gelehrt wird...
Florentin S. schrieb:> Dazu ein paar Fragen. Muss ich für jedes entity samt architecture eine> eigene Datei anlegen?
Nein, du kannst das alles
(jeweils ab library IEEE; use IEEE.STD_LOGIC_1164.ALL; ...)
in eine einzige Datei packen. Aber idR. ist es sinnvoller, genau das
nicht zu tun. Denn die Dateien werden doch sowieso von der IDE
verwaltet...
BTW:
AN0,AN1,AN2,AN3: inout std_logic;
Es ist nur Faulheit ein inout oder einen buffer zu verwenden,
damit sich das Signal zurücklesen lässt. Aber (!) inout und buffer
haben eigentlich eine gänzlich andere Funktion!!! Du wirst damit früher
oder später auf die Nase fallen...
Besser wäre es, ein internes Signal zu definieren, und an den Ports nur
in und out zu verwenden!
Hier mal dein Code überarbeitet:
So jetzt scheitert es an der vernetzung der Module und deren
Organisation im ISE.
Also ich habe jetzt eine Anzeige.vhd. Die kennt ihr ja schon. Dann eine
Zeitgeber.vhd. Ausschnitt:
Und eine Constraints.ucf (war bisher der Anzeige zugeordnet):
1
NET "AN0" LOC = "D14" ;
2
NET "AN1" LOC = "G14" ;
3
NET "AN2" LOC = "F14" ;
4
NET "AN3" LOC = "E13" ;
5
NET "CLOCK" LOC = "T9" ;
6
NET "LED<0>" LOC = "E14" ;
7
NET "LED<1>" LOC = "G13" ;
8
NET "LED<2>" LOC = "N15" ;
9
NET "LED<3>" LOC = "P15" ;
10
NET "LED<4>" LOC = "R16" ;
11
NET "LED<5>" LOC = "F13" ;
12
NET "LED<6>" LOC = "N16" ;
Wie organisiere ich diese jetzt am besten? Anscheinend ist eine *.ucf
immer nur einem Modul zugeordnet. Die Definitionen hier sind ja bis auf
den CLOCK alle für die Anzeige gedacht. Aber wo bringe ich dann den
Clock unter?
Florentin S. schrieb:> Anscheinend ist eine *.ucf immer nur einem Modul zugeordnet.
Machs dir am Anfang einfach und verwende nur 1 ucf-Datei. Diese word dem
"obersten" Modul zugeorndet, das alle Anschlüsse zur Aussenwelt hat.
Dieser Top-Level dürfte die UHR sein, denn dort geht ja der Takt rein.
Also müssen dort auch die LEDs rausgehen:
1
entitystrukturis
2
port(
3
CLOCK:instd_logic;
4
AN0,AN1,AN2,AN3:outstd_logic;
5
LED:outstd_logic_vector(6downto0))
6
);
7
endstruktur;
8
:
Und diesem Modul wird die UCF-Datei zugeordnet, denn genau dort hast du
ja die Portnamen wie auch in der UCF-Datei...
Und auf einmal kannst du die bisher unverdrahteten Ports deines Anzeige
auch noch verdrahten:
Anzeiger : twoseven
port map(CLOCK=>CLOCK,inp0=>con0,inp1=>con1,inp2=>con2,inp3=>con3,
AN0=>AN0,AN1=>AN1,AN2...,LED=>LED);
BTW:
Geber : timer
port map(CLOCK,con0,con1,con2,con3);
Mach das besser wie in der anderen Port-Liste nicht nach Position,
sondern mit expliziten Namen (wie im Anzeiger:twoseven auch).
Ok danke. Das habe ich jetzt mal gemacht, und jetzt meckert die IDE zu
mindestens nicht mehr herum. Allerdings wird jetzt auf der Anzeige
irgendwas ausgegeben, was sich ändert, wenn ich die Buttons auf dem
Board betätige.
Folglich scheint es irgendwo noch ein Problem zu geben, und die
Anschlüsse "hängen scheinbar in der Luft".
Hast du eine Idee, woran das liegen kann? Funktioniert der Zeitgeber so,
wie ich mir das gedacht habe? Eigentlich müssten da ja konstante Werte
auf den Ports liegen.
Die aktuelle Uhr.vhd ist im Anhang.
Ok. Jetzt scheint alles zu funktionieren. Anscheinend war irgendetwas in
der IDE faul. Nach einem Project Clean funktioniert alles wie gewollt.
Jetzt würde mich noch interessieren, wie man einen möglichst genauen 1Hz
Takt erzeugt. Hat dafür jemand Tipps? Nimmt man dafür auch einfach einen
Zähler, und zählt diesen bis 50*10^6 hoch (Mein Board arbeitet mit 50
MHz), oder gibt es da elegantere Varianten?
Hier die aktuelle Zeitgeber.vhd. Es werden die Sekunden und die Minuten
auf der Anzeige ausgegeben(besser zum testen :-)).
Als nächstes werde ich versuchen die Sekunden binär über ein paar LEDs
ausgeben zu lassen, und im Takt dazu den Trennpunkt der Anzeige blinken
zu lassen.
Als nächstes geht es dann an die Benutzereingabe, damit man die Uhr auch
stellen kann.
Florentin S. schrieb:> Nimmt man dafür auch einfach einen Zähler, und zählt diesen> bis 50*10^6 hoch (Mein Board arbeitet mit 50 MHz),
Jain...
Korrekt wäre: man zählt 50000000 Takte. Das sind von 0...49999999
1
:
2
signalcounter:integerrange0to50000000-1;
3
:
4
if(counter<50000000-1)then
5
counter<=counter+1;
6
else
7
counter<=0;
8
:
Übrigens ein immer wieder gern gemachter Fehler.... ;-)
Lothar Miller schrieb:> Übrigens ein immer wieder gern gemachter Fehler.... ;-)
Oh ja ich vergaß. Die Informatiker fangen ja bei 0 an mit zählen :-).
Beim einbauen des blinkenden Punktes sind mir gleich noch ein paar
Sachen aufgefallen.
Wenn man die Schnittelle im entity verändert muss man diese ja auch in
allen Architekturen ändern, in denen das entity über ein component
eingebunden ist. Das ist ja nicht gerade wartungsfreundlich. Gibt es da
einen Trick, oder muss man das einfach hinnehmen?
Des Weiteren hat mein Geber als Output nur einen Punkt. In das Interface
der Anzeige habe ich jedoch alle 4 Punkte eingebaut, da man die Anzeige
so ja auch für evtl. andere Projekte nutzen kann. Wie handhabt man am
elegantesten die nicht genutzten Ports(also die am Eingang der Anzeige).
Im Moment habe ich in der Anzeigen Schnittstelle, und auch beim
einbinden via component, die Ports mit einem Standard Wert belegt. Beim
Port Map habe ich diese Ports auf open gelegt. Trotzdem zeigt die IDE
noch Warnungen an. Also kann das scheinbar noch nciht ganz optimal sein.
Florentin S. schrieb:> Wenn man die Schnittelle im entity verändert muss man diese ja auch in> allen Architekturen ändern, in denen das entity über ein component> eingebunden ist. Das ist ja nicht gerade wartungsfreundlich. Gibt es da> einen Trick, oder muss man das einfach hinnehmen?
Sigasi VHDL Eclipse Plugin, dann geht das über Refactoring.
Florentin S. schrieb:> Wenn man die Schnittelle im entity verändert muss man diese ja auch in> allen Architekturen ändern, in denen das entity über ein component> eingebunden ist. Das ist ja nicht gerade wartungsfreundlich.
Abgesehen von irgendwelchen Managementsystemen ist das wie in einem
C-Programm: wenn du dort z.B. eine Funktionsdeklaration änderst, mußt du
auch an jeder betroffenen Stelle nachbessern.
> Beim Port Map habe ich diese Ports auf open gelegt. Trotzdem zeigt> die IDE noch Warnungen an.
Sind das tatsächlich Warnungen oder nur Infos?
In welchem Prozessschritt?
Florentin S. schrieb:> Beim> Port Map habe ich diese Ports auf open gelegt. Trotzdem zeigt die IDE> noch Warnungen an. Also kann das scheinbar noch nciht ganz optimal sein.
Doch, das passt schon. Irgendwann wird man von ISE bzw. XST so mit
Warnungen zugemüllt, so das die nicht mehr richtig hilfreich sind :-(
Leider hilft da der Message Filter auch nur bedingt.
Ich guck immer nach, ob folgende Warnungen auftauchen:
1
WARNING:Xst:737 --> unwanted Latches
2
WARNING:Xst:653 --> nicht zugewiesene (aber verwendete) Signale
Xst:752[...]Unconnected input port 'p0i' of component 'twoseven' is tied to default value
Ich werde mich jetzt als nächstes an die Benutzerschnittstelle, sprich
tasten zum Zeit stellen machen. Die Taster müssen ja vermutlich noch
entprellt werden. Was ist denn dafür die effektivste Methode?
Florentin S. schrieb:> Die Taster müssen ja vermutlich noch> entprellt werden. Was ist denn dafür die effektivste Methode?
Alle x Millisekunden den Wert einlesen (x = 10...100) und nach dem
Muster "001" suchen.
Duke