vivado DDS IP核的使用及仿真

参考:https://blog.csdn.net/weixin_45303812/article/details/123704440

新人第一次写文档,有错误的地方请大佬指点。

文档:Xilinx官网搜DDS

Configuration 可配置参数

1.Configuration Options,有如下三种模式

Phase Generator and SIN/COS LUT (DDS):相位和sin和cos的数据都是IP核自己产生

Phase Generator only:只要相位输出


SIN/COS LUT only模式:只需要sin/cos模块输出但此模式需要外部不断的输入累加的相位

2.System clock  系统时钟频率,同样也是采样率

3.Number of channels 通道数,本次用的是四通道,单通道设置为1

4.Mode of operation 不太懂,没涉及到,一般选择standard

5.Parameter selection分为两种模式,Hardware Parameter 和 System Parameter

Hardware Parameter模式没用过,看起来是设置输出的数据位宽和相位位宽就可以了。

System Parameter模式

SFDR:无杂散动态范围

简单来说就是每增加6dB,数据位宽增加1位,16位宽,就是96dB

Frequency Resolution:频率分辨率

这个决定了数据的精度,用时钟频率除以2的n次方,n为位宽,如果是多通道,需要再除以通道数

比如我这里设置是32位宽,4通道,时钟是491.52MHz,491.52*10^6 / (2^32*4),那么可以算出来这个大约设置在0.029-0.06之间,这边写个0.04,然后左边可以看到数config_tdata的位宽变成32位,位宽更大这样输入的频率精度就更精确。

Implementation可配置参数

1.Phase Increment Programmability相位增量(即频率控制字)控制模式选择一般选择固定或者可编程模式,如果是固定模式,可以通过第四个配置页Output Frequencies配置输出的频率,这里选择可编程模式,该模式下在valid有效时可对相位增量进行配置

如图,也就是congfig配置这个,我们需要4通道,那么valid就需要持续四个时钟周期,然后每个时钟周期输入我们需要的tdata,这个参数是根据我们之前设置的精度和时钟来算。具体下面tb用到时讲。

2.Phase Offset Programmability相位偏移量(即相位控制字)控制模式选择暂时没用到,用法应该和频率控制字类似。

3.Output  输出: sin、cos、sin&cos字面意思,这里选sin&cos

4.Has Phase Out :本实验不需要相位输出,不选。

其他的默认。

Detailed Implementation:设置输入输出的一些格式,需不需要ready,last等,根据需要选择即可。

Output Frequencies:输出频率,固定模式的时候设置这个,此处不需要。

最终配置如下:

代码部分:

直接调用IP核。

module dds_test(
		input 						aclk								,
		input 						aresetn								,
		input 						s_axis_config_tvalid				,
		output						s_axis_config_tready				,
		input 			[31: 0] 	s_axis_config_tdata					,
		input 						s_axis_config_tlast					,
		output						m_axis_data_tvalid					,
		input 						m_axis_data_tready					,
		output			[31: 0] 	m_axis_data_tdata					,
		output						m_axis_data_tlast					,
		output						event_s_config_tlast_missing		,
		output						event_s_config_tlast_unexpected		
    );

dds_compiler_0 dds_0 (
  .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_tready(s_axis_config_tready),                        // output wire s_axis_config_tready
  .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_tready(m_axis_data_tready),                            // input wire m_axis_data_tready
  .m_axis_data_tdata(m_axis_data_tdata),                              // output wire [31 : 0] m_axis_data_tdata
  .m_axis_data_tlast(m_axis_data_tlast),                              // output wire m_axis_data_tlast
  .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
);

endmodule

 tb部分,生成了四路正余弦IQ信号。

其中最重要的是上文提到的设置输出信号频率的参数设置。

以生成10M信号为例,我们的时钟采用的是491.52MHz,一共4路信号,那么实际采样率就是122.88MHz,我们设置的精度为32位,因此,10M信号的参数计算如下:

10/122.88 * 2^32 ≈ 32‘h 14D55555;

如果是-10M信号,由于频谱翻转,位置是122.88M-10M,计算如下

112.88/122.88 * 2^32 ≈ 32‘h EB2AAAAB

或者用2^32 - 10/122.88 * 2^32 ≈ 32‘h EB2AAAAB都可以,一个意思。

此外,DDS多通道的配置是,每个时钟周期VALID有效时,输入的参数才有效,因此多通道必须一个输入时钟一个参数,同时拉高valid,最后一个数据加last。

