之前的文章对dds ip 的结构、精度、参数、接口进行了详细的说明,本文通过例化仿真对该IP的实际使用进行演示。本文例化固定模式和可配置模式两种模式分别例化ip并仿真,说明该IP的应用。
1、固定模式:
该模式下IP的参数设置如下图,时钟频率设置为100Mhz,两个通道时分复用,SFDR 60dB.
然后相位、相位偏差全部选择固定模式,
输出频率配置为1Mhz和2Mhz:
设置完之后再summary这里可以看到该IP的实现细节,输出位宽10bit,2ch,没ch的时钟速率是50Mhz,使用一个M18K的BROM实现查找表等等的一些细节。
在additional summary里边可以看到相应的频率控制字和实际精度,因为当前设置的时标准模式不是栅格(rasterized)模式,所以输出是有频偏的。
上述设置生成的IP端口如下,输入端口为时钟复位信号,输出sin cos和phase值。
dds_compiler_0 your_instance_name (
.aclk(aclk), // input wire aclk
.aresetn(aresetn), // input wire aresetn
.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid
.m_axis_data_tdata(m_axis_data_tdata), // output wire [31 : 0] m_axis_data_tdata
.m_axis_phase_tvalid(m_axis_phase_tvalid), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata(m_axis_phase_tdata) // output wire [31 : 0] m_axis_phase_tdata
);
这个IP的tb就非常简单了,只有提供时钟复位即可,但是输出时时分复用的,所以tb对输出信号进行了处理将两路输出分开了,方便波形观察,如下:
`timescale 1ns/100ps
module tb_dds_fix_normal ;
reg aclk = 'd0;
reg aresetn = 'd0;
wire m_axis_data_tvalid ;
wire [31 : 0] m_axis_data_tdata ;
wire m_axis_phase_tvalid ;
wire [31 : 0] m_axis_phase_tdata ;
always #1 aclk = ~aclk;
initial
begin
#100;
aresetn =1'b1;
end
dds_compiler_0 dds_compiler_0 (
.aclk (aclk ), // input wire aclk
.aresetn (aresetn ), // input wire aresetn
.m_axis_data_tvalid (m_axis_data_tvalid ), // output wire m_axis_data_tvalid
.m_axis_data_tdata (m_axis_data_tdata ), // output wire [31 : 0] m_axis_data_tdata
.m_axis_phase_tvalid (m_axis_phase_tvalid ), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata (m_axis_phase_tdata ) // output wire [31 : 0] m_axis_phase_tdata
);
reg S_ch0_valid ;
reg [15:0] S_ch0_cos ;
reg [15:0] S_ch0_sin ;
reg [31:0] S_ch0_pha ;
reg [15:0] S_ch1_cos ;
reg [15:0] S_ch1_sin ;
reg [31:0] S_ch1_pha ;
always @(posedge aclk)
if(!aresetn)
S_ch0_valid <= 1'b1;
else if(m_axis_data_tvalid)
S_ch0_valid <= ~S_ch0_valid;
always @(posedge aclk)
if(S_ch0_valid)
begin
S_ch0_cos <= m_axis_data_tdata[15:0] ;
S_ch0_sin <= m_axis_data_tdata[31:16] ;
S_ch0_pha <= m_axis_phase_tdata ;
S_ch1_cos <= S_ch1_cos ;
S_ch1_sin <= S_ch1_sin ;
S_ch1_pha <= S_ch1_pha ;
end
else
begin
S_ch0_cos <= S_ch0_cos ;
S_ch0_sin <= S_ch0_sin ;
S_ch0_pha <= S_ch0_pha ;
S_ch1_cos <= m_axis_data_tdata[15:0] ;
S_ch1_sin <= m_axis_data_tdata[31:16] ;
S_ch1_pha <= m_axis_phase_tdata ;
end
endmodule
仿真波形如下:
2、相位可配置模式:
该模式将相位偏差和相位步进设置为axi配置模式,如下图,其它配置保持不变:
生成的端口如下,该模式下增加了config端口,用于phase信息的配置:
dds_compiler_cfg your_instance_name (
.aclk(aclk), // input wire aclk
.aresetn(aresetn), // input wire aresetn
.s_axis_config_tvalid(s_axis_config_tvalid), // input wire s_axis_config_tvalid
.s_axis_config_tdata(s_axis_config_tdata), // input wire [31 : 0] s_axis_config_tdata
.s_axis_config_tlast(s_axis_config_tlast), // input wire s_axis_config_tlast
.m_axis_data_tvalid(m_axis_data_tvalid), // output wire m_axis_data_tvalid
.m_axis_data_tdata(m_axis_data_tdata), // output wire [31 : 0] m_axis_data_tdata
.m_axis_phase_tvalid(m_axis_phase_tvalid), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata(m_axis_phase_tdata), // output wire [15 : 0] m_axis_phase_tdata
.event_s_config_tlast_missing(event_s_config_tlast_missing), // output wire event_s_config_tlast_missing
.event_s_config_tlast_unexpected(event_s_config_tlast_unexpected) // output wire event_s_config_tlast_unexpected
);
这时,需要对tb进行相应的修改,增加config的配置,如下,新增一个11bit的计数器,计满后对两个通道的phase值进行翻倍:
reg aclk = 'd0;
reg aresetn = 'd0;
reg s_axis_config_tvalid= 'd0;
reg [31 : 0] s_axis_config_tdata = {{16'd1310},{16'd1310}};
reg s_axis_config_tlast = 'd0;
wire m_axis_data_tvalid ;
wire [31 : 0] m_axis_data_tdata ;
wire m_axis_phase_tvalid ;
wire [15 : 0] m_axis_phase_tdata ;
always #1 aclk = ~aclk;
initial
begin
#100;
aresetn =1'b1;
end
reg [10:0] S_clk_cnt ;
always @(posedge aclk)
if(!aresetn)
S_clk_cnt <= 'd3;
else
S_clk_cnt <= S_clk_cnt + 'd1;
always @(posedge aclk)
s_axis_config_tvalid <= ((S_clk_cnt==0)||(S_clk_cnt==1));
always @(posedge aclk)
s_axis_config_tlast <= (S_clk_cnt==1);
always @(posedge aclk)
if(s_axis_config_tvalid)
s_axis_config_tdata <= s_axis_config_tdata + s_axis_config_tdata;
dds_compiler_cfg your_instance_name (
.aclk (aclk ), // input wire aclk
.aresetn (aresetn ), // input wire aresetn
.s_axis_config_tvalid (s_axis_config_tvalid ), // input wire s_axis_config_tvalid
.s_axis_config_tdata (s_axis_config_tdata ), // input wire [31 : 0] s_axis_config_tdata
.s_axis_config_tlast (s_axis_config_tlast ), // input wire s_axis_config_tlast
.m_axis_data_tvalid (m_axis_data_tvalid ), // output wire m_axis_data_tvalid
.m_axis_data_tdata (m_axis_data_tdata ), // output wire [31 : 0] m_axis_data_tdata
.m_axis_phase_tvalid (m_axis_phase_tvalid ), // output wire m_axis_phase_tvalid
.m_axis_phase_tdata (m_axis_phase_tdata ), // output wire [15 : 0] m_axis_phase_tdata
.event_s_config_tlast_missing (event_s_config_tlast_missing ), // output wire event_s_config_tlast_missing
.event_s_config_tlast_unexpected (event_s_config_tlast_unexpected) // output wire event_s_config_tlast_unexpected
);
仿真结果如下如,可以看到随着phase步进的不断累加,两个通道的输出频率也在不断增加.
好了,本文就写的这里,希望通着这一系列的文章能帮助大家深入理解并正确使用DDS IP,详细的仿真过程可参考B站视频。
-
FPGA
+关注
关注
1635文章
21837浏览量
608343 -
Xilinx
+关注
关注
71文章
2173浏览量
122838 -
仿真
+关注
关注
50文章
4155浏览量
134486 -
DDS
+关注
关注
21文章
639浏览量
153246
发布评论请先 登录
相关推荐
XILINX FPGA IP之Clocking Wizard详解

XILINX FPGA IP之MMCM PLL DRP时钟动态重配详解

xilinx FPGA的FFT IP核的调用
如何使用Xilinx DDS Compiler IP并把它运行在Ultra96板上的可编程逻辑中?
基于FPGA的DDS IP核设计方案

IP例化和几个基于FPGA芯片实现的Demo工程
关于Xilinx中DDS IP的运用与讲解

Xilinx Vivado DDS IP使用方法

Xilinx DDS IP核的使用和参数配置

评论