官方论坛
官方淘宝
官方博客
微信公众号
点击联系吴工 点击联系周老师

2.16 AD采集

发布时间:2021-08-22   作者:admin 浏览量:

本文的文档编号:000400000027

需要看对应的视频,请点击视频编号:002700000454

1、本文档讲述FPGA产生正弦波数据,由DA输出,然后再外部环回到AD接口进行采集,可通过在线调试工具进行观察

2、801开发板使用

项目背景

1.1 AD转换

转换 转换就是模数转换。顾名思义,就是把模拟信号转换成数字信号。主要包括积分型、逐次逼近型、并行比较型串并行型、ΣΔ调制型、电容阵列逐次比较型及压频变换型。

A/D转换器是用来通过一定的电路将模拟量转变为数字量。模拟量可以是电压、电流等电信号,也可以是压力、温度、湿度、位移、声音等非电信号。但在A/D转换前,输入到A/D转换器的输入信号必须经各种传感器把各种物理量转换成电压信号。

AD转换的技术指标,一般有如下几个:

1. 分辨率(Resolution) 指数字量变化一个最小量时模拟信号的变化量,定义为满刻度与2^n的比值。分辨率又称精度,通常以数字信号的位数来表示。

2. 转换速率(Conversion Rate)是指完成一次从模拟转换到数字的AD转换所需的时间的倒数。积分型AD的转换时间是毫秒级属低速AD,逐次比较型AD是微秒级属中速AD,全并行/串并行型AD可达到纳秒级。采样时间则是另外一个概念,是指两次转换的间隔。为了保证转换的正确完成,采样速率 (Sample Rate)必须小于或等于转换速率。因此有人习惯上将转换速率在数值上等同于采样速率也是可以接受的。常用单位是kspsMsps,表 示每秒采样千/百万次(kilo / Million Samples per Second)。

3. 量化误差 (Quantizing Error) 由于AD的有限分辨率而引起的误差,即有限分辨率AD的阶梯状转移特性曲线与无限分辨率AD(理想AD)的转移特 性曲线(直线)之间的最大偏差。通常是1个或半个最小数字量的模拟变化量,表示为1LSB1/2LSB

4. 偏移误差(Offset Error) 输入信号为零时输出信号不为零的值,可外接电位器调至最小。

5. 满刻度误差(Full Scale Error) 满度输出时对应的输入信号与理想输入信号值之差。

6. 线性度(Linearity) 实际转换器的转移函数与理想直线的最大偏移,不包括以上三种误差。

其他指标还有:绝对精度(Absolute Accuracy) ,相对精度(Relative Accuracy),微分非线性,单调性和无错码,总谐波失真(Total Harmonic Distotortion缩写THD)和积分非线性。


1.2 教学板AD原理图

明德扬教学板上板载板载32Mhz 转换速率、8bit高速AD芯片AD9280,满足各种信号的采集,满足用户实现各种常见滤波算法的实现。实际位置如下所示:

599

600

上面是AD9280的原理图。与FPGA相连的信号有:AD_D0~7AD_OTRAD_CLK

AD9280管脚

原理图信号

FPGA管脚

作用

CLK

AD_CLK

AD9280的工作时钟,最大是32MHz

OTR

AD_OTR

超过电压范围指示信号

D7

AD_D7

AD转换后的数字值。

D6

AD_D6

D5

AD_D5

D4

AD_D4

D3

AD_D3

D2

AD_D2

D1

AD_D1

D0

AD_D0

1.3 AD9280的控制时序

AD9280的控制时序如下图。

601

602

603

由时钟图可以看出,每个时钟就可以做AD转换一次,但会延迟3个时钟才输出。例如时序图中第一个时钟采集到S1,并对S1进行模数转换,经过3个时钟后,输出DATA1,这个DATA1就是S1所应对的数字值。

由参数时序可以看出,时钟最大是32MHz

由上面时序可以看出,控制AD9280非常简单,只要给出不超过32MHz的时钟,然后对其采集就行了。


2 设计目标

本次案例将使用到AD9709AD9280。其连接示意如下图所示

604

其中跳帽就设置成XXX,设置后,AD9709的通道A输出,就会环回给AD9280

