




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、精選優質文檔-傾情為你奉上MATLAB設計,FPGA實現,聯合ISE和Modelsim仿真的FIR濾波器設計 摘要:本文首先利用MATLAB產生兩個頻率不一樣的正弦信號,并將這兩個正弦信號相加,得到一個混疊的波形;然后利用MATLAB設計一個FIR低通濾波器,并由Verilog實現,聯合ISE和Modelsim仿真,實現濾除頻率較高的信號,并將濾波后的數據送到MATLAB中分析。本文首先介紹FIR濾波器的基本原理,然后從目前最流行的的設計方式入手,逐步介紹FIR濾波器的設計,其流程圖如圖1所示:圖1一、 FIR濾波器的基本原理:數字濾波器是從分析信號中提取用戶需要的信息,濾去不需要的信號成分或
2、者干擾成分。數字濾波器的數學模型:線性時不變數字濾波器的數學模型在時域中可以用線性常系數差分方程給出:其等效的Z變換為: 當 全為0時,Z域系統函數只有零點,數字濾波器的單位脈沖響應有限,通常這用濾波器被稱為有限沖激響應(FIR)濾波器。它的輸出只與當前的輸入和過去的輸入有關,跟過去的輸出無關。FIR濾波器的一個重要特性是具有線性相位,即系統的相異和頻率成正比,可達到無失真傳輸。 更加詳細的介紹FIR濾波器的理論算法知識,請參考別的先關書籍資料、二、 FIR濾波器的設計及驗證:1) 由MATLAB產生FIR濾波器的輸入數據,并存放到.txt文件中用MATLAB產生兩個頻率分別為:0.5MHz和
3、2MHz的正弦信號,并將這兩個正弦信號疊加,得到一個混疊的信號,并將這個混疊信號的波形數據存放到C盤根目錄下面的matlab_wave_data.txt文件中。MATLAB實現代碼如下:clear all;fs = ; % 25M 采樣率t = 0:1/fs:0.0002; % 共0.0002 * = 5000個點f1 = ;f2 = ;signal1 = sin(2*pi*f1*t); % 頻率為 0.5MHz 的正弦信號signal2 = sin(2*pi*f2*t); % 頻率為 2.0MHz 的正弦信% 由于正、余弦波形的值在0,1之間,需要量化成16bit,先將數值放大y2 = fi
4、x(16384 + (214 - 1) * signal1); % 量化到 15bity3 = fix(16384 + (214 - 1) * signal2); % 量化到 15bity1 = y2 + y3; % 量化到 16bit% 再將放大的浮點值量化,并寫道到存放在C盤的文本中fid = fopen('c:/matlab_wave_data.txt', 'wt');fprintf(fid, '%xn', y1); % 以16進制的格式將數據存放到.txt文件中。如果不用16進制,后面% 讀數會出錯。fclose(fid);plot(y2
5、, 'b');hold on;plot(y3, 'b');hold on;plot(y1, 'r');legend('0.5MHz正弦','2MHz正弦','兩者疊加');title('MATLAB產生的兩個正弦信號的疊加波形'); 信號波形圖如圖2所示:圖2 存放數據的文件路徑、名稱已經文本的內容如圖3所示:圖3用MATLAB回讀C盤根目錄下的matlab_wave_data.txt文件,驗證存入的波形數據是否正確,MATLAB代碼如下:fid = fopen('c:/ma
6、tlab_wave_data.txt','r');for i = 1 : 5001;%一共有5001個數據num(i) = fscanf(fid, '%x', 1);%從fid所指的文件中,以16進制的方式讀出一個數據endfclose(fid);figure(2);plot(num,'b');legend('MATLAB從txt文件中讀出的原始疊加波形數據');title('直接回讀MATLAB產生的兩個正弦信號的疊加波形'); 顯示的波形如圖4所示:圖4對比圖4和圖2中的疊加波形,可知以上操作的正確性。
7、2) 用MATLAB設計FIR濾波器輸入信號是頻率別為0.5MHz和2MHz的正弦信號的疊加,我們的任務是設計一個低通濾波器濾除掉2MHz的干擾信號。因此,我們可以設計一個采樣率為25MHz的低通濾波器,其通帶帶寬為1MHz,阻帶寬度為2MHz。通帶內紋波抖動為1dB,阻帶下降為80dB。在MATLAB的命令窗口輸入:fdatool命令并回車,打開FDATool工具箱,用MATLAB的FDATool工具設計該濾波器,參數設置如圖5所示:設計好參數后,點擊DesignFilter,可以在FDATool窗口的左上角看到濾波器的階數為63階,點擊File àGenerate M-file,
8、并將濾波器命名為mylowfilter。圖5 編寫如下代碼,濾除混疊信號中的高頻信號。Hd = mylowfilter; % 濾波器名稱output = filter(Hd, y1); % 對疊加信號 y ,進行濾波處理figure(3);plot(y2, 'k');hold on;plot(output, 'r');legend('0.5MHz原始信號','濾波后取出的信號');title('信號通過MTALAB的低通濾波器后的波形'); 濾波后的波形如圖6所示:圖6生成.coe文件,用于Xilinx的IPCor
9、e設計濾波器,FDATool窗口點擊File àExport,保持默認設置,點擊Export即可,次數在MATLAB的workspace窗口多出一個Num的1*64的數組,這就是濾波器的系數,如圖7所示:圖7由于MATLAB生成的濾波器系數全是一些小數,而FPGA只能處理整數,因此我們必須將這些小數擴大一定的倍數,使它們變成整數。在MATLAB的命令窗口輸入下面的一段代碼然后按Enter,即可將上面這些系數變為整數,注意這里的*32767,表示將系數擴大32767倍,這里的擴大倍數只能選2N,目的是為了后面濾波后的波形數據的高位截取(丟掉低位,即除以2N)。返回ans=0,表示操作正
10、確。coeff=round(Num/max(abs(Num)*32767);% abs() 求絕對值,max() 求最大值,round() 四舍五入fid = fopen('e:/fircoe.txt','wt'); %將濾波器系數寫入文件件中fprintf(fid,'%16.0fn',coeff);% 將濾波器系數以16位浮點數的格式保存fclose(fid) 程序運行的結果如圖8所示:圖8將文件的格式改為.coe格式,在文件的開口加上:radix = 10;coefdata = 在每個數字前的空格處加一個逗號“,”,并在最后一個數字后面加上分
11、號“;”如圖9所示:圖9 這樣就產生了可供FIR濾波器的IPCore可調用的.coe文件。3) 用Verilog編程讀取MATLAB產生的波形數據通過Verilog的$readmemh()函數即可讀出.txt文件中的數據(這里的數據是以16進制形式存儲的),具體用法如下:reg 15 :0 data_in0:2000; /定義一個16bit * 2001的數組initial begin/ 讀出MATLAB產生的波形數據 0.5MHz_sin + 4MHz_sin 信號 $readmemh("c:/matlab_wave_data.txt", data_in); /將 mat
12、lab_wave_data.txt中的數據讀入存儲器 data_inEnd 我在modelsim中嘗試用readmemh來讀取matlab生成的數據,但是一旦到了負數的地方就出現問題了,之后的所有數據都變成了xxxxx,因此我在用MATLAB產生波形數據時都給正弦信號添加了一個偏移量,將正弦信號平移到了0之上。用Modelsim仿真工具可以看到讀出的數據,并與原文件數據(圖3)比較,可以判斷讀出的數據是否正確,這里是ISE和Modelsim聯合仿真的結果,如圖10所示:圖104) 由Xilinx的FIR的IPCore實現FIR濾波器FIR的IPCore的生成步驟就不多說了,簡單的說一下參數配置
13、情況:a) 我們使用由MATLAB生成的.coe文件導入濾波器的系數。b) 輸入信號的采樣頻率為25MHz,這里必須和MATLAB產生的波形數據的采樣頻率保持一致。c) FIR濾波器的運行時鐘,這里我們選擇250MHz,這里必須和仿真文件里給的時鐘保持一致。d) 輸入數據的類型,我們這里選擇了無符號數,輸入數據位寬為16bit,因為modelsim不能讀出負數(要么用補碼,要么加偏移)。如圖11、圖12所示:圖11圖12FIR的IPCore的列化如下:FIR16_IP FIR16_IP_ins (.clk(clk), / input clk.rfd(rfd), / output rfd 在其上
14、升沿將輸入數據加載到濾波器內核中.rdy(rdy), / output rdy 在其上升沿輸出濾波器的計算結果.din(data_in_reg), / input 15 : 0 din.dout(dout); / output 35 : 0 dout 特別注意這個數據位寬我們主要對其進行簡單的控制:在rfd 上升沿將輸入數據加載到濾波器內核中,在rdy 上升沿輸出濾波器的計算結果。具體的Verilog代碼如下:always (posedge clk) beginif(reset = 1'b0) begini<=1'b0;m<=1'b0;data_in_reg
15、<=16'h0000;endelse beginrfd_1q<=rfd;rfd_2q<=rfd_1q;if(rfd_1q & rfd) begin/ rfd 信號的上升沿將輸入數據加載到濾波器內核中data_in_reg<=data_ini;i <=i + 1;m <=m;if(i = 2002)i<=0;endendendalways (posedge clk) beginif(reset = 1'b0) beginData_out_reg<=0;j<=0;n<=0;endelse beginrdy_1q&l
16、t;=rdy;rdy_2q<=rdy_1q;if(rdy_1q & rdy) beginData_out_reg<=dout;j<=j + 1'b1;n <=n;endendend這里還做了一個附加功能,將FIR濾波器的輸入數據存放到一個.txt文件當中,然后用MATLAB去讀取這個波形文件數據,看看讀出的波形是否和原來的混疊波形一樣。具體的Verilog和MATLAB代碼如下:integer wr_file;initial wr_file = $fopen("c:/FIR_in_data.txt");always ( m ) beg
17、inif(reset = 1'b1) begin$fdisplay(wr_file,"%h", data_in_reg);/ 33bit數if(j = 11'd2002) /共寫入2001個數據$stop;endendfid = fopen('c:/FIR_in_data.txt','r');for j = 1 : 2000;num1(j) = fscanf(fid, '%x', 1);%這句話的意思是從fid所指的文件以16進制方式讀出一個數據。endfclose(fid);figure(4);plot(nu
18、m1,'r');legend('Verilog讀出的txt文件中的數據');title('FIR濾波器的輸入數據'); MATLAB讀出的波形數據如圖13所示:圖135) 將FIR濾波器的輸出存入.txt文件中有上面的步驟我們已經驗證了輸入到FIR濾波器的數據都是正確的,下面就將FIR濾波器的輸出數據保存到一個.txt文件當中供MATLAB讀取。/剛剛的問題是,matlab讀一個數據是32bit的,/而FIR的輸出是36bit的,因此高4bit根本沒有讀上來。assignData_out31:0 = Data_out_reg35:4;intege
19、r w_file;initial w_file = $fopen("c:/FIR_out.txt");always ( n ) beginif(reset = 1'b1) begin$fdisplay(w_file,"%h", Data_out31:14);/ 33bit數if(j = 11'd2002) /共寫入2001個數據$stop;endend這里我也搞了好久才搞好,這里FIR濾波器的輸出數據位寬變成了36bit,而輸入數據位寬是16bit,為什么數據會變大幾萬倍呢?因為我們在將濾波器的系數由小數變成整數的時候,對這些系數整體擴大
20、了32767倍,再做了一個四舍五入(影響濾波器精度),對濾波器的系數擴大的倍數越大,四舍五入對精度的影響就越小,但是系數乘的倍數越大,FPGA在做乘加運算也就越復雜,也就越耗時,越耗資源,因此我們需要找一個平衡點。這里為了將信號的幅度變回原始的幅度(盡可能的靠近),我們只能通過將低位截取掉,截取低位相當于對數據做除法(除2),所以前面的濾波器系數的擴大倍數我們一定要用2N,這樣我們在這里還原信號幅度的時候,只需要截位就能達到目的。比如這里我們對濾波器的系數乘了32767,那我們在做除法還原波形幅度時,只需要除以32767即可(即截掉低16bit)。還有一種操作方式就是我們只保留數據的高16bi
21、t(和輸入數據的位寬保持一致),這兩種方式波形的幅度也就幾倍的差距,我還沒有完全搞懂這里,究竟怎樣才能將波形的幅度完全的還原回去,還是一個值得好好思考的問題?另一個問題是我的電腦是32bit位寬的,如果我們一次性讓MATLAB讀取36bit的數據那么數據的高4bit會讀不上來,會導致很奇怪的波形,我也遇到了這個問題。如圖14所示,波形明顯可以通過一些平移拼合成一個正弦波。通過對波形數據一個個的分析,我找到了這個問題。圖14圖15是波形幅度發生變化的截圖:圖156) 由MATLAB讀入FIR濾波器的輸出數據,并分析濾波結果由MATLAB讀取FIR濾波器的輸出數據,分析波形,具體的代碼如下:fid
22、 = fopen('c:/FIR_out.txt','r');for i = 1 : 2000;num(i) = fscanf(fid, '%x', 1);%這句話的意思是從fid所指的文件以16進制方式讀出一個數據。endfclose(fid);figure(5);plot(num,'r');y4 = y2;hold on;plot(y4, 'k');legend('經過FIR_IPCore濾波后的數據','0.5MHz的原始數據放大16384倍');title('經過FI
23、R濾波器的輸出數據'); 波形數據如圖16所示:圖16三、 總結本次設計我大約耗時一周,從0開始研究FIR濾波器的設計,聯合了MATLAB、ISE、Modelsim三個工具,不得不佩服MABLAB在數據分析方面強大的功能。本次設計走通了FIR濾波器的總體設計流程,為以后的工程實用打下了基礎,當然還有一些基本問題,如波形幅度如何完美的還原還沒搞清楚,有待進一步研究。在實際工程應用時,我們可以通過聯合MATLAB、ISE、Modelsim三個工具完全脫離硬件來設計、仿真、驗證FIR數字濾波器的性能,肯定能夠大大的縮短設計周期,提升濾波器性能。附錄:附錄為Verilog源代碼和MATLAB源
24、代碼,這些源代碼是經過調試的,是可以直接使用的。供大家參考。Verilog源代碼:module FIR_Lowpass(clk,reset, Data_out);inputclk;inputreset;output31 :0Data_out;reg35 :0Data_out_reg;reg 10:0 i = 0;reg 10:0 j = 0;reg 15 :0 data_in0:2000; /定義一個16bit * 2001的數組reg 15:0 data_in_reg = 0;initial begin/ 讀出MATLAB產生的波形數據 0.5MHz_sin + 4MHz_sin 信號$re
25、admemh("c:/matlab_wave_data.txt", data_in); /將 matlab_wave_data.txt中的數據讀入存儲器 data_inendwirerfd;wirerdy;wire 35:0dout;regrfd_1q;regrfd_2q;regrdy_1q;regrdy_2q;regn = 0;regm = 0;always (posedge clk) beginif(reset = 1'b0) begini<=1'b0;m<=1'b0;data_in_reg<=16'h0000;ende
26、lse beginrfd_1q<=rfd;rfd_2q<=rfd_1q;if(rfd_1q & rfd) begin/ rfd 信號的上升沿將輸入數據加載到濾波器內核中data_in_reg<=data_ini;i <=i + 1;m <=m;if(i = 2002)i<=0;endendendFIR16_IP FIR16_IP_ins (.clk(clk), / input clk.rfd(rfd), / output rfd 在其上升沿將輸入數據加載到濾波器內核中.rdy(rdy), / output rdy 在其上升沿輸出濾波器的計算結果.di
27、n(data_in_reg), / input 15 : 0 din.dout(dout); / output 35 : 0 doutalways (posedge clk) beginif(reset = 1'b0) beginData_out_reg<=0;j<=0;n<=0;endelse beginrdy_1q<=rdy;rdy_2q<=rdy_1q;if(rdy_1q & rdy) beginData_out_reg<=dout;j<=j + 1'b1;n <=n;endendend/剛剛的問題是,matlab讀
28、一個數據是32bit的,而FIR的輸出是36bit的,因此高4bit根本沒有讀上來。/ assignData_out31:0 = Data_out_reg35:4;assignData_out31:0 = Data_out_reg35:4;/*integer wr_file;initial wr_file = $fopen("c:/FIR_in_data.txt");always ( m ) beginif(reset = 1'b1) begin$fdisplay(wr_file,"%h", data_in_reg);/ 33bit數if(j =
29、 11'd2002) /共寫入2001個數據$stop;endend/*integer w_file;initial w_file = $fopen("c:/FIR_out.txt");always ( n ) beginif(reset = 1'b1) begin$fdisplay(w_file,"%h", Data_out31:14);/ 33bit數if(j = 11'd2002) /共寫入2001個數據$stop;endendendmoduleMATLAB源代碼%* MATLAB產生信號并保存到.txt文件中 *clear
30、 all;fs = ; % 25M 采樣率t = 0:1/fs:0.0002;% 共0.0002 * = 5000個點f1 = ;f2 = ;signal1 = sin(2*pi*f1*t); % 頻率為 0.5MHz 的正弦信號signal2 = sin(2*pi*f2*t); % 頻率為 4.0MHz 的正弦信號%y1 = signal1 + signal2; % 兩個正弦信號疊加%x = linspace(0, 12.56, 2048); % 在區間0,6.28 = 2*pi 之間等間隔的取1024個點%y1 = sin(x); % 計算相應的余弦值% 由于正、余弦波形的值在0,1之間,
31、需要量化成16bit,先將數值放大%y1 = y1 * 32768; % 32 * 1024 = 32768%y1 = y1 * 16384; % 32 * 1024 = 32768%y1 = y1 + 32768;y2 = fix(16384 + (214 - 1) * signal1);y3 = fix(16384 + (214 - 1) * signal2);y1 = y2 + y3;% 再將放大的浮點值量化,并寫道到存放在C盤的文本中fid = fopen('c:/matlab_wave_data.txt', 'wt');%fprintf(fid,
32、39;%16.0fn', y1); % 在寫文件時量化為16bit的定點實數【%16.0f,16.0表示16bit定點數,f表示實數】,范圍是: -32768 - 32767fprintf(fid, '%xn', y1); % 在寫文件時量化為16bit的定點實數【%16.0f,16.0表示16bit定點數,f表示實數】,范圍是: -32768 - 32767fclose(fid);figure(1);plot(y2, 'b');hold on;plot(y3, 'b');hold on;plot(y1, 'r');legend('0.5MHz正弦','2MHz正弦','兩者疊加');title('MATLAB產生的兩個正弦信號的疊加波形');%* MATLAB回讀保存到.txt文件中的信號 *fid = fopen('c:/matlab_wave_data.txt','r');for i = 1 : 5001;%num(i) = fscanf(fid, '%f', 1);%從fid所指的文件中,以實數的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 供暖項目轉讓合同標準文本
- 會場出租合同標準文本
- 農村地皮出售合同樣本
- 行業專家的知識分享與傳播計劃
- 上海住房合同標準文本
- 人防工程租用合同樣本
- 出售塔吊電纜合同標準文本
- 冷凍食品合同樣本
- 兼職合同樣本正規
- 出售舊木頭房屋合同標準文本
- 《山谷回音真好聽》名師課件(簡譜)
- 醫院抗菌藥物臨時采購使用申請表
- 高考英語核心詞匯1000個
- 校園海綿城市設計方案
- GB/T 4706.66-2024家用和類似用途電器的安全第66部分:泵的特殊要求
- GB/T 4706.1-2024家用和類似用途電器的安全第1部分:通用要求
- 2022年6月英語四級真題 第一套
- 《事故汽車常用零部件修復與更換判別規范》
- 2023-2024學年河南省安陽市殷都區八年級(下)期末數學試卷(含答案)
- 江蘇省蘇州市昆山、太倉、常熟、張家港市2023-2024學年七年級下學期語文期末試卷
- 家族辦公室公司章程
評論
0/150
提交評論