Hallo,
und das nächste Problem. Ich hab zwei Prozesse am laufen, der eine
reagiert auf positive, der andere auf negative Flanken. Nun habe ich
öfter den Fall das ein if-Zweig der Prozesse durchlaufen wird aber nicht
alle Signale gesetzt werden.
Da ich jetzt keinen Webspace zur verfügung haben, kann ich die ChipScope
Ergebnisse leider nicht zeigen, versuche aber das Verhalten an einem
Beispiel klar zu machen.
Beispiel: Im "FALLING_TX.." Prozess wird in "if(LAST_SHIFT_VALUE = '0'
and DATA_CLK = '1') then ...." gewechselt, allerdings wird lediglich
"USE_FALLING_VALUE <= '1';" übernommen, "FALLING_VALUE <= SERIAL_IN;"
hingegen wird nicht ausgeführt. Beim nächsten Einstieg in den if-Zweig
wird dann auch FALLING_VALUE richtig gesetzt.
Solch ein Verhalten ist sehr oft vorhanden, allerdings nicht immer. Kann
es sein das es sich nicht verträgt, wenn man Prozesse die auf
unterschiedliche Flanken reagieren, von einander abhängig macht?
(Asynchroner Reset wird noch ersetzt und Vectoren für die
Flankenerkennung eingeführt um es übersichtlicher zu gestalten, daher
bitte auf das wesentliche Bezug nehmen)
guest schrieb:> Solch ein Verhalten ist sehr oft vorhanden, allerdings nicht immer.
Das deutet auf unzureichendes Einsynchronisieren von externen
(asynchronen) Signalen hin...
> Kann es sein das es sich nicht verträgt, wenn man Prozesse die auf> unterschiedliche Flanken reagieren, von einander abhängig macht?
Es ist infach nur unschön. Denn damit verdoppelst du implizit die
Taktfrequenz deines Designs...
> Ich hab zwei Prozesse am laufen, der eine> reagiert auf positive, der andere auf negative Flanken.
Wozu?
Welche Frequenz hat dein SYS_CLK?
Welche der DATA_CLK?
BTW: von diesen ganzen großgeschriebenen Namen kriegt man ja die Krätze
ans Auge... :-/
> Das deutet auf unzureichendes Einsynchronisieren von externen> (asynchronen) Signalen hin...
Ich habe im Modul nur zwei externe (asynchrone Signale), zum einen
DATA_CLK, zum anderen SERIAL_IN. Liegt hier "LAST_SHIFT_VALUE = '0' and
DATA_CLK = '1'" schon ein dickes Problem? Also wenn ich DATA_CLK direkt
nutze ohne es vorher zu speichern um anschließend andere FF's mit dem
Wert zu beschreiben?
> Wozu?> Welche Frequenz hat dein SYS_CLK?> Welche der DATA_CLK?
SYS_CLK = 16 Mhz
DATA_CLK im ungünstigsten Fall 8 Mhz wodurch ich nicht mehr sicher mit
der SYS_CLK die DATA_CLK eintakten kann. Daher möchte ich zu jeder
Flanke (steigend und fallend) den aktuell anliegenden DATA_CLK Wert
abgreifen.
> BTW: von diesen ganzen großgeschriebenen Namen kriegt man ja die Krätze> ans Auge... :-/
Naja das wurde im Reichardt/Schwarz (Du kennst es) so empfohlen.
Allerdings mit der ungefähren Begründung "Es hat sich so
eingebürgert..", wenn ich mich recht erinnere.
guest schrieb:> SYS_CLK = 16 Mhz> DATA_CLK im ungünstigsten Fall 8 Mhz
Wenn du ein FPGA hast: nimm einen DCM und mach aus den 16MHz erst mal
eine höhere Frequenz. Das macht dir das Leben unglaublich
einfach(er)....
> DATA_CLK im ungünstigsten Fall 8 Mhz wodurch ich nicht mehr sicher mit> der SYS_CLK die DATA_CLK eintakten kann.
Da hast du also eine synchrone externe Schnittstelle (evtl. sogar SPI?),
die dir Daten sendet? Dann lass doch den Empfänger asynchron mit lokalem
Takt (Schieberegister mit DATA_CLK) laufen und übernehme dann das
empfangene Wort synchron nach SYS_CLK...
Also es existieren zwei Module die synchron Daten austauschen können.
Der Übertragungstakt wird vom Sendemodul erzeugt, und gibt somit auch
die Mindestfrequenz für den Empfänger vor.
Wie meinst du das mit dem asynchronen Schieberegister? Ich kann ja nicht
einfach " if(rising_edge(DATA_CLK)) then A <= A(X downto Y)& SERIAL_IN
end if; " nutzen?
guest schrieb:> Wie meinst du das mit dem asynchronen Schieberegister? Ich kann ja nicht> einfach " if(rising_edge(DATA_CLK)) then A <= A(X downto Y)& SERIAL_IN> end if; " nutzen?
Doch, genau so würde ich das in deinem Fall machen. Nur brauchst du dann
noch ein Signal, das sagt, wann ein Datenwort fertig übertragen ist
(beim SPI ist das der Chip-Select)...
Du kannst natürlich auch einfach nach x Bit das bis dahin empfangene
Wort in ein Schattenregister/Pufferregister schreiben und das dann über
die Taktdomänengrnze wegschleusen...
Wie willst du denn garantieren, dass das Schieberegister auch syncron
schaltet und nicht aufgrund von ungünstigem Routing einige Speicher das
DATA_CLK Signal eher bekommen als andere? Oder gibt es die Möglichkeit
externe Signale auf ein Taktnetz zu leiten??
guest schrieb:> Wie willst du denn garantieren, dass das Schieberegister auch syncron> schaltet und nicht aufgrund von ungünstigem Routing einige Speicher das> DATA_CLK Signal eher bekommen als andere?
Das Vertrauen in die Technik garantiert mir das... ;-)
> Oder gibt es die Möglichkeit externe Signale auf ein Taktnetz zu leiten??
Abhängig vom FPGA ginge das, aber das war bisher noch nie nötig...
Die paar FFs, die an diesem Takt angeschlossen sind, lassen sich mit den
lokalen Routing-Ressourcen problemlos verdrahten.
> Das Vertrauen in die Technik garantiert mir das... ;-)
Ja das fehlt bei mir noch im großen Maße.. Wie realisiert ISE denn einen
std_logic_vector(7 downto 0) ?? Werden da einfach 8 FF miteinader
verkettet? Wenn das so ist, woher weiß man das die länge der
Signalleitung von DATA_CLK zu den einzelnen FF des Registers gleich lang
sind?
Das es funktioniert kann ich mir vorstellen wenn die FF, räumlich
gesehen, nebeneinander liegen. Aber ob das immer gegeben ist, grade wenn
es voll wird auf dem FPGA... wer kann das sicherstellen??
guest schrieb:> Wie realisiert ISE denn einen std_logic_vector(7 downto 0) ??> Werden da einfach 8 FF miteinader verkettet?
Nur, wenn ein Takt beteiligt ist...
> Wenn das so ist, woher weiß man das die länge der Signalleitung von> DATA_CLK zu den einzelnen FF des Registers gleich lang sind?
Sagen wir das mal so: die Länge ist ausreichend kurz und vor allem
hinreichend gleich... ;-)
Ich habe da mal einen Ringoszillator mit S3 gebastelt, in dem etliche
LUTs hintereinander geschaltet werden:
http://www.lothar-miller.de/s9y/categories/29-Ringoszillator
Dazwischen liegt dann noch die Verdrahtung der LUTs, die ja für den
lokalen Takt auch verwendet werden wird. Und das Zeit zwischen zwei
LUT-Ausgängen ist rechnerisch etwa 1/(50MHz*2*8) = 1/800MHz = 1,25ns.
Davon abgezogen die Laufzeit durch die LUT laut DB 0,6ns ergibt ein
Routig-Delay von 0,6ns.
Probiers einfach aus... ;-)
guest schrieb:> Das es funktioniert kann ich mir vorstellen wenn die FF, räumlich> gesehen, nebeneinander liegen. Aber ob das immer gegeben ist, grade wenn> es voll wird auf dem FPGA... wer kann das sicherstellen??
Du könntest es über (Timing- oder Place-)Constraints fordern...
Ok, technisch mag es funktionieren, sauber ist es aber nicht oder
versteh ich das jetzt falsch?
Es ist ein paar Wochen her (Der erste Kontakt mit Hardware), da hatte
ich den unten stehenden Code gepostet wo ich folgenden Error erhielt:
"The IO component <BTN1> is placed at site <PAD278>. This will not allow
the use of the fast path between the IO and the Clock buffer. If this
sub optimal condition is acceptable for this design, you may use the
CLOCK_DEDICATED_ROUTE constraint in the .ucf file...."
Das Wundermittel war damals "NET "BTN1" CLOCK_DEDICATED_ROUTE = FALSE;"
um trotzdem was ans laufen zu bekommen.
Da gabs dann von dir was auf die Finger, dass man das so nicht macht,
sondern mit clock enable zu lösen hat. Ich seh da quasi keinen
Unterschied zum jetzigen Problem, d.h. ein externes Signal dient als clk
für beliebige FF's.
guest schrieb:> Da gabs dann von dir was auf die Finger, dass man das so nicht macht,> sondern mit clock enable zu lösen hat.
Der Name BTN deutet auf einen (mechanischen) Taster incl. Prellen...
hin. Das ist keine geeignete Taktquelle.
Wenn du aber einen digitalen Takt hast, relativiert sich das Ganze auf
die Frage:
1
If this sub optimal condition is acceptable for this design
Und wenn du sagen kannst: "Ja, das ist mir bewusst und ich kann die
resultierenden Laufzeitverzögerungen akzeptieren", dann spricht nichts
gegen eine solche Lösung.