Forum: FPGA, VHDL & Co. Process in VHDL, wie funktioniert das genau??


von noips (Gast)


Lesenswert?

Hallo allerseits,

ich erlerne nach und nach anhand von mehreren Websites VHDL. Eine von 
den Sachen, die mir unklar sind, ist der Process. In allen Quellen, die 
ich dazu gefunden habe heißt es, enthält ein Process sequentielle 
Anweisungen, die nach Aktivierung des Processes ähnlich wie bei 
gewöhnlichen Programmiersprachen nacheinander ausgeführt werden. Aber 
mir ist nicht klar, was genau ich darunter vorstellen muss. Nach einer 
ausführlicheren Erklärung habe ich bisher vergeblich gesucht. Kann mir 
vielleicht jemand von euch das klar machen?

Was heißt es denn jetzt genau "nacheinander ausgeführt" z.B. in diesem 
Code hier:
1
entity AND_OR_XOR is
2
  port (A,B                :  in bit;
3
        Z_OR, Z_AND, Z_XOR : out bit);
4
end AND_OR_XOR;
5
   
6
architecture RTL of AND_OR_XOR is
7
begin
8
9
   A_O_X:  process  (A, B)
10
    begin
11
      Z_OR   <= A or B;
12
      Z_AND <= A and B;
13
      Z_XOR <= A xor  B;
14
     end process  A_O_X ;
15
 
16
end RTL;

Heißt es, dass beim ersten Takt nach der Aktivierung des Prozesses hier 
der Ausgang Z_OR den Zustand entsprechen dem Ergebnis des Ausdrucks A or 
B annimmt. Beim zweiten Takt nimmt der Ausgang Z_AND den Wert A and B an 
und beim dritten Takt entsprechend Z_XOR <= A xor  B. Unter 
sequentieller Ausführung würde ich nur so ein Verhalten verstehen. 
Allerdings habe ich aus meinen bisherigen Programmierversuchen eher den 
Eindruck, dass in diesem Prozess alle drei Ausgänge gleichzeitig den 
Wert der entsprechend zugewiesenen logischen Verknüpfung annehmen.

Was stimmt denn jetzt in Wirklichkeit und was bedeutet in diesem Fall 
"sequentielle Anweisung"?

Danke schon mal für die Mühe!!

von enan (Gast)


Lesenswert?

Dieser Prozess hat mit Takten wenig zu tun.
Mir fehlt da
if rising_edge(clk)...
nur der reset sollte asynchron sein.

von TM (Gast)


Lesenswert?

Hey,

Das sollte ein kombinatorische Prozess sein sobalt sich die die Signale 
in der Sensitivity List ändern wird alles im Process kombinatorisch 
ausgeführt.

Ist in diesem Fall also quasi nur eine besser lesbare Beschreibung für 
ein Kombinatorisches Verhalten.

von noips (Gast)


Lesenswert?

> Dieser Prozess hat mit Takten wenig zu tun.

Diesen Code habe eins zu eins einfach von dieser Seite kopiert:
http://www.vhdl-online.de/tutorial/englisch/t_40.htm#pgfId-1015035

Und die Erklärungen die neben bzw. unter diesem Code auf der Seite 
stehen (sich dann also auch auf diesen Code beziehen), sagen dass die 
Anweisungen im Prozess nacheinander ausgeführt werden.

von Juri (Gast)


Lesenswert?

Wie TM bereits gesagt hat: Das Beispiel ist kein getakteter Process, 
sondern nur ein kombinatorischer Process. Alle Zuweisungen werden daher 
immer gleichzeitig ausgeführt! Dein Beispiel soll nur den Gebrauch der 
Sensitivy List verdeutlichen!

von noips (Gast)


Lesenswert?

Danke für die Atnworten!

Sagen wir mal, der Prozess würde so aussehen:
1
A_O_X:  process  (clk, rst)
2
    begin
3
      if rst = '0' then
4
        Z_OR <= '0';
5
        Z_AND <= '0';
6
        Z_XOR <= '0';
7
      elsif rising_edge (clk) then
8
        Z_OR   <= A or B;
