Hallo
Ich bin gerade etwas am verzweifeln:
Bei einem kleinen Schulprojekt soll ein RFID Empfänger über VHDL
beschrieben werden. Sollte kein Problem sein.
Nur kommen jetzt die Tücken von VHDL hinzu?
Als Eingang ist ein Manchester-Codiertes Datensignal, welches leider
nicht synchron auf die Referenz ändert (immer etwas verschoben und nicht
konstant zu RDY_CLK).
Jetzt kommt das interessante: Die Simulation klappt ohne Fehler (alles),
dann wird alles richtig synthetisiert und am Schluss läuft alles anders
auf der Hardware, als vorhin die Simulation, die Gedanken und dann die
"Analyse" des Codes.
Z.B. Wird ein Paket richtig empfangen (also die 9 '1' des Headers werden
gelesen) doch dann springt er mir irgendwie in das Fehlerhandlich, indem
ich die Abtastzeit um eine halbe Periode verschiebe. Und dies macht es
schön regelmässig. Eigentlich sollte maximal nach einem Wechsel der
Header korrekt gelesen werden können.
Man ich kann echt kein VHDL. In C hätte ich das in etwa 4h ohne Probleme
hingekriegt, aber hier bin ich nun schon eine Woche dran, und es läuft
immer noch nicht. Ausserdem kann man das zeugs ja nichtmal richtig
debugen (irgendwie eine Art Breakpoint setzen).
Könnte mir vieleicht jemand mal etwas helfen (und auch Verbesserungen
anbringen)? Wie gesagt, Programmieren ist kein Problem aber VHDL?! Eine
Welt für sich.
Gruss
Patrick
Patrick B. schrieb:> Man ich kann echt kein VHDL. In C hätte ich das in etwa 4h ohne Probleme> hingekriegt,
Das sieht man klar&deutlich: ein Softie, der Hardware machen muss. Schon
die überaus exzessive Verwendung bon Variablen...
Wenn ich mir die daraus entstehende Monsterlogik so überlege, dann frage
ich dich: welche Taktfrequenz hast du? Und: hast du das der Toolchain
auch gesagt?
Mhm, also laufen soll das ganze auf einem Spartan 3e mit 50MHz Takt, der
aber ev noch auf 1MHz heruntergeteilt wird. Das RDY_CLK Signal hat
125kHz wobei das Datensignal 64 Clockzyklen braucht (also noch
langsamer).
Verbesserungsvorschlag? Wie soll ich das den sonst
aufbauen/struckturieren?
Patrick B. schrieb:> laufen soll das ganze auf einem Spartan 3e mit 50MHz Takt
Weiß die Toolchain das? Welche Taktfrequenz gibt der Report aus? Hast du
entsprechende Constraints angegeben?
Dir muss klar werden, dass die Parity-Berechnung in der Hardware immer
da ist und immer gemacht wird. Aber nur im Zustand parity_check wird
das Ergebnis der Berechnung weiterverwendet.
> Verbesserungsvorschlag?
Einen Teil der Parity-Berechnung kannst du sicher schon bei der
Übertragung jedes einzelnen Bits berechnen:
Denn dort sind die Bits ja noch alle hübsch seriell. Später musst du sie
erst wieder über viel Logik (das wird aus deinen for-Schleifen
gemacht!!) miteinander ver-xor-en...
Muss der komplette Check unbedingt in 1 Takt ablaufen? Wenn nicht, dann
könntest du den Check auch über einen Automaten Schritt für Schritt
ablaufen lassen.
> Debug-Signal
Dein Debug-Signal hat übrigens einen Takt Latency, weil du es im
getakteten Prozess zuweist. Die Debugausgabe könntest du auch so machen,
das spart ein paar Zeilen:
http://www.lothar-miller.de/s9y/archives/49-FSM-debuggen.html> delay_cnt_max, edge_cnt, bit_cnt
Hier ist die Zählrichtung ungünstig: besser du lädst die Zähler mit 0
und zählst hoch. Denn dann kann zum "Laden" (=Rücksetzen) der
Reset-Eingang der Flipflops genommen werden. Zum Auswerten des
Zählerendes braucht man sowieso Logik.
> Nibbel
Sagen wir mal lieber Nibble, das ist weniger verfänglich...
> process(clk2, reset, state, rdy_clk_sync, demod_sync, .....
Dieser Prozess ist lediglich auf den clk2 sensitiv.
> data_shift_reg(63 downto 0) <= (others => '0');
Das ginge kürzer so: data_shift_reg <= (others => '0');
Lothar Miller schrieb:> Patrick B. schrieb:>> laufen soll das ganze auf einem Spartan 3e mit 50MHz Takt> Weiß die Toolchain das? Welche Taktfrequenz gibt der Report aus? Hast du> entsprechende Constraints angegeben?
Ich benutze die Xilinx ISE und habe beim Projekt schon das Spartan 3e
Starterkit angegeben. Eine Taktfrequenz wäre mir bis jetzt noch nicht
begegnet.
>> Verbesserungsvorschlag?> Einen Teil der Parity-Berechnung kannst du sicher schon bei der> Übertragung jedes einzelnen Bits berechnen:>
1
>whensave=>
2
>bit_cnt<=bit_cnt+1;--
3
>GesampelteBits
4
>data_shift_reg<=data_shift_reg(62downto0)&
5
>demod_sync(0);
6
>
> Denn dort sind die Bits ja noch alle hübsch seriell. Später musst du sie> erst wieder über viel Logik (das wird aus deinen for-Schleifen> gemacht!!) miteinander ver-xor-en...
Das Problem ist hier, dass es eine Kreuzparität ist:
9-Bit Header (alle 1),
4-Bit Daten + 1 Parität, 4-Bit Daten + 1 Parität .... und am Schluss 4
Bit Parität und 1 Stopbit.
Also müsste ich sowieso irgendwas wie ein Zähler haben, der mir die Bits
zählt und dann die Pakete mit der Parität verlgeicht.
> Muss der komplette Check unbedingt in 1 Takt ablaufen? Wenn nicht, dann> könntest du den Check auch über einen Automaten Schritt für Schritt> ablaufen lassen.
Nein, überhaupt nicht. Mir ist nur gerade kein anderer Lösungsansatz in
den Sinn gekommen.
Werde dann das Ganze mal etwas umbauen.
Patrick B. schrieb:> Werde dann das Ganze mal etwas umbauen.
Gib der Toolchain zuerst mal ein Clock-Constraint vor. Vielleicht hilft
das schon. Aber auf jeden Fall bekommst du einen Fehler, wenn sie die
50MHz nicht schafft.
Nur mal so nebenbei - aber keineswegs OT - wann immer bei mir die
Simulation sich korrekt verhielt, die Implementation aber nicht wie
erwartet, hat sich der streng prüfende Blick in das Constraint-File
gelohnt.
Nicht zugewiesene Signale (das kann bei per C&P erstellten Dateien
schnell mal passieren) führen in der ISE Toolchain dazu, das der PAR
Prozess sie auf irgendein freies IOB legt, was erst der Blick in den
FPGA Editor enthüllt - sofern man ihn denn öffnet. Damit lässt sich viel
Spaß haben - mein Klassiker war ein vergessenes Reset Signal.
Gruß,
Burkhard
Burkhard K. schrieb:> das der PAR> Prozess sie auf irgendein freies IOB legt, was erst der Blick in den> FPGA Editor enthüllt
Wahlweise gibt es einen .pad-Report. Der dürfte in diesem Fall
übersichtlicher sein, als der FPGA-Editor.
Duke
Lothar Miller schrieb:> Gib der Toolchain zuerst mal ein Clock-Constraint vor. Vielleicht hilft> das schon. Aber auf jeden Fall bekommst du einen Fehler, wenn sie die> 50MHz nicht schafft.
Habs mal etwas umgebaut: den ganzen Teil mit der Kreuzparität
auskommentiert und die erwähnten Vorschläge umgesetzt. Ebenso im
ucf-File das Clockconstraint definiert (gemäss IG230)
1
NET "CLK" LOC = "C9" | IOSTANDARD = LVCMOS33;
2
NET "CLK" PERIOD = 20.0ns HIGH 40%;
Ebenso der bit_cnt auskommentiert. Dort sollte nur der Sampelzeitpunkt
nach 2 Misserfolgen geändert.
Hat zwar zusätzliches Fehlverhalten generiert (da keine Prüfung mehr),
aber die Synthese läuft immer noch ohne Wahrnung durch.
Werde morgen mal mit dem LA weitersuchen.
Patrick B. schrieb:> NET "CLK" LOC = "C9" | IOSTANDARD = LVCMOS33;> NET "CLK" PERIOD = 20.0ns HIGH 40%;
In deinem Beispielcode hiess dein Taktnetz aber "clk2" und nicht "clk"
Also:
Habe jetzt das ganze etwas umgebaut und noch "verschönert". Das
Fehlverhalten konnte ich auf den letzten State eingenzen: Wenn ich im
update_output in wait_rdy_clk_edges mit 64 Takten wechsle gehts.
Wieso auch immer, denn ich verarbeite alles vor der neuen Flanke, die
ich im idle auswerte. Dann wieder mit 16 Takten Wartezeit neu
synchronisiere, und beim Wechsel zu save sind identische Taktzyklen von
rdy_clk vergangen.
Mhm, muss da wohl noch etwas genauer dahinter.
alex schrieb:> Wie viele Takte hat dein Design und wie sehen die Taktdomänenübergänge> aus?
Öhm, ich habe vieleich erst 40h VHDL "Erfahrungen". Was genau meinst du
damit und wie kann man das anschauen/herausfindig machen?
Noch eine generelle Frage (oder 2):
Ich habe öfters gesehen, dass es 1 oder 2-Prozessschreibweisen für eine
Statemachine gibt. Was ist der Vorteil von 2? Ich konnte so überhaupt
nicht arbeiten, da es unüberischtlich ist und man nur aus einem Prozess
in die Signale schreiben kann.
Ist es sinnfoll, Prozesse zu machen, die nur die Flanke eines Signals
auswerten, oder ähnliches? Eine grobe Segmentierung sozusagen.
Danke für eure Geduld.
Gruss
Patrick B. schrieb:> Ich habe öfters gesehen, dass es 1 oder 2-Prozessschreibweisen für eine> Statemachine gibt. Was ist der Vorteil von 2?
Du hast die Kombinatorik und die Speicherelemente getrennt. Du
berechnest explizit im kombinatorischen Prozess den Zustand, der mit der
nächsten Taktflanke übernommen wird.
Ich nehme auch die Ein-Prozess-Schreibweise, weil dort einige Fehler gar
nicht möglich sind:
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html> Ist es sinnfoll, Prozesse zu machen, die nur die Flanke eines Signals> auswerten, oder ähnliches? Eine grobe Segmentierung sozusagen.
Wenn man diese Flanke an vielen Stellen der restlichen Beschreibung
braucht, dann schon. Sonst schreibe gern alles im selben Prozess.