利用FPGA的IP覈實現FIR濾波器

一、首先是設計指標:

採用最優化設計方法(firpm),設計一個階數爲16階(長度爲17)的線性相位低通FIR濾波器,截止頻率爲500hz,fs=2000hz。,係數量化位數爲12bit,輸入數據位寬爲12bit,輸出數據位寬爲25Bit,系統時鐘爲2khz。

 

二、設計流程:

(1)利用MATLAB設計濾波器係數,浮點數類型。

(2)Matlab測試濾波器性能,輸入觀察輸出。

(3)利用FPGA的FIR濾波器IP核設計濾波器。

(4)編寫testbench,測試濾波器性能。輸入Matlab產生的激勵文本文件,

             輸出硬件處理後的信號,寫入文本文件中。

(5)Matlab分析硬件處理後保存在文本文件中的信號。

三、設計步驟:

1,利用MATLAB設計濾波器係數。代碼如下:

function hn=Fir_Coefficient_Design

N=17;      %濾波器長度

Sample_Freq=2000;   %採樣頻率

fc=500;    %低通濾波器的通帶截止頻率

B=12;      %量化位數

Cut_Off_Freq=[0 500 700 Sample_Freq/2];

Cut_Off_Freq=Cut_Off_Freq./(Sample_Freq/2); %歸一化

Fir_Amplitude=[1 1 0 0];

Fir_Coefficient=firpm(N-1,Cut_Off_Freq,Fir_Amplitude);

hn=Fir_Coefficient;

freqz(Fir_Coefficient,1,1024,Sample_Freq);

 

注意MATLAB中頻率歸一化是針對fs/2,即採樣率的一半。

接下來將濾波器係數寫入文本文件中,

fid=fopen('Fir_Coefficient.txt','w');

for k=1:length(Fir_Coefficient)    

      fprintf(fid,'%.14f',Fir_Coefficient(k));

      if(k~=length(Fir_Coefficient) )          

       fprintf(fid,'\r\n');

      end

end

fclose(fid);

由於採用FIR Complier13.0,其中的用戶手冊有這麼一句:

 

 

需要注意的就是最後一個係數後面不能有回車,否則導入係數文件的時候又會被FIR Complier識別爲一個新的係數。這樣,係數就被寫進了文本文件Fir_Coefficient.txt

(2)Matlab測試濾波器性能,輸入觀察輸出。

    思路就是生成兩個信號,一個在通帶內,一個在阻帶內,然後調用filter函數進行濾波處理,觀察輸出信號的頻譜。代碼如下:    

f1=200;       %信號1頻率爲200Hz

f2=800;       %信號2頻率爲800Hz

Fs=2000;      %採樣頻率爲2KHz

N=12;         %量化位數

t=0:1/Fs:1;

c1=2*pi*f1*t;

c2=2*pi*f2*t;

s1=sin(c1);%產生正弦波

s2=sin(c2);%產生正弦波

s=s1+s2;   %產生兩個單載波合成後的信號

s=s/max(abs(s));%歸一化處理

Q_s=round(s*(2^(N-1)-1));%12比特量化

%調用自已設計的濾波器函數對信號進行濾波

hn=Fir_Coefficient_Design;

Filter_s=filter(hn,1,Q_s);

然後觀察輸入輸出頻譜:可以看到800hz處的信號被衰減在-40db一下,符

合要求。

 

 

接下來將測試信號以二進制數據格式寫入Excitation_Signal_Bin.txt文件中,供給第四步仿真FPGA時testbench調用。

    fid=fopen('Excitation_Signal_Bin.txt','w');

for i=1:length(Q_s)

   B_s=dec2bin(Q_s(i)+(Q_s(i)<0)*2^N,N)

   for j=1:N

      if B_s(j)=='1'

          tb=1;

      else

          tb=0;

      end

      fprintf(fid,'%d',tb);  

   end

   fprintf(fid,'\r\n');

end

fprintf(fid,';');

fclose(fid);

 

(3)利用FPGA的FIR濾波器IP核設計濾波器。

 

    這個Altera提供的FIR Compiler v13.0有些老了,現在有FIR Compiler II v13.0,也就是2.0版本的FIR的IP核。這裏還是用FIR Compiler v13.0吧,2.0版本日後再研究研究。

    打開MegaWizard Plug-In Manager,選擇FIR Compiler v13.0,特別需要注意的是文件保存位置!只能保存在當前的工程目錄下,不能放在別的文件夾裏面!如果不放在工程目錄下,後一步的modeisim仿真就會出錯!

    

 接下來就是參數設置,單擊上方的"Edit Coefficient",跳出"Coefficient Generator Dialog"對話框,選擇下方的"Imported Coefficient Set",導入之前設計的濾波器係數"Fir_Coefficient.txt"。

    輸入輸出聲明如下,輸入一路,有符號二進制數,輸入位寬12bit,輸出選擇基於"實際的係數","全精度"。輸出位寬這裏計算出是25bit。

     

係數量化單位選擇12bit,濾波器結構選擇"分佈式算法,全並行結構",流水級數選擇1,數據和濾波器係數的存儲都選擇"Logic Cells"。這裏 有什麼不懂的,就要多看用戶手冊,寫的比較清楚。

 

     

 

