關於Altera多通道FIR II濾波器使用詳解

首先給出FIR II IP核的Avalon-ST接口的各信號定義

以上是所有的信號線說明。

下面我們打開FIR II IP核的界面

首先我們在Filter Specifcation界面下,一般我們需要配置的是紅色框1、2、3中的內容,其中紅色框1是來設置通道的個數的這裏我們有192個通道,紅色框2是設置模塊的工作頻率的這裏設置爲96MHz,紅色框3爲設置單個通道的數據率的這裏設置爲1MHz,設置好了以後我們發現我們一共有192個通道,而數據率爲1MHz,模塊的總時鐘爲96MHz,如果一個時鐘只傳輸一個通道的數據的話,那麼時間顯然是不夠的,這時我們就需要每個時鐘傳輸兩個通道的數據。這裏我們在紅色框4可以看出來,ast_sink_data表示輸入的數據,它是32位的,而一個通道的數據爲16位(後面會介紹),因此它的低16位表示一個通道,高16位表示另一個通道,這樣就可以在一個時鐘內輸入同時輸入兩個通道的數據。紅色框5ast_source_data表示輸出的數據,它是64位的,而一個通道的輸出數據位32位(後面會介紹),因此它的低32位表示一個通道,高32位表示另一個通道,這樣就可以在一個時鐘內輸出兩個通達的數據,這和輸入的情況的是一致的。

接下來我們點擊Coefficient Settings界面

這裏我們一般只需要設置紅色框內的係數量化位數,我們設置的是12位的,這裏可以根據我們對精度的要求而改變

接下來我們點擊Coefficients界面

該界面位濾波器係數設置界面,一般我們需要從外部文件導入,點擊紅色框的按鈕即可導入,一般我們會先由matlab設計好後生成txt文件後導入。

接下來點擊Input/Output Options界面

其中紅色框1表示設置單個通道的數據寬度,這裏我們設置爲16位。紅色框2表示將輸出的數據高位截掉的位數,這裏我們不截掉,所有輸入0。紅色框3表示將輸出的數據低位截掉的位數,這裏我們截掉了2位,這樣輸出的數據寬度就變成了32的了。

接下來點擊Implementation Options界面

一般需要選擇的是速度等級,這裏我們選擇中等。

最後一個界面Reconfigurability一般不勾選

設置好了以後我們就可以生成對應的IP核了。

下面給出的是測試用的verilog代碼:

//多通道FIR測試
module HEU_ACam001
(
	input wire MAIN_CLK,   //T21
	input wire nRST,       //AD6
	
//	input  wire [31:0] ast_sink_data,      //   avalon_streaming_sink.data
//	input  wire        ast_sink_valid,     //                        .valid
//	input  wire [1:0]  ast_sink_error,     //                        .error
//	input  wire        ast_sink_sop,       //                        .startofpacket
//	input  wire        ast_sink_eop,       //                        .endofpacket
	output wire [31:0] source_data,
	output wire [63:0] ast_source_data,    // avalon_streaming_source.data
	output wire        ast_source_valid,   //                        .valid
	output wire [1:0]  ast_source_error,   //                        .error
	output wire        ast_source_sop,     //                        .startofpacket
	output wire        ast_source_eop,     //                        .endofpacket
	output wire [6:0]  ast_source_channel  //                        .channel

);

//----------------------------------------------------上電延時復位------------------------------------------
parameter REST_CNT_MAX=50_000;
reg reset_n;
reg [15:0]reset_cnt;

always @(posedge MAIN_CLK)
begin
	if(~nRST)
		begin 
			reset_n <= 0;
			reset_cnt <= 0;
		end 
	else 
		begin 
			if(reset_cnt < REST_CNT_MAX)
				begin 
					reset_n <= 0;   //保持復位
					reset_cnt <= reset_cnt + 1;  //自加1
				end 
			else
				begin 
					reset_n <= 1;   //退出復位
					reset_cnt <= reset_cnt;   //保持
				end 
		end 
