【FPGA】 Vivado DDS IP核实现扫频信号
此文章是转载的,网址是:http://681314.com/A/2sZSOSkIHB;感谢作者。
文章目录
前言
一、DDS IP核概述
二、DDS IP核配置
三、调用DDS IP核
总结
前言
在我前面的工程中都是一些比较通用的设计工程没有用到哪一家的IP核所以代码具有很好的移植性今天我就来讲一下基于Xilinx厂家的芯片做一期DDS的设计与验证这里我所采用的EDA工具是Vivado 2018.3里面集成了DDS的IP核我们直接进行调用即可。
Xilinx公司是FPGA的主要生产商即使在现在的FPGA领域它都有着很大的话语权目前市面上的FPGA芯片主要有Xilinx和Altera两家其中Xilinx占据主导地位其产品在各个方面的应用更是炉火纯青。我们都知道FPGA的优点是基于它的可编程性使得其开发周期短但为了提升FPGA开发的周期性各家都提供了一些通用功能的IP核包括固化在芯片内的硬IP核和可编程调用的软IP核并在开发工具中提供了IP和的实例化和调用功能下面我就在Vivado中调用DDS IP核来进行设计。
一、DDS IP核概述
上图是DDS IP核的方案图从图中我们可以看到DDS IP核主要由5部分组成其中DDS IP核的核心是相位累加器和LUT查找表它们可以独立使用也可与一个可选的相位发生器一起使用。相位累加器实现查找表地址的产生LUT查找表用来存储输出波形。还有泰勒级数矫正模块和抖动产生器用来改善SFDR。最两边是AXI4接口是基于AXI4总线协议的接口模块用来实现相位累加字配置多通道配置以及相位累加器输出和sin/cos波形输出。
二、DDS IP核配置
1、首先创建一个工程文件然后点击IP Catalog直接在搜索框中搜索DDS创建DDS IP核。
2、 然后双击DDS Compiler进行DDS IP核的配置界面。
DDS IP核可以配置成三种模式分别是相位累加器和SIN/COS LUT模式、仅相位产生器模式、仅SIN/COS LUT模式这里我们选择第一种相位累加器和SIN/COS LUT模式。
输入时钟根据系统时钟定我这里选择100MHz
通道数我这里选择单通道
参数选择有系统参数System Parameter和硬件参数Hardware Parameter两种当选择系统参数时需要根据频率位宽来计算SFDR和FR(频率控制字当选择硬件参数时直接定义输出的相位宽度和频率宽度即可我这里选择硬件参数相位位宽是32位频率位宽是8位。
根据Xilinx官方手册phase width(相位位宽)Frequency Resolution(频率分辨率)channels(通道数)output width(输出波形位宽)SFDR之间的对于关系为
关于output width的位宽不同输出的数据格式如下
3、进入第二页配置界面配置频率控制字、相位控制字和输出波形。
由于在本次实验中需要连续输出不同的频率信号达到一个扫频的目的所以这里将频率可控制字和相位控制字都设置为可编程模式输出的波形为正余弦波形。如果你想输出固定频率的波形就可以选择锁定模式。这个根据实验要求进行更改即可。
4、第三页和第四页本次实验没有要求保持默认即可。在第四页由于频率控制字是可编程的在代码中会进行改变这里就不用做任何处理。
5、第5页就是配置的总览界面了在这里你可以看到你所配置的信息方便查看配置是否有问题。
6、最后点击OK就生成DDS IP核了然后就将DDS IP核例化到我们所设计的工程当中就可以直接使用了。
三、调用DDS IP核
调用DDS IP核实现扫频信号我这里设计的扫频范围是1KHz–10KHz通过控制频率控制字来更改输出的波形的频率让其在1KHz到10KHz直接变化又让其从10KHz变化到1KHz展现在频域中是三角波的形式。
1、顶层模块
`timescale 1ns / 1ps
//
//
// Create Date: 2023/03/16 09:54:38
// Design Name: 卡夫卡与海
// Module Name: DDS_top
// Project Name: DDS顶层模块
//
//
//
module DDS_top(
input sys_clk ,//系统时钟 100MHz
input sys_rst_n ,//系统复位
output m_data_tvalid ,//数据有效标志
output [7:0] m_data_sin ,//sin波形
output [7:0] m_data_cos //cos波形
);
//中间信号定义
wire s_phase_tvalid ;//相位有效标志
wire [31:0] s_phase_tdata ;//相位控制字
wire s_config_tvalid ;//频率有效标志
wire [31:0] s_config_tdata ;//频率控制字
wire m_phase_tvalid ;//输出相位有效标志
wire [31:0] m_phase_tdata ;//输出相位
wire [15:0] m_data_tdata ;//输出为16位高8位是sin波形低8位是cos波形
//assign m_data_sin = m_data_tdata[15:8];
//assign m_data_cos = m_data_tdata[7:0];
assign m_data_sin = {~m_data_tdata[15],m_data_tdata[14:8]};//将输出转为有符号数据输出 sin
assign m_data_cos = {~m_data_tdata[7],m_data_tdata[6:0]} ;//将输出转为有符号数据输出 cos
//模块例化
//DDS_IP模块
dds_compiler_0 u_dds_0 (
.aclk (sys_clk ),// input wire aclk
.s_axis_phase_tvalid (s_phase_tvalid ),// input wire s_axis_phase_tvalid
.s_axis_phase_tdata (s_phase_tdata ),// input wire [31 : 0] s_axis_phase_tdata
.s_axis_config_tvalid (s_config_tvalid),// input wire s_axis_config_tvalid
.s_axis_config_tdata (s_config_tdata ),// input wire [31 : 0] s_axis_config_tdata
.m_axis_data_tvalid (m_data_tvalid ),// output wire m_axis_data_tvalid
.m_axis_data_tdata (m_data_tdata ),// output wire [15 : 0] m_axis_data_tdata
.m_axis_phase_tvalid (m_phase_tvalid ),// output wire m_axis_phase_tvalid
.m_axis_phase_tdata (m_phase_tdata ) // output wire [31 : 0] m_axis_phase_tdata
);
//控制模块
dds_control u_dds_control(
.clk (sys_clk ),//时钟
.rst_n (sys_rst_n ),//复位
.phase_valid (s_phase_tvalid ),//相位有效标志
.phase_data (s_phase_tdata ),//相位控制字
.config_valid (s_config_tvalid),//频率有效标志
.config_data (s_config_tdata ) //频率控制字
);
endmodule
2、DDS IP核控制模块控制频率控制字的变化
Bash
`timescale 1ns / 1ps
//
//
// Create Date: 2023/03/16 10:26:29
// Design Name: 卡夫卡与海
// Module Name: dds_control
// Project Name: DDS控制模块
//
//
//
module dds_control(
input clk ,//时钟
input rst_n ,//复位
output phase_valid ,//相位有效标志
output [31:0] phase_data ,//相位控制字
output config_valid ,//频率有效标志
output [31:0] config_data //频率控制字
);
//参数定义
parameter F_word_1KHz = 32’hA7C5 ;//1KHz频率控制字 M = 1_0002^32/100_000_000
parameter F_word_10KHz = 32’h68DB8 ;//10KHz频率控制字 M = 10_0002^32/100_000_000
parameter F_word_change = 32’h1 ;//1KHz-10KHz变化精度
//信号定义
reg [31:0] config_data_reg ;//频率控制字寄存器
reg max_flag ;//当频率控制字最大时拉高
//max_flag
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
max_flag <= 1’b0;
end
else if(config_data_reg >= F_word_10KHz)begin
max_flag <= 1’b1;
end
else if(config_data_reg == F_word_1KHz)begin
max_flag <= 1’b0;
end
end
//控制频率控制字均匀变化
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
config_data_reg <= F_word_1KHz;
end
else if(max_flag == 1’b1)begin
config_data_reg <= config_data_reg - F_word_change;
end
else begin
config_data_reg <= config_data_reg + F_word_change;
end
end
//输出
assign phase_valid = 1’b1;
assign phase_data = 32’h0;//设置相位控制字为0
assign config_valid = 1’b1;
assign config_data = config_data_reg;
endmodule
3、仿真模块
Bash
`timescale 1ns / 1ps
//
//
// Create Date: 2023/03/16 14:04:09
// Design Name: 卡夫卡与海
// Module Name: DDS_top_tb
//
//
//
module DDS_top_tb();
reg sys_clk ;
reg sys_rst_n ;
wire m_data_tvalid ;
wire [7:0] m_data_sin ;
wire [7:0] m_data_cos ;
//模块例化
DDS_top u_DDS_top(
.sys_clk (sys_clk ),//系统时钟 100MHz
.sys_rst_n (sys_rst_n ),//系统复位
.m_data_tvalid (m_data_tvalid),//数据有效标志
.m_data_sin (m_data_sin ),//sin波形
.m_data_cos (m_data_cos ) //cos波形
);
//产生激励
initial begin
sys_clk = 1’b0;
sys_rst_n = 1’b0;
#20;
sys_rst_n = 1’b1;
#20000000;
$stop;
end
always #5 sys_clk = ~sys_clk;
endmodule
4、仿真波形如下
通过仿真波形可以看到生成了一个连续变化的正弦波和余弦波并且波形由慢到快再由快到慢成周期性变化满足设计要求。
总结
DDS IP核的配置还是比较简单的在使用封装好的IP核时不论是Xilinx的还是Altera的看官方手册还是很重要的只不过是纯英文的但是可以提升我们的英文阅读能力嘛当你阅读了很多IP核的手册过后你就会发现那些手册的排版基本上都是差不多的这样阅读起来也就没那么费劲了。