第一次学,查询了很多CSDN网页,也问了组里的技术专家,得到了很多指导。把我的个人学习笔记在这里保存记录分享,如果有问题欢迎大家批评指正。也欢迎大家点赞评论收藏,一起进步!
创建工程,在IP核配置页面选择DDS compiler 6.0。对IP核进行配置。

如图所示配置参数。
Configuration(配置)页面,Configuration Options 有三个选项,分别是相位产生器和SIN COS查找表、单独的相位产生器、单独的sin/cos,一般选择第一个,利用IP核生成一个频率相位可调的正余弦发生器。
将System Clock系统时钟设置为250MHz,Number of Channels通道数设为1,Parameter Selection(参数选择)主要分为Hardware Parameter 和 System Parameter两种。
在System Parameter模式下,配置页面需要配置系统参数设置。共有Spurious Free Dynamic Range(SFDR)、Frequency Resolution(频率分辨率)、Noise Shaping(需不需要整形噪声选择自动模式就行)三项。其中SFDR与输出数据位宽相关,见手册表格。

Hardware Parameter模式下,Noise Shaping噪声整形选项一般选择None。Phase width指的是输出的相位宽度信息,output width 指的是输出的数据位宽;相位位宽选择32位,数据位宽采用16位。
Implementation页面,Phase Increment Programmability与Phase Offset Programmability,相位增量(即频率控制字)和相位偏移量(即相位控制字)控制模式选择,一般选择可编程模式,该模式下在valid有效时可对相位增量和相位偏移量进行配置;Output sin、cos、sin&cos根据需要选择即可。如图所示:

在Summary中检查配置无误:

事实上,任何周期信号都可以分解为一系列正弦或余弦信号之和,正弦信号是关于相位的一个周期函数。相位和幅值的一一对应关系就好比存储器中地址和存储内容的关系,如果把一个周期内每个相位对应的幅度值存入存储器当中,那么对于任意频率的正弦信号,在任意时刻,只要已知相位Φ(t),也就知道地址,就可通过查表得到s(t)。
相位累加器在每个时钟脉冲输入时,把频率控制字累加一次,相位累加器的输出数据就是信号的相位,用输出的数据作为波形存储器(ROM)的相位取样地址,这样就可以把存取在波形存储器内的波形抽样值经查找表查处,完成相位到幅值的转换。频率控制字相当于Φ(t)中的2πfc,相位控制字相当于Φ(t)中的θ0。
由于相位累加器字长的限制,相位累加器累加到一定值后,其输出将会溢出,这样波形存储器的地址就会循环一次,即意味着输出波形循环一周。故改变频率控制字即相位增量,就可以改变相位累加器的溢出时间,在时钟频率不变的条件下就可以改变输出频率。改变查表寻址的时钟频率,同样也可以改变输出波形的频率。
为了获得较高的频率分辨率,则只有增加相位累加器的字长N。
这部分参考了部分CSDN内容。
原文链接:https://blog.csdn.net/u014586651/article/details/88830115
相位累加器的字长为N,就将一个完整周期的正弦波的相位均匀分割为
个离散相位。如果想将频率提高到2倍 = 点数变为1/2(隔一个点输出一个波形)。事实上,DDS满足:

其中,fout是输出频率,fclk是系统工作时钟的频率,FTW是频率控制字,N是相位累加器的位数。对于一个IP核生成一路信号,其满足:

其中,fout为输出频率,fclk为输入ip的时钟。Δθ为相位增量(频率控制字),Bθ(n)为频率精度位数、输出相位数据的宽度(Phase Width),计算公式满足:

其中Δf为频率精度,对应IP核中Frequncy Resolution。
相位控制字满足:

其中θ为相位偏移量,N为相位累加器的位数。
在IP Symbol中检查IP核的端口,对IP核进行配置和例化。
代码如下所示:
module simu(
);
reg clk;
reg [63:0]pinc_sin;
reg en_pinc;
initial begin
pinc_sin={32'd715827883,32'h0fffffff};
en_pinc=1; //必须为1才有效
clk=0;
end
always #2 clk=~clk;
wire [15:0]dout_dds;
wire data_tvalid;
dds_compiler_0 name(
.aclk(clk),
.s_axis_config_tvalid(en_pinc),//控制字有效信号,为1时控制字才有用。
.s_axis_config_tdata(pinc_sin),
.m_axis_data_tvalid(data_tvalid),
.m_axis_data_tdata(dout_dds));
endmodule
其中,pinc_sin采用位拼接的方式配置频率控制字和相位控制字,本实验初相偏差π/3,根据相位控制字计算公式,poff=(π/3)*2^32/2π= 32'd715827883,频率控制字选择32'h0fffffff,仿真可以输出正弦波形。

在第二节中已经实现了输出250MHz的正弦波形,现在将使用多相处理,用四路250MHz的正弦波形构建一个1GHz的正弦波形。

基本原理如上图所示,在一个上升沿内并行产生四个相位,再进行相应的相幅转换。图中1-4分别代表四路信号。由图可知,对于一路信号而言,其频率控制字FTW’=4FTW,每一路信号之间有一个FTW的相位差。
配置四个与第二节完全相同的DDS核:

simu代码如下所示:
module simu(
);
reg clk;
reg [63:0]pinc_sin_0;
reg [63:0]pinc_sin_1;
reg [63:0]pinc_sin_2;
reg [63:0]pinc_sin_3;
reg en_pinc_0;
reg en_pinc_1;
reg en_pinc_2;
reg en_pinc_3;
reg [15:0]q0;
//存储波形数据输出为csv文件
integer file_0;
integer file_1;
integer file_2;
integer file_3;
initial begin
//对四个dds赋值,每个间隔dds相差FTW。频率控制字FTW'=4FTW
pinc_sin_0={32'd715827883,32'h03fffffc};
//h0fffffff=d268435455;h00ffffff=16777215;h03fffffc=d67108860
pinc_sin_1={32'd732605098,32'h03fffffc};
pinc_sin_2={32'd749382313,32'h03fffffc};
pinc_sin_3={32'd766159528,32'h03fffffc};
en_pinc_0=16'd1;
en_pinc_1=16'd1;
en_pinc_2=16'd1;
en_pinc_3=16'd1; //必须为1才有效
clk=16'd0;
q0=16'd0;
file_0=$fopen("E:/study2022/dds2/data_0.csv","w");
file_1=$fopen("E:/study2022/dds2/data_1.csv","w");
file_2=$fopen("E:/study2022/dds2/data_2.csv","w");
file_3=$fopen("E:/study2022/dds2/data_3.csv","w");
end
always #2 clk=~clk;
wire [15:0]dout_dds_0;
wire [15:0]dout_dds_1;
wire [15:0]dout_dds_2;
wire [15:0]dout_dds_3;
wire data_tvalid_0;
wire data_tvalid_1;
wire data_tvalid_2;
wire data_tvalid_3;
always @(posedge clk)begin
if(q0 < 16'd4000)begin
$fwrite(file_0,"%h\n",dout_dds_0);
$fwrite(file_1,"%h\n",dout_dds_1);
$fwrite(file_2,"%h\n",dout_dds_2);
$fwrite(file_3,"%h\n",dout_dds_3);
q0 <= q0 + 16'd1;
end
else begin
q0 <= q0;
$fclose(file_0);
$fclose(file_1);
$fclose(file_2);
$fclose(file_3);
end
end
dds_compiler_0 name0(
.aclk(clk),
.s_axis_config_tvalid(en_pinc_0), //相位控制字有效信号,同。
.s_axis_config_tdata(pinc_sin_0),
.m_axis_data_tvalid(data_tvalid_0),
.m_axis_data_tdata(dout_dds_0));
dds_compiler_1 name1(
.aclk(clk),
.s_axis_config_tvalid(en_pinc_1), //相位控制字有效信号,同。
.s_axis_config_tdata(pinc_sin_1),
.m_axis_data_tvalid(data_tvalid_1),
.m_axis_data_tdata(dout_dds_1));
dds_compiler_2 name2(
.aclk(clk),
.s_axis_config_tvalid(en_pinc_2), //相位控制字有效信号,同。
.s_axis_config_tdata(pinc_sin_2),
.m_axis_data_tvalid(data_tvalid_2),
.m_axis_data_tdata(dout_dds_2));
dds_compiler_3 name3(
.aclk(clk),
.s_axis_config_tvalid(en_pinc_3), //相位控制字有效信号,同。
.s_axis_config_tdata(pinc_sin_3),
.m_axis_data_tvalid(data_tvalid_3),
.m_axis_data_tdata(dout_dds_3));
Endmodule
代码中对频率控制字、相位控制字进行了相关配置,并将输出的四路信号的相关点的数据存为csv文件。
实验波形图如图所示:

计算验证一下,FTW’=4TFW=67108860,fclk=250*10^6,N=32。
理论上的fout=FTW’*fclk/2^N=67108860*250*10^6/2^32=3.9062*10^6Hz。
观察波形图,输出信号周期为500ns-244ns=256ns,fout=1/256ns=3.9062*10^6Hz,相吻合,频率控制字设置无误。
相位初相能观察到π/3的初相,不同信号之间能观察到一个FTW的相差,频率控制字设置无误。


将保存的信号csv文件导入Matlab,对其进行交叉拼接处理,并绘制拼好后的正弦数组的频谱图。

相关Matlab代码如下所示:
%读取波形数值
%num_0 = xlsread('E:/study2022/dds/data_0.xlsx',1,'B1:B511')
%num_1 = xlsread('E:/study2022/dds/data_1.xlsx',1,'B1:B511')
%num_2 = xlsread('E:/study2022/dds/data_2.xlsx',1,'B1:B511')
%num_3 = xlsread('E:/study2022/dds/data_3.xlsx',1,'B1:B511')
%16进制转化为10进制数
data_0=hex2dec(data0)
data_1=hex2dec(data1)
data_2=hex2dec(data2)
data_3=hex2dec(data3)
%交叉合并(拼接)
merge=[data_0'
data_1'
data_2'
data_3'];
merge=reshape(merge,[],1); %[]=length(data_0)+length(data_1)+length(data_2)+length(data_3)
%把矩阵merge转化为csv文件
csvwrite('E:/study2022/dds2/merge.csv',merge);
%画图
for i=1:15960
if merge(i)>32768
merge(i)=merge(i)-65536; %将
else
i=i+1;
end
end
plot(merge)
%对画出的图像做FFT观察频谱
ff=20*log10(abs(fft(merge(1:15960))));
%ff2=abs(fft(merge(1:15960)));
plot(ff)
%plot(ff2)
其中,读取波形数值部分可以用MATLAB自带的导入工具:

绘图结果如下图所示:


N个采样点经过FFT变换后得到N个点的以复数形式记录的FFT结果。
假设采样频率为Fs,采样点数为N。那么FFT运算的结果就是N个复数(或N个点),每一个复数就对应着一个频率值以及该频率信号的幅值和相位。
第一个点对应的频率为0Hz(即直流分量),最后一个点N的下一个点对应采样频率Fs。其中任意一个采样点n所代表的信号频率:Fn=(n-1)*Fs/N。
对实验数据进行验证,理论上输出频率为fout=3.9062MHz,根据图可观察后计算,真实输出频率fout=10^6*63/16000=3.9375MHz,考虑到绘图误差,数据在可控范围内,整体实验成功。
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..