Forum: FPGA, VHDL & Co. Verständnis von delta-Zyklen in der Simulation


von Harry (Gast)


Angehängte Dateien:

Lesenswert?

Hi,
ich habe neulich ein Design simuliert (ISE/Isim 13.3) und bin dabei 
draufgekommen, dass ein FF mit einem synchronen Input einen Takt "zu 
früh" geschalten hat - und zwar zum "exakt" (?) gleichen Zeitpunkt, als 
der Input sich geändert hat. Was laut Hardware ja nie passieren kann, da 
ein D-FF per Definition ja am Schaltzeitpunkt des Taktes den Wert am 
Ausgang annimmt, den sein Eingang zuvor hatte (mal angenommen Setup/Hold 
stimmen).

Dann bin ich der Sache auf den Grund gegangen und konnte den Sachverhalt 
auf folgendes Szenario reduzieren und komplett in der Testbench 
nachstellen:
Der "inp" wird für einen Takt geschalten und wird in zwei getrennten FFs 
abgetaktet. Das Ergebnis ist, dass ein FF einen Takt früher, das zweite 
später schaltet. Simulationsplot siehe Anhang.
1
    pclk <= not pclk after 5 ns;
2
    pclk2 <= pclk;
3
    
4
    testt: process    
5
    begin
6
        wait for 995 ns;
7
        wait until rising_edge(pclk);
8
        inp <= '1';
9
        wait until rising_edge(pclk);
10
        inp <= '0';
11
        wait;
12
    end process;
13
    
14
    testp: process(pclk)
15
        begin
16
            if(rising_edge(pclk)) then
17
                if(inp = '1') then
18
                    test <= '1';
19
                else
20
                    test <= '0';
21
                end if;
22
            end if;
23
        end process;
24
    
25
    testp2: process(pclk2)
26
        begin
27
            if(rising_edge(pclk2)) then
28
                if(inp = '1') then
29
                    test2 <= '1';
30
                else
31
                    test2 <= '0';
32
                end if;
33
            end if;
34
        end process;

Als allererstes dachte ich an einen Codefehler. Danach an einen 
ISIM-Bug. Dann hab ich ein bisschen recherchiert und bin auf das Thema 
delta-Zyklen gestoßen. Anscheinend sollte man in der Simulation nicht 
beliebig von einem Signal aufs andere zuweisen, wenn man wirklich 
"gleichzeitige" Events haben will, da sonst die einzelnen Zeilen in 
delta-Zyklen abgearbeitet werden und deshalb in meinem einfach Beispiel 
der eine Takt früher wie der andere schaltet.

Siehe zb:
http://www.sigasi.com/content/vhdls-crown-jewel
und
Beitrag "Abgeleitete clocks in der Simulation - wie Probleme vermeiden?"

Nur, so ganz versteh ich's immer noch nicht. Kann mir das jemand 
vielleicht kurz und prägnant erklären?
Dem Synthese-Tool ist sowas egal, in Hardware wird das einfach ein 
Signal, egal wie oft man das hin und her zuweist oder nicht. Warum kann 
das in der Simulation nicht auch auf ein Signal reduziert werden?
Und: irgendwie muss ich meine Clock ja im Design verteilen? Woher weiß 
ich, welches port-map und welche Signalzuweisung nun ein Problem durch 
einen oder mehrere delta-Zyklen darstellt und was nicht? Gibts hierfür 
eine Faustregel?

Danke, lg Harry

PS: Gibts in ISim eine Möglichkeit, diese delta-Zyklen anzeigen zu 
lassen? Ich glaube, Modelsim kann das.

von VHDL hotline (Gast)


Lesenswert?

Über die Sache bin ich auch schon gestolpert. Bei clk-Zuweisungen muss 
man sich des einen delta cycles delay im Taktpfad bewusst sein. Hier 
werden ein paar Lösungen diskutiert:

http://www.verificationguild.com/modules.php?name=Forums&file=viewtopic&p=1765

von Sigi (Gast)


Lesenswert?

