Forum: FPGA, VHDL & Co. Clock-Signallaufzeit


von Daniel R. (dan066)


Lesenswert?

Ich habe eine Verständnisschwierigkeit, die sich bestimmt ganz schnell 
aufklären lässt:

Wie erreicht man, dass die Signalzuweisungen in einem 
aktaktenden-Register-Prozess alle gleichzeitig passieren, sodass race 
conditions nicht auftreten können?

Beispiel:
process (CLK)
begin
  if CLK='1' and CLK'event then
    SIG1_cs <= SIG1_ns;
    ...
    Sig100_cs <= Sig1_ns;
end process
Die _ns Signale sind Rechenergebnisse (nicht abgataktet), die _cs 
Signale sind Taktsynchron zu beschreiben, von eben diesem Prozess. Die 
_cs Signale werden außerdem nur gelesen und stehen in den jew. 
Sensitivlisten. So weit, so bekannt. SIG1_cs bis SIG100_cs stellen sehr 
viele FFs dar, die prinzipiell alle gleichzeitig über 
taktflankengesteuerte FFs mit ihren _ns Werten beschrieben werden, 
aufgrund ihrer Anzahl aber vermutlich über die ganze Chipfläche verteilt 
liegen. D.h. das CLK Signal braucht verschieden lange um die FFs zu 
erreichen.

Des Weiteren gibt es den Prozess
process (SIG1_cs, SIG50_cs)
variable calc:bit;
begin
  calc := SIG1_cs;
  calc := calc and SIG50_cs;
  ... oder ähnliche sehr kurze Berechnungen
  SIG50_ns <= calc;
end process
Angenommen das CLK Signal braucht "sehr kurz" um zum 
taktflankengesteuerten FF zu gelangen, das SIG1_cs durch SIG1_ns ersetzt 
und aufgrund phys. Entfernung braucht es "sehr lange" um zum FF zu 
gelangen, das SIG50_cs durch den Wert von SIG50_ns ersetzt.
Wird SIG1_cs beschrieben startet die Berechnung für SIG50_ns.

Woher weiß man nun, ob SIG50_cs den Wert erhält, den SIG50_ns VOR der 
Taktflanke hatte oder ob es den Wert erhält, den SIG50_ns bekommen hat 
NACHDEM die Taktflanke SIG1_cs beschrieben hat und durch den 
Berechnungsprozess ein neuer Wert für SIG50_ns berechnet wurde?
Ich würde pauschal sagen, die Zeitdifferenz zwischen dem ersten 
Erreichen des CLK-Signals an einem _ns Abtakt-FF und dem letzten 
Erreichen des CLK-Signals an einem _ns Abtakt-FF muss kleiner sein, als 
die kürzeste Signallaufzeit durch einen Prozess mit kombi. Logik.
Denn im genannten Beispiel oben, entscheidet ja einzig und allein die 
Länge der Signallaufzeit im Berechnungsprozess darüber ob SIG50_cs nun 
den Wert bekommt, den SIG50_ns hatte BEVOR oder NACHDEM SIG1_cs 
beschrieben wurde.

Für die Äußerung von Gedanken und Anregungen wäre ich sehr dankbar.

von Christian R. (supachris)


Lesenswert?

Naja, das weiß die Toolchain nach dem Place and Route. Du gibst im 
einfachsten Fall für ein komplett synchrones Design mit nur einem Takt 
ein Constraint vor, wie hoch die Periodendauer des Taktes ist. Und wenn 
alles durchgelaufen ist, sagt dir die Toolchain, ob das Timing passt, 
oder ob du Setup- bzw. Hold-Verletzungen hast. Normalerweise ist der 
Clock Skew auf den dedizierten Clock-Routing Pfaden so optimiert, dass 
alle FlipFlops auf dem gesamten FPGA nahezu gleichzeitig erreicht 
werden. Bei mehreren Takten und deren Takt-Übergängen oder asynchronen 
Schweinereien wirds natürlich dann etwas aufwendiger. Aber innerhalb des 
FPGA sollte man tunlichst alles sychron halten.

von Sigi (Gast)


Lesenswert?

Zum einen hast du ein Taktnetz, aus dem alle relevanten
FFs ihr Clock-Signal beziehen. Dies erfogt nicht perfekt,
so dass für alle FFs eine Spanne von [-Delta1 .. +Delta2]
gilt (folgt aus Device-Specs). Zum anderen sind deine
Signale mit einer Laufzeit (durch die Kombinatorik/lokale
Netzwerk) behaftet (kann nach Place&Route berechnet werden).

Nimmt man als Takt/Periodenlänge ClkLen, dann muss für
den einfachsten Fall alle Signallaufzeiten kleiner
ClkLen-Delta2-Delta1-FFHold-FFSetup sein (FFHold/FFSetup
aus Device-Specs), ein synchrones Design vorausgesetzt.
Denn ab ca. T+Delta2 sind alle "alten" Infos vollständig
vorhanden und müssen bis T+ClkLen-Delta1 durch die
Kombinatorik/lokales Netz gelaufen sein.

