明德扬肖老师 发表于 2020-7-3 17:47:16

【FPGA至简设计原理与应用】书籍连载24 第三篇FPGA至简设计项目 第十五章 AD采集


温馨提示:明德扬2023推出了全新课程——逻辑设计基本功修炼课,降低学习FPGA门槛的同时,增加了学习的趣味性,并组织了考试赢积分活动(点击→了解课程详情)http://www.mdy-edu.com/ffkc/415.html,感兴趣请联系易老师:13112063618(微信同步)

本案例的编号为:002400000079,如果有疑问,请按编号在下面贴子查找答案:MDY案例交流【汇总贴】_FPGA-明德扬科教 (mdy-edu.com)
本文为明德扬原创及录用文章,转载请注明出处
大家好,近期我们会连载《FPGA至简设计原理与应用》一书,有兴趣的同学可以学习,也希望大家可以对我们的书提出宝贵的意见和建议。

《FPGA至简设计原理与应用》书籍连载索引目录
http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=989


读过的朋友可积极在贴后留言,书籍正式出版时,我们会从留言者中挑选20位幸运读者,幸运读者可获潘老师亲笔签名书籍一本。

注:手机浏览可能格式会乱,建议用电脑端进行浏览。


第十五章 AD采集

本文档编号:000400000027
需要看对应的视频,请点击视频编号:002700000454
1、本文档讲述FPGA产生正弦波数据,由DA输出,然后再外部环回到AD接口进行采集,可通过在线调试工具进行观察
2、801开发板使用

第1节 项目背景

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)必须小于或等于转换速率。有的设计师习惯将转换速率在数值上等同于采样速率,这一做法也是可以接受的。转换速率常用单位是ksps和Msps,表示每秒采样千/百万次(kilo / Million Samples per Second)。
3. 量化误差 (Quantizing Error) :指由于AD的有限分辨率而引起的误差,即有限分辨率AD的阶梯状转移特性曲线与无限分辨率AD(理想AD)的转移特性曲线(直线)之间的最大偏差。其通常是1个或半个最小数字量的模拟变化量,表示为1LSB、1/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,满足各种信号的采集,用户可以利用其实现各种常见滤波算法的实现。开发板中AD芯片的实际位置如下所示。图3.15-1教学板中的AD接口图3.15-2AD9280的原理图
上图是AD9280的原理图,与FPGA相连的信号有:AD_D0~7、AD_OTR、AD_CLK。
表3.15-1AD9280与FPGA的相连信号
AD9280管脚原理图信号FPGA管脚作用
CLKAD_CLK AD9280的工作时钟,最大是32MHz。
OTRAD_OTR 超过电压范围指示信号
D7AD_D7 AD转换后的数字值。
D6AD_D6
D5AD_D5
D4AD_D4
D3AD_D3
D2AD_D2
D1AD_D1
D0AD_D0

1.3 AD9280的控制时序
AD9280的控制时序如下图所示。图3.15-3AD9280控制时序图3.15-4AD9280的时序参数图3.15-5AD9280的最大时钟
由图3.15- 3可以看出,每个时钟AD完成一次转换,但会延迟3个时钟才输出。例如图中第一个时钟采集到S1,并对S1进行模数转换,经过3个时钟后输出DATA1,这个DATA1即为S1所应对的数字值。
由参数时序可以看出,时钟最大值是32MHz。以上就是AD9280的工作原理,可以发现AD9280的控制非常简单,设置不超过32MHz的时钟后对其采集就行了。
第2节 设计目标

