Warum verschlingt dieser Verilog 30 Makrozellen und Hunderte von Produktbegriffen?

8

Ich habe ein Projekt, das 34 Makrozellen eines Xilinx Coolrunner II verbraucht. Ich bemerkte, dass ich einen Fehler hatte und verfolgte ihn wie folgt:

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 rleverund lleverein Bit breit sind, und ich brauche sie drei Bit breit. Wie dumm von mir. Ich habe den Code wie folgt geändert:

wire [2:0] rlever ...
wire [2:0] llever ...

es gab also genug Bits. Als ich das Projekt neu aufbaute, kostete mich diese Änderung jedoch mehr als 30 Makrozellen und Hunderte von Produktbedingungen. Kann mir jemand erklären, was ich falsch gemacht habe?

(Die gute Nachricht ist, dass es jetzt richtig simuliert ... :-P)

BEARBEITEN -

Ich bin wahrscheinlich frustriert, weil ungefähr zu dem Zeitpunkt, an dem ich Verilog und die CPLD zu verstehen beginne, etwas passiert, 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 zum Implementieren dieser drei Zeilen erfolgt zweimal. Das bedeutet , dass jede der 6 Zeilen von Verilog etwa 6 Makrozellen und 32 Produktterme verbraucht je .

EDIT 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.

EDIT 3 -

Ich habe ein neues Schema erstellt, das nur den von @thePhoton empfohlenen Mux enthält. Die Synthese führte zu einer unbedeutenden Ressourcennutzung. Ich habe auch das von @Michael Karas empfohlene Modul synthetisiert. Dies führte auch zu einer unbedeutenden Nutzung. Es herrscht also ein gewisser Verstand.

Es ist klar, dass meine Verwendung der Hebelwerte Bestürzung hervorruft. 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" von 111 15-Bit-Elementen. Dies verbrauchte eine bescheidene Anzahl von Makrozellen, aber vielvon Produktbegriffen - fast alle auf dem xc2c64a verfügbaren. Ich suche das, habe es aber nicht bemerkt. Ich glaube, mein Fehler wurde durch Optimierung verborgen. 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 ROMs optimiert 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 brachte mich dazu, eine bestimmte Basislinie zu erwarten. Als ich den Prioritätscodierer (gemäß diesem Thread) reparierte, sah ich den Overhead des Prioritätscodierers und des ROM, die zuvor optimiert worden waren, und schrieb dies ausschließlich dem ersteren zu.

Nach all dem war ich gut in Makrozellen, hatte aber meine Produktbedingungen erschöpft. Die Hälfte des ROM war wirklich ein Luxus, da es nur die 2er-Komposition 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 und Produktbegriffe verwendet. Natürlich muss ich es jetzt testen, um sicherzustellen, dass es tut, was ich will ...

Vielen Dank an ThePhoton und Michael Karas für die Unterstützung. Zusätzlich zu der moralischen Unterstützung, die sie mir bei der Lösung dieses Problems gewährt haben, habe ich aus dem Xilinx-Dokument ThePhoton gelernt und den von Michael vorgeschlagenen Prioritätscodierer implementiert.

Tony Ennis
quelle
Bedeutet nicht jedes Fragezeichen dort effektiv einen Multiplexer, und strukturell haben Sie sie auch kaskadiert? Wie viele Makrozellen haben Sie erwartet?
Vicatcu
Ich weiß nicht, wie viele Makrozellen das Konstrukt verbrauchen soll. Angesichts der Tatsache, dass mein Projekt derzeit 34 Makrozellen einschließlich dieser beiden 1-Bit-Multiplexer verbraucht und dass dies ein kleiner Teil des Projekts ist, bin ich von diesem Ergebnis überrascht.
Tony Ennis
Welches Tool verwenden Sie?
Das Photon
Xilinx ISE ...
Tony Ennis
In dem Code in Ihrer Bearbeitung, denke ich, möchten Sie |statt ||.
Das Photon

Antworten:

7

Der Code, den Sie anzeigen, ist im Wesentlichen ein Prioritätscodierer. Das heißt, es hat einen Eingang mit vielen Signalen, und sein Ausgang zeigt an, welches dieser Signale eingestellt ist, wobei dem am weitesten links eingestellten Signal Priorität eingeräumt wird, wenn mehr als eines eingestellt ist.

Ich sehe jedoch an den beiden von mir überprüften Stellen widersprüchliche Definitionen des Standardverhaltens für diese Schaltung.

Laut Wikipedia nummeriert der Standardprioritätscodierer seine Eingänge von 1. Das heißt, wenn das niedrigstwertige Eingangsbit gesetzt ist, gibt er 1 und nicht 0 aus. Der Wikipedia-Prioritätscodierer gibt 0 aus, wenn keines der Eingangsbits gesetzt ist.

Das XST-Benutzerhandbuch von Xilinx (S. 80) definiert jedoch einen Prioritätscodierer, der näher an dem liegt, was Sie codiert haben. Die Eingänge sind von 0 nummeriert. Wenn also der lsb des Eingangs eingestellt ist, wird ein 0-Ausgang ausgegeben. 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 die von Xilinx empfohlene Form 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 = 3b000;
    else if (sel[1]) code = 3b001;
    else if (sel[2]) code = 3b010;
    else if (sel[3]) code = 3b011;
    else if (sel[4]) code = 3b100;
    else if (sel[5]) code = 3b101;
    else if (sel[6]) code = 3b110;
    else if (sel[7]) code = 3b111;
    else code = 3bxxx;
end
endmodule

Wenn Sie Ihre umgebende Logik 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-Encoder-Modul mit instanziieren

v_priority_encoder_1 pe_inst (.sel({~|{RL[6:0]}, RL[6:0]}), .code(rlever));