本案例是FPGA先产生正弦信号,这个正弦信号输出给DA通道A,经过环回后,给回AD9280的输入端,FPGA再采集AD9280的数据,最后使用signaltap采集数字信号。

605

正弦信号的产生方式,与FIR滤波器的设计”案例一致。正弦信号的频率受开发板上的3个拨码开关控制,用3位信号key表示,一共可以产生8种频率。

正弦信号的频率 约等于: 100KHz * (key+1)

例如,当key等于0时,产生约100KHz的正弦信号;

key等于1时,产生约200KHz的正弦波;

key等于7时,产生约800KHz的正弦波。

FPGA产生25MHz的时钟给AD9280,也就是采样率为25M。用这个时钟作为SIGNALTAP的采样时钟,观察AD9280过来的数据波形。

上板效果图如下图所示。(用signaltap抓取波形)

606


3 设计实现

3.1 顶层信号

新建目录:D:mdy_bookd_prj在该目录中,新建一个名为ad_prj.v的文件,并用GVIM打开,开始编写代码。

我们要实现的功能,概括起来就是FPGA产生控制AD9709,让其中的通道A产生正弦波所对应的电压,同时采集AD9280的数据并观察。为了控制AD9709的通道A,就需要控制AD9709MODESLEEPCLK1WRT1DB7~0P1管脚。为了采集AD9280,那么就需要控制AD9280CLKD0~D7管脚。根据设计目标的要求,整个工程需要以下信号:

1. 使用clk连接到晶振,表示50M时钟的输入。

2. 使用rst_n连接到按键,表示复位信号。

3. 使用3位信号key,表示三位拨码开关。

4. 使用dac_mode信号连接到AD9709MODE管脚,用来控制其工作模式。

5. 使用dac_sleep信号连接到AD9709SLEEP管脚,用来控制其睡眠模式。

6. 使用dac_clka信号连接到AD9709CLK1管脚,用来控制通道A的时钟。

7. 使用dac_wra信号连接到AD9709WRT1管脚,用来控制通道A的写使能。

8. 使用8位信号dac_da连接到AD9709DB7~0P1管脚,用来控制通道A的写数据。

9. 使用ad_clk信号连接到AD9280CLK管脚,用来作来采样时钟。

10. 使用8ad_in信号连接到AD9280D7~0管脚,用来采集数据。

综上所述,我们这个工程需要10个信号,时钟clk,复位rst_ndac_modedac_sleepdac_clkadac_wradac_daad_clkad_in,其中dac_da ad_in8位信号,key3位信号,其他都是1位信号。

器件

AD9709管脚

AD9280管脚

原理图信号

FPGA管脚

FPGA工程信号

U8

MODE

DAC_MODE

Y4

dac_mode

SLEEP

DAC_SLEEP

H2

dac_sleep

CLK1

DA_CLKA

R2

dac_clka

WRT1

DA_WRA

U1

dac_wra

DB7P1

DAC_DA7

AA1

dac_da[7]

DB6P1

DAC_DA6

Y2

dac_da[6]

DB5P1

DAC_DA5

Y1

dac_da[5]

DB4P1

DAC_DA4

W2

dac_da[4]

DB3P1

DAC_DA3

W1

dac_da[3]

DB2P1

DAC_DA2

V2

dac_da[2]

DB1P1

DAC_DA1

V1

dac_da[1]

DB0P1

DAC_DA0

U2

dac_da[0]

U1

CLK

AD_CLK

L6

ad_clk

D7

AD_D7

N5

ad_in[7]

D6

AD_D6

M4

ad_in[6]

D5

AD_D5

M5

ad_in[5]

D4

AD_D4

R6

ad_in[4]

D3

AD_D3

T5

ad_in[3]

D2

AD_D2

U7

ad_in[2]

D1

AD_D1

V5

ad_in[1]

D0

AD_D0

V6

ad_in[0]

X1

SYS_CLK

G1

clk

K1

SYS_RST

AB12

rst_n

sw0

SW_D0

AA3

key[2]

sw1

SW_D1

AB3

key[1]

sw2

SW_D2

AB5

