Hallo, Ich möchte einen Trigger Programmieren. Ich habe mir die Zustandsmaschine so überlegt: (für positive Flanke) Zustand1: wenn gemessenes_level>trigger_level dann nächster_zustand=1 wenn gemessenes_level<trigger_level dann nächster_zustand=2 Zustand2: wenn gemessenes_level<trigger_level dann nächster_zustand=2 wenn gemessenes_level>trigger_level dann nächster_zustand=jetzt_wurde_getriggert_zustand Bevor ich jetzt Anfange das in Code umzusetzen wollte ich mal fragen ob etwas wie: if (level>trigger) begin next_state=1; end else begin next_state=1; end überhaupt synthetisierbar ist. Wenn nein: gibt es andere Möglichkeiten einen trigger zu programmieren? Viele Grüße, Christian
Größer und kleiner sind ohne Probleme synthetisierbar, aber ein größerer Wertebereich (je mehr Bits zur Darstellung) macht das ganze langsamer. Ein Vergleich ist im Prinzip nur eine Subtraktion.
Was bedeutet hierbei langsamer? Taktzyklen? Oder wird der maximale Takt dann durch höhere Signallaufzeiten eingeschränkt? Ich habe 8-Bit Daten. Wie stark wirkt sich das dabei aus? Ich sollte vielleicht mal dabei sagen, dass das ganze in ein XC9572XL CPLD soll. In FPGAs kann man sicher komplexere und andere Dinge synthetisieren als in CPLDs?
Hier gibts nen Artikel, in dem bahauptet wird, dass > und < zu vermeiden sind und statt dessen auf = geprüft werden soll (zumindest bei Zählern). Allerdings wird das Design unter Umständen durch die FSM zur Erzeugung der Ausgangssignale wieder aufgebläht. Zumindest bei dem von mir eingesetzten Cyclone 2 ist > und < kleiner und auch schneller als = mit FSM.
Ab einer gewissen Bitbreite für den Vergleich braucht es im CPLD zusätzliche Makrozellen für "Zwischenergebnisse", da die Logik mit wachsender Bitbreite recht schnell komplex wird. Diese zusätzlichen Makrozellen bewirken eine Verzögerung, die das Ganze dann langsamer macht. Ausserdem können dadurch kurzzeitig falsche Ergebnisse am Ausgang des Vergleichers liegen, was eine getaktete Auswertung unbedingt erforderlich macht. Wie schnell die Logik wächst, kann man feststellen, wenn man den Vergleicher "von Hand" implementiert:
1 | -- 1 Bit grösser:
|
2 | |
3 | Y <= A and not(B); -- pterm 1 |
4 | |
5 | -- 2 Bit grösser:
|
6 | Y <= (A(1) and not(B(1))) -- pterm 1 |
7 | or
|
8 | (not(A(1)) and not(B(1)) and A(0) and not(B(0))) -- pterm 2 |
9 | or
|
10 | (A(1) and B(1) and A(0) and not(B(0))); -- pterm 3 |
11 | |
12 | -- 3 Bit grösser:
|
13 | Y <= (A(2) and not(B(2))) -- pterm 1 |
14 | or
|
15 | (not(A(2)) and not(B(2)) and A(1) and not(B(1))) -- pterm 2 |
16 | or
|
17 | (A(2) and B(2) and A(1) and not(B(1))) -- pterm 3 |
18 | or
|
19 | (not(A(2)) and not(B(2)) and not(A(1)) and not(B(1)) |
20 | and A(0) and not(B(0))) -- pterm 4 |
21 | or
|
22 | (not(A(2)) and not(B(2)) and A(1) and B(1) |
23 | and A(0) and not(B(0))) -- pterm 5 |
24 | or
|
25 | (A(2) and B(2) and not(A(1)) and not(B(1)) |
26 | and A(0) and not(B(0))) -- pterm 6 |
27 | or
|
28 | (A(2) and B(2) and A(1) and B(1) |
29 | and A(0) and not(B(0))) -- pterm 7 |
Man bräuchte also (2^n)-1 Produktterme und das für eine einzige Makrozelle. Gruß Jörg
ok, Probieren geht über Studieren. Ich habe es einfach mal versucht zu implementieren: input [7:0] in1; input [7:0] in2; output out; input clock; reg out; reg next_out; always @ (in1,in2) begin if (in1>in2) begin next_out=1; end else begin next_out=0; end end always @ (posedge clock) begin out<=next_out; end Ergebnis: 3 Makrozellen und 28 P-Terms gebraucht. Soweit in Ordnung, auch wenn es mich irritiert, dass es nicht mit Jörgs Formel übereinstimmt. Was mir allerdings wirklich sorgen macht ist folgendes: Setup to Clock at the Pad (tSU) 18.300 ns. Die Schaltung soll nachher mit 50MHz laufen, also ist das schon hart an der Grenze. Eigentlich wäre es nicht schlimm wenn der Trigger mit ein paar Takten Verzögerung ausgelöst wird (solange die Zahl konstant ist). Sollte ich vielleicht pipelinen? Gibt es eine automatisierte Möglichkeit oder muss ich das dann komplett von Hand implementieren? Oder wäre es klüger das Ganze in ein anderes CPLD auszulagern? Eigentlich wäre noch genug Platz.
Ich habe es jetzt so gelöst: trig_a<=(ein[7:4]>trigger_level[7:4]); trig_b<=(ein[3:0]>trigger_level[3:0]); trig_e<=ein[7:4]==trigger_level[7:4]; trigger<=trig_a|(trig_b && trig_e); Scheint ganz gut zu funktionieren. Für Kritik wäre ich trotzdem dankbar.
Liegt da noch ein Takt zwsichen dem letzten Vergleich? Dann bekommst Du nämlich die erhoffte erhöhte Frequenzreserve.
So wie ich es verstanden habe ja. Ich meine die sequentiellen Zuweisungen werden doch alle gleichzeitig aufgerufen. Dann sollte doch die letzte zuweisung als Eingabe haben was noch von der letzten Zuweisung in den FFs steht. Auf jeden fall sagt die Timing-Analyse so das 109MHz möglich sind. Wenn ich direkt trigger<=(ein[7:0]>trigger_level[7:0]); programmiere meldet die Timing-Analyse was von 42MHz. Oder habe ich was übersehen?
Wenn das in einem getakteten Prozess steht, dann passt das schon so.
Am Besten ist, man stopft erstmal alles in einen getakteten Prozess und lagert dann die offensichtlich kürstesten Kombinatorischen wieder aus. Anders herum kann man alle kombinatorisch schreiben und der Sysmthese die Registeroptimierung überlassen.
Wie mache ich so eine automatische Registeroptimierung? Das muss man sicher irgendwo einstellen? Was muss ich beim schreiben des Codes beachten, damit es nachher auch wirklich funktioniert? Gilt das für CPLD und FPGA oder nur für eins von beiden?
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.