9
        Z_AND <= A and B;
10
        Z_XOR <= A xor  B;
11
      end if;
12
     end process  A_O_X ;

Werden hier dann die drei Zuweisungen jeweils nacheinander im Abstand 
von einem Takt ausgeführt oder werden sie in einem einzigen Takt 
gleichzeitig ausgeführt?

von TM (Gast)


Lesenswert?

In einem Takt gleichzeitig.
Für das was du hast das du etwas nach einander ausführen willst wäre 
eine Statemachine notwendig.

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


Lesenswert?

enan schrieb:
> nur der reset sollte asynchron sein.
Ja, nun. Das gerade nicht...
Siehe den Beitrag "vhdl-richtlinien f. synthese?"

>>>    A_O_X:  process  (A, B)
Der Prozess muss neu berechnet werden, wenn sich A bzw. B irgendwie 
ändern.

Und dann geht es los:
>>>    begin
>>>      Z_OR   <= A or B;
>>>      Z_AND <= A and B;
>>>      Z_XOR <= A xor  B;
>>>    end process  A_O_X ;
In der (virtuellen) Zeit 0 wird der Prozess duchlaufen und am Ende des 
Prozesses die Werte an die entsprechenden Signale zugewiesen.

In der realen Welt werden dafür dann einfach 3 Gatter erzeugt, an die 
parallel die beiden Eingangssignale angeschlossen sind.

noips schrieb:
> sagen dass die Anweisungen im Prozess nacheinander ausgeführt werden.
Sie werden lediglich in der Simulation nacheinander berechnet. In der 
Hardware existieren 3 getrennte Gatter. Die Hardware ist exakt die selbe 
wie bei dieser Beschreibung:
1
entity AND_OR_XOR is
2
  port (A,B                :  in bit;
3
        Z_OR, Z_AND, Z_XOR : out bit);
4
end AND_OR_XOR;
5
   
6
architecture RTL of AND_OR_XOR is
7
begin
8
      Z_OR  <= A or B;
9
      Z_AND <= A and B;
10
      Z_XOR <= A xor  B;
11
end RTL;

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


Lesenswert?

noips schrieb:
> Sagen wir mal, der Prozess würde so aussehen:A_O_X:  process  (clk, rst)
>  ...
> Werden hier dann die drei Zuweisungen jeweils nacheinander im Abstand
> von einem Takt ausgeführt oder werden sie in einem einzigen Takt
> gleichzeitig ausgeführt?
Sie werden deshalb gleichzeitig ausgeführt, weil ein Prozess in der 
Zeit 0 berechnet wird.
Wenn also ein Takt kommt, werden alle 3 Ergebnisse gleichzeitig neu 
berechnet. Diese Berechnung erfolgt nur auf dem Simulationsrechner 
nacheinander, währenddessen läuft aber die Simulationszeit nicht weiter!

von noips (Gast)


Lesenswert?

Besten Dank für die Antworten!

Lothar Miller schrieb:
> In der
> Hardware existieren 3 getrennte Gatter. Die Hardware ist exakt die selbe
> wie bei dieser Beschreibung:

Genau so habe ich es mir vorgestellt. Diese Erklärungen mit der 
sequentiellen Abarbeitung hat mich nur durcheinander gebracht. Dann 
beziehen sich die Erklärungen ja nur auf das Verhalten in der Simulation 
und nicht auf die synthetisierte Hardware, sehe ich es jetzt richtig?

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


Lesenswert?

noips schrieb:
> Dann beziehen sich die Erklärungen ja nur auf das Verhalten
> in der Simulation und nicht auf die synthetisierte Hardware,
> sehe ich es jetzt richtig?
Ja.
Für die Simulation ist eine korrekte Sensitivliste unbedingt nötig. Wenn 
du mal diese Beschreibung nimmst:
1
entity AND_OR_XOR is
2
  port (A,B,CLK            :  in bit;
3
        Z_OR, Z_AND, Z_XOR : out bit);
4
end AND_OR_XOR;
5
   
6
architecture RTL of AND_OR_XOR is
7
begin
8
9
   A_O_X:  process  (CLK)
