Forum: FPGA, VHDL & Co. Frage zum Theta Delta-Sigma AD


von tomy (Gast)


Lesenswert?

hallo zusammen,

ich steuere gerade den AD7401a mit FPGA an.

Mit Sinc3-Filter, prinzipiell wie im Datenblatt, siehe bitte Seite 16 
http://www.analog.com/static/imported-files/data_sheets/AD7401A.pdf
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.Numeric_std.ALL;
4
5
entity Sinc_filt is
6
  generic ( 
7
         DECIMATOR_M_BIT_SIZE   : natural := 8); -- M = 2^DECIMATOR_M_BIT_SIZE
8
    Port ( Mclk : in  STD_LOGIC;
9
           Mdata : in  STD_LOGIC;
10
           rst : in  STD_LOGIC;
11
           DataRate_clk : out  STD_LOGIC; -- in fifo abspeichern 
12
           DataOut : out  STD_LOGIC_VECTOR (15 downto 0));
13
end Sinc_filt;
14
15
architecture Behavioral of Sinc_filt is
16
17
  constant DATA_BIT_SIZE : natural := 3*DECIMATOR_M_BIT_SIZE + 1; -- intern DatenBus Sinc3
18
19
  ----------------------------------------------------------------------------------
20
  -- signal
21
  ----------------------------------------------------------------------------------
22
    
23
  -- integrator @ Mclk
24
  signal acc1    : signed (DATA_BIT_SIZE - 1 downto 0) := (others => '0');
25
  signal acc2    : signed (DATA_BIT_SIZE - 1 downto 0) := (others => '0');
26
  signal acc3    : signed (DATA_BIT_SIZE - 1 downto 0) := (others => '0');
27
  
28
  -- diffirentiator @ Mclk/DECIMATOR_M
29
  signal diff_clk : std_logic := '0';
30
31
  signal diff1    : signed (DATA_BIT_SIZE - 1 downto 0) := (others => '0');
32
  signal diff2    : signed (DATA_BIT_SIZE - 1 downto 0) := (others => '0');
33
  signal diff3    : signed (DATA_BIT_SIZE - 1 downto 0) := (others => '0');
34
  signal acc3_d   : signed (DATA_BIT_SIZE - 1 downto 0) := (others => '0');
35
  signal diff1_d  : signed (DATA_BIT_SIZE - 1 downto 0) := (others => '0');
36
  signal diff2_d  : signed (DATA_BIT_SIZE - 1 downto 0) := (others => '0');
37
  
38
  -- clk divider ->> Mclk/DECIMATOR_M
39
  signal clk_div_cnt : std_logic_vector(DECIMATOR_M_BIT_SIZE-1 downto 0) := (others => '0');
40
  
41
begin
42
  
43
  ----------------------------------------------------------------------------------
44
  -- Integrator @ Mclk
45
  ----------------------------------------------------------------------------------
46
  Integ_pro: process
47
  begin
48
    wait until rising_edge(Mclk); -- falling Mclk ->> data valid
49
      
50
    if rst = '1' then
51
      acc1 <= (others => '0');
52
      acc2 <= (others => '0');
53
      acc3 <= (others => '0');
54
    else
55
      if Mdata = '1' then
56
        acc1 <= acc1 + x"1";
57
      end if;
58
      acc2 <= acc2 + acc1;
59
      acc3 <= acc3 + acc2;
60
    end if;
61
  end process Integ_pro;
62
63
  ----------------------------------------------------------------------------------
64
  -- clk divider @ Mclk --> Mclk/DECIMATOR_M
65
  ----------------------------------------------------------------------------------
66
  clk_div_pro: process
67
  begin
68
    wait until rising_edge(Mclk);
69
    if rst = '1' then
70
      clk_div_cnt <= (others => '0');
71
    else
72
      clk_div_cnt <= std_logic_vector(unsigned(clk_div_cnt) + x"1");
73
    end if;
74
  end process clk_div_pro;
75
  
76
  -- wired
77
  diff_clk <= clk_div_cnt(DECIMATOR_M_BIT_SIZE-1);  -- MSB
78
  DataRate_clk <= diff_clk; 
79
  
80
  ----------------------------------------------------------------------------------
81
  -- differenciator @ falling diff_clk 
82
  ----------------------------------------------------------------------------------
83
  Diff_pro: process
84
  begin
85
    wait until falling_edge(diff_clk); -- Falling Edge!
86
      
87
    if rst = '1' then
88
      diff1 <= (others => '0');
89
      diff2 <= (others => '0');
90
      diff3 <= (others => '0');
91
      acc3_d <= (others => '0');
92
      diff1_d <= (others => '0');
93
      diff2_d <= (others => '0');
94
    else
95
      diff1 <= acc3  - acc3_d;
