该篇是FPGA数字信号处理的第五篇,选题为DSP系统中极其常用的FIR滤波器。本文将在前三篇的基础上,继续介绍在Vivado开发环境下使用Xilinx提供的FIR IP核进行FIR滤波器的设计。
1.“FPGA数字信号处理(二)并行FIR滤波器Verilog设计” https://blog.csdn.net/fpgadesigner/article/details/80594627
2.“FPGA数字信号处理(三)串行FIR滤波器Verilog设计” https://blog.csdn.net/fpgadesigner/article/details/80598992
3.“FPGA数字信号处理(四)Quartus FIR IP核实现” https://blog.csdn.net/fpgadesigner/article/details/80605869
Xilinx的FIR IP核属于收费IP,但是不需要像 Quartus那样通过修改license文件来破解。如果是个人学习,现在网络上流传的license破解文件在破解Vivado的同时也破解了绝大多数可以破解的IP核。只要在IP Catalog界面中FIR Compiler的License状态为“Included”即可正常使用。
和Quartus不一样,Vivado的FIR Compiler没有提供设计FIR滤波器和生成滤波器系数的功能,因此需要使用MATLAB等其它工具设计好滤波器再将系数导入到IP核中。MATLAB的FDATOOL工具在设计好滤波器后,可以直接生成IP核需要的coe文件,如下图所示:
在IP Catalog中打开FIR Compiler,主界面如下:
左边的Tab可以切换看到FIR的模块图(管脚信息)、频率响应等信息。右边的Tab是对FIR滤波器进行设计。
IP核支持两种FIR系数输入方式,以“Vector”的形式直接写入;或者以“COE File”的形式导入coe文件。Xilinx的FIR IP核支持多种滤波器结构,可以在“Filter Type”中设置,本文选择传统的“Single Rate”结构。该IP核同样也支持系数重载。
除了单速率(Single Rate,即数据输出与输入速率相同)外,FIR Compiler还支持抽取(Decimation)和插值(Interpolation)应用于多速率信号处理系统。此外还支持希尔伯特变换(Hilbert)模式,可以在“Filter Type”中设置。
IP核支持多通道数据输入,可以在Channel Specification这个Tab中设置输入数据的通道数。还可以在Hardware Oversampling Specification中设置过采样模式,即输入数据的频率可以高出FIR系统时钟的频率。
Implementation这个Tab中可以设置FIR系数的类型、量化方式、量化位宽(此值应该与MATLAB中的设置一致,否则频率响应是错的)和结构。本文由于是设计线性相位FIR,滤波器系数是对称的,因此选择为“Symmetric”,也可以选择为“Inferred”,软件会自动判断系数的结构。
Detailed Implementation这个Tab中可以设置优化方式、存储的类型、是否使用DSP单元等与综合、实现有关的信息。Interface这个Tab中可以设置与IP核接口相关的信息。
Vivado的很多IP核采用的是AXI4接口,主要有数据(tdata)、准备好(tready)、有效(tvalid)几种信号,还有主机(m)和从机(s)之分。另外在Interface这个Tab还可以配置使用更多辅助的AXI4接口信号。
接下来介绍几个主要的接口:
在设置为多通道、可变系数模式时,还会用到其它的接口。上表中的接口已经足够完成一次单通道、固定系数的FIR滤波器设计。其它接口在后文的设计中使用到FIR滤波器的其它模式时,再做介绍。
需要注意,同DDS Compiler一样(https://blog.csdn.net/fpgadesigner/article/details/80512067),AXI4接口的tdata位宽是以字节为单位,即只会是8的倍数,因此需要结合设计的实际位宽做相应处理。
IP核的接口在Verilog HDL中进行设计时,一定要参考官方文档中给出的时序图。在IP核的配置界面点击“documentation”,可以找到IP核的user guide。 也可以在Xilinx官网或DocNav工具中搜索pg149,查阅FIR Compiler的说明。
单通道、固定系数的FIR Compiler接口时序非常简单,Verilog HDL示例代码如下所示:
`timescale 1ns / 1ps
module Xilinx_FIRIP_liuqi
(
input clk, //FPGA系统时钟/数据速率:2kHz
input signed [11:0] Xin, //数据输入频率为2kHZ
output m_tvalid, //FIR输出数据有效信号
output signed [24:0] Yout //滤波后的输出数据
);
wire s_tready;
wire signed [31:0] m_tdata;
fir fir_lowpass_500kHz
(
.aclk (clk),
.s_axis_data_tvalid (1'b1),
.s_axis_data_tready (s_tready),
.s_axis_data_tdata ({{4{Xin[11]}},Xin}),
.m_axis_data_tvalid (m_tvalid),
.m_axis_data_tdata (m_tdata)
);
assign Yout = m_tdata[24:0];
endmodule
程序中认为输入的采样数据始终有效,因此将s_axis_data_tvalid永远置1。由于s_axis_data_tdata为16bit位宽,但输入信号数据为12bit位宽,因此用拼接运算符{}在高位填充补码的符号位;由于m_axis_data_tdata为32bit位宽,但输出信号数据有效位仅有25bit位宽,因此仅需取低25bit作为FIR滤波器输出。当然不这么操作,直接将信号赋值到实例化接口,结果也是正确的,这样做只是为了更严谨。
使用MATLAB生成一个200khz+800kHz的混合频率信号,写入txt文件,。编写Testbench读取txt文件对信号滤波,文件操作方法参考“Testbench编写指南(一)文件的读写操作”https://blog.csdn.net/fpgadesigner/article/details/80470972。
在Vivado中进行仿真,对正弦信号的滤波如下图所示:
新建一个虚拟总线,仅保留一个符号位。明显看到经过500Hz低通滤波器滤波后,输入的200+800Hz信号只剩下200Hz的单频信号。且当FIR滤波器输出有效时,m_tvalid信号置高。
完整的Vivado工程(含testbench仿真)可以在这里下载:https://download.csdn.net/download/fpgadesigner/10466659。