10
    begin
11
      Z_OR  <= A or  B;
12
      Z_AND <= A and B;
13
      Z_XOR <= A xor B;
14
    end process  A_O_X ;
15
 
16
end RTL;
Dann sieht das in der Simulation so aus, als ob das Ergebnis irgendwas 
mit CLK zu tun hätte, denn nur bei einer Änderung von CLK ändert sich 
das Ergebnis.
Die Synthese wird dir aber nur ein paar Infos zum Thema 
"unvollständige Sensitivliste" ausgeben und dann die nötigen 3 Gatter 
erzeugen.
Fazit: Simulation falsch...  :-o

von noips (Gast)


Lesenswert?

ich bedanke mich für die Hilfe!!

von brando (Gast)


Lesenswert?

noips schrieb:
>Genau so habe ich es mir vorgestellt. Diese Erklärungen mit der
>sequentiellen Abarbeitung hat mich nur durcheinander gebracht. Dann
>beziehen sich die Erklärungen ja nur auf das Verhalten in der Simulation
>und nicht auf die synthetisierte Hardware, sehe ich es jetzt richtig?

Wenn Du mit Variablen arbeitest, dann stimmt wiederum der Ausdruck 
sequentielle Abarbeitung. Eine Variable kann einen Zustand annehmen und 
danach kann wieder von ihr gelesen werden.

A_O_X:  process  (clk, rst)
    variable Var_B : std_logic;
    begin
      if rst = '0' then
        A <= '0';
        B <= '0';
        C <= '0';
      elsif rising_edge (clk) then
        B <= A or B;
        C <= B; -- Zustand um einen Takt älter als A

        Var_B := A or B;
        A <= Var_B;  -- Zustand um einen Takt schneller als C
      end if;
     end process  A_O_X ;

variable Var_Intern_2 : PRBS_REGISTER;




Eine weitere Sache die mir spontan einfällt: wenn beispielsweise in 
Zeile 10 ein Signal A den Zustand 1 einnehmen soll und in Zeile 100 
wiederum den Zustand 2, dann wird die Zeile 10 ignoriert!

A_O_X:  process  (clk, rst)
    begin
      if rst = '0' then
        A <= '0';
      elsif rising_edge (clk) then
        A <= '0'; -- Zuweisung 1 wird von Zuweisung 2 aufgehoben
        ............
        A <= '1';
      end if;
     end process  A_O_X ;

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


Lesenswert?

brando schrieb:
> Wenn Du mit Variablen arbeitest, dann stimmt wiederum der Ausdruck
> sequentielle Abarbeitung. Eine Variable kann einen Zustand annehmen und
> danach kann wieder von ihr gelesen werden.
Allerdings erscheint auch hier ein "Zwischenwert" niemals in der realen 
Hardware. Die Signalzuweisung erfolgt immer am Ende des Prozesses, der 
wiederum in der Zeit 0 abgearbeitet wird...
1
      elsif rising_edge (clk) then
2
        B <= A or B;
3
        C <= B; -- Zustand um einen Takt älter als A
4
      end if;
Es wird der gesamte Prozess mit den "alten" Werten von A, B und C 
druchgerechnet. Deshalb gibt das hier eigentlich 2 Prozesse:
1
      process...
2
      if rising_edge (clk) then
3
        B <= A or M;
4
      end if;
5
      
6
      process...
7
      if rising_edge (clk) then
8
        C <= B; -- Zustand um einen Takt älter als A
9
      end if;
Und jetzt ist klar: mit der nächsten steigenden Flanke wird der aktuelle 
Wert von B nach C geschrieben. Und es wird ein neuer Wert für B aus A 
und M berechnet.

brando schrieb:
> Eine weitere Sache die mir spontan einfällt: wenn beispielsweise in
> Zeile 10 ein Signal A den Zustand 1 einnehmen soll und in Zeile 100
> wiederum den Zustand 2, dann wird die Zeile 10 ignoriert!
Also stimmt auch hier der Begriff sequentielle Abarbeitung... :-o


