Forum: FPGA, VHDL & Co. FIR-Filter mit Eingangsrate > Ausgangsrate


von Jan (Gast)


Lesenswert?

Moin zusammen!

Ich versuche gerade folgendes FIR-Filter zu implementieren:
  H(z)=0.25 * [(1-z^-4) / (1-z^-1)]
Der Ausgang sollte also so aussehen:
  y(n)=0.25*x(n) + y(n-1) - 0.25*x(n-4)
Für den 1.Term shifte ich das Eingangssignal um 2 Bits nach rechts.
Der 2.Term gebe ich das Ausgangssignal y(n) auf ein Register und
für den 3. Term shifte ich um 2 Bits nach rechts und gebe das Signal auf 
ein Shift-Register mit 4 Stufen.

Soweit kein Problem.
Jedoch soll das Filter eine Verhältnis von Eingangs- zu Ausgangsfrequenz 
von 4 haben und der Ausgang ein Bit breiter sein.
  Z.B. Eingang: 16Bit@32MHz, Ausgang: 17Bit@8MHz
Meine Idee war nun, dass ich in diesem Fall das Schieberegister mit 4 
Stufen auf ein Register mit Enable-Signal reduzieren kann und ein 
gleiches Register für den Ausgang benutze.

Meine Frage ist erstmal, ob ich bis hierhin schon einen Denkfehler 
gemacht habe, oder sich das alles so richtig anhört :)

von J. S. (engineer) Benutzerseite


Lesenswert?

Wozu brauchst du das Schieberegister? Du verdrahtest in VHDL direkt um.

Oder ist das Wortregister = Wertespeicher gemeint?

Bei einer DDC, die Du faktisch durchführst, ignorierst Du einfach 3 von 
4 Worten. Dazu schiebst Du die Werte nacheinander durch eine pipeline 
und greifst die Taps direkt ab.

Der Filter schaut mir aber etwas komisch aus für diese Anwendung. Wenn 
das ein Dezimationsfilter werden soll, siehe mal nach CIC.

von Jan (Gast)


Lesenswert?

Hi,

mit Schieberegister meinte ich dann Wortregister. Ich muss den 
Eingangswert viermal verzögern, wegen x(n-4).

Jürgen S. schrieb:
> Bei einer DDC, die Du faktisch durchführst, ignorierst Du einfach 3 von
> 4 Worten. Dazu schiebst Du die Werte nacheinander durch eine pipeline
> und greifst die Taps direkt ab.
Ich dachte, dass ich so ggf. Register einsparen kann, in dem ich am 
Register nur zu jedem vierten Takt den Eingangswert übernehme.

Der Filter soll erstmal nur zum Ausprobieren sein, weil ich noch keine 
Filter in VHDL implementiert habe.

Ist meine Ausführung denn in der Theorie soweit richtig?

von J. S. (engineer) Benutzerseite


Lesenswert?

Wenn das DDC gelingen soll, musst Du vorher Filtern. Du musst also eine 
entsprechende Zahl von Registern füttern und auswerten. Um die kommst Du 
nicht herum. Du bekommst dann für jeden neuen Wert einen neuen 
gefilterten Wert aus der pipeline, von denen Du jeden 4. nutzt. Wenn Du 
schon am Eingang vor der Filterung verwirfst, hast Du Aliaseffekte.

von Jan (Gast)


Lesenswert?

Ich habe das ganze mal in vhdl geschrieben, dabei werden alle Werte 
verarbeitet, aber am Ausgangsregister nur jede 4. Wert gespeichert.
Habe ich das so richtig verstanden?
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity filter2 is
6
    port(
7
        CLK : in  std_logic;                    --Clock
8
        X   : in  std_logic_vector(8 downto 0); --9Bit input
9
        Y   : out std_logic_vector(14 downto 0) --15bit output
10
    );
11
end filter2;
12
13
architecture Behavioral of filter2 is
14
    signal y_0 : std_logic_vector(14 downto 0);
15
    signal y_1 : std_logic_vector(14 downto 0);
16
    signal x_1 : std_logic_vector(8 downto 0);
17
    signal x_2 : std_logic_vector(8 downto 0);
18
    signal x_3 : std_logic_vector(8 downto 0);
19
    signal x_4 : std_logic_vector(8 downto 0);
20
    signal xsum  : std_logic_vector(8 downto 0);
21
    signal xsumq : std_logic_vector(14 downto 0);
22
    signal cnt : std_logic_vector(1 downto 0);
23
24
begin
25
    --Sum of x(n), x(n-4) ;  8bit addition
26
    xsum <= std_logic_vector(signed(X)-signed(x_4));
27
    
28
    --Quarter of xsum & 8bit -> 15bit
29
    --       positiv                                             negative
30
    xsumq <= "00000000" & xsum(8 downto 2) when xsum(8)='0' else "11111111" & xsum(8 downto 2);
31
    
32
    --Registers
33
    Registers : process(CLK, X, y_0)
34
    begin
35
        if rising_edge(CLK) then
36
            y_1 <= y_0;
37
            
38
            x_1 <= X;
39
            x_2 <= x_1;
40
            x_3 <= x_2;
41
            x_4 <= x_3;
42
            
43
            --Output register ;   15bit addition
44
            if cnt="11" then
45
                y_0 <= std_logic_vector(signed(xsumq)+signed(y_1));
46
            else
47
                y_0 <= y_0;
48
            end if;--cnt
49
        end if;--CLK
50
    end process Registers;
51
    
52
    --Counter
53
    Counter : process(CLK)
54
    begin
55
        if rising_edge(CLK) then
56
            cnt <= std_logic_vector(unsigned(cnt)+1);
57
        end if;--CLK
58
    end process Counter;
59
    
60
    --Y output
61
    Y <= y_0;
62
    
63
end Behavioral;

von Johannes E. (cpt_nemo)


Lesenswert?

Jan schrieb:
> Ich versuche gerade folgendes FIR-Filter zu implementieren:
>   H(z)=0.25 * [(1-z^-4) / (1-z^-1)]

Das sieht für mich eher nach einem IIR-Filter aus...

> if cnt="11" then
>     y_0 <= std_logic_vector(signed(xsumq)+signed(y_1));
> else
>     y_0 <= y_0;
> end if;--cnt

Das ist so nicht richtig. Du berechnest Y_0 nur in jedem 4. Takt und das 
wird dann in y_1 kopiert. Damit ist die Übertragungsfunktion nicht so 
wie gewünscht.
Definiere besser y_0 als Variable, die ständig berechnet wird, danach 
kommt die Zuweisung y_1 = y_0.

Für die Abtastung mit langsamerer Frequenz definierst du dann noch ein 
Ausgangsregister, z.B. y_out = y_0, das mit cnt="11" enabled wird. 
Wichtig ist, dass das langsame Register nur für den Ausgang verwendet 
wird und nicht für die Berechnung innerhalb des Filters.

von Jan (Gast)


Lesenswert?

Super, danke euch beiden für die Hilfe!

von Mirco (Gast)


Lesenswert?

Johannes E. schrieb:
> Das sieht für mich eher nach einem IIR-Filter aus...
Für mich auch und zwar nach einem unnötig kompliziert formulitertem..

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.