Forum: FPGA, VHDL & Co. Cyclone10CL025*Quartus Register mit Wert belegen zerstört Funktion an anderer Stelle


von Andreas R. (df8oe)


Lesenswert?

Hallo an alle,
ich arbeite an einem recht aufwändigen FPGA-Projekt. Dort ist ein SDR 
Empfänger und Sender implementiert, der über einen I2C Bus gesteuert 
wird. Aktuell läuft alles - aber ich möchte den I2C-Block neu gestalten. 
Es ist keine IP - es ist ein in Verilog handgeschriebener I2C-Slave. In 
diesem Modul muss ich alles mögliche ändern. Um nicht jedesmal den 
kompletten SDR neu zu bauen (das dauert doch schon recht lange) verwende 
ich zum Testen dieses Entwicklungsboard hier: 
https://de.aliexpress.com/item/33050240958.html . Darauf läuft mein Code 
auch so wie er soll. Schiebe ich dieses Modul jedoch in das aufwändige 
Zielprojekt, dann funktioniert auf einmal der DSP-Teil (FIR-Filter, 
Dezimierung) nicht mehr so wie er soll. Ich habe Stunden den Fehler in 
meinem Code gesucht bis ich festgestellt habe, dass schon zwei banale 
Zeilen im I2C-Modul den gleichen Effekt haben: ich lege ein Register im 
Modul an mit
reg [7:0] dataready;
dem ich dann in der Resetroutine einen Wert zuweise mit:
dataready <= 0;
Sowie die Zuweisung drin ist, geht der DSP Teil nicht mehr. Das Register 
dataready wird sonst nirgendwo mehr benutzt (was mir Quartus Prime lite 
auch brav meldet) - aber nicht warum der DSP Teil dann nicht mehr läuft. 
Da diese beiden Zeilen nichts Böses in sich tragen (und auf dem 
Entwicklungsboard mit vielen anderen weiteren Zeilen auch eine bewiesene 
Funktion haben) kann ich mir nur vorstellen dass der Fitter Dinge anders 
routet wenn ich diese Zeile einfüge.
Ich denke also ich muss dem Fitter irgendwie sagen (mit dem 
Constraints_File??) dass er das bestehende Routing so lassen soll wie es 
ist. Nach meiner Vorstellung nach dem ersten Lauf einen "Schnappschuss" 
machen und den dann als Basis für weiteres nehmen. Nur wie geht das? Und 
ist meine Vermutung überhaupt richtig? Ich bin in Sachen FPGA 
Programmierung noch ein ziemlicher Anfänger und war schon froh dass ich 
den I2C-Slave von "only read mit festen 10 Bytes" auf "Register 
verwenden - variable Datenlänge - read/write" umstellen konnte. Den DSP 
Code verstehe ich aktuell nicht vollständig. Es ist GPLv3 lizensierter 
Code den ich auch noch verstehen und verändern möchte: aber deutlich 
später. Solange ich schon am I2C-Teil scheitere brauche ich damit gar 
nicht erst anzufangen... Wie kann ich das Problem angehen? Ich bin für 
jeden Tipp dankbar!

von C-64 Freund (Gast)


Lesenswert?

Wie passen dies
> ich arbeite an einem recht aufwändigen FPGA-Projekt.

und dies
> Ich bin in Sachen FPGA-Programmierung noch ein ziemlicher Anfänger

zusammen?

von Andreas R. (df8oe)


Lesenswert?

Die Antwort passt nicht wirklich auf meine Frage ;)

Es gibt viele bereits lauffähige Projekte / Codeblöcke. Die habe ich 
übernommen - vorerst ohne sie komplett zu durchschauen. Aber selbst dort 
habe ich schon kleiner Fehlerchen gefunden und beseitigt - und die 
Funktion war dann besser / stabiler (je nach Codeänderung die zu Grunde 
liegt). Und dann sind da einfachere Teile - wie SAI, SPI, I2C. Die 
verstehe ich schon. Das ist ein Hobbyprojekt, und ich liebe "learning by 
doing". Mir ist durchaus bewusst dass die Lösung meines Problemes 
vermutlich für jemanden der schon lange mit FPGAs und Quartus arbeitet 
einfach ist. Für mich aber trotz intensiver Nutzung der Suche im Forum 
hier und im Netz nicht.

von Steffen H. (avrsteffen)


Lesenswert?

Andreas R. schrieb:
> Dort ist ein SDR Empfänger und Sender implementiert, der über einen I2C
> Bus gesteuert wird.

Also gibt es schon einen funktionierenden I2C Slave der den SDR steuert? 
Wenn ja, wie meinst du das? Da sind I2C Register, die den SDR 
einstellen?

