并行FIR滤波器的FPGA实现

文章讲述了设计一个15阶低通FIR滤波器,采用Blackman窗,应用于FPGA实现并行结构,12bit量化。通过Matlab设计和验证滤波效果,Modelsim仿真显示性能符合预期,强调了速度提升与面积成本的关系。
摘要由CSDN通过智能技术生成

要求:设计一个15阶(长度为16)的低通线性相位FIR滤波器,采用blackman窗,截止频率500Hz,采样频率2KHz,采用FPGA并行结构滤波器实现,滤波器系数量化位宽12bit,输入数据位宽12bit,输出数据位宽29bit,系统时钟2KHz。

1.首先采用Matlab求出符合要求的滤波器的系数,并观察12bit量化后的滤波器幅频响应曲线(代码如下)。
matlab代码与上节串行FIR滤波器设计基本一样

运行结果为

可以发现12bit量化符合要求

2.采用Matlab仿真产生待测试数据并通过设计的滤波器验证理论上的滤波效果同时将生成的测试数据写入txt文件中供后面Modelsim仿真时读取

运行结果:

我们可以发现当输入信号为白噪声时输出800Hz以后的频率衰减已经达到-40dB了

当输入信号为200Hz和800Hz的叠加信号时,滤波后的输出只剩200Hz的信号了,800Hz被滤除了。达到了预期的效果。

3.编写Verilog代码实现FPGA设计滤波器结构

/*
*
*@Author: X-Z
*@Date:2023-09-18 20:57:28
*@Function:采用并行结构实现FIR滤波器
*/

/*
    设计一个15阶(长度2为16)的低通线性相位的FIR滤波器,采用布莱克曼窗,截止频率500Hz,采样频率2KHZ,
    采用FPGA实现并行结构的滤波器,系数量化位数12Bit,输入数据位宽12bit,输出数据位宽29bit
    系统时钟2KHz
*/
//乘法器使用了1级流水线,加法器没有使用流水线会立即输出相加结果

module FirParaller(
    input                    clk         ,//系统时钟2KHz
    input                    rst_n       ,
    input  signed [11:0]     Xin         ,//输入信号12bit
    output signed [28:0]     Yout         //输出信号
);

//将数据存入移位寄存器Xin_Reg中
    reg signed [11:0] Xin_Reg[15:0];
    reg [3:0] i,j;
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin//初始化寄存器
            for(i=0;i<15;i=i+1)
                Xin_Reg[i] <= 12'd0;
        end
        else begin
            for(j=0;j<15;j=j+1)//此处与串行结构不同,不需要判断计数器状态
                Xin_Reg[j+1] <= Xin_Reg[j];
            Xin_Reg[0] <= Xin; 
        end
    end

