Forum: FPGA, VHDL & Co. Sinus


von Micha (Gast)


Lesenswert?

Hallo,
ich hab noch ein Problem in VHDL.

Ich möchte eine Sinus-Funktion auf einen A/D-Wandler ausgeben.
In meinem Programm habe ich eine "Variable INTEGER RANGE 0 to 255",
die bei jeder positiven Flanke um 1 erhöht wird. Die Sinusfunktion soll
mit diesen 256 Schritten abgebildet werden. Ich hab jetzt versucht, dies
mit sin(counter) zu machen, bekam allerdings die Meldung, daß sin()
static sein muß.

Wie lässt sich das realisieren? Über ein Array, in dem ich die 256
Sinuswerte abspeichere?

von FPGAküchle (Gast)


Lesenswert?

Du willst bestimmt keinen CORDIC Block zur sinusberechnung einbauen und
sicherlich keine CPU um den sinus berechnen lassen. Bleibt also
Tabelle, meint ROM-feld. Du kannst Dir für Xilinx einen solchen vor
coregen bauen lassen, die sinuswerte schreibst du dann in das *.coe
file. Soviel in Kürze.
Aber muss es ein Sinus sein? ein Dreieck ist auch ganz gut zum Testen.
Und
ein bisserl Tiefpass dahinter macht fast einen Sinus draus. das dreieck
erzeugt dir
bequem ein up/Down counter. Aber meinst du wirklich einen AD und
keinen
DA wandler? Aus einen FPGA kriegst du keine Analogen Signale, da
musstest du schon was hinter die Pins schalten.

von Micha (Gast)


Lesenswert?

Ich meinte natürlich einen D/A-Wandler, da habe ich mich vertippt.
Ein Dreieck reciht leider nicht aus.
Ich hab jetzt nach einigen Stunden folgendes geschrieben:

  sin_gen: process(int_clock, reset)
      TYPE sinus_array IS ARRAY (natural range 0 to 255) of INTEGER;
      variable counter: integer range 0 to 255;
      variable sinus: sinus_array;
  begin

     for I in 0 to 255 loop
         sinus(I) :=integer((sin(2.0  MATH_PI  real(I) / 256.0) + 1.0
) * 127.5);
    end loop;

      if (reset = '1') then
       q <= (others =>'0');
     elsif (int_clock'event and int_clock='1') then
        q <= conv_std_logic_vector(sinus(counter),8);
        if (counter < 255) then
             counter := counter +1;
         else counter := 0;
            end if;
    end if;
  end process sin_gen;

Simulation sieht gut aus. Morgen teste ich es mal mit Hardware. Vielen
Dank.

von Jens (Gast)


Lesenswert?

ich bekomme hier ständig die Fehlermeldung
1
Error (10500): VHDL syntax error at SinusGeneration.vhd(21) near text "real";  expecting ")", or ","
1
Error (10500): VHDL syntax error at SinusGeneration.vhd(21) near text ")";  expecting ";"
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
5
entity SinusGeneration is
6
  generic
7
  (  
8
    test: integer := 256
9
  );
10
  Port 
11
  (  
12
    clk: in std_logic;
13
    rst: in std_logic
14
  );
15
end SinusGeneration;
16
17
architecture Behavioral of SinusGeneration is
18
begin
19
  sin_gen: process(clk, rst)
20
  TYPE sinus_array IS ARRAY (natural range 0 to 255) of INTEGER;
21
  variable counter: integer range 0 to 255;
22
  variable sinus: sinus_array;
23
  begin
24
    for I in 0 to 255 loop
25
      sinus(I) :=integer((sin(2.0 MATH_PI real(I) / 256.0) + 1.0) * 127.5);
26
    end loop;
27
    if (rst = '1') then
28
      q <= (others =>'0');
29
    elsif (clk'event and clk='1') then
30
      q <= conv_std_logic_vector(sinus(counter),8);
31
      if (counter < 255) then
32
        counter := counter +1;
33
      else counter := 0;
34
      end if;
35
    end if;
36
    end process sin_gen;
37
  
38
end Behavioral;

ich habe auch vor einen Sinus zu erzeugen und diesen variable machen in 
der Frequenz. Kann mir da jemand einen Denkanstoß geben?

Danke im vorraus

von Matthias (Gast)


Lesenswert?

Dir fehlt der *-Operator.

Im vorigen Post war der wohl drin aber wurde in der Anzeige zu einer 
Hervorhebung von MATH_PI umgewandelt.

von Jens (Gast)


Lesenswert?

ja danke habe alle Compilerfehler ausgebügelt.

Jedoch versuche ich jetzt diesen über ein Oszi ein Sinus Signal 
darzustellen. Klappt leider nur nicht. Wo habe ich einen Denkfehler?

von Duke Scarring (Gast)


Lesenswert?

@Jens:
> Wo habe ich einen Denkfehler?
Es sind nicht alle VHDL-Konstrukte synthetisierbar.

Duke

von Falk B. (falk)


Lesenswert?

@  Micha (Gast)

>Wie lässt sich das realisieren? Über ein Array, in dem ich die 256
>Sinuswerte abspeichere?

Ja. Und das Array legast du am besten als Konstanten an, welche du 
vorher per Excel oder so berechnest. Scnst gibts wieder 
Compiler-Gemecker.

Wie man das machen kann sieht man hier.

http://www.mikrocontroller.net/articles/TTL74185#Konstanten_Array

MFG
Falk

von GastausHannover (Gast)


Lesenswert?

hallo zusammen

ich hab den code mals mit ise 10 von xilinx synthesieren gelassen, es 
geht fehlerfrei!?

Mit extra pagket-Einbinden: (sonst fehlermeldung wegen real-type und 
konstant MATH_PI)
1
use IEEE.MATH_REAL.ALL;

ich bewundere mich: MATH_REAL Paket kann nicht synthesieren werden, also 
nur für Simulation!

Hab ich einen Denkfehler?

gruß

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

GastausHannover schrieb:
> Hab ich einen Denkfehler?
Zwei hast du:
1) Der Thread ist 1,5 Jahre alt. Wozu hast du den ausgegraben?
2) Die MATH_REAL wird nicht synthetisiert, sondern nur zur Berechnung 
verwendet. Das Ergebnis der Berechnung ist ein integer. Und der kann 
ohne weiteres synthetisiert werden:
1
    for I in 0 to 255 loop
