Forum: FPGA, VHDL & Co. Konversions-Funktion als VHDL-Netzliste anlegen und weiternutzen


von Messtechniker (Gast)


Lesenswert?

Ich möchte eine komplizierte Übertragungsfunktion zur Wiederverwertung 
in unterschiedlichen Schaltungen vorbereiten. Die Funktion kommt aus 
einem MATLAB oder EXCEL, das die Werte Y(X)) erzeugt und hat z.B. 16 Bit 
auf 16 Bit. Ureigentlich wird eine Kennlinie verbogen, z.B. leicht 
logarithmisch gemacht.

Eine Möglichkeit ist, sie per COE bei power up in ein RAM zu schieben, 
was bereits gelungen ist und auch funktioniert. Da es sich aber um eine 
teils als Interpolationsfunktion genutzte Ü-Kennline handelt, hat sie 
Lücken. Diese sind dynamisch und von der Funktion abhängig.
D.h. es gibt X-Werte die nicht definiert sind. Das macht etwa 30% des 
Speichers aus. Bei den neuen 18 Bit-Versionen sind es aber schon 40%.

Ich würde gerne das RAM sparen und es als Kombinatorik bauen lassen. 
Nach meiner Vorstellung braucht er dazu für jedes Bit eine Schaltung mit 
maximal 16 Eingängen, also eine klassische UND-ODER-Struktur.

Angelegt habe ich das hier:
1
     case to_integer (unsigned(inp_dat)) is
2
3
when  0  =>  out_sqr  <=  0  ;
4
when  1  =>  out_sqr  <=  512  ;
5
when  2  =>  out_sqr  <=  724  ;
6
when  3  =>  out_sqr  <=  887  ;
7
when  4  =>  out_sqr  <=  1024  ;
8
when  5  =>  out_sqr  <=  1145  ;
9
when  6  =>  out_sqr  <=  1254  ;
10
when  7  =>  out_sqr  <=  1355  ;
11
when  8  =>  out_sqr  <=  1448  ;
12
when  9  =>  out_sqr  <=  1536  ;
13
when  10  =>  out_sqr  <=  1619  ;
14
when  11  =>  out_sqr  <=  1698  ;
15
when  12  =>  out_sqr  <=  1774  ;

Das file wird mit einem Script direkt erzeugt und wäre sehr elegant 
nutzbar, um verschiedene Versionen zu machen, die austauschbar sind. 
Leider baut die Synthese eine geschlagene Ewigkeit, bis sie damit fertig 
ist und schob es anfänglich trotzdem in ein RAM. Das habe ich ihm mit 
USE BRAM 0 abgewöhnt und versucht, das zu bauen, aber selbst nach 2h 
kommt kein Ergebnis.

Woran könnte das liegen?

Gibt es einen besseren Weg?

von Gustl B. (-gb-)


Lesenswert?

Messtechniker schrieb:
> 16 Bit auf 16 Bit.

Dir ist klar wie viele Bits das sind? 2^16 Werte willst du abbilden auf 
2^16 andere Werte.

Messtechniker schrieb:
> aber selbst nach 2h kommt kein Ergebnis.

Was sagt denn deine Toolchain zu den Ressourcen? Werden schon >100% der 
LUTs gebraucht? Das P+R kann sehr lange dauern wenn das FPGA voller 
wird.

BRAM dafür ideal geeignet. Aber eine Tabelle aus 2^16 Einträgen mit je 
16 Bits sind eben 1 MBit Speicher den du brauchst.

Der andere übliche Weg ist den Algorithmus zur Berechnung in Hardware zu 
bauen, dann brauchst du da keine Tabelle ablegen.

Und wenn das nicht geht, dann kann man auch nur Teile der Tabelle 
ablegen. Also z. B. jeden 8ten oder 2^nten Wert. Wenn man dazwischen was 
braucht muss man interpolieren.

von Achim S. (Gast)


Lesenswert?

Messtechniker schrieb:
> Ich würde gerne das RAM sparen und es als Kombinatorik bauen lassen.

Kombinatorik wird im FPGA nicht mit und-oder Struktur implementiert 
sondern ebenfalls über RAM ( nur eben über das distributed RAM der LUTs 
statt über das BlockRAM deines ersten Ansatzes). wenn du gleich viele 
Stützwerte speichern willst, wirst du gleich viel RAM brauchen.

die Verschwendung des RAMs kommt daher, das du nicht für alle 2**n 
Stützwerte verwendest. wenn du es schaffst, die tatsächlich benutzen 
Adressen auf einen kleineren (dicht belegten) Adressraum abzubilden, 
kannst du darüber die Verschwendung von Ram vermeiden.

Messtechniker schrieb:
> Gibt es einen besseren Weg?

wird dein Signal wirklich noch besser, wenn du die Ausgleichskurve mit 
2**18 stützstellen speicherst (statt 2**16 stützstellen zu nehmen und zu 
interpolieren)

von Achim S. (Gast)


Lesenswert?

Achim S. schrieb:
> mit 218 stützstellen speicherst (statt 216 stützstellen zu nehmen und zu
> interpolieren)

