Hallo zusammen,
ich habe einen Sensor, dessen 1bit Dateneingang ich seriell eintakte. Je
nachdem, ob der Eingang 1 oder 0 ist, werden verschiedene Summen A1/A2
und B1/B2 gebildet, die positiv, aber auch negativ sein können. Diese
sollen dann in der folgenden Formel verrechnet werden (siehe Bild,
leider weiß ich nicht, wie man den Formeleditor hier bedient). Das
Ergebnis soll 16bit haben.
Ich habe versucht die Formel so umzuformen, dass möglichst viele 2er
Potenzen vorhanden sind. Dennoch bin ich nun mit meinem Latein am Ende.
Den Ausdruck in der eckigen Klammer würde ich mithilfe von Variablen in
einem Prozess berechnen.
- Dazu habe ich die 16bit Werte A1/A2 und B1/B2 um ein 17. Bit
erweitert, für das "Vorzeichen" (16 DOWNTO 0)
- Die Summe beider Werte A1/A2 und B1/B2 muss ich ja nochmal um ein Bit
erweitern. (17 DOWNTO 0)
- Um die *2 hinzubekommen, habe ich zusätzlich zum Additionsbit noch ein
weiteres Bit hinzugefügt (19 DOWNTO 0).
1
SIGNALs_a1:signed(16DOWNTO0);
2
SIGNALs_a2:signed(16DOWNTO0);
3
SIGNALs_b1:signed(16DOWNTO0);
4
SIGNALs_b2:signed(16DOWNTO0);
5
...
6
7
calc:PROCESS(CLK,NRES)
8
variablev_a_block:signed(17DOWNTO0);
9
variablev_b_block:signed(17DOWNTO0);
10
variablev_sum:signed(19DOWNTO0);
11
variablev_shift:signed(35DOWNTO0);
12
variablev_ergebnis:signed(35DOWNTO0);
13
BEGIN
14
IF(NRES='0')THEN
15
s_sensor_vaue<=(OTHERS=>'0');
16
----- FALLING EGDE!!! ------
17
ELSIFfalling_edge(CLK)THEN
18
v_a_block:=s_a1+s_a2;
19
v_b_block:=s_b1+s_b2;
20
v_sum:=('0'&v_a_block)+(v_b_block&'0');
21
ENDIF;
22
ENDPROCESScalc;
In v_sum sollte nun die eckige Klammer stehen.
Nun kommt die Formel aus der analogen Welt, so dass das 1/2^16 sich
nicht so einfach abbilfen lässt. Das ist ja ein extrem kleiner Wert, so
dass ich den mit x Stellen nach dem Komma darstellen muss, um dann die
v_sum damit zu multiplizieren.
2^16 wäre ja eine einfach shift Operation. Damit mir aber keine
Informationen verloren gehen, muss ich den Vektor entsprechend
erweitern.
1
v_shift:="0000000000000000"&v_sum;
Dann müsste ich das einfach von 2^15 abziehen, erweitert um die
Nachkommastellen.
1
v_ergebnis:=x"800000000"-v_shift;
- Ist mein Gedankenansatz so korrekt?
- Wie kann ich aber nun mit der 2^16-1 umgehen, was ja an sich keine
Shiftoperation mehr ist?
- Habe ich den signed Typ korrekt verwendet?
- Sind meine Gedanken zu den Vorzeichenbits und die ständigen
Bit-Erweiterungen incl. der Nachkommastellen korrekt?
- Wo muss ich nun aus v_ergebnis "herausschneiden"?
Ich muss nochmal die Theorie zu dieser Formel erfragen, der Kommilitone
ist leider gerade im Urlaub, so dass ich erstmal nur stupide rechnen
kann, ohne zu wissen, was genau ich da rechne. Es müsste eine Art
Mittelwertbildung sein.
Vielen Dank! :)
Ich würde das ganze erstmal mit 2^16-1 durchmultiplizieren und dann den
rechten Teil der Gleichung mit genügender Bitbreite rechnen (sieht nach
32bit aus). Am Schluss multiplizierst Du das Ergbnis mit der
vorberechneten Konstanten 1/(2^16-1). Damit bekommst Du die
Rundungsfehler erst ganz am Schluss rein. Um eine Multiplikation kommst
Du nicht herum, wenn des wirklich 2^16-1 sein muss, aber
Konstantenmultiplier sind nicht so wild. Geht es um einen FPGA? Um
welchen?
Wegen der größeren Bitbreiten wäre es sinnvoll, das ganze zu pipelinen.
Und numeric_std hat Funktionen zum resizen von Bitvektoren, siehe hier:
http://www.synthworks.com/papers/vhdl_math_tricks_mapld_2003.pdf.
Ich kann so keinen Fehler erkenennen, aber der Simulator in meinem Kopf
ist etwas unzuverlässig :-)
Wenn möglich, solltest Du einen synchronen Reset verwenden statt einen
asynchronen, aber das hat auf die Arithemtik keine Auswirkungen.
Calc schrieb:> leider weiß ich nicht, wie man den Formeleditor hier bedient
Stichwort: LaTeX
> Diese sollen dann in der folgenden Formel verrechnet werden
Ich glaube fast, die "-1" ist falsch, die erinnert mich sehr an die
Berechnung der Spannung aus einem ADC-Wert. Und dort werden dann auch
die Formeln mit 255, 1023, 2047, 4095... gern genommen, sind aber
falsch.
Was soll mit dieser Formel erreicht werden?
Hallo,
Vancouver schrieb:> Am Schluss multiplizierst Du das Ergbnis mit der> vorberechneten Konstanten 1/(2^16-1).
Mit einer vorgerechneten Kontante multiplizieren ist eine gute Idee!
Vancouver schrieb:> siehe hier:> http://www.synthworks.com/papers/vhdl_math_tricks_mapld_2003.pdf.
Vielen Dank für den Link. Nicht viel neues dabei, wenn man das hier
bereits kennt:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std
Aber doch nochmal eine gute Übersicht....
Lothar M. schrieb:> Was soll mit dieser Formel erreicht werden?
Der Ausgabewert bzw. der Wert eines Sensors, basierend auf den aus dem
Eingangssignal gebildeten Summen. Das Eingangssignal wird wohl durch die
Messgröße beeinflusst. Je nach Messgröße vergrößern oder verkleinern
sich die Summen und am Ende findet eine Art Mittelwertbildung statt,
denn es werden zwei "Messungen" gemittelt.
Ich habe noch keine Infos, auf welcher Basis diese Formel entstanden
ist. Ich habe nur die Aufgabe bekommen, das in Hardware zu rechnen. Dann
hat sich der Kommilitone in den Ski-Urlaub verabschiedet.
Lothar M. schrieb:> Ich glaube fast, die "-1" ist falsch, die erinnert mich sehr an die> Berechnung der Spannung aus einem ADC-Wert. Und dort werden dann auch> die Formeln mit 255, 1023, 2047, 4095... gern genommen, sind aber> falsch.
Das kann ich dem Kollegen nochmal als Hinweis geben, vielleicht
vereinfacht sich dadurch alles etwas, sollte er diesen Fehler gemacht
haben.
Vielen Dank!
Calc schrieb:> Vielen Dank für den Link. Nicht viel neues dabei, wenn man das hier> bereits kennt:
War der falsche Link, sorry. Ich meinte das Fixedpoint-Package
http://www.vhdl.org/fphdl/Fixed_ug.pdf,falls Du das verwenden willst.
Aber ich weiß nicht ob sich das lohnt für die eine Multiplikation.
Bist Du sicher, dass die Formel in der zitieren Form stimmt?
Kleine Überschlagsrechnung: wenn Deine A0/A1 und B0/B1 Werte ohne
Vorzeichen 16 Bit Breite haben, dann kann deren Summe maximal auf
(unsigned) 65535*6 (=393210) anwachsen, dieser Wert passt in 19 Bit.
Wenn Du dieses Zwischenergebnis durch (2^16 -1, d.h. 16 Bit) teilst,
bleiben 3 MSB übrig - die von einem 15 bit Wert (32768) abgezogen bzw.
dazu (negativer Wert) addiert werden sollen!???
Das Ergebnis wäre ein 3-Bit Rauschen auf einem 15-Bit Offset. Scheint
mir so keinen Sinn zu ergeben.
Ich möchte wetten, dass der Nenner sich komplett über den Term
erstrecken sollte. So ist das Murks. Und das was Lothar andeutet, könnte
auch noch Thema sein.
Ich habe nochmal die Unterlagen durchgeschaut.
s_a1 wird pro Schritt immer +1 oder -1 gerechnet.
s_a2 wird immer s_a1 + s_a2 gerechnet.
Es werden maximal 2^16 Schritte gerechnet.
s_a1 hat also maximal 17 bit (65536), mit Vorzeichen also 18 bit = 17
DOWNTO 0.
s_a2 hat also maximal 31 bit (2147450880), mit Vorzeichen als 32 bit =
31 DOWNTO 0
Wenn ich beide Summen nun zusammen addieren will.
Das Bit 17 und das Bit 31 sind ja jeweils die Vorzeichenbits.
Muss ich dann also alles so rechnen, damit ich die Vorzeichen korrekt
verrechne?
Calc schrieb:> damit ich die Vorzeichen korrekt verrechne?
Das sa(17) ist nicht DAS VorzeichenBIT.
Calc schrieb:> Das Bit 17 und das Bit 31 sind ja jeweils die Vorzeichenbits.
Solche einzelnen(!) Vorzeichenbits gibt es nicht in der allgemein
verwendeten Zweierkomplementdarstellung. Das hatten wir doch vor kurzem
schon mal...
Ah, ja, hier im Beitrag "signed Vektoren unterschiedlicher Breite korrekt addieren". Erinnerst
du dich? Was hast du da nicht verstanden?
Wenn du es dir unbedingt selber machen willst, dann muss es für eine
korrekte Vorzeichenerweiterung so aussehen:
Ich habe jetzt auf die Schnelle nicht gefunden, welches FPGA benutzt
wird.
Es macht aber sicher Sinn, auch mal die Nase ins Handbuch zu stecken, ob
spezielle Hardware für die Multiplikation zur Verfügung steht und wie
man die Synthese dazu bringt, die auch zu benutzen.
17 Bit breite Vektoren beispielsweise werden wahrscheinlich eher nicht
unterstützt...
Markus F. schrieb:> Ich habe jetzt auf die Schnelle nicht gefunden, welches FPGA benutzt> wird.>> Es macht aber sicher Sinn, auch mal die Nase ins Handbuch zu stecken, ob> spezielle Hardware für die Multiplikation zur Verfügung steht und wie> man die Synthese dazu bringt, die auch zu benutzen.>> 17 Bit breite Vektoren beispielsweise werden wahrscheinlich eher nicht> unterstützt...
Oh doch, das funktioniert ganz gut. Quartus z.B. verwendet bei
Multiplikationen automatisch die passende Hardware (in Grenzen). Ein
Blick ins Handbuch bzw. eigene Experimente schaden aber auf keinen Fall.
Zumindest wenn man die Hardware optimal ausnutzen will. Signed-Zahlen im
Format 1+17 Bit wären z.B. optimal für Altera FPGAs: dort werden dann
z.B. 9 Bit Multiplikatoren kaskadiert.
Auf jeden Fall sollte das gründlich simuliert werden. Bei neueren
Versionen von Modelsim ist es sehr hilfreich wenn man sich für die
Anzeige der Festkommazahlen einen passenden benutzerdefinierten "Global
Signal Radix" definiert.
Allerdings scheint die Formel fehlerhaft zu sein. Wenn das Endergebnis
16 Bit haben soll ist eine Division durch 2^16-1 ziemlich sinnfrei...
> Wenn das Endergebnis 16 Bit haben soll ist eine Division durch 2^16-1> ziemlich sinnfrei...
Sein Kollege scheint wohl durch 2^(16-1) Teilen zu wollen um ne Zahl
zwischen -1 und +1 zubekommen, was natürlich vollkommen sinnfrei ist,
denn man kann die Zahl ja einfach genauso interpretieren ohne durch
irgendetwas zu Teilen (Fixedpoint interpretiert).