Forum: FPGA, VHDL & Co. Bitfile Integrität im FPGA über Laufzeit prüfen


von Bronco (Gast)


Lesenswert?

Hallo,

ich habe einen Spartan3, in dessen SRAM nach Power-on ein Bitfile 
geladen wird. Nun möchte ich gerne im FPGA prüfen, ob das Bitfile 
während der Laufzeit stabil bleibt oder ggf. irgendwo etwas kippt 
(Selbsttest).
Bei µC ist das recht einfach: Checksumme über das Programm rechnen und 
mit der Referenz vergleichen.
Aber beim FPGA? Geht das überhaupt irgendwie oder steh ich da auf 
verlorenem Posten?

von Duke Scarring (Gast)


Lesenswert?

Mit einem externen Controller (oder PC) kannst Du das Bitfile auch 
wieder auslesen. Allerdings müssen u.a. die Schaltzustände von Flipflops 
und Arbeitszellen im BRAM maskiert werden. Dann kannst Du wieder Deine 
Checksumme prüfen.

Duke

von Bronco (Gast)


Lesenswert?

Duke Scarring schrieb:
> Mit einem externen Controller (oder PC)

Eine Möglichkeit, daß der FPGA sich selbst überprüft, gibt's wohl nicht, 
oder?

von Christian R. (supachris)


Lesenswert?

Beim Spartan 3 nicht, ab Extended Spartan 3A oder neuer gibts den ICAP 
(Internal Configuration Access Port). Da kannst du theoretisch das 
Bitfile auslesen und die CRC berechnen.

von Christian R. (supachris)


Lesenswert?

Bronco schrieb:
> Nun möchte ich gerne im FPGA prüfen, ob das Bitfile
> während der Laufzeit stabil bleibt oder ggf. irgendwo etwas kippt
> (Selbsttest).

Wie möchtest du übrigens sicherstellen, dass nicht gerade der Teil des 
Designs, der das Bit-File überprüfen soll, von einem Bit-Kipper 
betroffen ist?

von Bronco (Gast)


Lesenswert?

Ich komme aus dem µC-Welt, und da ist ein Programm-CRC-Test nichts 
besonders.
Es wundert mich ein wenig, daß ich beim FPGA bisher nichts 
vergleichbares gefunden habe (ich weiß, ich soll nicht immer µC und FPGA 
vergleichen).

Nun ist ja (beim Spartan) eine CRC im Bitfile, die während der 
FPGA-Konfig geprüft wird, da hätte es vielleicht einen eleganten Trick 
gegeben können, um darüber die Integrität zu checken.

von 1234 (Gast)


Lesenswert?

Ich kenne mich mit Xilinx nicht gut aus. Bei Altera gibts in den FPGAs 
einen (nicht rekonfigurierbaren) CRC Check, der eben dies automatisch 
macht. Da der nicht auf konfigurierbaren SRAM-Zellen basiert, ist die 
Wahrscheinlichkeit eines Bitflips stark reduziert.
Auskunft ob Xilinx sowas hat, gibt dir in der Regel das Datenblatt des 
Chips.

von Christian R. (supachris)


Lesenswert?

Naja, beim µC ist das Problem ja das selbe. Wenn jetzt das Prüfprogramm 
aus dem RAM ausgeführt wird, in dem ein Bitkipper vermutet oder möglich 
ist, ist das Prüfprogramm selbst ja eventuell kaputt. Beim Spartan 6 
gibts ein POST_CRC_ERROR Flag innerhalb des Designs, je nach BitGen 
Settings kann das wohl benutzt werden, um CRC Fehler beim Laden des 
BitStreams festzustellen Wenn kein Reboot on Error). Allerdings weiß ja 
dann niemand ob das Bitfile überhaupt gescheit funktioniert, um den 
Status auslesen zu können. Normalerweise wird ein FPGA nicht gestartet, 
wenn bei der Config was schief geht, nachher hat man da wenig 
Möglichkeiten. Über das ICAP kann man die gesamte Konfig auslesen, aber 
dann hast du das gleiche Problem wie oben.
Auch ein dedizierter CRC Block reduziert lediglich die 
Wahrscheinlichkeit, denn der will ja auch erst mal angesteuert werden. 
ist halt nicht mit dem µC vergleichbar.
Was ist denn Sinn der Übung? Weltraum? Warum sollte/könnte da was 
kippen?

von Bronco (Gast)


Lesenswert?

Christian R. schrieb:
> Was ist denn Sinn der Übung? Weltraum? Warum sollte/könnte da was
> kippen?

Wir haben Geräte im Feld, die immer wieder Fehler zeigen, die durch 
Reset (und damit Neukonfig des FPGA) behoben werden können.
Es gibt deutliche Hinweise darauf, daß die Fehler durch ESD verursacht 
werden.
Ich würde nun gerne eingrenzen, ob ggf. die Logik im FPGA verfälscht 
wird oder ob der Fehler an anderer Stelle entsteht.

von Schlumpf (Gast)


Lesenswert?

Dazu würde es ja aber nicht reichen, die Konsistenz des Bit-Files zu 
prüfen, sondern du müsstest Prüfen, ob die Config-RAM-Zellen im FPGA 
noch den gewünschten Zustand haben. Und ich glaube, dann wird es noch 
komplizierter.

Kannst du dem Fehler nicht einfacher auf die Schliche kommen?
Indem du z.B. ein Gerät so modifizierst, dass du z.B. nur das PFGA 
zurücksetzten kannst und der Rest der Schaltung in seinem Zustand 
verbleibt? Damit kannst du dann zumindest mal eingrenzen, wo der Fehler 
tatsächlich auftaucht.
Ggf kann man auch die Config-RAMs mit dem Download-Adapter auslesen und 
per PC-Tool mit dem original Bit-File vergleichen.

von Christian R. (supachris)


Lesenswert?

Dann geht das ganze aber nur sinnvoll durch Readback über JTAG. 
Vermutlich ist die Ursache aber ein unsauberes Design, wahrscheinlich 
asynchrone Eingänge nicht richtig eingetaktet und das bringt bei 
Störungen die State Machines durcheinander ...eventuell auch unsaubere 
Versorgungsspannung.

von Lattice User (Gast)


Lesenswert?

Bronco schrieb:
> Ich komme aus dem µC-Welt, und da ist ein Programm-CRC-Test nichts
> besonders.
> Es wundert mich ein wenig, daß ich beim FPGA bisher nichts
> vergleichbares gefunden habe (ich weiß, ich soll nicht immer µC und FPGA
> vergleichen).

