最近在調試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