Forum: FPGA, VHDL & Co. Simulation von Hold und Setup bei externen Chips


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Gregor (Gast)


Lesenswert?

Ich möchte die Timing Spezifikation externer Chips bei der Verifikation 
von Schaltungen (PLD glue logic, teilweise FPGAs) berücksichtigen und 
dazu VHDL oder Verilog benutzen.

Wie geht man da vor?  Ich bringe ein Beispiel:

Ein Umschalt-Chip hat Decoder-Eingänge ABCD, welche interne Adressen 
bedienen, aus denen gelesen werden kann und die auch steuernde 
Funktionen haben. Die Setup-Hold SEPC weist für verschiedene 
Betriebsfälle andere Werte aus. Temperaturen mal aussen vor gelassen ist 
es z.B. so, dass bei weniger Spannung mit mehr SETUP-Bedarf zu rechnen 
ist. Da wir 5V und 3,3V gemischt verwenden und dazu 3,3er auch mal mit 
2,5 ansteuern ergeben sich je nach Schaltung, Port und Modus 
unterschiedliche Bedarfszeiten.

Beispiele:

- Wenn sich eine Adresse ändert, dann muss die bei 5V 3ns lang anliegen, 
bevor der Takt kommt, bei 3,3V sind es 4,5ns. Auch die Holdzeiten 
wachsen.

- Bei fallender Flanke des Taktes, reagiert der Ausgang 1 des Chips 
zwischen 5 und maximal 7 ns, Ausgang 2 braucht etwas länger und wenn der 
Chip in einem anderen Modus ist, dauert es noch länger.  Bei steigender 
Flanke gibt es auch andere Werte.

Die Sache ist nun die, dass man nicht einfach das Schlechteste nehmen 
kann und die Zugriffe langsam taktet, weil die Bandbreite nicht reict. 
Wir müssen die CHips jeweils ausnutzen. Dazu braucht es aber eine 
Simulation mit einem Model des Chips, welches bei Verletzung eines 
Kriteriums entsprechend negativ meldet oder reagiert.

Ich hatte nun überlegt, die internen Register die geschaltet werden, bei 
jeder Änderung einer ihrer Quelle nach 1-2ns auf "X" zu setzen, um sie 
dann nach weiteren 2-3ns wieder auf den eigentlichen Wert zu setzen.

Das Gleiche bei Eingangs- und Ausgangssignalen.

Damit sollte sich die Unsicherheit in die Schaltung fortsetzen.

Durch das richtige Takten und Schreiben der Register sowie Setzen der 
Steuerleitungen, (enable, Strb, ena_clock) wäre durch den Programamierer 
sicherzustellen, dass er zu keinem Zeitpunkt ein X eintakten und 
verarbeiten kann.

von Gregor (Gast)


Lesenswert?

Ich habe folgendes probiert:

Bei jeder Änderung von set_prog geht tls_intern auf unknown, ist also 
nur noch kurz stabil, um dann erst später wieder stabil zu sein.
Alle Signale die von tls_intern abhängen sind damit für eine Weile tabu 
und der Simulator soll dies durch X auch anzeigen. Der else Zeig soll 
dafür sorgen, dass das Signal stabil bleibt, wenn kein Takt kommt.

Leider arbeitet die zweite nicht (Endlosschleife) und die erste Lösung 
kllappt funktionell nicht.