2
      sinus(I) :=integer((sin(2.0 * MATH_PI * real(I) / 256.0) + 1.0) * 127.5);
3
    end loop;


BTW:
Es würde reichen, nur 1/4 vom Sinus auszurechnen.
Der Rest wiederholt sich irgendwie immer wieder...   :-o

von GastausHannover (Gast)


Lesenswert?

Lothar Miller schrieb:
> 1) Der Thread ist 1,5 Jahre alt. Wozu hast du den ausgegraben?

weil ich bin noch newbie in vhdl:-)

Lothar Miller schrieb:
> Das Ergebnis der Berechnung ist ein integer. Und der kann
> ohne weiteres synthetisiert werden:    for I in 0 to 255 loop
>       sinus(I) :=integer((sin(2.0  MATH_PI  real(I) / 256.0) + 1.0) * 127.5);
>     end loop;

Dann wieso muss man noch einen Type-cast integer brauchen?kann man nicht 
einfach so zuweisen?:
1
sinus(I) :=(sin(2.0 * MATH_PI * real(I) / 256.0) + 1.0) * 127.5);

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> kann man nicht einfach so zuweisen?:
Nein.
Kann man nicht, weil das hier VHDL ist und nicht C, BASIC oder sonst 
was. Denn in VHDL kann auf ein Signal bzw. eine Variable nur etwas 
zugewiesen werden, das explizit den selben Typ hat.

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


Lesenswert?

Am Anfang sind Typen und der Typ-cast etwas lästiges. Erspart dann doch 
die Fehlersuche, weil zwischen dem Programmier und der Fitsoftware keine 
Missverständnisse existieren.

von GastausHannover (Gast)


Lesenswert?

Lothar Miller schrieb:
> Es würde reichen, nur 1/4 vom Sinus auszurechnen.
> Der Rest wiederholt sich irgendwie immer wieder...   :-o

genau, ich hab grad ausprobiert:-)


FPGAküchle schrieb:
> Du kannst Dir für Xilinx einen solchen vor
> coregen bauen lassen, die sinuswerte schreibst du dann in das *.coe
> file.

wie kann man ein sinus.coe-file erzeugen? damit man in ROM reinlegen und 
auslesen kann?

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


Lesenswert?

Du musst ein Array erzeugen, das ist deine Table.

type wave_typ is array (0 to 127) of signed (0 to 7);

constant sin_fkt: wave_typ :=
("10000000",
 "01000000",
.......

);

von GastausHannover (Gast)


Lesenswert?

René D. schrieb:
> Du musst ein Array erzeugen, das ist deine Table.
>
> type wave_typ is array (0 to 127) of signed (0 to 7);
>
> constant sin_fkt: wave_typ :=
> ("10000000",
>  "01000000",
> .......
>
> );


kann man das automatisch erzeugen lassen, ich meine vllt mit matlab, 
exel..?

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


Lesenswert?

Es geht auch mit VHDL!!!!
Matlab ist gut für Untersuchungen. Halte es besser aus dem Design.

Doch da muss ich auch erst in das Buch schauen.

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


Lesenswert?

So ungefähr muss es lauten.
Das ist ungetestet!!!



USE ieee.math_real.all; --ergänzen


----
constant interations:integer:127;

type wave_typ is array (0 to 127) of signed (0 to 7);

signal sinus_fkt: wave_typ;


table :for a in 1 to interations  generate

  sinus_fkt(a)<=to_signed(integer(angle_bits *( sin( real(a))),size);
end generate table;

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.