von Schlumpf (Gast)


Lesenswert?

Deine Toolchain kennt sowohl die Laufzeiten der Signale durch die ganze 
Logik und Routing als auch die Laufzeiten auf dem Taktnetz.
Wobei der Skew auf dem Taktnetz eher gering ausfällt.

Wenn du eine synchrone Beschreibung machst, in der der Ausgang des einen 
Registers durch eine Logik etc auf den Eingang eines zweiten Registers 
führt und diese beiden Register am selben Takt "hängen", dann weiss die 
Toolchain, dass sie es so routen muss, dass es passt.
Also dass mit dem ersten Takt der Ausgang des ersten Registers seinen 
Wert annimmt und mit "Eintreffen" des nächsten Taktes am Zielregister 
das Datum auf jeden Fall rechtzeitig am Zielregister anliegen muss.
Ob die zur Verfügung stehende Laufzeit sich aufgrund des Taktskews 
zwischen den beiden Registern ein wenig verlängert oder verkützt, 
berücksichtig die Toolchain.
Falls es nicht passt, bekommst du eine Meldung.

Fazit: Du musst dir eigentlich gar keinen Kopf drum machen.
Beschreibe alles schön synchron und dann passt das.

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


Lesenswert?

Daniel R. schrieb:
> Wie erreicht man, dass die Signalzuweisungen in einem
> aktaktenden-Register-Prozess alle gleichzeitig passieren, sodass race
> conditions nicht auftreten können?
Das ist die Aufgabe des FPGA-Designers. Dass das nicht passiert, dass 
die Taktverteilung symmetrisch ist, dass du dir keine Gedanken darum 
machen musst, dafür bezahlst du deinem FPGA-Lieferanten Geld. Und dann 
musst du selber nur noch dafür sorgen,

Aber wenn du ein ASIC machst, dann bist du selber dafür 
verantwortlich, wie der Takt durch dein Design läuft. Du hast dann 
Hilfmittel und musst selber das Taktnetz auf solche Zustände hin 
untersuchen.

Daniel R. schrieb:
> allein die Länge der Signallaufzeit im Berechnungsprozess
Ein Prozess hat keine Laufzeit! (da sollten viele Ausrufezeichen hin!)
Du hast hier die falsche Denkweise! Ein Prozess wird einfach in 
Kombinatorik und Flipflops umgesetzt. Und natürlich hat diese 
Kombinatorik Durchlaufzeiten, die korrelieren aber in keinster Weise 
mit der Reihenfolge der Zuweisungen im Prozess. Nehmen wir mal den hier:
1
  process (a,b,c,d) begin
2
     z <= a+b*c;
3
     y <= d;
4
  end process;
Natürlich wird hier die Zuweisung an y viel schneller fertig sein (das 
sind ja nur Verbindungen) als die Berechnung von z.

: Bearbeitet durch Moderator
von Daniel R. (dan066)


Lesenswert?

Lothar Miller schrieb:
> Ein Prozess hat keine Laufzeit! (da sollten viele Ausrufezeichen hin!)
> Du hast hier die falsche Denkweise! Ein Prozess wird einfach in
> Kombinatorik und Flipflops umgesetzt. Und natürlich hat diese
> Kombinatorik Durchlaufzeiten, die korrelieren aber in keinster Weise
> mit der Reihenfolge der Zuweisungen im Prozess. Nehmen wir mal den hier:
> process (a,b,c,d) begin
>      z <= a+b*c;
>      y <= d;
>   end process;
> Natürlich wird hier die Zuweisung an y viel schneller fertig sein (das
> sind ja nur Verbindungen) als die Berechnung von z.

Lothar Miller schrieb:
> Daniel R. schrieb:process (TRIGGER, CLK)
> variable vCLK:bit;
> begin
>   vCLK := CLK;
>   ... einige Anweisungen   <--- Diese Annahme ist GRUNDLEGEND falsch!
>   ... zur Verzögerung
>   CLK <= vCLK;
> end process
> Denn die Anweisungen in einem Prozess haben in der Hardware keine
> "Ausführungsreihenfolge".
> Das hier:process (a,b,c,d,e)
> variable v:bit;
> begin
>   v := a;
>   w <= a or b and c or d or e;
>   x <= v and c or d xor e;
>   y <= v or a and b or c;
>   z <= v;
> end process
> Ergibt exakt die selbe Hardware wie das hier:process (a,b,c,d,e)
> variable v:bit;
> begin
>   v := a;
>   z <= v;
>   y <= v or a and b or c;
>   x <= v and c or d xor e;
>   w <= a or b and c or d or e;
> end process