Dann hast du nicht genau genug gesucht.

Bei Lattice heisst das Feature Soft Error Detection und gibt es für 
ECP2/M, XP2, ECP3, MachXO2. Bei Xilinx habe ich es auch schon im 
Zusammenhang mit einer Studie über Fehlerhäufigkeiten gesehen, weiss 
aber nicht mehr für welche Familien es verfügbar ist. Bei der Xilinx 
Variante konnte man auch zur Laufzeit einen Fehler injizieren und damit 
das Verhalten des eigenen Designs im Fehlerfalle testen.

Christian R. schrieb:
> Vermutlich ist die Ursache aber ein unsauberes Design, wahrscheinlich
> asynchrone Eingänge nicht richtig eingetaktet und das bringt bei
> Störungen die State Machines durcheinander ...eventuell auch unsaubere
> Versorgungsspannung.

Halte ich auch für die wahrscheinlichere Fehlerursache.

von Bronco (Gast)


Lesenswert?

Lattice User schrieb:
>> Vermutlich ist die Ursache aber ein unsauberes Design, wahrscheinlich
>> asynchrone Eingänge nicht richtig eingetaktet und das bringt bei
>> Störungen die State Machines durcheinander ...eventuell auch unsaubere
>> Versorgungsspannung.
>
> Halte ich auch für die wahrscheinlichere Fehlerursache.

Ich ehrlich gesagt auch (das darf ich sagen, denn das Projekt ist nicht 
von mir entwickelt worden, ich darf nur die Fehler rausmachen).

Allerdings hätte es geholfen, diese Fehlerquelle ausschließen zu können.

von Christian R. (supachris)


Lesenswert?

Bronco schrieb:
> Allerdings hätte es geholfen, diese Fehlerquelle ausschließen zu können.

Wenn das Ding nicht im Weltraum operiert, kann man das eigentlich 
ausschließen. Notfalls halt über JTAG zurücklesen und vergleichen.

von Bronco (Gast)


Lesenswert?

Christian R. schrieb:
> Notfalls halt über JTAG zurücklesen und vergleichen.

Das Problem ist, daß dieser Fehler sehr unregelmäßig im Feld auftritt, 
aber ich konnte ihn im Labor nie reproduzieren.
Ich suche jetzt seit gut 3 Monaten in einem Projekt, das mich nur noch 
ärgert, und jeder Ansatz führt in eine Sackgasse... :-O

von Schlumpf (Gast)


Lesenswert?

kannst du vielleicht eine Version der Hardware machen, in der der uC an 
das JTAG-Interface des FPGA angeschlossen ist?
Dann könntest du im Fehlerfall über JTAG die SRAM-Zellen auslesen und in 
irgendeinem NV-Speicher ablegen.
Der Kunde sendet das Gerät zurück und du kannst die Info auslesen und 
vergleichen, ob das noch mit dem Ausleseergebnis übereinstimmt, wenn das 
Gerät noch funktionierte.

von Bronco (Gast)


Lesenswert?

Schlumpf schrieb:
> kannst du vielleicht eine Version der Hardware machen, in der der uC an
> das JTAG-Interface des FPGA angeschlossen ist?

Keine Chance!
Es brennt, Lösung muß her, keine Idee, woran es liegt, und kosten darf's 
auch nix...

von Christian R. (supachris)


Lesenswert?

Na dann. Pech gehabt. Das unterscheidet den Bastler vom Entwickler. :)

von Schlumpf (Gast)


Lesenswert?

Bronco schrieb:
> Keine Chance!
> Es brennt, Lösung muß her, keine Idee, woran es liegt, und kosten darf's
> auch nix...

5 Fädeldrähte kosten nix.
Bissle Hirnschmalz kostet Zeit.

Aber wenn das schon zu viel ist, und du glaubst, dass dir hier jemand 
per Ferndiagnose sagt, wo der Fehler liegt, dann wirst wohl Pech gehabt 
haben.

Mein Tipp:
Ich glaube nicht, dass im FPGA die Bits kippen.
Ich glaube eher an ein schlechtes HDL-Design (asynchron, latch, fehlende 
Timing Constraints, Glitches, etc), wenn es tatsächlich am FPGA liegt.
Oder eine bugy Software.

Du hast hier jetzt ein paar Ideen bekommen, wie man prüfen könte, ob der 
FPGA "schuld" ist, aber die scheinen dir ja zu kompliziert zu sein.
Auf deine ursprüngliche Frage, ob es einen fertigen checker für sowas 
gibt, wurde ja auch geantwortet, aber der kostet halt leider auch Geld. 
Und das Problem ist, dass du neu synthetisieren musst und dann die Welt 
im FPGA wieder ganz anders aussieht und eventuell der Fehler gar nicht 
mehr auftritt.

von Christian R. (supachris)


Lesenswert?

Bronco schrieb:
> Ich komme aus dem µC-Welt

Und vor allem sollte man bei einem solch nicht-trivialen Problem 
jemanden ranlassen, der Ahnung davon hat. FPGA und µC unterscheiden sich 
nun mal extrem.

von Bronco (Gast)


Lesenswert?

Es wäre zu aufwändig, die ganze Entwicklungsgeschichte dieses Produkts 
hier darzustellen, aber ich kam erst dazu, als sowohl HW und Firmware 
schon fertig gebastelt (muß man leider so sagen) waren und das Ding an 
Kunden verkauft war.
Meine Aufgabe ist es jetzt, nachträglich Qualität reinzuzaubern.

Eure ganzen Anregungen nehm ich durchaus ernst, und ich verbringe seit 
Monaten den Großteil meiner Zeit damit, die Logik nach Problemen zu 
durchforsten (von denen ich auch schon viele Gefunden habe), wobei ich 
übrigens auch die Simulation und Testbenches zu schätzen gelernt habe.

Die Selbsttest-Geschichte war nur eine Idee, läßt sich aber leider im 
Spartan3 wohl nicht realisieren.

von Schlumpf (Gast)


Lesenswert?

Synthetisierst du im Rahmen deiner Fehlersuche auch hin und wieder das 
HDL-Design neu? Oder hast du die Fehler außerhalb des HDL-Designs 
gefunden?

von Bronco (Gast)


Lesenswert?

