这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » FPGA » 基于FPGA的AD/DA采集(附件源码代码)

共1条 1/1 1 跳转至

基于FPGA的AD/DA采集(附件源码代码)

菜鸟
2018-11-13 17:50:31     打赏

原码代码 源码.rar

项目背景

1.1 AD转换

    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的时钟,然后对其采集就行了。


设计实现

3.1 顶层信号

    新建目录:D:\mdy_book\ad_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_book\ad_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  ;





关键词: FPGA     FPGA设计     FPGA开发板     FPGA视    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]