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
endif;
12
13
--wait for 0 ps;
14
15
endprocessi_proc1;
1
i_proc2:process
2
begin
3
if(set_prog'event)then
4
waitfor0.1ns;
5
tls_intern<='U';
6
waitfor1.2ns;
7
tls_intern<=set_prog;
8
else
9
tls_intern<=set_prog;
10
11
endif;
12
13
endprocessi_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.
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.
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.
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
constantt_addr_setup:time:=3ns;
2
3
...
4
5
time_check_address_setup:process
6
variablechange:time;
7
begin
8
waituntiladdress'event;
9
change:=now;
10
waituntilrising_edge(clk);
11
12
assert(now-change)>=t_addr_setup
13
report" address setup time to short"
14
severityerror;
15
endprocess;
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.