[FPGA]DDS与并行ADC、DAC

[FPGA]DDS与并行ADC、DAC

基础知识

高速数据转换器的时钟管理

在这里插入图片描述

  • ACLK和DCLK的区别

    • 用于进行数据转换的ACLK,应尽量高质量

    • 最好不要经过FPGA,否则该时钟的波形质量会下降

    • 用同步数据的DCLK,只要满足数据的建立保持特性即可

  • 本实验配套电路板的局限性

    • 由于成本问题,本实验配套电路板没有采用时钟管理芯片

    • DAC、ADC的数据转换时钟经过了FPGA芯片内部

    • 对于高指标的设计不能这样做

本设计的时钟方案
  • 使用FPGA片内的锁相环

    由50MHz晶振的时钟信号,倍频得到80MHz的DAC时钟,分频得到20MHz的ADC时钟

  • 用FPGA的逻辑对内部的80MHz时钟反相作为DAC芯片时钟,用于满足DAC数据的建立-保持时序

  • ADC芯片在时钟的上跳锁存数据

    ADC时钟同样进行反相,作为ADC接口逻辑的驱动时钟

  • 注意:这种用FPGA的内部逻辑电路进行ADC、 DAC的时钟相位调整的方法,其时钟的抖动和相位噪声不好。高质量设计中,通常用专门的时钟管理芯片完成时钟的相位调节

转换器的垂直域(电压、数值)问题

  • AD9762是无符号的DAC器件

    • 有符号补码需要先把高位取反再送给DAC
    • 数据转换的对应关系如图:

在这里插入图片描述

  • AD9200是无符号的ADC

    • 最大电压对应MAX值,0电压对应0值
  • 注意ADC芯片还有一个溢出 out of range 信号

    • ADC输入的电压如果超限,则溢出信号置位1
    • 数据溢出对于ADC的采样结果是灾难性的,尤其是对于频域处理算法,数据溢出效果会在后面说明
    • 一旦检测到ADC溢出,必须先调整其不溢出之后, 再进行其他处理动作。

工程设计

在之前的基础之上,本设计增加了DAC和ADC的芯片来输出出入波形,所以需要增加对应需要的功能即可。向DAC送入数据和从ADC接收数据需要进行处理,所以需要增加两个接口程序。此外,本实验用的外扩子卡没有时钟管理芯片,所以需要使用pll进行时钟获得所需的时钟并送入子卡。

DAC接口

上文所述,数据送入DAC需要将补码转化为无符号数,接口需有数据转化的功能,即将最高位取反。输出信号幅度要可调,以此来观察数据溢出对ADC的影响,所以需要将数据大小根据要求等比例调整。这里选择开关作为输入,ROM数据除以输入作为输出的方式来调整输出信号的幅度。为了将开关的00映射为1,即不压缩幅度,选择了右移输入位数的方法。此外,本实验用到的DAC芯片为AD9762,输入为12位,而之前写的DDS输出为8位,所以还需要进行移位补零工作。

module DAC_interface( CLKIN , DATIN , SCALE , DAT2DAC );
input           CLKIN;
input  [8-1:0]  DATIN   ;
input  [2-1:0]  SCALE   ;
output [12-1:0] DAT2DAC ;

reg [12-1:0]  DAT2DAC ;
reg [12-1:0]  datin_R1;

always @ (posedge CLKIN) begin
  datin_R1 [11]    <= ~ DATIN[7]; // inverse the msb to unsigned
  datin_R1 [10: 4] <= DATIN[6:0];
  datin_R1 [3 : 0] <= 0;
  DAT2DAC          <= (datin_R1 >> SCALE);
end

endmodule

ADC接口

需要先从ADC接收ADC时钟信号,然后按ADC时钟信号来接收数据信号,此外还要注意ADC的溢出信号OTR。此外把STBY_ADC信号置1,则ADC一直处于工作状态。

module ADC_interface( CLK_ADC , DAT_ADC , OTR_ADC , OTR_OUT , STBY_ADC , DOUT );

input        CLK_ADC  ;  
input  [9:0] DAT_ADC  ;  
input        OTR_ADC  ;
output       OTR_OUT  ;
output       STBY_ADC ;
output [9:0] DOUT     ; 

reg [9:0] DOUT   ; 
reg       OTR_OUT;

always @ (posedge CLK_ADC) begin  
  DOUT    <= DAT_ADC   ; 
  OTR_OUT <= OTR_ADC;
end

assign STBY_ADC = 1'b0;

endmodule

锁相环

