首先给出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抓取的是一致的。
具体的我们可以查看数值
可以看到结果是一模一样的。