Ok, Signalzuweisungen in einem Prozess werden vom Synthesetool als 
nebenläufige Verdrahtungen mit oder ohne kombi. Logik umgesetzt (davon 
hängt dann ab in welcher Reihenfolge die Zuweisungen tatsächlich 
passieren). Also von den Zuweisungen
y <= v or a and b or c;
z <= v;
wird die zweite sicherlich zuerst abgeschlossen sein, da hier nur ein 
Draht notwendig ist und keine Logikzellen, wie bei der ersten Zuweisung.

Aber anders verhält es sich doch wenn man Variablen verwendet. Die 
Zuweisungen an Variablen laufen in der Reihenfolge ab, wie sie angegeben 
wurden. Deshalb ist es möglich:
1
process (SIG1)
2
variable var1:bit;
3
begin
4
  var1 := SIG1;
5
  if var1='1' then
6
    OUT <= '1';
7
  else
8
    OUT <= '0';
9
  end if
10
end process
zu schreiben, aber nicht:
1
process (SIG1)
2
signal tmp1:bit;
3
begin
4
  tmp <= SIG1;
5
  if tmp='1' then
6
    OUT <= '1';
7
  else
8
    OUT <= '0';
9
  end if
10
end process
denn hier passiert die Zuweisung an tmp nebenläufig oder anders gesehen 
am "Ende" des Prozesses. Ist SIG1 ein abgetaktetes Signal, verschiebt 
sich die kombi. Logik um einen Takt, da erst beim nächsten ausführen des 
unteren Prozesses der an tmp übergebene Wert in der if-Abfrage verwendet 
werden kann.

Schreibt man also einen langen Block von Anweisungen, die auf Variablen 
rumrechnen, werden die vom Synthesetool erzeugten Logikblöcke in die 
Tiefe gestapelt sein und nicht als parallele Zuweisungen realisiert 
werden.
Signalzuweisungen erzeugen jew. parallel ausgeführte (relativ kurze) 
kombi. Blöcke.
Variablenberechnungen erzeugen längere Verkettungen von Logikblöcken mit 
längerer Signallaufzeit.
Richtig?
Dass die Ausgänge solcher langen Verkettungen während der Berechnung vor 
sich hin glitchen kann ich mir auch gut vorstellen;)

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


Lesenswert?

Daniel R. schrieb:
> zu schreiben, aber nicht:
Ja klar: hier ist die Sensitivliste falsch, weil unvollständig.
Wir hatten das schon im 
Beitrag "Re: Variable vs Signal"

> denn hier passiert die Zuweisung an tmp nebenläufig oder anders gesehen
> am "Ende" des Prozesses.
Genau deswegen muss der Prozess noch einmal durchlaufen werden. Das 
sagt die Sensitivliste dem Simulator. Die Synthese macht es eh' schon 
"richtig"...

> Schreibt man also einen langen Block von Anweisungen, die auf Variablen
> rumrechnen, werden die vom Synthesetool erzeugten Logikblöcke in die
> Tiefe gestapelt sein und nicht als parallele Zuweisungen realisiert
> werden.
Keine sorge: die Synthese klopft diese Struktur schon flach. Ein 
"komplizierter" Prozess mit Variabeln wird mit Signalen genauso 
aufwendig umgesetzt...

> Signalzuweisungen erzeugen jew. parallel ausgeführte (relativ kurze)
> kombi. Blöcke.
> Variablenberechnungen erzeugen längere Verkettungen von Logikblöcken mit
> längerer Signallaufzeit.
> Richtig?
Nein.
Es ist eher so: weil mit der "sofortigen" Änderung von Variablen ein 
Beschreibungsstil ermöglicht wird, der viele Ebenen beinhaltet, werden 
solche Prozesse in der realen Hardware oft aufwendig. Nehmen wir mal das 
da:
1
process (clk)
2
signal tmp: integer;
3
begin
4
  if rising_edge(clk);
5
     if init='1' then
6
       tmp := startwert;
7
     end if;
8
     if tmp=3 then
9
       tmp := tmp+offset;  
10
     end if;
11
     if jump='1' then
12
       tmp := addr-8;
13
       speicher[tmp]<=wert;
14
     elsif reduce='1' then
15
       tmp := tmp+1;
16
     end if;
17
  end if;
18
end process
Hier kann man tmp sofort beliebig manipulieren und "gleich" wieder 
darauf zugreifen. In der Realität muss der Synthesizer aber diese 
Berechungen alle parallel ausführen und gleichzeitig machen.

Weil diese "sofortige" Manipulation mit Signalen nicht erfolgt, muss man 
sich vorher ein paar Gedanken zur Strucktur machen. Und das schadet 
meist nicht!

: Bearbeitet durch Moderator
von Victor (Gast)


Lesenswert?

At last! Something clear I can unndsrtaed. Thanks!

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.