最近在调试DA芯片AD9125正好需要测试输出正弦波,看了下VIVADO有自带的IP可以产生正弦波和余弦波,正好拿过来学习学习。
看官方手册也是挺多的,看了老半天也没完全看懂怎么用,在网上搜了相别人写的博客:
- https://blog.csdn.net/u013215852/article/details/91042672 (Vivado DDS IP核使用和仿真(一、单通道信号发生器))
- https://blog.csdn.net/u013215852/article/details/91044141(Vivado DDS IP核使用和仿真(二、多通道信号发生器))
用dds Compiler v6.0 IP可以生成正弦波和余弦波。
系统时钟80Mhz,1个通道,数据位宽16bit,相位位宽16bit,输出频率1Mhz的正弦波和余弦波生成方式如下:
Spurious Free Dynamic Range(dB) ,它决定了输出波形数据的位宽,公式:SFDR = Output Data Width x 6 =16*6=96
Frequency Resolution,它决定了相位的位宽,当相位位宽为16时,计算公式如:
F= fCLK/(2 ^ phase width ) = 80_000_000/(2^16)=1220.703125(注意小数位要全部填上)
第二个界面按着这个选择即可:
这个选择默认:
输出频率根据需要进行输出:
相位偏移:
然后是生成IP,仿真:注意它不能生成example
我们得用一个只有这个IP的工程,没有其它代码,将tb_dds_complier文件在sim下面设置为顶层,如果有其它代码有可能会造成无法将tb_dds_complier文件设置为顶层。
调用vivado的仿真工具仿真,得到的波形如下:将要看的正弦波和余弦波设置为有符号数和模拟量
上面得到的就是正弦波和余弦波,你以为这样接结束了?并没有,仔细看会发现正弦波和余弦波波形并不是1Mhz的,它是125khz。
这是因为自带的仿真tb文件里面输入时钟不是80M的,如下图,它是10Mhz的
修改后如下:
重新编译仿真,看波形:
现在仿真波形就是1Mhz的了。
在仿真这部分被坑了一把,一直以为是我的设置错了。当然直接上板调试是没有问题的。
在前面那两个连接的博客中仿真波形也是跟我的一样的,只不过他没有注意到这个细节部分。
----------------------2019.10.31更新-----------------
这几天想测试VIVADO2017.4生成的DDS IP看能不能在Questasim上仿真,发现使用Questasim10.6b、Questasim10.6c、Questasim10.6d才可以对VIVADO2017.4生成的DDS IP进行仿真,使用Questasim10.7以上版本和Questasim10.6以下版本都不行,其实每一个VIVADO的版本都对应了一个Questasim的版本。另外使用Questasim仿真的时候不要使用IP自动生成的VHDL代码去仿真,因为VHDL代码的头文件里包含了IP文件,编译的时候会提示找不到IP核的那个文件,导致编译不过。
我的做法是生成DDS IP的时候使用OOC模式,就会在IP的目录下生成dds_compiler_0_sim_netlist.v文件,我们使用它来进行仿真,编译就可以通过并且看到跟VIVADO仿真中一样的波形。
----------------------2020.03.24更新-----------------
经过这几个月对这个IP核的使用,有一些新的笔记,在这里记录一下:
假设有这样的一个使用场景,我们需要测试两个DDS的同步输出,同时需要对两个DDS的输出频率随时进行修改,每次同步输出的初始相位也会进行修改,那么配置方式如下:
SFDB设置为96表示波形赋值数据的位宽为16bit(16*6=96),FR设置为0.02表示频率的精度为0.02,此时相位位宽为32bit;
S_AXIS_PHASE总线的位宽为64bit
由于一个DDS IP我们只生成一个通道,所以可以不需要tlast。
wire [63:0] s_axis_phase_tdata;//bit[63:32]表示相位控制字,bit[31:0]表示频率控制字
wire [31:0] m_axis_data_tdata;//bit[31:16]表示cos函数,bit[15:0]表示sin函数
dds_compiler_0 dds (
.aclk (clk_50 ),//: IN STD_LOGIC;
.aresetn (rst_n ),//: IN STD_LOGIC;
.s_axis_phase_tvalid (1'b1 ),//: IN STD_LOGIC;
.s_axis_phase_tdata (s_axis_phase_tdata ),//: IN STD_LOGIC_VECTOR(63 DOWNTO 0);
.m_axis_data_tvalid (),//: OUT STD_LOGIC;
.m_axis_data_tdata (m_axis_data_tdata ),//: OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
.m_axis_phase_tvalid (),//: OUT STD_LOGIC;
.m_axis_phase_tdata () //: OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
);
需要注意的时s_axis_phase_tvalid信号应该一直拉高,否则会出现没有波形输出的情况!!!!!
在输出任意频率的时候:频率控制字 = (FREQ*2^32)/50_000_000