FPGA实现FIR滤波
什么是FIR滤波?
FIR(Finite Impulse Response) Filter:有限冲激响应滤波器。
FIR滤波器这里就不赘述其原理了,晚上有很多解释的。我这里给两个我参考的,并且认为还不错的
FIR滤波器的verilog实现
源代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/05/10 10:23:52
// Design Name:
// Module Name: FIR
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module FIR(
input clk,
input rst_n,
input [DATA_WIDTH:1] data_in,
output reg [DATA_WIDTH + 8:1] filtered_data,
output reg filtered_data_valid
);
//定义parameter
parameter DATA_WIDTH = 8; //数据位宽
parameter b0 = 0; //FIR抽头参数
parameter b1 = 8;
parameter b2 = 22;
parameter b3 = 38;
parameter b4 = 50;
parameter b5 = 38;
parameter b6 = 22;
parameter b7 = 8;
parameter b8 = 0;
//将数据缓存
reg [DATA_WIDTH:1] data_reg [9:0];
integer i,j;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (i = 0;i <=9 ;i = i + 1 ) begin
data_reg[i] <= 0;
end
end
else begin
data_reg[0] <= data_in;
for (j = 1; j <= 9 ;j = j + 1) begin
data_reg[j] <= data_reg[j-1];
end
end
end
//进行FIR处理
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
filtered_data <= 0;
filtered_data_valid <= 0;
end
else begin
filtered_data <= b0 * data_reg[0] + b1 * data_reg[1] + b2 * data_reg[2] + b3 * data_reg[3] +
b4 * data_reg[4] + b5 * data_reg[5] + b6 * data_reg[6] + b7 * data_reg[7] +
b8 * data_reg[8];
filtered_data_valid <= 1;
end
end
endmodule
测试代码
MATLAB生成信号源
clc;
clear all;
s_p = 0:255; %正弦波一个周期的采样点
N = 2^8;
sin_data = sin(2*pi*s_p/N);
%生成噪声信号
y2=randn(1, N);%生成一个白噪声数组(白噪声的随机数范围是[-3,3]),数组长度为N
subplot(3,1,2);
plot(1:N, y2);
%生成正弦波信号和噪声信号复合的信号
y=sin_data+y2/10;
subplot(3,1,3);
plot(1:N, y);
%定点化
fix_y = fix(y*127) + 150;
plot(1:N,fix_y);
%写到文件
fid = fopen('sin_sp_ram_256X8.coe','wt');
fprintf(fid,'MEMORY_INITIALIZATION_RADIX=10;\n');
fprintf(fid,'MEMORY_INITIALIZATION_VECTOR=\n');
for i=1:1:N
fprintf(fid, "%d",fix_y(i));
if i == N
fprintf(fid,';');
else
fprintf(fid,',\n');
end
end
fclose(fid);
Testbench
当然,抽头数据是随便设的
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/05/10 21:27:44
// Design Name:
// Module Name: FIR_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module FIR_tb;
// Parameters
localparam DATA_WIDTH = 32;
localparam b0 = 0;
localparam b1 = 0;
localparam b2 = 1;
localparam b3 = 3;
localparam b4 = 8;
localparam b5 = 3;
localparam b6 = 1;
localparam b7 = 0;
localparam b8 = 0;
// Ports
reg clk = 0;
reg rst_n = 0;
wire [DATA_WIDTH:1] data_in;
wire [DATA_WIDTH:1] filtered_data;
wire filtered_data_valid;
FIR
#(
.DATA_WIDTH(DATA_WIDTH ),
.b0(b0 ),
.b1(b1 ),
.b2(b2 ),
.b3(b3 ),
.b4(b4 ),
.b5(b5 ),
.b6(b6 ),
.b7(b7 ),
.b8(b8 )
)
FIR_dut (
.clk (clk ),
.rst_n (rst_n ),
.data_in (data_in ),
.filtered_data (filtered_data ),
.filtered_data_valid ( filtered_data_valid)
);
reg [7:0] addra;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
addra <= 0;
end
else begin
addra <= addra + 1;
end
end
wire [31:0] douta;
//调用FIFO
FIR_tb_ram your_instance_name (
.clka(clk), // input wire clka
.wea(0), // input wire [0 : 0] wea
.addra(addra), // input wire [7 : 0] addra
.dina(0), // input wire [31 : 0] dina
.douta(douta) // output wire [31 : 0] douta
);
assign data_in[DATA_WIDTH:1] = douta[31:0];
initial begin
begin
#500 rst_n = 1;
end
end
always
#5 clk = ! clk ;
endmodule