延续至简设计法的设计特色,开始一个新的设计之前依旧要首先明确设计目标。设计目标是整个设计的核心灵魂,后续的每个步骤与操作都是围绕设计目标进行展开的。至简设计法旨在让设计师在设计过程中按照最中的简单快捷的方式实现每个步骤和思路,明确设计目标正是为了让后面的每个阶段的工作都有意义,而不去进行不必要的工程展开,这样一来可以少走很多弯路。对于初学者来说,学习阶段好习惯的养成可以为之后的工程师生涯打下坚实的基础。所以再次强调,在最开始设计前一定要将设计目标分析透彻,认真思考本次设计最终想要实现什么目的,达到什么效果,然后再投入到设计中去。
本设计将开发板上的AD接口与DA接口相连接,FPGA产生正弦信号后将该正弦信号输出给DA通道A,经过环回后,给回AD9280的输入端。FPGA采集AD9280的数据后使用signaltap采集数字信号,其实现结构如下图所示。
图3.15-6AD采集的实现结构
正弦信号的产生方式与“FIR滤波器的设计”方式一致,正弦信号的频率受开发板上的3个拨码开关控制,用3位信号key表示,即一共可以产生8种频率。正弦信号的频率约为100KHz * (key+1)。当key值为0时产生约100KHz的正弦信号,当key值为1时产生约200KHz的正弦波,当key值为7时产生约800KHz的正弦波。FPGA产生25MHz的时钟,将其传输给AD9280,即AD采样率为25M。在设计中将这一时钟作为SIGNALTAP的采样时钟来观察AD9280传输过来的数据波形。
本次设计使用到的DA9709和AD9280连接示意如下图所示。图3.15-7教学板连接示意图
上板效果图如下图所示,(用signaltap抓取波形),想要观看完整上板演示视频效果的读者朋友可以登陆至简设计法官网查看:WWWXXXXX。图3.15-8AD采集的效果图
第3节 设计实现
接下来就进入设计的实现阶段,本书会按照步骤和原理分析与读者分享案例的实现方法,考虑到初学者的需要,此部分的内容会比较详细。基础知识掌握得比较牢靠,只想学习此设计的步骤的同学可以跳过此部分,后面章节有简化版的步骤分享。在此还是建议初学者不要选择捷径,一定按照详细分析的内容进行学习,只有掌握基础知识、打好基础,才可以从容的独立完成项目设计。
3.1 顶层信号
新建目录:D:\mdy_book\ad_prj。在该目录中,新建一个名为ad_prj.v的文件。用GVIM打开后开始编写代码。这里再次强调,建议初学者按照书中提供的文件路径以及文件名进行设置,避免后续跳出未知错误。
确定顶层信号。分析设计目标可知本设计需要实现以下功能:FPGA产生控制DA9709的信号,令其中的通道A产生正弦波所对应的电压,同时采集AD9280的数据并观察。在此过程中,想要控制DA9709的通道A,就需要控制DA9709的MODE、SLEEP、CLK1、WRT1、DB7~0P1管脚。想要采集AD9280,就需要控制AD9280的CLK、D0~D7管脚。根据设计需求,共需要10个信号:信号clk连接到晶振表示50M时钟的输入;信号rst_n连接到按键表示复位;3位信号key表示三位拨码开关;信号dac_mode连接到DA9709的MODE管脚用来控制其工作模式;信号dac_sleep连接到DA9709的SLEEP管脚用来控制其睡眠模式;信号dac_clka连接到DA9709的CLK1管脚用来控制通道A的时钟;信号dac_wra连接到DA9709的WRT1管脚用来控制通道A的写使能;8位信号dac_da连接到DA9709的DB7~0P1管脚用来控制通道A的写数据;信号ad_clk连接到AD9280的CLK管脚用来作来采样时钟;8位ad_in信号连接到AD9280的D7~0管脚用来采集数据。
综上所述,本设计一共需要10个信号:时钟信号clk,复位信号rst_n,拨码开关的输入信号key,dac_mode、dac_sleep、dac_clka、dac_wra、dac_da、ad_clk和ad_in,其中dac_da、ad_in是8位信号,key是3位信号,其他都是1位信号。信号和硬件的对应关系见下表所示。表3.15-2信号和管脚关系
器件DA9709管脚AD9280管脚原理图信号FPGA管脚FPGA工程信号
U8MODE
DAC_MODEY4dac_mode
SLEEP
DAC_SLEEPH2dac_sleep
CLK1
DA_CLKAR2dac_clka
WRT1
DA_WRAU1dac_wra
DB7P1
DAC_DA7AA1dac_da
DB6P1
DAC_DA6Y2dac_da
DB5P1
DAC_DA5Y1dac_da
DB4P1
DAC_DA4W2dac_da
DB3P1
DAC_DA3W1dac_da
DB2P1
DAC_DA2V2dac_da
DB1P1
DAC_DA1V1dac_da
DB0P1
DAC_DA0U2dac_da
U1
CLKAD_CLKL6ad_clk

D7AD_D7N5ad_in

D6AD_D6M4ad_in

D5AD_D5M5ad_in

D4AD_D4R6ad_in

D3AD_D3T5ad_in

D2AD_D2U7ad_in

D1AD_D1V5ad_in