//将对称系数的输入数据相加,同时将对应滤波器系数送人乘法器
//为进一步提高运行速度,另外增加一级寄存器
    reg signed [12:0] Add_Reg[7:0];
    always@(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            for(i=0;i<8;i=i+1)
                Add_Reg[i] <= 13'd0;
        end
        else begin
            for(j=0;j<8;j=j+1)
                Add_Reg[j] <=  {Xin_Reg[j][11],Xin_Reg[j]} + {Xin_Reg[15-j][11],Xin_Reg[15-j]};
        end
    end 

//与串行结构不同,另外需要实例化8个乘法器IP核
//实例化有符号数乘法器IP核
    wire signed [11:0] coe [7:0];//滤波器12bit量化滤波器系数
    wire signed [24:0] Mout [7:0];//乘法器输出为25bit的数据

//滤波器系数
/*
 '000' 'FFD''00F''02E' 'F8B''EF9' '24E' '7FF'
 '7FF''24E''EF9''F8B''02E''00F''FFD''000'

ans =

  列 1 至 10

           0          -3          15          46        -117        -263         590        2047        2047         590

  列 11 至 16

        -263        -117          46          15          -3           0

*/
    assign coe[0] = 12'h000;
    assign coe[1] = 12'hffd;
    assign coe[2] = 12'h00f;
    assign coe[3] = 12'h02e;
    assign coe[4] = 12'hf8b;
    assign coe[5] = 12'hef9;
    assign coe[6] = 12'h24e;
    assign coe[7] = 12'h7ff; 

// localparam coe[0] = 12'h000,
//            coe[1] = 12'hffd,
//            coe[2] = 12'h00f,
//            coe[3] = 12'h02e,
//            coe[4] = 12'hf8b,
//            coe[5] = 12'hef9,
//            coe[6] = 12'h24e,
//            coe[7] = 12'h7ff; 


//例化8个并行的乘法器
mul u_mult0(
	.clock  (clk        ),
	.dataa  (coe[0]     ),
	.datab  (Add_Reg[0] ),
	.result (Mout[0]    )
    );
mul u_mult1(
	.clock  (clk        ),
	.dataa  (coe[1]     ),
	.datab  (Add_Reg[1] ),
	.result (Mout[1]    )
    );
mul u_mult2(
	.clock  (clk        ),
	.dataa  (coe[2]     ),
	.datab  (Add_Reg[2] ),
	.result (Mout[2]    )
    );
mul u_mult3(
	.clock  (clk        ),
	.dataa  (coe[3]     ),
	.datab  (Add_Reg[3] ),
	.result (Mout[3]    )
    );
mul u_mult4(
	.clock  (clk        ),
	.dataa  (coe[4]     ),
	.datab  (Add_Reg[4] ),
	.result (Mout[4]    )
    );
mul u_mult5(
	.clock  (clk        ),
	.dataa  (coe[5]     ),
	.datab  (Add_Reg[5] ),
	.result (Mout[5]    )
    );
mul u_mult6(
	.clock  (clk        ),
	.dataa  (coe[6]     ),
	.datab  (Add_Reg[6] ),
	.result (Mout[6]    )
    );
mul u_mult7(
	.clock  (clk        ),
	.dataa  (coe[7]     ),
	.datab  (Add_Reg[7] ),
	.result (Mout[7]    )
    );

//对滤波器系数与输入数据的乘法结果进行累加,并输出滤波后的数据
//与串行结构不同,此处在一个时钟周期内直接将所有乘法器结果相加
    reg signed [28:0] sum1,sum2;
    reg signed [28:0] yout;
    //reg [3:0] k;
    // always @(posedge clk or negedge rst_n)begin
    //     if(!rst_n)begin
    //         sum   = 29'd0;
    //         yout <= 29'd0;
    //     end
    //     else begin
    //         yout <= sum;
    //         sum = 0;
    //         for(k=0;k<8;k=k+1)
    //             sum = sum + Mout[k];
    //     end
    // end

//采用两级流水线实现累加运算
    always @(posedge clk or negedge rst_n)begin
        if(!rst_n)begin
            sum1  <= 29'd0;
            sum2  <= 29'd0;
            yout  <= 29'd0;
        end
        else begin
            sum1 <= Mout[0]+Mout[1]+Mout[2]+Mout[3];
            sum2 <= Mout[4]+Mout[5]+Mout[6]+Mout[7];
            yout <= sum1 + sum2;
        end
    end

    assign Yout = yout;

endmodule

4.编写测试激励文件(略)

5.将仿真滤波器滤波后输出的数据写入txt文件中。

Modelsim仿真结果:

通过仿真我们可以发现大致实现了滤波性能,但还是不够直观,因此我们采用Matlab进行分析滤波性能。

6.采用Matlab分析经过滤波后的数据,分析滤波性能。代码(略)

运行结果为:

我们发现采用FPGA滤波前后的波形和Matlab仿真波形图基本一致,说明程序代码没问题,并行FIR滤波器运行速度大大提高,但消耗了大量的面积资源,用面积换取速度。最终设计满足要求。(昨晚就学完了并行滤波器,没来得及写抓紧补上)。

注:自学完杜勇的FIR滤波器所写。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值