Hallo,
irgendwie steh ich auf dem Schlauch. Ich kriege von einem bipolaren AD
zwei 12 Bit Werte, welche ich mir als zweierkomplement oder als straight
binary (0 bis 4095) ausgeben kann. Diese liegen mir dann als
std_logic_vector vor, welche ich dann entsprechend in signed oder
unsigned casten kann oder muss ich noch was beachten?
zweierkomplement wäre ja signed und straight binary unsigned oder?
Mach ich das am besten mit den Werten als Zweierkomplement oder mit dem
straight binary?
Später muss ich das Ergebnis dividieren, so das der Quotient immer
zwischen -1 und 1 liegt. Dafür wollt ich den IP-Core von Lothar Miller
verwenden.
http://www.lothar-miller.de/s9y/archives/29-Division-in-VHDL.html
oder hat da jemand eine andere Idee, weil mein Quotient ja nicht größer
als 1 wird?!
Danke für eure hilfe :-)
Marc K. schrieb:> Mach ich das am besten mit den Werten als Zweierkomplement
Eher ja. Denn sonst hast du nur positive Werte und musst selber noch den
Offset abziehen...
> Später muss ich das Ergebnis dividieren, so das der Quotient immer> zwischen -1 und 1 liegt.
Wie willst du denn diesen Zahlenbereich darstellen?
> oder hat da jemand eine andere Idee, weil mein Quotient ja nicht größer> als 1 wird?!Denk dir einfach das Komma vor das MSB.
Dann hast du eine Zahl von -1...+0.999, und das ganz ohne Rechnen...
:-o
ok vielen dank. Ich werde es mit dem Zweierkomplement machen :-)
Lothar Miller schrieb:> Wie willst du denn diesen Zahlenbereich darstellen?
Das hab ich mich auch gefragt. Ich weiß noch nicht so recht wie ich das
realisieren soll.
Lothar Miller schrieb:> Denk dir einfach das Komma vor das MSB.>> Dann hast du eine Zahl von -1...+0.999, und das ganz ohne Rechnen...>> :-o
Ich muss die Divison aber durchführen, der Divisor ändert sich immer so
das halt keine größere Zahl als 1 rauskommt. Mich interessiert
eigentlich nur das vorzeichen und paar Nachkommastellen.
Marc K. schrieb:> Ich muss die Divison aber durchführen,
Warum?
> keine größere Zahl als 1 rauskommt.
Nach wie vor die Frage: wie willst du mit Integerzahlen eine Zahl
kleiner 1 darstellen?
Weiterhin meine Antwort: denk dir einfach ein "Null Komma" vor die 12
Bit. Dann hat das führende Bit (links) die Wertigkeit 1/2, das nächste
1/4, dann 1/8, 1/16, usw. Je weiter du nach rechts kommst, umso weniger
ist ein Bit wert. Genau so, wie du es von gewöhnlichen Integerzahlen
gewöhnt bist.
So wird das bei Signalprozessoren, die mit Festkommazahlen rechnen, auch
gern gemacht. Und dafür gibt es massenweise Literatur.
Lothar Miller schrieb:> Marc K. schrieb:>>> Ich muss die Divison aber durchführen,>> Warum?
Da sich mein Dividend und Divisor unabhängig ändert. Ich jedoch weiß das
nur der bereich (-1 bis 1) rauskommen kann. Sonst ist ein fehler im AD
Wert. Ich weiß auch das dies mit Integer nicht möglich ist...
ich werd mich erstmal einlesen und vermutlich löst sich das Problem. ich
dachte nur vielleicht gehts auch ganz einfach :-)
vielen dank für die antwort :-)
Du hast doch für beide einen Skalierungsfaktor drin. Z.B. wird die 1
immer als 32768 dargstellt. Das betrifft dann Zähler und Nenner.
Rauskommen "tut" dann bei einer Division (egal ob mit core oder manuell)
immer einen Bitfolge, die du nur zu interpretieren brauchst. Also: Bit
einsammeln und für jeden shift nach links, den Du zusätzlich machst,
musst du hinterher einen "weginterpretieren".
Bei einem core kannst Du so teilen, dass vorne die 1 rauskommt und dann
sofort den Rest weiterverarbeiten, indem du nochmal teilst. Oder, Du
multiplizierst = schiebst den Zähler so weit nach links, dass Du genug
Stellen rausbekommst.
Beispiel:
Zählerwert = Z, Nennerwert = N, mit -N < Z < +N;
Digitale Darstellung:
ZD = 32768 x Z = -32768*Z < ZD < 32767*Z
Wenn Z aus z.B: einem ADC stammt und selber schon 15 Bit hat, hast du
eben rund 30Bit+Signum. Dann könntest Du reduzieren.
Gehen wir also davon aus, dass wir 31 Bit im Zähler haben und 31 im
Nenner.
Du rechnest dann einfach ZD & "00000000" / ND und heraus kommt eine
Zahl mit 8 Stellen vor dem Komma. Den Rest, den der Core auswirft,
kannst Du dann verwerfen. Der teil der Schaltung wird dann auch nicht
synthetisiert. Habe das bei Altera exzessiv durchgecheckt.
ok danke. Ich bin gerade noch am umstrukturieren, aber hab ich das
jetzt richtig verstanden. Ich erweitere die Zähler und Nenner so
Divisor <= "000000000000" & std_logic_vector(Nenner);
Dividend <= std_logic_vector(Zaehler) & "000000000000";
Marc K. schrieb:> Divisor <= "000000000000" & std_logic_vector(Nenner);
Den Divisor würde ich gar nicht erweitert. Bläht nur den Divider auf,
der dann wieder reduziert wird, wenn die Synthese die vielen Nullen
sieht.
ich nutzte ein FPGA von Microsemi und ich habe dort bezüglich der
division nachgefragt. Diese meinten man kann es einfach mit "/"
implementieren. Wie es aussieht funktioniert es auch :-/
Marc K. schrieb:> Diese meinten man kann es einfach mit "/" implementieren.> Wie es aussieht funktioniert es auch :-/
Kann Altera auch.
Aber sieh mal nach, wie es mit dem Ressourcenverbrauch aussieht.
Was kostet dich eine 32/16 Division, die in 1 Takt fertig ist?
Lothar Miller schrieb:> Marc K. schrieb:>> Diese meinten man kann es einfach mit "/" implementieren.>> Wie es aussieht funktioniert es auch :-/> Kann Altera auch.> Aber sieh mal nach, wie es mit dem Ressourcenverbrauch aussieht.> Was kostet dich eine 32/16 Division, die in 1 Takt fertig ist?
Das sagt die synthese bei folgendem code:
Marc K. schrieb:> CORE Used: 151 Total: 38400 (0.39%)
Das sind vermutlich die Logic Cells.
Interessant wäre noch die Taktfrequenz. Dazu müsste man vorher und
hinterher noch ein Register dranpappen.
Duke
Marc K. schrieb:> Wolltest du das wissen?
Jein...
Einen Divider für 6 Bit kann ich in ein BRAM packen...
Ich wollte das eigentlich für 32/16 Bits wissen:
1
:
2
zahl_32:INstd_logic_vector(31downto0);
3
zahl_16:INstd_logic_vector(16downto0)
4
:
Und auch: Wie schnell kannst du dieses Design takten?
Lothar Miller schrieb:> Marc K. schrieb:>> Wolltest du das wissen?> Jein...> Einen Divider für 6 Bit kann ich in ein BRAM packen...>> Ich wollte das eigentlich für 32/16 Bits wissen:>
Lothar Miller schrieb:
> Marc K. schrieb:>> Wolltest du das wissen?> Jein...> Einen Divider für 6 Bit kann ich in ein BRAM packen...>> Ich wollte das eigentlich für 32/16 Bits wissen:>> :> zahl_32 : IN std_logic_vector(31 downto 0);> zahl_16 : IN std_logic_vector(16 downto 0)> :>
CORE Used: 1799 Total: 38400 (4.68%)
IO (W/ clocks) Used: 81 Total: 147 (55.10%)
Differential IO Used: 0 Total: 65 (0.00%)
> Und auch: Wie schnell kannst du dieses Design takten?
Wo seh ich das?
Marc K. schrieb:> zahl_32 : IN std_logic_vector(5 downto 0);> zahl_16 : IN std_logic_vector(5 downto 0)> CORE Used: 151 Total: 38400 (0.39%)Marc K. schrieb:> zahl_32 : IN std_logic_vector(31 downto 0);> zahl_16 : IN std_logic_vector(15 downto 0)> CORE Used: 1799 Total: 38400 (4.68%)
Da wird tatsächlich ein kombinatorischer Divider gebaut.
>> Und auch: Wie schnell kannst du dieses Design takten?> Wo seh ich das?
Das ist eine wichtige Zahl, die solltest du mit einem Blick erkennen
können. Such mal im Synthese- oder Implementation-Report nach MHz.
>>> Und auch: Wie schnell kannst du dieses Design takten?>> Wo seh ich das?> Das ist eine wichtige Zahl, die solltest du mit einem Blick erkennen> können. Such mal im Synthese- oder Implementation-Report nach MHz.
Alles was ich mit MHz im Report gefunden habe.
Lothar Miller schrieb:> Da wird tatsächlich ein kombinatorischer Divider gebaut.
Klaro und wenn man dem genug FF-stages hinten dran packt, kann die
Synthese ihn per register retiming auch auf das jeweils benötigte Tempo
bringen.
Bei Actel FPGAs würde ich da nicht zuviel erwarten bezüglich
Taktfrequenz. Deren Architecktur ist nicht auf solche Rechenschaltungen
optimiert. Ich kann es hier ja auch mal fix bauen und nachprüfen, haben
die Toolchain auch am Start.
T. M. schrieb:> Also Synplify Pro 9.0.2A2 kann diese Division nicht synthetisieren. Er> möchte gern nur durch 2^n teilen.
Ich nutzte Synplify Pro AE F-2012.03MSP1. Da gehts.
Das ganze nochmal für einen MachXO2 (LCMXO2-4000HE Speedgrade 6)
Spannend ist der Unterschied zwischen der neuen Lattice Synthese Engine
(LSE) und Synplify Pro
LSE:
Mit dem LSE werden viel weniger Resourcen gebraucht, es ist obendrein
noch schneller obwohl der kritische Pfad über fast 3 mal so viele
Logikebenen geht.
Du solltest am Eingang UND Ausgang mindestens 2, besser 3 Register
haben, damit er
a) in die IO-FFs kommt
b) bequem zu jeder Resource kommt.
Damit ist sicher gestellt, dass das ausgerechnete Tempo wirklich das
Maximum ist, dass die Architektur in einer günstigen Umgebung kann.
Habe beispielhaft einen Divider mit 160 Stellen gemacht:
signed(Zaehler(79 downto 0) & Leerbits(79 downto 0)) / signed (Nenner(79
downto 0));
Er braucht nach 6 min Synthese >33.000 slices im Spartan3 und kommt auf
etwas über 1MHz :-)
Nach Optimierung durch Trans & MAP (insgesamt 49 min) braucht er 154.000
slices und schafft knapp 3 MHz
Da waren die alten DX33-Copros schon schneller :-)
Gibt es eigentlich CoProzessor-Chips als fertige ASICs?
Sowas liesse sich doch an einen FPGA anschliessen, die könnten dann
DIV/LOG/SQR berechnen.
> Gibt es eigentlich CoProzessor-Chips als fertige ASICs?
Nimm nen Fließkomma DSP z.B. C6000 mit PCIe Interface und verbinde den
mit nem V6 oder V7. Oder über Serdes.
Uwe schrieb:>> Gibt es eigentlich CoProzessor-Chips als fertige ASICs?>> Klar nennt sich FPU 80387 für x86 und MC68882.
War schon klar, dass SO ein link kommt :-)
Uwe schrieb:> Nimm nen Fließkomma DSP z.B. C6000> SERDES
Ist wieder mit Flaschenhals. Ein ASIC könnte mit jedem Takt ein Datum
berechnen.
Spartanist schrieb:> Ist wieder mit Flaschenhals. Ein ASIC könnte mit jedem Takt ein Datum> berechnen.
Das kannst du mit einem Kern im FPGA auch, und noch dazu vergleichsweise
ressourcenschonend.
Tradeoff ist dann halt die Latenz. Zwar jeden Tankt ein Datum, aber
nicht sofort am Ausgang.
Spartanist schrieb:> Lothar Miller schrieb:>> Da wird tatsächlich ein kombinatorischer Divider gebaut.> Klaro und wenn man dem genug FF-stages hinten dran packt, kann die> Synthese ihn per register retiming auch auf das jeweils benötigte Tempo> bringen.
Das ist aber immer langsamer als ein nicht aufgeteilter Pfad und dazu
ein Multicycle Constraint, weil ja für jedes FF noch die Setup-Zeit
dazukommt...
Lothar Miller schrieb:> Das ist aber immer langsamer als ein nicht aufgeteilter Pfad und dazu> ein Multicycle Constraint,
Nun, dieses gilt ja generell: Sobald Speicher hinzutreten, wird der
Zeitpfad länger, aber oft benötigt man die pipelinefähige Schaltung, um
bei jedem Takt Daten einspeisen zu können.
Doch, natürlich - unser Beispiel schon.. Oben die Kombinatorik hat 0,x
Takte und benutzt damit einen Takt. Einen, der langsam genug ist. Eine
beschleunigte Architektur braucht dann mehr Takte, nämlich die, die man
künstlich angehängt hat und wird Dank balancing schneller.
Sie ist dann immer noch pipelinefähig.
Du hast natürlich dann Recht, wenn eine nicht gepipelinte Architektur
mit FFs nachversorgt wird.
Michael schrieb:> Sie ist dann immer noch pipelinefähig.
Da wage ich mal vorsichtig zu widersprechen...
Wenn du eine <10MHz Logik durch Zugabe von Registern und anpassen der
Constraints auf ~100MHz hochzwiebelst ist das mitnichten pipelined.
Pipelined wuerde bedeuten, dass du jeden 100MHz Takt neue Daten in die
Stufe reinfuetterst und dass nach ~10 Zyklen dann das jeweilige Ergebnis
rausfaellt.
Wenn du das ganze pipelined machen willst musst du schon eine adequate
FSM schreiben die in jeder pipeline-Stufe eben auch die Daten
entsprechend auf die naechste Stufe verteilt. Das ist dann aber
Design/Handarbeit