实验十二 DA及DDS 12.2 DDS正弦信号发生器实验

一、实验设计目标

编写程序,使用FPGA调用存有正弦波表的ROM驱动R-2R DAC:

\1. 使用计数器生成地址线,产生固定频率的正弦波;

\2. 使用DDS方式产生地址信号驱动ROM,从而输出频率可调的正弦波。

二、实验设计思路

本实验中,第一步FPGA以500KHz时钟频率驱动一个计数器,产生0-1023的循环计数,并将其作为地址信号从ROM中顺序读取1024个点送给R-2R DAC,当ROM中存储一个完整的正弦波时,R-2R DAC输出的就是一个频率为500KHz/1024 = 488.28125Hz的正弦波。那么如何改变这个正弦波的频率呢?这就要使用DDS(直接数字合成)技术。

DDS信号源是能直接合成所需波形的一种频率合成器件,由频率合成器(相位累加器、波形查询表)和数模转换器构成。波形合成的基本思想与实验2.1中锯齿波的产生原理相同,只要控制送入数模转换器的数字值以一定规律周期性变化,便能得到所需的波形。

图2.7是DDS器件的核心部分流程图,包含相位累加器和波形查询表。CLK为工作脉冲,KW代表频率控制字。相位累加器内有一个N位寄存器,每来一个时钟脉冲CLK,相位累加器以步长KW递增,将相位累加器的高n位用作ROM的地址输入,即可完成从地址到波形幅值的映射工作。波形查询表ROM中存储了一个完整周期的正弦波,包含了2n个采样点的数据。查询表把送入的地址信息addr映射成所需波形的数字幅度信号,即输出Wave_Data。

img

2.7 核心部分流程图

DDS合成公式为:

img (2.3)

可以看出,当CLK的频率和N的值不变时,只要改变输入的频率控制字KW,即可改变输出波形的频率。

三、功能模块图与输入输出引脚说明

该工程包含顶层模块DAC_DDS,底层模块Phase_Acc和Sine_ROM。下面介绍一下顶层模块各引脚的功能:

(1)CLK:50MHz的时钟信号输入。

(2)SW_In:拨动开关输入,其中SW_In[0]是复位输入信号,低有效;SW_In[1]是ROM地址选择信号,为高时是计数器作为ROM地址,为低时是DDS的相位累加器输出的高10位作为ROM地址。

(3)DAC_Data:输送到R-2R电路的数字值,共有八位总线。

四、程序设计

DAC的驱动和计算公式在上一个实验中已经描述,这里主要描述下面两个关键点:

4.1 调用ROM IP,存储正弦波表

在上一个实验中,我们是以计数器的输出作为DAC的数据提供给R-2R DAC电路,而在这一个实验里,我们将在FPGA里存一张表,表里是一个完整的正弦波数字信号,接下来用计数器生成正弦波表的地址,就可以将正弦波表里的幅度数值输出给R-2R DAC,这样DAC的输出就是一个正弦信号。

首先我们需要生成一张正弦波表,可以用matlab,excel产生,也可以使用Mif_Maker2010来生成一个1024点8位数据宽度的正弦波表,程序如下:

1、如图2.15所示,打开Mif_Maker2010,点击设定波形里的全局参数。

img

图2.15 打开Mif_Maker2010,选择全局参数

设定全局参数如下,点击确定

img

设定波形中选择正弦波。

img

点击保存。

img img

图2.16 保存正弦波表为sine_1024.mif

将产生的sine_1024.mif文件复制到工程文件夹里面,下面我们调用TD的IP核来建立一个 ROM 查找表,步骤如下:

5、打开TD中的IP Generator管理器。如图2.17所示。

6、选择“Create a new IP core”,点击OK,将IP命名为sin_rom并存在dds程序文件夹下。如图2.18所示。

img

图2.17 选择IP Generator

img img

图2.18 创建IP名

7、在弹出来的IP核管理器中选择BRM下面的ROM。如图2.19所示。

img

图2.19 选择建立ROM IP

8、双击ROM后,进入ROM的设定页面。如图2.20所示设定ROM参数。

img

图2.20 配置ROM参数并将其初始化为sine_1024.mif的表

这样便生成了正弦ROM表的源文件。 在Top中可以直接调用这个ROM。

img

ROM的数据输出送到R-2R DAC的数据端口,ROM的地址ROM_ADDR由SW_In[1]选择是由计数器提供的0-1023循环,还是DDS的相位累加器模块产生的。两种地址的产生程序如下:

img

15 -28:分频器从50MHz时钟输入分频得到500KHz的时钟。

31-40: 500KHz时钟循环计数从0-1023,这样得到的正弦信号频率为500KHz/1024 = 488.2815Hz;

42-51:调用相位累加器模块产生地址,步进量KW可以手动修改,计算方法为KW=f*2^28/500000,这里2^28是指相位累加器的长度为28位,500000是我们的采样率500KHz。因此我们知道了期望频率后,就可以反推KW的值,例如本例中我们期望产生100Hz的正弦信号,通过上面公式计算得到KW=53,687.0912,我们这里取整得KW=53687,因此我们产生的100Hz实际上是99.99983Hz,并不是完美的100Hz,因此如果需要更精确的频率步进,可以使用更长的累加器位数,设计中上常用40位甚至更长。下面给出相位累加器的代码。

4.2 相位累加器模块

img

11-21: 设定一个28位的相位累加寄存器,然后在每个时钟(本例中是500KHz)的上升沿将其与频率控制字KW累加,一旦超过2^28,就折返回起始位置。

23:将相位累加寄存器的高10位取出来送给ROM的地址线,实现地址与幅度之间的转换。

五、FPGA管脚配置

set_pin_assignment { CLK } { LOCATION = R7; IOSTANDARD = LVCMOS33; }

set_pin_assignment { div_clk } { LOCATION = T4; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DAC_Data[0] } { LOCATION = B14; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DAC_Data[1] } { LOCATION = B15; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DAC_Data[2] } { LOCATION = B16; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DAC_Data[3] } { LOCATION = C15; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DAC_Data[4] } { LOCATION = C16; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DAC_Data[5] } { LOCATION = E13; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DAC_Data[6] } { LOCATION = E16; IOSTANDARD = LVCMOS33; }

set_pin_assignment { DAC_Data[7]} { LOCATION = F16; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW_In[0] } { LOCATION = A9; IOSTANDARD = LVCMOS33; }

set_pin_assignment { SW_In[1] } { LOCATION = A10; IOSTANDARD = LVCMOS33; }

DA****C_DDS输出实验IO Constraint

六、实验结果

SW0拨至“UP”,SW1也拨到“UP”,DAC输出口上产生488Hz的正弦波,连接到口袋仪器的AIN1观察信号。如下图所示。

img

图2.6 ROM表使用计数器查表时输出的正弦波

img

图2.7 ROM表使用DDS查表法时输出的正弦波

大家可以自行计算其他的正弦信号频率计算出KW值进行验证。当输出频率变高时,可能需要在DAC输出后面加入模拟低通滤波器来平滑波形。

img

图2.7 DDS查表法输出10KHz时的正弦波(KW=5368709)

img

图2.7 DDS查表法输出50KHz的正弦波(KW=26843545)