Forum: FPGA, VHDL & Co. Sigma-Delta: CIC-Decimation Filter in VHDL -- seltsames Verhalten?


von marvin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

ich arbeite zur Zeit daran ein Mikrofon mit einem Pulsdichtemoduliertem 
1Bit-breiten Sigma-Delta Ausgang mittels VHDL an einem Spartan3-FPGA 
anzusprechen. Dazu wollte ich einen CIC-Decimation Filter (Hogenhauer 
Filter, N=5, R=256, M=1) zusammen mit einem nachgeschalteten 
FIR-Compensation Filter (61 taps) verwenden. Im Endeffekt soll der FPGA 
8Bit PCM-Samples mit 9000Hz über eine RS232-Schnittstelle an einen PC 
übertragen.

Der FIR-Filter selber kommt als IP-Core daher, die Koeffizienten hab 
ich. Den CIC-Teil muss ich selbst implementieren.

Leider tu ich mich da sehr schwer... Das Ausgangssignal der Simulation 
mit bereits geschriebenem VHDL-Code und einem Testsample hört sich 
übelst an. So als ob das Mikrofon stark übersteuert. Also begebe ich 
mich auf Fehlersuche...

In Matlab hab ich so einen Filter stehen. Bei der Übertragung in VHDL 
habe ich zwar eigentlich auch keine Fehler gemacht... Aber fangen wir 
von vorne an. Könnte vielleicht mal jemand einen Blick drauf werfen, 
seinen Senf geben? Erst eine Funktion um ein Sample zu Filtern, dann das 
Plotten der Impulsantwort. Matlab/Octave.
1
%%
2
% Teil 1
3
%%
4
function [y] = cic_octave(x, M, N, R)
5
6
reg_int=zeros(1,N);
7
reg_comb=zeros(N,M+2);%erste spalte
8
l=1;
9
10
for i=1:length(x)
11
12
    % Integrieren:
13
    if (N==1)
14
        reg_int = x(i) + reg_int;
15
    else
16
        reg_int = [x(i) reg_int(1:end-1)] + reg_int;
17
    end
18
    % Dezimieren:
19
    if (mod(i,R)==0)
20
        reg_comb = [[reg_int(end); reg_comb(1:end-1,end)] reg_comb(:,1:end-1)];
21
        reg_comb(:,end) = reg_comb(:,1) - reg_comb(:,end-1);
22
        y(l) = reg_comb(end,end);
23
        l=l+1;
24
    end
25
end
26
27
% Verstaerkung kompensieren:
28
y = y/((M*R)^N);
29
30
end%function
31
32
%%
33
%  Teil 2
34
%% 
35
function [y]=cic_response( M, N, R )
36
37
x = [0 0 0 1 zeros(1,1024*2^5-1)];
38
y = cic_octave(x, M, N, R);
39
40
Y = fft(y);
41
YY=abs(Y)/max(abs(Y));
42
YY_dB=20*log10(YY(1:length(YY)/2));
43
44
plot(linspace(0,1,length(YY_dB)),YY_dB);
45
titlename = sprintf('CIC Frequenzgang\nR=%i M=%i N=%i',R,M,N);
46
title(titlename);
47
xlabel('Omega');
48
ylabel('A in dB');
49
50
end%function

Den Filter hatte ich in kompliziert auch schon geschrieben, aber dann 
nochmal aus einer übersichtlichen Diplomarbeit[1] übernommen. Der Code 
für den CIC-Filter sieht ja ganz nett aus, aber ich stehe vor dem 
Problem das Ergebnis zu interpretieren.

Wenn ich eine Impulsantwort generiere, sollte ich doch aus der 
Fouriertransformierten den Frequenzgang erstellen können? Denjenigen 
welchen ich herausbekomme kann man aber gar nicht mit dem für CIC-Filter 
auf Einschlägigen Seiten vergleichen. Ich vermisse die "Nebenkeulen", 
die "Aliasbänder", das "nachhoppeln" der Kennlinie...

Für kleine Werte von R (zB R=4) kommt beim Frequenzgang Mumpitz heraus, 
aber das schiebe ich mal auf Rundungsfehler in Octave?

[1] http://opus.haw-hamburg.de/volltexte/2009/750/

von Michael O. (mischu)


Lesenswert?

Ein super Trick bei FIR Filtern ist einfach mal alle Koeffizienten bis 
auf einen zu Null zu setzen. Wenn dann immer noch Blödsinn herauskommt, 
liegt es nicht an der Übertragungsfunktion.

Versuch das Problem in einzelne Blöcke zu teilen.
Du könntest Deinen CIC-Teil mit einer vordefinierten Datenfolge aus dem 
internen RAM füttern und dir die Impulsantwort anschauen.

Ebenso kannst Du dir einen Test-Generator für das pulsdichtemodulierte 
Signal bauen und so den Decimation-Teil testen.

Leider bringt es nix fünf ungetestete Teile zusammen zu dengeln und 
hinterher zu fragen, warum das Gesamtsystem es nicht tut.

von Duke Scarring (Gast)


Lesenswert?

marvin schrieb:
> Den CIC-Teil muss ich selbst implementieren.
Bei Xilinx gibt es im Coregen den CIC-Compiler. Vielleicht kann der Dir 
weiterhelfen.

