Forum: FPGA, VHDL & Co. Sinus über DDS erzeugen


von Matrix1 (Gast)


Lesenswert?

Hallo,
brauche Hilfe in VHDL programmierung.

Ich will ein sozusagen Sinusgenerator(sinus über mehrere Perioden) über 
ein DDS erzeugen, welches vorher in einer Look up Tabelle die Werte 
abgelegt wurden.
Kann mir einer helfen wie ich das in VHDl realisieren soll und wie ich 
die Lookup Tabelle erzeuge, wenn ich das hinbekomme muss ich noch 
weitere Aufgaben erfüllen. Dazu später

Danke.

: Verschoben durch Moderator
von MB (Gast)


Lesenswert?

Das Prinzip hinter DDS hast du verstanden?

Sonst: http://de.wikipedia.org/wiki/Direct_Digital_Synthesis

Auf dem Bild siehst du die Hauptkomponenten der DDS.

Jetzt musst du diese Komponenten in VHDL nachbilden.

Da brauchst in etwa ein Addierwerk, einen Teiler um deinen Hauptakt 
herunter auf den DDS Takt zu Teilen, deine LUT, irgend eine Augabe 
(externer DA Wandler oder per PWM), und eine Speicher für die Phase.

von Matrix1 (Gast)


Lesenswert?

Hallo,
Danke für deine Antwort, hab mich schon damit auseinander gesetzt jedoch 
bin ich noch ein Anfänger in VHDl, ich brauce lediglich Hilfe für den 
Anfang, vielleicht kannst du mir ja elfen den Anfang zu finden.Danke.

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Mod: Links von Lothar Miller (lkmiller) Datum: 14.07.2011 10:29  hierher 
kopiert und Doppelpost in µC&E-Forum gelöscht.

1. Forums-Suche:
http://www.mikrocontroller.net/search?query=sinus+dds+vhdl&forums[]=9&max_age=-&sort_by_date=1

2. Google-Suche:
http://www.google.de/search?q=sinus+vhdl+ddfs

3. http://www.lothar-miller.de/s9y/categories/31-DDFS

von Matrix1 (Gast)


Lesenswert?

Martin Thomas schrieb:
> Mod: Links von Lothar Miller (lkmiller) Datum: 14.07.2011 10:29  hierher
> kopiert und Doppelpost in µC&E-Forum gelöscht.
>
> 1. Forums-Suche:
> http://www.mikrocontroller.net/search?query=sinus+...
>
> 2. Google-Suche:
> http://www.google.de/search?q=sinus+vhdl+ddfs
>
> 3. http://www.lothar-miller.de/s9y/categories/31-DDFS

Hallo, danke für die Info, punkt 1 und 2 hatte ich schon durchforstet, 
jedoch keine passende Lösung gefunden, nun habe ich eine kleine Beispiel 
lösung gefunden hier im mikrokontroller artikel, da gibt es einen code 
womit man sinus sägezahn und rechteck erzeugt, das wird auch bei mir 
übersetzt und rechnet auch die richtigen werte aus, jeoch will ich 
wissen, ob es eine Frage der Einstellung ist das die Signalform so 
fließend und bündig wie ganz unten auf der Seite

http://www.mikrocontroller.net/articles/VHDL_Testbench

zu sehen ist oder wie kommt die zustande, bei mir kommt nur die 
Zustandsform, ich würd gerne auch so darstellen wollen.Danke.

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


Lesenswert?

Matrix1 schrieb:
> bei mir kommt nur die Zustandsform
Welchen Simulator hast du?
ISIM z.B. kann keine Analogwerte darstellen...
Modelsim kann das, der Aldec Simulator auch.

von Matrix1 (Gast)


Lesenswert?

Hallo, Danke für die Antwort,

ich benutze den ISim Simulator von Xilinx, schade, na gut.

Was ich noch wissen würde ist, statt der 15 Werte im Array könnte ich 
doch auch 360 Werte reinschreiben, dies ist ja dann meine Look up Table, 
wie kann ich denn eigentlich die Lookup Table über eine Datei in das 
VHDL Code einbinden.Danke.  ich möchte gern 12 bit Daten ausgeben, da 
ich einen 12 bit DA-Wandler benutzen muss,dann muss ich doch nur 11 
downto 0 machen, ach mir fällt ein, dass ich ja die Werte für den Sinus 
erstmal berechnen muss, gut Danke fürs erste.

von Uwe Bonnes (Gast)


Lesenswert?

Statt Tabelle kann man auch einen CORDIC  nehmen...

von Matrix1 (Gast)


Lesenswert?

Hallo Lothar
ich hätt da noch eine Frage der dritte Link bezieht sich denke ich mal 
für deine Persönlichkeit, ich habe versucht deinen Code umzusetzen, 
jedoch klappt das leider nicht, hab üer xilinx die testench erstellt, 
hast du vielleicht ne alternative test bench.Danke.

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


Lesenswert?

Matrix1 schrieb:
> hab üer xilinx die testench erstellt,
> hast du vielleicht ne alternative test bench.Danke.
Naja, die Testbench ist an Einfachheit kaum zu übertreffen: Freq_Data 
und einen Takt anlegen und fertig...

Zeig doch mal deine Testbench und was für Fehlermeldungen sie bringt. 
Oder sag einfach mal, WAS nicht geht.

von Matrix1 (Gast)


Lesenswert?

Hallo,

ja gut er gibt kein Ausgangs Signal,

dies ist dein Code den ich eingefügt habe:
1
library IEEE;
2
3
use IEEE.STD_LOGIC_1164.ALL;
4
use IEEE.numeric_std.all;
5
6
entity Sinus_DDS is
7
    Port ( clk : in  STD_LOGIC;
8
        Freq_Data : in  std_logic_vector (7 downto 0); 
9
        Dout      : out std_logic_vector (7 downto 0));