Versuch erstmal, das Problem mit der "Gleichzeitigkeit" zu
verstehen:

  ...
  wait until rising_edge(pclk);  -- Abfrage   Zeitpunkt T
  inp <= '1';                    -- Zuweisung Zeitpunkt T+Delta
  ...

d.h. <inp> wird erst "kurz nach" T beschrieben, zum Zeitpunkt
T hat <inp> noch seinen alten Wert. Und das hat Auswirkung auf
den nachfolgenden Code:

  ...
  if(rising_edge(pclk)) then  -- Abfrage   Zeitpunkt T
    if(inp = '1') then        -- Abfrage   Zeitpunkt T (alter Wert!)
      test <= '1';
    else
  ...

d.h. <inp> hat in T noch den alten Wert, erst in T+T_CLK kann der
neue Wert in diesem Prozess abgefragt werden. Soviel zum ersten Teil.

  ...
  pclk2 <= pclk; -- Zuweisung Zeitpunkt T+Delta
  ...
  if(rising_edge(pclk2)) then  -- Abfrage   Zeitpunkt T+Delta
    if(inp = '1') then         -- Abfrage   Zeitpunkt T+Delta (neuer 
Wert!)
      test2 <= '1';
  ...

Hier wird <pclk2> und <inp> zum "gleichen" Zeitpunkt ein neuer Wert
zugeordnet, also klappt die Abfrage und Zuordnung wie gewünscht.
(genaugenommen müsste man Delta in Delta1 und Delta2 aufspalten,
von denen aber nicht bekannt ist, welche Differenz grösser ist)
Man kann sich das ganze auch als gerichteten Graphen vorstellen.

Der grosse Fehler ist also, dass du mit einer Clock schreibst und
mit einer anderen liest.

von Klakx (Gast)


Lesenswert?

Ja wenn du einen Takt anfasst, musst du danach immer auf der Hut sein. 
Innerhalb von Designs sollte man den Takt möglichst von weit oben in der 
Hierarchie zuführen. In testbenches kann man noch eine konstante anfügen 
zur Verzögerung

von Sigi (Gast)


Lesenswert?

Klakx schrieb:
> In testbenches kann man noch eine konstante anfügen
> zur Verzögerung

Das hilft aber nur bei eingehenden Signalen, alle "internen"
Register-Signale werden idR mit rising_edge(clk) geschaltet,
d.h. der Phasenoffset ist wieder weg, es sei denn man passt
all seine Komponenten/Zuweisungen an (z.B. mit .. after 0.1 ns
etc.). Man kommt also um ein grundlegendes Verständnis nicht
rum.

von J. S. (engineer) Benutzerseite


Lesenswert?

Solche Unschönheiten gibt es auch bei ModelSIM, insbesonders, wenn man 
den after-Konstrukt einsetzt.

In dem oben beschriebenen Fall ist das Problem aber kein 
simulationstechnisches sondern da fallen ja in der simulierten Realität 
Takte und Daten auf denselben infinitisimalen Zeitpunkt. Von daher ist 
der Ergebnis "zufällig" bzw hängt von sequentiellen Ablauf ab. Das 
sollte man dort, wo man das nicht benötigt, vermeiden, weil es den 
Nutzen einer Logiksimulation mindert und diese erschwert.

Die Problematik ist bei korrekt formulierten Logikschaltungen nicht 
gegeben, sondern tritt nur bei physikalischen Simulationen auf. Und 
dabei muss man eben an jeder Stelle Zeiten einfügen und dabei 
berücksichtigen, wenn man logische Zuweisungen macht, die hinter 
verschwinden. Durch die tatsächliche Zeitdehnung in einer Simulation 
gibt es eben keine echte Gleichzeitigkeit. Da hilft es dann tatsächlich, 
mehr, wie in C zu denken und den Ablauf der Zeit straght forward runter 
zu schreiben.

: Bearbeitet durch User
von Sigi (Gast)


Lesenswert?

Jürgen Schuhmacher schrieb:
> Solche Unschönheiten gibt es auch bei ModelSIM, insbesonders, wenn man
> den after-Konstrukt einsetzt.
Keine Unschönheit, sondern Semantik der Simulation: Vor Simulationsstart
wird zuerst ein Graph (vgl.bar Petrinetz) erstellt und dann 
abgearbeitet.
Die meisten Simulatoren arbeiten so.