96
      diff2 <= diff1 - diff1_d;
97
      diff3 <= diff2 - diff2_d;
98
      
99
      acc3_d  <= acc3;
100
      diff1_d <= diff1;
101
      diff2_d <= diff2;
102
    end if;
103
  end process Diff_pro;
104
105
106
  ----------------------------------------------------------------------------------
107
  -- 16- bit DataOutput 
108
  ----------------------------------------------------------------------------------
109
110
  DataOut <= std_logic_vector(diff3(DATA_BIT_SIZE-1 downto DATA_BIT_SIZE-16)); -- 16-Bit DataOut
111
112
end Behavioral;

Mclk = 16MHz
M = 256 = 2^8 ->> f_Data_rate = Mclk/M = 16MHz/256 = 62.5 kHz ~ 16µS. 
Ist das ein langsamer AD-Wandler?
Auf dem Spartan 3a-Starerkit gibts 12-Bit, seriell DA-Wandler. Ich 
füttere den DA mit dem DataOut (16 downto 5) vom Sinc3-Filter, über ein 
asynchon-fifo. Mit einem Signal-Generator habe ich Reference-Sinus, und 
vergleiche das mit dem Ergebniss vom DA-Wandler. Bei großen Frequenz 
z.b. > 300Hz Sinus entsteht Phasenverschiebung zwischen beiden auf Ozsi, 
abhängig von Frequenz (> 15µS) wegen Tiefpassverhalten von Sinc3...

Meine Frage ist: Wie muss man genau machen, damit man ein richtiges 
AD-Ergebniss vom Delta-Sigma AD-Wandler bekommt? Ich hab den Artikel [1] 
durchgelesen, aber mir nicht klar, ob man ein Halb-Band Filter hinter 
Sinc3 schalten muss, wenn ja dann wie genau? Ist das das Ziel, dass man 
Amplitude- Attenution wegen Sinc3 (s. 7-4 in [1]) kompensieren?... [1] 
http://www.numerix-dsp.com/appsnotes/APR8-sigma-delta.pdf

vielen Dank im voraus!
Lg Tomy

von Duke Scarring (Gast)


Lesenswert?

tomy schrieb:
> Mclk = 16MHz
> M = 256 = 2^8 ->> f_Data_rate = Mclk/M = 16MHz/256 = 62.5 kHz ~ 16µS.
> Ist das ein langsamer AD-Wandler?
Ja. Es gibt inzwischen Wandler mit mehreren 100 MHz Samplerate.

Duke

von Tomy (Gast)


Lesenswert?

danke für deine Antwort!

kann jemand noch mir erklären, die Sache mir Sinc3-Filter, ob es 
ausreichend ist?

vielen Dank im Voraus!

Lg Tomy

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


Lesenswert?

tomy schrieb:
1
  clk_div_pro: process
2
  begin
3
    wait until rising_edge(Mclk);
4
    if rst = '1' then
5
      clk_div_cnt <= (others => '0');
6
    else
7
      clk_div_cnt <= std_logic_vector(unsigned(clk_div_cnt) + x"1");
8
    end if;
9
  end process clk_div_pro;
10
  
11
  -- wired
12
  diff_clk <= clk_div_cnt(DECIMATOR_M_BIT_SIZE-1);  -- MSB
13
  DataRate_clk <= diff_clk; 
14
  
15
  Diff_pro: process
16
  begin
17
    wait until falling_edge(diff_clk); -- Falling Edge!
So erzeugt man in einem FPGA keine abgeleiteten Takte. Im Idealfall hast 
du sowieso nur 1 Takt und arbeitest dann mit Clock-Enables:
1
  signal diff_enable : std_logic := '0';
2
  
3
  -- clk divider ->> Mclk/DECIMATOR_M
4
  signal clk_div_cnt : integer range 0 to 2**DECIMATOR_M_BIT_SIZE-1 := 0;
5
6
  :
7
  :
8
9
  clk_div_pro: process
10
  begin
11
    wait until rising_edge(Mclk);
12
    if clk_div_cnt = 2**DECIMATOR_M_BIT_SIZE-1 then
13
      clk_div_cnt <= 0;
14
      diff_enable <= '1';
15
    else
16
      clk_div_cnt <= clk_div_cnt+1;
17
      diff_enable <= '0';
18
    end if;
19
  end process clk_div_pro;
20
  
21
  Diff_pro: process
22
  begin
23
    wait until rising_edge(Mclk); -- es kann nur EINEN geben!
24
    if (diff_enable='1') then
25
        :

von tomy (Gast)


Lesenswert?

danke Lothar für dein Tipp:-)

kann jemand noch mir erklären, die Sache mir Sinc3-Filter, ob es
ausreichend ist?