Andreas R. schrieb:
> aber ich möchte den I2C-Block neu gestalten.
> verwende ich zum Testen dieses Entwicklungsboard..
> Darauf läuft mein Code auch so wie er soll. Schiebe ich dieses Modul
> jedoch in das aufwändige Zielprojekt, dann funktioniert auf einmal der
> DSP-Teil (FIR-Filter, Dezimierung) nicht mehr so wie er soll.

Also hast du ein neues I2C Slave Modul dafür geschrieben und willst es 
jetzt wieder mit dem SDR verbinden und dies funktioniert nicht?
Vielleicht solltest du mal etwas Code zur Verfügung stellen damit wir 
dir hier eventuell weiter helfen können.

von Fpgakuechle K. (Gast)


Lesenswert?

* Mach ne simulation vom I2C
* Zeichne ein Blockbild mit den internen Bussen/Registern von deinem 
design
*schau ob dein Ansatz (änderung des designs auf Board A mit FPGA-Typ X), 
Übertragung des Designs 1:1 auf ein anderes Board B möglicherweise mit 
FPGA type Y überhaupt funktionieren kann.

Das
"verwende
ich zum Testen dieses Entwicklungsboard hier:  Darauf läuft mein Code
auch so wie er soll. Schiebe ich dieses Modul jedoch in das aufwändige
Zielprojekt, ..." und
"Ich denke also ich muss dem Fitter irgendwie sagen (mit dem
Constraints_File??) dass er das bestehende Routing so lassen soll wie es
ist. Nach meiner Vorstellung nach dem ersten Lauf einen "Schnappschuss"
machen und den dann als Basis für weiteres nehmen."

kann man auch so interpretieren, das dein Designflow/'Programmierablauf' 
nicht funktionieren kann. Weil die 'Teile' nicht zusammenpassen und du 
nicht weisst welche Dateien/Settings überhaupt zwischen den Systemen 
auszutauschen sind.
--
Sorry aber das klingt nach einem grundsätzlichen Problem aus völliger 
Unkenntniss der FPGA-Methologie und digitaler Schaltungstechnik, da ist 
eine Hilfe per internetforum so gut wie ausgeschlossen. Lass Dir von 
einer Fachkraft vor Ort eine Entwicklungs-/Testumgebung aufsetzen und 
erklären.


PS: Dein Link zeigt einen 10CL016 und keinen 10CL025 (wie im Topic 
behauptet).

von Markus F. (mfro)


Lesenswert?

Hmmm. Ominös. Kann eigentlich nicht sein. Ein zusätzliches Register, das 
lediglich initialisiert und nie gelesen wird, wird mit (sehr) hoher 
Wahrscheinlichkeit sowieso wegoptimiert (sollte im "Registers removed 
during Synthesis"-Report im "Analysis & Synthesis"-Log eigentlich zu 
sehen sein) und kann deshalb kaum die Ursache für das beschriebene 
Verhalten sein.

Sehr viel wahrscheinlicher ist, dass das Timing ohnehin schon am Limit 
ist, nur zufällig funktioniert hat und Du an der völlig falschen Stelle 
suchst.

Was sagt der Timing Analyzer?

