ZYNQ之高速AD/DA验证实验
本实验是高速AD/DA验证实验,将使用高速DA芯片实现数模转换,产生正弦波模拟电压信号,并通过高速AD芯片将模拟信号转换成数字信号。本实验用到的硬件是黑金AX7020开发板和与其配套的ADDA模块——AN108。
前言
本实验是高速AD/DA验证实验,将使用高速DA芯片实现数模转换,产生正弦波模拟电压信号,并通过高速AD芯片将模拟信号转换成数字信号。本实验用到的硬件是黑金AX7020开发板和与其配套的ADDA模块——AN108。
一、ADDA模块介绍
本实验中使用的ADDA模块型号为AN108,该模块如下图所示。
其中,ADC的最大采样率为32MHz,精度为8位,DAC的最大采样率为125MHz,精度也为8位。
该ADDA模块不管是AD IN口还是DA OUT口都是通过BNC接口与外界连接的。
AN108的硬件结构图如下图所示。
DA电路由高速DA芯片AD9708、7阶巴特沃斯低通滤波器、幅度调节电路和信号输出接口组成。高速DA芯片AD9708是8位,125MSPS的DA转换芯片,内置1.2V参考电压,差分电流输出。AD9708芯片差分输出以后,为了防止噪声干扰,电路中接入了7阶巴特沃斯低通滤波器,其带宽为40MHz。在滤波器之后,连接了2片高性能的145MHz带宽的运放AD8056,以实现差分变单端、幅度调节等功能,从而使得整个电路性能得到最大限度的提升,幅度调节使用的是5K的电位器,因此最终的输出范围是-5V—5V,即10Vpp。
需要注意的是,由于电路器的精度不是很精确,最终的输出有一定误差,有可能波形幅度不能达到10Vpp,也有可能出现波形削顶等问题,这些都属正常情况。
AD电路由高速AD芯片AD9280、衰减电路和信号输入接口组成。高速DA芯片AD9280是8位,32MSPS的AD转换芯片。在信号进入芯片AD9280之前,使用一片AD8056芯片构建衰减电路,接口的输入范围是-5V至5V,通过衰减电路以后,输入范围满足AD芯片的输入范围,即0~2V,相应的转换公式如下。
黑金7020开发板与ADDA模块的连接如下图所示,开发板排针的1脚2脚和39脚40脚都在开发板上标出来了,ADDA模块的1脚2脚也在ADDA模块上标注出来了,由于AN108是34脚,而开发板的排针是40脚,因此要注意不要插反,先将ADDA模块的1脚2脚和开发板的1脚2脚口对齐,再依次从上至下插入即可。
二、添加ROM IP核
这部分的细节可以参考博文:ZYNQ之FPGA 片内ROM读写测试实验。
首先创建一个名为adda_test的工程,新工程汇总的界面如下图所示,点击Finish即可完成创建。
在本次实验中,将正弦波的波形数据存储在ROM中,这是因为实验中并不需要写数据(如果需要,就要用RAM),然后通过读取ROM中的数据,继而发送给DA转换芯片即可。
首先打开波形数据生成器,选择数据长度为256,数据位宽为8,选择正弦波生成,然后点击保存。
将该文件最好保存在工程目录下,选择保存的格式为.coe。
如果没有波形数据生成器,可以点此下载。
接着来创建ROM IP核,将其命名为rom_256x8b,各栏目的设置如下图所示。
Basic栏目设置。
Port A Options栏目设置。
Other Options栏目下,选择加载初始文件,就是上面保存的.coe文件。
三、添加ILA IP核
ILA下各栏目的设置如下图所示。
这里设置两个探针,分别用来监测ad的数据和da的数据。
探针位数的设置如下图所示。
四、编写测试程序
新建名为adda_test的Verilog文件,依次按照下图中标注的序号进行即可。
在新建好的adda_test.v文件中写入如下代码。
//本代码来自正点原子
`timescale 1ns / 1ps
module adda_test(
input sys_clk , //系统时钟
input sys_rst_n , //系统复位,低电平有效
//DA芯片接口
output da_clk , //DA(AD9708)驱动时钟,最大支持125Mhz时钟
output [7:0] da_data , //输出给DA的数据
//AD芯片接口
input [7:0] ad_data , //AD输入数据
//模拟输入电压超出量程标志(本次试验未用到)
//input ad_otr , //0:在量程范围 1:超出量程
output ad_clk //AD(AD9280)驱动时钟,最大支持32Mhz时钟
);
//wire define
wire [7:0] rd_addr; //ROM读地址
wire [7:0] rd_data; //ROM读出的数据
//DA数据发送
da_wave_send u_da_wave_send(
.clk (sys_clk),
.rst_n (sys_rst_n),
.rd_data (rd_data),
.rd_addr (rd_addr),
.da_clk (da_clk),
.da_data (da_data)
);
//ROM存储波形
rom_256x8b u_rom_256x8b (
.clka (sys_clk), // input wire clka
.addra (rd_addr), // input wire [7 : 0] addra
.douta (rd_data) // output wire [7 : 0] douta
);
//AD数据接收
ad_wave_rec u_ad_wave_rec(
.clk (sys_clk),
.rst_n (sys_rst_n),
.ad_data (ad_data),
// .ad_otr (ad_otr),
.ad_clk (ad_clk)
);
//ILA采集AD数据
ila_0 ila_0 (
.clk (ad_clk ), // input wire clk
.probe0 (da_data), // input wire [7:0] probe0
.probe1 (ad_data) // input wire [7:0] probe0
);
endmodule
同样的方法新建名为da_wave_send.v的文件并写入如下代码。
//本代码来自正点原子
module da_wave_send(
input clk , //时钟
input rst_n , //复位信号,低电平有效
input [7:0] rd_data, //ROM读出的数据
output reg [7:0] rd_addr, //读ROM地址
//DA芯片接口
output da_clk , //DA(AD9708)驱动时钟,最大支持125Mhz时钟
output [7:0] da_data //输出给DA的数据
);
//parameter 频率调节控制
parameter FREQ_ADJ = 8'd5; //频率调节,FREQ_ADJ的值越大,最终输出的频率越低,范围0~255
//reg define
reg [7:0] freq_cnt ; //频率调节计数器
//数据rd_data是在clk的上升沿更新的,所以DA芯片在clk的下降沿锁存数据是稳定的时刻
//而DA实际上在da_clk的上升沿锁存数据,所以时钟取反,这样clk的下降沿相当于da_clk的上升沿
assign da_clk = ~clk;
assign da_data = rd_data; //将读到的ROM数据赋值给DA数据端口
//频率调节计数器
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
freq_cnt <= 8'd0;
else if(freq_cnt == FREQ_ADJ)
freq_cnt <= 8'd0;
else
freq_cnt <= freq_cnt + 8'd1;
end
//读ROM地址
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
rd_addr <= 8'd0;
else begin
if(freq_cnt == FREQ_ADJ) begin
rd_addr <= rd_addr + 8'd1;
end
end
end
endmodule
再新建名为ad_wave_rec.v的文件并写入如下代码。
//本代码来自正点原子
module ad_wave_rec(
input clk , //时钟
input rst_n , //复位信号,低电平有效
input [7:0] ad_data , //AD输入数据
//模拟输入电压超出量程标志(本次试验未用到)
input ad_otr , //0:在量程范围 1:超出量程
output reg ad_clk //AD(AD9280)驱动时钟,最大支持32Mhz时钟
);
//时钟分频(2分频,时钟频率为25Mhz),产生AD时钟
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
ad_clk <= 1'b0;
else
ad_clk <= ~ad_clk;
end
endmodule
到这里,本实验的测试代码就添加完成了。
一开始打算使用PLL来输出ad和da的时钟,但是在程序中应用时出错了,报错信息如下。
INFO: [Labtools 27-1434] Device xc7z020 (JTAG device index = 1) is programmed with a design that has no supported debug core(s) in it.
WARNING: [Labtools 27-3361] The debug hub core was not detected.
Resolution:
- Make sure the clock connected to the debug hub (dbg_hub) core is a free running clock and is active.
- Make sure the BSCAN_SWITCH_USER_MASK device property in Vivado Hardware Manager reflects the user scan chain setting in the design and refresh the device. To determine the user scan chain setting in the design, open the implemented design and use ‘get_property C_USER_SCAN_CHAIN [get_debug_cores dbg_hub]’.
For more details on setting the scan chain property, consult the Vivado Debug and Programming User Guide (UG908).
WARNING: [Labtools 27-3413] Dropping logic core with cellname:‘ila_0’ at location ‘uuid_D7F66BBC62045AEA8C9B20B797086963’ from probes file, since it cannot be found on the programmed device.
出现这个问题的原因是在ILA中使用了通过PLL生成的时钟。
所以就添加了另外两个模块da_wave_send和ad_wave_rec,这两个模块中主要还是对时钟的设置。da_wave_send中将时钟进行了翻转,同时设置读ROM的地址;ad_wave_rec中将系统时钟进行二分频,得到25MHz时钟,即ad_clk。
五、管脚分配
ADDA模块——AN108的34针排布的原理图如下。
黑金开发板的J11扩展口原理图如下。
其中,J11扩展口所对应的引脚号如下表所示。
J11管脚 | 信号名称 | ZYNQ引脚名 | ZYNQ引脚号 |
---|---|---|---|
PIN1 | GND | - | - |
PIN2 | +5V | - | - |
PIN3 | EX_IO2_1N | IO_L6N_T0_35 | F17 |
PIN4 | EX_IO2_1P | IO_L6P_T0_35 | F16 |
PIN5 | EX_IO2_2N | IO_L15N_T2_35 | F20 |
PIN6 | EX_IO2_2P | IO_L15P_T2_35 | F19 |
PIN7 | EX_IO2_3N | IO_L18N_T2_35 | G20 |
PIN8 | EX_IO2_3P | IO_L18P_T2_35 | G19 |
PIN9 | EX_IO2_4N | IO_L14N_T2_35 | H18 |
PIN10 | EX_IO2_4P | IO_L14P_T2_35 | J18 |
PIN11 | EX_IO2_5N | IO_L9N_T1_35 | L20 |
PIN12 | EX_IO2_5P | IO_L9P_T1_35 | L19 |
PIN13 | EX_IO2_6N | IO_L7N_T1_35 | M20 |
PIN14 | EX_IO2_6P | IO_L7P_T1_35 | M19 |
PIN15 | EX_IO2_7N | IO_L12N_T1_35 | K18 |
PIN16 | EX_IO2_7P | IO_L12P_T1_35 | K17 |
PIN17 | EX_IO2_8N | IO_L10N_T1_35 | J19 |
PIN18 | EX_IO2_8P | IO_L10P_T1_35 | K19 |
PIN19 | EX_IO2_9N | IO_L17N_T2_35 | H20 |
PIN20 | EX_IO2_9P | IO_L17P_T2_35 | J20 |
PIN21 | EX_IO2_10N | IO_L11N_T1_35 | L17 |
PIN22 | EX_IO2_10P | IO_L11P_T1_35 | L16 |
PIN23 | EX_IO2_11N | IO_L8N_T1_35 | M18 |
PIN24 | EX_IO2_11P | IO_L8P_T1_35 | M17 |
PIN25 | EX_IO2_12N | IO_L4N_T0_35 | D20 |
PIN26 | EX_IO2_12P | IO_L4P_T0_35 | D19 |
PIN27 | EX_IO2_13N | IO_L5N_T0_35 | E19 |
PIN28 | EX_IO2_13P | IO_L5P_T0_35 | E18 |
PIN29 | EX_IO2_14N | IO_L16N_T2_35 | G18 |
PIN30 | EX_IO2_14P | IO_L16P_T2_35 | G17 |
PIN31 | EX_IO2_15N | IO_L13N_T2_35 | H17 |
PIN32 | EX_IO2_15P | IO_L13P_T2_35 | H16 |
PIN33 | EX_IO2_16N | IO_L19N_T3_35 | G15 |
PIN34 | EX_IO2_16P | IO_L19P_T3_35 | H15 |
PIN35 | EX_IO2_17N | IO_L20N_T3_35 | J14 |
PIN36 | EX_IO2_17P | IO_L20P_T3_35 | K14 |
PIN37 | GND | - | - |
PIN38 | GND | - | - |
PIN39 | +3.3V | - | - |
PIN40 | +3.3V | - | - |
具体的引脚分配见下表。
名称 | 引脚号 |
---|---|
sys_clk | U18 |
da_clk | F20 |
da_0 | M20 |
da_1 | L19 |
da_2 | L20 |
da_3 | J18 |
da_4 | H18 |
da_5 | G19 |
da_6 | G20 |
da_7 | F19 |
ad_clk | G18 |
ad_0 | L17 |
ad_1 | L16 |
ad_2 | M18 |
ad_3 | M17 |
ad_4 | D20 |
ad_5 | D19 |
ad_6 | E19 |
ad_7 | E18 |
根据上面表中的对应关系,打开管脚配置页面依次设置即可。
六、连接开发板测试
连接开发板,点击Generate Bitstream生成比特流文件,将其下载到开发板上,在ILA窗口运行后得到如下图所示的正弦波。
由上图可以看到,输入的ad_data数据是正弦波的波形,说明该实验验证成功了。
如果设置的ILA采样深度太小,得到的波形就是这样的。
所以在ILA中设置采样深度时要设置合理,设置的太大,需要耗费的资源也越多。
按理说这里的数模转换波形需要用示波器测量,具体的测量方法是将示波器带夹子的一端连接开发板的GND端(开发板上任意的GND均可),然后将示波器另一端探针接到DA通道上,这里由于条件限制就利用ILA代替了示波器,其输出也是正弦波。
总结
以上就是ZYNQ之高速AD/DA验证实验的所有内容了,该实验与ROM读写测试实验有一定的相似之处,同时也是在其基础上进行更复杂的实验,本实验需要注意的是ADDA模块在插入开发板时不要插反,同时在管脚分配时也要注意不要出错。
本文参考资料:
正点原子–course_s1_ZYNQ那些事儿-FPGA实验篇V1.06.pdf
ALINX黑金AX7020开发板用户手册V2.2.pdf
领航者ZYNQ之FPGA开发指南_V2.0 .pdf
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)