gruß Tomy

von Duke Scarring (Gast)


Lesenswert?

tomy schrieb:
> kann jemand noch mir erklären, die Sache mir Sinc3-Filter, ob es
> ausreichend ist?
Das mußt Du wissen. Dafür macht man vorher eine Systembetrachtung und 
zur Prüfung dieser Btrachtung eine Modellsimulation. Dafür eignet sich 
z.B. ein Tool wie Matlab.

Duke

von tomy (Gast)


Lesenswert?

Duke Scarring schrieb:
> Das mußt Du wissen. Dafür macht man vorher eine Systembetrachtung und
> zur Prüfung dieser Btrachtung eine Modellsimulation. Dafür eignet sich
> z.B. ein Tool wie Matlab.

wie sieht das Systembetrachtung mit Matlab ungefähr aus? Ich hab noch 
nie einen Filter mit Matlab entworfen:( kannst du mir ein Beispeil-code 
für sinc3 geben?

lg Tomy

von Cetec F. (ftec)


Lesenswert?

if Mdata = '1' then
        acc1 <= acc1 + x"1";
      end if;


kann mir jemand erklären warum hier x"1" geschrieben wurde?

und warum nicht wie hier:

      if Mdata = '1' then
      --  acc1 <= acc1 + x"1";
      acc1 <= acc1 + acc1;
      end if;

von Cetec F. (ftec)


Lesenswert?

sorry habe mich vertippt:

>       if Mdata = '1' then
>       --  acc1 <= acc1 + x"1";
      acc1 <= acc1 + 1;
>       end if;

von Tomy (Gast)


Lesenswert?

cetec Ftec schrieb:
>>       if Mdata = '1' then
>>       --  acc1 <= acc1 + x"1";
>       acc1 <= acc1 + 1;
>>       end if;

so weit ich kenne:
weil acc1 als std_locgic_vector deklariert wurde.

Deine Variante wäre acc1 als integer.

von Cetec F. (ftec)


Lesenswert?

Danke zuerst,

Tomy schrieb:
> so weit ich kenne:
> weil acc1 als std_locgic_vector deklariert wurde.

du hast oben acc1 als unsigned deklariert.
ist es möglich deine gesamte code mit verbesserten version zu sehen und 
die Testbenc?

Gruß
Ftec

von Cetec F. (ftec)


Angehängte Dateien:

Lesenswert?

ich versuche nach dieser Muster (PDF) einen Sinc3filter zu erweitern, 
wie der Lothar oben erklärte.
aber ich kriege error:

No identifier "signed" in scope

kann mir jemand, wie man es korrigiert.

Gruß
Ftec

von Tomy (Gast)


Angehängte Dateien:

Lesenswert?

cetec Ftec schrieb:
> du hast oben acc1 als unsigned deklariert.
> ist es möglich deine gesamte code mit verbesserten version zu sehen und
> die Testbenc?

Hallo,

hier ist meine Version im Anhang, für testbench hab ich kein echtes 
AD-Model, sondern nur data-streaming aus AD-Wandler...Ich würde sagen es 
reicht erstmal für Filter Testen...

von Cetec F. (ftec)


Lesenswert?

Hallo Tomy,

danke sehr nett von dir.

in "sinc_filt" hast du einen component drin für "edge detect", dafür 
wird auch die Code benötigt oder?

Gruß
Ftec

von Tomy (Gast)


Lesenswert?

cetec Ftec schrieb:
> in "sinc_filt" hast du einen component drin für "edge detect", dafür
> wird auch die Code benötigt oder?

nein, du kannst auskommentieren

lg Tomy

von Tomy (Gast)


Angehängte Dateien:

Lesenswert?

ach doch, hier ist der im Anhang...das hab ich mir auch hier im forum 
geholt..

von Cetec F. (ftec)


Lesenswert?

Hallo Tomy,

danke nocmals.

ich versuche meine VHDL code zu simmulieren, aber ich kriege es nicht 
hin.
kannst du mir dabei helfen? ich kann meine Code hochladen.
Danke
Ftec

von Tomy (Gast)


Lesenswert?

cetec Ftec schrieb:
> kannst du mir dabei helfen? ich kann meine Code hochladen.

ich würde versuchen....

von Cetec F. (ftec)


Angehängte Dateien:

Lesenswert?

Hi,

danke, hier ist die Code.

Gruß
Ftec

von Student (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe versucht anhand des Beispiels hier im Forum selbst ein Sync3 
Filter zu schreiben.  In Testbench hatte ich „0101010101….“ Reihenfolge 
generiert, was einem level von 0.5 entsprechen sollte. Leider bekomme 
ich lauter 0000 als Ausgabe. Kann mir jemand sagen woran es liegt?

Danke im Voraus
Student

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.