一天一个设计实例-基于FPGA的模数、数模转换器应用设计

基于FPGA的模数、数模转换器应用设计

本节设计采用黑金ADDA模块,模块硬件结构如下:

图7‑32 硬件结构

数模转换( DA) 电路

如硬件结构图所示, DA 电路由高速 DA 芯片、 7 阶巴特沃斯低通滤波器、幅度调节电路和信号输出接口组成。

使用的高速 DA芯片是 AD公司推出的 AD9708。AD9708 是 8位,125MSPS的 DA 转换芯片,内置 1.2V 参考电压,差分电流输出。芯片内部结构图如下图所示

图7‑33 芯片内部结构图

AD9708 芯片差分输出以后, 为了防止噪声干扰,电路中接入了 7 阶巴特沃斯低通滤波器, 带宽为 40MHz, 频率响应如下图所示

图7‑34 频率响应

滤波器参数如下图所示

图7‑35 滤波器参数

滤波器之后,我们使用了 2 片高性能 145MHz 带宽的运放 AD8056,实现差分变单端,以及幅度调节等功能,使整个电路性能得到了最大限度的提升。幅度调节,使用的是 5K 的电位器,最终的输出范围是-5V~5V( 10Vpp)。

注:由于电路器的精度不是很精确,最终的输出有一定误差, 有可能波形幅度不能达到 10Vpp,也有可能出现波形削顶等问题,这些都属正常情况。

波形展示:

注:由于幅频特性的影响,随着频率的增加, 波形的幅度会不断减小。

图7‑36 波形展示

模数转换( AD)电路

如硬件结构图中所示, AD 电路由高速 AD 芯片、衰减电路和信号输入接口组成。

AD9280是一款单芯片、8位、32 MSPS模数转换器(ADC),采用单电源供电,内置一个片内采样保持放大器和基准电压源。它采用多级差分流水线架构,数据速率达32 MSPS,在整个工作温度范围内保证无失码。

AD9280的输入经过设计,使成像和通信系统的开发更加轻松。用户可以选择各种输入范围和偏移,并可通过单端或差分方式驱动输入。

AD9280具有一个片上可编程基准电压源。也可以选用外部基准电压,以满足应用的直流精度与温度漂移要求。AD9280采用+2.7 V至+5.5 V电源供电,非常适合高速应用中的低功耗操作。AD9280的额定温度范围为-40°C至+85°C工业温度范围。

AD9280 特性

与AD876-8引脚兼容;

功耗:95 mW(3 V电源);

工作电压范围:+2.7V至+5.5V;

微分非线性(DNL)误差:0.2 LSB;

省电(休眠)模式;

三态输出;

超量程指示;;

内置钳位功能(直流复位);

可调片内基准电压;

IF欠采样至135 MHz;

内部结构图如下图所示:

图7‑37 AD9280内部结构图

根据下图的配置,我们将 AD 电压输入范围设置为:0V~2V

图7‑38 AD 电压输入范围设置为:0V~2V

在信号进入 AD 芯片之前,我们用一片 AD8056 芯片构建了衰减电路, 接口的输入范围是-5V~+5V(10Vpp)。衰减以后,输入范围满足 AD 芯片的输入范围( 0~2V)。转换公式如下:

65(.)

当输入信号 Vin=5(V)的时候,输入到 AD 的信号 Vad=2(V);

当输入信号 Vin=-5(V)的时候,输入到 AD 的信号 Vad=0(V);

DA 实验操作步骤

因为代码比较简单,所以就不贴代码了,实验步骤如下:

1. 利用 Quartus II 软件,将程序下载到 FPGA 中。

2. 调整示波器,使其正确显示完整波形。

3. 您可以通过电位器( U6)来手动调节波形的幅值。

AD 实验操作步骤

1.利用 Quartus II 软件,将程序下载到 FPGA 中。

2.利用 SignalTap II 对数据进行实时采集。

AGC的FPGA实现

基于前面介绍的硬件实现AGC,硬件结构及框图非常简单,这里就不再赘述,代码如下:

代码7‑9 7.5.5 AGC的FPGA实现代码

1.module Autogreat(clkin_50MHz,ADCclk_25MHz,DACclk_25MHz,ADCin,DACout);

2.//50MHz 分频 25MHz, ADCin 读入 8 位 ADC 数据, DACout 发送 8 位转换数据,进行 DAC 转换

3.input clkin_50MHz;

4.input [7:0]ADCin;

5.output reg ADCclk_25MHz;

6.output reg DACclk_25MHz;

7.output reg[7:0]DACout;

8.reg[3:0]counter;

9.reg[8:0]cnt500;//2^9=512,采集 500 次,进行冒泡

10.//reg [7:0]max,tmp;//冒泡使用

11.reg [7:0]tmp;

12.reg [7:0]great;//定义增益使用

13.reg [7:0]great1;//接受 great 的高八位

14.reg [15:0]tmp16;

15.reg [7:0]realgreat;//真正增益,相当于 great 右移 8 位

16.//---@分频开始@---//

17.always@(posedge clkin_50MHz)

18.    begin