Wie könnte ich das hinbekommen?
1
i_proc1 : process (set_prog)
2
begin
3
    if (set_prog'event) then
4
        --wait for 0.1 ns;
5
        --tls_intern <= 'U';
6
        --wait for 1.2 ns;
7
        tls_intern <= set_prog;
8
    --else
9
     --   tls_intern <= set_prog;
10
11
    end if;
12
    
13
    --wait for 0 ps;
14
    
15
end process i_proc1;
1
i_proc2 : process
2
begin
3
    if (set_prog'event) then
4
        wait for 0.1 ns;
5
        tls_intern <= 'U';
6
        wait for 1.2 ns;
7
        tls_intern <= set_prog;
8
    else
9
        tls_intern <= set_prog;
10
11
    end if;
12
    
13
end process i_proc2;

-------------------------------------

Was ich z.B. brauche ist die Behandlung der REG_ADR:

- reg_adr_intern <= D & C & B & A;

- IF "wenn sich bei A oder B oder C oder D etwas tut" THEN
  reg_adr_visible = unbekannter Wert

- Nach Setup-Time :   reg_adr_visible <= reg_adr_intern;
- jetzt kann getaktet werden

Ähnlich bei der Holdtimeverletzung:
  - ich warte auf den Takt, warte dann noch mal 2ns holdtime und weise 
dann erst das Signal zu.
  - falls es sich durch einen anderen Zugriff ändert, ist es falsch.
- falls gar kein Takt da ist, bleibt das aussen sichtbare auf dem Stand 
des inneren

Als Letztes führe ich noch die Temperatur und Spannung ein und 
beaufschlage andere Wartezeiten.

Leider kriege ich es wegen Formulierungsproblemen nicht hin.

von Strubi (Gast)


Lesenswert?

Was ist mit den VITAL2000-Libraries?
Das unschöne daran ist halt, dass man das Modell immer explizit wrappen 
muss.
Vielleicht kommst du mit PSL (Property Specification Language) weiter?
Ansonsten ein spannendes Thema, besonders in Bezug auf glitch-sichere 
Hardware.

von Christoph Z. (christophz)


Lesenswert?

Gregor schrieb:
> Die Setup-Hold SEPC weist für verschiedene
> Betriebsfälle andere Werte aus. Temperaturen mal aussen vor gelassen ist
> es z.B. so, dass bei weniger Spannung mit mehr SETUP-Bedarf zu rechnen
> ist. Da wir 5V und 3,3V gemischt verwenden und dazu 3,3er auch mal mit
> 2,5 ansteuern ergeben sich je nach Schaltung, Port und Modus
> unterschiedliche Bedarfszeiten.

Gib deinem Chip Model einen Generic, mit dem du die Betriebsspannung 
definierst.

Innerhalb des Models nutzt du dann diesen Generic um die dazu passenden 
Zeiten aus einer Tabelle oder so auszuwählen.

> Beispiele:
>
> - Wenn sich eine Adresse ändert, dann muss die bei 5V 3ns lang anliegen,
> bevor der Takt kommt, bei 3,3V sind es 4,5ns.

In VHDL gibt es dazu ganz praktische Signal Attribute wie z. B. 
signalname'DELAYED(zeit) das dir den Signalwert zur Zeit now - zeit 
zurückgibt oder signalname'LAST_EVENT das dir die Zeit seit dem letzten 
event zurückgibt.

In der Simulation sind so setup-, Periodenzeitmessungen etc. einfach 
möglich und können dann mit Asserts geprüft werden.

Das klappt dann auch für ungetaktete Bausteine wie z. B. SRAM.

> Auch die Holdzeiten wachsen.
> - Bei fallender Flanke des Taktes, reagiert der Ausgang 1 des Chips
> zwischen 5 und maximal 7 ns, Ausgang 2 braucht etwas länger und wenn der
> Chip in einem anderen Modus ist, dauert es noch länger.  Bei steigender
> Flanke gibt es auch andere Werte.
1
wait for falling_edge(clk);
2
ausgang1 <= (others => 'x');
3
ausgang2 <= (others => 'x');
4
wait for DELAY_TABLE(supplyVoltageGeneric,1);
5
ausgang1 <= "wert1";
6
wait for max(0,DELAY_TABLE(supplyVoltageGeneric,2)-DELAY_TABLE(supplyVoltageGeneric,1));
7
ausgang2 <= "wert2";

DELAY_TABLE ist hat zwei Dimensionen: Betriebsspannung und 
Ausgangsnummer

oder so ähnlich, vielleicht auch in etwas hübscher :-)


Gregor schrieb:
> Leider arbeitet die zweite nicht (Endlosschleife)

Ja. Dann lass doch einfach den else Zweig weg. Das Signal ändert je eben 
nur, wen du auf set_prog einen Event hast.
Wahrscheinlich möchtest du bei der set_prog deklaration noch einen 
Initialisierungswert mitgeben.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Gregor schrieb:
> Dazu braucht es aber eine Simulation mit einem Model des Chips,
> welches bei Verletzung eines Kriteriums entsprechend negativ meldet
> oder reagiert.
Diesen Teil der Begründung kann ich nicht so ganz nachvollziehen...

> Wie geht man da vor?
Sind bei diesen Bausteinen auch eigene ASICS mit dabei? Oder was soll da 
modelliert und simuliert werden? Willst du über eine Timingsimulation 
die "maximale Geschwindigkeit" deines Designa herausfinden?

Denn wenn ich davon ausgehe, dass ich die Verdrahtung und die Versorgung 
(und damit die zeitlichen Parameter) der Bauteile kenne, dann brauche 
ich gar keine Timingsimulation, sondern lediglich eine 
Verhaltenssimulation und entsprechend formulierte Timing-Constraints.

von Gregor (Gast)


Lesenswert?

Lothar M. schrieb:
> Denn wenn ich davon ausgehe, dass ich die Verdrahtung und die Versorgung
> (und damit die zeitlichen Parameter) der Bauteile kenne, dann brauche
> ich gar keine Timingsimulation, sondern lediglich eine
> Verhaltenssimulation und entsprechend formulierte Timing-Constraints.

Mit timing contraints lässt sich daber die Schaltung nicht verändern. Es 
geht darum, sie richtig zu bauen, damit z.B. nach dem Loslassen eines 
Taktes eine genügend lange Zeit gewartet wird, bevor man ausliest oder 
das Datum sitzt bevor man schreibt.

Nehmen wir einen Baustein, der mit 12.000 MHz getaktet wird. Dieser Takt 
kommt aus einer 120MHz Domain. Eine Möglichkeit wäre, die Datenleitungen 
zu setzen und den 12M einen Takt =1/120 MHz später kommen zu lassen. Das 
war aber gerade einige 100ps zu knapp, es mussten 2 Takte sein. 
Natürlich kann man sich das alles selber im Kopf überlegen, aber damit 
ist es eben nicht verifiziert.

Ich möchte das Modell des Interfaces so haben, dass es einen Fehler 
produziert, wenn man ungeschickt taktet.

Nochmal: Es geht nicht um einfache Interfaces wie bei einem ARM, wo man 
einmal global das timing einstellt, auf wait states achtend richig 
ausliest, sondern um eine Sammlung von Chips die alle unterschiedlich 
arbeiten, aber z.B. am gleichen Bus oder MUX hängen.

Ein Betriebsfall ist z.B. ein Bus-Switch für I2C, der so schnell 
getaktet wird, dass er Busse interleaven kann und damit mehrere 
Leitungen beobachet. Dazu muss der MUX aber richtig gesteuert werden, 
also Adresse raus, optimal warten, dann Lesen, SET einhalten, EinTakten, 
HOLD einhalten und das ganze  8x. Wenn man sich an der jeweils 
langsamsten Zeit orientiert, wird der Zyklus zu lang und die Abtastrate 
passt nicht. Da der selbe MUX aber verschiedene Busse taktet und einige 
seltener bedient werden, hängen 2 MUX in Reihe. Man muss also das 
verkoppelte timing einhalten. Das ist so kopmliziert, dass sich gleich 2 
Designer daran vertan haben ein timing dafür hinzuschreiben.

von Gregor (Gast)


Lesenswert?

Christoph Z. schrieb:
> In VHDL gibt es dazu ganz praktische Signal Attribute wie z. B.
> signalname'DELAYED(zeit) das dir den Signalwert zur Zeit now - zeit
> zurückgibt oder signalname'LAST_EVENT das dir die Zeit seit dem letzten
> event zurückgibt.
Das finde sehr interessant. Das sehe ich mir näher an. Danke für die 
Ausführungen.

Christoph Z. schrieb:
> Dann lass doch einfach den else Zweig weg. Das Signal ändert je eben
> nur, wen du auf set_prog einen Event hast.
Das war nur ein Teil des Baumes. Es gibt auch einen Pfad, der ohne den 
Takt zu einer Änderung führt. Ich arbeite das am Mo nochmals auf und 
formuliere es konkret als Problem.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Gregor schrieb:
> Das ist so kopmliziert
So ist es.
Und ich habe gelernt, dass in der Praxis nur die einfachen Sachen 
funktionieren. Oder auch komplizierte Sachen, die aus einfachen, 
funktionierenden Sachen aufgebaut sind.
Wenn du aber schon ganz am Anfang aus einem Bus das letzte Quäntchen 
herauspressen musst, dann fällt dir das Ding irgendwann auf den Kopf.

> Das ist so kopmliziert, dass sich gleich 2 Designer daran vertan haben
> ein timing dafür hinzuschreiben.
Wenn ich mit etwas fertig bin, dann ist es so einfach, dass es jeder 
Designer auf Anhieb kapiert.

> sondern um eine Sammlung von Chips die alle unterschiedlich arbeiten,
> aber z.B. am gleichen Bus oder MUX hängen.
Ich erledige das z. B. für SPI mit einem Automaten, dessen Timing für 
jeden Teilnehmer umprogrammiert wird, damit jeder Slave mit "seinem" 
optimalen Ablauf angesteuert werden kann.
Für diesen Automaten gibt es ein 10-seitiges Datenblatt, das die 
Einstellungen erklärt und Beispiele zeigt. Und zum Ermitteln der 
Parameter für diesen Automaten nimtt man einfach das Datenblatt des 
jeweiligen Slaves.
Eine Timingsimulation könnte mir dabei nicht helfen.

: Bearbeitet durch Moderator
von Gustl B. (gustl_b)


Lesenswert?

Du hast einen Baustein angeschlossen der Daten parallel und dazu einen 
Takt vom FPGA bekommt. Das läuft mit 12 MHz und macht schon Probleme?! 
Da würden mich interessieren wie du intern den Takt erzeugst, wie du das 
Clockdomain Crossing machst und auch was das für ein externer Baustein 
ist.
Bei so geringen Frequenzen könntest du den Takt und auch die Daten mal 
angucken. Ein Takt mit viel Jitter könnte Ärger machen wenn die Flanke 
mal vor und mal nach den Daten kommt. Du könntest den erzeugten 12 MHz 
Takt auch um 90° verschieben gegenüber den Daten.

von Jürgen S. (engineer) Benutzerseite


Lesenswert?

Gregor schrieb:
> Eine Möglichkeit wäre, die Datenleitungen
> zu setzen und den 12M einen Takt =1/120 MHz später kommen zu lassen. Das
> war aber gerade einige 100ps zu knapp, es mussten 2 Takte sein.
> Natürlich kann man sich das alles selber im Kopf überlegen, aber damit
> ist es eben nicht verifiziert.

Also soll die Zahl der Takte ermittelt werden? Oder geht es auch um die 
optimale Abtastfrequenz?

Wenn es nur darum geht, sicherzustellen, dass keine falschen Daten 
reinkommen, reicht es eigentlich, sie bei jeder Änderung eine Weile auf 
UNDEFINED zu setzen. Der Simulator treibt das dann durch die 
Kombinatorik hindurch. Zu frühes Sampeln wird dann ein U erwischen.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jürgen S. schrieb:
> UNDEFINED ... U
Das ist sicher eines der beliebtesten Irrtümer: U bedeutet 
UNINITIALIZED. Aber natürlich kann man es für diesen Zweck verwenden.

Vorgesehen und als UNKNOWN definiert ist allerdings das X.

: Bearbeitet durch Moderator
von Jürgen S. (engineer) Benutzerseite


Lesenswert?

Das ist schon richtig, faktisch bedeutet das programmablauftechnische 
"unitialized" aber ein funktionelles "undefined". Man könnte auch das X 
nehmen, allerdings kommt dies auch als Folge von Kollisionen zustande, 
wodurch ich für den Anwendungsfall das U bevorzuge.

von Gustl B. (-gb-)


Lesenswert?

Lass es, darüber habe ich schon diskutiert (-:

In dem anderen Tread hatte ich für X "Konflikt" vorgeschlagen, aber ein 
anderer Forist hat den tollen Begriff "unbestimmbar" genannt. Das trifft 
es perfekt, denn X ist nicht nur unbekannt, sondern man kann es gar 
nicht kennen selbst wenn man möchte.

Für U das "uninitialisiert" gefällt mir nicht weil Initial etwas wie 
Anfang bedeutet, man ein Signal aber auch nach dem Anfang in der 
Simulation auf U setzen kann. Aber es ist eben auch so, dass man ein 
Signal zu jedem Zeitpunkt wieder in einen Ausgangszustand versetzen 
können möchte bei dem eben der Zustand schlicht noch nicht festgelegt 
wurde. Es braucht also natürlich den Zustand U, "undefiniert" finde ich 
da besser wie "uninitialisiert" denn undefiniert beinhaltet eigentlich 
sogar mehr. Weil streng nach Wortherkunft könnte etwas nur am Anfang 
uninitialisiert sein bis es einmalig initialisiert wird. Danach ist es 
eben initialisiert weil es das wurde. Aber wenn etwas undefiniert ist 
kann man das jederzeit definieren und ihm die Definition auch wieder 
wegnehmen.

Aber gut, so ist das eben definiert, das werden wir nicht ändern und 
müssen wir ja auch nicht, wir wissen ja was das X und U bedeuten.

von Duke Scarring (Gast)


Lesenswert?

Gregor schrieb:
> Wenn sich eine Adresse ändert, dann muss die bei 5V 3ns lang anliegen,
> bevor der Takt kommt, bei 3,3V sind es 4,5ns.

Also ungefähr so:
1
    constant t_addr_setup : time := 3 ns;
2
3
...
4
5
    time_check_address_setup: process
6
        variable change: time;
7
    begin
8
        wait until address'event;
9
        change := now;
10
        wait until rising_edge( clk);
11
12
        assert (now - change) >= t_addr_setup
13
            report " address setup time to short"
14
            severity error;
15
    end process;

Damit bekommt man dann in der Simulation einen Fehler geschmissen. Das 
ist allerdings nur die Minimalvariante. Man braucht für jede 
Signalbeziehung einen process. Bei mir stehen die dann mit im 
Simulationsmodell des jeweiligen IC.

Duke

von Martin S. (strubi)


Lesenswert?

Bevor hier wieder die std_logic library in Frage gestellt wird: Die FMF 
-bibliothek (https://www.freemodelfoundry.com/) beinhaltet eine Menge 
konkreter Chip-Modelle, an denen man sich auch was abgucken kann.
m.E. braucht man dazu nicht wieder das Rad neuerfinden...
Wenn das nicht reicht: Es gibt es bei GHDL Moeglichkeiten, fuer 
spezifische Signaltypen seine eigenen Hooks aufzurufen, um z.B. 
kapazitive Aspekte zu co-simulieren (und tracen), ohne dass man sich 
eine neue VHDL-Klasse schreiben oder AMSfaehige Simulatoren anwerfen 
muss.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.