`timescale 1ns/1ps
module dds_tb();

reg 						aclk								;
reg 						aresetn								;
reg 						s_axis_config_tvalid				;
wire						s_axis_config_tready				;
reg 			[31: 0] 	s_axis_config_tdata					;
reg 						s_axis_config_tlast					;
wire						m_axis_data_tvalid					;
reg 						m_axis_data_tready					;
wire			[31: 0] 	m_axis_data_tdata					;
wire						m_axis_data_tlast					;
wire						event_s_config_tlast_missing		;
wire						event_s_config_tlast_unexpected		;

reg    	[1 : 0]   	cnt_chan				;
reg 	[31: 0] 	m_dout_0				;
reg 	[31: 0] 	m_dout_1				;
reg 	[31: 0] 	m_dout_2				;
reg 	[31: 0] 	m_dout_3				;

always @(posedge aclk) begin
	if (!aresetn) begin
		cnt_chan <= 2'b0;// reset
	end
	else begin
		cnt_chan <= cnt_chan + 1'b1;
	end
end
always @(posedge aclk) begin
	if (cnt_chan == 2'b0) begin
		m_dout_0 <= m_axis_data_tdata;
	end
	else if(cnt_chan == 2'b01)begin
		m_dout_1 <= m_axis_data_tdata;
	end
	else if(cnt_chan == 2'b10)begin
		m_dout_2 <= m_axis_data_tdata;
	end
	else if(cnt_chan == 2'b11)begin
		m_dout_3 <= m_axis_data_tdata;
	end
end

parameter fre_ch0 = 32'h14D55555  ,//10M
          //fre_ch0 = 873813333   ,
          fre_ch1 = 32'hEB2AAAAB  ,//-10M
          fre_ch2 = 32'h29AAAAAA     ,//20M
          fre_ch3 = 32'hD6555556    ;//-20M

initial aclk = 1'b0;
always #(500/491.52) aclk = ~aclk;
initial begin
        aresetn = 1'b0;s_axis_config_tvalid=0;s_axis_config_tdata = 0;s_axis_config_tlast=0;m_axis_data_tready=1'b0;
		#(1000*100/491.52)   aresetn = 1'b1;
		#(1000*100/491.52)    s_axis_config_tvalid = 1;s_axis_config_tdata = fre_ch0;m_axis_data_tready=1'b1;
		#(1000/491.52) s_axis_config_tvalid = 1;s_axis_config_tdata = fre_ch1;
		#(1000/491.52) s_axis_config_tvalid = 1;s_axis_config_tdata = fre_ch2;
		#(1000/491.52) s_axis_config_tvalid = 1;s_axis_config_tdata = fre_ch3;s_axis_config_tlast=1;
		#(1000/491.52) s_axis_config_tvalid = 0;s_axis_config_tdata = 0;s_axis_config_tlast=0;
end


dds_test tb (
  .aclk(aclk),                                                       
  .aresetn(aresetn),                                                 
  .s_axis_config_tvalid(s_axis_config_tvalid),                       
  .s_axis_config_tready(s_axis_config_tready),                       
  .s_axis_config_tdata(s_axis_config_tdata),                         
  .s_axis_config_tlast(s_axis_config_tlast),                         
  .m_axis_data_tvalid(m_axis_data_tvalid),                           
  .m_axis_data_tready(m_axis_data_tready),                           
  .m_axis_data_tdata(m_axis_data_tdata),                             
  .m_axis_data_tlast(m_axis_data_tlast),                             
  .event_s_config_tlast_missing(event_s_config_tlast_missing),       
  .event_s_config_tlast_unexpected(event_s_config_tlast_unexpected)  
);
endmodule

仿真结果:

输出的四路信号分别为10M,-10M,20M,-20M的IQ信号,图片仿真的结果没把IQ拆出来,大概看个波形,可以看出得到了想要的结果。

Vivado是一款由Xilinx开发的集成电路设计工具,用于设计和实现FPGA和SoC。DDS IP核Vivado中的一个IP核,用于生成数字频率合成器。根据引用\[2\]中的代码,可以看出DDS IP核的配置是通过控制字来实现的。控制字的值决定了输出信号的频率和相位。在引用\[3\]中的tb文件中,可以看到控制字的值被设置为66和6666,这将影响DDS IP核生成的输出信号的频率。通过修改控制字的值,可以实现不同的频率输出。在Vivado使用DDS IP核,需要将IP核添加到设计中,并根据需求配置IP核的参数,如控制字的值、时钟频率等。然后,将设计综合、实现和生成比特流文件,最后下载到目标设备中进行验证和测试。 #### 引用[.reference_title] - *1* *2* [Vivado DDS IP核使用仿真、多相处理和相关计算验证](https://blog.csdn.net/Popplio/article/details/126711613)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [FPGA自学笔记--DDS ip核使用vivado)](https://blog.csdn.net/lgk1996/article/details/123245246)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yan0224

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值