一、简介
ADC是analog to digital converter也就是代表模拟转数字
DAC是digital to analog converter是数字转模拟
性能指标:
通常我们关注转换速率以及分辨率两个指标
转换速率:每秒可以采集多少个点
分辨率:分辨率是由数据位宽决定,位宽越大越精准(例如0.21比0.2更精准)
其中本次ad da实验采用串并比较型是较快的速度
DA 芯片(AD9708/3PD9708,两款芯片兼容)输出的是一对差分电流信号,通过高性能和高带宽的运放电路,实现差分变单端以及幅度调节等功能,使整个电路性能得到了最大限度的提升,最终输出的模拟电压范围是-5V~+5V。
AD 芯片(AD9280/3PA9280,两款芯片兼容)的输入模拟电压转换范围是0V~2V,所以电压输入端需要先经过电压衰减电路,使输入的-5V~+5V 之间的电压衰减到0V~2V 之间,然后经过AD 芯片将模拟电压信号转换成数字信号。
CLOCK 的时钟频率越快,AD9708 的数模转换速度越快,AD9708 的时钟频率最快为
125Mhz。当输入数据为0时候 ad9708输出5V 输入数据为255时,ad9708输出电压为-5v(因为其外部有一个反相放大电路)(da)
AD9280 芯片的最大转换速度是32MSPS,即输入的时钟最大频率为32MHz。(ad)
AD9280 支持输入的模拟电压范围是0V 至2V,0V 对应输出的数字信号为0,2V 对应输出的数字信号为255。
在当前采样周期后三个周期才可以得到ad输出的data如下图
二、实验内容
2.1实验任务
用软件产生一个正弦波,将该正弦波存储在rom中(数字信号),使用da模块先将数字信号转化为模拟信号,再采用ad模块将其输出的模拟信号转化为数字信号,再用ila抓取输出的数字信号检测波形是否正确。
2.2实验框图
其中da和ad的时钟频率不超过其传输的最大速度即可(ad32MHz)(da125Mhz)
为什么要采用25mhz deg120的信号?
由此图可得,ad的数据采样信号的时钟并不在输出数据的正中间,因此可能会出现采样的亚稳态,为调整ila采样时候的稳定,因此我们需要120°相位。
为什么da模块需要180°时钟相位?
若使用无相位的是时钟(即数据发送时钟),则其上升沿采样时恰巧是数据改变的时候,会出现亚稳态,若选择加入半个相位,会使得采样时钟再数据中心点。
2.3软件生成正弦波
采用正点原子开发的软件可以生成正弦波数据,并可以选择位宽、深度、倍频。
这里位宽是选择和芯片一样的位宽即可,adda芯片位宽为8;深度表示一个周期用多少个点来表示这个正弦波,点数越大正弦波越精确(类似于二分法)(注意rom的位宽深度应该与上位机一致);倍频,即可以提升正弦波频率(频率高容易失真)
最后将生产的coe文件载入rom中就行。
三、代码实现
3.1IP核配置
本次实验需要配置锁相环(PLL)进行分频以及ROM模块提前载入正弦波的数据
3.2数据发送模块
该模块需要读取rom中的数据(需要发送地址给rom),并发送给后面的da模块,顺带输出180°相位的驱动时钟(对原时钟取反即可)。
module send_data(
input clk ,
input rst ,
//rom
output reg [7:0] rd_addr ,
input [7:0] rd_data ,
output rom_en ,
//da
output da_clk ,
output [7:0] da_data
);
reg [2:0] freq_cnt ; //降低波形频率计数器
parameter FREQ = 5;
assign da_clk = ~clk ;
assign da_data = rd_data ;
assign rom_en = 1'b1;
always @(posedge clk or negedge rst ) begin
if (!rst )
freq_cnt <= 3'b0 ;
else if (freq_cnt < FREQ )
freq_cnt <= freq_cnt + 3'b1 ;
else
freq_cnt <= 3'b0 ;
end
always @(posedge clk or negedge rst ) begin
if (!rst )
rd_addr <= 8'b0 ;
else if ((freq_cnt == FREQ) &&(rd_addr < 8'd255 ))
rd_addr <= rd_addr + 8'b1 ;
else if ((freq_cnt == FREQ) &&(rd_addr == 8'd255 ))
rd_addr <= 8'b0 ;
else
rd_addr <= rd_addr;
end
endmodule
在这个模块定义了一个计数器使得每计数6个才改变一次rom地址读取,说明我们降低原始正弦波频率到了六分之一。
3.3顶层模块
由于ad和da是模块并只需要输入数据即可进行工作,因此不需要对这两个模块进行驱动,只需要插好线即可。
module ad_da_top(
input sys_clk ,
input sys_rst ,
//da
output da_clk ,
output [7:0] da_data ,
//ad
input [7:0] ad_data ,
input ad_otr ,
output ad_clk
);
wire clk_50m;
wire clk_25m;
wire clk_25m_120deg;
wire rom_en ;
wire locked ;
wire [7:0] rd_addr;
wire [7:0] rd_data;
clk_wiz_0 u_clk_wiz_0
(
// Clock out ports
.clk_out1(clk_50m), // output clk_out1
.clk_out2(ad_clk), // output clk_out2 25m
.clk_out3(clk_25m_120deg), // output clk_out3
// Status and control signals
.locked(locked), // output locked
// Clock in ports
.clk_in1(sys_clk)
);
blk_mem_gen_0 u_blk_mem_gen_0 (
.clka(clk_50m), // input wire clka
.ena(rom_en), // input wire ena
.addra(rd_addr), // input wire [7 : 0] addra
.douta(rd_data) // output wire [7 : 0] douta
);
send_data u_send_data(
.clk ( clk_50m ),
.rst ( sys_rst ),
.rd_addr ( rd_addr ),
.rd_data ( rd_data ),
.rom_en ( rom_en ),
.da_clk ( da_clk ),
.da_data ( da_data )
);
ila_0 u_ila_0 (
.clk(clk_25m_120deg), // input wire clk
.probe0(ad_otr), // input wire [0:0] probe0
.probe1(ad_data), // input wire [7:0] probe1
.probe2(da_data), // input wire [7:0] probe2
.probe3(rd_data) // input wire [7:0] probe3
);
endmodule
四、下载验证
下载验证时候是没有任何数据的,因为ila调试频率应至少大于JATG下载频率的2.5倍,否则ila无法得到调试信息。设置方法如下:
在下载后选择Xilinx tcf,在点击下方的properties可以看到PARAM选项,展开来可以看见可以设置频率,将其频率调整到满足2.5倍小于ila采样频率即可