锁相环部分就是对FPGA内部ATLPLL锁相环模块进行配置,从而生成我们所需的20MHz和80MHz时钟信号即可。

ATLPPL的端口有点多,代码太长了,放一个配置后的锁相环的RTL视图:

在这里插入图片描述

顶层设计

按照需求连接各部分并分配管脚即可。连接到子卡的端口按照子卡每个端口的功能去找FPGA板子上对应管脚的编号。

在这里插入图片描述

左上角为开关和高低电平的输入,其中SW9和SW8控制DAC的输出幅度,其余开关用于控制DDS频率字。

左下角为PPL,输入50MHz晶振振生成80MHz的DAC时钟和20MHzADC时钟。

右上角为DDS,生成补码正弦波,转成无符号后送至DAC。

右下角为ADC的数据接收接口。

两个子卡的时钟需要反相,所以使用了两个非门来控制。

数据测量与分析

SignalTap检测数据

首先使用SMA同轴电缆连接DAC的输出和ADC的输入。其实这样直接相连是不严谨的,实际应用中应该接一个低通滤波或带通滤波。本实验只是为了对DAC和ADC有一个基础的认识。

拨动开关调整为SW9、SW0闭合,其他断开。此时输出幅度被压缩至一半,输出频率为 f = f d a c × C N T 2 n = f d a c × 1 2 10 = 78125 f=f_{dac}\times\frac{CNT}{2^n}=f_{dac}\times\frac1{2^{10}}=78125 f=fdac×2nCNT=fdac×2101=78125Hz。

SignalTap采样数据为:

在这里插入图片描述

SIgnalTap选择的采样频率为ADC的时钟,数周期得输出信号的周期为时钟信号的256倍,即 f = 1 256 f a d c = 78125 f=\frac 1{256}f_{adc}=78125 f=2561fadc=78125Hz,与理论推导相同。

观察到此时ADC采样数据已经接近ADC的上下限,不难猜想得如果将SW9断开,输出信号幅值变回原值,则ADC采样会产生溢出。断开SW9后采样得:

在这里插入图片描述

如图,出现了溢出产生的失真。其中顶部切割失真是由于信号幅值过高产生了数据溢出。可以看到顶部切割失真的部分对应周期的OTR_OUT信号输出高电平,即存在数据溢出。底部切割失真应该是超出了芯片的转换范围,数据手册太长了,我没找到。

当存在数据溢出时,ADC采到的信号均为高电平,那么就只知道数据超出ADC的转换范围了,基本数据丢失了属于是,获得的数据基本没有意义。所以当ADC出现数据溢出时必须先处理数据使其不溢出,才能够继续下一步的操作。

频谱分析

用matlab进行频谱分析画图得:

在这里插入图片描述

DAC输出直接连到ADC,对于DAC中的所有信号频率来说是不满足奈奎斯特采样理论的。但高频率分量其实都是杂波和噪音,并且幅值非常小,远小于所需的频率,混叠部分可以忽略不计。而我们所需的都是小于10MHz的,对于它们来说是满足奈奎斯特采样理论的。所以可以直接将DAC输入连到ADC上。

频率为0处有幅值,查阅ADC的数据手册可知是因为ADC含基准电压。此外幅值最大的频率分量便是我们所要生成的信号。

在这里插入图片描述

频谱的最高频率为采样频率的一半,这是奈奎斯特采样理论的内容。

观察DAC的频谱,噪音的包络类似一个个小的包连成。这是因为数字信号是间断的,相当于时域为正弦包络的一串冲激卷积门函数,频域即为乘上Sa函数。

参数修改

ROM数据位数修改

修改目标

程序本来设计的ROM存储数据为8位,而本工程中使用的DAC可以输入十二位,所以进行修改提高精度。将ROM数据提高到16位并输出12位数据到DAC。

操作步骤

首先需要将ROM的数据更新到16位。然后需要匹配余下的传输数据的部分。

DDS文件中rom_rdW的带宽改为十六位,将ROM的位数全部输出到rom_rdW。然后在输出语句中添加输出位宽,即输出rom_rdW[16-1:16-12]。

因为输入为12位,与DAC输入位宽匹配,所以不需要在DAC接口模块进行移位,直接最高位取反即可。不要忘记缩放DAC的输出缩放。修改后的代码为:

always @ (posedge CLKIN) begin
  datin_R1 [11]    <= ~ DATIN[11]; // inverse the msb to unsigned
  datin_R1 [10: 0] <= DATIN[10:0];
  DAT2DAC          <= (datin_R1 >> SCALE);
end

最后将两个文件重新生成bdf符号并在顶层文件中进行替换。