Der Ansatz ein (anscheinend) einmal funktionierendes Design 
"einzufrieren",  unverändert weiter zu benutzen um "an anderer Stelle 
weiterzubauen" scheint naheliegend, führt aber nicht zum Ziel. Zum einen 
kann das die Lite-Variante von Quartus nicht (das erfordert "Design 
Partition"-Funktionalität und die gibt's nur gegen Bezahlung), zum 
anderen würde das wahrscheinlich auch nicht helfen (man kann nun mal 
nichts ändern, ohne was zu ändern).

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Markus F. schrieb:
> Sehr viel wahrscheinlicher ist, dass das Timing ohnehin schon am Limit
> ist, nur zufällig funktioniert hat und Du an der völlig falschen Stelle
> suchst.
Oder gar, dass da irgendwo der übliche asynchrone Eingang nicht 
eingetaktet wird.

Andreas R. schrieb:
> Darauf läuft mein Code auch so wie er soll.
Wieviele "Takte" hat dein Code?

> Sowie die Zuweisung drin ist, geht der DSP Teil nicht mehr.
Aber dein neu implementierter I2C tut was er soll?
> Sowie die Zuweisung drin ist, geht der DSP Teil nicht mehr.
Undd was davon "geht nicht mehr"? Einfach alles? Oder nur der Teil, der 
mit dem I2C interagiert?
Was steht in den Reports? Infos, die du nicht verstehst, sind dabei 
genauso wichtig wie Warnings, die dir nichts sagen...

von Andreas R. (df8oe)


Lesenswert?

Danke für eure Gedanken und eure Zeilen. Ich bin gerade dabei das GitHub 
für den Code aufzuarbeiten und werde es dann veröffentlichen.

Vorab:
Das "Ursprungsprojekt" lief auf einem 10CL006 - der war damit "so gut 
wie voll". Dann habe ich eine neue PCB mit veränderter Hardware erstellt 
und einen 10CL016 eingesetzt. Auch das lief problemlos. Weil ich vor 
hatte erheblich mehr Hardware anzubinden habe ich getestet, ob auch der 
10CL025 läuft: er tat es. Die Pinbelegung habe ich von Anfang an auf den 
025 ausgelegt. Die FPGAs sind im 256 UBGA Gehäuse. Die letzte PCB ist 
nun fertig (6-fach-Layer) und auch diese tut wie sie soll. Die neu 
hinzugekommene Hardware ist bereits teilweise ausgetestet und läuft 
ebenfalls. Die weitere Hardware wird Stück für Stück in den FPGA-Code 
eingebunden - so der Plan.

Via I2C wird die Arbeitsfrequenz und die Samplerate des 
Ausgangs-Datenstromes (SAI) eingestellt. Ich habe diese auch mal 
"hardgecoded" im FPGA, so dass der I2C nichts mehr weiterreicht was zum 
Betrieb nötig ist. Auch das läuft. Das I2C-Handshaking geht natürlich 
noch. Wenn ich dann die oben gesagte Registerzuweisung in den Code 
einfüge, geht das I2C-Handshaking nach wie vor, der SAI-Strom hat auch 
noch die richtige Frequenz, aber der Datenstrom stimmt nicht mehr. Auf 
jeden Fall geht der Empfänger nicht mehr (reagiert nicht mehr auf 
Eingangssignale) und das auswertende SDR-Programm, das am SAI lauscht, 
erkennt Rauschen mit hoher Feldstärke. Es kommt etwas aus dem Tritt was 
definitiv nichts mit dem Codeteil der verändert wurde zu tun hat. Es 
sind mehrere Takte im Spiel (logischerweise). Meine Vermutung ist dass 
es in der Tat an gravierenden Fehlern in der Verknüpfung der Taktsignale 
liegt. Dazu mache ich auch eine Blockschaltung die ins GitHub wandert. 
Es wird nicht möglich sein die Ursache einzugrenzen ohne Kenntnis des 
gesamten Projektes.

EDIT/Nachtrag:
In sofern kann ich zustimmen dass die Sache "zufällig" läuft. Die 
Taktverhältnisse sind nicht so verknüpft dass eine robuste Schaltung 
herauskommt.

: Bearbeitet durch User
von Fpgakuechle K. (Gast)


Lesenswert?

Andreas R. schrieb:
> Danke für eure Gedanken und eure Zeilen. Ich bin gerade dabei das GitHub
> für den Code aufzuarbeiten und werde es dann veröffentlichen.
>
> . Dazu mache ich auch eine Blockschaltung die ins GitHub wandert.
Es ist hilfreich, wenn sich neben den Code auch ein dazu passender Satz 
an Logfiles (Synthese, placer, router, drc, ...) finden lässt. 
Idealerweise mit script für den Designflow, an dem man erkennt, welche 
Optimierungen/compilerschalter aktiv sind.

> In sofern kann ich zustimmen dass die Sache "zufällig" läuft. Die
> Taktverhältnisse sind nicht so verknüpft dass eine robuste Schaltung
> herauskommt.

Stichwort dazu ist CDC - Clock Domain Crossing, da hat die Software mehr 
oder weniger passende Checks deren Ergebnisse sich auch im Log unter 
diesen Stichwort finden lassen. Wobei man das Problem aber schon früh 
mit der Spec löst, indem man sich fragt, ob es diesen Taktdomänübergang 
braucht und welches Mittel aus dem 'Werkzeugkasten' (FIFO, Handshake, 
Synchronizer, Gray-Codierung, level statt edge-detection, debounce, ..) 
hier sinnvoll ist.

Ich hatte mal das Problem bei ein-clk-langen Steuersignale, die aus der 
schnellen in langsame Domain wechselten und mit 50% Wahrscheinlichkeiten 
liefen (weil Taktverhältniss 2:1  und Phasenlage je nach Zufall bei 
PowerOn) die lediglich auf 2 clk pulsewidth verlängert werden mussten, 
damit es lief.

Dort 'ne kurze Einführung in das Thema mit Vivado:
https://www.xilinx.com/video/hardware/cross-clock-domain-checking-cdc-analysis.html


Das Prinzip ist bei Altera/intel gleich, auch dr Syntax der timing 
constraints sollte inzwischen gleich sein.

von I_scho_wieda (Gast)


Lesenswert?

C-64 Freund schrieb:
> Wie passen dies
>> ich arbeite an einem recht aufwändigen FPGA-Projekt.
>
> und dies
>> Ich bin in Sachen FPGA-Programmierung noch ein ziemlicher Anfänger
>
> zusammen?

Kann Dir doch am AW vorbeigehn, oder?!

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.