DDS(Direct Digital Frequency Synthesizer)直接数字频率综合和FIR(Finite Impulse Response)有限脉冲响应在数字信号中是比较常见的几种之一。在这里就最近碰到的这两个在FPGA中的实现做个记录,也算是为将来有个回顾。
一、DDS
话不多说,直接上vivado中的DDS IP核的配置

①Configuration(配置项),可选择相位和正余弦输出,仅相位,仅正弦或余弦 3种中的其中一种,对于需要正交输出的,则选择第一个
②System Requirements(系统需求):时钟,通道数,操作模式,参数选择等
时钟:为给定输入的时钟频率
通道数:为给定的想要的输出通道数量,当通道数大于2时,每个通道所能使用的频率为输入频率的N分频。100/2=50M
操作模式:分为 标准模式 和 栅格模式
Parameter Selection(参数选择):系统参数 和 硬件参数,当配置项为相位生成器或 单个的正余弦时,仅可使用硬件参数。

System Parameter(系统参数)时,需要指定SFDR和频率精度。SFDR 设定输出宽度以及内部的总线宽度。
频率精度,以Hz为单位,指定最小频率分辨率,用于确定相位累加器及其相关相位增量PINC,相位偏移POFF值所用的相位宽度。根据下一个Noise shaping的选择,可以增加相位宽度,并且频率分辨率高于此处指定的分辨率。事实上,Noise Shaping 的设置采用auto即可。
Hardware Parameters(硬件参数)时,需要指定相位宽度和输出宽度

参数选择 用系统参数和硬件参数时,会有一个差别,即系统参数时,需要设置输出信号的频率,而硬件参数时,需要设置相位角增量值。相应的都是在计算输出信号的频率,一个是直接给定,另一个是通过相位角来计算的。
数据输出,当启用正弦或余弦时,数据输出有效。在新版本的IP核中,已经将输出合并到一个tdata中,以取代了以往单独的sine和cosine数据输出。

数据是通过符号位扩展来达到字节的边界的,且有效的数据位位于低位,符号位位于高位,对于单个的正弦或余弦,最低位即为对应的数据位,而正弦和余弦同时输出的数据,余弦数据位于低位。
上图中,表示了11位的有效数据,符号位扩展到了字节的边界位。
个人认为,DDS IP核的几个重点配置大部分都在了,在IP的具体配置中,对于前述的system parameter,则需要在后续的配置中指明输出信号的频率;而对于hardware parameter 则需要指明相位角增量这些参数,可参照后面给出的官方的配置文档。
当IP生成之后,剩下的就是将其例化到具体的模块里面去了。
二、FIR
至于什么叫FIR,这里就不过多说明了,请参照其他资料,csdn上这方面的东西还是挺多的。
在设计中,采用matlab联合vivado的方式实现FIR功能。那么就有几个步骤的工作需要做:
①在matlab中设计出符合频率响应特性的滤波器,并导出系数,将这些系数按照一定的量化格式给到FPGA;
②FPGA 通过将上述系数导入的IP中,并经由一些配置,实现IP核;
③FPGA中对IP核的例化,实现FIR功能;
下面开始上图。
在matlab中用fdatool进行滤波器的设计,如下

之后,切换成量化参数界面,更改为定点Fixed-point模式,并指定量化的位数

之后,点击target --> coe文件,生成xilinx对应的coe文件。以便后续在FPGA 的IP中调用。
vivado中对IP的配置操作:
滤波选项:选择用coe文件(因为要使用前述matlab导出的系数),系数集 因为只有一个,所以设置为1,滤波类型选择 single rate,其余默认即可

通道规格:此处最重要的设置是设置采样率,时钟等。需要跟Matlab生成coe系数文件时所采用的设置保持一致。在这里将时钟与采样率设置成1:1的关系,否则会导致滤波结果中仍然会出现其他频率成分的信号,类似于“混叠”。图中中,设置的参数与matlab中的不一致,那是因为截图的时候不是同样的参数,