19.        if(counter==1)

20.        begin

21.            ADCclk_25MHz<=~ADCclk_25MHz;

22.            DACclk_25MHz<=~DACclk_25MHz;

23.            counter<=0;

24.        end

25.        else if(counter==0)

26.        begin

27.            counter<=counter+1;

28.        end

29.    end

30.//---@分频结束@---//

31.//---@获取自动增益,并调整输出电压开始@---//

32.always@(posedge DACclk_25MHz)

33.    begin

34.        tmp16<=(adcin-128)*great1;< span="">//ADCin-128,取中线上面部分,

35.//128 即 1000_0000 为正电压中心线,乘以增益,单边放大

36.        realgreat<=tmp16[15:8];< span="">//取得 tmp 高 8 位,即浮点数整数部分

37.        DACout<=128+realgreat;< span="">//真正 DAC 输出部分

38.//---@实验成功语句@---//

39.//---@DACout<=(ADCin-128)*1+128;@---//

40.//---@实验成功语句@---//

41.    end

42.//---@对 ADCin 进行处理@---//

43.always@(posedge ADCclk_25MHz)

44.    begin

45.//---@冒泡取大开始@---//

46.        if(cnt500>=500)

47.        begin

48.            cnt500<=0;

49.//max<=tmp;//取得 500 次采样最大值

50.//great<=(64*256)/(max-128);//64 为设定电压值,相当于放大倍数,

51.//64 乘以 256 相当于左移 8 位,需要 16 位储存, max-8'b10000000

52.            great<=(36*256)/(tmp-128);//此时 great 为 16 位,需要其高八位,

53.//64 为 0100_0000,当设置输出为正负 2.5V 时用 64,比较时运用差值

54.            great1<=great[7:0];

55.        end

56.        else if(cnt500<500)< span="">//在两个信号周期内采样

57.    begin

58.        if(tmp<=adcin)< span="">//当前 tmp 小于等于 ADCin

59.        begin

60.            tmp<=adcin;< span="">//冒泡取得比当前大的值

61.        end

62.        else

63.        begin

64.            tmp<=tmp;< span="">//保持当前值

65.        end

66.            cnt500<=cnt500+1;< span="">//cnt500 自增

67.        end

68.//---@冒泡取大结束@---//

69.    end

70.//---@获取自动增益,并调整输出电压结束@---//

71.endmodule

FPGA 与外部端口在上一节已经说明。整个 HDL 分为分频部分、读取 ADC转换值部分、增益处理和 DAC 输出波形部分。

1.分频部分

第一个部分请见

1.always@(posedge clkin_50MHz)

2.begin

3.…..

4.end

部分,为二分频,分别产生 20MHz 和 AD 和 DA 时钟。

1.读取 ADC 转换值部分

第二个部分请见

1.always@(posedge clkin_50MHz)

2.begin

3.…..

4.end

部分。其中输入信号为 100KHz, ADC 采样时钟为 25MHZ,所以一个信号周期可以采样 250 次,设置采集 500 次,利用冒泡法取得最大值,信号最大值的 AD 转换值储存在 tmp 当中;记录 500 次后,利用 tmp 取得正半周期的幅度,即“tmp-128”,因为根据上一节介绍,其 AD 电路将正弦信号负半周衰减后抬升到正电压, “tmp-128”即为 tmp-8’b100_0000,即得到正半周期的幅度。

此时,再利用“great<=(36*256)/(tmp-128);”,得到与预设电压的增益或者衰减系数,注意 great 为 8 位, 而(36*256)是将 36 左移 8 位, 这里运用了 8 位拓展为 16 位,来就利用 FPGA 完成浮点数运算。

紧接着这句话,是“great1<=great[7:0];”,这句话其实并没有什么现实意义,但是最初写的时候, great 是 16 位的,后来写我就没有改。注意 great1 也是 8 位的。

2.增益处理和 DAC 输出波形部分

第二个部分请见

1.always@(posedge DACclk_25MHz)

2.begin

3.…..

4.end

部分。首先是“tmp16<=(ADCin-128)*great1;”, 这句话中 tmp16 是 16位数据, “ADCin-128” 为 ADCin 的值减去轴的值(见 2.2.2) , 然后乘以增益(great1 大于等于 1 为增益,小于 1 则为衰减,这里都叫为增益) , 8 位乘以 8位得到 16 位,恰巧这里又用了拓展位数进行浮点数运算。

最后“realgreat<=tmp16[15:8];”和“DACout<=128+realgreat;”则为将 tmp1的高八位给 realgreat,即将整数部分给 realgreat,而后一句则为 DACout 是当前计算得到的值再加上轴的值(128,即 8’b1000000)。最后 DAC 输出,得到波形。

实验结果如下:

最后的实验效果可以见下图中。可以看到,随着输入信号幅值变化,输出信号可以稳定在一个设定值(设定为 36,即输出用十进制表示为:92~154) 附近,但是波形稳定不是很好,另外当输入信号电压峰峰值超过AD 模块限定的 10V 时,出现削顶。

图7‑39 实验结果图

(0)

相关推荐