BTW:
      if rst = '0' then
        A <= '0';
        B <= '0';
        C <= '0';
      elsif rising_edge (clk) then
        B <= A or B;
Das ist ein "Selbsthalter"...  ;-)
Wenn A irgendwann mal '1' wird, dann bleibt B fürderhin '1'...

von Ben G. (benson85)


Lesenswert?

Hallo,

ich hätte zu diesem Thema auch noch eine kleine Frage und zwar genau 
dann wenn ich z.B. 10 Variablen in meinem Prozess habe.
Nun hab ich einen relativ hohen Clock (beispielsweise 100 MHz) in der 
Sensitivitätsliste, mache aber eine relativ große Berechnung in diesem 
Prozess. Da die Variablen ja nun wirklich sequentiell abgearbeitet 
werden ist dies ja nicht immer komplett gleichzeitig in Gattern 
auszuführen bzw. benötigt evtl mehr Zeit als die Periodendauer meines 
Clocks.
Was passiert wenn ein neues Clock-Event auftaucht die vorherige 
Berechnung aber noch nicht abgeschlossen ist? Ist der Prozess dann 
gesperrt (ähnlich wie ein Mutex in C) und ich verpasse eventuell ein 
Clockevent oder wird der laufende Prozess einfach unterbrochen und neu 
gestartet?
Falls dem so ist wie lässt sich dieses Problem beseitigen, ist hier 
Pipelining das richtige Stichwort und spricht man bei so einem Problem 
generell von Timing Problemen im FPGA?

Mich interessiert hier hauptsächlich die synthetisierte Version, also 
das Verhalten im bspw. einem FPGA. Ich denke mit reiner Simulation 
lassen sich Probleme dieser Art nicht erkennen bzw vernünftig lösen...

Vielen Dank.
Benson

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


Lesenswert?

Ben G.. schrieb:
> Da die Variablen ja nun wirklich sequentiell abgearbeitet
> werden ist dies ja nicht immer komplett gleichzeitig in Gattern
> auszuführen bzw. benötigt evtl mehr Zeit als die Periodendauer meines
> Clocks.
Doch. Die Variablen werden ebenfalls garantiert parallel in Gatter 
abgebildet. Evtl. eben in mehreren Logikebenen hintereinander.
Ein Process (mit nur einem Takt bzw. wait) wird immmer in der 
theoretischen Zeit 0 abgearbeitet. Und das geht in der Realität nur, 
wenn keine 2. Registerebene vorhanden ist.

> Was passiert wenn ein neues Clock-Event auftaucht die vorherige
> Berechnung aber noch nicht abgeschlossen ist?
Dann ist dein Takt einfach zu schnell für dein Design. Und dann kann 
alles passieren...
Aber dann hattest du deine Timing-Constraints (wenigstens die 
Taktfrequenz) nicht richtig gesetzt. Denn sonst hätte die Implementation 
herumgemeckert, dass dein Design die gewünschte Frequenz nicht erreicht.

> Falls dem so ist wie lässt sich dieses Problem beseitigen, ist hier
> Pipelining das richtige Stichwort und spricht man bei so einem Problem
> generell von Timing Problemen im FPGA?
Ja, Pipelining heißt erst mal, dass mehrere "Zwischenregister" 
eingeführt werden, vor die jeweils nur soviel Logik kommt, dass der 
entsprechende Logikpfad schnell genug ist.
Ein Stichwort dazu ist auch "Register Balancing". Damit werden 
"automatisch" weitere Registerstufen eingeführt...

> Ich denke mit reiner Simulation
> lassen sich Probleme dieser Art nicht erkennen bzw vernünftig lösen...
Eine Timing-Simulation könnte das aufdecken. Aber wie gesagt: vernünftig 
gesetzte Timing-Constraints zeigen solche Fehler schon bei der 
Implementation auf.

von D. I. (Gast)


Lesenswert?