其余项的配置,后续就不一一列出了。
当IP配置完成后,剩下的就是例化IP,对其进行使用了。
三、编码开发
设计中通过DDS产生了2个正弦波信号,频率分别为250K和5M,将这两个信号相加作为FIR滤波器的输入,FIR设置的通带为1M,以期望滤除5M的信号,仅保留250K信号输出。
1、例化DDS
wire data1_valid;
wire data2_valid;
dds_sin dds_sin_250k (
.aclk(clk_out1), // input wire aclk
.aresetn(clk_locked), // input wire aresetn
.m_axis_data_tvalid(data1_valid), // output wire m_axis_data_tvalid
.m_axis_data_tdata(sin_data1) // output wire [15 : 0] m_axis_data_tdata
);
dds_sin2 dds_sin2_5M (
.aclk(clk_out2), // input wire aclk
.aresetn(clk_locked), // input wire aresetn
.m_axis_data_tvalid(data2_valid), // output wire m_axis_data_tvalid
.m_axis_data_tdata(sin_data2) // output wire [15 : 0] m_axis_data_tdata
);
2、例化加法器,实现求和
//加法运算
//wire [16:0] addr_data;
adder adder_inst (
.A(sin_data1), // input wire [15 : 0] A
.B(sin_data2), // input wire [15 : 0] B
.CLK(clk_out2), // input wire CLK
.CE(1'b1), // input wire CE
.S(addr_data) // output wire [16 : 0] S
);
3、例化FIR
//通过Matlab FDATOOL 工具进行FIR设计,导出coe文件
//此处对应的Fpass=1M,Fstop=2.5M
//需要注意的是,数据的格式,在FIR中输入输出数据均是以8位为边界的
//实际的IP中,输入需要16位,输出需要35位,IP中例化的则是16位和40位
wire [39:0] fir_out_tdata;
wire m_axis_data_tvalid;
wire s_axis_data_tready;
fir_compiler_0 fir_compiler_inst (
.aclk(clk_out3), // input wire aclk
.s_axis_data_tvalid(data2_valid && data1_valid), // input wire s_axis_data_tvalid
.s_axis_data_tready(s_axis_data_tready), // output wire s_axis_data_tready
.s_axis_data_tdata({ {7{addr_data[16]}} ,addr_data}), // input wire [23 : 0] s_axis_data_tdata
.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid
.m_axis_data_tdata(fir_out_tdata) // output wire [39 : 0] m_axis_data_tdata
);
assign fir_outdata = fir_out_tdata[35:0];
4、顶层设计
module Top_dds_fir(
input clk_i,
input rst_n,
output [15:0] sin_data1, //输出波形1
output [15:0] sin_data2, //输出波形2
output [16:0] addr_data, //输出相加后的波形3,3=1+2
// output [31:0] mul_data, //输出相乘后的波形
output [35:0] fir_outdata //输出滤波后的波形
);
当然,还有一部分例化时钟IP的代码缺失,请自行补充吧。
四、仿真
仿真代码比较简单,模块例化、给个时钟,进行初始化设置等等。
module TB_top_dds_fir( );
reg clk_i;
reg rst_n;
wire [15:0] sin_data1;
wire [15:0] sin_data2;
wire [16:0] addr_data;
wire [35:0] fir_outdata;
Top_dds_fir Top_dds_fir(
.clk_i(clk_i),
.rst_n(rst_n),
.sin_data1(sin_data1),
.sin_data2(sin_data2),
.addr_data(addr_data),
.fir_outdata(fir_outdata)
);
initial begin
//initial
clk_i = 1'b0;
rst_n = 1'b0;
#100;
rst_n = 1'b1; //100nS后,放开复位
#20000;
$finish;
end
always #10 clk_i = ~ clk_i; //产生50M时钟
endmodule
仿真结果:结果如下图所示。从图中可以看出,求和后的波形为两个波形的叠加,经fir后,将高频信号滤除了,仅保留了低频信号输出。



本文详细介绍了在FPGA中DDS(直接数字频率合成器)和FIR(有限impulseresponse)的配置过程,包括DDS的系统参数、硬件参数设置,以及FIR的Matlab设计和Vivado中的IP配置。通过实例展示了如何在FPGA中利用DDS产生正弦波并经过FIR滤波,实现实时信号处理。

6805

被折叠的 条评论
为什么被折叠?