Christian R. schrieb:
> Und vor allem sollte man bei einem solch nicht-trivialen Problem
> jemanden ranlassen, der Ahnung davon hat. FPGA und µC unterscheiden sich
> nun mal extrem.

Ich hab tatsächlich nicht viel Erfahrung mit FPGAs. Genau aus diesem 
Grund geh ich ziemlich nach Lehrbuch und Lothar Miller vor.
Damit konnte ich viele bestehende Probleme finden, die von unseren 
erfahrenen Leuten übersehen wurden (gerade beim Synchronisieren und 
Clock-Domain-Crossing).
Das hat sich inzwischen rumgesprochen, und wenn's ein 
(Qualitäts-)Problem gibt, muß ich mich drum kümmern, weil die erfahrenen 
Entwickler lieber neue Produkte in aller machen, als sich mit alten 
Problemen zu plagen.
Wenn FPGA-Entwicklung so aussieht, dann will ich wirklich gerne wieder 
zu den µCs zurück.

von Schlumpf (Gast)


Lesenswert?

Bronco schrieb:
> Genau aus diesem
> Grund geh ich ziemlich nach Lehrbuch und Lothar Miller vor.

--> Schonmal kein gut ;)
Und wenn du mit diesen Hinweisen bereits Fehler im Design gefunden hast, 
dann liegt die Vermutung nahe, dass eure "erfahrenen" Leute noch mehr 
Schlampereien eingebaut haben.

Hier vielleicht noch ein paar Punkte, die du abchecken kannst:

- Gibt es nach der Synthese im Report "unconstrained pathes"?

- Sind alle asynchronen Eingäne (Pins) direkt über mindestens eine
  Registerstufe (besser zwei) synchronisiert?

- Sind die Pfade zwischen den Clock-Domains korrekt constrained?

- Sind die Steuersignale zwischen den Domains von zeitlichen Ablauf so
  gesteuert, dass in allen möglichen Timinggrenzen der Synthese
  gewährleistet ist, dass die Daten zum Zeitpunkt des Übernahme-Signals
  stabil sind?

- Gibt es Latches? -> Synthese Report

- Sind alle Register vollständig beschrieben?

- Sind die Sensitivity-Listen vollständig (da streiten sich die Geister,
  aber ich hab es selbst schon erlebt, dass eine unvollständige Liste zu
  einem ungewollten Verhalten im Chip geführt hat)

- Können Gitches entstehen, die in kombinatorischer Logik zu Problemen
  führen können?

- Sind die Ausgänge über Register geführt und daher glitchfrei?

von Schlumpf (Gast)


Lesenswert?

Schlumpf schrieb:
> --> Schonmal kein gut ;)

Was hab ich denn da für nen Mist geschrieben?
"Schonmal gut" sollte das heißen :-)

von Schlumpf (Gast)


Lesenswert?

einen hab ich noch:

- Sind die Signale an die internen RAMs (falls vorhanden) glitchfrei?
  je nach Konfiguration des RAMs kann sein, dass er keine 
Eingangsregister
  hat und dann können Glitches Speicherzellen überschreiben

von Bronco (Gast)


Lesenswert?

Schlumpf schrieb:
> Hier vielleicht noch ein paar Punkte, die du abchecken kannst:
Werd ich auf jeden Fall tun, danke!
Ich will ja auch was lernen dabei (deswegen mach ich doch den ganzen 
Sche*ß überhaupt).

Konkret gibt es folgendes Problem:
Der FPGA ist mit einem RAM verbunden (über 16Bit-Bus + Steuersignale).
Die Leiterbahnführung ist unoptimal (unterschiedliche Längen der Signale 
und auch noch an unterschiedliche FPGA-I/O-Blöcke angeschlossen).
Als der Entwickler das inbetrieb genommen hat, funktionierte es nicht, 
wie geplant, und er hast lange drann herumgedoktort, bis es seiner 
Meinung nach getan hat.
Der VHDL-Code des entsprechenden Moduls zeugt von ewigem Trial&Error.

Der Fehler äußert sich so, daß ein Teil der Daten, die der FPGA in dem 
RAM puffert, korrupt sind. Dabei ist nicht klar, ob er sie schon falsch 
reinschreibt oder erst falsch rausliest.
Natürlich hab ich den Fehler zuerst in dem VHDL-Modul vermutet (bzw. 
vermute ihn immer noch dort).
Was allerdings seltsam ist, ist, daß der Neuladen des FPGA hilft.

Wie gesagt: die Firmware-Integrität war nur eine von vielen Ideen.

von Bronco (Gast)


Lesenswert?

Bronco schrieb:
> Dabei ist nicht klar, ob er sie schon falsch
> reinschreibt oder erst falsch rausliest.

Ich meine: ob es beim Schreiben oder beim Lesen zu der Korruption kommt.
Die Daten im FPGA beim Schreiben sind noch okay, das hab ich geprüft.

von Schlumpf (Gast)


Lesenswert?

Bronco schrieb:
> Der FPGA ist mit einem RAM verbunden (über 16Bit-Bus + Steuersignale).

Ist es ein einfacher SRAM? Wie ist das Timing seitens des FPGA 
vorgesehen? Sampelt der vielleicht beim Lesen aus dem RAm zu früh, so 
dass die Daten zu dem Zeitpunkt noch nicht stabil sind?

von Bronco (Gast)


Lesenswert?

Schlumpf schrieb:
> Ist es ein einfacher SRAM? Wie ist das Timing seitens des FPGA
> vorgesehen? Sampelt der vielleicht beim Lesen aus dem RAm zu früh, so
> dass die Daten zu dem Zeitpunkt noch nicht stabil sind?

Es ist ein DRAM mit internem Refresh, welches mit synchronem Burst 
betrieben wird. Dazu wird ein externer Clock verwendet (taktet das DRAM 
direkt und den FPGA).
Das Timing ist irgendwie hingetrickst, mit viel Trial&Error (die 
Clock-Phase wurde durch Tests herausgefunden und die FPGA-Logik setzt 
manche Signale bei steigender und andere bei fallende Flanke, obwohl 
laut Datenblatt alles bei steigender Flanke geschehen sollte usw.)
Der Entwickler sagt, die Hardware ist schuld, und anders konnte er es 
nicht machen. Aber was er sich genau gedacht hat, konnte er mir auch 
nicht mehr erklären.
Leider stecken die Leiterbahnen in einer mehrlagigen Leiterplatte, so 
daß man sie auch nicht messen kann.

von Schlumpf (Gast)


