Hallo zusammen, ich benötige eigentlich dauernd eine Flankenerkennung in VHDL, aber jedes mal ein zweites, taktverschobenes Signal zu erzeugen finde ich total umständlich. Vor allem, da man keine prozessinternen Signale definieren kann, sammeln sich in größeren Entities irgendwann ziemlich viele Signale in einer langen Liste an, es wird unübersichtlich und ziemlich viel redundante Schreibarbeit. Leider kann man auch keine Funktionen benutzen, da man dort keine Signale generieren darf. Eine Entity für jede Flankenerkennung zu erstellen wäre ähnlich unübersichtlich wie ein zusätzliches Signal. Gibt es da was eleganteres? Schöne Grüße, grtu
Ich kenne die Flankenerkennung mit einem 2-Bit-Schieberegister (2 D-Flipflops hintereinander), die erledigt gleichzeitig eine Synchronisierung mit einem zentralen Takt. Oder soll es asynchron sein, also quasi sofort reagieren?
Christoph db1uq K. schrieb: > Ich kenne die Flankenerkennung mit einem 2-Bit-Schieberegister (2 > D-Flipflops hintereinander), die erledigt gleichzeitig eine > Synchronisierung mit einem zentralen Takt. Oder soll es asynchron sein, > also quasi sofort reagieren? Ich meine genau so ein 2-Bit-Schieberegister.
A. G. schrieb: > ich benötige eigentlich dauernd eine Flankenerkennung in VHDL, aber > jedes mal ein zweites, taktverschobenes Signal zu erzeugen finde ich > total umständlich. Vor allem, da man keine prozessinternen Signale > definieren kann, sammeln sich in größeren Entities irgendwann ziemlich > viele Signale in einer langen Liste an, es wird unübersichtlich und > ziemlich viel redundante Schreibarbeit. Verstehe ich das richtig, dass du viele Flankenerkennungen innerhalb einer Entity benötigst? Dann würde ich das mit for ... generate erschlagen Wenn du immer mal wieder eine Flankenerkennung benötigst und so eine Art library call suchst, da gibts die Komponenten instantzierung (die lässt sich dann auch mit for ... generate kombinieren).
A. G. schrieb: > ich benötige eigentlich dauernd eine Flankenerkennung in VHDL, aber > jedes mal ein zweites, taktverschobenes Signal zu erzeugen finde ich > total umständlich. Vor allem, da man keine prozessinternen Signale > definieren kann, sammeln sich in größeren Entities irgendwann ziemlich > viele Signale in einer langen Liste an, es wird unübersichtlich und > ziemlich viel redundante Schreibarbeit. Zeig doch mal, was du da so umständlich machst oder als umständlich ansiehst. Wenn du es ganz geschickt machst, dann ist da gar keine Sensitivliste im Prozess: http://www.lothar-miller.de/s9y/archives/16-Takt-im-Prozess.html Damit gibts natürlich nur getaktete Prozesse. Kombinatorik wird dann aber auch ohne Sensitivliste mit nebenläufigen Anweisungen erschlagen. Und ein 2-Bit-Schieberegister geht etwa so:
1 | schieberegister <= schieberegister(0) & eingang when rising_edge(clk); |
Das erscheint mir jetzt nicht allzu lang... Siehe auch: http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung
:
Bearbeitet durch Moderator
A. G. schrieb: > Vor allem, da man keine prozessinternen Signale > definieren kann, sammeln sich in größeren Entities irgendwann ziemlich > viele Signale in einer langen Liste an, es wird unübersichtlich und > ziemlich viel redundante Schreibarbeit. Dafür gibt's in VHDL den Block. Damit kann man Signale, die nur lokal gebraucht werden, dort definieren, wo sie gebraucht werden.
Markus F. schrieb: > Damit kann man Signale, die nur lokal gebraucht werden, dort definieren, > wo sie gebraucht werden. Ich denke, hier ging es tatsächlich nur um die Sensitivliste, in die dann einfach alle Signale reinkommen, die im Modul deklariert werden. Oder alle, die im Prozess auftauchen. Obwohl es ein komplett synchroner Prozess ohne Reset ist... ;-)
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Markus F. schrieb: >> Damit kann man Signale, die nur lokal gebraucht werden, dort definieren, >> wo sie gebraucht werden. > Ich denke, hier ging es tatsächlich nur um die Sensitivliste, in die > dann einfach alle Signale reinkommen, die im Modul deklariert werden. > Oder alle, die im Prozess auftauchen. Obwohl es ein komplett synchroner > Prozess ohne Reset ist... ;-) Die Sensitivliste heisst bei mir meist ...(all). Das ist einigermassen überschaubar ;).
Mir ging es nicht um die Sensitivliste, sondern um die Deklaration am Beginn der Architecture. Lothar M. schrieb: > Und ein 2-Bit-Schieberegister geht etwa so:schieberegister <= > schieberegister(0) & eingang when rising_edge(clk); > Das erscheint mir jetzt nicht allzu lang... Das ist mir schon klar. Auch wenn es nicht lang ist, es ist dennoch etwas, das man prinzipiell automatisieren bzw. abstrahieren könnte. Ich denke der einzige Weg wäre aber, wie schon geschrieben wurde, als Entity.
A. G. schrieb: > Mir ging es nicht um die Sensitivliste, sondern um die Deklaration am > Beginn der Architecture. > > Lothar M. schrieb: >> Und ein 2-Bit-Schieberegister geht etwa so:schieberegister <= >> schieberegister(0) & eingang when rising_edge(clk); >> Das erscheint mir jetzt nicht allzu lang... > > Das ist mir schon klar. Auch wenn es nicht lang ist, es ist dennoch > etwas, das man prinzipiell automatisieren bzw. abstrahieren könnte. Ich > denke der einzige Weg wäre aber, wie schon geschrieben wurde, als > Entity. Nein. Kombiniere, was bereits gesagt wurde: Nehmen wir mal an, Du hast eine architecture wie folgt:
1 | architecture arch of xyz is |
2 | -- Hunderte von Signalen
|
3 | signal async_signal : std_ulogic; |
4 | signal sync_signal : std_ulogic; |
5 | begin
|
6 | -- Hunderte von Instanzierungen und Logiken
|
7 | |
8 | -- und irgendwo 199 Zeilen weiter unten brauchst Du plötzlich
|
9 | -- ein Sync-Register (das Du sonst nirgendwo brauchst, so dass
|
10 | -- eine separate Entity als Overkill erscheint.
|
11 | -- Dann nimm' einen Block:
|
12 | |
13 | sync_block: block |
14 | constant SYNC_LENGTH : integer := 2; |
15 | -- Block-Lokale Signale
|
16 | signal sync_register : array (SYNC_LENGTH downto 0) of std_ulogic; |
17 | begin
|
18 | sync_register <= sync_register(sync_register'length - 1) & async_signal when rising_edge(clk); |
19 | sync_signal <= sync_register(sync_register'high); |
20 | end block sync_block; |
21 | end architecture arch; |
Das Schieberegister ist so hübsch versteckt (genau dort, wo es gebraucht wird) und nach aussen siehst Du nur, was Du aussen brauchst. Mit dem (einfachen) Beispiel ist der Nutzen natürlich begrenzt, so ein Block hat aber m.E. vielerlei Verwendungsmöglichkeiten, um ein Design sehr viel lesbarer zu machen. Sieht man viel zu wenig, finde ich.
A. G. schrieb: > Markus F. schrieb: >> Nein. Kombiniere, was bereits gesagt wurde: > > Stimmt, das sieht gut aus. =) Prima. P.S.: ich sehe gerade, dass ich da noch zwei blöde Fehler eingebaut habe, aber die erkläre ich hiermit zum didaktischen Kniff und Du darfst sie selber finden ;)
:
Bearbeitet durch User
Lothar M. schrieb: > Ich denke, hier ging es tatsächlich nur um die Sensitivliste, in die > dann einfach alle Signale reinkommen, die im Modul deklariert werden. Naja, je mehr temporäre Zwischensignale man erzeugen muss, desto mehr sprechende Namen muss man sich einfallen lassen. VHDL verleitet dann noch dazu, sehr deutlich sprechende Namen zu verwenden...
S. R. schrieb: > VHDL verleitet dann > noch dazu, sehr deutlich sprechende Namen zu verwenden... Was nicht von Nachteil ist :-) Für die Flankenerkennung haben wir den Artikel.
A. G. schrieb: > ich benötige eigentlich dauernd eine Flankenerkennung in VHDL Auf den zweiten Blick frage ich mich: warum denn eigentlich "dauernd"? Eine Flankenerkennung samt Einsynchronisierung brauche ich ja nur beim Wechsel der Taktdomäne (z.B. um asynchrone externe Signale einzutakten). Innerhalb einer Taktdomäne arbeite ich mit Clock-Enables, die jeweils nur 1 Taktzyklus lang aktiv sind. Auf solche Signale muss ich dann keine Flankenerkennung mehr machen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.