Hallo zusammen, ich habe einen 8bit ADC, der ein Sinussignal digitalisiert. Nun möchte ich dieses Sinussignal digital quadrieren. Ich habe also angefangen und habe einen sequentiellen Multiplizierer gebaut und als ich fertig war ist mir etwas aufgefallen, woran ich nun etwas verzweifle. Der ADC gibt Werte von 0 bis 256 aus. Dabei fallen 128 Werte auf die positive Halbwelle und 128 Werte auf die negative Halbwelle. 0 => 127 negative Werte 127 => 255 positive Werte Nun hatte ich die Idee, einfach das oberste Bit als Vorzeichenbit zu interpretieren, dadurch die negative Halbwelle einfach nach oben zu kippen und dann die verbleibenden 7 bit zu quadrieren. Aber das geht leider nicht, da nach dem Nulldurchgang die nächste Stelle 0111.1111 ist und nicht 0000.0001. So war diese Idee hinfällig. Nun stehe ich etwas auf dem Schlauch und habe keine Idee, wie ich das in VHDL umsetzen kann. Hat jemand dazu eine Idee bzw. kann helfen? Vielen Dank! Michael
Michael schrieb: > Ich habe also angefangen und habe einen sequentiellen Multiplizierer > gebaut Warum selber bauen? In VHDL sieht eine Multiplikation so aus: y <= a*b; Und die Quadratur mithin y <= a*a; > 0 => 127 negative Werte > 127 => 255 positive Werte 127 ist also mal positiv und mal negativ? > Nun hatte ich die Idee, einfach das oberste Bit als Vorzeichenbit zu > interpretieren Ich würde einfach signed rechnen (macht ja Sinn mit einem negativen Wert), und vorher einen Wert von 127 (müssen das nicht 128 sein?) vom ADC-Wert abziehen...
> Nun möchte ich dieses Sinussignal digital quadrieren.
Wenn es nicht mehr als 8-10 Bit werden, passt der ganze Kram doch bequem
in eine Lookup-Table rein. Bei Xilinx-FPGAs zB. in ein BRAM. Braucht
keine Logik und ist auch noch schneller (fertig) als so ein
Multiplizierer ohne dedizierte Logik (DSP/MUL-Blöcke).
Hallo, Lothar Miller schrieb: > 127 ist also mal positiv und mal negativ? Das war ein Fehler meinerseits, die 128 der erste positive Wert. Georg A. schrieb: > Wenn es nicht mehr als 8-10 Bit werden Die Sache könnte später auch auf 10 oder gar 12bit ausgebaut werden. Eine LUT ist also weniger ratsam. Lothar Miller schrieb: > Warum selber bauen? In VHDL sieht eine Multiplikation so aus: Ich habe einen generic eingefügt, der mir erlaubt anzugeben, wieviele Additionen pro Takt ausgeführt werden. Damit steigt zwar der Platzbedarf, aber ich bin später nicht darauf angewiesen, dass die Multiplikation immer so viele Takte wie Bits benötigt und ich kann bei freien Ressourcen auch alles mit einem Takt abhandeln. Lothar Miller schrieb: > Ich würde einfach signed rechnen Ich habe mich bisher immer erfolgreich gedrückt, wenn es um das Rechnen mit signed ging. Das Vorzeichenbit hat mich immer verwirrt, aber vielleicht ist es auch nur halb so wild. Aber nun werde ich wohl nicht drum herum kommen. Also konvertiere ich die ADC-Werte durch Subtraktion mit 128 in signed... ok, muss ich mich belesen, wie das genau funktioniert und korrekt ist. Wie würdest Du das berechnen?
1 | adc_wert_sgn(8 downto 0) <= unsigned(adc_wert); |
2 | adc_wert_scale <= adc_wert_sgn - 128; |
oder mache ich einfach eine signed-Extension vom adc_wert und subtrahiere dann 128?
1 | adc_wert_sgn(8 downto 0) <= sxt(adc_wert); |
2 | |
3 | adc_wert_sgn(8 downto 0) <= adc_wert(adc_wert'HIGH) & adc_wert; |
Vielen Dank! Michael
Michael schrieb: > dass die Multiplikation immer so viele Takte wie Bits benötigt In einem halbwegs aktuellen FPGA braucht die komplette Multiplikation genau 1 Takt, denn da gibt es ja jede Menge Multiplizierer.... Michael schrieb: > Also konvertiere ich die ADC-Werte durch Subtraktion mit 128 in > signed... ok, muss ich mich belesen, wie das genau funktioniert und > korrekt ist. > Wie würdest Du das berechnen? So ginge das:
1 | port (... |
2 | x : in std_logic_vector(7 downto 0); |
3 | y : out std_logic_vector(7 downto 0); |
4 | ...
|
5 | );
|
6 | |
7 | :
|
8 | |
9 | signal u : unsigned (7 downto 0); |
10 | signal s : signed (7 downto 0); |
11 | |
12 | :
|
13 | |
14 | u <= unsigned(x); |
15 | s <= signed(u-to_unsigned(128,8)); |
16 | y <= std_logic_vector(s); |
Aber (hmhm... räusper...) das Invertieren des MSB macht das selbe... ;-) (siehe die unteren beiden Zeilen im Screenshot der Simulation)
Vielen Dank! Nun habe ich zwei signed-Werte und muss diese mit meinem Multiplizierer vereinen, der auf std_logic_vector ausgelegt ist. Ich habe schon gewusst, wieso ich bisher immer behaarlich signed-Berechnungen umgangen habe. :-) Aber nun komme ich wohl nicht umhin, es mal damit zu versuchen. Oder komme ich mit dem not(MSB) doch wieder drum herum, weil ich bei std_logic_vector bleiben kann. Ich finde diesen signed-Datentyp immer noch höchst umständlich, weil man nie sicher sein kann, wie dieser Wert nun interpretiert werden kann. Kann ich denn signed einfach so quadrieren und bekomme dann auch ein richtiges Ergebnis? Ich muss mich mit signed noch vertraut machen, ob es wirklich nur ein std_logic_vector mit einem MSB mehr ist, was das Vorzeichen vorgibt. Vielen Dank! Micha
Michael schrieb: > std_logic_vector bleiben kann. Ich finde diesen signed-Datentyp immer > noch höchst umständlich, weil man nie sicher sein kann, wie dieser Wert > nun interpretiert werden kann. Genau anders herum ist es doch. Ein Vektor kann alles darstellen und der Nutzer muss sich um die Interpretation kümmern. > Kann ich denn signed einfach so quadrieren und bekomme dann auch ein > richtiges Ergebnis? Na klar. Einfach Signed * Signed. Das Ergebnis ist dann zunächst mal doppelt so breit und kann wieder nach std_logic_vector zurück gecastet werden. Was ist daran kompliziert? Das sinnlose höchste Bit nach der Quadrierung kannst du ja dann mit resize wieder wegmachen. Ich weiß nicht, ob der Synthesizer erkennt, ob das Ergebnis ein Bit weniger braucht. Bei einer normalen Mul sagt er dir sogar (im Gegensatz zur Addition) wenn die Bitbreiten nicht stimmen. Das Offset sollte so am einfachsten klappen: adc_wert_scale <= signed(unsigned(adc_wert) - to_unsigned(128, 8));
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.