D0AD_D0V6ad_in
X1

SYS_CLKG1clk
K1

SYS_RSTAB12rst_n
sw0

SW_D0AA3key
sw1

SW_D1AB3key
sw2

SW_D2AB5key

将module的名称定义为ad_prj,已知该设计有10个信号:clk、rst_n、key、dac_mode、dac_sleep、dac_clka、dac_wra、dac_da、ad_clk和ad_in,将与外部相连接的信号写入模块接口列表,具体顶层代码如下所示:
123456789module ad_prj(clk,rst_n,         key       ,dac_mode ,dac_clka,dac_da,dac_wra,dac_sleep,ad_clk,ad_in         );

随后声明输入输出属性。这里需要声明这个信号对于FPGA来说属于输入还是输出,如果是输入信号则声明其为input,如果是输出则声明其为output。在本设计中,由于clk是外部的晶振输入给FPGA的,因此在FPGA中clk为1位的输入信号input;同样地,rst_n是外部按键给FPGA的,因此在FPGA中rst_n为1位输入信号input;dac_da为8位的输出信号output;dac_mode,dac_clka,dac_wra,dac_sleep为1位输出信号output;ad_clk为1位输出信号output;ad_in为8位输入信号input;key为3位输入信号input。综上所述,补充输入输出端口定义的代码如下:
1234567input             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      ad_in   ;

3.2 正弦信号设计
将正弦信号命名为sin_data信号,sin_data是从表3.15- 3中选择出来的值,该表一共有128个点。具体的采样算法在前面章节“信号发生器和DA转换”中有详细描述,这里就不再进行赘述了。表3.15-3DAC输出采样点对应幅度值
采样点isin_data(16进制)采样点isin_data(16进制)采样点isin_data(16进制)采样点isin_data(16进制)
07F32FE647D961
18533FE6577971
28C34FE6670982
39235FD676A993
49836FC68641004
59E37FA695E1016
6A438F870581027
7AA39F67152103A
8B040F4724C104C
9B641F17346105F
10BC42EF744110612
11C143EB753C10715
12C644E8763610819
13CB45E477311091D
14D046E0782C11021
15D547DC792811125
16DA48D880231122A
17DE49D3811F1132E
18E250CE821B11433
19E651C9831711538
20EA52C484141163E
21ED53BE851111743
22F054B986E11849
23F355B387B1194E
24F556AD88912054
25F757A78971215A
26F958A190512260
27FB599B91312367
28FC60959221246D
29FD618F93112573
30FE628994112679
31FE63829511277F

定义一个7位的选择信号addr。只要将addr控制好,就可以快速得到sin_data。因此可以写出下面代码: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

接下来就来确定一下信号addr。addr是用来控制选择数据的地址,通过控制addr的增加值,就能产生多种频率的正弦波。以频率为100KHz的正弦信号为例。该正弦信号的周期是10000ns,本工程的工作时钟是20ns,也就是10000/20 = 500个时钟输出一个正弦信号,即500个时钟需要输出128个点,因此每个时钟addr增加的值为128/500 = 0.256。
按同样的分析方法,可以得到其他信号频率的addr增加值如下所示:
100KHz的正弦信号,每个时钟addr增加:128/250 = 0.256200KHz的正弦信号,每个时钟addr增加:128/250 = 0.512300KHz的正弦信号,每个时钟addr增加:128/166.6667 = 0.7679400KHz的正弦信号,每个时钟addr增加:128/125 = 1.024500KHz的正弦信号,每个时钟addr增加:128/100 = 1.28600KHz的正弦信号,每个时钟addr增加:128/83.3333 = 1.5358700KHz的正弦信号,每个时钟addr增加:128/71.4286 = 1.792800KHz的正弦信号,每个时钟addr增加:128/62.5 = 2.048
addr是表示的是采样点的值,即0~127的整数,但是上面方法计算出addr的每次增加值包含小数。众所周知FPGA是没有小数的,因此可以将上面的小数乘以1024后取整,这样一来就变成了每次要增加的整数,将结果保存到addr_tmp中。即:
100KHz的正弦信号,每个时钟addr_tmp增加:0.256*1024 = 262.144 ≈ 262200KHz的正弦信号,每个时钟addr_tmp增加:0.512*1024 = 524.288 ≈ 524300KHz的正弦信号,每个时钟addr_tmp增加:0.7679*1024 =786.3296 ≈ 786400KHz的正弦信号,每个时钟addr_tmp增加:1.024*1024 =1028.576 ≈ 1029500KHz的正弦信号,每个时钟addr_tmp增加:1.28*1024 =1310.72≈ 1311600KHz的正弦信号,每个时钟addr_tmp增加:1.5358*1024 =1572.6592 ≈1573700KHz的正弦信号,每个时钟addr_tmp增加:1.792*1024 =1835.008 ≈ 1835800KHz的正弦信号,每个时钟addr_tmp增加: 2.048*1024 =2097.152 ≈ 2097
分析设计目标可以知道上面8种频率信号都是由拨码信号key控制的,因此可以写出addr_tmp的代码如下: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