> In dem oben beschriebenen Fall ist das Problem aber kein
> simulationstechnisches sondern da fallen ja in der simulierten Realität
> Takte und Daten auf denselben infinitisimalen Zeitpunkt.
Nein, es ist nicht derselbe infinitesimaler Zeitpunkt, es sind mind.
2 Zeitpunkte, einmal T und einmal T+.

>Von daher ist
> der Ergebnis "zufällig" bzw hängt von sequentiellen Ablauf ab. Das
> sollte man dort, wo man das nicht benötigt, vermeiden, weil es den
> Nutzen einer Logiksimulation mindert und diese erschwert.
Zufällig ist das Ergebnis nicht, denn bei der Erstellung des Graphen
ist die Reihenfolge für das Simulationsergebnis irrelevant (es sei denn,
der Simulator hat disbezgl. einen Fehler).

von Harry (Gast)


Lesenswert?

Hallo an alle und danke für die ausführlichen Antworten.

Sigi schrieb:
> Der grosse Fehler ist also, dass du mit einer Clock schreibst und
> mit einer anderen liest.

Ja, anscheinend hab ich hier zuviel in Hardware und zu wenig in Software 
gedacht. Denn für die Synthese wären pclk und pclk2 dasselbe und würde 
auf ein Signal reduziert. Nicht so für den Simulator, was mir durch eure 
Ausführungen nun etwas klarer ist.
Und das ist in der Realität dann schon eine gemeine Falle, denn das 
angeführte Beispiel war ja gekünstelt, um den Effekt hervorzuheben. In 
einer richtigen Testbench ist das ja typischerweise irgendwo 
verschachtelt und man sucht ewig nach dem "Fehler", der nur in der 
Simulation einer ist...

Eine Frage nochmal aufgeriffen:
> PS: Gibts in ISim eine Möglichkeit, diese delta-Zyklen anzeigen
> zu lassen? Ich glaube, Modelsim kann das.

Danke, lg

von Sigi (Gast)


Lesenswert?

Harry schrieb:
> Und das ist in der Realität dann schon eine gemeine Falle, denn das
> angeführte Beispiel war ja gekünstelt, um den Effekt hervorzuheben. In
> einer richtigen Testbench ist das ja typischerweise irgendwo
> verschachtelt und man sucht ewig nach dem "Fehler", der nur in der
> Simulation einer ist...
..nicht die einzige Falle: Nimm z.B. ein std_logic_vector und teile ihn
in zwei Teile. Je ein Teil wird von einem Prozess geschrieben, beide
Teile aber von beiden Prozessen gelesen. Dann gibt's auch Probleme.
Das liegt daran, dass der (jeder!) Simulator einen gerade beschriebenen
Vektor markiert, nicht aber Teile davon. Den Rest kann man sich dann
selbst zusammenreihmen.
Dies ist kein Simulator-Fehler, sondern in VHDL spezifiziert.

Kleine Denksportaufgabe: wie sieht's mit Komponenten-Ports aus, dabei
werden ja Signale an verschiedene Komponenten weitergereicht?

> Eine Frage nochmal aufgeriffen:
>> PS: Gibts in ISim eine Möglichkeit, diese delta-Zyklen anzeigen
>> zu lassen? Ich glaube, Modelsim kann das.
Wahrscheinlich nicht, Delta-Zyklen sind ja nur ein abstraktes Konstrukt,
um "Jetzt" von "Gleich" zu unterscheiden, was durch Graphen bzw.
Markierungen implementiert wird.
Interesant wäre eher, zu welchen Zeitpunkt welche Signale schon
beschrieben und welche "gleich" beschrieben werden.

von Weltbester FPGA Pongo (Gast)


Lesenswert?

Sigi schrieb:
> Nimm z.B. ein std_logic_vector und teile ihn
> in zwei Teile. Je ein Teil wird von einem Prozess geschrieben, beide
> Teile aber von beiden Prozessen gelesen.

