Nabend! Ich habe eine (für die meisten wahrscheinlich ganz triviale) Frage: Wird VHDL sequentiell (zum Beispiel wie C) abgearbeitet oder nicht? Denn wenn Ja; Wie macht man das dann z.B. mit einem Ripple-Carry-Addierer. Würde hier alles parallel berechnet, dann sind die ganzen Carry-Bits der vorherigen Volladdierer ja noch gar nicht "fertig" o.O Vielen Dank für die Erhellung..
Gute Frage. Du musst das taktweise betrachten. Zwischen zwei Taktflanken wird parallel abgearbeitet, aber während der Taktperiode sequentiell. Bei dem Ripple-Carry legst du das Ergebnis an und nach einem Takt ist das Ergebnis berechnet. Allerdings läuft die Kette nacheinander durch. Das ist auch der begrenzende Faktor für den Takt. Alle 'gleichzeitig' ablaufenden Prozesse müssen während einer Taktperiode abgearbeitet werden können.
>Wird VHDL sequentiell (zum Beispiel wie C) abgearbeitet oder nicht? Weder noch! Aber wenn man mal ausser acht lässt, das VHDL nicht "abgearbeitet" wird, in dem Sinne wie ein Programmtext durch einen Interpreter interpretiert wird dann muss die Antwort wohl Sowohl als auch! lauten. Das wird Dich vielleicht zum lachen bringen aber dennoch ein wenig frustrieren. Der Punkt ist, das Du in VHDL Schaltungsstrukturen beschreibst. Als solche sind per se alle Schaltungsteile gleichzeitig aktiv und reagieren gleichzeitig auf die jeweiligen Änderungen ihrer Eingangssignale. Durch die Anordnung der Elemente erhälst Du gewisse sinnreiche Folgen von Verarbeitungsschritten. Eine Vereinfachung eines komplexen Ablaufes, wie er durch die Signallauf- und Verarbeitungszeiten entsteht, kann erreicht werden (und wird auch dringend empfohlen, aber auch darin gibt es Kontroversen) indem man die Gesamtaufgabe zeitlich in Teilschritte zerlegt, und über Register und Flip-Flops jeweisl Teilresultate an nachfolgende Kombinatorische Teile weiterreicht. In diesem letzteren Sinne, aber wohlgemerkt aufgrund der Befolgung einer Empfehlung, erfolgen Aktionen nacheinander. Von einer "Verarbeitung" zur Laufzeit des FPGA kann aber eindeutig nicht die Rede sein. Dein Beispiel eines Ripple-Ripple-Carry-Addiererdas Paradebeispiel einer Struktur die dieser zuletzt erwähnten Empfehlung nicht folgt. Wie Du richtig erkannt hast: >Würde hier alles parallel berechnet, dann sind die ganzen Carry-Bits der >vorherigen Volladdierer ja noch gar nicht "fertig" gibt es nach der Änderung der Eingangssignale eine Zeitlang ungültige Ergebnisse. Genauso richtig, qualifizierst Du diese "Zeitlang" als den bis alle "vorherigen" Volladerer "fertig" sind. An und für sich (die erwähnte Kontroverse zwischen den "Synchronen Menschen" und den Asynchronen Menschen" erstmal ausser acht gelassen) ist das nicht weiter negativ. Man muss es nur wissen und beachten, in dem man die Durchlaufzeit von den Eingängen des ersten Addierers bis zu den Ausgängen des letzten Addierers abwartet bevor man das Ergebnis abliest. Das prinzipiell analoge Bild ergibt sich auch bei einem Parallel-Addierer. Auch hier muss eine gewisse Zeit abgewartet werden bis das Ergebnis gültig ist. Aufgrund der Struktur, die logisch völlig zu dem Ripple-Addierer identisch ist (und sein muss, sonst wäre es keine Addierer), ist aber diese Zeit deutlich kürzer. Wesentlich aber ist, das die Zeit nicht mehr von der Anzahl der Stellen abhängt.
WieWo schrieb: > Nabend! > Ich habe eine (für die meisten wahrscheinlich ganz triviale) Frage: > > Wird VHDL sequentiell (zum Beispiel wie C) abgearbeitet oder nicht? Falscher Ansatz. Klingt jetzt hart, ist aber sinnvoll ;-) Ich nehme an, du möchtest Hardware synthetisieren. Hardware besteht aus Schaltnetzen und Flipflops. Nun ist das ja so, dass Hardware eigentlich kein 'nacheinander' kennt. Gut, hier und da etwas Laufzeit, aber die ist praktisch klein. Deine Konstruktion wird hier und da etwas zappeln, wenn sich Eingangssignale verändern, aber nach kurzer Zeit ist wieder Ruhe und die Konstruktion gelangt in einen stabilen Zustand. Das ist all jenes Zeug, was du in VHDL direkt hinschreiben kannst. Zuweisungen, bedingte Zuweisungen, logische Operationen und so weiter. Alles, was außerhalb von Prozessen steht. Völlig egal, in welcher Reihenfolge du es notierst. Alles wird unmittelbar in irgendwelche Logik-Gatter verschaltet; daran siehst du auch den Grund, warum ein Signal nur an genau einer Stelle zugewiesen werden darf. Bei ehreren Zuweisungen an dasselbe Signal hintereinander gilt nicht die letzte Zuweisung, sondern es gibt sofort eine Fehlermeldung. Prozesse sind ja vermutlich das, was dich gerade stutzig gemacht hat: Da kann man 'if' und 'case' benutzen, mehrere Zuweisungen hintereinander funktionieren wie in einer Programmiersprache. Das hat aber nichts damit zu tun, dass da irgendetwas sequentiell läuft - auch Prozesse werden strikt zu Logik-Gattern verschaltet! Wie? So: VHDL funktioniert wie Papier und Bleistift. Ein Prozess in VHDL bedeutet nur, dass du ein Blatt Papier hernimmst und die letzten Zustände aller Signale aufschreibst. Das, was jetzt auf dem Papier steht, heißt Eingangsvektor. Der Vektor hängt ja beispielsweise irgendwie von den Eingangssignalen der gesamten Schaltung ab. Dann liest du dir den Prozess von oben bis unten durch: Wo immer einem Signal ein Wert zugewiesen wird, kritzelst du den Zustand durch und schreibst den neuen daneben. Und wenn noch eine Zuweisung für dasselbe Signal kommt, streichst du halt nochmals durch und notierst daneben. Und wenn ein Signal in Abhängigkeit von einem anderen zugewiesen wird, ist diese Abhängigkeit immer vom Eingangsvektor und nicht von deinem Gekritzel (!). Wenn du fertig mit dem Prozess bist, guckst du dir den Schmierzettel an. Da steht jetzt der Ergebnisvektor drauf. Und du überlegst dir jetzt eine Logik-Schaltung, die den Eingangsvektor von vorhin irgendwie zum Ergebnisvektor verknüpft. Fertig. Ich habe oben von einer Abhängigkeit immer vom Eingangsvektor geschrieben. Das hat eine wichtige Konsequenz: Es macht den sequentiellen Charakter der Prozesse platt. Nimm folgendes Beispiel:
1 | signal a: STD_LOGIC := '0'; |
2 | signal b: STD_LOGIC := '0'; |
3 | |
4 | process (a, b) is |
5 | begin
|
6 | a <= '1'; |
7 | if a = '1' then |
8 | b <= '1'; |
9 | end if; |
10 | |
11 | a <= '0'; |
12 | end process; |
Hier werden die beiden Signale 'a' und 'b' immer '0' sein. Nach obigem Schema, du schreibst dir zu Beginn den Eingangsvektor auf:
1 | a 0 | |
2 | b 0 | |
Erste Zeile durchdenken:
1 | a 0 | 1 |
2 | b 0 | |
if-Anweisung durchdenken, wohl gemerkt: 'a' ist nicht das Gekritzel, sondern nach wie vor der Eingangsvektor! 'a' ist '0', das if wird nicht durchlaufen:
1 | a 0 | 1 |
2 | b 0 | |
Letzte Zeile: '1' streichen und '0' daneben kritzeln:
1 | a 0 | (1) 0 |
2 | b 0 | |
'a' ist also am Ende immer '0' und 'b' hat sich nie verändert. Auf diese Weise kannst du jeden Prozess platt machen in kombinatorische Logik, damit erübrigt sich die Frage nach sequentiell oder nicht.
Sven P. schrieb: > Ich habe oben von einer Abhängigkeit immer vom Eingangsvektor > geschrieben. Das hat eine wichtige Konsequenz: Es macht den > sequentiellen Charakter der Prozesse platt. Jetzt warte ich gespannt auf die Variablen, die sich ja "sofort" ändern, und deshalb so gern von ehemaligen Softwareprogrammierern verwendet werden... ;-) WieWo schrieb: > Wird VHDL sequentiell (zum Beispiel wie C) abgearbeitet oder nicht? Ja. > Denn wenn Ja; Wie macht man das dann z.B. mit einem > Ripple-Carry-Addierer. Würde hier alles parallel berechnet, dann sind > die ganzen Carry-Bits der vorherigen Volladdierer ja noch gar nicht > "fertig" o.O Es dauert ein paar hundert ps, bis die komplette Carry-Chain durchlaufen ist, aber das kommt nicht daher, dass die "Befehle" nacheinander "abgearbeitet" werden, sondern daher, dass die Logik der Carry-Kette und die Verdrahtung zwischen den Addierern eine gewissen Laufzeit haben und somit das Carry durch die Addiererkette einfach "durchrieselt" (daher kommt auch der Name "to ripple"). Aber der komplette Addierer existiert parallel in Hardware, er wird nicht Bit für Bit berechnet...
Lothar Miller schrieb: > Sven P. schrieb: >> Ich habe oben von einer Abhängigkeit immer vom Eingangsvektor >> geschrieben. Das hat eine wichtige Konsequenz: Es macht den >> sequentiellen Charakter der Prozesse platt. > Jetzt warte ich gespannt auf die Variablen, die sich ja "sofort" ändern, > und deshalb so gern von ehemaligen Softwareprogrammierern verwendet > werden... ;-) This page was intentionally left blank...
Weiso? Ein paar Hundert Pikosekunden sind ne halbe Nanosekunde. Ist doch realistisch.
Ach. Ich schlag mich gerade mit einem rum, für den 10ns pro Gatter schon Turbo sind.
Hmm schrieb: >>Es dauert ein paar hundert ps... > Picosekunden? Ich will auch so'n FPGA!!! Für die Durchlaufzeit durch eine LUT (bzw. einen CLB) findest du in den Datenblättern Zeiten zwischen 200ps und 700ps... Dazu kommt natürlich noch die Verdrahtung. Aber gerade bei der Carry-Chain kannst du sicher sein, dass sie effizient implementiert ist, denn jeder Zähler braucht diese Kette. Hmm schrieb: > Ach. Ich schlag mich gerade mit einem rum, für den 10ns pro Gatter schon > Turbo sind. Welche Technologie?
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.