频率控制修改

修改目标

只需要用到0.5MHz,1MHz,1.5MHz,2MHz,2.5MHz,3.5MHz,4.5MHz,5.5MHz八个频率的正弦波,所以只用三个拨码开关控制,000至111分别映射为这八个输出频率。

操作步骤

首先要算八个频率对应的频率字,然后在DDS中加上一个频率字的选择即可。

计算公式即为之前得出的 f = f s y s × C N T 2 n f=f_{sys}\times\frac{CNT}{2^n} f=fsys×2nCNT,因为Verilog中没有小数,所以取位宽n为最大值32来使误差尽可能小。由公式计算出频率增量CNT,取整,转化为二进制,然后修改原代码中频率计算的部分,由输入为频率字赋对应的值。

修改后的代码为:

always @ (posedge CLK or posedge RST) begin
  if(RST) begin
    phase_acc_R <= 0;
    freqin_R    <= 0;
  end
  else begin
    if(FREQEN) begin
//      freqin_R <= FREQIN;
//bgein
		case(FREQIN[24:22])
			3'b000: freqin_R <= 32'b 0000_0001_1001_1001_1001_1001_1001_1010;
			3'b001: freqin_R <= 32'b 0000_0011_0011_0011_0011_0011_0011_0011;
			3'b010: freqin_R <= 32'b 0000_0100_1100_1100_1100_1100_1100_1101;
			3'b011: freqin_R <= 32'b 0000_0110_0110_0110_0110_0110_0110_0110;
			3'b100: freqin_R <= 32'b 0000_1000_0000_0000_0000_0000_0000_0000;
			3'b101: freqin_R <= 32'b 0000_1011_0011_0011_0011_0011_0011_0011;
			3'b110: freqin_R <= 32'b 0000_1110_0110_0110_0110_0110_0110_0110;
			3'b111: freqin_R <= 32'b 0001_0001_1001_1001_1001_1001_1001_1010;
		endcase
//end
    end // if(FREQEN) 
    if(DDSEN) begin
      phase_acc_R <= phase_acc_R + freqin_R;
    end // if(DDSEN) 
    if(ddsen_R2) begin
      DDSOUT <= rom_rdW[16-1:16-12];
    end
  end
end
assign rom_raW = phase_acc_R[32-1: 32-1-7+1];
结果验证
SignalTap数据采集验证

这里采集的是DAC的输出数据,时钟频率为80MHz,以此来计算实际获得的信号的频率。

将SignalTap采集到的数据放大,可以数得/算得一个信号周期对应的时钟周期,以此比例关系估算实际信号的频率。

在这里插入图片描述

测量计算结果为:

在这里插入图片描述

频谱分析验证

SignTap数周期只是估算,精确计算需要像上文一样导出数据进行频谱分析。有8组数据需要分析,可以录制宏来减少体力劳动。

MATLAB频谱分析画图结果如图:

在这里插入图片描述

采样计算结果并不十分准确,因为最小分辨率的存在,会有误差,可以用示波器测一测。频谱分析中使用的采样频率为20MHz,采样点数为8192个, F 0 = 1 T 0 = 1 1 f s × 2 13 ≈ 2440 F_0=\frac1{T_0}=\frac1{\frac1{f_s}\times2^{13}}\approx2440 F0=T01=fs1×21312440,所以最小分辨率为2440Hz。

示波器测试也有误差,误差是看示波器价格的。因为示波器触发电平的存在,可以多几个周期来测。大概屏幕上显示5到10个周期左右测出来的频率就会比较稳定,否则会有较大的波动。

在这里插入图片描述

时钟修改

在本例中,ADC的20MHz时钟和DAC的80MHz时钟是从一个晶振用PLL分出来的,这种时钟叫做同步时钟。这样设计的电路含有两个时钟,为多周期电路。在DAC及之前的部分为80MHz,在ADC及之后的部分为20MHz。ADC芯片的时钟要求为20MHz。为了提高计算密度和需求,想要在ADC之后的电路也使用80MHz的时钟,即用80MHz的时钟处理ADC送入的20MHz的数据流。

按照设想的修改,则电路可认为只有一个80MHz的时钟。其中在ADC的部分,用80MHz的时钟和时间基准电路分出一个20MHz的送入ADC使用。

修改后的时钟为:
在这里插入图片描述

修改后ADC所使用的20MHz并不算是系统的时钟,对于系统来说只是一个普通的信号。系统以20MHz的频率从ADC采样读取数据,然后继续以80MHz的时钟处理数据。

修改后的电路使用时钟示意:

在这里插入图片描述

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值