end 
//-------------------------------------------------------默認設置------------------------------------------------
wire [1:0]  ast_sink_error/*synthesis keep*/; 
assign ast_sink_error = 2'b00;
//------------------------------------------------------數據寫入邏輯----------------------------------------
parameter MAX_FIR_data_clk_cnt = 95;
reg [31:0] ast_sink_data;
reg        ast_sink_valid;
reg        ast_sink_sop;        
reg        ast_sink_eop;   
reg [6:0]  FIR_data_clk_cnt;
reg signed [15:0] FIR_data;

always @(negedge MAIN_CLK)
begin 
	if(~nRST)
		begin 
			FIR_data_clk_cnt <= 0;
			ast_sink_valid <= 0;
			ast_sink_sop <= 0;
			ast_sink_eop <= 0;
			ast_sink_data <= 0;
			FIR_data <= -32768;
		end
	else
		begin 
		

			if(FIR_data_clk_cnt > MAX_FIR_data_clk_cnt)
				begin 
					ast_sink_valid <= 0;                    //數據輸入關閉
					ast_sink_data <= 0;	                   //輸入全零
					ast_sink_sop <= 0;
					ast_sink_eop <= 0;
				end 
			else 
				begin 
					ast_sink_valid <= 1;                    //數據輸入開啓
					ast_sink_data <= {FIR_data,FIR_data};	 //輸入數據
					
					if(FIR_data_clk_cnt == 0)
						begin 
							FIR_data <= FIR_data;
							ast_sink_sop <= 1;
							ast_sink_eop <= 0;
						end 
					else if(FIR_data_clk_cnt == MAX_FIR_data_clk_cnt)
						begin 
							FIR_data <= FIR_data + 4096;
							ast_sink_sop <= 0;
							ast_sink_eop <= 1;
						end	
					else 
						begin 
							FIR_data <= FIR_data;
							ast_sink_sop <= 0;
							ast_sink_eop <= 0;
						end 
				end 
				
				
			FIR_data_clk_cnt <= FIR_data_clk_cnt + 1;
				
//			if(FIR_data_clk_cnt == MAX_FIR_data_clk_cnt)	
//				begin 
//					FIR_data_clk_cnt <= 0;
//				end 
//			else 
//				begin 
//					FIR_data_clk_cnt <= FIR_data_clk_cnt + 1;
//				end 
				
		end 
end 
//----------------------------------------------------例化多通道FIR邏輯-------------------------------------------

assign source_data = ast_source_data[31:0];

ORT_FIR ORT_FIR_inst1 
(
	.clk                (MAIN_CLK),           //                     clk.clk
	.reset_n            (reset_n),            //                     rst.reset_n
	.ast_sink_data      (ast_sink_data),      //   avalon_streaming_sink.data
	.ast_sink_valid     (ast_sink_valid),     //                        .valid
	.ast_sink_error     (ast_sink_error),     //                        .error
	.ast_sink_sop       (ast_sink_sop),       //                        .startofpacket
	.ast_sink_eop       (ast_sink_eop),       //                        .endofpacket
	.ast_source_data    (ast_source_data),    // avalon_streaming_source.data
	.ast_source_valid   (ast_source_valid),   //                        .valid
	.ast_source_error   (ast_source_error),   //                        .error
	.ast_source_sop     (ast_source_sop),     //                        .startofpacket
	.ast_source_eop     (ast_source_eop),     //                        .endofpacket
	.ast_source_channel (ast_source_channel)  //                        .channel
);


endmodule

編譯後載入目標板中並使用SignalTap工具進行信號抓取,得到如下結果:

作爲對比下面給出matlab的代碼,代碼中的係數文件由濾波器生成時產生的。

%%
load E:\Graduate_student\Projects\2D_Image_Sonar\Code\FPGA\HEU_ACam001_20190810\ORT_FIR\ORT_FIR_sim\ORT_FIR_coef_int.txt

hn = ORT_FIR_coef_int;
FIR_data = -32768:4096:32767;
FIR_data = [FIR_data,FIR_data];
FIR_data = [FIR_data,FIR_data];
FIR_data_out = fix(filter(hn,1,FIR_data)/4);

figure;
subplot(2,1,1);
plot(FIR_data);
grid on;
subplot(2,1,2);
plot(FIR_data_out);
grid on;

運行得到如下結果:

可以看到波形和前面的signalTap抓取的是一致的。

具體的我們可以查看數值

可以看到結果是一模一樣的。

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