key[0]

module的名称定义为ad_prj,代码如下:

1

2

3

4

5

6

7

8

9

module ad_prj(

clk       ,

rst_n     ,

key       ,

dac_mode ,

dac_clka  ,

dac_da   ,

dac_wra  ,

dac_sleep,

ad_clk    ,

ad_in

);

其中clkrst_n1位的输入信号,dac_da8位的输出信号,dac_modedac_clkadac_wradac_sleep1位输出信号,ad_clk1位输出信号,ad_in8位输入信号,key3位输入信号。

1

2

3

4

5

6

7

input             clk        ;

input             rst_n      ;

input [ 3-1:0]     key        ;

output            dac_mode ;

output            dac_clka  ;

output [ 8-1:0]    dac_da    ;

output            dac_wra   ;

output            dac_sleep ;

output            ad_clk    ;

input  [8-1:0]      ad_in     ;


3.2 信号设计

由于正弦信号的产生要求,与FIR滤波器设计”相同,所以不再详细描述原因。现在把相关代码整理如下。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

always  @(*)begin

case(addr)

0: sin_data = 8'h7F;

1: sin_data = 8'h85;

2: sin_data = 8'h8C;

3: sin_data = 8'h92;

4: sin_data = 8'h98;

5: sin_data = 8'h9E;

6: sin_data = 8'hA4;

7: sin_data = 8'hAA;

8: sin_data = 8'hB0;

9: sin_data = 8'hB6;

10: sin_data = 8'hBC;

11: sin_data = 8'hC1;

12: sin_data = 8'hC6;

13: sin_data = 8'hCB;

14: sin_data = 8'hD0;

15: sin_data = 8'hD5;

16: sin_data = 8'hDA;

17: sin_data = 8'hDE;

18: sin_data = 8'hE2;

19: sin_data = 8'hE6;

20: sin_data = 8'hEA;

21: sin_data = 8'hED;

22: sin_data = 8'hF0;

23: sin_data = 8'hF3;

24: sin_data = 8'hF5;

25: sin_data = 8'hF7;

26: sin_data = 8'hF9;

27: sin_data = 8'hFB;

28: sin_data = 8'hFC;

29: sin_data = 8'hFD;

30: sin_data = 8'hFE;

31: sin_data = 8'hFE;

32: sin_data = 8'hFE;

33: sin_data = 8'hFE;

34: sin_data = 8'hFE;

35: sin_data = 8'hFD;

36: sin_data = 8'hFC;

37: sin_data = 8'hFA;

38: sin_data = 8'hF8;

39: sin_data = 8'hF6;

40: sin_data = 8'hF4;

41: sin_data = 8'hF1;

42: sin_data = 8'hEF;

43: sin_data = 8'hEB;

44: sin_data = 8'hE8;

45: sin_data = 8'hE4;

46: sin_data = 8'hE0;

47: sin_data = 8'hDC;

48: sin_data = 8'hD8;

49: sin_data = 8'hD3;

50: sin_data = 8'hCE;

51: sin_data = 8'hC9;

52: sin_data = 8'hC4;

53: sin_data = 8'hBE;

54: sin_data = 8'hB9;

55: sin_data = 8'hB3;

56: sin_data = 8'hAD;

57: sin_data = 8'hA7;

58: sin_data = 8'hA1;

59: sin_data = 8'h9B;

60: sin_data = 8'h95;

61: sin_data = 8'h8F;

62: sin_data = 8'h89;

63: sin_data = 8'h82;

64: sin_data = 8'h7D;

65: sin_data = 8'h77;

66: sin_data = 8'h70;

67: sin_data = 8'h6A;

68: sin_data = 8'h64;

69: sin_data = 8'h5E;

70: sin_data = 8'h58;

71: sin_data = 8'h52;

72: sin_data = 8'h4C;

73: sin_data = 8'h46;

74: sin_data = 8'h41;

75: sin_data = 8'h3C;

76: sin_data = 8'h36;

77: sin_data = 8'h31;

78: sin_data = 8'h2C;

79: sin_data = 8'h28;

80: sin_data = 8'h23;

81: sin_data = 8'h1F;