Ansonsten, wie mischu schon schrieb, teile und herrsche:
Da Du ein Referenzmodell hast kannst Du Deinen VHDL-Code simulieren 
(Stichwort VHDL Testbench) und die Werte vergleichen.

Duke

von marvin (Gast)


Lesenswert?

Ja das ist ja auch mein Gedanke gewesen. Deswegen wollte ich sicher 
gehen das mein CIC-Modell in Matlab richtig arbeitet. Eben weil die 
Ergebnisse nicht das sind, was ich erwarten würde. Den Frequenzgang 
würde ich gar nicht so erwarten wie ich ihn im ersten Post angehängt 
hab...

Den CIC-Compiler kann ich leider nicht nehmen da ich aus völlig 
unverständlichen Gründen die Xilinx Version 10.4 verwenden muss, welche 
nur den CIC-Compiler 3.0 mitliefert -- dieser Version fehlt aber der 
Support für meinen Spartan3!

von steve (Gast)


Lesenswert?

hallo, möchte fragen.
ist es möglich eine genau R=1000 zu setzen? oder muss ich
in konstellation  bitzahl (hier=1024) nehmen?
mir ist noch verwirren.. Vielen Dank..

von marvin (Gast)


Lesenswert?

Hi Steve

klar, theoretisch beziehungsweise in Matlab/Octave kannst du jedes R 
nehmen, wie du willst. Aber die Hardwareimplementierung wird 
effizienter, wenn du Potenzen von 2 als Teiler nimmst -- einfach weil du 
einen Zähler- und Vergleichbaustein brauchst, welcher alle 1000 Samples 
die nächste Stufe antippt. So ein Zähler ist aber in einer Schaltung 
einfacher zu bauen, wenn er nur alle 1024 Samples tippen muss.

von steve (Gast)


Lesenswert?

Hallo Marvin,
danke dir für deine Aufklärung..
kannst du (oder anderen) mir nochmal erklaren bitte.

es steht in der Literatur M=Delay.
(nach der Noble-identity, wo R steht zwischen Integrator und Comb)
ist M verhält sich als Teiler von R? was spielt eigentlich M hier?

meine Aufgabe besteht darin, dass ich
aus bereit abgetastete Eingangssignal 192Mhz
um 192Khz dezimiere, also welche Werte R und M wähle ich?
ich habe die Werte von Frequenz 192Mhz, M=1 und R=1000 ohne Skalierung 
einfach eingeben, aber irgendwie
geht mein Rechner sehr langsam. Danke nochmals..

Steve

von marvin (Gast)


Angehängte Dateien:

Lesenswert?

Antwort mit eigener Frage angehängt ;-)
-----------------------------------------------------------

Ich würde mir mal das Paper von Eugene Hogenhauer ansehen, wo er die 
CIC-Filter beschreibt (einfach bei Google suchen, da gibts nichts 
anderes). Finde ich im Nachhinein(!) am hilfreichsten, wenn auch nicht 
am übersichtlichsten.

R ist der Rate-Change -- also der Frequenz-Faktor zwischen dem linken 
und rechten Teil der Schaltung. Das ist die Eigenschaft um eine 
Dezimation zu erreichen.

M ist der Unit-Delay, und sagt aus, wie lange die Comb-Sektionen jeweils 
ein Signal zwischenspeichern sollen, bevor es wieder subtrahiert wird. 
Dieser Parameter sorgt für breitere "Gaps" zwischen den "Beulen" im 
Frequenzgang und ist normalerweise sowieso 1 oder 2. Ich denke mal du 
bist mit 1 gut beraten!

N ist die Anzahl der Integrator- und Comb-Stufen. Er sorgt für steilere 
Flanken im Frequenzgang. Das hängt von deiner Anwendung ab, was du da 
haben willst -- Werte von 1 bis 5 sind vielleicht "üblich".

Wenn du ein 192Mhz Signal auf 192kHz downsamplen willst, scheinst du 
durchaus einen glatten 1000er als Teiler nehmen zu können. Das die 
Berechnung aufwendig ist stellt auch niemand in Frage ;-)

-----------------------------------------------------------

Ich hab vielleicht aber noch eine Frage an das geneigte Publikum. Wie 
sollte denn die Antwort eines CIC-Filters auf ein Rechtecksignal 
aussehen? Wie also verhält sich der Ausgang bei einem Sprung auf "1" am 
Eingang?

Meiner Meinung nach sollte doch jeder reguläre Filter irgendwann auch 1 
erreichen. Meine implementierung erreicht aber irgendwie genau -1. Auch 
wenn ich -1 an den Eingang lege komm -1 heraus... Seltsames Verhalten 
oder Realität?

Ich hab mal einen Plot des Problems angehängt (Hier die Version mit -1 
am Eingang, der Ausgang ist aber der gleiche wie bei +1... Das kann ich 
mir nicht erklären, wo ich noch einen Fehler gemacht haben sollte in 
meinem VHDL-Code... Nicht das der Ausgang am Ende doch immer so 
aussieht...???

von marvin (Gast)


Lesenswert?

äh, die Impulsantwort des gleichen Filters sieht übrigens gut aus...

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.