Forum: FPGA, VHDL & Co. Sinuserzeugung in VHDL


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Emtec (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe Forenuser,


Ich habe eine Aufgabe in der ich einen Sinusgenerator über ein 
instabiles Filter mit der folgenden Formel in VHDL erzeugen muss.

y(n)=b0 * x(n) + b1 * x(n-1) - a1 * y(n-1) - y(n-2)

b0=sin(phi)
b1=sin(OMEGA0-phi)
a1=-2*cos(OMEGA0)

Bsp: phi = pi/4
     OMEGA0=pi/8

Meine Frage bezieht sich nur auf b0, also:
b0=sin(phi)

Ich weiß ich kann einen Sinus über eine Taylorreihe realisieren.
Aber wie soll ich das machen wenn der Datentyp Real (Floating Datentyp) 
NICHT synthetisierbar ist?
Was gäbe es noch für alternativen?

Ich wäre euch für JEDE Hilfe wirklich sehr dankbar.

lg Emtec

von Auskenner (Gast)


Bewertung
0 lesenswert
nicht lesenswert

von Schlaubi-Schlumpf (Gast)


Bewertung
0 lesenswert
nicht lesenswert

von Emtec (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Auskenner schrieb:
> http://de.wikipedia.org/wiki/Digital_Signal_Synthesis


Ich muss den Ausgang von dem Board Pulsbreitenmoduliert über einen DAC 
in eine äquivalente Ausgangsspannung umwandeln.
Es soll alles Digital erzeugt werden ohne eine externe 
Oszillatorschaltung.
Trotzdem danke für die Antwort.

von berndl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mei, du hast doch bestimmt RAMs auf deinem Baustein. Bau halt einfach 
eine Sinus LUT von 0 bis knapp 90 Grad...

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Emtec schrieb:
> Ich habe eine Aufgabe in der ich einen Sinusgenerator über ein
> instabiles Filter mit der folgenden Formel in VHDL erzeugen muss.
Warum?
Wenn unbedingt ein Sinus nötig ist, und eine Tabelle für die Genauigkeit 
nicht reicht, dann such mal nach Cordic...

> Was gäbe es noch für alternativen?
http://www.lothar-miller.de/s9y/categories/31-DDFS

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Emtec schrieb:
> Ich muss den Ausgang von dem Board Pulsbreitenmoduliert über einen DAC
> in eine äquivalente Ausgangsspannung umwandeln.
Gibts da auch Namen für die beteiligten Komponenten?
Welche Genauigkeit?
Welche Frequenzen?

Ich hätte noch den Beitrag "Re: PWM Signal erzeugen"

von Emtec (Gast)


Bewertung
0 lesenswert
nicht lesenswert
berndl schrieb:
> Mei, du hast doch bestimmt RAMs auf deinem Baustein. Bau halt einfach
> eine Sinus LUT von 0 bis knapp 90 Grad...

Ich entschuldige mich im voraus für meine Fragerei.
Ich bin noch Anfänger in dem ganzen...

Wie soll ich eine LUT machen?
Ich nehme an Du meinst ich nehme pro Abtastwert den zugehörigen y-Wert 
und schreibe den in einem Array, oder?
Dann lasse ich das oszillieren...
Aber wie soll ich die Werte in eine LUT schreiben wenn ich "Real" nicht 
benutzen darf?

@Lothar Miller

Lothar Miller schrieb:
> Emtec schrieb:
> Gibts da auch Namen für die beteiligten Komponenten?
> Welche Genauigkeit?
> Welche Frequenzen?
>
> Ich hätte noch den Beitrag "Re: PWM Signal erzeugen"

Danke für die Links.
Die Genauigkeit weiß ich auch noch nicht, die Aufgabestellung ist noch 
nicht vollständig :-(

Es soll die Frequenz und die Phasenlage variabel eingestellt werden 
welche über Bushbuttons entprellt werden.
Die einzelnen Komponenten des Filters werden so dann verändert.
Der Filter ist Selbstoszillierend und braucht einen Eins-Impuls zur 
anregung.

Ich brauche nur eine teilweise annähernde Tayloraproximation für 
variable Werte die ich für das a1 brauche.

Danke schon mal für die Hilfe.

lg

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Emtec schrieb:
> Ich brauche nur eine teilweise annähernde Tayloraproximation
Reichen 8 Bit Auflösung?
Dann wärst du mit einer 90° Lookup-Tabelle am schnellsten fertig. Denn 
Rechnen in VHDL ist nicht unbedingt schön und einfach...

> Wie soll ich eine LUT machen?
Die legt dir der Synthesizer in ein Block-RAM ab. Deshalb musst du zur 
Laufzeit nichts berechnen, hast ein blitzschnelles und 
ressourcensparendes Design. Das ist aber in meiner DDFS ganz klar 
dargestellt...

von berndl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Emtec schrieb:
> Aber wie soll ich die Werte in eine LUT schreiben wenn ich "Real" nicht
> benutzen darf?

Du willst VHDL machen. Da gibt es kein 'Real'! Da gibt es nur xxx-bit 
breite Datenwoerter.
Wenn du also Werte zwischen 0 und <1.0 darstellen willst und z.B. 16bit 
zur Verfuegung hast, dann entspraeche 65536 halt genau 1.0. Mit 16bit 
erreichst du aber nur 65535...
Also einfach einen passenden Multiplikator erfinden...

von berndl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
berndl schrieb:
> Du willst VHDL machen. Da gibt es kein 'Real'!

ups, muss mich korrigieren. Natuerlich gibt es in VHDL auch 'Real'. Aber 
eben in Hardware nicht. Deshalb die Kruecke mit dem Multiplikator.
Such mal nach IEEE754 im Web, das ist das, was dein PC mit 
Floating-Point macht.
Und entschuldigen brauchst dich uebrigens auch nicht, fuer Fragen ist 
ein Forum ja schliesslich auch da...

von Michel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
berndl schrieb:
> Aber
>
> eben in Hardware nicht. D

Nichts, was es im VHDL gibt, gibt es auch in der Hardware. Auch kein INT 
und kein bitvektor. Ist alles Interpreation und muss zusammengebaut 
werden.

Und selbstverständlich kann man in VHDL REAL operationen formulieren und 
synthetisieren.

von Thomas R. (Firma: abaxor engineering) (abaxor)


Bewertung
0 lesenswert
nicht lesenswert
Emtec schrieb:
> y(n)=b0 * x(n) + b1 * x(n-1) - a1 * y(n-1) - y(n-2)

Das ist die Differenzengleichung für ein IIR-Filter und bei solchen sind 
Koeffizienten bx und ax normalerweise konstant.

Und was bei dir zu den Koeffizienten steht

> b0=sin(phi)
> b1=sin(OMEGA0-phi)
> a1=-2*cos(OMEGA0)

> Bsp: phi = pi/4
>      OMEGA0=pi/8

deutet auch darauf hin, dass deine Koeffizienten konstant sein sollen. 
Und tatsächlich kann man ein IIR-Filter dazu überreden Dauerschwingungen 
auszuführen, wenn es eben instabil ist. Geh noch mal in dich und versuch 
die Aufgabenstellung richtig zu verstehen. Am besten du implementierst 
diese Funktion mal mit Matlab o.ä., um überhaupt ein Gefühl zu bekommen 
was passieren soll.

Die Berechnung von Konstanten mittels Winkelfunktionen geht problemlos 
in VHDL auch für die Synthese.

Tom

von Robert K. (Firma: Medizintechnik) (robident)


Bewertung
0 lesenswert
nicht lesenswert
Eigentlich ist der Rückbezug auf Werte, die zwei Takte alt sind 
("y(n-2)"), nichts anderes, als eine DGL 2.Ordnung.

Schon von der Anschauung her kann/muss das schwingen.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Thomas Reinemann schrieb:
> Die Berechnung von Konstanten mittels Winkelfunktionen geht problemlos
> in VHDL auch für die Synthese.
Emtec schrieb:
> Es soll die Frequenz und die Phasenlage variabel eingestellt werden
> welche über Bushbuttons entprellt werden.
Soviel zum Thema "konstant"...

Michel schrieb:
> Und selbstverständlich kann man in VHDL REAL operationen formulieren und
> synthetisieren.
Hast du mal ein Beispiel?

von Thomas R. (Firma: abaxor engineering) (abaxor)


Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Thomas Reinemann schrieb:
>> Die Berechnung von Konstanten mittels Winkelfunktionen geht problemlos
>> in VHDL auch für die Synthese.
> Emtec schrieb:
>> Es soll die Frequenz und die Phasenlage variabel eingestellt werden
>> welche über Bushbuttons entprellt werden.
> Soviel zum Thema "konstant"...

Ok, ich gebe zu ich habe nur das Originalposting gelesen und da steht 
nichts vom Verstellen der Phase und Frequenz. Phase verstellen ohne 
Referenz wird aber schwer.

Tom

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Thomas Reinemann schrieb:
> Phase verstellen ohne Referenz wird aber schwer.
Wieso? Freie Auswahl.
0° ist genausogut wie 180°....

Das ist wie beim Italiener: wenn der nur Pizza "Vier Jahreszeiten" hat, 
dann ist ruckzuck bestellt. Wenn der aber noch 35 Varianten hat, dann 
dauert das eine Ewigkeit, bis man die Pizza "Vier Jahreszeiten" 
bestellt... ;-)

von Michel (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Das ist wie beim Italiener: wenn der nur Pizza "Vier Jahreszeiten" hat,
>
> dann ist ruckzuck bestellt. Wenn der aber noch 35 Varianten hat, dann
>
> dauert das eine Ewigkeit, bis man die Pizza "Vier Jahreszeiten"
>
> bestellt... ;-)

Auch beim dritten Lesen kapiere ich nicht, was du damit sagen willst ...

von Emtec (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke an euch allen für eure Hilfe.
Ich werde mein bestes versuchen und melde mich wieder wenn was nicht 
geht.
Tut mir leid für das späte schreiben, hatte viel zu tun :(

Euch allen noch einen lieben Gruß.

lg

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Michel schrieb:
> Auch beim dritten Lesen kapiere ich nicht, was du damit sagen willst ...
Ok, dann nochmal:
>> Phase verstellen ohne Referenz wird aber schwer.
> Das ist wie beim Italiener: wenn der nur Pizza "Vier Jahreszeiten" hat,
> dann ist ruckzuck bestellt. Wenn der aber noch 35 Varianten hat, dann
> dauert das eine Ewigkeit, bis man die Pizza "Vier Jahreszeiten"
> bestellt... ;-)
Wenn du keine Auswahl hast, dann nimmst du, was du bekommst. Das ist bei 
der Phase vermutlich 0°. Und wenn du die Auswahl von 0° bis 360° hast, 
dann kommst du nach einem langwierigen Entscheidungsprozess auch auf 0°.

Das wirst du noch oft sehen: wenn es in einer Besprechung 3 verschiedene 
Varianten gibt, die eigentlich alle gleich gut sind, dann dauert es eine 
Ewigkeit, bis man eine davon auswählt (weil und obwohl fast kein 
Unterschied im Ergebnis ist). Glücklich zu nennen ist also der, der 
keine Alternativen hat...

von Vladimir (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Glücklich zu nennen ist also der, der
>
> keine Alternativen hat...

Darum waren in der DDR ja alle so glücklich

nur eine Sorte von Autos, Obst, Parteien, Meinung

von noname (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Emtec schrieb:
> y(n)=b0 * x(n) + b1 * x(n-1) - a1 * y(n-1) - y(n-2)

> b0=sin(phi)
> b1=sin(OMEGA0-phi)
> a1=-2*cos(OMEGA0)

> Bsp: phi = pi/4 , OMEGA0=pi/8

Habe es mit Excel ausprobiert. Geht nicht.

Stimmt die Formel?

von Emtec (Gast)


Bewertung
0 lesenswert
nicht lesenswert
noname schrieb:
> Emtec schrieb:
>> y(n)=b0 * x(n) + b1 * x(n-1) - a1 * y(n-1) - y(n-2)
>
>> b0=sin(phi)
>> b1=sin(OMEGA0-phi)
>> a1=-2*cos(OMEGA0)
>
>> Bsp: phi = pi/4 , OMEGA0=pi/8
>
> Habe es mit Excel ausprobiert. Geht nicht.
>
> Stimmt die Formel?

Ja, sie stimmt.
Bei mir gehts :)

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Emtec schrieb:
> Bei mir gehts :)
Was geht?
Bei mir schwingt das Ding schon, aber es schaukelt sich innerhalb 
kürzester Zeit in Ekstase und macht insgesamt nichts sinnvolles. Von 
einem Sinus mit definierter Phase und Amplitude ist da weit&breit nichts 
zu sehen...

von Emtec (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi Lothar Miller,

Lothar Miller schrieb:
> Emtec schrieb:
>> Bei mir gehts :)
> Was geht?
> Bei mir schwingt das Ding schon, aber es schaukelt sich innerhalb
> kürzester Zeit in Ekstase und macht insgesamt nichts sinnvolles. Von
> einem Sinus mit definierter Phase und Amplitude ist da weit&breit nichts
> zu sehen...

Ich habe es bis zum Wert 40 in Excel Simuliert. Mit Matlab kenne ich 
mich nicht so gut aus...
Im Anhang habe ich ein Bild davon raufgeladen wie es mit einer 
Phasenverschiebung und Frequenz gehen könnte...

von Emtec (Gast)


Bewertung
0 lesenswert
nicht lesenswert
In meinem Fall habe ich Phi = PI/4 und Omega = PI/8 gewählt

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Ach blöd, ich habe nicht einen 10-Sprung, sondern einen 01-Sprung auf x 
reingelassen...

von noname (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Ach blöd, ich habe nicht einen 10-Sprung, sondern einen 01-Sprung auf x
>
> reingelassen...
???

Ich habe es probiert, bei mir schaukelt es sich auch auf.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
noname schrieb:
>> Ach blöd, ich habe nicht einen 10-Sprung, sondern einen 01-Sprung auf x
>> reingelassen...
> ???
Sieh dir die Werte für X in der Tabelle an.
Es ist immer x=0, nur für einen einzigen Takt ist x=1...

von Emtec (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> noname schrieb:
>>> Ach blöd, ich habe nicht einen 10-Sprung, sondern einen 01-Sprung auf x
>>> reingelassen...
>> ???
> Sieh dir die Werte für X in der Tabelle an.
> Es ist immer x=0, nur für einen einzigen Takt ist x=1...

Um dies zu ergänzen:
X ist kwasi nur einmal 1 zu Beginn, da dies nur zur Anregung dient.
Dieser instabile Digitale Filter braucht einen Dirac Impuls zu Beginn um 
zu oszillieren...

lg

von Jürgen S. (engineer) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Das kann man aber noch gehörig vereinfachen, indem man die Startwerte 
inklusive Startimpuls ausdrücklich vorgibt. Dann vereinfachen sich auch 
die Formeln.

Der Generator ist dann ganz gut, wenn man statische Freuquenzen erzeugen 
muss oder keine exakten Frequenzen braucht, da das update der 
COS/SIN-Kostrukte zu aufwändig ist. Da ist dann eine DDS einfacher.

von Mister LG (Gast)


Bewertung
0 lesenswert
nicht lesenswert
J. S. schrieb:
> das update der
> COS/SIN-Kostrukte zu aufwändig ist.
Die liessen sich in einer Tabelle halten, wenn man z.B. nur ein paar 
Töne erzeugen will. Mehr geht mit einem FPGA ohnehin nicht vernünftig.

von Jürgen S. (engineer) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Mister LG schrieb:
> Die liessen sich in einer Tabelle halten,
Dann kann ich auch gleich die Sinustabelle als solche in einer Tabelle 
halten und DDS machen.

Mister LG schrieb:
> Mehr geht mit einem FPGA ohnehin nicht vernünftig.
Man kann mit einigen einfachen IIR-Filtern sogar aus einem Rechteck 
einen passablen Sinus machen und die Tonhöhen modulieren, indem man die 
Phasen anpasst. Erst recht geht es mit einem interpolierten Wert aus 
einer Sinustabelle.

von Spartanist (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Emtec schrieb:
> Ich habe es bis zum Wert 40 in Excel Simuliert. Mit Matlab kenne ich
> mich nicht so gut aus...
Ist es möglich, dass die "Schwingung" nur für bestimmte Werte 
funktioniert, also z.B: nicht beliebig fein? Beim Rumprobieren 
(ebenfalls Excel) fiel mir auf, dass eine geringe Modifiaktion des 
a-Wertes nur die Amplitude ändert, nicht aber die Abstände. Bei 
grösserer Variation fällt die Schwingung dann plötzlich aus.

von F. S. (de0_board)


Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe User,

ich hab mich nun hier Registriert. Also ich bin der TE.

Ich habe das Projekt nach einer gewissen Zeit wieder aufgenommen und 
hänge da wieder an einem kleines Problem mit VHDL.

Also:

Ich möchte anhand einer Schalterstellung die Frequenz rauslesen.
Daraus erreiche ich mir dann das OMEGA = 2*PI*f/fs
Das Problem das ich habe ist, dass ich nicht weiß wie ich das auf einem 
1:7 Format realisieren soll.

Ich habe eine Funktion fraction_mult die 2 Zahlen miteinander 
multipliziert.
Jedoch dürfen die nicht über 1 drüber gehen da sie ja dann den 
Zahlenbereich überschreitet, also nicht größer als 0.1111111 (1:7).

Also ich wollte das OMEGA mit einer LUT realisieren. Ich schau kwasi in 
einer if Verkettung nach dem OMEGA wo ich für jede Schalterstellung ein 
geeignetes habe.
Gut, das hab ich.

Aber wie kann ich zB das b1 berechnen?

Das b1 setzt sich aus (-2)*cos(omega-phi) zusammen
Wenn ich phi 0 mache zur einfachheit halber, dann ergibt der cos von 
meinem Beispiel omega = 0,39269908 0,92. Noch realisierbar.
Aber dann muss er mit (-2) multipliziert werden. 2 allein ist ja schon 
auf einem 1:7 Format gar nicht darstellbar...

Ich soll in dem 1:7 Format beleiben, da ich immer damit rechne und eine 
Umrechnung das ganze komplizierter machen wird...

Weiß irgendwer wie ich das umgehen kann?
Ich tue mich schwer mit diesem Fraction Format.

Hoffe auf einen kleinen Tipp. Danke euch allen nochmal.

lg

von dose (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die kannst nur im binären Zahlenformat rechnen. (unter Umständen auch im 
oktalen oder hexadezimal Zahlenformat)

Du suchst nach einer Abbildung deines Formates). Leider kenne ich kein 
Zahlenformat 1:7.


Das ein bit kann auch gebrochenrationale Werte entsprechen.
1bit = 1/8pi

Wenn du nich auf oktal,binär, hex kommt dann musst due die Stellen 
erhöhen und eine Restfehler in der Umrechnung hinnehmen.
Das ist der typische Rechenfehler der Numerik.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
F. S. schrieb:
> Ich soll in dem 1:7 Format beleiben,
Sagt wer?
> da ich immer damit rechne und eine Umrechnung das ganze
> komplizierter machen wird...

Wie willst du halbwegs aufwendige vorzeichenbehaftete Arithmetik mit 8 
Bits schaffen können?

> dann ergibt der cos von meinem Beispiel omega = 0,39269908 0,92.
Wie rechnest du das um?
1:7 bedeutet doch: 1 Vorkommastelle, 7 Nachkommastellen (wobei die 
Vorkommastelle dem Vorzeichen zum Opfer fällt...), oder nicht?
> Noch realisierbar.
Aber schon EXTREM ungenau!

von A.S. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
F. S. schrieb:
> Ich soll in dem 1:7 Format beleiben
Bei dem Algorithmus dürften 8 bit bei Weitem nicht reichen

von F. S. (de0_board)


Bewertung
0 lesenswert
nicht lesenswert
Ihr habt Recht. Das Format ist zu klein, habs schon auf 16 Bit 
vergrößert.

Ich hänge eher in der Multiplikations-Funktion:
function fraction_mult(a : fixp; c : fixp) return fixp is
    variable result_3   : fixp;
    variable ergebnis   : STD_LOGIC_VECTOR((bit_lenght - 1) downto 0);
    variable mult_value : SIGNED(((bit_lenght * 2) - 1) downto 0);
  begin
    if (a.ip = 1 and c.ip = 1) then
      result_3.ip    := 1;
      result_3.fp    := bit_lenght - 1;
      result_3.nb    := bit_lenght;
      mult_value     := SIGNED(a.value) * SIGNED(c.value);
      result_3.value := mult_value(((bit_lenght * 2) - 1) downto bit_lenght); -- Unteren Werte werden abgeschnitten.

      ergebnis       := STD_LOGIC_VECTOR(result_3.value);
      ergebnis       := STD_LOGIC_VECTOR(SHIFT_LEFT(UNSIGNED(ergebnis), 1));
      result_3.value := SIGNED(ergebnis((bit_lenght - 1) downto 0));

    elsif (a.ip = c.ip) then
      result_3.ip    := (a.ip + c.ip) - 1;
      result_3.fp    := bit_lenght - (result_3.ip);
      result_3.nb    := bit_lenght;
      mult_value     := SIGNED(a.value) * SIGNED(c.value);
      result_3.value := mult_value(((bit_lenght * 2) - 1) downto bit_lenght); -- Unteren Werte werden abgeschnitten.

      ergebnis       := STD_LOGIC_VECTOR(result_3.value);
      ergebnis       := STD_LOGIC_VECTOR(SHIFT_LEFT(UNSIGNED(ergebnis), 1));
      result_3.value := SIGNED(ergebnis((bit_lenght - 1) downto 0));

--      result_3.ip := result_3.ip - 1;
--      result_3.fp := result_3.fp + 1;

    else
      result_3.ip    := (a.ip + c.ip) - 1;
      result_3.fp    := bit_lenght - (result_3.ip);
      result_3.nb    := bit_lenght;
      mult_value     := SIGNED(a.value) * SIGNED(c.value);
      result_3.value := mult_value(((bit_lenght * 2) - 1) downto bit_lenght);

      ergebnis       := STD_LOGIC_VECTOR(result_3.value);
      ergebnis       := STD_LOGIC_VECTOR(SHIFT_LEFT(UNSIGNED(ergebnis), 1));
      result_3.value := SIGNED(ergebnis((bit_lenght - 1) downto 0));

      if (result_3.value = "0000000000000000" and result_3.ip > 1) then
        result_3.ip := 1;
        result_3.fp := bit_lenght - 1;
        result_3.nb := bit_lenght;
      end if;

    --      if ((a.ip /= 1 and c.ip /= 1)) then
    --        result_3.ip    := result_3.ip - 1;
    --        result_3.fp    := result_3.fp + 1;
    --        ergebnis       := STD_LOGIC_VECTOR(result_3.value);
    --        ergebnis       := STD_LOGIC_VECTOR(SHIFT_LEFT(UNSIGNED(ergebnis), 1));
    --        result_3.value := SIGNED(ergebnis((bit_lenght - 1) downto 0));
    --      end if;

    end if;

    return result_3;
  end function fraction_mult;

Ich weiß nicht was ich falsch mache, ich bin noch nicht so sattelfest in 
VHDL. Es gibt Probleme bei der Multiplikation von verschiedenen Fraction 
Formaten.

Könnte mir bitte jemand einen Tipp geben, die Funktion funktioniert, 
aber irgendwie nicht für jedes beliebiges Format.

Danke schon im voraus.

lg F.S.

von Martin K. (mkmannheim) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
War das beim VHDL nicht so, dass signed nur 50% des Vectors auslastet 
und eine Multiplikation damit zu 25% führt? - also 2 Bits oben 
wegfallen?

Muss man das so ausführlich beschreiben und warum?

Ich habe das immer mit einem "*" beschrieben. Geht das beim signed / bei 
dieser Applikation nicht? - warum nicht?

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Martin Kluth schrieb:
> Geht das beim signed / bei dieser Applikation nicht?
Doch, es geht.
> - warum nicht?
Das Problem liegt hier irgendwie beim Verständnis der Fixkommazahlen.

Wenn ich bei einer Fixkommamultiplikation erst beide Faktoren 
gedanklich mit einem festen Faktor f multipliziere (so dass das Komma 
weg ist), dann eine Integermultiplikation mache (mit dem Operator *) und 
hinterher das Ergebnis gedanklich durch f² teile, dann habe ich 
letzlich nichts verändert, aber nur eine generische Operation verwendet. 
Und der Trick dabei ist, die gedankliche Division durch f² in eine 
Verdrahtungsänderung umzumünzen...

In Zahlen: bei einer Multiplikation von zwei 1.7 Fixkommazahlen
1.7 = V.NNNNNNN      (V=Vorkommastellen, N=Nachkommastellen)
muss ich beide mental mit 128 multiplizieren. Dann ist das Komma weg:
8.0 = VVVVVVVV.

Anschliessend erfolgt die reale Multiplikation, die als Ergebnis einen 
Integer mit 16 Bits hat:
16.0 = VVVVVVVVVVVVVVVV.

Jetzt teile ich das Ergebnis wieder mental durch 16384 und erhalte 
eine
2.14 Fixkommazahl.
2.14 = VV.NNNNNNNNNNNNNN

Wenn jetzt das Ergebnis noch keinen Überlauf und damit in einer 1.7 
Fixkommazahl Platz hat, dann kann ich einfach meine 1.7 Fixkommazahl 
/herausschneiden/:
2.14 = VV.NNNNNNNNNNNNNN
-->     |||||||||
1.7  =  V.NNNNNNN

Das wars. Blöd ist jetzt allerdings, wenn ein Überlauf aufgetreten ist, 
denn dann lässt sich diese Zahl eigentlich nicht mehr darstellen, es 
müsste umskaliert werden, der Schritt zur Fließkommazahl rückt in 
unangenehme Nähe...

DSP verwenden deshalb gern das 0.8 oder 0.16, 0.24 oder 0.32 Format, das 
ja nur Zahlen von -1...0.9999 darstellen kann. Fazit: jede 
Multiplikation (ausgenommen -1*-1) ergibt zwingend ein richtiges und 
darstellbares Ergebnis.

von Martin K. (mkmannheim) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Fazit: jede
>
> Multiplikation (ausgenommen -1*-1)

Eine 1.0 geht doch auch garnicht, wenn man voll skaliert, also Maximum = 
16383/16384 z.B. ist doch immer <1

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Martin Kluth schrieb:
> Eine 1.0 geht doch auch garnicht, wenn man voll skaliert, also Maximum =
> 16383/16384 z.B. ist doch immer <1
Klar, genau das habe ich m.E. geschrieben mit 0.9999...

Aber -1 ist möglich: -16384/16384.
Und -1*-1 gibt dann was? Richtig: 1.
Aber genau diese 1 ist nicht darstellbar, und deshalb darf diese 
Rechnung sinnvollerweise nicht ausgeführt werden.

von VHDLler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
ich beschränke meinen Zahlenraum deswegen auch in der negativen Hälfte 
auf "n-1", da gibt es dann solche Eskapaden nicht. Noch besser ist es, 
von vorn herein physikalische Grenzen zu setzen und z.B. 8000 als 
Maximum zu nehmen und nicht 8192 (bringt eh nix). Den Rest des 
Zahlenraums kann man prima für overflow, underflow und andere messages 
nutzen.

Hier beim Sinus würde ich auch nicht ans Limit gehen, selbst beim 8Bit 
Sinus reichen +/- 100, statt 127, oder meinetwegen 125.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Aber ein 8-Bit-Wandler erreicht eben erst bei 0 und 255 (oder -128 und 
+127) seine Endwerte...

von VHDLler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die sind aber i.d.R. nicht nutzbar, weil sie nicht von einem Überlauf zu 
unterscheiden sind, es sei denn, es gibt ein overflow flag. Also fallen 
2 Werte ohnehin schon mal wech. Die Wegnahme gerade der - 128 reduziert 
das maximal mögliche Ergebnis nach der Multiplikation um ein weiteres 
Bit - der Endvektor muss also nicht, wie oben (2n-1) lang sein, sondern 
kann 2n-2) lang sein. Beispiel: n = 16.

a) Länge von signed (n = 16)         = 15, 2n-1  = 31, weil
   (-32768 * -32768) = 30.0 ->  30 downto 0, ca. 50% gefüllt

b) Länge von signed (n ohne - 32768) = 14, n + n = 30, weil
   (-32767 * 32767)  = 29.99 -> 29 downto 0, ca. 99,9% gefüllt

Wenn man hinterher mit den erzeugten Werten etwas anstellen will, 
meinetwegen Filtern, Skalieren etc. dann hat man wieder dasselbe 
Problem:

Wegen einem lumpigen Wert in der Aussteuerung zu Beginn der Kette 
braucht man ständig ein Bit mehr.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Einen Überlauf kann ich aber nicht mit ein paar "Sicherheitsschritten" 
auffangen. Schon eine simple Addition braucht ein ganzes Bit für einen 
Überlauf...

Oder was sollte das helfen, wenn ich statt -128..+127 einen Bereich von 
-100..+100 verwende (also jedesmal mindestens 27 Reserve), aber 64+64 
rechnen will? Wie will ich da was sinnvolles mit dem "Headroom" 
anfangen?

>> Aber ein 8-Bit-Wandler erreicht eben erst bei 0 und 255 (oder -128 und
>> +127) seine Endwerte...
> Die sind aber i.d.R. nicht nutzbar, weil sie nicht von einem Überlauf zu
> unterscheiden sind, es sei denn, es gibt ein overflow flag.
Nur mit einem zusätzlichen Überlaufflag kann ich einen Überlauf 
erkennen. Ich nutze auf jeden Fall bei 8 Bit soweit möglich den Bereich 
von -128..+127.

von Pesto (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Nur mit einem zusätzlichen Überlaufflag kann ich einen Überlauf
>
> erkennen. Ich nutze auf jeden Fall bei 8 Bit soweit möglich den Bereich
>
> von -128..+127.

Wie willst du denn eine 127 von einer überlaufenen 127 unterscheiden?

Wandler haben nicht alle ein Überlaufbit und am oberen Ende sind sie oft 
völlig unlinear.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Pesto schrieb:
> Wie willst du denn eine 127 von einer überlaufenen 127 unterscheiden?
Am Overflow-Bit.
Nur mit diesem zusätzlichen neunten Bit geht das zuverlässig bei 
einer 8-Bit-Zahl. Egal ob signed oder unsigned.

Oder hast du eine Lösung für dieses Problem:
Lothar Miller schrieb:
> Oder was sollte das helfen, wenn ich statt -128..+127 einen Bereich von
> -100..+100 verwende (also jedesmal mindestens 27 Reserve), aber 64+64
> rechnen will?

von Weltbester FPGA-Pongo (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Die o.g. Lösung ist viel zu aufwändig. Einfach ein Dreieck auf ein 
Mehrfach IIR-Filter und fertig ist die Laube.

y=     x | 0 < x < n/2
y= 1 - x | n/2 < x < n

mit x = omega x phi / n

f1(t+1) = f1(t) * k + y(t) * (k-1)
f2(t+1) = f2(t) * k + f1(t+1) * (k-1)
f3(t+1) = f3(t) * k + f2(t+1) * (k-1)

u.s.w.

von F. S. (de0_board)


Bewertung
0 lesenswert
nicht lesenswert
Ich danke euch allen für diese wertvollen Beiträge.

Ich arbeite nun mit 16 Bit.

Was dieses Zahlenformat betrifft so habe ich mich eigentlich immer an 
diese Regel gehalten:

- Wenn beide Zahlenformate im 1.n Format sind bleibt auch nach der
  Multiplikation das Format im 1.n.
  Was ich nicht ganz verstehe, ist, dass sich das multiplizierte
  Ergebnis Rechtsbündig befindet. Warum ist das so? Ich muss bei der 1.n
  Multiplikation um eine Stelle nach Links schiften.
- Für zwei Zahlen mit unterschiedlichen Formaten gilt:
  (I1+I2-1).(Q1+Q2)
  Da verstehe ich irgendwie nicht was ich falsch mache.

Ich multipliziere im Prinzip im SIGNED Modus, da das Vorzeichen bei der 
Multiplikation ja eine sehr große Rolle spielt.

@Lothar Miller:

Ein Überlauf kann beim Sinus nicht vorkommen, da der Sinus ja nicht 
größer als 1 ist. Bei einer 1 muss ich halt wie Du richtig sagst 
0.111111111111111 rausschieben und eine Abfrage machen.
Das gleiche gilt ja für 2.14 auch, oder?

DANKE nochmals an alle die sich die Zeit nehmen.

lg F.S.

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
F. S. schrieb:
> Was ich nicht ganz verstehe, ist, dass sich das multiplizierte
>   Ergebnis Rechtsbündig befindet. Warum ist das so?
Das ist so, weil du als Ergebnis der Multiplikation zweier 1.n Zahlen 
eine doppelt so breite 2.2n Zahl als Ergebnis bekommst.

von Ingenieur (Gast)


Bewertung
0 lesenswert
nicht lesenswert
F. S. schrieb:
> Bei einer 1 muss ich halt wie Du richtig sagst
>
> 0.111111111111111 rausschieben und eine Abfrage machen.

darf ich freundlichst zwischenfragen, wie das gemeint ist?
welche Abfrage?

ich glaube, hier sind zwei Fragen im Gange:

a) Sinus und dessen optimale Erzeugung
b) Umgang mit signed fixed point

Ich habe mir das damals in Beispielen angesehen, in dem ich diese im 
Simulator durchrechnen habe lassen.

von high tec ing (Gast)


Bewertung
0 lesenswert
nicht lesenswert
So wie ich es sehe, ist eine DDS-Tabelle am besten geeignet, wenn es um 
einen präzisen Sinus geht. Gibt es eine Möglichkeit zu berechnen, welche 
S/N eine Sinuswelle erzeugt, die man auf diese Weise tabelliert hat?

von Signalprozessing Ingenieur (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Das müsste theoretisch untersuchbar sein, meine ich.

von gerhard (Gast)


Bewertung
0 lesenswert
nicht lesenswert
high tec ing schrieb:
> So wie ich es sehe, ist eine DDS-Tabelle am besten geeignet, wenn es um
> einen präzisen Sinus geht. Gibt es eine Möglichkeit zu berechnen, welche
> S/N eine Sinuswelle erzeugt, die man auf diese Weise tabelliert hat?

Wenn Du meine sin/cos-Funktion auf opencores benutzt, kannst Du die 
erzeugten Wellen vom Testbett in eine Datei schreiben lassen und danach 
mit Matlab oder sowas untersuchen. Da muss der Modelsim eben etwas 
ackern.

Gruß, Gerhard

von René D. (Firma: www.dossmatik.de) (dose)


Bewertung
0 lesenswert
nicht lesenswert
high tec ing schrieb:
> So wie ich es sehe, ist eine DDS-Tabelle am besten geeignet,
Tabellen haben nur in ihrem Stützpunkt einen Wert. Werte dazwischen 
werden über rechten und linken Stützwert angenähert. Oder du hast eine 
riesen Tabelle

Am genausten geht es mit dem Cordic Algorthmus. Den benutzt auch dein 
Taschenrechner.


> S/N eine Sinuswelle erzeugt, die man auf diese Weise tabelliert hat?

Wenn du umbedingt eine Tabelle brauchst. VHDL kann auch mit Sinus und 
Cosinus rechnen. Das lässt sich aber nicht synthetisieren.
Kann aber genutzt werden, um Tabellen zu erzeugen.

von high tec ing (Gast)


Bewertung
0 lesenswert
nicht lesenswert
gerhard schrieb:
> Wenn Du meine sin/cos-Funktion auf opencores benutzt
Da schaue ich mal, danke

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.