Hallo VHDL-Gemeinde,
schon wieder habe ich - wer hätte das gedacht - ein Problem. Ein
selbstgebastelter IP-Core, der in der Simulation einwandfrei
funktioniert, scheint sich auf dem FPGA immer wieder aufzuhängen.
Zentraler Teil ist eine FSM. Die variable r wird durch Triggerimpulse
gezählt und eine weitere Zählvariable gemäß einem Bitmuster mitgezählt.
Nach einigen Triggerimpulsen bleibt alles stehen, hier mal der Code:
Ich hab ich anderen Beiträgen was über "Eintakten" gelesen. Kann hier
der Fehler liegen?
Der daranhängende MicroBlaze bleibt nicht hängen, nur der IPCore.
Wie gesagt, stelle ich das Szenario im Simulator nach, dann funktioniert
alles. Allerdings ist das natürlich das VHDL Modell ohne
Schnittstellenanbindung, aber daran kanns ja eigentlich nicht liegen.
Wäre für jeden Tipp sehr dankbar. Vielleicht hat schon mal jemand
ähnliche Erfahrungen gemacht.
Vielen Dank.
Gruß
Flo
Du hast 3 Taktdomänen:
> rising_edge(clk_c)> rising_edge(ETrigger_C)> rising_edge(SWDTTrigger_C)
Und du fragst in der ersten Domäne (clk_c) Signale ab, die von den
beiden anderen asynchron gesetzt werden (EFlag und SWDTFlag). Das wird
garantiert Probleme geben (Hintergrund: Laufzeiten im FPGA, siehe
http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren)
> EFlag> SWDTFlag
Sieh dir mal an, wie man einen Spike in einen synchronen Puls umwandelt:
http://www.lothar-miller.de/s9y/categories/19-SpikePuls> Wie gesagt, stelle ich das Szenario im Simulator nach,> dann funktioniert alles.
Solche Fehler findest du in der Verhaltenssimulation niemals, in einer
Post-Route-Simulation evtl. zufällig. Du mußt diese Fehler per Design
ausschliessen (= Lernen, Üben, Wissen)... :-o
In welchem Zustand, habe ich noch nicht rausgefunden. Dazu muss ich erst
wohl das Zustandssignal nach außen führen ?!
Allerdings konnte ich feststellen, dass sich das VHDL Modul im
stand-alone Betrieb, also nicht als IP-Core + Microblaze, nicht
aufhängt.
Bin ein wenig ratlos.
Schönen Pfingstmontag an alle Leser.
Gruß
Flo
Bevor ich das probier, noch eine Frage: Mal angenommen, die FSM bleibt
im Zustand Calc_dN hängen bzw. wackelt zwischen Cald_dN und WaitOneClk.
Könnte da irgendwas mit dem Handshake mit der Divisions-Komponente nicht
stimmen? Weise ich da vielleicht Signale falsch zu, sodass Synthese und
Simulation sich unterscheiden?
Hat z.B. eine Bedingung wie
in der ein Signal abgefragt und dann davon abhängig gesetzt wird
irgendwelche für den Anfänger unvorhergesehene Folgen? Wird z.B.
startDIV gleichzeitig gesetzt und abgefragt und führt daher zu irgendwas
"Verrücktem"?
Vielen Dank für die Hilfe.
Gruß
Flo
> Wird z.B. startDIV gleichzeitig gesetzt und abgefragt ...
... ist das eine ganz übliche Vorgehensweise. Absolut jede State-Machine
arbeitet so.
1
IfbusyDIV='0'andstartDIV='0'then
2
startDIV<='1';
3
elsifbusyDIV='0'andstartDIV='1'then
4
startDIV<='0';
Das startDIV ist in der brutalen Realität ein Flipflop, das am Eingang
eine Kombinatorik hat, mit der der Zustand berechnet wird, der mit dem
nächsten Takt übernommen wird. Und danach ist dieses startDIV mindestens
einen Takt lang stabil.
Dein Problem liegt irgendwo anders...
Also, zunächst habe ich noch ein paar kleine Änderungen vorgenommen, die
mit dem Problem nichts zu tun haben. Der Vollständigkeit halber hier der
Code:
Florian Rems schrieb:> when Calc_dN =>> ------------------------------------------------------> if dir(0)=dir(1) then> If busyDIV='0' and startDIV='0' then
...
> elsif busyDIV='0' and startDIV='1' then
...
> else> s <= Calc_dN;> end if;> else
...
> end if;
Damit s = calc_dN bleibt, müssen folgende Bedingungen erfüllt sein:
dir(0)=dir(1) und busyDIV=1. Und genau das ist offenbar der Fall...
Kannst Du Dir dir(0), dir(1), busyDIV und startDIV auch noch mit
ausgeben lassen?
Rick
Danke für den Hinweis. Seh ich auch so. Der "Divider" ist auch eine FSM,
mal sehen, ob die vielleicht auch hängen bleibt, eben mit busyDIV='1'.
Was mich allerdings irritiert ist, dass mein Konstrukt stand-alone auf
dem FPGA NICHT hängen bleibt. In Verbindung mit dem MicroBlaze, wenn der
FPGA also nahezu voll ist, tritt dieses Problem auf. Dann kann es
eigentlich kein systematischer Fehler im Code sein?!
Gruß
Flo
Florian Rems schrieb:> systematischer Fehler
Hmm. Jetzt wo Du es sagst: Wieviele Clocks verwendest Du? Ist da
eventuell ein unsauberes Clock-Domain-Crossing verbaut?
Rick
Also der IP-Core arbeitet mit einem Takt, den hole ich mir direkt vom
Takt des PLB-Buses vom Microblaze. Könnte da vielleicht ein Problem
bestehen?
>Wieviele Clocks verwendest du?
Ich denke, nur eine. Aber woran erkenne ich das?
Was versteht man unter einem Clock-Domain-Crossing?
Danke für die Hilfe.
Gruß
Flo
> Ich denke, nur eine. Aber woran erkenne ich das?
Am 'event oder rising_edge() bzw. falling_edge().
Aber das hatten wir schon im
Beitrag "Re: Custom IP-Core hängt sich auf."> Was versteht man unter einem Clock-Domain-Crossing?
Den Übergang von Signalen von einer Taktdomäne in die andere...
Sitchworte: Eintakten, Synchronisieren, Fifo
Bzgl. Eintakten etc. dürften ja wohl alle "Missetaten" beseitigt sein.
Selbst wenn ich jetzt weiß, dass BusyDIV='1' bleibt, vielleicht weil die
Divisions-FSM hängen bleibt, nutzt mir das auch nix, weil es ja im
stand-alone Betrieb funktioniert. Kann es denn an der Anbindung als
IP-Core liegen? Da werden eigentlich nur den Signalen Register
zugewiesen und umgekehrt.
Frustrierend ...
Gruß
Flo
Noch eine Idee: Sind denn Timing-Probleme denkbar. Der Report im Xilinx
EDK für den IP-Core schreibt:
Clock Information:
------------------
-----------------------------------------------+------------------------
---------------------------------------------------------------+-------+
Clock Signal | Clock buffer(FF name)
| Load |
-----------------------------------------------+------------------------
---------------------------------------------------------------+-------+
SPLB_Clk |
NONE(motor_controller_ip_0/PLBV46_SLAVE_SINGLE_I/I_SLAVE_ATTACHMENT/I_DE
CODER/rnw_s_h)| 886 |
motor_controller_ip_0/USER_LOGIC_I/CON/C/Busy_C|
NONE(motor_controller_ip_0/USER_LOGIC_I/CON/LOG/Mode_LOG_0)
| 3 |
-----------------------------------------------+------------------------
---------------------------------------------------------------+-------+
INFO:Xst:2169 - HDL ADVISOR - Some clock signals were not automatically
buffered by XST with BUFG/BUFR resources. Please use the buffer_type
constraint in order to insert these buffers to the clock signals to help
prevent skew problems.
Asynchronous Control Signals Information:
----------------------------------------
------------------------------------------------------------------------
----------------------------+-------------------------------------------
--------------------+-------+
Control Signal
| Buffer(FF name) | Load
|
------------------------------------------------------------------------
----------------------------+-------------------------------------------
--------------------+-------+
motor_controller_ip_0/USER_LOGIC_I/CON/C/Reset_C(motor_controller_ip_0/U
SER_LOGIC_I/CON/C/Reset_C:Q)|
NONE(motor_controller_ip_0/USER_LOGIC_I/CON/instSWDT/count_21)| 24 |
------------------------------------------------------------------------
----------------------------+-------------------------------------------
--------------------+-------+
Timing Summary:
---------------
Speed Grade: -4
Minimum period: 18.272ns (Maximum Frequency: 54.729MHz)
Minimum input arrival time before clock: 15.577ns
Maximum output required time after clock: 5.833ns
Maximum combinational path delay: No path found
Clock ist 50 MHz. Ist das vielleicht zu knapp? Weiß jemand, wie man
probeweise den Takt verringert?
Vielen Dank für jeglichen Tipp.
Gruß
Flo
> Clock ist 50 MHz. Ist das vielleicht zu knapp?
Nein, das würde reichen.
Aber du hast offenbar doch noch ein paar weitere Takte in deinem Design,
erkennbar (wie gesagt) an 'event oder rising_edge() bzw. falling_edge().
Sieh dir die mal genauer an.
Das sieht komisch aus: motor_controller_ip_0/USER_LOGIC_I/CON/C/Busy_C
Sind da doch ausversehen mehrere Clockdomains drin?!
Mit der Taktfrequenz das passt schon, solange Du keine Timing-Errors
(Timingscore > 0) hast.
Rick
Jetzt sieht das Ganze so aus.
========================================================================
=
TIMING REPORT
NOTE: THESE TIMING NUMBERS ARE ONLY A SYNTHESIS ESTIMATE.
FOR ACCURATE TIMING INFORMATION PLEASE REFER TO THE TRACE REPORT
GENERATED AFTER PLACE-and-ROUTE.
Clock Information:
------------------
-----------------------------------+------------------------------------
---------------------------------------------------+-------+
Clock Signal | Clock buffer(FF name)
| Load |
-----------------------------------+------------------------------------
---------------------------------------------------+-------+
SPLB_Clk |
NONE(motor_controller_ip_0/PLBV46_SLAVE_SINGLE_I/I_SLAVE_ATTACHMENT/I_DE
CODER/rnw_s_h)| 887 |
-----------------------------------+------------------------------------
---------------------------------------------------+-------+
INFO:Xst:2169 - HDL ADVISOR - Some clock signals were not automatically
buffered by XST with BUFG/BUFR resources. Please use the buffer_type
constraint in order to insert these buffers to the clock signals to help
prevent skew problems.
Asynchronous Control Signals Information:
----------------------------------------
------------------------------------------------------------------------
----------------------------+-------------------------------------------
--------------------+-------+
Control Signal
| Buffer(FF name) | Load
|
------------------------------------------------------------------------
----------------------------+-------------------------------------------
--------------------+-------+
motor_controller_ip_0/USER_LOGIC_I/CON/C/Reset_C(motor_controller_ip_0/U
SER_LOGIC_I/CON/C/Reset_C:Q)|
NONE(motor_controller_ip_0/USER_LOGIC_I/CON/instSWDT/count_14)| 24 |
------------------------------------------------------------------------
----------------------------+-------------------------------------------
--------------------+-------+
Timing Summary:
---------------
Speed Grade: -4
Minimum period: 21.721ns (Maximum Frequency: 46.038MHz)
Minimum input arrival time before clock: 16.085ns
Maximum output required time after clock: 4.772ns
Maximum combinational path delay: No path found
Dazu muss ich sagen, dass jetzt zwei der IP-Cores dabei sind, so wie es
am Schluss auch funktionieren soll.
Ist das mit dem Timing immer noch in Ordnung? jetzt hätten wir ja
weniger als 50 Mhz.
Es bleibt leider immer noch hängen, genau wie oben.
Gruß
Flo
Device utilization summary:
---------------------------
Selected Device : 3s500efg320-4
Number of Slices: 5142 out of 4656 110% (*)
Number of Slice Flip Flops: 5037 out of 9312 54%
Number of 4 input LUTs: 7757 out of 9312 83%
Number used as logic: 7206
Number used as Shift registers: 295
Number used as RAMs: 256
Number of IOs: 54
Number of bonded IOBs: 54 out of 232 23%
IOB Flip Flops: 16
Number of BRAMs: 16 out of 20 80%
Number of MULT18X18SIOs: 17 out of 20 85%
Number of GCLKs: 4 out of 24 16%
Number of DCMs: 1 out of 4 25%
WARNING:Xst:1336 - (*) More than 100% of Device resources are used
Wie kann es sein, dass ich den Bitstream trotz (*) auf den FPGA laden
kann?
> Device utilization summary: 110%
Sagt wer?
Die Synthese?
Oder P&R?
> Wie kann es sein, dass ich den Bitstream trotz (*) auf den FPGA laden> kann?
Jetzt muß P&R endlich mal was tun und etwas optimieren...
> Minimum period: 21.721ns (Maximum Frequency: 46.038MHz)
Das ist nach der Synthese...
> Ist das mit dem Timing immer noch in Ordnung?
... da kann bei richtigen constaints schon noch was verbessert werden.
> jetzt hätten wir ja weniger als 50 Mhz.
Also die Frage: du hast den Takt korrekt constrained?
Habe gerade versucht, die Divisionskomponente quasi auszuschalten und
einen festen Wert für dN vorgegeben. Damit tritt das Aufhängen nicht
mehr auf. Es muss also was mit der Divisions-FSM zu tun haben. Das ist
allerdings keine Lösung, denn irgendwie muss ich diese Division
durchführen.
Gruß
Flo
Ich habs geahnt... :-o
Der läuft eigentlich recht gut.
Du solltest dir die Geschichte mit dem Takt nochmal anschauen.
> Ich habe gar nichts constrained :-)
Gib doch mal einen constraint auf den Takt vor.
Folgendes stand tatsächlich im UCF File:
TIMESPEC TS_sys_clk_pin = PERIOD sys_clk_pin 20000 ps;
Das hat das EDK reingeschrieben. Was wäre denn eine sinnvolle Änderung?
Gruß
Flo