赞
踩
要求:设计一个15阶(长度为16)的低通线性相位FIR滤波器,采用blackman窗,截止频率500Hz,采样频率2KHz,采用FPGA并行结构滤波器实现,滤波器系数量化位宽12bit,输入数据位宽12bit,输出数据位宽29bit,系统时钟2KHz。
运行结果为
可以发现12bit量化符合要求
运行结果:
我们可以发现当输入信号为白噪声时输出800Hz以后的频率衰减已经达到-40dB了
当输入信号为200Hz和800Hz的叠加信号时,滤波后的输出只剩200Hz的信号了,800Hz被滤除了。达到了预期的效果。
- /*
- *
- *@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
Modelsim仿真结果:
通过仿真我们可以发现大致实现了滤波性能,但还是不够直观,因此我们采用Matlab进行分析滤波性能。
运行结果为:
我们发现采用FPGA滤波前后的波形和Matlab仿真波形图基本一致,说明程序代码没问题,并行FIR滤波器运行速度大大提高,但消耗了大量的面积资源,用面积换取速度。最终设计满足要求。(昨晚就学完了并行滤波器,没来得及写抓紧补上)。
注:自学完杜勇的FIR滤波器所写。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。