sollte 2 hoch 16 bzw. 2 hoch 18 heißen...

von Messtechniker (Gast)


Lesenswert?

Achim S. schrieb:
> ie Verschwendung des RAMs kommt daher, das du nicht für alle 2**n
> Stützwerte verwendest. wenn du es schaffst, die tatsächlich benutzen
> Adressen auf einen kleineren (dicht belegten) Adressraum abzubilden,
Nein, das geht leider nicht.

Gustl B. schrieb:
> Der andere übliche Weg ist den Algorithmus zur Berechnung in Hardware zu
> bauen, dann brauchst du da keine Tabelle ablegen.
Es gibt keine analytische Lösung dafür. Die Tabelle ist Ergebnis von 
Berechnung und Messung. Diese wiederum ist die Folge von physikalischen 
Dreckeffekten und sieht bei jedem System anders aus.

Gustl B. schrieb:
> Dir ist klar wie viele Bits das sind? 2^16 Werte willst du abbilden auf
> 2^16 andere Werte.
Ganz richtig.

Wie schon dargestellt, müsste jedes der 16 Ergebnis-Bits eine eigene 
Schaltung bekommen, die von 16 Eingängen abhängig ist. Also sowas wie:

E(0) = A(15) and (not A(14)) and A(13) and A(11) ... A(0);
E(1) = (not A(15)) and (not A(14)) and A(12) ... A(1);

u.s.w.

Jede der 16 Gleichungen hat also maximal 16 Eingänge. Dabei kann es noch 
ein Not geben. In den PLDs haben wir das immer als Matrix programmiert. 
Das kann eigentlich so groß nicht werden, meine ich. Wenn eine LUT 6 
Eingänge hat, braucht man 16x2 / 6 = 6 Stück und dann noch 1-2 dahinter 
um diese 6 ersten zu ver-und-en. Oder ist da ein Denkfehler?

Hatte die Synthese abgebrochen und simuliere das jetzt nochmals durch. 
Eventuell baue ich es auch erst einmal kleiner zum Testen.

von Achim S. (Gast)


Lesenswert?

