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 :)
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.
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?
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.
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; |
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.