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.
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.
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.
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.
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.
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.
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.
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
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.
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.
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
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.
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.
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
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.
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.