Wer so einen Scheiss programmiert, dem gehört es auch nicht besser, 
Probleme zu bekommen!


> Kleine Denksportaufgabe: wie sieht's mit Komponenten-Ports aus, dabei
> werden ja Signale an verschiedene Komponenten weitergereicht?

Wird je nach Optimierungseinstellung des Compilers plattgerechnet.


> Wahrscheinlich nicht, Delta-Zyklen sind ja nur ein abstraktes Konstrukt,

Und gehen in der compilierten Simulation komplett unter.

Ich kann nur davor warnen, sich unnötig von solchen Geschichten abhängig 
zu machen. Ich empfehle dazu das Buch: "ASIC and FPGA Verification" von 
Richard Munden.

von Klaus F. (kfalser)


Lesenswert?

Weltbester FPGA Pongo schrieb im Beitrag #4082503:
>> Kleine Denksportaufgabe: wie sieht's mit Komponenten-Ports aus, dabei
>> werden ja Signale an verschiedene Komponenten weitergereicht?
>
> Wird je nach Optimierungseinstellung des Compilers plattgerechnet.

Abgesehen davon, dass ich bei keinem Simulator je irgendwelche Compiler 
Optimierungen gesehen habe, stimmt das sicher nicht, da man dann je nach 
Einstellung unterschiedliche Simulationsergebnisse hätte.

Port Zuweisungen werden durchgereicht, und zeigen auf das selbe Signal.
Sie erzeugen keinen Delta-Zyklus.
Sie sind nicht das selbe wie eine concurrent Zuweisung außerhalb eines 
Prozesses.

Dass eine concurrent Zuweisung einen Delta-Zyklus erzeugt, hängt damit 
zusammen, dass sie GENAU wie ein Prozess wirken und im Simulator auch so 
behandelt werden.
1
a <= b;   -- a,b sind Signale
ist genau das selbe wie
1
process(b)
2
begin 
3
    a <= b;
4
end process;

Erst wenn b zum Zeitpunkt T sich ändert, beginnt der Prozess zu laufen. 
An a wird zugewiesen, a ändert sich aber erst am Ende des Zeitschrittes, 
wenn alle Prozesse wieder gestoppt wurden.
Somit erhält a erst zwischen T und T+DeltaZyklus den neuen Wert b und 
triggert somit womöglich zum Zeitpunkt T+Deltazyklus wiederum neue 
Prozesse.

von Sigi (Gast)


Lesenswert?

Klaus Falser schrieb:
> Weltbester FPGA Pongo schrieb im Beitrag #4082503:
> ..
>> Wird je nach Optimierungseinstellung des Compilers plattgerechnet.
>
> Abgesehen davon, dass ich bei keinem Simulator je irgendwelche Compiler
> Optimierungen gesehen habe, stimmt das sicher nicht, da man dann je nach
> Einstellung unterschiedliche Simulationsergebnisse hätte.
Genau. Das wäre eine totale Katastrophe.
>
> Port Zuweisungen werden durchgereicht, und zeigen auf das selbe Signal.
> Sie erzeugen keinen Delta-Zyklus.
> Sie sind nicht das selbe wie eine concurrent Zuweisung außerhalb eines
> Prozesses.
Sehr gut, dasselbe gilt für Aliases.

Weltbester FPGA Pongo schrieb im Beitrag #4082503:
>> Wahrscheinlich nicht, Delta-Zyklen sind ja nur ein abstraktes Konstrukt,
>
> Und gehen in der compilierten Simulation komplett unter.
Eben nicht, alle Simulatoren wandeln vor Siumlationsstart das HDL-Design
in einen Graphen/Netzwerk um, die Sematik bzgl. Delta-Zyklen wird dabei
erhalten.

> Ich kann nur davor warnen, sich unnötig von solchen Geschichten abhängig
> zu machen. Ich empfehle dazu das Buch: "ASIC and FPGA Verification" von
> Richard Munden.
Die einzige Möglichkeiten sich vor dem Delta-Zyklen-Ansatz zu schützen
ist nicht zu simulieren (oder Post-Sims zu benutzen => langsam). Aber
das ist noch schlechter.

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.