Moin, ich komme bei den timing constraints einfach nicht weiter. Ich habe das auch noch nicht so richtig verstanden und verstehe aber auch nicht die Xilinx Dokumentation. Wenn man weiss worum es geht ist die Doku leicht - wenn man es nicht versteht finde ich es schon sehr schwierig zu verstehen. Zum Problem: Im Timing_Summary sind immer 600 Eintrge bei "Check Timing" 400 bei "No Clock" und 200 bei "unconstrained internal endpoint". Ich besitze 2 Clocks die von ausserhalb kommen. Eine SPI_CLK (8MHz) und eine Clock (125MHz). Die SPI_CLK geht über einen I/O zu einem IBUFG und ist von dort aus als Signal SCLK vorhanden. Wobei ich vor dem IBUFG -create_clock verwende und nach IBUFG create_generated_clock. Habe ich das soweit richtig verstanden ? Die "System" Clock kommt als Differential Clock vom Generator und geht auf die IOs CLKIN_P und CLKIN_N. Die IOs sind an einem IBUFGDS "angeschlossen" welcher aus dem Diff Signal die Clock FPGA_CLK_125 macht. Dieses Signal geht an einen MMCM und ich erstelle daraus die Clock FPGA_CLK_100 welche ich als CLocksignal für alle meine Entitys benutze. create_clock -period 8.000 -name FPGA_CLK_125_DS -waveform {0.000 4.000} [get_ports CLKIN_P] create_clock -period 125.000 -name SPI_CLK -waveform {0.000 62.500} [get_ports SPI_CLK] create_generated_clock -name SCLK -source [get_ports SPI_CLK] -multiply_by 1 -add -master_clock SPI_CLK [get_pins CON_IBUFG/O] create_generated_clock -name FPGA_CLK_125 -source [get_ports CLKIN_P] -multiply_by 1 -add -master_clock FPGA_CLK_125_DS [get_pins CON_IBUFGDS/O] create_generated_clock -name FPGA_CLK_100 -source [get_pins MMCME2_BASE_inst/CLKIN1] -multiply_by 1 -add -master_clock FPGA_CLK_125 [get_pins MMCME2_BASE_inst/CLKOUT0] Das sind derzeit alle Clocks in meiner Constraint File. Lasse ich die gernerated Clocks weg sagt er "timing met" aber 600 "Check Timing" Einträge. mit den Einträgen sagt Vivado "timing not met" und weiterhin 600 Einträge. Ich verzweifel.Ich habe sehr bald Abgabe meiner Arbeit und komme dort einfach nicht weiter. Daraus resultiert auch das die Post Synthese Simulation nicht die Werte wie die Behav Simulation bringt. Hoffnungsvoll, Björn
Björn R. schrieb: > Wenn man weiss worum es geht ist die Doku leicht - wenn man es nicht > versteht finde ich es schon sehr schwierig zu verstehen. Damit bist Du nicht allein... > Ich besitze 2 Clocks die von ausserhalb kommen. Eine SPI_CLK (8MHz) und > eine Clock (125MHz). Da geht es schon los. Sind die Takte unabhängig voneinander? Sprich: kommen die letzendlich aus verschiedenen Taktquellen oder sind sie vom selben Quartz abgeleitet. Wenn es verschiedene Taktquellen sind, mußt Du die Signale beachten, die von einer Taktdomäne gespeist werden und in der anderen genutzt werden. Das nennt sich dann 'clock domain crossing' und braucht besondere Beachtung. Duke
Duke Scarring schrieb: >> Ich besitze 2 Clocks die von ausserhalb kommen. Eine SPI_CLK (8MHz) und >> eine Clock (125MHz). > Da geht es schon los. Sind die Takte unabhängig voneinander? > Sprich: kommen die letzendlich aus verschiedenen Taktquellen oder sind > sie vom selben Quartz abgeleitet. > > Wenn es verschiedene Taktquellen sind, mußt Du die Signale beachten, die > von einer Taktdomäne gespeist werden und in der anderen genutzt werden. > Das nennt sich dann 'clock domain crossing' und braucht besondere > Beachtung. Ich denke einen Anfang der Probleme haben wir schonmal gefunden. Die SPI_CLK kommt von einem Raspberry , die Clock für den FPGA wird mit auf dem Board vom FPGA (ARTIX 7) erzeugt, also ja die Erzeugung geschieht nicht von derselben Taktquelle. Ich habe einen Vektor SPI_DATA welcher mit jedem Takt von SPI_CLK den Wert von der MOSI-Leitung liest und diesen "speichert". Das passiert SPI-Üblich während Chip Select = 0 ist. Wenn CS nicht 0 ist werden Abschnitte von SPI_DATA anderen Vektoren zugewiesen welche folglich mit anderen Entitys welche die FPGA_CLK_100 nutzen verbunden sind. Nur eine Clock Group zu erstellen hat leider keine Besserung gebracht. Was muss dort besonders beachtet werden ?
Björn R. schrieb: > Ich denke einen Anfang der Probleme haben wir schonmal gefunden. Du kannst 2 unabhängige Takte nicht zueinander constrainen. Für diesen Taktdomänenübergang kannst du nicht das FPGA verantwortlich machen, den muss du selber in die Hand nehmen. Du musst die Toolchain anweisen, alle Pfade zwischen diesen beiden Taktdomänen zu ignorieren, weil sie eh' nicht automatisiert umgesetzt werden können, sondern einen Fifo oder ein Handshakeverfahren brauchen... http://www.xilinx.com/support/documentation/sw_manuals/xilinx11/pce_p_exceptions_ignore_paths.htm
Macht es nicht auch bei solch einer lahmen Clock wie der 8Mhz SPI Clock Sinn dieses als Signal einzusynconisieren? Also etwa:
1 | |
2 | SPIsync : process (125MhzClock) |
3 | Begin
|
4 | If risingedge(125MhzClock) then |
5 | SPIclock_old = SPiClock |
6 | If ( (SPIclock_old = '0') and (SPIClock = '1')) then |
7 | SPIclock_en =' 1' |
8 | else SPIclock_en = '0' |
9 | End if |
10 | End if |
11 | End process |
Gerald M. schrieb: > Also etwa Das ist noch nicht einsynchronisiert, der Eingang wird ohne Zwischenspeicher direkt abgefragt! Da fehlt noch unbedingt 1 Flipflop. Aber ich würde es so machen und damit jedem Gelecke mit 2 Takten aus dem Weg gehen. Denn schließlich ist letztlich der SS auch asynchron und muss für die Datenübernahme einsynchronisiert werden.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Aber ich würde es so machen und damit jedem Gelecke mit 2 Takten aus > dem Weg gehen. Denn schließlich ist letztlich der SS auch asynchron und > muss für die Datenübernahme einsynchronisiert werden. Ich würde es auch (fast) so machen. Im Prinzip kann man ein normales Shift-Register mit dem SPI-Clock beschreiben:
1 | process
|
2 | begin
|
3 | wait until rising_edge( SPI_CLK); |
4 | shift_reg <= shift_reg( 6 downto 0) & SPI_DI; |
5 | end process; |
Für das Einlesen der Daten nimmt man die Flanke vom /SS. Und genau nur diese muss einsynchronisiert werden (2 FF).
1 | signal ss_reg : std_ulogic_vector( 2 downto 0); -- = 3 FF |
2 | -- das dritte ist für die Flankenabfrage
|
3 | ..
|
4 | process
|
5 | begin
|
6 | wait until rising_edge( CLK); |
7 | ss_reg <= ss_reg( 1 downto 0) & SPI_SS; |
8 | end process; |
Die anderen Signale (und der Inhalt vom Schieberegister) sind zu diesem Zeitpunkt stabil und damit unkritisch.
1 | process
|
2 | begin
|
3 | wait until rising_edge( CLK); |
4 | -- Flankenabfrage
|
5 | if ss_reg( 2 dowtnto 1) = "01" then |
6 | spi_data <= shift_reg; |
7 | end if; |
8 | end process; |
Duke
Okey ich glaube so langsam kommt die Idee. Statt zwei Taktdomänen zu verwenden soll ich versuchen nur eine / die FPGA_CLK_100 als Clock zu verwenden und damit alles zu beschreiben. shift_reg <= shift_reg( 6 downto 0) & SPI_DI; Ist hierbei nicht immer die 8te Stelle SPI_DI ? wait until rising_edge( CLK); -- Flankenabfrage if ss_reg( 2 dowtnto 1) = "01" then spi_data <= shift_reg; Passier hierbei nicht das gleiche wie bei meiner aktuellen Implementierung ? Weil shift_reg ist doch abhängig von der SPI_CLK oder irre ich mich da ? Danke schonmal für eure Hilfe =) LG Björn
In Björn R. schrieb: > Passier hierbei nicht das gleiche wie bei meiner aktuellen > Implementierung ? Naja, die Namen in deinem Beispiel sind nicht ganz konsistent. Wenn du nur 1 Taktdomäne haben willst, dann musst du die externen Signale über 2 Flipflops einsynchronisieren. Und dann für den Takt eine Flankenerkennung implementieren. Und abhängig von der jeweiligen Flanke dann die Daten einlesen oder den Ausgang aktualisieren. Oder du machst es wie von Duke vorgeschlagen: das eigentliche SPI Schieberegister mit dem Schwerpunkt Takten und die Datenübernahme dann über den einsynchronisierten Slaveselect.
Björn R. schrieb: > shift_reg <= shift_reg( 6 downto 0) & SPI_DI; > > Ist hierbei nicht immer die 8te Stelle SPI_DI ? Nein, weil mit 'wait until rising_edge( CLK);' ein Register (=DAS Schieberegister) draus gemacht wurde. Ohne Prozess und ohne 'wait' hättest Du eine kombinatorische Schleife. Duke
So, habe noch viel gelesen und ich muss mich recht herzlich bei Euch Allen bedanken. Ihr habt mir echt geholfen =), vor allem in manchen Dingen "synchron" zu denken. Die SPI funktioniert nun und ich habe viele Teile meines Codes nochmal überarbeitet. Ich verstehe zwar immernoch nicht die timing Constraints aber Vivado gibt schon sehr viel weniger Warnmeldungen aus. Weil die Erzeugung des Bitstreams klappt werde ich das einfach mal auf den FPGA laden und mit einem Logic Analyzer schauen was passiert. LG Björn
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.