Ich habe ein Projekt, das 34 Makrozellen eines Xilinx Coolrunner II verbraucht. Ich bemerkte, dass ich einen Fehler hatte und verfolgte ihn zu diesem:
assign rlever = RL[0] ? 3'b000 :
RL[1] ? 3'b001 :
RL[2] ? 3'b010 :
RL[3] ? 3'b011 :
RL[4] ? 3'b100 :
RL[5] ? 3'b101 :
RL[6] ? 3'b110 :
3'b111;
assign llever = LL[0] ? 3'b000 :
LL[1] ? 3'b001 :
LL[2] ? 3'b010 :
LL[3] ? 3'b011 :
LL[4] ? 3'b100 :
LL[5] ? 3'b101 :
3'b110 ;
Der Fehler ist, dass rlever
und llever
ein Bit breit sind, und ich brauche, dass sie drei Bit breit sind. Wie dumm von mir. Ich habe den Code wie folgt geändert:
wire [2:0] rlever ...
wire [2:0] llever ...
Also gab es genug Bits. Als ich das Projekt jedoch neu erstellte, kostete mich diese Änderung mehr als 30 Makrozellen und Hunderte von Produktbegriffen. Kann mir jemand erklären was ich falsch gemacht habe?
(Die gute Nachricht ist, dass es jetzt korrekt simuliert ... :-P )
BEARBEITEN -
Ich nehme an, ich bin frustriert, denn ungefähr zu dem Zeitpunkt, an dem ich glaube, dass ich Verilog und CPLD verstehe, passiert etwas, das zeigt, dass ich eindeutig kein Verständnis habe.
assign outp[0] = inp[0] | inp[2] | inp[4] | inp[6];
assign outp[1] = inp[1] | inp[2] | inp[5] | inp[6];
assign outp[2] = inp[3] | inp[4] | inp[5] | inp[6];
Die Logik zur Implementierung dieser drei Zeilen kommt zweimal vor. Das bedeutet, dass jede der 6 Zeilen von Verilog etwa 6 Makrozellen und jeweils 32 Produktterme verbraucht .
BEARBEITEN 2 - Gemäß dem Vorschlag von @ThePhoton zum Optimierungsschalter finden Sie hier Informationen von den von ISE erstellten Zusammenfassungsseiten:
Synthesizing Unit <mux1>.
Related source file is "mux1.v".
Found 3-bit 1-of-9 priority encoder for signal <code>.
Unit <mux1> synthesized.
(snip!)
# Priority Encoders : 2
3-bit 1-of-9 priority encoder : 2
Der Code wurde also eindeutig als etwas Besonderes erkannt. Das Design verbraucht jedoch immer noch enorme Ressourcen.
BEARBEITEN 3 -
Ich habe einen neuen Schaltplan erstellt, der nur den von @thePhoton empfohlenen Mux enthält. Die Synthese führte zu einem unbedeutenden Ressourcenverbrauch. Ich habe auch das von @Michael Karas empfohlene Modul synthetisiert. Dies führte auch zu einem unbedeutenden Verbrauch. Es herrscht also eine gewisse Vernunft vor.
Meine Verwendung der Hebelwerte verursacht eindeutig Bestürzung. Da kommt noch mehr.
Endgültige Bearbeitung
Das Design ist nicht mehr verrückt. Ich bin mir jedoch nicht sicher, was passiert ist. Ich habe viele Änderungen vorgenommen, um neue Algorithmen zu implementieren. Ein Faktor, der dazu beitrug, war ein „ROM“ mit 111 15-Bit-Elementen. Dies verbrauchte eine bescheidene Anzahl von Makrozellen, aber vielvon Produktbegriffen - fast alle auf dem xc2c64a verfügbaren. Ich suche danach, hatte es aber nicht bemerkt. Ich glaube, mein Fehler wurde durch die Optimierung versteckt. Die "Hebel", von denen ich spreche, werden verwendet, um Werte aus dem ROM auszuwählen. Ich gehe davon aus, dass ISE bei der Implementierung des (kaputten) 1-Bit-Prioritätscodierers einen Teil des ROM wegoptimiert hat. Das wäre ein ziemlicher Trick, aber es ist die einzige Erklärung, die mir einfällt. Diese Optimierung reduzierte den Ressourcenverbrauch deutlich und wiegte mich in der Erwartung einer bestimmten Grundlinie ein. Als ich den Priority-Encoder (wie in diesem Thread) repariert habe, habe ich den Overhead des Priority-Encoders und des zuvor optimierten ROMs gesehen und dies ausschließlich dem ersteren zugeschrieben.
Nach all dem war ich gut mit Makrozellen, hatte aber meine Produktkonditionen erschöpft. Die Hälfte des ROM war wirklich ein Luxus, da es nur die 2er-Zusammenstellung der ersten Hälfte war. Ich habe die negativen Werte entfernt und sie an anderer Stelle durch eine einfache Berechnung ersetzt. Dadurch konnte ich Makrozellen gegen Produktbedingungen eintauschen.
Im Moment passt dieses Ding in den xc2c64a; Ich habe 81 % bzw. 84 % meiner Makrozellen bzw. Produktbegriffe verwendet. Natürlich muss ich es jetzt testen, um sicherzustellen, dass es das tut, was ich will ...
Danke an ThePhoton und Michael Karas für die Hilfe. Zusätzlich zu der moralischen Unterstützung, die sie mir bei der Lösung dieses Problems gewährt haben, habe ich aus dem von ThePhoton veröffentlichten Xilinx-Dokument gelernt und den von Michael vorgeschlagenen Prioritäts-Encoder implementiert.
Der angezeigte Code ist im Wesentlichen ein Prioritätscodierer. Das heißt, es hat einen Eingang für viele Signale, und sein Ausgang zeigt an, welches dieser Signale gesetzt ist, wobei dem am weitesten links stehenden gesetzten Signal Priorität gegeben wird, wenn mehr als eines gesetzt ist.
Ich sehe jedoch widersprüchliche Definitionen des Standardverhaltens für diese Schaltung an den beiden Stellen, die ich überprüft habe.
Laut Wikipedia nummeriert der Standard-Prioritäts-Encoder seine Eingänge von 1 an. Das heißt, wenn das niederwertigste Eingangsbit gesetzt ist, gibt er 1 aus, nicht 0. Der Wikipedia-Prioritäts-Encoder gibt 0 aus, wenn keines der Eingangsbits gesetzt ist.
Das XST-Benutzerhandbuch von Xilinx (S. 80) definiert jedoch einen Prioritäts-Encoder, der näher an dem liegt, was Sie codiert haben. Die Eingänge sind von 0 an nummeriert, wenn also das lsb des Eingangs gesetzt ist, ergibt es einen 0-Ausgang. Die Xilinx-Definition gibt jedoch keine Spezifikation für die Ausgabe an, wenn alle Eingabebits gelöscht sind (Ihr Code gibt 3'd7 aus).
Das Xilinx-Benutzerhandbuch bestimmt natürlich, was die Xilinx-Synthesesoftware erwartet. Der Hauptpunkt ist, dass (*priority_extract ="force"*)
XST eine spezielle Anweisung benötigt, um diese Struktur zu erkennen und optimale Syntheseergebnisse zu erzielen.
Hier ist das von Xilinx empfohlene Formular für einen 8-zu-3-Prioritätscodierer:
(* priority_extract="force" *)
module v_priority_encoder_1 (sel, code);
input [7:0] sel;
output [2:0] code;
reg [2:0] code;
always @(sel)
begin
if (sel[0]) code = 3’b000;
else if (sel[1]) code = 3’b001;
else if (sel[2]) code = 3’b010;
else if (sel[3]) code = 3’b011;
else if (sel[4]) code = 3’b100;
else if (sel[5]) code = 3’b101;
else if (sel[6]) code = 3’b110;
else if (sel[7]) code = 3’b111;
else code = 3’bxxx;
end
endmodule
Wenn Sie Ihre Umgebungslogik neu anordnen können, damit Sie den von Xilinx empfohlenen Codierungsstil verwenden können, ist dies wahrscheinlich der beste Weg, um ein besseres Ergebnis zu erzielen.
Ich denke, Sie können dies erreichen, indem Sie das Xilinx-Encodermodul mit instanziieren
v_priority_encoder_1 pe_inst (.sel({~|{RL[6:0]}, RL[6:0]}), .code(rlever));
Ich habe alle Bits zusammengefügt RL[6:0]
, um ein 8. Eingangsbit zu erhalten, das den 3'b111-Ausgang auslöst, wenn alle RL-Bits niedrig sind.
Für die llever
Logik können Sie wahrscheinlich die Ressourcennutzung reduzieren, indem Sie ein modifiziertes Encodermodul nach der Xilinx-Vorlage erstellen, das jedoch nur 7 Eingangsbits benötigt (Ihre 6 Bits LL
plus ein zusätzliches Bit, das hoch geht, wenn die anderen 6 alle niedrig sind).
Die Verwendung dieser Vorlage setzt voraus, dass Ihre ISE-Version die XST-Synthese-Engine verwendet. Es scheint, als würden sie die Synthesewerkzeuge bei jeder größeren Version von ISE ändern, also überprüfen Sie, ob das von mir verlinkte Dokument tatsächlich Ihrer Version von ISE entspricht. Wenn nicht, überprüfen Sie den empfohlenen Stil in Ihrer Dokumentation, um zu sehen, was Ihr Tool erwartet.
(* priority_extract="force" *)
und wahrscheinlich auch explizit die Ausgabe von egal zu enthalten, obwohl Sie jede mögliche Eingabe abdecken. (Ohne sie versucht XST wahrscheinlich, eine vollständige Nachschlagetabelle zu erstellen, weshalb so viele Produktbegriffe vorhanden sind.) Versuchen Sie zuerst, die Option "egal" hinzuzufügen. Wenn es nicht funktioniert, versuchen Sie es genau mit der Xilinx-Boilerplate.Die Antwort von ThePhoton ist ausgezeichnet. Ich möchte hier einige zusätzliche Informationen zu Ihrer Überlegung hinzufügen. Dies rührt von der Tatsache her, dass wir, obwohl wir hochmoderne, ausgefallene FPGA- und CPLD-Geräte haben, die HDLs und Synthesewerkzeuge verwenden, aufschlussreich sein können, Dinge, die vor Jahren entwickelt wurden, genau zu betrachten. Bleiben Sie bei mir, während ich dies bis zu meiner Empfehlung am Ende durchgehe.
Es gibt diskrete Logikteile, die die Prioritätscodierfunktion ausführen. Die durch diese Teile implementierte Logik gibt es schon lange, als es wichtig war, die Anzahl der Transistoren auf ein absolutes Minimum zu reduzieren. Sie können im Internet nach Logikteilen mit generischen Teilenummern wie 74HC148 oder MC14532B suchen, um Datenblätter zu finden, die entsprechende Logikdiagramme für diese Teile enthalten. Das folgende Diagramm ist ein Beispiel aus dem TI-Datenblatt für das Teil 74HC148 .
Diese Logik implementiert die folgende Wahrheitstabelle (aus demselben Datenblatt):
Beachten Sie, dass die obige Teilefamilie niedrige aktive Eingangssignale verwendet. Ein weiteres Datenblatt für das MC14532B-Teil von ON Semiconductor zeigt eine Wahrheitstabelle für die Encoder-Funktion, die Active-High-Eingangssignale ähnlich Ihrem Verilog-Beispiel verwendet.
Das gleiche Datenblatt zeigt die logischen Gleichungen für den MC14532B wie folgt:
Möglicherweise möchten Sie ähnliche Gleichungen direkt in Ihren Verilog-Code codieren, um zu sehen, wie er mit Ihrem aktuellen Beispiel verglichen wird. Es ist sehr wahrscheinlich, dass es zu einem viel günstigeren Ergebnis führt.
Vicatcu
Toni Ennis
Das Photon
Toni Ennis
Das Photon
|
nach anstelle von||
.Toni Ennis
Toni Ennis
Das Photon