FIR Compiler IP系数重加载方法

1 基本介绍

FIR Compiler模块提供了两种滤波器系数重加载方法。
1、reload方法,利用reload接口写入新系数。
2、config方法,提前将系数分组后写到Coefficient Vector中,再通过config接口写入系数组编号,选择相应的滤波器系数。与reload方法相比,config方法较为简单,缺点是灵活性不够,需要提前规划好所有需要重配置的滤波器系数。

2 实现流程

1、利用MATLAB生成两个带通滤波器的coe系数文件。
第一个带通滤波器允许5M的信号通过,第一个带通滤波器允许10M的信号通过。
2、在Vivado利用DDS产生两个点频信号。其频率分别为5M和10M,并将两个点频信号相加。
3、调用FIR IP,并将coe系数文件加载到IP中。

3 具体实现步骤

3.1 生成两个带通滤波器的coe系数文件

close all;
clear all;
clc;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%           参数定义
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Quantify_bit=16;   % 量化位数 16位
fs=125e6;          % 采样频率
N=1e3;
t=(0:N-1)/fs;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%----      产生原始信号  5M+10M的混叠信号
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
f1=5e6;
f2=10e6;

x=cos(2*pi*f1*t)+cos(2*pi*f2*t+pi/6);
figure(1); 
plot(t,x);



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%            带通滤波器
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ---------BANDPASS_5M Returns a discrete-time filter object.
% All frequency values are in MHz.
Fs = 125;  % Sampling Frequency

N    = 100;      % Order
Fc1  = 3;       % First Cutoff Frequency
Fc2  = 7;       % Second Cutoff Frequency
flag = 'scale';  % Sampling Flag
Beta = 0.5;      % Window Parameter
% Create the window vector for the design algorithm.
win = kaiser(N+1, Beta);

% Calculate the coefficients using the FIR1 function.
b1  = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);



%------BANDPASS_10M Returns a discrete-time filter object.
% All frequency values are in MHz.
Fs = 125;  % Sampling Frequency

N    = 100;      % Order
Fc1  = 8;        % First Cutoff Frequency
Fc2  = 12;       % Second Cutoff Frequency
flag = 'scale';  % Sampling Flag
Beta = 0.5;      % Window Parameter
% Create the window vector for the design algorithm.
win = kaiser(N+1, Beta);

% Calculate the coefficients using the FIR1 function.
b2  = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);


%----拼接
h=[b1,b2];
L_h=length(h);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%      导出滤波器的数据
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fid=fopen('bandpass.coe','w');  % 实部
[b1_data]= coe_generate(fid,Quantify_bit,L_h,h);




%----5M的带通
y1=conv(x,b1);
delay=(length(b1)-1)/2;
y1=y1( delay+1:1:end-delay );
L=length(y1);
f=(0:L-1)*fs/L-fs/2;
Y1=fftshift(fft(y1));
P1=abs(Y1)/L;

figure(2);
subplot(211);plot(t,y1);
subplot(212);plot(f,P1);




%----10M的带通
y2=conv(x,b2);
y2=y2( delay+1:1:end-delay );
L=length(y2);
Y2=fftshift(fft(y2));
P2=abs(Y2)/L;

figure(3);
subplot(211);plot(t,y2);
subplot(212);plot(f,P2);


