Hallo,
ich versuche gerade nachzuvollziehen was das Synthese-Tool aus meinem
Code eigentlich macht.
Dazu betrachte ich gerade ein Address Decoder für folgendes Memory
Layout:
Memory | Address Offset
-----------------------
Mem 0 | 0x000000
Mem 0-1 | 0x180000
Mem 1 | 0x200000
Mem 1-2 | 0x380000
Mem 2 | 0x400000
Mem 2-3 | 0x580000
Mem 3 | 0x600000
Mem 3-4 | 0x780000
Mem 4 | 0x800000
Mem 4-5 | 0x980000
Mem 5 | 0xA00000
Mem 5-6 | 0xB80000
Mem 6 | 0xC00000
Mem 6-7 | 0xD80000
Mem 7 | 0xE00000
Mem 7-0 | 0xF80000
(Die Namensgebung kommt von den Prozessoren die am Ende darauf zugreifen
sollen... sollte aber erstmal keine Rolle spielen ;-) )
Das heißt wir haben zwei Arten von Speicher. Zum einen größere
Hauptspeicher mit 1,5 MB und kleinere Speicher mit 0,5 MB.
Der zugehörige Address Decoder hat folgende Entity:
SLAVE_QTY ist dabei eine Konstante die global definiert ist, da sie auch
in anderen Komponenten genutzt wird. Momentan beträgt sie 16.
Nun habe ich zwei verschiedene Ansätze für die Architektur:
1. Variante bei der ich mir selber rausgesucht habe welche Bits benötigt
werden und welches Kombinationen zu zum entsprechenden Chipselect führen
So, nun is klar das er in der RTL mir bei der ersten Variante Logik aus
dem One-Hot-Decoder und den Und Gattern baut, so wie ich das ja
beschrieben habe und bei der 2. Variante nen haufen vergleicher. Wenn er
das jetz aber auf die LUTs abbildet, sollte doch bei gleichem Verhalten
auch das gleiche rauskommen oder?
Das Synthese-Tool von Altera macht aus der 1. Variante Logik mit 21 LUTs
und aus der 2. Logik mit 24 LUTs. Das ist das was ich nicht ganz
verstehe, ich dachte das Synthese-Tool geht alle eingangsmöglichkeiten
durch und schaut was an den ausgängen danach anliegt und erstellt anhand
dieser Informationen entsprechend die LUTs. Nun sollten aber beide
Beschreibungen funktionell das gleiche machen, oder? (oder liegt as an
irgendwelchen 'X' und 'U' zuständen?). Habt ihr vlt noch ne Idee woher
der Unterschied kommt.
Na ja, da die zweite Variante besser anpassbar bei Veränderungen des
Memory Layouts ist und 3 LUTs auch fast nichts sind werde ich wohl eher
diese Variante bevorzugen.
Vielen Dank schon mal für eure Antworten und Grüße
Thomas
Na hauptsächlich wollte ich wissen, wie die 3 LUTs unterschied zustande
kommen. Wenn mir vlt noch jemand sagen kann ob meine Ansatz überhaupt
richtig ist, dass bei der Synthese einfach alle Eingangsmöglichkeiten
versucht werden, dabei geschaut wird was am Ausgang passiert und anhand
dessen dann die die LUTs erstellt werden.
Grüße
Thomas
Ein kleinwenig Erklärung dazu findet sich hier
http://de.wikipedia.org/wiki/Logiksynthese
und hier:
http://de.wikipedia.org/wiki/Verfahren_nach_Quine_und_McCluskey
Zitat:
>Das Verfahren nach Quine und McCluskey (QMCV, nach Willard Van Orman>Quine und Edward J. McCluskey) ist eine Methode, um Boolesche Funktionen>zu minimieren (...) Das Verfahren benötigt im schlechtesten Fall>exponentielle Laufzeit, um eine minimale Lösung zu finden. Das Verfahren>findet immer eine minimale Lösung, es ist jedoch möglich, dass es noch>andere (gleichwertige) Lösungen gibt, die nicht gefunden werden. Da das>zugrunde liegende Problem NP-vollständig ist, und unter der Annahme,>dass P ≠ NP gilt, gibt es kein in diesem Sinne effizientes Verfahren.
Hallo Thomas
folgende verbreiteten Irrtümern sitzt du auf:
-die FPGA-tools wissen was für Dich otpimal ist und nehmen dir die
Entscheidung über für Dich richtige Implementierung ab
-LUT ist alles
-VHDL ist eine Hochsprache zur Beschreibung von Funktionen in Hardware
-die kombinatorische Funktion ist alles was eine digitale Schaltung
bestimmt
Synthesetools setzen zuerst um was du beschrieben hast, Signal um
Signal,Block um Block.
Erst dann folgen verschiedene Optimierungsroutinen, die einzeln
aktiviert sein müssen.
Hast Du einen Komperator beschrieben, setzen
die Tools einen Komperator an. Der kann aus LUTS aufgebaut sein, kann
aber auch (bspw bei größer|kleiner Vergleichern)
als "Arithmetik" Subtrahierer aufgebaut sein.
FPGA haben Strukturen die sich für klein granulare logische
Verknüpfungen anbieten,
(LUT's), Strukturen die Optimal für breite/Schnelle Addierer sind
(Carry-Chain) und Blöcke für breite, konzentrierte Logik
(BlockRAMS genutz als ROM-LUT). Wobei optimal heißen kann:
-wenig Ressourcen genutzt
-wenig LUT's genutzt
-schnell
-leicht routbar
-leicht testbar
Eine Optimal kleine Schaltung kann schlecht routbar sein. Bspw. kann
bei einem kleinem zentraler Adressdecoder es schwierig sein
die ChipSelect Leitungen an die im FPGA vestreut liegenden Datenbus
Eingangs-FF der einzelnen Module zu verdrahten. Besser waren da
dezentrale Adressdecoder in der Nähe des Moduls. Das ist wie beim
Entflechten eines PCB's, schnell hat man sich durch falsche Platzierung
eines kleinen Blocks die optimale Gesamtlösung für das Gesamt-PCB
verbaut.
Einige wenige Logik-Optimierungen können die Tools, aber immer unter
der Verbidungen das diese Optimierung aktiviert ist und an der
Beschreibung
funktionall nicht verändert wird. Beispielsweise bleiben Signale die
einer "Zwischenvariable" entsprechen erhalten, auch wenn sie in einer
LUT verschwinden könnten.
Könnte ja sein das der Anwender nach diesem Signal in der Netzliste
sucht un es an einen Hardware-debugger wie Chipscope anzuschliessen.
-Für deine Schaltung empfehle ich dir den Synthesereport durchzulesen.
Dort steht welche Hardwareblöcke in der Beschreibung erkannt worden und
was daraus gebaut wurde,
Bei Xilinx sieht das so aus:
Related source file is
"C:/Users/KommPute/FPGA/Misc/FloatCounter/FloatPointCount/flcnt.vhd".
Found 12-bit register for signal <count_q>.
Found 12-bit adder for signal <count_q$add0000> created at line 145.
Found 17-bit comparator equal for signal <do_tick_0$cmp_eq0000>
created at line 120.
Found 4-bit up counter for signal <expo_q>.
Found 17-bit register for signal <prescale_limit_q>.
Found 17-bit comparator not equal for signal
<prescale_limit_q$cmp_ne0000> created at line 109.
Found 17-bit up counter for signal <prescale_q>.
Summary:
inferred 2 Counter(s).
inferred 29 D-type flip-flop(s).
inferred 1 Adder/Subtractor(s).
inferred 2 Comparator(s).
-Eine Blick in den RTL-View hilft auch meist weiter.
-Wieviel Resourcen ein Komperator verbraucht sollte im Library Guide
stehen.
-Bei den Optimierungen sollte "Flatten Netlist" aktiviert sein oder
sowas wie Optimierungen über Hierarchiegrenzen.
-Eine Idee wie stark sich die VHDL-Beschreibung auf die Implemtierung
auswirkt vermittelt das WP 274 von Xilinx. In dem Forums-thread:
Beitrag "Sinn von "MULT_AND""
wird andiskutiert, was es noch so neben den LUT's gibt.
-Und nicht vergessen:
Die tools setzen das um was du beschrieben hast und nehmen dir keine
Designentscheidungen ab.
Thomas schrieb:> Das heißt wir haben zwei Arten von Speicher. Zum einen größere> Hauptspeicher mit 1,5 MB und kleinere Speicher mit 0,5 MB.
Ich würde das anhand der signifikanten Bits ausklamüsern:
Erst mal die unnötigen Nullen weg:
Memory |
-----------------------
Mem 0 | 0x000000 --> 000 0 0
Mem 0-1 | 0x180000 --> 000 1 1
Mem 1 | 0x200000 --> 001 0 0
Mem 1-2 | 0x380000 --> 001 1 1
Mem 2 | 0x400000 --> 010 0 0
Mem 2-3 | 0x580000 --> 010 1 1
Mem 3 | 0x600000 --> 011 0 0
Mem 3-4 | 0x780000 --> 011 1 1
Mem 4 | 0x800000 --> 100 0 0
Mem 4-5 | 0x980000 --> 100 1 1
Mem 5 | 0xA00000 --> 101 0 0
Mem 5-6 | 0xB80000 --> :
Mem 6 | 0xC00000 -->
Mem 6-7 | 0xD80000 -->
Mem 7 | 0xE00000 -->
Mem 7-0 | 0xF80000 --> 111 1 1
Und dann sieht man sofort: das oberste Nibble geht schon sehr stark in
Richtung "der Chipselect"...
Jetzt nur noch das obere Bit vom Nibble davor mit reingepackt: