www.mikrocontroller.net

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


Autor: marvin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.
%%
% Teil 1
%%
function [y] = cic_octave(x, M, N, R)

reg_int=zeros(1,N);
reg_comb=zeros(N,M+2);%erste spalte
l=1;

for i=1:length(x)

    % Integrieren:
    if (N==1)
        reg_int = x(i) + reg_int;
    else
        reg_int = [x(i) reg_int(1:end-1)] + reg_int;
    end
    % Dezimieren:
    if (mod(i,R)==0)
        reg_comb = [[reg_int(end); reg_comb(1:end-1,end)] reg_comb(:,1:end-1)];
        reg_comb(:,end) = reg_comb(:,1) - reg_comb(:,end-1);
        y(l) = reg_comb(end,end);
        l=l+1;
    end
end

% Verstaerkung kompensieren:
y = y/((M*R)^N);

end%function

%%
%  Teil 2
%% 
function [y]=cic_response( M, N, R )

x = [0 0 0 1 zeros(1,1024*2^5-1)];
y = cic_octave(x, M, N, R);

Y = fft(y);
YY=abs(Y)/max(abs(Y));
YY_dB=20*log10(YY(1:length(YY)/2));

plot(linspace(0,1,length(YY_dB)),YY_dB);
titlename = sprintf('CIC Frequenzgang\nR=%i M=%i N=%i',R,M,N);
title(titlename);
xlabel('Omega');
ylabel('A in dB');

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/

Autor: Michael O. (mischu)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: marvin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: steve (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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..

Autor: marvin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: steve (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: marvin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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...???

Autor: marvin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
äh, die Impulsantwort des gleichen Filters sieht übrigens gut aus...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.