82: sin_data = 8'h1B;

83: sin_data = 8'h17;

84: sin_data = 8'h14;

85: sin_data = 8'h11;

86: sin_data = 8'hE ;

87: sin_data = 8'hB ;

88: sin_data = 8'h9 ;

89: sin_data = 8'h7 ;

90: sin_data = 8'h5 ;

91: sin_data = 8'h3 ;

92: sin_data = 8'h2 ;

93: sin_data = 8'h1 ;

94: sin_data = 8'h1 ;

95: sin_data = 8'h1 ;

96: sin_data = 8'h1 ;

97: sin_data = 8'h1 ;

98: sin_data = 8'h2 ;

99: sin_data = 8'h3 ;

100: sin_data = 8'h4 ;

101: sin_data = 8'h6 ;

102: sin_data = 8'h7 ;

103: sin_data = 8'hA ;

104: sin_data = 8'hC ;

105: sin_data = 8'hF ;

106: sin_data = 8'h12;

107: sin_data = 8'h15;

108: sin_data = 8'h19;

109: sin_data = 8'h1D;

110: sin_data = 8'h21;

111: sin_data = 8'h25;

112: sin_data = 8'h2A;

113: sin_data = 8'h2E;

114: sin_data = 8'h33;

115: sin_data = 8'h38;

116: sin_data = 8'h3E;

117: sin_data = 8'h43;

118: sin_data = 8'h49;

119: sin_data = 8'h4E;

120: sin_data = 8'h54;

121: sin_data = 8'h5A;

122: sin_data = 8'h60;

123: sin_data = 8'h67;

124: sin_data = 8'h6D;

125: sin_data = 8'h73;

126: sin_data = 8'h79;

127: sin_data = 8'h7F;

endcase

end

always  @(posedge clk or negedge rst_n)begin