function [yt]= coe_generate(fid,Quantify_bit,L,b)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%            MATLAB生成coe文件
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%.coe文件中
% 第一行为定义数据格式, 2代表 ROM 的数据格式为二进制。
% 从第 3 行开始yong到第最后一行,是这个  L(数据长度为1024* ADC_bit(16bit) 大小 ROM 的初始化数据。
% 第一行到倒数第二行的数字后面用逗号,最后一行数字结束用分号。

yt=round(b*(2^(Quantify_bit-1)-1));    % 16bit量化


% fid=fopen('band_filter.coe','w');  % w表示write
fprintf(fid,'Radix = 10;\r\n'); % 二进制
fprintf(fid,'coefdata = \r\n');
for p=1:L
    fprintf(fid,'%d',yt(p));  % 写入数据
    
   
    %  下面if语句的目的
    %  每行数字后面用逗号(,),最后一行数字结束用分号(;)
    if (p<L)
        fprintf(fid,' \r\n'); 
    else
        fprintf(fid,';\r\n');    % 分号(;)  结束标志位
    end
   
end
    fclose(fid);
end


3.2 配置 DDS

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3 配置 FIR IP

下图中,选择COE file,Coefficient File 选择MATLAB生成的coe系数文件
由于有两组滤波器系数,所以Number of Coefficient Sets选择2。

在这里插入图片描述
在这里插入图片描述
下图中,MATLAB的量化位数为16bit,所以这里的Quantization选择16,COE系数为十进制有符号数。

Quantify_bit=16;   % 量化位数 16

FIR滤波器的输入信号的位宽为16。
在这里插入图片描述
在这里插入图片描述

5 实现代码

在这里插入图片描述

5.1 源文件

`timescale 1ns / 1ps


module FIR_COEF_Reload(
        input       clk                 , //系统时钟   125M
        input       reset               , //复位         
        input [1:0] Freq_Select           // config信道上选择系数的组别
    );
 
 
 
//--------1、产生10M和5M的正弦波信号,然后两个信号混叠    
//  输出频率字的计算公式:deta_theta=f_out*(2^B)/f_clk 
// 相位位宽:32bit   系统时钟 f_clk=125M
wire [31:0] PINC_10M;
wire [31:0] PINC_5M;
assign PINC_10M=32'h147AE148;    //10M对应的频率字
assign PINC_5M=32'hA3D70A4;    //5M对应的频率字

wire [31:0] Signal_Freq10M;//10M的正弦波 
wire [31:0] Signal_Freq5M; //5M的正弦波 
wire  Freq10M_vaild;
wire  Freq5M_vaild;  
// 输出10M的正弦波 
dds_sin Inst_dds_sin_10M (
   .aclk(clk),                                  // input wire aclk
   .s_axis_config_tvalid(1'b1),  // input wire s_axis_config_tvalid
   .s_axis_config_tdata(PINC_10M),    // input wire [31 : 0] s_axis_config_tdata
   .m_axis_data_tvalid(Freq10M_vaild ),      // output wire m_axis_data_tvalid
   .m_axis_data_tdata (Signal_Freq10M),        // output wire [31 : 0] m_axis_data_tdata
   .m_axis_phase_tvalid(),    // output wire m_axis_phase_tvalid
   .m_axis_phase_tdata()      // output wire [31 : 0] m_axis_phase_tdata
); 
    
// 输出5M的正弦波 
dds_sin Inst_dds_sin_5M (
   .aclk(clk),                                  // input wire aclk
   .s_axis_config_tvalid(1'b1),  // input wire s_axis_config_tvalid
   .s_axis_config_tdata(PINC_5M),    // input wire [31 : 0] s_axis_config_tdata
   .m_axis_data_tvalid(Freq5M_vaild ),      // output wire m_axis_data_tvalid
   .m_axis_data_tdata (Signal_Freq5M),     // output wire [31 : 0] m_axis_data_tdata
   .m_axis_phase_tvalid(),    // output wire m_axis_phase_tvalid
   .m_axis_phase_tdata()      // output wire [31 : 0] m_axis_phase_tdata
);   
 
//  信号截取
wire [15:0] Signal_Freq10M_16bit;//10M的正弦波 
wire [15:0] Signal_Freq5M_16bit; //5M的正弦波    
assign Signal_Freq10M_16bit=Signal_Freq10M[31:16];      
assign Signal_Freq5M_16bit=Signal_Freq5M[31:16];     



//-----------------两个正弦波信号叠加
// 为什么需要扩展1位
 // 2个信号相加需要扩展1位,4个信号相加需要扩展2位,
wire [16:0] SignalMix_temp;  
wire [15:0] SignalMix; 
assign  SignalMix_temp= {Signal_Freq5M_16bit[15] ,Signal_Freq5M_16bit } +
                        {Signal_Freq10M_16bit[15],Signal_Freq10M_16bit};
 assign SignalMix= SignalMix_temp[16:1];                     
//add Inst_16add16 (
//  .A(Signal_Freq10M_16bit),      // input wire [15 : 0] A
//  .B(Signal_Freq5M_16bit),      // input wire [15 : 0] B
//  .CLK(clk),                    // input wire CLK
//  .S(SignalMix)                 // output wire [15 : 0] S
//); 
  
  
  
  
  
  
//----信号带通滤波  通过系数重加载选择10M还是5M的信号通过
reg         filter_config_tvalid            ;// input 
wire        filter_config_tready            ;// output
reg [7:0]   filter_config_tdata             ;// input 

//output
wire [31:0] y;
wire y_vaild;


// 调用带通滤波器
fir_compiler_Freq1 Inst_bandpass (
  .aclk(clk),   // input wire aclk
 
  .s_axis_data_tvalid(Freq10M_vaild && Freq5M_vaild), // input wire s_axis_data_tvalid
  .s_axis_data_tready( ),                              // output wire s_axis_data_tready
  .s_axis_data_tdata (SignalMix         ),             // input wire [15 : 0] s_axis_data_tdata
 
  .s_axis_config_tvalid(filter_config_tvalid),  // input wire s_axis_config_tvalid
  .s_axis_config_tready(filter_config_tready),  // output wire s_axis_config_tready
  .s_axis_config_tdata (filter_config_tdata ),    // input wire [7 : 0] s_axis_config_tdata
  
  .m_axis_data_tvalid(y_vaild),      // output wire m_axis_data_tvalid
  .m_axis_data_tdata(y)             // output wire [31 : 0] m_axis_data_tdata
);

wire [15:0] y_16bit;
assign y_16bit=y[31 : 16]; //截位


  
 //-------s_axis_config配置  
// 功能:通过控制filter_config_tvalid和filter_config_tdata,进而实现动态配置FIR的coe系数
always@(posedge clk)
begin
    if(reset)
        begin
            filter_config_tvalid<=1'b0;
            filter_config_tdata<=8'd0;
        end
    else if( filter_config_tready )//config通道准备好接收数据
        begin
            filter_config_tvalid<=1'b1;
            case(Freq_Select)
                2'd0: filter_config_tdata<=8'd0; //选择系数的组别
                2'd1: filter_config_tdata<=8'd1;
                default:  
                      filter_config_tdata<=8'd0;
            endcase                             
        end
    else 
        begin
            filter_config_tvalid<=filter_config_tvalid;
            filter_config_tdata<=filter_config_tdata;
        end  
end    
    
 
    
endmodule

5.2 testbench

`timescale 1ns / 1ps


module sim_FIR_COEF_Reload;

reg         clk        ;
reg         reset      ;
reg [1:0]   Freq_Select; // config信道上选择系数的组别

FIR_COEF_Reload Inst_FIR_COEF_Reload(
        .clk          (clk        )       , //系统时钟   125M
        .reset        (reset      )       , //复位         
        .Freq_Select  (Freq_Select)       // config信道上选择系数的组别
    );

initial
begin
    clk<=1'b0;
    reset<=1'b1;
    Freq_Select<=2'd0;
    #20
        reset<=1'b0;
    #5000   //5us 
        Freq_Select<=2'd1;     
end

always #4 clk=~clk;//T=8ns F_clk=125M


endmodule

5.3 结果

在这里插入图片描述
coe文件的第1组数据,允许5M的信号通过,所以当s_axi_config_tdata=0时,输出信号y的频率为5M。
coe文件的第2组数据,允许10M的信号通过,所以当s_axi_config_tdata=1时,输出信号y的频率为10M。

在这里插入图片描述

在这里插入图片描述

6 注意点

DDS和FIR的钟都是125M,所以生成的钟的频率必须为125M。

7 工程文件链接

工程文件
https://download.csdn.net/download/weixin_46136963/74135712

  • 5
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值