作者:碎碎思,来源:OpenFPGA
介绍
直接数字合成器 (DDS) 是软件定义无线电和数字通信系统中的关键工具,因为它们提供了一种在数字域中生成复杂信号的方法,该信号也是可变的。虽然 DDS 背后的理论相当简单,但第一次在 FPGA 中实现它可能有点挑战,这就是为什么我想创建这个项目作为一个简单的示例,说明如何使用Xilinx DDS Compiler IP并把它运行在 Ultra96 板上的可编程逻辑中。
DDS 也称为数控振荡器 (NCO),包含正弦波数据值的查找表,该表接收给定的相位值并输出正弦波的适当数据/幅度值。该输入值决定了输出波形的频率,值越小,DDS 通过正弦查找表的步进越慢,输出波形的频率越低。相反,输入值越高,DDS 步进查找表的速度越快,输出波形的频率也越高。此输入值通常称为调谐字,但在 Xilinx DDS Compiler IP 中,它称为相位增量。
如上图所示,此相位增量值 (Δθ) 越大,DDS 围绕表示复杂波形的单位圆的步进速度越快。当 M 加倍时,生成的复杂波形的频率也加倍,因为它绕单位圆的步进速度是原来的两倍。与该单位圆的相位值相关的数据点存储在 DDS 的查找表中。
在这一点上,我们可以看到 DDS 的主要优势之一:我们可以快速、平滑地改变输出波形的频率,只需告诉 DDS 多快步进查找表的输入值(又名 - 多快绕单位圆移动)。
输入相位增量值不断添加到自身 (A1 & D1) 以生成所需输出波形的每个瞬时值,从而从查找表 (T1) 中获得该瞬时相位值的适当数据值/幅度。
为了演示 DDS 及其输出波形频率变化的难易程度,我决定使用简单的线性调频波形比较合适。线性调频是指正弦波以一个频率开始,然后在一段时间内线性增加或减少(有时也称为扫描)。
决定在 26 us的时间内以 1MHz 的步长从 1MHz 到 25MHz 进行简单的线性调频(时钟是 100MHz,每个时钟周期 10 ns,我随机选择让 DDS 编译器输出每个频率 1 us只是为了在逻辑分析器窗口中容易看到它)。
通过递归地将 1MHz 的相位增量值添加到自身,然后将其作为输入提供给 Xilinx DDS Compiler IP ,这实现了从 1MHz 到 FPGA 结构时钟一半的线性调频(在 ILA 中采样时保留奈奎斯特规则)以 1MHz 为步长。选择只提高到 25MHz,这样整个 chirp 就可以立即显示在我的屏幕上进行截图,但我的结构时钟设置为 100MHz,所以可以降低到 50MHz。
使用 PG141 中的以下等式为 B 列中的每个输出波形频率计算了 C 列中的相位增量值:
然后我将 C 列中的相位增量值转换为十六进制以去除小数位,因为我是在 Verilog 中编写此代码的。我创建了 E 列和 F 列以表明相位增量的差异确实导致了与 1MHz 相同的十六进制值。
接下来就是搭建工程进行验证,详细的搭建过程就不展示了,可以在最后的工程中找到,在工程中主要有以下IP:
在 Vivado 的 Flow Navigator 列下,打开 IP 库并搜索“DDS”。当 DDS Compiler IP 出现在 IP 存储库的列表中时双击它,将弹出一个对话框。单击“Customize IP”按钮,将出现 DDS 编译器的配置窗口。
在如上所示的第一个选项卡中,为了我们的目的,保留所有默认设置。
在第二个选项卡下,为相位增量和偏移可编程性选择AXI Stream 接口。
同样关于 DDS 编译器的 AXI Stream 接口,在详细实施选项卡下,选中“Output TREADY”框。在处理 AXI Stream 时,TREADY 信号是一个必要的信号。
在加ILA的时候,一共加了4个探头监测DDS从接口的输入相位增量值和DDS主接口的输出数据和相位值。将芯片的深度设置为 65536。
实例化 ILA 和 DDS IP 后,编写了简单状态机来创建 AXI Stream 接口,将相位增量值输入到 DDS,然后等待 1 us,然后将 1MHz 步长添加到相位增量值并将其输入到DDS。该状态机还保持计数,在达到 25MHz 的相位增量值后,在下一次迭代中从 1MHz 开始返回。
这个简单的 AXI Stream 接口状态机在许多不同的应用程序中都非常方便。主要逻辑步骤是:
4 - 检查来自目标 IP 从接口的 Tready 信号,验证它已准备好接收下一个数据值。
生成新的比特流后,打开 FPGA 开发板的电源并连接到其 JTAG 端口。
在 Vivado 的 Flow Navigator 中,选择Open Hardware Manager ,然后选择Open Target和Autodetect选项。Hardware Manager与 FPGA 建立连接后,选择Program Device选项并指定刚刚生成的比特流。
成功下载后,ILA 窗口将出现,单击即时捕获按钮(带有 >> 字符的蓝色按钮),将看到 DDS 的波形。
ILA 顶部的图是 DDS 输出的实际正弦波形,下面的图是它的瞬时相位值。第三张图是输入到 DDS 的相位增量值。
底部的十六进制值只是状态机状态,用于演示每个状态如何与 DDS 控制关联。
参考
https://www.hackster.io/whitney-knitter/xilinx-dds-compiler-ip-tutorial-on-the-ultra96-f820db
https://docs.xilinx.com/v/u/en-US/pg141-dds-compiler
总结
希望这个简单的 DDS 示例对您有所帮助。关于更多信息可以查看官方IP文档(参考链接中),并深入了解其操作理论。
示例工程
https://github.com/wknitter/ultra96v2_chirpPrj