Lesenswert?

Hört sich aber alles ziemlich besch.. an.
Ob es daran liegt, lässt sich natürlich auf die Distanz schwer sagen, 
aber so vermurkste Timings, die offensichtlich nicht Datenblattkonform 
sind, und halt irgendwie so lange hingeschoben wurde, bis es 
funktionierte, lassen nicht gerade hoffen, dass man den Fehler schnell 
eingrenzen kann.

Na ja ich hoff, ich konnte dir trotzdem ein paar hilfreiche Tipps geben, 
aber ne Ferndiagnose an einem System, welches offensichtlich ziemlich 
vermurkst ist, ist natürlich nicht möglich.

Viel Erfolg!

von Bronco (Gast)


Lesenswert?

Schlumpf schrieb:
> Viel Erfolg!

Bei der Fehlersuche oder bei der Jobsuche?

Danke!

von Lattice User (Gast)


Lesenswert?

Bronco schrieb:
> Es ist ein DRAM mit internem Refresh, welches mit synchronem Burst
> betrieben wird. Dazu wird ein externer Clock verwendet (taktet das DRAM
> direkt und den FPGA).

Was ist das für ein DRAM genau?
Bei welcher Frequenz?

> Das Timing ist irgendwie hingetrickst, mit viel Trial&Error (die
> Clock-Phase wurde durch Tests herausgefunden und die FPGA-Logik setzt
> manche Signale bei steigender und andere bei fallende Flanke, obwohl
> laut Datenblatt alles bei steigender Flanke geschehen sollte usw.)

Das hört sich abenteuerlich an.
Dafür gibt es IO Constraints zur Einstellung von Setup und Holdzeiten. 
Auch sollte man immer die IO Flipflops verwenden, sonst hat man mit 
jedem neuem Bitimage andere Setup/Hold Erfordenisse.

> Der Entwickler sagt, die Hardware ist schuld, und anders konnte er es
> nicht machen. Aber was er sich genau gedacht hat, konnte er mir auch
> nicht mehr erklären.

:-(

> Leider stecken die Leiterbahnen in einer mehrlagigen Leiterplatte, so
> daß man sie auch nicht messen kann.

Auch innere Signale sollten an den VIAs auf der Unterseite zugänglich 
sein, es denn es sind buried VIAs. Um die richtigen zu finden, brauchts 
du nur die kompletten Boarddesigndaten.

Bronco schrieb:
> Was allerdings seltsam ist, ist, daß der Neuladen des FPGA hilft.

Neuladen ist ja ein Reset.
Timingprobleme können z.B. dafür sorgen dass bei einer Onehot FSM zwei 
States gleichzeitig aktiv sind. Und schon geht nichts mehr.


Wum den Fehler zu provozieren mal mit Fön und Kältespray probieren.
Was man auch probieren kann ist die Versorgungspannungen an die unterere 
Grenze oder sogar leicht darunter einzustellen.

von Schlumpf (Gast)


Lesenswert?

Bronco schrieb:
> Bei der Fehlersuche oder bei der Jobsuche?

Jetzt mal mal den Teufel nicht an die Wand ;-)

von Bronco (Gast)


Lesenswert?

Lattice User schrieb:
>Was ist das für ein DRAM genau?
http://download.micron.com/pdf/datasheets/psram/128mb_burst_cr1_5_p26z.pdf
>Bei welcher Frequenz?
80MHz

>Das hört sich abenteuerlich an.
>Dafür gibt es IO Constraints zur Einstellung von Setup und Holdzeiten.
Welche 45 Timing Constraints-Fehler erzeugen! Der Entwickler sagt, das 
ging nicht besser, weil die Hardware auf den Signalen Skews erzeugt, und 
damit alles wieder ausgeglichen wird :-O

>Auch sollte man immer die IO Flipflops verwenden, sonst hat man mit
>jedem neuem Bitimage andere Setup/Hold Erfordenisse.
Das hab ich.

>Auch innere Signale sollten an den VIAs auf der Unterseite zugänglich
>sein, es denn es sind buried VIAs. Um die richtigen zu finden, brauchts
>du nur die kompletten Boarddesigndaten.
Nicht bei einer 12-lagigen Platine mit BGA-Bauteilen :-(

>Wum den Fehler zu provozieren mal mit Fön und Kältespray probieren.
Ja, genau das mach ich seit mehreren Wochen: Verschiedene Boards bei 
verschiedenen Temperaturen mit verschiedenen Firmwaren testen und 
versuchen, irgendein Muster im Verhalten zu erkennen.


Ich denke, das einzig sinnvolle wäre, jedes Bus-Signal mit dem Logic 
auszumessen. Aber weder komm ich an die Leitungen ran, noch haben wir 
einen Logic.

von Duke Scarring (Gast)


Lesenswert?

Bronco schrieb:
[DRAM]
>>Bei welcher Frequenz?
> 80MHz
Auf dem Spartan3 ist das schon sportlich. Der hat m.E. auch keine 
IO-Delays um Skew ausgleichen zu können.

Du kannst die ersten beiden RAM-Zellen mit Nullen und Einsen füllen. Mit 
einer DCM schiebst Du dann den Takt für das Lesen der Daten solange hin 
und her, bis Du in der Mitte vom Auge bist.

> Ich denke, das einzig sinnvolle wäre, jedes Bus-Signal mit dem Logic
> auszumessen. Aber weder komm ich an die Leitungen ran, noch haben wir
> einen Logic.
Einmal mit Profis arbeiten ;-)

Duke

von Schlumpf (Gast)


Lesenswert?

Bronco schrieb:
> Welche 45 Timing Constraints-Fehler erzeugen! Der Entwickler sagt, das
> ging nicht besser, weil die Hardware auf den Signalen Skews erzeugt, und
> damit alles wieder ausgeglichen wird :-O

Das heißt, der Entwickler ist greifbar und hat sich noch nicht aus dem 
Staub gemacht?
Wieso wird der dann nicht verpflichtet, den Fehler zu suchen, wenn er ja 
doch anscheinende recht genau weiss, was da geht und was nicht?
Aber gut, das ist eure interne Politik und um die geht es hier nicht.