if(rst_n==1'b0)begin

addr_tmp <= 0;

end

else if(key==0) begin

addr_tmp <= addr_tmp + 262;

end

else if(key==1) begin

addr_tmp <= addr_tmp + 524;

end

else if(key==2) begin

addr_tmp <= addr_tmp + 786;

end

else if(key==3) begin

addr_tmp <= addr_tmp + 1029;

end

else if(key==4) begin

addr_tmp <= addr_tmp + 1311;

end

else if(key==5) begin

addr_tmp <= addr_tmp + 1573;

end

else if(key==6) begin

addr_tmp <= addr_tmp + 1835;

end

else begin

addr_tmp <= addr_tmp + 2097;

end

end

assign addr = addr_tmp >>10 ;

always  @(posedge clk or negedge rst_n)begin

if(rst_n==1'b0)begin

dac_da <= 0;

end

else begin

dac_da <= 255 - sin_data;

end

end

assign dac_sleep = 0        ;

assign dac_wra   = dac_clka ;

assign dac_clka  = ~clk      ;

还有最后一个信号要设计:ad_clk。由设计目标可知,要求是25MHz的时钟。为了产生时钟,我们就要用到PLL

3.3 生成PLL IP

1.打开IP核管理工具

打开quartus软件,然后选择Tools ->IPcatalog,在右侧弹出如下界面

607

在搜索框中,填下ALTPLL,就会出现如下界面。

608

ALTPLL就是我们需要使用的PLL IP核。双击ALTPLL,在弹出的对话框中起个文件名,如vga_pll,记得选择verilog。然后点OK就可以开始设置参数了。

609

2.设置IP参数

610

上图中,主要是设置输入的时钟频率,明德扬开发板输入时钟是固定的50MHz,因此可填写50,注意旁边的单位是选择MHz。其他默认,按next

611

上图的option inputs中,全部取消勾选,不需要产生复位信号。上图中的lock output,全部取消勾选,不需要产生locked指示信号。然后选Next

612

不用做任何更改,直接Next

613

不用做任何更改,直接Next。

614

增加输入时钟,由于我们只有一个输入时钟,所以只用inclk0即可,无需增加。直接Next

615

不用做任何更改,直接Next

616

设置c0的输出频率。我们选择Enter output clock frequest中,直接填入25,单位选择MHz,就是表示要产生25MHz的时钟。然后点击Finish,弹出如下窗口。

617

取消my_pll_bb.v的勾选,然后选择FinishQUARTUS就会产生PLL IP的代码了。

稍等片刻,到工程目录 D:mdy_bookd_prj,可以看到生成一个my_pll.v文件,用GVIM打开后,可以看到PLL模块的模块输入输出接口。其中inclk050MHz输入时钟,c025MHz的输出时钟。顶层模块直接例化就可以使用了。

618

1

2

3

4

my_pll u_my_pll(

.inclk0(clk   ) ,

.c0    (ad_clk )

);

至此,主体程序已经完成。接下来是将module补充完整。

3.4 信号定义

接下来定义信号类型。

FIR滤波器案例”中已经说明了部分信号的说明,现补充如下。

1

2

3

4

wire    [6:0]    addr    ;

reg   [7:0]      sin_data    ;

reg   [7:0]      dac_da    ;

wire             dac_sleep  ;

wire             dac_wra   ;

wire             dac_clka   ;

wire             dac_mode ;

reg   [16:0]    addr_tmp    ;

ad_clk是由例化模块输出信号,非always产生,可以定义为wire型,只有1位。

1

wire                        ad_clk  ;

4 综合与上板

4.1 添加文件到工程

619

1.前面已经介绍了新建工程。现在打开quartus,在Project菜单中选择Add/Remove File to Project,弹出文件窗口。

620

点击右上角的,在弹出来的窗口中,双击选择D:mdy_bookd_prj目录下的ad_prj.v文件。然后记得要点Add,才算正式加到工程。

621

OK关闭本窗口。


4.2 综合

1.点击右上角蓝色三角键进行编译

622

之后等待编译成功


4.3 配置管脚

623

在菜单栏中,选中Assignments,然后选择Pin Planner,就会弹出配置管脚的窗口。

624

在配置窗口中的location一列,可以填写每个管脚所对应的FPGA管脚号。

器件

AD9709管脚

AD9280管脚

原理图信号

FPGA管脚

FPGA工程信号

U8

MODE

DAC_MODE

Y4

dac_mode

SLEEP

DAC_SLEEP

H2

dac_sleep

CLK1

DA_CLKA

R2

dac_clka

WRT1

DA_WRA

U1

dac_wra

DB7P1

DAC_DA7

AA1

dac_da[7]

DB6P1

DAC_DA6

Y2

dac_da[6]

DB5P1

DAC_DA5

Y1

dac_da[5]

DB4P1

DAC_DA4

W2

dac_da[4]

DB3P1

DAC_DA3

W1

dac_da[3]

DB2P1

DAC_DA2

V2

dac_da[2]

DB1P1

DAC_DA1

V1

dac_da[1]

DB0P1

DAC_DA0

U2

dac_da[0]

U1

CLK

AD_CLK

L6

ad_clk

D7

AD_D7

N5

ad_in[7]

D6

AD_D6

M4

ad_in[6]

D5

AD_D5

M5

ad_in[5]

D4

AD_D4

R6

ad_in[4]

D3

AD_D3

T5

ad_in[3]

D2

AD_D2

U7

ad_in[2]

D1

AD_D1

V5

ad_in[1]

D0

AD_D0

V6

ad_in[0]

X1

SYS_CLK

G1

clk

K1

SYS_RST

AB12

rst_n

sw0

SW_D0

AA3

key[2]

sw1

SW_D1

AB3

key[1]

sw2

SW_D2

AB5

key[0]

按上面配置好每个信号的管脚,其最终效果如下图。

625

关闭Pin Planner,软件自动会保存管脚配置信息。


4.4 再次综合

626

在菜单栏中,选中Processing,然后选择Start Compilation,再次对整个工程进行编译和综合。

627

出现上面的界面,就说明编译综合成功。


4.5 连接开发板

628

连接示意如上图所示。将电源接上开发板;USB BLASTER一端连接到JTAG插口,另一端连到PCUSB接口;将开发板上的P7接口和P11与示波器的两个通道相连。最后再将电源打开。


4.6 设置SIGNALTAP


4.7 用SIGNALTAP观察




   拓展阅读