接下來選擇step 2,生成仿真文件,選擇"Verilog HDL",還可以生成.m文件供MATLAB進行仿真分析,最後,Step3: Generate,這樣整個濾波器便設計完成了。

接下來編寫.v文件例化,即可。其輸入輸出信號參見IP核用戶手冊即可。這裏給出代碼參考:

    module Fir_FPGA (

    reset_n,clk,Xin,

    Yout);    

    input        reset_n;   //復位信號,低電平有效

    input        clk;       //FPGA系統時鐘/數據速率:2kHz

    input     signed [11:0]    Xin;  //數據輸入頻率爲2kHZ

    output signed [24:0]    Yout; //濾波後的輸出數據

    wire ast_sink_valid,ast_source_ready,ast_source_valid;

    wire [1:0] ast_source_error;

    wire [1:0] ast_sink_error;

    assign ast_sink_valid=1'b1;

    assign ast_source_ready=1'b1;

    assign ast_sink_error=2'd0;

    fir    u_fir(

        .clk(clk),

        .reset_n(reset_n),

        .ast_sink_data(Xin),

        .ast_sink_valid(ast_sink_valid),

        .ast_source_ready(ast_source_ready),

        .ast_sink_error(ast_sink_error),

        .ast_source_data(Yout),

        .ast_sink_ready(ast_sink_ready),

        .ast_source_valid(ast_source_valid),

        .ast_source_error(ast_source_error));

(4)編寫testbench,測試濾波器性能。    

主要就是將第二步MATLAB生成的激勵信號輸入module,然後將輸出寫入文本文件,供下一步MATLAB進行分析。

    這裏採用Quartus II 軟件的"processing->start->start Test Bench Template Writer"選項自動生成模塊測試文件(Fir_FPGA.vt),該目錄自動存儲在"工程目錄\simulation\modelsim"下,然後打開文件,編寫文件即可。主要是時鐘,復位信號,按照時鐘節拍輸入和輸出數據。這裏給出輸入和輸出:

    //從外部TX文件(SinIn.txt)讀入數據作爲測試激勵

integer Pattern;

reg [11:0] stimulus[1:data_num];

initial

begin

  //文件必須放置在"工程目錄\simulation\modelsim"路徑下    

    $readmemb("Excitation_Signal_Bin.txt",stimulus);

    Pattern=0;

    repeat(data_num)

        begin

            Pattern=Pattern+1;

            Xin=stimulus[Pattern];

            #clk_period;//採用並行結構,數據週期等於時鐘週期

        end

end

 

//將仿真數據dout寫入外部TXT文件中(Response_Signal.txt)

integer file_out;

initial

begin

  //文件放置在"工程目錄\simulation\modelsim"路徑下                                                  

    file_out = $fopen("Response_Signal.txt");

    if(!file_out)

        begin

            $display("could not open file!");

            $finish;

        end

end

wire rst_write;

wire signed [24:0] dout_s;

assign dout_s = Yout;                   //將dout轉換成有符號數據

assign rst_write = clk& (reset_n);//產生寫入時鐘信號,復位狀態時不寫入數據

always @(posedge rst_write )

    $fdisplay(file_out,"%d",dout_s);

    然後在quartus ii中設置"Assignment->Settings"選擇"EDA Tool Setting",設

置如下:主要就是選擇modelsim。

 

    再選擇下邊的"Simulation",設置仿真工具名稱(Modelsin-Altera),下面的NativeLink setting,選中第二項"Compile test bench",選擇上面編輯的Fir_FPGA.vt,設置好名稱之類的選項後,選擇quartus ii 中的"Tool->Run simulation tool->RT Simulation",就可以啓動Modelsim進行仿真。仿真完成後,處理後數據自動保存在Response_Signal.txt中。

 

(5)Matlab分析硬件處理後保存在文本文件中的信號。

 

    最後,用MATLAB分析Response_Signal.txt中的數據,主要就是輸入輸出的頻譜情況。分析結果如下:    

 可以看到,800hz處信號被衰減,達到預期效果。

四、總結

(1)Fir濾波器階數=抽頭數目減去1。

(2)firpm函數使用偶數階係數,偶對稱,總是在奈奎斯特頻率處不爲0。

(3).m文件返回值,可以在函數中指出。例如

function hn=Fir_Coefficient_Design

代碼……

Fir_Coefficient=firpm(N-1,Cut_Off_Freq,Fir_Amplitude);

hn=Fir_Coefficient;

(4)也是困擾了我一晚上的,生成的IP核按照CB哥的教程放入自己新建的core文件夾下,啓動modelsim進行仿真時總是提示" Library auk_dspip_lib not found",提示找不到這個庫。

    

 

後來google了一下,在這個網址下

"http://www.alteraforum.com/forum/showthread.php?t=29063"。一哥們給出解答:"Move your generated megafunction files back to the main project folder",需要把生成的FIR IP核全部文件放在工程目錄下,好像這個Bug不影響其他的IP核,呵呵,日後用到其他IP核再說。


轉自:http://blog.chinaaet.com/teenagerold/p/5100051606

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章