AD9910的切换profile问题
Last updated on October 20, 2022 1:36:04 PM
本文中,可能将AD9910和DDS混称,可能有各种简称。
Intro
在我的实验室广泛使用AD9910作为DDS芯片,用于产生rf信号经过放大供给AOM。
在实验中,我们有这么一种需求:希望信号在短时间内可以切换为我们期望的另一种配置(频率,幅度,相位等等)。这种需求当然是相当合理的,比如我想一些参数即时改变,用于实现比如快速反馈、做优化等等。当然,可以用AWG来做这个事情,但是AWG多贵啊(x,而DDS只需要不到1w块就可以买四个通道(当然,电路板是自己做的)。
那么如何满足我们这么一种需求呢?AD9910提供了三种[1]解决方案:
- 通过串口通信加spi通信来实现对profile的配置;
- 通过给profile引脚对应的电平从而快速切换profile0-7中的配置;
- 通过并行接口(parallel port)来实现对幅度、相位、频率的快速、任意[2]调制。
看起来很好,但是我们仔细一想很容易排除了1和3这两种想法:
- 串口通信太慢了!这一点是显而易见的,即使在对时序要求不那么严格([3])的离子阱实验中,也不可能为了串口通信等待量级的时间。而且串口通信相对不稳定。
- 并行接口需要14 bits per channel,这14位bit需要精准地同步在一个的时钟上,这听起来就不是一个很现实的事情(做到过,但是考虑到一块板子上有很多芯片,而且FPGA管脚资源有限,用14个bit来实现这个功能并不是一个很好的选择)。
ps. 当然,平时配置DDS还是通过串口通信的方式实现的,而且设计上其实留有并口的接口。
方案只剩下一种,自然是使用三个bit来切换profile。这种方式有和并口可比的速度(),同时只需要三位bit就可以实现8个profile的切换,看起来十分的划算。
那么,代价是什么呢?
至今实验室中还没有一块多通道DDS可以实现profile的全正确切换。比如我从000切换到001,只有一个管脚的值发生了改变,这是一定可以切对的,但从001切换到010,有两位同时改变,这时DDS可能会错误的识别为各种奇怪的值,比如011,并保持在这个错误的profile。
那切换profile会有概率切换错,这谁还敢用?
当然,有妥协的办法:使用格雷码。这样每次DDS切换profile都只改变一位,如我想从001切换到010,可以使用如下路径:001->000(or 011)->010。
看起来很好。但这总归在我们的时序中引入了不期望的一段。
这可咋整?
AD9910的内部有一个采样时钟频率/4的sync_clk时钟。一般我们会用10M的晶振或者铷钟,pll 100倍到1G使用,这样sync_clk是250M (4ns)。AD9910会在每个sync_clk的上升沿检测三个profile管脚,从而实现profile的切换。
我们一开始的理解是,profile是边沿敏感,必须非常严格地同步在sync_clk上。为什么认为是边沿敏感呢,因为如果是电平敏感的话,切到了错误的profile上总是可以调整过来的。
坑如下:
- sync_clk太快了,显然需要对输入的profile做一些操作,让他们在4ns内完成切换。
- 其实profile管脚是电平敏感。
1总是可以解决的,比如用fifo+打拍将profile的改变同步在sync_clk的edge上。2是什么意思呢?
DDS感受到了profile有变化后,会发送一个io_update信号。在io_update的这段时间,是profile管脚的deadtime。这就很坑了,意味着虽然检测到了正确的电平,但DDS这段时间忙着错误的业务,没空鸟你,你的这条命令就被忽略了。
也就是说,如果一切都做的比较好,且profile的更新同步在sync_clk上,profile还是无法正确地切换,说明DDS内部的sync_clk和你从FPGA发出的profile到达DDS管脚时的信号的边沿有点重合了,导致无法正确地读取profile。
那一种很鸡贼的方法就是,本来你的profile同步在sync_clk的上升沿上,只需要把它改为同步在下降沿上,这样profile信号就会凭空平移2ns,这样就会错开。
突然感觉文章戛然而止了。。。Let’s call it a day.