而addr_tmp是小数乘以1024后得到的,因此最终addr_tmp还需要除以1024后再赋给addr。在设计中除以1024即信号向右移10位。addr_tmp向右移10位后,保留7位结果赋给addr就可以了。因此addr_tmp位宽为17位,其代码表示如下:
1assign addr = addr_tmp>>10 ;

3.3 DA接口信号设计
接下来设计信号dac_da。dac_da是直接输出正弦信号的,但由于DA的输出电压与dac_da是成反比例线性关系,所以dac_da都是通过(255-sin_data)得到。写代码时可以调用至简设计法模板,在编辑模式下输入“Shixu2”,将其补充完整得到dac_da的代码表示如下:
12345678always@(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begindac_da<= 0;    end    else begindac_da<= 255 - sin_data;    endend

接着设计信号dac_sleep,AD是一直工作的,因此dac_sleep一直为0;dac_clka为了满足tS的时间要求,可以让dac_clka = ~clk,dac_wra信号可以与dac_clka相同,其具体代码表示如下:
123assign dac_sleep = 0      ;assign dac_wra   = dac_clka ;assign dac_clka= ~clk      ;

至此,主体程序已经完成。
3.4 信号定义
接下来将module补充完整首先来定义信号类型。reg和wire的判断很容易搞不清楚总会有多余的联想,比如认为reg就是寄存器,wire是线;或者认为reg会综合成寄存器,wire不会综合成寄存器。但是这些其实和reg型还是wire型都并无关系,在进行信号类型判断时不需要做任何的联想,只要记住一个规则“用always实现的是reg型,其他都是wire型”就可以了。
addr是用assign设计的,因此类型为wire。addr值最大为127,需要用7根线表示,即位宽为7。
关于信号位宽的确定方法,在这里至简设计法分享一个非常实用的技巧:打开计算器,点击“查看”,选择“程序员”模式,在“十进制”下将信号值输入进去,就会获得对应的信号位宽。利用这一方法将addr的最大计数值127输入到计算器中,如下图所示,可以看到其位宽为7。图3.15-9通过计算器获取信号位宽
综上所述,addr的定义代码如下所示。
1wire        addr    ;

addr_tmp是用always设计的信号,因此类型为reg。该信号的位宽是17,代码表示如下:
1reg       addr_tmp    ;

sin_data是用always设计的,因此类型为reg。其最大值为255,要用8根线表示,位宽为8,这里可以在编辑模式下输入“Reg8”调用至简设计法模板,补充完整后得到代码如下:
1reg       sin_data    ;

dac_da是用always设计的,因此类型为reg,其位宽为8;dac_sleep是用assign设计的,因此类型为wire,其位宽为1;dac_wra是用assign设计的,因此类型为wire,其位宽为1;dac_clka是用assign设计的,因此类型为wire,其位宽为1;dac_mode是用assign设计的,因此类型为wire,其位宽为1。
依旧在编辑模式下输入“ Reg8”“Wire1”调用至简设计法模板,补充完整后得到代码如下:
1reg       dac_da    ;wire          dac_sleep;wire          dac_wra;wire          dac_clka;wire          dac_mode ;

ad_clk是由例化模块输出信号,非always产生,可以定义为wire型,位宽只有1位。在编辑模式下输入“Wire1”调用至简设计法模板,补充完整后得到代码如下:
1wire                        ad_clk;

至此,整个代码的设计工作已经完成。完整版的工程代码如下:module ad_prj(

clk,

rst_n,

         key       ,

dac_mode ,

dac_clka,

dac_da,

dac_wra,

dac_sleep,

ad_clk,

ad_in

         );

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      ad_in   ;



wire        addr    ;

reg       addr_tmp    ;

reg       sin_data    ;

reg       dac_da    ;

wire          dac_sleep;

wire          dac_wra;

wire          dac_clka;

wire          dac_mode ;

wire          ad_clk;



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      ;



endmodule

第4节 综合与上板

4.1 添加文件
打开软件“Quartus”,点击“File”菜单下的“New Project Wizard”,如下图所示。图3.15-10QUARTUS新建工程命令
弹出“Introduction”界面点击“Next”,如下图所示。图3.15-11QUARTUS新建工程介绍界面
设置工程目录、工程名、顶层模块名,其中工程目录设置为:D:\mdy_book\ad_prj,工程名设置为:ad_prj,顶层模块名设置为:ad_prj,填写完毕后直接点击“next”,如下图所示。图3.15-12QUARTUS设置新工程路径和名称
在设置新工程类型界面选择“Empty project”选项,选择空白工程点击“Next”,如下图所示。图3.15-13QUARTUS设置新工程类型
错误!未找到引用源。接下来添加文件,此处不选择任何文件,直接点击“Next”,如下图所示。图3.15-14QUARTUS添加文件到工程界面
随后进入芯片型号选择界面,选择“Cyclone ⅣE”,在芯片型号选择处选择“EP4CE15F23C8”,如下图所示,完成选择后点击“Finish”。图3.15-15QUARTUS设置新工程的芯片型号
打开软件“Quartus”,在“Project”菜单中选择“Add/Remove File to Project”,随后会弹出文件窗口。图3.15-16添加文件命令界面
点击右上角的按钮,在弹出来的窗口中双击选择D:\mdy_book\ad_prj目录下的“ad_prj.v”和“my_pll.qip”文件。点击“Add”后完成添加,添加成功后点击“OK”关闭本窗口。添加文件成功界面如下图所示。图3.15-17添加文件成功界面
4.2 综合
编译界面如下图所示,在菜单栏中选中“Processing”然后选择“Start Compilation”,开始对整个工程进行编译和综合。图3.15-18编译命令界面
当出现如下图所示的界面就说明编译综合成功。图3.15-19编译成功界面
4.3 配置管脚
下面需要对相应管脚进行配置。如下图所示,在菜单栏中选中“Assignments”,然后选择“Pin Planner”,随后就会弹出配置管脚的窗口。图3.15-20配置管脚命令界面
在配置窗口最下方中的“location”一列,参考表3.2-2信号和管脚关系,按照表3.15- 2中最右两列配置好FPGA管脚,配置管理来源参见管脚配置环节,最终配置的结果如图3.15-22。配置完成后,关闭Pin Planner,软件自动会保存管脚配置信息。图3.15-21配置管脚界面
表3.15 - 1信号和管脚关系
器件DA9709管脚AD9280管脚原理图信号FPGA管脚FPGA工程信号
U8MODE DAC_MODEY4dac_mode
SLEEP DAC_SLEEPH2dac_sleep
CLK1 DA_CLKAR2dac_clka
WRT1 DA_WRAU1dac_wra
DB7P1 DAC_DA7AA1dac_da
DB6P1 DAC_DA6Y2dac_da
DB5P1 DAC_DA5Y1dac_da
DB4P1 DAC_DA4W2dac_da
DB3P1 DAC_DA3W1dac_da
DB2P1 DAC_DA2V2dac_da
DB1P1 DAC_DA1V1dac_da
DB0P1 DAC_DA0U2dac_da
U1 CLKAD_CLKL6ad_clk
D7AD_D7N5ad_in
D6AD_D6M4ad_in
D5AD_D5M5ad_in
D4AD_D4R6ad_in
D3AD_D3T5ad_in
D2AD_D2U7ad_in
D1AD_D1V5ad_in
D0AD_D0V6ad_in
X1 SYS_CLKG1clk
K1 SYS_RSTAB12rst_n
sw0 SW_D0AA3key
sw1 SW_D1AB3key
sw2 SW_D2AB5key



图3.15-22配置管脚成功界面

4.4 再次综合
再次打开“QUARTUS”软件,在菜单栏中选中“Processing”,然后选择“Start Compilation”,再次对整个工程进行编译和综合,如下图所示。图3.15-23编译命令界面
当出现图3.2-19QUARTUS编译成功标志时就说明编译综合成功。图3.15-24编译成功界面
4.5 连接开发板
完成编译后开始进行上板调试操作,开发板连接方式如下图所示。将电源接上开发板,USB BLASTER一端连接到JTAG插口,另一端连到PC的USB接口。将开发板上的AD接口和DA两个通道相连,连接完成后再将电源打开。图3.15-25教学板连接示意图
4.5.1 设置SIGNALTAP
编译通过后,点击“Tools”选项下的“SingaⅡLogic Analyzer”。图3.15-26设置signaltap界面
得到的原始“signaltap”界面如下图所示。图3.15-27原始“signaltap”界面
点击“Hardware”中的“Setup”选项,弹出“Hadware Setup”窗口。在“Currently selected hardware”选项下选择“USB-Blaster ”,如下图所示。图3.15-28Hadware Setup设置界面
点击“SOF Manager”右边的三个点,随后会弹出文件选择窗口,如下图所示。图3.15-29弹出文件选择窗口
选择“ad_prj.sof ”文件,点击“Open”如下图所示。图3.15-30选择文件界面
配置时钟界面如下图所示,点击“Clock”选项后的三个点标志,“Filter”处选择下拉菜单中的“Design Entry(all names)”选项,点击“list”,在“Nodes Found”栏选择“clk”选项,点击两栏中间第一个右向箭头后可以看到“Selected Nodes”栏出现对应的“clk”,如下图所示。图3.15-31配置时钟界面
在“Sample depth”选项下拉菜单中选择1K,如下图所示。图3.15-32采样设置
选择所有要抓取的信号,选择完毕后点击“OK”。图3.15-33选择要抓取的信号
回到本界面再次进行编译。图3.15-34再次进行编译
点击“SOF Manager”进行下载,如下图所示。图3.15-35下载界面
需要注意的是:点击按键表示抓取一次,点击按键表示连续抓取。
4.5.2 用SIGNALTAP观察
为了方便查看波形,可以在“Hierarchy Display”区域空白处右键,点击“Bus Display Format”选项中的“Unsigned Line Chart”,得到更加细节化的正弦波,如下图所示。图3.15-36细节化观察波形
100KHz的正弦波如下图所示。图3.15-37100KHz正弦波
300kHz的正弦波如下图所示。图3.15-38 300KHz正弦波
500KHz的正弦波如下图所示。图3.15-39 500KHz正弦波
800KHz的正弦波如下图所示。图3.15-40 800KHz正弦波
第5节 简化版步骤分享
这里依旧会分享简化版的步骤,方便掌握基础原理后进行反复操作复习。
5.1 设计实现

5.1.1 顶层信号
新建目录:D:\mdy_book\ad_prj。在该目录中,新建一个名为ad_prj.v的文件,并用GVIM打开,开始编写代码。
分析设计目标,确定顶层信号。信号和硬件的对应关系见表3.15- 2。 表3.15- 2信号和管脚关系
器件DA9709管脚AD9280管脚原理图信号FPGA管脚FPGA工程信号
U8MODE
DAC_MODEY4dac_mode
SLEEP
DAC_SLEEPH2dac_sleep
CLK1
DA_CLKAR2dac_clka
WRT1
DA_WRAU1dac_wra
DB7P1
DAC_DA7AA1dac_da
DB6P1
DAC_DA6Y2dac_da
DB5P1
DAC_DA5Y1dac_da
DB4P1
DAC_DA4W2dac_da
DB3P1
DAC_DA3W1dac_da
DB2P1
DAC_DA2V2dac_da
DB1P1
DAC_DA1V1dac_da
DB0P1
DAC_DA0U2dac_da
U1
CLKAD_CLKL6ad_clk

D7AD_D7N5ad_in

D6AD_D6M4ad_in

D5AD_D5M5ad_in

D4AD_D4R6ad_in

D3AD_D3T5ad_in

D2AD_D2U7ad_in

D1AD_D1V5ad_in

D0AD_D0V6ad_in
X1

SYS_CLKG1clk
K1

SYS_RSTAB12rst_n
sw0

SW_D0AA3key
sw1

SW_D1AB3key
sw2

SW_D2AB5key

写出顶层代码如下:
123456789module ad_prj(clk,rst_n,         key       ,dac_mode ,dac_clka,dac_da,dac_wra,dac_sleep,ad_clk,ad_in         );

声明输入输出属性代码如下:
1234567input             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      ad_in   ;

5.1.2 正弦信号设计
采样点对应幅度值如下表所示。表3.15- 3DAC输出采样点对应幅度值
采样点isin_data(16进制)采样点isin_data(16进制)采样点isin_data(16进制)采样点isin_data(16进制)
07F32FE647D961
18533FE6577971
28C34FE6670982
39235FD676A993
49836FC68641004
59E37FA695E1016
6A438F870581027
7AA39F67152103A
8B040F4724C104C
9B641F17346105F
10BC42EF744110612
11C143EB753C10715
12C644E8763610819
13CB45E477311091D
14D046E0782C11021
15D547DC792811125
16DA48D880231122A
17DE49D3811F1132E
18E250CE821B11433
19E651C9831711538
20EA52C484141163E
21ED53BE851111743
22F054B986E11849
23F355B387B1194E
24F556AD88912054
25F757A78971215A
26F958A190512260
27FB599B91312367
28FC60959221246D
29FD618F93112573
30FE628994112679
31FE63829511277F

设计sin_data信号: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
设计addr信号: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
设计addr_tmp信号:
1assign addr = addr_tmp>>10 ;

5.1.3 DA接口信号设计
设计dac_da信号:
12345678always@(posedge clk or negedge rst_n)begin    if(rst_n==1'b0)begindac_da<= 0;    end    else begindac_da<= 255 - sin_data;    endend

设计dac_sleep信号:
123assign dac_sleep = 0      ;assign dac_wra   = dac_clka ;assign dac_clka= ~clk      ;

至此,主体程序已经完成,接下来是将module补充完整。
5.1.4 信号定义
首先定义信号类型,addr信号的定义代码表示如下:
1wire        addr    ;

addr_tmp信号的定义代码表示如下:
1reg       addr_tmp    ;

sin_data信号的定义代码表示如下:
1reg       sin_data    ;

dac_da、dac_sleep、dac_wra、dac_clka、dac_mode信号的定义代码表示如下:
1reg       dac_da    ;wire          dac_sleep;wire          dac_wra;wire          dac_clka;wire          dac_mode ;

ad_clk信号的定义代码表示如下:
1wire                        ad_clk;

完整版的工程代码如下:module ad_prj(
clk,
rst_n,
         key       ,
dac_mode ,
dac_clka,
dac_da,
dac_wra,
dac_sleep,
ad_clk,
ad_in
         );
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      ad_in   ;
wire        addr    ;
reg       addr_tmp    ;
reg       sin_data    ;
reg       dac_da    ;
wire          dac_sleep;
wire          dac_wra;
wire          dac_clka;
wire          dac_mode ;
wire          ad_clk;
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      ;
endmodule

5.2 综合与上板

5.2.1 添加文件
打开软件“Quartus”,点击“File”菜单下的“New Project Wizard”,如下图所示。图3.15- 10 QUARTUS新建工程命令
点击“Next”。图3.15- 11 QUARTUS新建工程介绍界面
此时会出现的是工程文件夹、工程名、顶层模块名设置界面,设置目录为D:\mdy_book\ad_prj,工程名和顶层名为ad_prj,设置完成后点击“Next”。图3.15- 12 QUARTUS设置新工程路径和名称
选择“Empty project”后点击“Next”。图3.15- 13 QUARTUS设置新工程类型
错误!未找到引用源。接着是添加文件界面。此处不选择任何文件,直接点击“Next”,如下图所示。图3.15- 14 QUARTUS添加文件到工程界面
“Device family”选项中选择“Cyclone ⅣE”,“Available devices”选项下选择“EP4CE15F23C8”随后点击“Next”。图3.15- 15 QUARTUS设置新工程的芯片型号
再次打开软件“Quartus”,在“Project”菜单中选择“Add/Remove File to Project”,随后弹出文件窗口。图3.15- 16 添加文件命令界面
点击右上角的按钮,在弹出来的窗口中双击选择D:\mdy_book\ad_prj目录下的“ad_prj.v”和“my_pll.qip”文件。点击“Add”添加成功后点击“OK”,关闭本窗口。图3.15- 17 添加文件成功界面
5.2.2 综合
在菜单栏中选中“Processing”,然后选择“Start Compilation”,开始对整个工程进行编译和综合。图3.15- 18 编译命令界面
当出现下图的界面,则说明编译综合成功。图3.15- 19 编译成功界面
5.2.3 配置管脚
配置管脚界面如下图所示,在菜单栏中选中“Assignments”,然后选择“Pin Planner”,随后会弹出配置管脚的窗口。图3.15- 20 配置管脚命令界面
在配置窗口“location”配置管脚,配置完成关闭“Pin Planner”即可自动保存配置信息。图3.15- 21 配置管脚界面
5.2.4 再次综合
再次打开“QUARTUS”软件,在菜单栏中选中“Processing”,然后选择“Start Compilation”,再次对整个工程进行编译和综合,如下图所示。图3.15- 23 编译命令界面
当出现图3.2-19QUARTUS编译成功标志,则说明编译综合成功。图3.15- 24 编译成功界面
5.2.5 连接开发板
完成编译后开始进行上板调试操作,开发板连接方式如下图所示。将电源接上开发板,USB BLASTER一端连接到JTAG插口,另一端连到PC的USB接口。将开发板上的AD接口和DA两个通道相连,连接完成后再将电源打开。
图3.15- 25 教学板连接示意图
5.2.6 设置SIGNALTAP
编译通过后,点击“Tools”选项下的“SingaⅡLogic Analyzer”。图3.15-41设置signaltap界面
得到的原始“signaltap”界面如下图所示。图3.15-42原始“signaltap”界面
点击“Hardware”中的“Setup”选项,弹出“Hadware Setup”窗口。在“Currently selected hardware”选项下选择“USB-Blaster ”,如下图所示。图3.15-43Hadware Setup设置界面
点击“SOF Manager”右边的三个点,随后会弹出文件选择窗口,如下图所示。图3.15-44弹出文件选择窗口
选择“ad_prj.sof ”文件,点击“Open”如下图所示。图3.15-45选择文件界面
配置时钟界面如下图所示,点击“Clock”选项后的三个点标志,“Filter”处选择下拉菜单中的“Design Entry(all names)”选项,点击“list”,在“Nodes Found”栏选择“clk”选项,点击两栏中间第一个右向箭头后可以看到“Selected Nodes”栏出现对应的“clk”,如下图所示。图3.15-46配置时钟界面
在“Sample depth”选项下拉菜单中选择1K,如下图所示。图3.15-47采样设置
选择所有要抓取的信号,选择完毕后点击“OK”。图3.15-48选择要抓取的信号
回到本界面再次进行编译。图3.15-49再次进行编译
点击“SOF Manager”进行下载,如下图所示。图3.15-50下载界面
需要注意的是:点击按键表示抓取一次,点击按键表示连续抓取。
5.2.7 用SIGNALTAP观察
为了方便查看波形,可以在“Hierarchy Display”区域空白处右键,点击“Bus Display Format”选项中的“Unsigned Line Chart”,得到更加细节化的正弦波,如下图所示。图3.15-51细节化观察波形
100KHz的正弦波如下图所示。图3.15-52100KHz正弦波
300kHz的正弦波如下图所示。图3.15-53 300KHz正弦波
500KHz的正弦波如下图所示。图3.15-54 500KHz正弦波
800KHz的正弦波如下图所示。图3.15-55 800KHz正弦波
第6节 扩展练习
至此,整个AD采集设计已经分享完毕,在学会了整个设计之后可以展开更多思考,基于原理不变的情况下多做一些尝试,比如更改产生的正弦波周期后查看展示效果,这样可以帮助同学们更深刻的掌握本案例。也欢迎有更多思路和想法的同学前往至简设计法论坛上进行交流讨论。




XTQ 发表于 2021-3-12 11:29:50

图片这里笔误了吧

admin 发表于 2021-3-27 22:46:49

AD采集案例问题汇总
【问题1】 ADC采集的数据一直很小,好像没采集到,如下图。

答:提供如下几个思路,请逐个确认。
1. 确保本案例中的SMA线连接正确,特别注意要三个SMA头,要选正确的连接。
2. 查看SMA线,MP801板上的SMA是母头,所以SMA线上应该是公头。
3. 换条SMA线看看,看不是线出问题了。
4. MP801的DAC输出电压是比较低的,经过环回后,AD采集的值比较小,这是正常的,应该能看出正弦波出来,如果看不到就是有问题。
5. 使用信号发生器产生激励,单独测试AD。6. dac_mode要设置为1。(注意,原工程有错误,新工程已经补充了)
7. 以上问题还没解决,可反馈给老师。



页: [1]
查看完整版本: 【FPGA至简设计原理与应用】书籍连载24 第三篇FPGA至简设计项目 第十五章 AD采集