Ben G.. schrieb:
> Hallo,
>
> ich hätte zu diesem Thema auch noch eine kleine Frage und zwar genau
> dann wenn ich z.B. 10 Variablen in meinem Prozess habe.
> Nun hab ich einen relativ hohen Clock (beispielsweise 100 MHz) in der
> Sensitivitätsliste, mache aber eine relativ große Berechnung in diesem
> Prozess. Da die Variablen ja nun wirklich sequentiell abgearbeitet
> werden ist dies ja nicht immer komplett gleichzeitig in Gattern
> auszuführen bzw. benötigt evtl mehr Zeit als die Periodendauer meines
> Clocks.
> Was passiert wenn ein neues Clock-Event auftaucht die vorherige
> Berechnung aber noch nicht abgeschlossen ist? Ist der Prozess dann
> gesperrt (ähnlich wie ein Mutex in C) und ich verpasse eventuell ein
> Clockevent oder wird der laufende Prozess einfach unterbrochen und neu
> gestartet?

Das ist dann eine Timing Violation. Was passiert ist ein Griff in die 
Flip-Flop-Wundertüte, mal schaltet es mal schaltet es nicht, mal ist es 
0 mal ist es 1.

von Klaus Falser (Gast)


Lesenswert?

Ben G.. schrieb:
> Was passiert wenn ein neues Clock-Event auftaucht die vorherige
> Berechnung aber noch nicht abgeschlossen ist? Ist der Prozess dann
> gesperrt (ähnlich wie ein Mutex in C) und ich verpasse eventuell ein
> Clockevent oder wird der laufende Prozess einfach unterbrochen und neu
> gestartet?

Die Anzahl der Variablen, bzw. die Anzahl der Anweisungen hat nichts zu 
sagen. Die Anweisungen werden NUR bei der Simulation wie eine 
Programmiersprache sequentiell ausgeführt und die Simulation läuft dann 
einfach langsamer.
Bei der Synthese wird eine Verschaltung des FPGA's erzeugt, bei der sich 
alle Signale gleich WIE IN DER SIMULATION verhalten. Diese Verschaltung 
kann mehr oder weniger komplex sein und dabei kann es manchmal 
passieren, dass doe internen Bauteile des FPGA's (jedes davon hat einen 
bestimmte Durchlaufzeit) so miteinander verschalten werden müssen, dass 
die Hardware zu langsam ist. In diesem Falle funktionieren Teile der 
Schaltung nicht korrekt, weil die Eingänge der Flipflops zum Zeitpunkt 
der Taktflanke noch nicht den korrekten Wert haben.
Das hat aber mit dem Durchlaufen des Prozesses nichts zu tun.

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


Lesenswert?

Nehmen wir mal ein Beispiel:
1
  process 
2
     variable a,b,c : std_logic;
3
  begin
4
    wait until rising_edge(clk);
5
    a := v and w;
6
    b := a and x;
7
    c := b and y;
8
    result <= not c;
9
  end process;

Das wird genau gleich implementiert wie das hier:
1
  process begin
2
    wait until rising_edge(clk);
3
    result <= not (v and w and x and y);
4
  end process;

Und weil es genau gleich implementiert wird, ist logischerweise die 
maximale Taktfrequenz genau gleich hoch...

von Ben G. (benson85)


Lesenswert?

Vielen Dank für die Antworten. Dann muss ich gestehen das ich den Aspekt 
der Timing Contraints immer etwas vor mir hergeschoben habe. Vom Prinzip 
her habe ich in die richtige Richtung gedacht, aber ich bin mal "gut 
Glück" davon ausgegangen das der FPGA schnell genug sein wird und die FF 
schnell genug schalten.

Ich habe das Thema Timing Constraints mal grob angeschnitten, allerdings 
war das Manual von Altera hierzu ziemlich mächtig. Prinzipiell benutze 
ich da den Time Quest Analyzer, wenn ich bspw 3 verschiedene Clocks von 
einer PLL erzeugen lasse gebe ich ja im Time Quest Analyzer die Daten zu 
den einzelnen Clocks an und weise sie den einzelnen Signale in meinem 
Design zu. Gibt es hierzu noch spezielle Dinge zu beachten bzw. Verweise 
auf gut erklärte Beispiele?

Wird denn bei der Synthese des Designs tatsächlich auch hinsichtlich der 
Angaben der Timing Constraints optimiert? Also in Bezug auf Anordnung 
der einzelnen Register etc, Signallaufzeiten usw. ?

