通过上面的介绍相信大家对数字变频已经有了一个较为整体性的认识,下面笔者来对照XILINX的DDS IP核对数字变频技术展开更进一步的说明,做到了理论和实践很好地结合,这样大家再带入Modelsim进行仿真测试就不仅掌握了数字变频的理论知识,也明白了其IP核的使用方法。
查阅XILINX的DDS IP核官方手册pg141-dds-compiler,如图1所示是DDS IP核的简化图,大家可以看到这里和前面数字变频理论基础介绍大同小异,XILINX的DDS IP核内部由累加器、寄存器、查找表等组成。
图1 DDS IP核的简化图
如图2所示是DDS IP核的频率控制字计算说明,这里XILINX也举实例说明频率控制字的计算方法,接着再归纳推导出一般性公式,大家可以看到例子当中fclk是120Mhz的 时钟频率即FPGA内部时钟,相位位宽Bθ(n)是10即正弦查找表是2的10次方,Δθ是十进制的12即每个时钟周期累加器在做12的递增操作。
整个操作合起来看就是FPGA内部以120Mhz的时钟频率,对一个累加器进行每个周期12的自加操作,同时每个周期再把累加器值映射到一张2的10次方正弦查找表中,取出表中的对应数值送到外部DAC中,外部DAC再通过硬件上的运放调理,输出给定幅值的特定频率正弦波,那么问题来了即经过这样一番操作后,输出正弦波的频率到底是多少赫兹呢?这里XILINX官方手册也给出了计算结果:fout=fclk*Δθ/2^Bθ(n)即fout=120*10^6*12/2^10=1.406250Mhz,当然对一般应用场景来说都是已知FPGA内部时钟频率fclk、DDS期望输出频率fout以及正弦查找表的位宽去求频率控制字Δθ,所以变换整理公式即可以得到:Δθ= fout*2^Bθ(n)/ fclk。
图2 DDS IP核的频率控制字计算说明
搞明白DDS IP核频率控制字的计算方法,相信细心的同学在思考过后肯定会抱有一些疑惑其中最典型的应该就是fclk是FPGA内部时钟频率这点好理解,fout是DDS期望输出频率也同样直观易懂,但是公式中的Bθ(n)正弦查找表位宽要怎么去选定呢,这个值的选取有没有什么特定的含义呢?
其实笔者刚接触到DDS IP核的时候在看完XILINX官方手册给出的频率控制字计算公式后同样抱有这样的困惑,当时也在网络上搜索了很多博客资料等,但遗憾的是很少看到真正有价值的文章,如图3所示是Bθ(n)正弦查找表位宽选取的计算说明,这个值的选取将会直接影响到DDS IP核输出的频率分辨率。
如下图所示,这里XILINX官方手册同样也人性化地举了一个例子进行说明,对于fclk为100Mhz的时钟频率系统,要想得到最小输出精度为1hz的正弦波波形,则要对应的正弦查找表是2的27次方位宽,可以看到XILINX官方给出的计算公式是fclk/Δf的比值再以2为底数向下取对数,在这里猛地一看感觉非常绕脑,但是仔细分析就不难发现其中的含义:对于给定fclk的时钟频率系统,每个时钟周期都会进行频率控制字的自加操作,显然在这里累加值至少为1,那么当累加器为1时则对应了系统的最小分辨率即fclk/2^Bθ(n),这个值代表了DDS IP核可以设定的最小频率精度。
图3 DDS IP核的频率分辨率的计算说明
在结合XILINX的DDS IP核手册对数字变频参数进行说明后,我们再来看一看IP核的具体设置和各个信号量所代表的含义,以方便后续对其进行仿真测试,搞明白整个IP核的行为特征,细心的同学不难发现在XILINX的VIVADO环境下支持旗下所有7系列的芯片,而相比于ISE环境,大部分XILINX的官方IP核都支持AXI总线协议,AXI总线协议引入了握手机制等,当然在这里篇幅原因笔者就不展开叙述了,感兴趣的同学可以查阅XILINX的官方手册。
如图4所示是DDS IP核CONFIG输入通道的数据格式,顾名思义地用户通过这个输入通道就可以初始化DDS IP核,以输出给定频率和相位的正弦波波形,可以看到XILINX的官方手册对DDS IP核的组包格式进行了详细说明,同时注意到s_axis_config_tdata信号在s_axis_config_tvalid信号为高时有效,且s_axis_config_tdata信号是由PINC和POFF两者共同拼接而成的。
这里XILINX官方也举例进行说明方便用户理解,如下图所示当相位phase位宽是11位时即相位累加器总位宽是11位,则相位控制字POFF和频率控制字PINC位宽都是11位,那么对于总位宽是32的s_axis_config_tdata的0-10位是PINC的输入值,16-26位是POFF的输入值。
频率控制字PINC即每个fclk时钟周期内DDS IP核内部自加值,相位控制字POFF即在相位累加器中频率控制字自加的基础上再增加的一个固定值,这样即可实现改变频率相位的效果,当然具体的细节会笔者会在后面仿真DDS IP核中做进一步说明。
图4 DDS IP核CONFIG输入通道的数据格式
如下图5所示是DDS IP核DATA输出通道的数据格式,在IP核中默认选择Sine和Cosine都输出的情况下,m_axis_data_tdata也是由SINE和COSINE共同组成,在这里XILINX官方手册同样举例做了说明,对于总位宽是32的m_axis_data_tdata的0-10位是COSINE的输出值,16-26位是SINE的输出值。
如图6所示是DDS IP核复位信号的说明,大家可以清楚地看到XILINX的DDS IP核支持了两种接口方式,一种是不含TREADY握手信号的而另一种是含TREADY握手信号的,官方手册中指出aresetn信号默认为高当其为低时则表示对DDS IP核的复位,同时该信号作为复位信号时需要至少2个时钟周期持续为低才生效。
注意到m_axis_data_tvalid在复位起效果后会被拉低若干个时钟周期,而当其作为输出信号重新再被DDS IP核置高后,此时m_axis_data_tdata输出数据才是用户所期望的正弦波波形数据,对照XILINX的官方手册简单地总结几点也为后续仿真DDS IP核提供依据:
- s_axis_config_tdata信号在s_axis_config_tvalid信号为高时有效,且s_axis_config_tdata信号是由PINC和POFF两者共同拼接而成的;
- m_axis_data_tdata信号在m_axis_data_tvalid信号为高时有效,且m_axis_data_tvalid信号在默认SINE和COSINE输出状态下也是由Sine和Cosine两者共同拼接而成的;
- aresetn信号低时则表示对DDS IP核的复位至少拉低2个时钟周期DDS IP核才可实现内部复位,复位完成后波形输出信号m_axis_data_tdata在m_axis_data_tvalid为高时有效,相似的相位输出信号m_axis_phase_tdata在m_axis_phase_tvalid为高时有效;
图5 DDS IP核DATA输出通道的数据格式
图6 DDS IP核复位信号的说明
最后想补充说明一点如图7所示是DDS IP核对SFDR无杂散动态范围的说明,其实说真这个名词也很少听过,但在XILINX的DDS IP核初始化中需要去单独配置,所以至少我们需要搞清楚这个值的设定取决哪些因素,XILINX官方手册同样很贴心地给出了计算公式,即DDS IP核的最终输出位宽在None and Dithering模式下是SFDR/6的向下去余,在Taylor模式下是SFDR/6的向下去余后再加1,再去结合原理图我们选取的DAC芯片型号是AD9708,其对应的位宽是8位,所以在None and Dithering和Auto模式下我们需要配置SFDR的值是48,当然感兴趣的同学可以再对照手册理解下SFDR的具体含义。
图7 DDS IP核对SFDR无杂散动态范围的说明
通过以上对数字变频理论分析和对XILINX的DDS IP核手册信息提取为后期的程序设计提供了有力支撑,下面笔者就通过配置和仿真IP核等具体操作,带着大家实际观察波形去验证前面的知识点,大家打开Vivado在IP核的搜索栏中输入关键字DDS,如图8所示选中DDS IP核即可,如图9到11所示是该IP核的具体配置,笔者在这里不想再像写说明书一样每个选项都逐一赘述列举,具体的细节完全可以去查阅XILINX的DDS IP核官方手册pg141-dds-compiler。
对于DDS IP核的配置说明几点核心问题,首先我们选择了0.5Mhz作为fclk即系统时钟,然后把分辨率设置为高精度的0.01hz,根据上面的公式大家可以计算得出需要累加器位宽是26(500000/2^26=0.00745<0.01),其次在SFDR中选择48对应了硬件上AD9708的8位输出位宽,再次把PINC和POFF都设置为支持用户设定和DDS IP核输出Sine和Cosine模式,最后选择自动分配延迟周期节约IP核底层硬件资源,并引出aresetn复位信号。
图8 Vivado的搜索栏中搜索DDS IP核
图9 DDS IP核的Configuration界面
图10 DDS IP核的Implementation界面
图11 DDS IP核的Detailed Implementation界面
在配置完DDS IP核,我们就要开始写对应的Testbench带入Modelsim进行仿真验证帮助朋友们进一步理解整个IP核的行为特征,在写激励之前不妨问自己几个问题即想验证哪些功能。
在这个例程中我们希望用DDS IP核输出可设定频率和偏移的正弦波,那么对于fclk是0.5Mhz,正弦波形查找表位宽Bθ(n)是26位且最小分辨率是0.01hz,DDS正弦波输出位宽为8位的情况下,fout正弦波输出频率即为fout=fclk*Δθ/2^Bθ(n)=500000*Δθ/2^26。
显然在这里输出正弦波频率fout是已知的,而频率控制字Δθ是未知的,那么对fout是1hz时,Δθ=fout*2^Bθ(n)/fclk=1*2^26/500000=134.217728,2hz时Δθ=134.217728*2=268.435456,即通俗易懂的Δθ=134*fout,这也非常好理解当PINC频率控制字Δθ越大,那么遍历完整个正弦波形查找表的速度也就越快,反应出来的直观结果就是频率越来越大其周期越来越小。
同时我们也想在这个Testbench中验证DDS IP核的相位控制字和复位功能,那么我们还需要计算出POFF相位控制字的值,通过前面的分析可知fclk是0.5Mhz,正弦波形查找表位宽Bθ(n)是26位,那么按照数学上对于正弦波的定义,一个完整的正弦波周期是360deg折合成一张总地址是2^26的查找表,相对应的偏移90deg则POFF相位控制字是2^25,偏移180deg则POFF相位控制字是2^26,所以激励中我们可以设计每次在拉低aresetn两个周期后,通过拉高s_axis_config_tvalid信号再向s_axis_config_tdata写入POFF和PINC,观察m_axis_data_tvalid和m_axis_data_tdata、m_axis_phase_tvalid和m_axis_phase_tdata是否符合我们的设计预期。
也需要注意到一点细节在DDS IP核的极性配置中我们没有勾选负半轴的Sine和Cosine,所以在这里需要简单地做一下波形拼接成一个完全周期的正弦波,具体细节大家可以参考如图12所示的DDS IP核的输入信号激励设计。
图12 DDS IP核的输入信号激励设计
大家带入到Modelsim里仿真即可观察到如图13所示DDS IP核的仿真结果,注意到在Testbench激励中,我们开始第一次输入的s_axis_config_tdata值是64'd134即对应为1hz频率的正弦波;而第二次输入的s_axis_config_tdata值是{6'd0,1'd1,25'd0,32'd1340}即对应为10hz频率偏移180deg的正弦波;第三次输入的s_axis_config_tdata值是{6'd0,2'd1,24'd0}即对应为10hz频率偏移90deg的正弦波,每次在拉低aresetn两个时钟周期后,再对应地拉高s_axis_config_tvalid,通过s_axis_config_tdata信号写入PINC和POFF的值,大家可以带入Modelsim中观察其仿真结果完全符合预期设计。
图13 DDS IP核的仿真结果