Hallo zusammen, ich möchte meinen Memory Controller testen. Er stellt ein dual Port Memory dar, das einem µC und einem FPGA ermöglicht auf ein externes Sram zuzugreifen. Jetzt habe ich die Testbench angefangen und dazu habe ich mir ein Sram Model besorgt und eingebunden. Soweit funktioniert auch alles. In der Vorarbeit habe ich eine Testbench nur für das Sram getestet. Läuft wie erwartet, keine Fehler. Anders bei meinem Memory Controller. Da kommt die Fehlermeldung:"-E- Data not valid at end-of-write to SRAM." Die Meldung wird vom Sram-Model generiert. Es muss also im Memory Controller irgendwas falsch sein. Die Frage ist nun, Warum die Fehlermeldung kommt. Ich verstehe den Zusammenhang nicht, was passieren muss, damit diese Fehlermeldung kommt. Ich werde einfach nicht schlau draus. Und solange ich das nicht verstanden habe werde ich den Fehler in meinem Code sicher auch nicht finden. Ich hänge das Model vom Sram mit an. Danke euch! Grüße, Jens
Jens W. schrieb: > Die Frage ist nun, Warum die Fehlermeldung kommt. Guck in den angehängten Code, wann, also bei welcher Bedingung diese Meldung ausgegeben wird. Gekürzt:
1 | IF do_write'EVENT and (do_write = '1') then |
2 | IF NOT Check_For_Valid_Data(D) THEN |
3 | IF D'EVENT AND Check_For_Valid_Data(D'DELAYED) THEN |
4 | |
5 | ELSE
|
6 | write(output, "-E- Data not valid at end-of-write to SRAM."); |
7 | END IF; |
Check_For_Valid_Data ist eine Funktion. So wirklich verstehe ich den Sinn nicht. Gut, für die Simulation prüft die ob alle Bits in den Daten tatsächlich '1' oder '0' sind und nicht UXZHL. Jens W. schrieb: > Es muss also im Memory Controller irgendwas falsch sein. Warum zeigst du uns den denn dann nicht? Ich würde erstmal vermuten, dass die Daten, das ist ja ein inout, beim Schreiben ins RAM mal auf 'Z' gesetzt sind.
Jens W. schrieb: > Die Frage ist nun, Warum die Fehlermeldung kommt. Ich verstehe den > Zusammenhang nicht, was passieren muss, damit diese Fehlermeldung kommt. > Ich werde einfach nicht schlau draus. Es ist doch simpel, schau auf dem Waveformviewer ob sich am Datenbus was tut, während der Datenbus ruhig sein soll. VHDL ist eben nicht wie C wo textuelle Fehlermeldungen die einzige Rückmeldung zur Fehleranalyse sind, mit einem VHDL-Simulator kann man sich in einem y(t)-Diagramm anschauen, wie und wann die Signal schalten. Ebenso solltest du lernen wie mann die timing diagramm im Datenblatt liest, Beispiel im Anhang.
Hallo zusammen, Fpgakuechle K. schrieb: > VHDL ist eben nicht wie C wo textuelle Fehlermeldungen die einzige > Rückmeldung zur Fehleranalyse sind, mit einem VHDL-Simulator kann man > sich in einem y(t)-Diagramm anschauen, wie und wann die Signal schalten. > > Ebenso solltest du lernen wie mann die timing diagramm im Datenblatt > liest, Beispiel im Anhang. Da bin ich ja dabei. Aber auch bei der Einarbeitung kommt es vor, dass man nicht alles auf Anhieb versteht. Gustl B. schrieb: > Check_For_Valid_Data ist eine Funktion. So wirklich verstehe ich den > Sinn nicht. Gut, für die Simulation prüft die ob alle Bits in den Daten > tatsächlich '1' oder '0' sind und nicht UXZHL. Der Hinweis hat geholfen. Beim Schreiben (nWE low -> high) ändern sich die Daten auf "Z". Und das schreibt er dann auch ins RAM. Und beim Auslesen merkt die Funktion, dass da nicht eindeutige Daten drin stehen (also UXZHL) und gibt den Fehler aus. Das Interface vom Controller reiche ich nur durch. Aber da muss ich die Daten wohl noch etwas verzögern, dann wird das Timing da sauber. Ich versuchs weiter und geb Bescheid. Danke euch! Grüße, Jens
Hallo, kurze Info: Genau das war es. Das nWE von low auf high und die Daten am SRAM haben sich gleichzeitig geändert. Ich habe nun die Änderung der Daten von der Flanke auf nWE verzögert. Das hat geholfen. Keine Fehlermeldung mehr. Danke euch! Grüße, Jens
Hallo zusammen, jetzt muss ich noch was fragen. Ich hoffe der Thread hier ist nicht schon zu alt und es liest keiner mehr. Ich habe nun alles im Simulator zum Laufen bekommen. Da funktioniert alles wie es soll. Wenn ich nun aber das Bitfile auf mein Target schiebe, dann verhält sich die Geschichte nicht mehr so wie im Simulator. Ich beschreibe mal was ich mache. Auf dem Board ist ein µC und ein FPGA. Beide teilen sich das RAM. Jetzt läuft erstmal nur ein Speichertest-Programm. Der µC schreibt den Speicher voll mit Primzahlen. Das FPGA nimmt diese und macht eine XOR Verknüpfung mit einem Wert und schreib den neuen Wert zurück ins SRAM. Der Controller liest nun wieder die Werte, macht die gleiche logische Operation und schaut, ob das Ergebnis gleich ist. Lesen und Schreiben von µC ins SRAM läuft ohne Probleme. Nur wenn ich die Operation im FPGA anstoße lese ich nur noch 0 zurück. Also muss bei der Operation im FPGA was schief laufen. Nur, in der Simulation sieht das gut aus. Warnungen bekomme ich auch keine, die auf ein Problem hindeuten würden. Wo könnte ich noch schauen? Müsst ich nicht in irgendwelchen Synthese Reports Hinweise finden? Ich hänge euch mal den Code für die Operation im FPGA mit an und das Blockschaltbild. Grüße, Jens
Jens W. schrieb: > Ich habe nun alles im Simulator zum Laufen bekommen. Da funktioniert > alles wie es soll. Wenn es dann real nicht klappt, ist irgendwas in der realen Welt anders, als es in der Simulation angenommen wird. So ist zumindest meine Erfahrung. Sehe ich das richtig, das uC und SRAM beide im FPGA sind oder ist das Schaltbild nur eine Skizze? Und der SRAM ist eigentlich gar kein SRAM, sondern eher ein Rechenbeschleuniger mit SRAM-Interface, oder? Duke
Hallo Duke, das Schaltbild ist die Top Entity. Das SRAM ist ein echtes SRAM auf dem Board. Und der µC ist ein echter µC auf dem Board. Im FPGA wird nun der Zugriff auf das RAM geregelt. Den Platz brauche ich noch für die echte Anwendung. Hier ist ja nur Schreiben und Lesen der beiden Kandidaten geregelt. Ich bin auch ein Stückchen weiter. Ich vermute, dass ich ein Timing Problem habe im FPGA. Ich versuche gerade die einzelnen Schritte für den Lese- und Schreibzugriff zu verlangsamen und alles Schritt für Schritt der Reihe nach zu machen auch wenn das erstmal länger dauert. Um die Geschwindigkeit kümmere ich mich später. Erstmal muss die Karre laufen. An der Umsetzung an sich kann man jetzt wohl keine groben Schnitzer auf den ersten Blick erkennen oder? Grüße, Jens
Hast du ein Timingmodell von dem RAM in VHDL für die Simulation? Das wäre mein Ansatz, simulieren bis da keine Fehler auftreten und dann auf die Hardware. Welcher SRAM Baustein ist das genau, dann gucke ich mal ob ich ein Modell finde oder schreibe.
Hallo, das Modell für die Simulation habe ich. Die Werte für die Zeiten habe ich aus dem Datenblatt übertragen. Das sollte passen. Meine Vermutung ist, dass ich mit Signallaufzeiten innerhalb des FPGA zu kämpfen habe. Irgendwie ist da ein Effekt, den die Simulation nicht richtig erfasst. Was dann einen Unterschied zwischen Modell und Wirklichkeit bedeutet und in dem Fall, dass es fehl schlägt. Gibt es ein File, wo ich reinschauen kann, das mir Infos für die Signallaufzeiten bereit stellt? Wo fängt man an zu debuggen, wenn man Glitches oder Synchronisationsprobleme hat? Grüße, Jens
Du kannst das Zeug im FPGA constrainen damit das eben Timings einhält. Wenn das nicht geschafft wird sagt dir das die Toolchain. Die Timings im FPGA kannst du im Timing Report lesen.
Jens W. schrieb: > Wo fängt man an zu debuggen, wenn man Glitches oder > Synchronisationsprobleme hat? Post-Map bzw. Post-PnR-Simulation (mit den 'realen' Timings) schon gemacht? Von was fuer Zyklendauern/Taktfrequenzen reden wir?
Hallo, ich bin mit 96MHz unterwegs. Das SRAM ist ein Typ mit 10ns, das dachte ich mir, da komme ich mit der Frequenz gut hin ohne extra Waitstates. Wobei die aber drin sind. Momentan habe ich 3 Takte als Waitstate. Ich bin einen Schritt weiter. Ich habe in dem File "SRAM_Operation.vhd", das ich oben angehängt hatte ein bisschen weiter gemacht. Da wird ja noch ein XOR-Verknüpfung mit den Werten gemacht. Und ich dachte, ich kommentiere das mal aus und schaue, ob dann auch noch Schrott ins SRAM geschrieben wird. Und es sieht so aus, dass es dann passt. Das würde bedeuten, dass ich gar kein Timing Problem habe, sondern die Werte irgendwie nicht passen. (Wobei in das dann auch nicht mit der Simulation übereinstimmt, denn da sehe ich die Werte, die ich erwarte). Ich werde morgen die Geschichte mit der XOR Verknüpfung nochmal neu machen und dann schauen, ob es klappt. Könnte von euch nochmal jemand in das File schauen, ob da ein grober Schnitzer drin ist? Ich sehe den Fehler noch nicht. Grüße, Jens
Jens W. schrieb: > Da wird ja noch ein XOR-Verknüpfung mit den Werten gemacht. Und ich > dachte, ich kommentiere das mal aus und schaue, ob dann auch noch > Schrott ins SRAM geschrieben wird. Möglich das ohne das XOR vor dem "internal_SRAM_Data_out" IOB-Flipflops verwendet werden (so kenn ich das von Xilinx), und damit würde das Delay des FPGA internen Routings wegfallen. So meine ich kann man bei z.B..Xilinx kein IOB_Flipflop verwenden: >when modify => > internal_SRAM_Data_out <= to_stdlogicvector(SRAM_Data_in) XOR int_crc; So wäre es eher möglich: >when modify => > internal_SRAM_Data_out <= to_stdlogicvector(SRAM_Data_in); Möglicher auch das die andere Logik dazwischen funkt ... Wie sehen die anderen Schaltungsteile aus?
Hallo zusammen, ich habe die Stelle gefunden. Es ist nicht die XOR Verknüpfung selbst, sondern die Stelle, wo ich den crc-Wert überschreibe mit dem neuen Wert. int_crc <= internal_SRAM_Data_out; Diese Zeile ist es. Wenn ich die raus nehme funktioniert alles bestens. Warum das nicht geht habe ich leider nicht heraus finden können. Aber als Fazit, ein Timing Problem ist es nicht. Entsteht da irgendeine rekursive Schleife oder sowas? Grüße, Jens
Jens W. schrieb: > Entsteht da irgendeine rekursive Schleife oder sowas? Nope, das passt alles. Jens W. schrieb: > Aber als Fazit, ein Timing Problem ist es nicht. Steht das so in den Timing Reports?
Hallo Tobias, im Timing Report sind keine Fehler zu finden. Ich habe extra nochmal alles durchlaufen lassen. Im Summary habe ich 16 Warnungen. Aber die sind klar. Vom µC wird die Adresse eingetaktet und das passiert über Latches. Das wird da bemängelt. Grüße, Jens
Jens W. schrieb: > im Timing Report sind keine Fehler zu finden. Der kann auch nur Fehler finden, wenn Du Timing Constraints vorgegeben hast. Wie sehen die Constraints aus? Gerade wenn Du die Adresse eintaktest, sollte irgendwo ein 'OFFSET IN' auftauchen, sonst kann es passieren, das ein Teil der Adresse erst einen Takt später kommt. Und warum wird die Adresse überhaupt eingetaktet? Relevant sind die Signale /OE, /WE und /CE. Wenn man z.B. auf /WE eine fallende Flanke erkennt, sollte die Adressen stabil sein, sonst hat der µC was falsch gemacht... Duke
Hallo Duke, ah, da könnte ich nochmal schauen. Das ist neu für mich! Constraints vorgegeben habe ich nicht. Wie mache ich das? Oder wo kann ich das nachlesen wie das geht? Die Adresse wird eingetaktet, da das Interface vom µC das so vorgibt. Das ist das EBI (external Bus Interface) von Atmel. Aber das spielt denke ich keine Rolle. Der µC greift auf die Daten zu und das funktioniert auch ohne Probleme. Die andere Seite (vom FPGA aus) ist das Problem. Und wenn ich die Zeile, wo der neue Wert für die XOR Verknüpfung raus nehme, dann funktioniert es. Das ist eine ganz andere Stelle als das Eintakten der Adresse vom µC. Das würde mich echt überraschen, wenn das einen Einfluss hat. Aber das mit den Constraints will ich gerne nochmal ausprobieren. Grüße, Jens
Jens W. schrieb: > Oder wo kann ich das nachlesen wie das geht? Xilinx UG612: https://www.xilinx.com/support/documentation/sw_manuals/xilinx14_7/ug612.pdf > Die Adresse wird eingetaktet, da das Interface vom µC das so vorgibt. > Das ist das EBI (external Bus Interface) von Atmel. Das der EBI einen Takt hat, mag sein. Aber an einem normalen SRAM-Baustein gibt es üblicherweise keinen Takteingang. Der arbeitet asynchron: Adresse anlegen und die Zugriffszeit abwarten, dann kann man sich am Ausgang die Daten abholen, fertig. Duke
Jens W. schrieb: > Das ist das EBI (external Bus Interface) von Atmel. Zeig doch mal den restlichen VHDL-code und sag welcher Atmel und welcher SRAM?
Hallo zusammen, @Duke: Vielen Dank für den User Guide. Damit bin ich erstmal beschäftigt! ;-) @Bernhard: Die Files findest du im Anhang. Es ist ein ATXMega128 und das SRAM ist ein CY7C1049GN30-10ZSXI. Die Top Entity ist das Blockschaltbild von oben. Der Clock hat 96Mhz. Das ist sicher auch noch wichtig. Und alle bekommen den gleichen Clock. Grüße, Jens
Hallo Jens, Deine drei VHDL-Dateien lassen sich erstmal fehlerfrei übersetzten. Hast Du noch eine Testbench dazu, das man die Funktionsweise im Simulator nachvollziehen kann? Duke
Hallo Duke, klar habe ich das. Ich habe mehrere geschrieben. Memory_Interface ist nur für den Zugriff für das SRAM selbst. Memory_Controller ist für alles. Ich hänge auch noch das SRAM_Modell mit an, das ich verwendet habe. Grüße und Danke!
Hallo zusammen, ich habe noch ein paar Screenshots gemacht um das besser zu erklären. Die Simulation läuft richtig. Da habe ich die Werte mit einem Pfeil markiert. Erst was er aus dem Speicher liest und dann das Ergebnis nach dem XOR. Und das Ergebnis ist dann wieder der neue Wert für das nächste XOR und so weiter. Am µC habe ich nur ein kleines Testprogramm. Ich schreibe den Speicher mit Primzahlen voll und lese diese wieder aus. failure_count ist 0, das heißt, er liest genau das aus was er geschrieben hat, nämlich die Primzahlen. Dann legt das FPGA los und dann stehen falsche Werte im Speicher (Screenshot). Und das verstehe ich nicht warum das so ist. Simulation ist richtig. Lesen und Schreiben funktioniert auch. Aber die Werte sind falsch. Und jetzt kommt es: Wenn ich die Zeile 121 heraus nehme int_crc <= internal_SRAM_Data_out; dann funktioniert die Geschichte richtig. Wenn ich die XOR-Operation also immer mit dem initalen Wert 0x5A durchführe. Grüße, Jens
Lass raten, da am Anfang deines Testprogramms in der Hardware machst du einen reset?
1 | if (reset = '1') then |
2 | internal_SRAM_CSn <= '1'; |
3 | internal_SRAM_rw <= '0'; |
4 | internal_SRAM_exe <= '0'; |
5 | int_SRAM_Addr <= 0; |
6 | state_reg <= idle; |
7 | -- **fehlt** da nicht was? z.B int_crc <= INIT_CRC ???
|
8 | end if; |
9 | --(...)
|
10 | when write_ram1 => --write value back |
11 | int_crc <= internal_SRAM_Data_out; |
Da gibt es dann keinen reset-wert, sondern nur den Wert der letzten operation. Oder lässt du den FPGA neu initialisieren, dann wäre dein initalwert da!
1 | signal int_crc : std_logic_vector(DATA_WIDTH-1 downto 0) := INIT_CRC; |
Die Simulation started mit diesem Wert, der FPGA (wenns ein Xilinx wäre) nur nach dem Powerup - mach mal an deine Simulation hintendran noch nen Reset und dann wieder ein paar Operationen und staune...
:
Bearbeitet durch User
Hallo Bernhard, vielen Dank für den Hinweis! Ich habe im Zustand "idle" die Zeile int_crc <= INIT_CRC; ergänzt. Der idle-Zustand wird ja immer dann eingenommen, wenn das Chip Select nicht aktiv ist. Also immer bevor der Prozess angestoßen wird. Die Initialisierung ist somit immer gegeben auf den richtigen Wert. Und das Chip select bekomme ich über die busy-Leitung mit. das passt. Aber, das alleine scheint es nicht zu sein. Das Verhalten ist immer noch nicht so, wie es sein soll. Hat jemand noch eine Idee? Ich komme da an meine Grenze. Ich lade euch für die Simulation noch das file für das Initialisieren des SRAMs mit hoch Grüße, Jens
Hallo Jens, ich kann Deine Simulation noch nicht nachvollziehen, da die Datei mit dem Memory_Interface fehlt:
1 | # vsim -voptargs="+acc" work.memory_interface_memory_interface_sch_tb |
2 | # ** Note: (vsim-3812) Design is being optimized... |
3 | # ** Error (suppressible): Memory_Interface_tb.vhd(112): (vopt-3473) Component instance "/Memory_Interface_Memory_Interface_sch_tb/UUT : Memory_Interface" is not bound. |
4 | # Optimization failed |
5 | # Error loading design |
6 | # Errors: 1, Warnings: 0 |
Dann noch zwei Hinweise: 1. Zwischen Zahl und Zeiteinheit sollte ein Leerzeichen stehen. Z.B. so:
1 | wait for 50 ns; |
2. Es ist für die eigene Übersicht sehr hilfreich, wenn die Entity und der Dateiname identisch sind. Duke P.S.: Die Simulation für den mem_controller läuft fehlerfrei durch.
Hallo zusammen, vielen Dank euch allen! Ich bin auch einen Schritt weiter. Mittlerweile läuft der RAM-Test fehlerfrei durch. Ich hatte in der Datei Memory_Controller noch die fehlenden States ergänzt. Da wurde ja nur unterschieden, wenn der µC oder das FPGA das CS aktiviert. Wenn beide versuchen darauf zuzugreifen wird das error-Flag gesetzt. Was nicht schön war, war, wenn beide nichts machen. Das habe ich alles in eine große if-elsif-else Verzweigung eingebaut und dann klappte alles. Warum das aber nicht als Warnung angezeigt wurde kann ich nicht sagen. Dafür bin ich noch zu neu in der Geschichte drin. Jetzt hoffe ich nur, dass nicht später, wenn ich das im eigentlichen Design verwenden will, wieder der Fehler auftritt. Alle Fehler, die man nicht verstanden hat, kommen wieder. Das ist leider meine Erkenntnis... Aber das wird sich heraus stellen. @Duke: Zur Vollständigkeit lade ich dir noch das Memory_Interface mit hoch. Viele Grüße, Jens
Jens W. schrieb: > Alle Fehler, die man nicht verstanden hat, kommen wieder. Das ist leider > meine Erkenntnis... Ja, das kann ich bestätigen. Momentan suche ich in zehn Jahre alten Code einen Fehler, der im realen System nur ca. einmal pro Stunde auftritt. Und auch nur dann, wenn es signifikanten Datenverkehr auf dem Netzwerk gibt... Duke
Hallo Duke, oh Gott! Der worst-case! Vermutlich trommelt der Kunde noch im Hintergrund, warum das so lange dauert. Kann ja nur ne Kleinigkeit sein, wenn der Fehler so selten auftritt. Da wünsche ich dir viel Erfolg! Grüße, Jens
Hallo zusammen, kleines Update: Ich habe nun auch den letzten Fehler noch gefunden. Der lag am µC und nicht am FPGA. Ich hatte eine Funktion drin, die einfach mal 100 Bytes in ein dump_array schreibt. Und der Speicherzugriff erfolgt mit einem Bank Select Signal, da der µC im SRAM-Mode nicht den gesamten Speicher direkt unterstützt. Da wird also das höchste Addressbit manuell geschaltet. Leider umständlich, aber da hat der XMega noch einen Bug. So, und bei der Testfunktion fürs SRAM wurde das Bank Select richtig bedient, bei der Funktion memory_dump() aber nicht. Der hat also für die Visualisierung mitten rein gegriffen und nicht an den Anfang. Die Zeile ist ergänzt und nun funktioniert alles wie erwartet und auch simuliert. Vielen Dank euch alles für die wertvollen Tipps! Grüße, Jens
Jens W. schrieb: > und nun funktioniert alles wie erwartet und auch > simuliert. Prima. Und Danke für die Rückmeldung!
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.