首先給出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抓取的是一致的。
具體的我們可以查看數值
可以看到結果是一模一樣的。