10
end Sinus_DDS;
11
12
architecture Behavioral of Sinus_DDS is
13
14
signal Data     : std_logic_vector (7 downto 0);  
15
signal Result   : std_logic_vector (7 downto 0);  
16
signal Accum    : unsigned (20 downto 0) := (others=>'0');   
17
alias  Address  : unsigned (5 downto 0) is Accum(Accum'high-2 downto Accum'high-7);  
18
alias  Sign     : std_logic is Accum(Accum'high);   -- MSB  
19
alias  Quadrant : std_logic is Accum(Accum'high-1); 
20
21
begin
22
23
-- Phasenakkumulator      
24
process begin     
25
  wait until rising_edge(CLK);     
26
  Accum <= Accum + unsigned(Freq_Data);    
27
  end process;    
28
  
29
process (Sign,Quadrant,Address)     
30
  subtype SLV8 is std_logic_vector (7 downto 0);     
31
  type Rom64x8 is array (0 to 63) of SLV8;      
32
  constant Sinus_Rom : Rom64x8 := (       
33
  x"00",  x"03",  x"06",  x"09",  x"0c",  x"0f",  x"12",  x"15",       
34
  x"18",  x"1b",  x"1e",  x"21",  x"24",  x"27",  x"2a",  x"2d",       
35
  x"30",  x"33",  x"36",  x"39",  x"3b",  x"3e",  x"41",  x"43",       
36
  x"46",  x"49",  x"4b",  x"4e",  x"50",  x"52",  x"55",  x"57",       
37
  x"59",  x"5b",  x"5e",  x"60",  x"62",  x"64",  x"66",  x"67",       
38
  x"69",  x"6b",  x"6c",  x"6e",  x"70",  x"71",  x"72",  x"74",       
39
  x"75",  x"76",  x"77",  x"78",  x"79",  x"7a",  x"7b",  x"7b",       
40
  x"7c",  x"7d",  x"7d",  x"7e",  x"7e",  x"7e",  x"7f",  x"7f");   
41
42
begin     
43
  if(Quadrant='0')      
44
  then Result <= Sinus_Rom ( to_integer(Address));     
45
  else Result <= Sinus_Rom (63-to_integer(Address));     
46
  end if;     
47
  if (Sign='1')      
48
    then Data <= Result;     
49
    else Data <= std_logic_vector (-signed(Result));     
50
  end if;   
51
end process;   
52
process begin     
53
  wait until rising_edge(CLK);     
54
  Dout <= Data;   
55
  end process;
56
end Behavioral;

und dies ist die testbench die Xilinx erzeugt
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
use IEEE.numeric_std.all;
4
 
5
-- Uncomment the following library declaration if using
6
-- arithmetic functions with Signed or Unsigned values
7
--USE ieee.numeric_std.ALL;
8
 
9
ENTITY Sinus_DDS_tb IS
10
END Sinus_DDS_tb;
11
 
12
ARCHITECTURE behavior OF Sinus_DDS_tb IS 
13
 
14
    -- Component Declaration for the Unit Under Test (UUT)
15
 
16
    COMPONENT Sinus_DDS
17
    PORT(
18
         clk : IN  std_logic;
19
         Freq_Data : IN  std_logic_vector(7 downto 0);
20
         Dout : OUT  std_logic_vector(7 downto 0)
21
        );
22
    END COMPONENT;
23
    
24
25
   --Inputs
26
   signal clk : std_logic := '0';
27
   signal Freq_Data : std_logic_vector(7 downto 0) := (others => '0');
28
29
   --Outputs
30
   signal Dout : std_logic_vector(7 downto 0);
31
32
   -- Clock period definitions
33
   constant clk_period : time := 10 ns;
34
 
35
BEGIN
36
 
37
  -- Instantiate the Unit Under Test (UUT)
38
   uut: Sinus_DDS PORT MAP (
39
          clk => clk,
40
          Freq_Data => Freq_Data,
41
          Dout => Dout
42
        );
43
44
   -- Clock process definitions
45
   clk_process :process
46
   begin
47
    clk <= '0';
48
    wait for clk_period/2;
49
    clk <= '1';
50
    wait for clk_period/2;
51
   end process;
52
 
53
54
   -- Stimulus process
55
   stim_proc: process
56
   begin    
57
      -- hold reset state for 100 ns.
58
      wait for 100 ns;  
59
60
      wait for clk_period*10;
61
62
      -- insert stimulus here 
63
64
      wait;
65
   end process;
66
67
END;

weder dout ändert sich noch freq. Danke.

von Matrix1 (Gast)


Lesenswert?

hallo,

Hab für Freq_Data einen fixen Wert angegeben, aber ich denk mal das muss 
von selbst passieren, die Testbench initialisiert dies aber am Anfang 
mit nuss, wie sage ich dass Freq data ständig seinen Wert ändern soll, 
soll ich einen Zähler einbauen, der dann incrementiert?

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


Lesenswert?

Matrix1 schrieb:
> Hab für Freq_Data einen fixen Wert angegeben
Du hast 0 angegeben. Oder besser: du hast gar nichts angegeben, das hat 
der Wizzard für dich gemacht....  :-/

Porbier doch einfach mal das:
   signal Freq_Data : std_logic_vector(7 downto 0) := x"7f";

> wie sage ich dass Freq data ständig seinen Wert ändern soll
Wieso willst du das? Willst du da was wobbeln?

von Matrix1 (Gast)


Lesenswert?

Hallo,
Danke für deine Antwort.
Hab mal ne Verständnisfrage, was genau ist dein Freq_data denn, sind das 
Frequenzdaten, was mir auffällt ist dass du kein reset hast, hat das 
eine bestimmten Hintergrund?

Danke

von Matrix1 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
hab mal die Simulation durchgeführt und hab das hier rausbekommen wie 
auf dem Bild zu sehen ist, ist dies so in Ordnung ja.

Was mein eigentliches Ziel ist, dass ich einen Fehler  in den Sinus 
einbauen muss, dass eißt ich muss eine Sinusperiode auslassen um einen 
Fehler zu projektieren. Dies wird dann auf einen Sensor gegeben, der 
dann feststellen muss, dass ein Fehler im Signal vorliegt, wenn du 
Anregungen hast wie ich das realisieren kann bin ich dir dankbar.

Danke

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


Lesenswert?

Matrix1 schrieb:
> was mir auffällt ist dass du kein reset hast,
Gut beobachtet.
> hat das eine bestimmten Hintergrund?
Ja. Dieses Modul braucht keinen Reset. Und deshalb bekommt es keinen.
Die Notwendigkeit eines Resets (und in deinem Fall für Xilinx vor allem 
eines asynchronen Resets) muss unbedingt hinterfragt werden. Was ist ein 
Reset? Wofür brauche ich den? Für den Reset-Taster vom Entwickler? Für 
den Simulator? Antwort beidesmal: NEIN.
Das hatten wir schon mal im Beitrag "Xilinx und die Resets"

Matrix1 schrieb:
> dass ich einen Fehler  in den Sinus einbauen muss, dass eißt ich muss
> eine Sinusperiode auslassen um einen Fehler zu projektieren.
Sieh dir mal in deiner Simulation den Akkumulator an. Wenn du dessen 
obere Bits mit "0000000" vergleichst, dann weißt du schon mal, wo du 
in deiner Sinuskurve bist. Und dann kannst du ja einfach mal einen 
Zyklus lang "00000000" ausgeben...

von Matrix1 (Gast)


Lesenswert?

Hallo,
komm einfach net drauf wie ich einen Zyklus lang 0 ausgeben soll, hab 
grad voll den Blackout, deine Lookup table erzeugt ja einen viertel 
Sinus, den immer wieder ausgegeben wird ein ganzer Sinus erzeugt, ich 
weß auch wo der Sinus wieder beginnt, nur weiß ic nicht wie ich dies im 
Code realisieren soll, wo soll ich sagen, dass der Ausgang so lang null 
sein soll und dann erste wieder von vorne begonnen werden soll.Danke für 
deine Hilfe.

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


Lesenswert?

Matrix1 schrieb:
> wo soll ich sagen, dass der Ausgang so lang null
> sein soll und dann erste wieder von vorne begonnen werden soll
Lothar Miller schrieb:
> Sieh dir mal in deiner Simulation den Akkumulator an.
Ein wenig solltest du schon auch noch selber denken...  :-/

Ich könnte es mir auch so vorstellen: wenn ein Übergang vom negativen in 
den positiven Bereich und gleichzeitig vom zweiten in den ersten 
Quadranten stattfindet, dann bist du am Anfang einer Sinuskurve...

Also könntest du das auch so machen:
1
   signal qalt , salt : std_logic;
2
   signal stoerung : std_logic := '0';
3
4
   process begin     
5
      wait until rising_edge(CLK);     
6
      if (stoerung='1') then Dout <= x"00";
7
      else                   Dout <= Data;     
8
      end if;
9
   end process;
10
11
   process begin
12
      wait until rising edge(clk);
13
      if (qalt='1' and Quadrant='0' and salt='1' and Sign='0) then
14
         stoerung <= not stoerung;
15
      end if;
16
   end process;

von Matrix1 (Gast)


Lesenswert?

Guten Morgen,
danke fü deine Hilfe, hab nun einiges ausprobiert und hab auch den 
kleinen code einbißchen erweitert, damit die Ausgabe richtig erscheint, 
hab nun soweit erweitert
1
signal qalt , salt : std_logic :='1';
2
   signal stoerung : std_logic := '1';
3
--
4
process begin     
5
      wait until rising_edge(CLK);     
6
      if (stoerung='1') then Dout <= x"00";
7
      elsif (Sign='1') then Dout <= std_logic_vector(  Result);
8
    else Dout <= std_logic_vector(0-Result);
9
    
10
              
11
              --Dout <= std_logic_vector(  Result) when (Sign='1') else                 
12
                --    std_logic_vector(0-Result);              
13
                           
14
      end if;
15
   end process;
16
17
   process begin
18
      wait until rising_edge(CLK);
19
      if (qalt='1' and Quadrant='0' and salt='1' and Sign='0') then
20
         stoerung <= not stoerung;
21
      end if;
22
   end process;

leider wird dabei nicht ein Zyklaus ausgelassen sondern im Intervall 
periodisch immer wieder (siehe Bild), ich will lediglich, dass nur ein 
einziger Zyklus ausgelassen wird. Was kann man denn noch 
ausprobieren.Danke.

von Matrix1 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo, das Bild hatte ich vergessen.

von Duke Scarring (Gast)


Lesenswert?

Matrix1 schrieb:
> ich will lediglich, dass nur ein
> einziger Zyklus ausgelassen wird. Was kann man denn noch
> ausprobieren.Danke.
Woher soll die Schaltung denn wissen, wann sie den Zyklus auslassen 
soll?

Duke

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


Lesenswert?

Matrix1 schrieb:
> leider wird dabei nicht ein Zyklaus ausgelassen sondern im Intervall
> periodisch immer wieder (siehe Bild)
Das ist auch nicht ein ganzer Zyklus, sondern nur ein Quadrant...
Da fehlt nämlich auf jeden Fall was für die Flankenerkennung:
1
   process begin
2
      wait until rising_edge(CLK);
3
      if (qalt='1' and Quadrant='0' and salt='1' and Sign='0') then
4
         stoerung <= not stoerung;
5
      end if;
6
      qalt <= Quadrant;
7
      salt <= Sign;
8
   end process;

Matrix1 schrieb:
> Was kann man denn noch ausprobieren.
Du wirst evtl. von aussen ein Signal eispeisen wollen, über das dann 
z.B. auf Tastendruck (Einsynchronisieren, Entprellen und 
Flankenerkennung) eine Halbwelle ausgelassen wird.
Oder du erzeugst einen Zähler, der 100 Sinuswellen mitzählt und jeweils 
die 101. auslässt, oder, oder, oder...
So langsam wäre es an der Zeit, das noch mal genauer anschauen und zu 
VERSTEHEN. Der dazu nötige Prozess heißt MITDENKEN.

> Danke.
De nada.

von Matrix1 (Gast)


Lesenswert?

Hallo,
die Schaltung weiß ja auch net, es soll lediglich eine Periode von 
vielen Sinussen ausgegeben werden (Sinusgenerator) und darin soll ein 
Sinus fehlen, der ein Fehler darstellt, dies wird dann über einen FPGA 
in eine Sensorschaltung eingespeist(DA umgewandelt) was dann erkennen 
soll, dass an einem Kreis ein von vielen Stäben ein Stab fehlt.

Danke nochmal für deine Hilfe Lothar, ich bemüh mich sehr dies zu 
verstehen bin noch ein Anfänger in diesem Gebiet.

von Selbi (Gast)


Lesenswert?

Wenn ein kompletter Sinus fehlt, merkt man das gar nicht.

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


Lesenswert?

Selbi schrieb:
> Wenn ein kompletter Sinus fehlt, merkt man das gar nicht.
Dann würde ich aber von einer sehr ausgeprägten Wahrnehmungsschwäche 
ausgehen. Denn da sollte wohl ein Unterschied zwischen "Sinus da" und 
"kein Sinus da" erkennbar sein...

von Matrix1 (Gast)


Lesenswert?

Hallo,
wie Lothar geschrieben hat, dass man eine bestimmte Anzahl von 
Sinusperioden erzeugt und dann die letzte mit null belegt, dass probier 
ich jetzt auch mal aus.Danke.

von Kommentarbube (Gast)


Lesenswert?


von Matrix1 (Gast)


Lesenswert?

Hallo,

Lothar wollt mal fragen, ich versuch nun die Sinustabelle über den 
Synthesizer zu erstellen, jedoch kommt die ganze Zeit eine 
Fehlermeldung, hab schon einiges ausprobiert leider klappt es nicht:
1
use ieee.math_real.all;  :  type Rom64x8 is array (0 to 63) of signed (7 downto 0);   
2
-- Sinus von 0° bis 90° (0 bis PI/2)  
3
signal Sinus_Rom : Rom64x8;
4
:   table: for i in 0 to 63 generate       
5
Sinus_Rom(i) <= to_signed(integer( ( sin(2.0*MATH_PI*real(i)/255.0) +1.0)*127),8);   
6
end generate;


Hier kommt immer diese Fehlermeldung:

1
Line 61. * can not have such operands in this context.
2
Line 61. IN mode Formal SIZE of to_signed with no default value must be associated with an actual value.

wie kann ich das Problem lösen hab auch die richtige library 
benutzt.Danke für deine Hilfe.

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


Lesenswert?

Matrix1 schrieb:
> *127
Mach da mal besser *127.5 draus...

Als Tipp: sieh dir auch den 
Beitrag "Re: [VHDL] Daten von ADC in BRAM speichern" an.

von Matrix1 (Gast)


Lesenswert?

Hallo,
du hast mal weiter oben dies hier geposted


Da fehlt nämlich auf jeden Fall was für die Flankenerkennung:
1
process begin
2
      wait until rising_edge(CLK);
3
      if (qalt='1' and Quadrant='0' and salt='1' and Sign='0') then
4
         stoerung <= not stoerung;
5
      end if;
6
      --qalt <= Quadrant;
7
      --salt <= Sign;
8
   end process;

wenn ich für die Simulation das hier einstelle:
1
signal qalt , salt : std_logic:='1';
2
   signal stoerung : std_logic := '1';

dann ist alles in Ordnung der eine Quadrant wird ausgelassen, wie auf 
dem Bild weiter oben, jedoch wenn ich
1
qalt <= Quadrant;
2
salt <= Sign;

wieder einfüge, dann ist der Ausgang immer Null, ausserdem will ich ja, 
dass nur eine einzige STörung kommt. woran kann das liegen.Danke.

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


Lesenswert?

Matrix1 schrieb:
> wieder einfüge, dann ist der Ausgang immer Null, ausserdem will ich ja,
> dass nur eine einzige STörung kommt. woran kann das liegen.
Am fehlenden Mitdenken?

> der eine Quadrant wird ausgelassen
Aber du willst ja nicht nur 1 Quadranten auslassen...

Probiers mal so:
1
process begin
2
      wait until rising_edge(CLK);
3
      if (Quadrant='0' and salt='1' and Sign='0') then
4
         stoerung <= not stoerung;
5
      end if;
6
      salt <= Sign;
7
   end process;
Dann überleg dir, was da passiert. Dann spiel mit den Signalen ein wenig 
herum, und lern was dabei. Wichtig ist, dass du
1. etwas machen willst.  Dir
2. dazu was ausdenkst.   Und dann
3. kontrollierst, ob das klappt.
Die ersten beiden Schritte lässt du in diesem Prozess derzeit noch 
aus... :-/

> Danke.
De nada.

von A. F. (chefdesigner)


Lesenswert?

Kann man die Störung nicht manuell in den Datenstrom einkopieren?

Wie untersuchst du eigentlich den Bruch eines Sinus, oder kommt das 
nicht vor?

von Matrix1 (Gast)


Lesenswert?

hallo,
hab mal ne Verständnisfrage, wie genau findet er nun heraus welcher 
Quadrant vorhanden ist, und wie funktioniert das mit den 
Attributen.Danke.

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


Lesenswert?

Matrix1 schrieb:
> und wie funktioniert das mit den Attributen.Danke.
Such mal nach vhdlqrc.pdf

Matrix1 schrieb:
> wie genau findet er nun heraus welcher Quadrant vorhanden ist
Der aktuell ausgegebene Quadrant ergibt sich aus den Signalen Sign und 
Quadrant (naja, diesen Namen habe ich offenbar ein wenig unglücklich 
gewählt). Und Sign und Quadrant sind einfach die obersten beiden 
Bits des Akkumulators...

von Matrix1 (Gast)


Lesenswert?

alles klar hab verstanden danke.

Hab zuerst mit viertel Sinus und der Lookup Table éinen ganzen Sinus 
erzeugt, laut deinem Code, das klappt ja wunderbar, nun habe ich die 
Methode benutzt mit der Schleife wo man einen ganzen Sinus erzeugen 
kann.
da ich aus 256 Werten ein Sinus erzeugen will sieht die Schleife ja 
wiefolgt aus:
1
table: for i in 0 to 255 generate       
2
Sinus_Rom(i) <= to_signed(integer( sin(2.0*MATH_PI*real(i)/255.0)*127.5 -0.5 ),8);   
3
    end generate table;

dazu müsste doch der Wertebereich von RomAddr und Adress auf 255 erhöht 
werden oder, und bei der ZUweisung der Bits für die Address müsste doch 
auch statt der 64 auf 255 geändert werden oder nicht?

1
Result   <= signed(Sinus_Rom(RomAddr)); 
2
 Quadrant <= Accum(Accum'left-1); 
3
 Address  <=    to_integer(Accum(Accum'high-2 downto Accum'high-7))  when (Quadrant='0') else                
4
          63-to_integer(Accum(Accum'high-2 downto Accum'high-7));

Sinus_Rom hat ja einen Wertebereich von 255 und RomAddr ja nur dann 64, 
dann würden ja für Result nur 64 Werte ausgegeben, oder hab ich wieder 
da was falsch verstanden.

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


Lesenswert?

Klar, wenn du die Länge der Tabelle änderst, dann mußt du auch den 
Zugriff auf die Tabelle ändern. Sieh dir das einfach mal im Simulator 
an...

von Matrix1 (Gast)


Angehängte Dateien:

Lesenswert?

hab ich ja auch gemacht, nur entsteht dabei ein ganz anderes Sinus 
Signal als vorher, guck dir mal das Bild an

So sieht nun der Gesamte Code aus:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.numeric_std.all;
4
--use IEEE.Std_logic_arith.all;
5
use ieee.math_real.all;
6
--use IEEE.std_logic_unsigned.all;
7
8
9
10
-- Uncomment the following library declaration if using
11
-- arithmetic functions with Signed or Unsigned values
12
--use IEEE.NUMERIC_STD.ALL;
13
14
-- Uncomment the following library declaration if instantiating
15
-- any Xilinx primitives in this code.
16
--library UNISIM;
17
--use UNISIM.VComponents.all;
18
19
entity ganzer_Sinus is
20
    Port ( CLK : in  STD_LOGIC;
21
        Freq_Data : in  std_logic_vector (7 downto 0);
22
        Dout      : out std_logic_vector (7 downto 0)
23
        );
24
end ganzer_Sinus;
25
26
architecture Behavioral of ganzer_Sinus is
27
28
  signal Result   : signed (7 downto 0);  
29
  signal Accum    : unsigned (20 downto 0) := (others=>'0');
30
   signal Address  : integer range 0 to 255;
31
  signal RomAddr  : integer range 0 to 255;
32
  signal Quadrant : std_logic; 
33
  signal Sign     : std_logic;
34
  
35
    
36
  type Rom is array (0 to 255) of signed (7 downto 0);   
37
  signal Sinus_Rom : Rom;
38
  
39
  signal qalt , salt : std_logic;
40
   signal stoerung : std_logic := '0';
41
  
42
begin
43
--Sinustabelle über Synthesizer erzeugt, indem ein viertel Sinus erzeugt wird
44
     --table: for i in 0 to 63 generate       
45
    --Sinus_Rom(i) <= to_signed(integer(( sin(2.0*MATH_PI*real(i)/255.0) +1.0)*127.5),8);
46
    --end generate table;
47
    
48
--Sinustabelle  über Synthesizer erzeugt, ganzer Sinus wird erzeugt
49
50
    table: for i in 0 to 255 generate       
51
    Sinus_Rom(i) <= to_signed(integer( sin(2.0*MATH_PI*real(i)/255.0)*127.5 -0.5 ),8);   
52
    end generate table;
53
54
 -- Phasenakkumulator      
55
 process begin     
56
 wait until rising_edge(CLK);
57
 Accum <= Accum + unsigned(Freq_Data);
58
  end process;   
59
 -- BROM         
60
 process begin     
61
 wait until rising_edge(CLK);
62
 RomAddr <= Address;          
63
 -- getaktete Adresse --> BRAM   
64
 end process;   
65
 Result   <= signed(Sinus_Rom(RomAddr)); 
66
 Quadrant <= Accum(Accum'left-1); 
67
 Address  <=    to_integer(Accum(Accum'high-2 downto Accum'high-7))  when (Quadrant='0') else                
68
          255-to_integer(Accum(Accum'high-2 downto Accum'high-7));    
69
          
70
 
71
72
-- 1 Takt Latency wegen BROM   
73
process begin     
74
wait until rising_edge(CLK);
75
     Sign    <= Accum(Accum'left);
76
    end process;
77
    
78
process begin     
79
      wait until rising_edge(CLK);     
80
      if (stoerung='1') then Dout <= x"00";
81
      elsif (Sign='1') then Dout <= std_logic_vector(  Result);
82
      else Dout <= std_logic_vector(0-Result);
83
    
84
    --Dout <= std_logic_vector(  Result) when (Sign='1') else                 
85
                --    std_logic_vector(0-Result);              
86
                           
87
      end if;
88
    end process;
89
90
   --process begin
91
     -- wait until rising_edge(CLK);
92
      --if (qalt='1' and Quadrant='0' and salt='1' and Sign='0') then
93
        -- stoerung <= not stoerung;
94
      --end if;
95
    --qalt <= Quadrant;
96
      --salt <= Sign;
97
   --end process;
98
   
99
  process begin
100
      wait until rising_edge(CLK);
101
      if (qalt='1' and Quadrant='0' and salt='1' and Sign='0') then
102
       --qalt='1' and 
103
         stoerung <= not stoerung;
104
      end if;
105
    --qalt <= Quadrant;
106
      --salt <= Sign;
107
   end process;
108
  
109
  
110
    --Dout     <= std_logic_vector(  Result)   when (Sign='1') else                 
111
    --        std_logic_vector(0-Result);
112
113
end Behavioral;

leider habe ich kein mOdelsim wo ich das Sinus Signal Analog sehen kann 
ob es auch genau so aussieht wie es aussehen soll.

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


Lesenswert?

Matrix1 schrieb:
1
 Result   <= signed(Sinus_Rom(RomAddr)); 
2
 Quadrant <= Accum(Accum'left-1); 
3
  Address  <=    to_integer(Accum(Accum'high-2 downto Accum'high-7))  when (Quadrant='0') else                
4
           255-to_integer(Accum(Accum'high-2 downto Accum'high-7));
Wenn du einen GANZEN Sinus in der Tabelle hast, dann mußt du dich um 
Vorzeichen oder Quadranten nicht mehr kümmern. Gib einfach die ganze 
Tabelle aus:
1
 Result   <= signed(Sinus_Rom(to_integer(Accum(20 downto 13))));

von Matrix1 (Gast)


Angehängte Dateien:

Lesenswert?

Ja gut, aber für die Störung brauche ich die ganzen definitionen 
trotzdem, aber es klappt, der Sinus wird ausgegeben und die Störung 
erfolgt ebenfalls,

ich versuch die ganze Zeit, einen Zähler einzubauen, der ganze Sinusse 
zählt, aber ich versteh nicht, wo der Anfang des Sinus und wo das Ende 
ist, damit ich dies in meiner Definition einbauen kann. Hab nachgefragt, 
und hab wohl einige Sachen durcheinander gebracht, ich muss nämlich die 
Anzahl der Sinusse vorgeben, dass heißt die Anzahl der Zähne vorgeben 
und dann einen Zahn (Sinus) auslassen, ´du hattest rechtgehabt, es muss 
irgendwie extern erfolgen, über ein Interface sollen diese Daten 
eingespeist werden.

kann ich über Freq_Data die breite des Sinus ändern oder ist dies nur 
eine Hilfsvariable.

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


Lesenswert?

Matrix1 schrieb:
> kann ich über Freq_Data die breite des Sinus ändern oder ist dies nur
> eine Hilfsvariable.
Probiers aus. Kostet nix.

> aber ich versteh nicht, wo der Anfang des Sinus und wo das Ende
> ist, damit ich dies in meiner Definition einbauen kann.
Wenn die oberen 8 bits deines Akkus 0 sind (bzw. werden), dann bist du 
am Anfang der Tabelle. Und in der Tabelle steht dein Sinus. Wo bist du 
dann also in deinem Sinus?

von Duke Scarring (Gast)


Lesenswert?

Matrix1 schrieb:
> leider habe ich kein mOdelsim wo ich das Sinus Signal Analog sehen kann
> ob es auch genau so aussieht wie es aussehen soll.
Dann schreib Dir die Werte in eine Textdatei und verwende gnuplot, 
Matlab, Excel, Openoffice calc, younameit um ein Diagramm draus zu 
machen.

Duke

von Matrix1 (Gast)


Lesenswert?

Hallo,

hab einige Variationen ausprobiert, bei der hier zählt er zwar
1
process begin     
2
 wait until rising_edge(CLK);
3
  if((Accum(20 downto 13)) = 0) then n <= n+1;
4
    end if;
5
    end process;

aber in der Simulation seh ich, dass Accum(20 downto 13) = 0 lange Null 
ist,bis es seinen ZUstand ändert, bis dahin hat n bei jedem Zustand eins 
hochgezählt.

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


Lesenswert?

Matrix1 schrieb:
> aber in der Simulation seh ich, dass Accum(20 downto 13) = 0 lange Null
> ist,bis es seinen ZUstand ändert, bis dahin hat n bei jedem Zustand eins
> hochgezählt.
Tja, da wäre es nicht ohne, wenn man da erkennt, dass, wie
Lothar Miller schrieb:
> die oberen 8 bits deines Akkus 0 sind (bzw. werden)
Aha: WERDEN.
Du mußt dir also MERKEN, welche Bits du vorher hattest und dann auf !=0 
vergleichen. So etwa:
1
signal akku_old : unsigned(7 downto 0);
2
process begin     
3
 wait until rising_edge(CLK);
4
  if(Accum(20 downto 13)=0 and akku_old/=0) then n <= n+1;
5
  end if;
6
  akku_alt <= Accum;
7
end process;

von Matrix1 (Gast)


Lesenswert?

mir ist auch aufgefallen, dass ich ja ein process eingerichtet habe, 
dass heißt bei jeder steigenden Flanke überprüft er und wenn null ist 
dann zählt er hoch bis Accum seinen Zustand richtig ändert kommen 
dazwischen etliche steigende Flanken wo abgefragt wird ist Accum Null, 
dann hochzählen, kein Wunder das er alle Flanken mitzählt.

von Matrix1 (Gast)


Lesenswert?

Hallo,
kannst du mir paar tipps geben, wie ich es schaffe den Abstand zwischen 
den einzelnen Sinussen zu vergrößern, die Abstände sollen zeigen, dass 
die Zähne am Rad in einem bestimmten Abstand stehen, jetzt würde ja 
bedeuten, dass alle Zähne am Rad nebeneinander sind, Hab versucht, dass 
nur eine bestimmte Anzahl von Sinussen ausgegeben wird, dafür habe ich 
dies ergänzt
1
process begin
2
    wait until rising_edge(CLK);
3
    if(Accum(20 downto 13)=0 and Accum_alt(7 downto 0) /= 0) then n <= n+1;
4
    elsif (n(7 downto 0) = 60) then n <= "00000000";  --Exit;
5
    end if;
6
    Accum_alt <= Accum(20 downto 13);
7
    end process;
aber das bringt ja nichts, weil er dann bis 60 zählt, dann von 0 wieder, 
gibt es nicht eine Abbruchbedingung in vhdl, Exit ist ja um aus einer 
Schleife herauszukommen.

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


Lesenswert?

Wenn du in VHDL Abläufe modellieren willst, dann nimmst du am besten 
einen Zustandsautomaten (State Machine).

Aber da könntest du jetzt schon auch ein wenig Sebständigkeit zeigen. 
Sieh dir mal das Buch VHDL-Synthese von Reichardt/Schwarz an, und lern 
was draus...

BTW:
Das
Accum_alt(7 downto 0)
und das
n(7 downto 0)
ist nicht nötig, wenn diese Signale sowieso nur 8 Bit breit sind...

BTW2:
> gibt es nicht eine Abbruchbedingung in vhdl
Was willst du denn überhaupt abbrechen?

von Matrix1 (Gast)


Lesenswert?

abbrechen will ich ja nichts was ich meinte war, dass wenn n =40 sinusse 
gezählt hat, dass dann der prozess aufhören soll, weiter zu machen, da 
ich ja nur 40 Sinusse wollte.

Ja klar ich arbeite mich nebenher auch ein und das Buch besorg ich mir 
auch.

von J. S. (engineer) Benutzerseite


Lesenswert?

@Matrix1:

Ich glaube, ihr habt einen Fehler in eurer Formel. Der Endwert des 
Argumentes darf nicht auf 255, sondern muss auf 256 bezogen werden, 
damit das entstehende Elementarelement des Sinusbogens exakt passt. Das 
wären nämlich dann die Werte ab einschließlich der Nummer 256 aufwärts. 
So werden entweder 2 Teilbögen zusammengesetzt, die nicht passen, weil 
ein Wert im nächten Bogen wiederholt wird oder die Skalierung stimmt 
nicht.

Das Ganze fällt bei grossen Auflösungen nicht so auf, wird aber 
augenscheinlich, wenn man einen Sinus aus z.B. nur 8 Werten aufbauen 
will. Ich habe das hier mal genauer gepostet. Man beachte die Version 2 
und ihre Vorteile.

http://www.mikrocontroller.net/articles/Digitale_Sinusfunktion

Bei der Amplitude würde ich es auch anders machen. Siehe mein Beispiel.

von ralf (Gast)


Lesenswert?

>> gibt es nicht eine Abbruchbedingung in vhdl
>Was willst du denn überhaupt abbrechen?
Originalzitat unseres Profs:

Wer bei VHDL immer noch die Abläufe sucht und nach *Start*-, Abbruch 
oder Endekriterien sucht, der sollte diesen Umstand als 
Abbruchkriterium für sein Studium hernehmen :-)

von Matrix (Gast)


Lesenswert?

Hallo,
bin grad dabei in modelsim zu simulieren, dabei will ich ein 
Signalverlauf
analog darstellen, was ja auch möglich ist, aber wie schaffe ich es,
dass der angezeigte Signalverlauf nicht über den ganzen wavefenster
angezeigt, wird, ich habe einen Sinusgenerator programmiert und nun will
ich es analog  ansehen, nur erscheint das Signal über das ganze Fenster,
Zoomen bringt ja nichts, es ändert nur in die Breite, wie ändere ich die
höhe, will sie kleiner haben.Danke.

von Duke Scarring (Gast)


Angehängte Dateien:

Lesenswert?

Bei mir (ModelSim 10.0b) gibt es da einen rescale Knopf.

Duke

von Edi M. (Gast)


Lesenswert?

anonsten manuell bei der waveform den Bereich (min,max) einstellen. Geht 
oft schnelle, als das auto-re-zoom.

von Duke Scarring (Gast)


Lesenswert?

E. M. schrieb:
> Geht oft schnelle, als das auto-re-zoom.
Mit dem Upate von 6.6 auf 10.0 ist das Feature richtig brauchbar 
geworden.

Duke

von Matrix (Gast)


Lesenswert?

Danke für euere Hilfe.

von Edi M. (Gast)


Lesenswert?

>So werden entweder 2 Teilbögen zusammengesetzt, die nicht passen
Warum sollten die Bögen nicht passen? Sie sind doch vollkommen 
spiegelsymmetrisch?

von J. S. (engineer) Benutzerseite


Lesenswert?

Edgar M. schrieb:
>>So werden entweder 2 Teilbögen zusammengesetzt, die nicht passen
> Warum sollten die Bögen nicht passen? Sie sind doch vollkommen 
spiegelsymmetrisch?

Sie sind punktsymmetrisch zu dem Maximalwert bei phi=90Grad. Das ist 
aber ein isolierter Wert der sozusagen zwischen den Bereichen steht. Bei 
der gesamten Geschichte muss man sich ja immer fragen, zu welchem 
Bereich eine Stützstelle gehören soll. Wenn der Nullpunkt der erste im 
ersten Viertel ist, dann gehört der 90-Grad Punkt zum zweiten und so 
fort.

Die Reihe mit 4 Bereichen wäre also:
 0,00  22,50  45,00  67,50  90,00

und umgeklappt:
90,00  67,50  45,00  22,50   0,00

... also ein 5-Punkt-System, das ohne Verschiebung nicht in die binäre 
Darstellung passt. Das erste und das zweite Viertel können dann nicht 
durch einfaches "Umklappen" gebildet werden, was bei meiner Methode 
(Stützstellen in der Mitte der Bereiche) sehr wohl funktioniert:

11,25  33,75  56,25  78,75
78,75  56,25  33,75  11,25

"umklappen" ist also wie "fortsetzen"

von J. S. (engineer) Benutzerseite


Lesenswert?

Nachsatz:

Der Teiler "255" vom Beitrag ganz oben stimmt, wie gesagt, deshalb 
nicht, weil es bei 8 Bit 256 Bereiche sind, die die Abstände zwischen 
den Punkten definieren. Man bekäme so eine Art Kompression der Welle mit 
256/255 im ersten Viertelbogen und einen Phasensprung von 2 x 1/256 beim 
Übergang.

von M.K. (Gast)


Lesenswert?

@Juergen S.

Ich ersehe noch nicht genau, wo der wirkliche Vorteil der Verschiebung 
sein soll. Die Werte kann ich doch frei belegen, also auch mit 
meinetwegen 10 Grad Verschiebung.

Und die Phasenwerte lassen sich binär ganzzahlig darstellen, egal, 
wieviele Bits man braucht. Die Tabelle ist doch zyklisch.

Wie macht das denn eine DDS in einem CHIP?

Kommt das da auch verschoben raus? - ich denke nicht!

von J. S. (engineer) Benutzerseite


Lesenswert?

M.K. schrieb:
> egal, wieviele Bits man braucht.
ja und nein,

> Die Tabelle ist doch zyklisch.
nein, es sind 4 "Brocken",

Die Umrechung der bits ist einfacher, weil es nur eine Negation ist, 
ohne substraktion oder carry o.ä. -

000 -> 111
001 -> 110
...
111 -> 000


das ist schneller und kleiner, vor allem in mickrigen PLD-Anwendungen 
und langsamen CHIPs. Dafür habe ich das seinerzeit auch gemacht.

> Wie macht das denn eine DDS in einem CHIP?
gute Frage, ich denke, dass es bei den grossen Vektoren in einer 
CHIP-DDS keine Rolle spielt.

> Kommt das da auch verschoben raus? - ich denke nicht!
müsste man mal testen

von M.K. (Gast)


Lesenswert?

Juergen S. schrieb:
> Die Umrechung der bits ist einfacher, weil es nur eine Negation ist,

und das macht so viel aus?

von J. S. (engineer) Benutzerseite


Lesenswert?

In einem PLD, das für 32 Motoren zuständig ist und jeder seine eigene 
Tabelle braucht, schon.

von Hallmackenreuther (Gast)


Lesenswert?

Juergen S. schrieb:
> jeder seine eigene
> Tabelle braucht

Wieso braucht jeder seine eigene Tabelle??
Sinus ist Sinus, oder nicht?

von Michael W. (Gast)


Lesenswert?

Auch wenn das Thema etwas älter ist, greife ich es kurz auf (es wurde 
von der Suche vorgeschlagen)

Hallmackenreuther schrieb:
> Juergen S. schrieb:
>> jeder seine eigene Tabelle braucht
>
> Wieso braucht jeder seine eigene Tabelle??
> Sinus ist Sinus, oder nicht?

Der Frage möchte ich mich anschliessen! Wäre es nicht einfacher, in VHDL 
nur eine Tabelle zu erzeugen und sie mehrfach zu nutzen?

Wie liesse sich das steuern? Resource Sharing? Oder manuell per Hand 
einkopieren und auf die intelligente Synthese hoffen? Oder doch einfach 
nur Multiplexen? Das Tool wäre in diesem Fall Xilinx XST. Synplify 
stünde gfs zur Verfügung.

In meinem Fall hätte ich eine grosse Tabelle zu realisieren, mit 1000 
Punkten, die u.U. im BRAM liegen muss, weil sie in einem Testfall nicht 
ganz sinusförmig sein soll, wozu auch immer.


ralf schrieb:
>>> gibt es nicht eine Abbruchbedingung in vhdl
>>Was willst du denn überhaupt abbrechen?
> Originalzitat unseres Profs:
>
> Wer bei VHDL immer noch die Abläufe sucht und nach *Start*-, *Abbruch*
> oder Endekriterien sucht, der sollte diesen Umstand als
> Abbruchkriterium für sein Studium hernehmen :-)
Zu soetwas fällt mir nur ein: Typische Arroganz von Profs! Die habe ich 
auch kennengelernt. Die tun immer so, als hätten sie selber keine 
Defizite und machen sich über Studenten lustig, die noch am Anfang 
stehen.

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


Lesenswert?

Markus Wagner schrieb:
> Wäre es nicht einfacher, in VHDL nur eine Tabelle zu erzeugen und sie
> mehrfach zu nutzen?
> Wie liesse sich das steuern? Resource Sharing?
Wie würde diese Tabelle denn in Hardware abgebildet? Als RAM?! Und wie 
könnten gleichzeitig viele Komponenten auf 1 RAM zugreifen? Richtig: gar 
nicht. Das ginge nur, wenn man den Zugriff auf dieses RAM zeitlich 
multiplext...

von J. S. (engineer) Benutzerseite


Lesenswert?

Markus Wagner schrieb:
>> Wer bei VHDL immer noch die Abläufe sucht und nach *Start*-, *Abbruch*
>> oder Endekriterien sucht, der sollte diesen Umstand als
>> Abbruchkriterium für sein Studium hernehmen :-)
> Zu soetwas fällt mir nur ein: Typische Arroganz von Profs! Die habe ich
> auch kennengelernt. Die tun immer so, als hätten sie selber keine
> Defizite

Zumal der Prof in schon in diesem Fall ein "Defizit" aufweist, denn in 
VHDL gibt es ja sehr wohl "Abläufe" mit Start- und Endbedingungen, um 
z.B. per Loop und Generate die unterschiedlichsten mehrdimesionalen 
Strukturen wie Busse und Areale zu erzeugen und zu verdrahten. Irgendwie 
haben selbst Professoren oft ein ungeordnetes Bild von dem 
HW-Beschreibung <-> Software und heben schnell darauf ab, dass es biite 
ja keine Controller sind und werden nicht müde, die Deklaration der 
FPGA-Entwicklung als "Programmieren" als falsch zu krtiseren und 
verlieren völlig aus den nAugen, was VHDL heute tatsächlich ist: Eine 
Beschreibungssprache, die eine Software steuert, nämlich einen komplexen 
Erzeugungsmechanismus, der unter Zuhilfenahme von mehr woder weniger 
konkrete Randbdingungen aus einem Baukasten die HW-Elemente selektiert, 
die zur Erledigung der gestellten Aufgabe nötigt ist. Das ist im Prinzip 
genau dasselbe, was ein Entwicklungsingenieur tun müsste: Er liest die 
funktionellen Anforderungen, sucht sich die Chips aus und verdraht dann 
das Ganze, wobei er eben die RAMS, PLL, Multiplier und LUTs zur 
Verfügung hat.

Bei genauerer Betrachung ist VHDL sogar viel abstrakter, als z.B. eine 
Microcontroller-Software in C, denn bei dem C-Programm kann man mehr 
oder weniger klar erkennen, wann später mal was im Controller passiert, 
bzw welcher Teil aktiv ist.

Bei VHDL geht das kaum, weil letztlich kleine Randbedingungen der 
Syntheseinstellungen und des konkrten Timings dafür sorgen, ob etwas in 
FFs gepuffert wird oder es in BRAMS wander, bzw ob eine Kombinatorik im 
RAM oder in LUTs sitzt, bzw wie diese gebildet und zusammengefasst 
wurde.

Das für einige offenbar Verwirrende ist eben der Umstand, dass VHDL die 
gesamte Palette an Beschreibungsoptionen bietet, angefangen von der 
zielgenauen Referenzierung eines ganz bestimmten IO-FFs, bzw einer PLL, 
über das unkonkrete Inferrieren eines Speichers-RAMS bis hin zur 
komplett abstrakten bedingten Synthese von Strukturen und deren 
Handlungen im Falle des Erfüllens spezieller Bedinungen.

Ob dann jemand so oder so von der FPGA-Entwicklung denkt, hängt ganz 
offensichtlich davon ab, aus welcher Ecke er kommt und was ihm bei 
seinem Erfahrungsschatz so alles an Wissensbrocken fehlt.

von J. S. (engineer) Benutzerseite


Lesenswert?

Markus Wagner schrieb:
> Der Frage möchte ich mich anschliessen! Wäre es nicht einfacher, in VHDL
> nur eine Tabelle zu erzeugen und sie mehrfach zu nutzen?

Um die Frage, die ich damals übersehen hatte, mal zu beantworten: In der 
Tat könnte das Sinus-RAM beim typischen Motor-Controller multiplext 
werden, soforn sie mit genügend geringen Geschwindigkeiten angesteuert 
werden müssen. Sagen wir mal 3000 UPM mit 256 Schritten, macht bei 32 
Motoren irgendwas an die 1 MHz. Die App, die ich anführte, muss aber 
auch messen und IQ-Prozessieren und einen Filter bedienen und dann wurde 
das extrem eng. Zudem müsste da recht viel Logik verbaut werden und bei 
kleinen Tabellen sind lokale LUTs resourcentechnisch auch "billiger".

> Wie liesse sich das steuern? Resource Sharing?
> Oder manuell per Hand
> einkopieren und auf die intelligente Synthese hoffen? Oder doch einfach
> nur Multiplexen? Das Tool wäre in diesem Fall Xilinx XST.

Solange die Zugriffe auf die Resource zeitlich entkoppelt ist, kann das 
gehen. OB die Synthese das im Einzelnen auch sieht und hinbekommt, ist 
eine andere Frage. Ich würde da Xilinx XST nicht zuviel zutrauen. Ich 
habe das Thema teilweise näher untersucht und kann zumindests für meinen 
Fall des pipelined Synth sagen, dass mehrfach genutzte RAMs, die zu 
verschiedenen Zeiten zugegriffen werden, nicht automatisch erkannt 
werden. Wenn Ich sie vereinigen wollte, msste ich es mit einem MUX 
machen, der passend gesteuert wird. Bei einem EQ, der parallele 
Instanzen nutzt, ging es wiederum, wenn die Kanäle zeitlich multiplext 
werden: Die Multiplier die genutzt wurden, sind nicht mehrfach erzeugt 
worden. Formuliert man das dasselbe als echte pipeline, also "von innen 
gemultiplext" geht es technisch auch, aber die Synthese packt es nicht. 
Dies ist aber die technisch überlegene, weil effektivste Realisation. 
Dieser Sachverhalt ist einer der Hauptgründe, warum ich auch der 
automatischen Code-Generation aus MATLAB kritisch gegenüber stehe: 
MATLAB generiert keine mehrdimensionalen pipelines. Das muss man selber 
machen.

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


Lesenswert?

>> Wieso braucht jeder seine eigene Tabelle??
>> Sinus ist Sinus, oder nicht?
>
> Der Frage möchte ich mich anschliessen! Wäre es nicht einfacher, in VHDL
> nur eine Tabelle zu erzeugen und sie mehrfach zu nutzen?


MATH_REAL hat die Funktion Sinus.
Mit einer Loop Funktion kann man sich so eine Tabelle erzeugen.
Kein Problem.

Man kann auch den Sinus über die Cordic Funktion erzeugen. Das ist sogar 
ohne Tabelle. Nur zur Vollständigkeit.

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.