在现代通信信号处理领域中,信息传输的安全性和保密性变得越来越重要。数字信号是数据经采样、量化、编码后所得到的离散的序列样值。在通信系统中,若信道中传输的是数字信号则称为数字通信。在以往的模拟通信中,模拟滤波器无法克服电压漂移、温度漂移和噪声等问题对自身的影响,从而带来了许多误差和不稳定因素,但是在数字通讯中数字滤波器既有稳定性搞、精度高、设计灵活、不需要阻抗匹配等优点。
数字滤波技术是数字信号分析、处理技术的重要分支。无论是信号的获取、传输,还是信号的处理和交换都离不开滤波技术,它对信号安全可靠和有效灵活地传输是至关重要的。在所有的电子系统中,使用最多技术最复杂的要算数字滤波器了。数字滤波器的优劣直接决定产品的优劣。
本文将用matlab与vivodo联合实现FIR数字滤波器
首先在matlab中直接生成量化后的混合波数据:
Fs = 200000; %采样频率决定了两个正弦波点之间的间隔
N = 4096; %采样点数
N1 = 0 : 1/Fs : (N-1)/Fs;
in =sin(6000*2*pi*N1) + sin(14000*2*pi*N1);
fidc= fopen('C:/Users/Lenovo/Desktop/ccfir/matl/sin_data.txt','wt'); //保存到自己想要的位置上
for x = 1 : N
fprintf(fidc,'%x\n',round((s(x)+2.12)*58));
end
fclose(fidc);
下面用matlab自带的fdatool工具设计FIR数字滤波器,在命令行窗口输入fdatool按下回车就会出现设计窗口。具体过程不再赘述。
下面进行vivado界面的仿真:(比较简单,没有使用IP核,顺便学习一下FIR数字滤波器的经典结构)
下面开始设计FIR数字滤波器:
`timescale 1ns / 1ps
//
// Company:
// Engineer: thirsty of cola
//
// Create Date: 2022/05/20 15:16:11
// Design Name:
// Module Name: fir
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
`timescale 1ms / 1ps
module fir(
input[7:0] FIR_IN, //滤波器的输入信号
input CLK, //时钟信号
input RSTn, //复位信号
output reg[15:0] FIR_OUT//滤波器输出信号
);
reg[7:0] delay_pipeline1 ;//延时模块
reg[7:0] delay_pipeline2 ;
reg[7:0] delay_pipeline3 ;
reg[7:0] delay_pipeline4 ;
reg[7:0] delay_pipeline5 ;
reg[7:0] delay_pipeline6 ;
reg[7:0] delay_pipeline7 ;
reg[7:0] delay_pipeline8 ;
reg[7:0] delay_pipeline9 ;
/*第一级流水,将输入信号进行延时,每到来一个时钟信号,
便将输入信号保存到delay_pipelin1中,然后将剩下的依次移动一位。*/
always@(posedge CLK or negedge RSTn)
if(!RSTn)
begin
delay_pipeline1 <= 8'b0 ;
delay_pipeline2 <= 8'b0 ;
delay_pipeline3 <= 8'b0 ;
delay_pipeline4 <= 8'b0 ;
delay_pipeline5 <= 8'b0 ;
delay_pipeline6 <= 8'b0 ;
delay_pipeline7 <= 8'b0 ;
delay_pipeline8<= 8'b0 ;
delay_pipeline9<= 8'b0 ;
end
else begin
delay_pipeline1 <= FIR_IN ;
delay_pipeline2 <= delay_pipeline1 ;
delay_pipeline3 <= delay_pipeline2 ;
delay_pipeline4 <= delay_pipeline3 ;
delay_pipeline5 <= delay_pipeline4 ;
delay_pipeline6 <= delay_pipeline5 ;
delay_pipeline7 <= delay_pipeline6 ;
delay_pipeline8 <=delay_pipeline7 ;
delay_pipeline9<= delay_pipeline8 ;
end
//滤波器系数
wire[7:0] coeff1 = 8'd7; //在matlab中生成的滤波器系数,也可以是16进制
wire[7:0] coeff2 = 8'd5;
wire[7:0] coeff3 = 8'd51;
wire[7:0] coeff4 = 8'd135;
wire[7:0] coeff5 = 8'd179;
wire[7:0] coeff6 = 8'd135;
wire[7:0] coeff7 = 8'd51;
wire[7:0] coeff8 = 8'd5;
wire[7:0] coeff9 = 8'd7;
//乘积结果保存寄存器
reg signed [16:0] multi_data1 ;
reg signed [16:0] multi_data2 ;
reg signed [16:0] multi_data3 ;
reg signed [16:0] multi_data4 ;
reg signed [16:0] multi_data5 ;
reg signed [16:0] multi_data6 ;
reg signed [16:0] multi_data7 ;
reg signed [16:0] multi_data8 ;
reg signed [16:0] multi_data9 ;
//x(n) * h(n-k)
always@(posedge CLK or negedge RSTn)
if(!RSTn)
begin
multi_data1 <= 17'b0 ;
end
else begin
multi_data1 <= delay_pipeline1*coeff1 ;
end
//x(1) * h(1)
always@(posedge CLK or negedge RSTn)
if(!RSTn)
multi_data2 <= 16'b0 ;
else
multi_data2 <= delay_pipeline2*coeff2 ;
//x(2) * h(2)
always@(posedge CLK or negedge RSTn)
if(!RSTn)
multi_data3 <= 16'b0 ;
else
multi_data3 <= delay_pipeline3*coeff3 ;
//x(3) * h(3)
always@(posedge CLK or negedge RSTn)
if(!RSTn)
multi_data4 <= 16'b0 ;
else
multi_data4 <= delay_pipeline4*coeff4 ;
//x(4) * h(4)
always@(posedge CLK or negedge RSTn)
if(!RSTn)
multi_data5 <= 16'b0 ;
else
multi_data5 <= delay_pipeline5*coeff5 ;
//x(5) * h(5)
always@(posedge CLK or negedge RSTn)
if(!RSTn)
multi_data6 <= 16'b0 ;
else
multi_data6 <= delay_pipeline6*coeff6 ;
//x(6) * h(6)
always@(posedge CLK or negedge RSTn)
if(!RSTn)
multi_data7 <= 16'b0 ;
else
multi_data7 <= delay_pipeline7*coeff7;
//x(7) * h(7)
always@(posedge CLK or negedge RSTn)
if(!RSTn)
multi_data8 <= 16'b0 ;
else
multi_data8 <= delay_pipeline8*coeff8;
//x(8) * h(8)
always@(posedge CLK or negedge RSTn)
if(!RSTn)
multi_data9 <= 16'b0 ;
else
multi_data9 <= delay_pipeline9*coeff9 ;
//将乘积累加,累加的结果就是滤波后的信号
always@(posedge CLK or negedge RSTn)
if(!RSTn)
FIR_OUT <= 16'b0 ;
else
FIR_OUT <= multi_data1 + multi_data2 + multi_data3 +
multi_data4 +multi_data5 + multi_data6 + multi_data7 +
multi_data8 + multi_data9 ;
endmodule
下面开始写testbench:
`timescale 1ns / 1ps
//
// Company:
// Engineer: thirsty of cola
//
// Create Date: 2022/05/20 14:48:35
// Design Name:
// Module Name: tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module tb(
);
reg CLK;
reg [7:0] FIR_IN;
reg RSTn;
reg [7:0] mem[1:4096]; //设计一个rom放读入的数据
wire [15:0] FIR_OUT;
reg [12:0] i;
//例化FIR滤波器
fir i1 (
.CLK(CLK),
.FIR_IN(FIR_IN),
.FIR_OUT(FIR_OUT),
.RSTn(RSTn)
);
initial
begin
$readmemh("C:/Users/Lenovo/Desktop/cc/viva/project_1/sin_data.txt",mem);//将待滤波信号读入mem
RSTn= 0;
CLK= 0;
#50;RSTn= 1;
#50000;
$stop;
end
initial
forever
#50 CLK = ~CLK;//时钟生成,注意与采样率一致
always@(posedge CLK or negedge RSTn)
if(!RSTn)
FIR_IN <= 8'b0 ;
else
FIR_IN <= mem[i]; //读入数据
always@(posedge CLK or negedge RSTn)
if(!RSTn)
i <= 12'd0;
else
i <= i + 1'd1;
endmodule
上面我们就完成了一个简单的数字滤波器的设计,其RTL视图如下所示:
从上图我们可以看出,FIR数字滤波器的结构比较简单,大体上来说就是一堆延迟器和一堆乘法器还有一堆加法器所组成的,原理也比较好理解。
大家可以参考FIR数字滤波器的直接型结构,方便理解
下面我们来刻苦仿真波形,怎么样吧:
在该例子中,i相当于地址信号,不停的做累加,用于让MEM读取matlab量化后的数据信息。我们可以看到MEM所读取的数据和TXT文本文档中的数据一样,说明我们已近将待处理信号读到了。
下面我们具体分析FIR_IN和FIR_OUT信号,注意要对其中的进制和输出波i选哪个类型进行改变:
从上图我们可以看出,输入信号和输出信号有很大的差异,滤波器滤除了高频分量而保留下了低频部分的信息,说明设计成功。
注:该例子仅供学习参考,现在的数字滤波器基本都是自适应的,还有待大佬们的指正,谢谢啦。