Achja: Ich gebe zu die "Critical Warnings" bezüglich der fehlenden 
Timing Contraints in Quartus hab ich bewusst übersehen...Aber ich werde 
mich wohl ausführlicher darum kümmern.

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


Lesenswert?

Ben G.. schrieb:
> Wird denn bei der Synthese des Designs tatsächlich auch hinsichtlich der
> Angaben der Timing Constraints optimiert?
Nicht bei der Synthese ...
> Also in Bezug auf Anordnung der einzelnen Register etc,
> Signallaufzeiten usw. ?
... aber beim Place&Route. Gut erkannt.

> wenn ich bspw 3 verschiedene Clocks von einer PLL erzeugen lasse gebe ich
> ja im Time Quest Analyzer die Daten zu den einzelnen Clocks an und weise
> sie den einzelnen Signale in meinem Design zu.
Hört sich nach statischer Timinganalyse an...
Das wäre allerdings zu spät, denn dort wird das Design nur auf die 
Einhaltung von Timings kontrolliert. Vorgaben für das Design macht 
man schon früher im Constraints-File.

von Ben G. (benson85)


Lesenswert?

Das Constraints-File hängt aber von der Entwicklungsumgebung ab? Oder 
ist dies tatsächlich ein standardisiertes File welches ich selbst 
erstellen muss?

Ich habe nämlich nun unter Quartus im Time Quest Analyzer relativ 
komfortabel die Constraints gesetzt und in den Settings meines Projekts 
das automatisch erzeugte .sdc- File hinzugefügt.

Da ich die ALTPLL-Komponente benutze war er mit folgenden 2 Zeilen in 
der tcl Kommandozeile vollkommen zufrieden:

derive_pll_clocks -create_base_clocks
derive_clock_uncertainty

Wenn ich nun mein Projekt erneut compiliere sollte er doch beim 
Place&Route auf die Constraints-Vorgaben hin optimieren?

Die Critical Warnings sind nun abgeändert in "Timing requirements not 
met", was wohl auch stimmt da das Verhalten des FPGA's nicht mit der 
Simulation übereinstimmt.

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


Lesenswert?

Ben G.. schrieb:
> Das Constraints-File hängt aber von der Entwicklungsumgebung ab?
Ja, da kocht jeder Hersteller sein eigenes Süppchen...

> Wenn ich nun mein Projekt erneut compiliere sollte er doch beim
> Place&Route auf die Constraints-Vorgaben hin optimieren?
Die Tools werden nun (abhängig von Optimierungseinstellungen mehr oder 
weniger gut) versuchen, deine Vorgaben einzuhalten. Wenn sie das nicht 
schaffen, passiert sowas:
> Die Critical Warnings sind nun abgeändert in "Timing requirements not
> met", was wohl auch stimmt da das Verhalten des FPGA's nicht mit der
> Simulation übereinstimmt.
Ja, das Verhalten des FPGAs ist unbestimmt, wenn das Timing nicht 
eingehalten werden kann.

von Ben G. (benson85)


Lesenswert?

Ich habe nun alle Constraints gesetzt. Nun habe ich insgesamt 4 Prozesse 
in meinem Design.
Ein Prozess davon soll eine Division von 2 16 bit Integer Zahlen 
durchführen. Ich habe den Prozess soweit möglich von allen anderen 
arithmetischen operationen befreit, aber selbst mit einem Clock von 1 
MHz habe ich immer noch Probleme mit dem Timing, bzw. bekomme immer ein 
Critical Warning "Timing requirements not met"
Ich habe auch schon versucht die Division in optimierter Floating Point 
Division durchzuführen, dies brachte auch keinen Erfolg.

Hat hierzu jmd brauchbare Hinweise, auch wenn dies nun etwas off topic 
gerät...

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


Lesenswert?

Ben G.. schrieb:
> "Timing requirements not met"
Jetzt sollte dir die "Statische Timinganalyse" sagen können, welcher 
Signalpfad nicht erfüllt ist.

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.