Du willst nunmal insgesamt 2^16 mal 16 Bit speichern. Wenn ein Großteil 
dieser Information redundant wäre (weil z.B. viele benachbarte 
Stützstellen ähnliche Werte haben, dann lässt sich das reduzieren (indem 
es "komprimiert" gespeichert wird). Aber die Größenordnung der 
abgespeicherten Informationsmenge zur Ausgleichstabelle wird bei 128 
kByte bleiben - egal ob in BlockRAM oder in LUTs gespeichert.

Messtechniker schrieb:
> Das kann eigentlich so groß nicht werden, meine ich. Wenn eine LUT 6
> Eingänge hat, braucht man 16x2 / 6 = 6 Stück und dann noch 1-2 dahinter
> um diese 6 ersten zu ver-und-en. Oder ist da ein Denkfehler?

Das mit dem Denkfehler trifft zu. Eine LUT hat 6 Eingänge. Wenn du 7 
Eingänge abdecken willst, brauchst du 2 LUTs. Für 8 Eingänge sind es 4 
LUTs, für 9 Eingänge 8 LUTs (alles nur rein rechnerisch, real 
funktioniert das mit der Potenzierung nur auf kleiner Skala).

Wenn du 16 Eingangsbits abdecken willst brauchst du als 2^(16-6) = 1024 
LUTs, um ein Ausgangsbit zu erzeugen. Und die müssten ja noch 
entsprechend zusammengeführt und verdrahtet werden. Das Ergebnis siehst 
du an deinen aktuellen Implementierungsversuchen.

Ich wiederhole nochmal, was ich oben schrieben habe:

Achim S. schrieb:
> wird dein Signal wirklich noch besser, wenn du die Ausgleichskurve mit
> 2^18 stützstellen speicherst (statt 2^16 stützstellen zu nehmen und zu
> interpolieren)

Steckt in deiner Tabelle tatsächlich so viel Information über einen 
"echten" Kurvenverlauf? Unterscheiden sich bei 2^16 (oder sogar 2^18) 
Stützstellen die Wert benachbarter Stützstellen wirklich deutlich und 
kannst du den Unterschied tatsächlich bis auf 16 (oder gar 18) Bit 
Auflösung bestimmen? Oder reicherst du die Übertragungsfunktion in 
Wirklichkeit nur noch mit Rausch-Information an, die dein Messergebnis 
real gar nicht mehr verbessert?

Falls du wirklich glaubst, die volle Tabelleninformation nutzen zu 
können und zu wollen: spendiere das notwendige RAM dafür. Du wirst 
nichts besseres finden, um Messwerttabellen zu speichern, als RAM. Wenn 
das interne RAM nicht ausreichen sollte, nutze ein größeres FPGA oder 
spendiere ein externes RAM.

von Achim S. (Gast)


Lesenswert?

Achim S. schrieb:
> Wenn
> das interne RAM nicht ausreichen sollte, nutze ein größeres FPGA oder
> spendiere ein externes RAM.

Und als Nachtrag: wenn du tatsächlich auf externen Speicher setzen 
solltest, muss das natürlich kein RAM sein. Als externen Speicher kannst 
du die Speichertechnologie deiner Wahl einsetzen (z.B. auch einen Flash, 
in dem deine Kalibrierwerte gespeichert sind).

von Testuser (Gast)


Lesenswert?

Messtechniker schrieb:
> Wie schon dargestellt, müsste jedes der 16 Ergebnis-Bits eine eigene
> Schaltung bekommen, die von 16 Eingängen abhängig ist.

Nein. Denn du bildest ja nicht 16 Bits auf 16 Bits ab, sondern 2^16 
Werte zu je 16 Bits auf 2^16 Werte zu 16 Bits. Und außerdem sind deine 
Ausgangsbits doch keine Funktion der Eingangsbits. Du brauchst also 
Speicher.

Und zwar 1 Mbit. Das haben nur größere FPGAs als LUTRAM. Bei BRAM auch 
in der unteren Mittelklasse schon möglich.

Messtechniker schrieb:
> Hatte die Synthese abgebrochen und simuliere das jetzt nochmals durch.

Interessant wäre jetzt der genaue FPGA in den das rein soll. 
Simulationen bringt da nicht so viel, aber du kannst ja mal gucken was 
im RTL Viewer draus gebaut wird. Und dann kannst du spaßeshalber mal ein 
dickes FPGA einstellen und gucken was die Synthese macht. P+R kannst du 
weglassen.

von Duke Scarring (Gast)


Lesenswert?

Messtechniker schrieb:
> Das habe ich ihm mit
> USE BRAM 0 abgewöhnt und versucht, das zu bauen, aber selbst nach 2h
> kommt kein Ergebnis.
Ich bin mal den umgekehrten Weg gegangen: Die Tools haben immer versucht 
den ROM-Inhalt (=Lookup-Table) als Logikgleichung zu optimieren. Jedes 
Ausgangsbit ist eine Logikfunktion mit 2^n Eingängen. Als der 
Synthesizer gezwungen wurde, das in den Block-RAM zu packen lief die 
Synthese gleich viel schneller.

Duke

von Meßtechniker (Gast)


Lesenswert?

So, habe nochmal ein Bier gehabt und das Hirn durchgespült und ja, 
natürlich gibt es wesentlich mehr, als nur jeweils 16(x16) Kombinationen 
gültiger und-Verknüpfungen, die man verodern muss.

Die Netzliste hat für den Fall 16 inzwischen auch synthetisiert und ist 
erwartungsgemäß gewaltig.

Gleichwohl gibt es Gründe das so zu machen, zumindest für die kleineren 
Korrekturfunktionen.

Daher mal zur anderen Frage:

Davon ausgehend, ich habe ein synthetisiertes Ergebnis (Vivado kann ein 
SCH aufmachen, oder die Implementierung) ... wie kann ich diese 
Netzliste schnappen und als LIB-file hinterlegen, um es später in ein 
VHDL hineinzudroppen?

von J. S. (engineer) Benutzerseite


Lesenswert?

Die 16 Eingänge stimmen schon aber die Gleichungen können ja beliebig 
kompliziert sein. Es gibt nicht nur eine Kombination der 16 Eingänge 
sondern theoretisch JEDE, Also für a(15) alle darunter und not a(15) 
auch. Das sind 2hochN Gleichungen. Entsprechend viele LUTs werden 
benötigt.

Hallo vielleicht wäre diese LUT-IP etwas:

https://www.xilinx.com/content/dam/xilinx/support/documents/ip_documentation/v_gamma_lut/v1_1/pg285-v-gamma-lut.pdf

Generell macht das Optimieren solcher Tabellen nur Sinn, wenn man 
weniger als 30%, besser nur 20% Füllung hat, weil das ja letztlich ins 
distributed RAM kommt und damit wichtige Resourcen wegfrisst. Der 
Synthesizer steckt das obendrein auf Wunsch am Ende doch noch in ein 
BRAM und dann ist man genau so weit. Etwaige Optimierungen an den 
Adressen kann er dann ja auch berücksichtigen - das muss also nicht 
vorab oder per Hand gemacht werden.

Wo ich mit einer solche Strategie Erfolg hatte, ist mein 
Frequenz-Zähler-Core:

Der kann pro Kaskade jeweils durch 1,2,3 ... 9,10 teilen und einen Sinus 
generieren. Die dazu nötigen Stützstellen purzeln auf die benötigten 
ganzzahligen Vielfachen der Adressen zusammen. Mit einer Dichte von 
Faktor 7x4 (empirisch ermittelt) komme ich auf eine Zahl, die in der 
Nähe einer Binärzahl liegt und ein RAM weitgehend nutzt, wenn man einen 
Viertelbogen einschreibt. Das reicht (bei nur einem BRAM) für einen sehr 
guten DDS-Sinus.

Für die Abbildung solcher Spezialkorrekturfunktionen wo sich mehrere 
Effekte addieren, ist es ansonsten eher lohnend auf Approximation zu 
setzen und mit stückweisen, diskreten Annäherungen zu arbeiten.

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.