Die Aussage, dass es nicht besser geht und die Skews auf der Hardware 
das dann schon richten, die finde ich sehr spannend.
Wenn er die Skews kennt, dann kann er die in den Constraints für den 
FPGA mit einrechnen. Somit ist die Zielvorgabe für die Synthese klar. 
Schmeißt die dann immer noch Fehler, dann hat sie die Zielvorgabe nicht 
erreicht und man muss mit Problemen rechnen.
Wenn man allerdings pauschal sagt, dass man eigentlich schrottige 
Constraints verwendet und weiss, dass die Synthese es nicht schafft, 
aber es dann ja schon irgendwie passt, weil die HW nen Skew erzeugt, 
dann ist das unterstes Bastelniveau!
Man müsste ja nach JEDEM Syntheselauf die Laufzeiten der einzelnen 
Signale manuell auswerten, mit den Skews auf der Leiterplatte verrechnen 
und dann entscheiden, ob das so passt.
Dieses Vorgehen ist, mit Verlaub, kompetter Murks. Und ich würde mir 
diesen Entwickler an den "Ei..n" packen, weil die Aussage "geht nicht 
besser" kann ich nicht ganz glauben, sondern klingt für mich eher nach 
"ich habe keine Ahung, warum mein Gebastel überhaupt jemals funktioniert 
hat, aber ich hab jetzt die Hosen gestrichen voll, dass ich mit dem 
Schei.. nochmal auseinander setzen muss, weil ich war damals schon nicht 
verstanden, was ich hier tue."

Ich an deiner Stelle würde das Problem entweder politisch lösen, oder du 
musst dir wirklich die Mühe machen, anhand des Datenblattes des RAMs und 
der Leiterplattengeometrie (Signallaufzeiten auf dem PCB), alle 
Constraints sauber zu definieren. Ansonsten stocherst du eigentlich nur 
genauso planlos im Dunkeln, wie der Entwickler des Boards.

von Gustl B. (-gb-)


Lesenswert?

Hallo, ich betreibe diesen RAM wie auf Seite 11 des verlinkten PDFs 
beschrieben. Das Board ist hier ein Nexys2.


Ich verwende zwar nur 50MHz aber das geht total problemlos und ziemlich 
einfach, ich brauche je 16Bit so 5 Takte für schreiben oder lesen. Also 
so 20MBytes/s. Wenn dir das reicht kann ich gerne mal Code hochladen.

Allerdings hab ich mir keinen "Controller" geschrieben sondern verwende 
einzelne Schreib- und Leseoperationen.

-gb-

von Bronco (Gast)


Lesenswert?

Gustl Buheitel schrieb:
> Hallo, ich betreibe diesen RAM wie auf Seite 11 des verlinkten PDFs
> beschrieben. Das Board ist hier ein Nexys2.

Danke, aber wir benutzen den Burst-Mode, um die max. Datenrate zu 
erreichen.

Das Problem ist auch nicht das RAM, sondern die Anbindung des RAMs an 
den FPGA (Layout). Da sind anscheinend viele Defizite, die man in der 
FPGA-Logik ausgleichen wollte.

von Johannes E. (cpt_nemo)


Lesenswert?

Verwendest du eine PLL mit mehreren Ausgangstakten? Ich hatte mal einen 
ähnlichen Effekt (bei einem Altera Cyclone II):

Mit einer PLL wurden aus einem externen Takt-Signal mehrere Takte 
erzeugt, die zueinander eine bestimmte Phasenlage haben müssen. Wenn auf 
dem externen Takt-Signal eine Störung war bzw. der externe Takt 
kurzzeitig ausgesetzt hat, konnte es passieren, dass sich die Phasenlage 
der Ausgangstakte der PLL zueinander verschoben hat und dann auch 
dauerhaft falsch geblieben ist.

Nach einem Neustart der FPGAs war es dann wieder gut. Alternativ gibt es 
auch einen Reset-Eingang für die PLL, mit der die Phasenlage der 
Ausgangssignale neu initialisiert wird.

von Bronco (Gast)


Lesenswert?

Johannes E. schrieb:
> Nach einem Neustart der FPGAs war es dann wieder gut. Alternativ gibt es
> auch einen Reset-Eingang für die PLL, mit der die Phasenlage der
> Ausgangssignale neu initialisiert wird.

Danke, das ist ein interessanter Ansatz.

Ich hab mir auch schon überlegt, ob zu dem Zeitpunkt, wo das Busprotokol 
im RAM konfiguriert ist, der DCM überhaupt schon gelockt ist.
Dem geh ich mal nach...

von Johannes E. (cpt_nemo)


Lesenswert?

Bronco schrieb:
> Ich hab mir auch schon überlegt, ob zu dem Zeitpunkt, wo das Busprotokol
> im RAM konfiguriert ist, der DCM überhaupt schon gelockt ist.
> Dem geh ich mal nach...

Üblicherweise verwendet man den "Locked"-Ausgang (heist bei Altera so, 
bei Xilinx evtl. anders), um das sicherzustellen.

von Lattice User (Gast)


Lesenswert?

Bronco schrieb:
>
>>Auch innere Signale sollten an den VIAs auf der Unterseite zugänglich
>>sein, es denn es sind buried VIAs. Um die richtigen zu finden, brauchts
>>du nur die kompletten Boarddesigndaten.
> Nicht bei einer 12-lagigen Platine mit BGA-Bauteilen :-(
>

Die Platine hat also buried VIAs?

Du schreibst weiter oben, dass eine externe Clock verwendet wird die den 
DRAM direkt taktet und auch an den FPGA geht.
Laut dem DRAM Datenblatt muss aber bei bestimmten Operationen die Clock 
fest auf Low sein. Wie wird das erreicht?

von Bronco (Gast)


Lesenswert?

Lattice User schrieb:
> Die Platine hat also buried VIAs?
Jede Menge.

> Du schreibst weiter oben, dass eine externe Clock verwendet wird die den
> DRAM direkt taktet und auch an den FPGA geht.
> Laut dem DRAM Datenblatt muss aber bei bestimmten Operationen die Clock
> fest auf Low sein. Wie wird das erreicht?
Der externe 80MHz-Clock ist fest verdrahtet mit dem CLK-Eingang, woraus 
sich ergibt, daß das RAM ausschließlich im synchronen Burst-Mode 
betrieben werden kann. :(
Ich hatte auch schon die Idee, das RAM zu Testzwecken aysnchron 
anzusteuern, aber die Idee konnte ich knicken, weil ich im FPGA keine 
Kontrolle über den CLK-Eingang des RAMs hab.

von Lattice User (Gast)


Lesenswert?

Bronco schrieb:

> Der externe 80MHz-Clock ist fest verdrahtet mit dem CLK-Eingang, woraus
> sich ergibt, daß das RAM ausschließlich im synchronen Burst-Mode
> betrieben werden kann. :(

Auch im synchronen Modus muss man die Configregister im RAM asynchron 
beschreiben. Und man muss ja mindestens einmal schreiben um den RAM in 
den Burstmode zu bringen.

> Ich hatte auch schon die Idee, das RAM zu Testzwecken aysnchron
> anzusteuern, aber die Idee konnte ich knicken, weil ich im FPGA keine
> Kontrolle über den CLK-Eingang des RAMs hab.

Werden die 80 MHz noch für etwas anderes auf dem Board gebraucht?

von Bronco (Gast)


Lesenswert?

Lattice User schrieb:
> Auch im synchronen Modus muss man die Configregister im RAM asynchron
> beschreiben. Und man muss ja mindestens einmal schreiben um den RAM in
> den Burstmode zu bringen.
Wir benutzen die Methodik, die im Datenblatt unter "Configuration 
Register WRITE, Synchronous Mode" (Figure 13) beschrieben ist. Dabei 
werden die Address-Leitungen benutzt, um die Register zu konfigurieren.

> Werden die 80 MHz noch für etwas anderes auf dem Board gebraucht?
Nein, nur für's RAM.

von Lattice User (Gast)


Lesenswert?

Bronco schrieb:

>
>> Werden die 80 MHz noch für etwas anderes auf dem Board gebraucht?
> Nein, nur für's RAM.

D.h. man könnte (zumindestens testweise) den Clockgenerator entfernen 
und CLK auf L löten.

Die FPGA interne Clock für den RAM Controller muss man dann halt 
woanders herholen.

Ich kenn mich mit dem Spartan nicht aus, aber wenn es möglich ist den 
verwendeten Pin auch als Ausgang zu verwenden kann man die Clock für
den RAM auch im FPGA erzeugen.
Hätte auch den Vorteil dass die Abdeckung der Timinganalyse viel grösser 
ist.
Vorrausgesetzt der FPGA ist schnell genug ist es sogar sinnvoll mit dem 
doppelten Takt zu arbeiten und CLK wie einen normalen Signalausgang zu 
anzusteuern.

von Kest (Gast)


Lesenswert?

Ein Schuß ins Blaue:
schaue mal den Constraint "Signal Strength" an (keine Ahnung, wie es bei 
Xilinx heißt). Setze diesen so weit wie möglich herunter. Damit werden 
die "Ecken" der Signale "gegelättet" (leihenhaft ausgedrückt)

Kest

von Bronco (Gast)


Lesenswert?

Ich hab inzwischen ein interessantes Detail herausgefunden:
Wenn ich die Spannungsversorgung wegnehme und wieder anschließe und dann 
den FPGA lade, kommt ist mit hoher Wahrscheinlichkeit zu einem 
RAM-Fehler.
Wenn ich dann den FPGA nochmal lade, ist der Fehler mit hoher 
Wahrscheinlichkeit weg.
Das hab ich vielfach reproduzieren können.
Es spielt keine Rolle, wie lange ich zwischen Power-On und dem ersten 
FPGA laden warte (konnte auch nach 10min Wartezeit den Fehler 
reproduzieren).

Übrigens hab ich auch eine Prüfung der DCM-Lock-Signal eingebaut, 
brachte aber keine Verbesserung... verdammt!

von Schlumpf (Gast)


Lesenswert?

Sozusagen eine Toggle-Eigenschaft.
tut - tut nicht - tut - tut nicht...

Das ist echt sehr eigenartig.
Vorallem weil du schreibst, dass es egal ist, wie lange die Pause 
zwischen den Vorgängen ist. Das würde ja bedeuten, dass irgendeine 
Information auf dem Board erhalten bleibt, trotz Spannungsabfall. Was 
könnte das sein?
Oder ist es doch einfach nur Zufall, dass das Board dieses Verhalten 
zeigt?

Ich weiss, das ist jetzt nicht hilfreich, aber vielleicht hilft es, in 
eine Richtung zu denken.

Resets sind "sauber"?

von Schlumpf (Gast)


Lesenswert?

Haben alle Register einen definierten Reset-Wert?
ist der interne globale Reset mit dem Lock-Signal der PLL verknüpft?

von Lattice User (Gast)


Lesenswert?

Lass mal die DRAM Initialisuerung (Schreiben der Konfiguratiosnregister) 
2 mal durchführen.

von Bronco (Gast)


Lesenswert?

Es wird immer besser:
Bei ca. 20°C muß ich den FPGA i.d.R. 2x laden, damit der Fehler weggeht.
Bei ca. 30°C nur noch 1x, und bei 60°C geht es auf Anhieb!

Den Sche*ß soll mir mal einer erklären...

Lattice User schrieb:
> Lass mal die DRAM Initialisuerung (Schreiben der Konfiguratiosnregister)
> 2 mal durchführen.

Okay, werd ich macen.

Schlumpf schrieb:
> Haben alle Register einen definierten Reset-Wert?
Soweit ich beurteilen kann: ja.
> ist der interne globale Reset mit dem Lock-Signal der PLL verknüpft?
Einen globaler Reset gibt es gar nicht... wär noch'ne Idee!

von Johannes E. (cpt_nemo)


Lesenswert?

Bronco schrieb:
> Es wird immer besser:
> Bei ca. 20°C muß ich den FPGA i.d.R. 2x laden, damit der Fehler weggeht.
> Bei ca. 30°C nur noch 1x, und bei 60°C geht es auf Anhieb!

> Einen globaler Reset gibt es gar nicht... wär noch'ne Idee!

Das passt jetzt aber ganz gut zusammen. Wenn es kein Reset gibt, dann 
ist die Initialisierung von einigen FlipFlops eher zufällig und das kann 
dann auch Temperaturabhängig sein.

Hat die PLL auch einen Reset-Eingang, um die Phasenlage der 
Ausgangstakte zu synchronisieren?


Zumindest können wir jetzt mit sehr großer Sicherheit sagen, dass es 
keine Fehler im Bitfile sind.

von Christian R. (supachris)


Lesenswert?

Du kannst ja auch mal die Konfiguration per BitGen Einstellung bis zum 
DCM Lock verzögern, das sollte den gleichen Effekt wie den GSR ergeben. 
Ansonsten gibts so eine GSR Komponente (STARTUP_SPARTAN3).

von Bronco (Gast)


Lesenswert?

Christian R. schrieb:
> Du kannst ja auch mal die Konfiguration per BitGen Einstellung bis zum
> DCM Lock verzögern, das sollte den gleichen Effekt wie den GSR ergeben.
> Ansonsten gibts so eine GSR Komponente (STARTUP_SPARTAN3).

Jo, hab ich schon drinn:
1
   DCM_INST : DCM
2
   generic map( ...
3
            STARTUP_WAIT => TRUE)

Hilft leider nichts.

von Christian R. (supachris)


Lesenswert?

Das muss aber in BitGen auch freigeschaltet sein, soweit ich weiß:
1
The FPGA startup sequence must also
2
be modified to insert a LCK (lock) cycle before the postponed cycle
3
(see “Bitstream Generation Settings”).

von Bronco (Gast)


Lesenswert?

Du hast Recht, wußte ich noch nicht. Danke!

von Schlumpf (Gast)


Lesenswert?

Bronco schrieb:
> Schlumpf schrieb:
>> Haben alle Register einen definierten Reset-Wert?
> Soweit ich beurteilen kann: ja.
>> ist der interne globale Reset mit dem Lock-Signal der PLL verknüpft?
> Einen globaler Reset gibt es gar nicht... wär noch'ne Idee!

Ein Reset-Wert ist nicht unbedingt gleichzusetzen mit dem default-Wert. 
Jedenfalls überlässt du dann ein wenig zu sehr der Synthese was sie 
daraus macht.
Besser ist es auf jeden Fall ein globales Reset-Signal zu definieren und 
dieses mit dem LOCK-Signal der PLL zu verknüpfen. Und wenn du keinen 
Reset-Pin hast, dann nehm einfach nur das Lock-Signal der PLL als Reset. 
Und dann werden ALLE Register über
1
if reset = '0' then
2
....
zu einem definierten Wert gesetzt, wenn das Reset-Signal aktiv ist.

Ob dein Problem daher kommt, kann man natürlich nicht sagen, aber es ist 
eine Stelle, die du zumindest leicht ausschließen kannst, indem du alle 
Register vollständig beschreibst

von Bronco (Gast)


Lesenswert?

Noch ein Detail:
Wenn der FPGA einmal den korreken Zustand hat, kommt der Fehler gar 
nicht mehr, auch wenn ich den ganzen Temperaturbereich abfahre.
Bei 15°C kann ich den FPGA so oft laden, wie ich will, der Fehler ist 
immer da. Wenn ich den FPGA bei 30°C lade, ist der Fehler weg, und dann 
kann ich auch wieder auf 15°C runtergehen, ohne daß der Fehler kommt 
(solange ich den FPGA nicht neu lade).
Das muß ein Initialisierungsdreck sein. Wenn ich doch nur diesen 
Spaghetti-Code nachvollziehen könnte... :-O

von Christian R. (supachris)


Lesenswert?

Hm, dann hilft vielleicht wirklich, in den Signaldeklarationen einen 
sinnvollen Wert jedem FlipFlop zuzuweisen und dann die Konfig solange 
verzögern bis alle DCMs gelockt sind. Fies ist auch dass das LOCK am 
Spartan 3 auch gerne mal zu zeitig kommt, da klappert der Takt noch 
etwas. Ich hab da meistens noch ein Schieberegister dran, mit dem ich 
das LOCK nochmal ein paar Takte verzögere. Das hat auch den Vorteil, 
dass man das LOCK als synchronen Reset nehmen kann.
Vielleicht hilft auch der Trick mit dem BUFGCE statt BUFG hinter dem 
DCM, da kannst du den Takt definitiv erst los rennen lassen, wenn LOCK 
da ist. Also mit dem fehlenden LOCK die Takte abschalten.

von Bronco (Gast)


Lesenswert?

Christian R. schrieb:
> Vielleicht hilft auch der Trick mit dem BUFGCE statt BUFG hinter dem
> DCM, da kannst du den Takt definitiv erst los rennen lassen, wenn LOCK
> da ist. Also mit dem fehlenden LOCK die Takte abschalten.

Das wär noch eine Idee!

Bisher hab ich es etwa so gelöst:
1
if (rising_edge(RAMCLK) then
2
  if (RAMCLK_DCMLOCKED) then
3
    ...
4
  end if;
5
end if;

Ich gehe mal davon aus, daß es keinen Unterschied macht, welche 
Bedingung zuerst kommt.

von Christian R. (supachris)


Lesenswert?

Bronco schrieb:
> Bisher hab ich es etwa so gelöst:

Das sollte ja auch gehen, aber die Initialisierung fehlt dann eventuell. 
Vielleicht ist ja auch irgendwo bei einem Signal mal eine 
Initialisierung auf 1 nötig, der Code versucht das Reset mit DCMLOCK = 0 
und dem Takt aus dem DCM, das geht dann natürlich schief und weil die 
Synthese nicht-initialisierte Signale normalerweise auf 0 initialisiert, 
passt was nicht.

von Johannes (Gast)


Lesenswert?

Bronco schrieb:
> if (rising_edge(RAMCLK) then
>   if (RAMCLK_DCMLOCKED) then
>     ...
>   end if;
> end if;

Das halte ich für sehr gefählich, wenn nicht sichergestellt ist, dass 
RAMCLK_DCMLOCKED auf deinen Takt synchronisiert ist.

Deshalb alle asynchronen Reset-Signale miteinander verknüpfen, dazu 
gehören auch die Locked-Signale. Dieses verknüpfte Signal muss dann mit 
mindestens einem Register synchronisiert werden, besser sind zwei 
Register.

Daraus wird dann ein globales Reset-Signal erzeugt, welches so 
verarbeitet werden kann:
1
if Reset = '1' then
2
  <hier alle Register initialisieren>
3
elsif (rising_edge(RAMCLK) then
4
  <hier den normalen Code ausführen>
5
end if

von Christian R. (supachris)


Lesenswert?

Johannes schrieb:
> Dieses verknüpfte Signal muss dann mit
> mindestens einem Register synchronisiert werden, besser sind zwei
> Register.
>
> Daraus wird dann ein globales Reset-Signal erzeugt, welches so
> verarbeitet werden kann:

Nana, und wieso dann trotzdem den asynchronen Reset? Dann doch lieber 
synchron. Siehe Beitrag "Xilinx und die Resets"

von Johannes E. (cpt_nemo)


Lesenswert?

Christian R. schrieb:
> Nana, und wieso dann trotzdem den asynchronen Reset?

Das ist jetzt eher eine philosophische Frage. Es gibt schon Gründe, 
asynchronen Reset zu verwenden:

- Reset ist auch dann wirksam, wenn kein Takt aktiv ist.
- Es wird keine zusätzliche Logik bzw. LUTs verbraucht.
- Latenzzeit ist kürzer.

Aber du hast schon recht; wenn man das Reset-Signal korrekt 
synchronisiert hat, kann man dieses auch in synchroner Logik 
verarbeiten.

Christian R. schrieb:
> Dann doch lieber synchron.

Was soll daran besser sein?

von Bronco (Gast)


Lesenswert?

Das isz jetzt echt mal eine interessante Frage:

Optimalerweise macht man alles taktsynchron. Aber was macht man, wenn 
der Takt eventuell noch nicht stabil ist?

Eigentlich muß man wirklich den Takt abschalten, bis DCM_Lock gegeben 
ist.

von Johannes E. (cpt_nemo)


Angehängte Dateien:

Lesenswert?

Bronco schrieb:
> Eigentlich muß man wirklich den Takt abschalten, bis DCM_Lock gegeben
> ist.

Nein, muss man nicht bzw. das würde nichts nützen.

Dafür gibt es den asynchronen Reset. Solange das Lock-Dignal nicht 
gesetzt ist, ist Reset aktiv und alle Register werden im 
Initialisierungszustand festgehalten.

Getreu dem Motto "Ein Bild sagt mehr als tausend Worte" hab ich mal 
einen Screenshot angehängt, wie ich das Locked-Signal üblicherweise 
verschalte.

Das ist ein Beispiel aus einem Altera-Projekt, bei Xilinx sollte das 
genau so funktionieren.

von Bronco (Gast)


Lesenswert?

Hey Leute, ich bin einen Riesenschritt weiter gekommen!

Ich hab jetzt die Komponente "STARTUP_SPARTAN3" eingebaut, die ich bis 
dato noch gar nicht gekannt hab. Ich steuere die Signale "GSR" und "GTS" 
im Moment noch über ein externes Ereignis an.
Soweit ich bisher getestet habe, sind die RAM-Problem nach einem solchen 
"Reset" immer zuverlässig weg, und zwar deutlich zuverlässiger als nach 
FPGA-Neuladen.

Ich weiß, Supachris hat oben schon darauf hingewiesen, aber ich hatte 
"Global Reset" falsch verstanden, ich dachte, Ihr meint, daß man in 
jedem Modul einen Reset-Zweig von Hand programmiert.

Jetzt werd ich mal probieren, ob ich das über die DCM-Locks 
automatisieren kann...

Danke Euch allen!

von Holger H. (holger-h-hennef) Benutzerseite


Lesenswert?

Bronco schrieb:
> Jetzt werd ich mal probieren, ob ich das über die DCM-Locks
>
> automatisieren kann...
Ja das finde ich auch, automatisieren ist wichtig.

Ja hier sind das die attribute STARTUP_WAIT=>TRUE .
                               DCM_WAIT=TRUE attribute
Link:
http://www.xilinx.com/support/documentation/user_guides/ug332.pdf
Zitat:
STARTUP_WAIT=TRUE attribute, the FPGA waits for such
DCMs to acquire their respective input clock and assert their
LOCKED output. This setting selects the Configuration
#################################################################
Startup phase where the FPGA waits for the DCMs to lock.
#######################################################
See “Waiting for DCMs to Lock, DCI to Match,” page 253.
###########################################
....................

Damit ist das sicher einfach für den Anwender gemacht,
 STARTUP_WAIT        => TRUE, -- FALSE
1
  
2
dcm_inst : DCM_SP
3
    generic map (
4
      DLL_FREQUENCY_MODE    => "LOW",
5
      DUTY_CYCLE_CORRECTION  => TRUE,
6
      CLKOUT_PHASE_SHIFT    => "NONE",
7
      PHASE_SHIFT          => 0,
8
      CLKFX_MULTIPLY        => 5,  -- range 2 to 32
9
      CLKFX_DIVIDE        => 4,  -- range 1 to 32
10
      CLKDV_DIVIDE        => 2.0,
11
      STARTUP_WAIT        => FALSE, -- TRUE
12
                                   -- DCM_WAIT=TRUE attribute 
13
      CLKIN_PERIOD        => 31.25 --@30MhzMy-Base-Clock
14
    )
-- .....................
--   O_CLK_40M    generated 32Mhz /4 *5 = 40Mhz clock
--   O_CLK_115200  generated 40Mhz / 346 = 115606 baud clock
--                                    346/2= 173 => 0xad
              -- 115200 baud clock
  divider: process(clk_dcm_fx_bufg)
    begin
    if rising_edge(clk_dcm_fx_bufg) then
      if (counter = x"ad") then      -- 40Mhz /2 /"0ad" = 115606.9
        clk_divider <= not clk_divider;
        counter <= (others => '0');
      else
        counter <= counter + 1;
      end if;
    end if;
  end process;
--
Ja auf unserem Labortisch ist das Design stabil ..aber der 
Feldversuch.???.
Hint:
Hilfreich sind auch Muster-Beispiele zu MultiBoot Aplikationen,
wo halt 3 FPGAS gemeinsam Master-Slave[#1][#2]..in Vorgabe-sequenz 
definiert angefahren werden.
------------------------------------------------------------------------ 
-----------------------
Hint:
Zusatz in Hardware  ist noch der z.B Lattice Power-Manager II Chip.
(ca. 1$ ) Als Analog-Digital (8*GPI/O..) micro Sequencer wird das FPGA 
Design
mit dem man die jeweilige (3,3,2.5,1.8 Vcore) Spg-Versogung für Core- 
Bank, I/O  ...
Start-Up Sequenz vorlegt u. dyn. ueberwachen kann.
    (besonders in IndustrieNetzen mit EMTransienten) ..
Somit also via build in Chip. (48 Pin-Package ) u. Feature
I2C Bus ein dyn. Monitoring-Status, u. Watchdog-Master-Feed-Back. 
Trigger-U-ref gratis
damit machen kann.
--- Also: Think And not OR

>Ich steuere die Signale "GSR" und "GTS"
>im Moment noch über ein externes Ereignis an.

Viel Erfolg mit deinem Project ...
Gruss Holger.

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.