Ich habe nicht 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 lleverLogik können Sie wahrscheinlich den Ressourcenverbrauch reduzieren, indem Sie ein modifiziertes Encoder-Modul erstellen, das der Xilinx-Vorlage folgt, aber nur 7 Eingangsbits benötigt (Ihre 6 Bits LLplus ein zusätzliches Bit, das hoch geht, wenn die anderen 6 alle niedrig sind).

Bei Verwendung dieser Vorlage wird davon ausgegangen, dass die von Ihnen verwendete ISE-Version die XST-Synthese-Engine verwendet. Es scheint, als würden sie die Synthesewerkzeuge bei jeder größeren Version von ISE ändern. Überprüfen Sie daher, ob das von mir verknüpfte Dokument tatsächlich Ihrer Version von ISE entspricht. Wenn nicht, überprüfen Sie den empfohlenen Stil in Ihrer Dokumentation, um festzustellen, was Ihr Tool erwartet.

Das Photon
quelle
Danke, die Verdauung wird einige Zeit dauern. Meine ISE verwendet XST, obwohl ich nicht weiß, welche Version.
Tony Ennis
Der Schlüssel ist die (* priority_extract="force" *)und wahrscheinlich auch explizite Einbeziehung der nicht interessierenden Ausgabe, obwohl Sie jede mögliche Eingabe abdecken. (Ohne diese Option versucht XST wahrscheinlich, eine vollständige Nachschlagetabelle zu erstellen, weshalb so viele Produktbegriffe verwendet werden.) Fügen Sie zuerst die Option "Egal" hinzu. Wenn es nicht funktioniert, versuchen Sie, das Xilinx-Boilerplate genau zu verwenden.
Das Photon
Ich habe einen vollständigen Rip des obigen Codes implementiert und kein verbessertes Ergebnis erzielt. Die ISE-Zusammenfassungsseiten zeigen an, dass ein MUX erkannt wurde, obwohl die Erkennung nicht so stark war wie bei anderen Konstrukten. Ich werde die relevanten Informationen in ein paar Minuten veröffentlichen.
Tony Ennis
edit - ignoriere den obigen Kommentar über 'starke Anerkennung' - es ist da, ich habe es letzte Nacht verpasst; Ich habe die Arbeit überarbeitet und die Realität funktioniert korrekt.
Tony Ennis
6

Die Antwort von ThePhoton ist ausgezeichnet. Ich möchte hier einige zusätzliche Informationen für Ihre Überlegung hinzufügen. Dies ergibt sich aus der Tatsache, dass es informativ sein kann, die vor Jahren entwickelten Dinge genau zu betrachten, obwohl wir über hochmoderne FPGA- und CPLD-Geräte verfügen, die HDLs und Systhesis-Tools verwenden. Bleib bei mir, während ich dies zu meiner Empfehlung am Ende durchlaufe.

Es gibt diskrete Logikteile, die die Prioritätscodierungsfunktion ausführen. Die von diesen Teilen implementierte Logik gibt es schon seit langer Zeit, als es wichtig war, die Anzahl der Transistoren auf ein Minimum zu reduzieren. Sie können im Internet nach Logikteilen mit generischen Teilenummern wie 74HC148 oder MC14532B suchen, um Datenblätter zu finden, die äquivalente Logikdiagramme für diese Teile enthalten. Das folgende Diagramm ist ein Beispiel aus dem TI-Datenblatt für den 74HC148-Teil .

Geben Sie hier die Bildbeschreibung ein

Diese Logik implementiert die folgende Wahrheitstabelle (aus demselben Datenblatt entnommen):

Geben Sie hier die Bildbeschreibung ein

Beachten Sie, dass die obige Teilefamilie niedrige aktive Eingangssignale verwendet. Ein weiteres Datenblatt für den Teil ON Semiconductor MC14532B zeigt eine Wahrheitstabelle für die Encoderfunktion mit aktiven Signalen mit hohem Eingang, ähnlich wie in Ihrem Verilog-Beispiel.

Geben Sie hier die Bildbeschreibung ein

Das gleiche Datenblatt zeigt die logischen Gleichungen für den MC14532B wie folgt:

Geben Sie hier die Bildbeschreibung ein

Möglicherweise möchten Sie ähnliche Gleichungen direkt in Ihren Verilog-Code codieren, um zu sehen, wie dieser mit Ihrem vorliegenden Beispiel verglichen wird. Es ist sehr wahrscheinlich, dass dies zu einem viel günstigeren Ergebnis führt.

Michael Karas
quelle
Danke, ich werde es tun. Dieses Problem bringt mich um. Ich glaube, es wurde früher effizienter synthetisiert. Und dann habe ich etwas geändert. / selfbonk
Tony Ennis
Danke, ich habe es implementiert. Es machte leider keinen wesentlichen Unterschied.
Tony Ennis
Gute Antwort. Lassen Sie uns Tony sehen, wie viele Produktausdrücke es sollte diese Logik implementieren müssen. Tony, wenn Sie entweder Xilinx 'Boilerplate oder Michaels Gleichungen verwenden und immer noch Hunderte von Produktbegriffen generieren, müssen Sie nach einer subtilen Änderung in Ihrem Code suchen, die das Problem möglicherweise verursacht hat. Oder schauen Sie sich die Syntheseprotokolldatei genau an, um festzustellen, ob etwas passiert, das Sie nicht erwarten.
Das Photon
Ich stimme @ThePhoton voll und ganz zu. Ich habe etwas abgespritzt. Ich bin mir so sicher wie möglich, dass dies früher funktioniert hat - ich habe nicht einmal bemerkt, dass der Verbrauch so gering war. Na ja, es ist eine gute Ausrede, um mehr über die Zusammenfassungsinformationen zu erfahren.
Tony Ennis