Hallo, Ich habe ein Design in Quartus gemacht (streng synchron aufgebaut, ~10000 LEs), welches leider manchmal nach dem Compilen korrekt funktioniert und manchmal nicht, was mich auf Timingprobleme schliessen lässt. Laut Timing analyzer müsste aber alles OK sein. Ich habe auch alle Clocks mit 'create_clock' und 'create_generated_clock' definiert. Weiss jemand welche zusätzlichen Constraints noch hilfreich sein könnten?
> streng synchron aufgebaut
Sieh mal deine Resets an.
Sind die asynchron?
Ist da evtl. sogar Kombinatorik drin?
Meine state machines, FIFOs etc. haben zwar asynchrone resets, aber das Signal wird vorher gelatcht, also sollten glitches ausgeschlossen sein. Tja...
Ein wenig mehr Infos wären schon hilfreich, z.B. welcher Art der Fehler ist, ob er bei einem einzigen Build mal auftritt und mal nicht, oder ob es erst nach einer neuen Synthese wieder geht. Zu den Constraints muss noch gesagt werden, dass neben den Clocks auch IOs constrained werden sollten - bei SOPC-Komponenten wie PCI oder DDR-Speicher wird das halbwegs automatisch per Skript gemacht.
> Ich habe ein Design in Quartus gemacht (streng synchron aufgebaut, > ...alle Clocks mit 'create_clock' und 'create_generated_clock' definiert. Wie passt das zusammen? Hast Du nun mehrere Clocks, dann muss das Design als asynchron behandelt werden, oder nicht?
Also ob es funktioniert scheint reine glückssache zu sein und hängt von minimalen Änderungen ab (z.B. hinzufügen eines monitoring Pins). Ausschlag gebend scheint mir zu sein, dass das Zeug neu gefittet wird... Was die IOs angeht, kann ich das mit dem Oszilloskop verifizieren. Ein Beispiel eines sporadisch auftretenden Problems: Ich weiss z.B. dass meien Ethernet-Schnittstelle funktioniert, da 1 mal pro Sekunde ein Watchdog-Packet übermittelt wird und das Paket korrekt ankommt. Wenn ich nun per Befehl eine Funktion im Design aktiviere, die Daten eines ADCs zum PC schicken soll kriege ich zum Beispiel nur Nullen en masse und das Paket wird falsch "verpackt", d.h. die Datenübertragung ist fehlerhaft, weil ein datenbyte als Paketgrösse interpretiert wird. Das könnte z.B. heissen dass die Paketgrösse am anfang des Pakets falsch geschrieben wird, oder dass das Paket zu lang oder zu kurz ist. Irgendwie ist das Problem logisch nicht erklärbar, oder ich bin zu blöd. Hier mal ein Ausschnitt aus dem Code, der ein Paket macht und vom einen FIFO in den anderen schaufelt. Man muss dazu sagen, dass das Ziel-FIFO einen 16 Bit Eingang hat und einen 8 Bit Ausgang:
1 | -- Get scope data |
2 | |
3 | when s_get_scope_data0 => |
4 | if scope_fifo_usedw[] >= 16 and w5100_tx_fifo_free_space[] >= 19 then |
5 | state = s_get_scope_data1; |
6 | else |
7 | state = s_get_meas_data0; |
8 | end if; |
9 | |
10 | when s_get_scope_data1 => |
11 | -- Write packet size |
12 | w5100_tx_fifo_din[] = 36; |
13 | w5100_tx_fifo_write = vcc; |
14 | |
15 | state = s_get_scope_data2; |
16 | |
17 | when s_get_scope_data2 => |
18 | -- Write packet type |
19 | w5100_tx_fifo_din[] = DATA_SCOPE; |
20 | w5100_tx_fifo_write = vcc; |
21 | |
22 | state = s_get_scope_data3; |
23 | |
24 | when s_get_scope_data3 => |
25 | -- Write packet flags |
26 | if scope_packet_counter[].q == 0 then |
27 | w5100_tx_fifo_din[] = PACKET_FLAG_IS_FIRST; |
28 | scope_packet_counter[].d = scope_packet_counter[].q + 1; |
29 | elsif scope_packet_counter[].q == 15 then |
30 | w5100_tx_fifo_din[] = PACKET_FLAG_IS_LAST; |
31 | scope_packet_counter[].d = 0; |
32 | else |
33 | w5100_tx_fifo_din[] = 0; |
34 | scope_packet_counter[].d = scope_packet_counter[].q + 1; |
35 | end if; |
36 | |
37 | scope_packet_counter[].ena = vcc; |
38 | w5100_tx_fifo_write = vcc; |
39 | |
40 | reg_a[].d = 16; |
41 | reg_a[].ena = vcc; |
42 | |
43 | state = s_get_scope_data4; |
44 | |
45 | when s_get_scope_data4 => |
46 | if reg_a[].q != 0 then |
47 | -- Write curve point |
48 | scope_fifo_read = vcc; |
49 | w5100_tx_fifo_din[] = scope_fifo_dout[]; |
50 | w5100_tx_fifo_write = vcc; |
51 | |
52 | reg_a[].d = reg_a[].q - 1; |
53 | reg_a[].ena = vcc; |
54 | |
55 | state = s_get_scope_data4; |
56 | else |
57 | state = s_get_scope_data5; |
58 | end if; |
59 | |
60 | when s_get_scope_data5 => |
61 | state = s_get_scope_data6; |
62 | |
63 | when s_get_scope_data6 => |
64 | state = s_get_scope_data7; |
65 | |
66 | when s_get_scope_data7 => |
67 | state = s_get_scope_data0; |
>> Ich habe ein Design in Quartus gemacht (streng synchron aufgebaut, >> ...alle Clocks mit 'create_clock' und 'create_generated_clock' definiert. >Wie passt das zusammen? >Hast Du nun mehrere Clocks, dann muss das Design als asynchron behandelt >werden, oder nicht? Die anderen Clocks werden per Divider aus dem master clock generiert.
Also ist das Design asynchron... Hast Du die Taktdomänen-Übergänge abgesichert?
>Also ist das Design asynchron... Hast Du die Taktdomänen-Übergänge >abgesichert? Wo nötig setze ich DCFIFOs ein... aber das Design ist trotzdem synchron.
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.