8.4 实验原理
8.4.1 DAC及DDS介绍
上一节我们学习了ADC的相关知识,DAC与ADC功能相反,DAC是数字模拟转换器(英语:Digital to analog converter,英文缩写:DAC)是一种将数字信号转换为模拟信号(以电流、电压或电荷的形式)的设备。在很多数字系统中(例如计算机),信号以数字方式存储和传输,而数字模拟转换器可以将这样的信号转换为模拟信号,从而使得它们能够被外界(人或其他非数字系统)识别。

上图两个都是8位DAC模型,转换精度为 2的8次方等于256,即将Vref分成256份,DAC转换输出模拟电压最小步进为Vref / 256,模拟电压 Vout = N * Vref / 256 。
- 并行DAC与数字电路接口包含一根clk和8根data管脚,clk为芯片时钟管脚,data为芯片数据管脚,每个clk周期从data管脚输出8bit的数据,完成一次数模转换,所以clk频率等于转换率。
- 串行DAC(以DAC081S101为例)与数字电路接口为三根线(sync,clk,din),兼容三线SPI总线,sync为帧同步管脚,clk为芯片时钟管脚,din为芯片数据管脚,当DAC帧同步信号拉低后每个clk周期从din发送1bit的数据,但是根据DAC081S101的时序,需要16个clk完成一次DA转换,所以clk频率至少等于采样率的16倍。
DDS是直接数字式频率合成器(Direct Digital Synthesizer)的英文缩写。与传统的频率合成器相比,DDS具有低成本、低功耗、高分辨率和快速转换时间等优点,广泛使用在电信与电子仪器领域,是实现设备全数字化的一个关键技术。DDS是一种全数字化的频率合成器,由相位累加器、波形ROM、D/A转换器和低通滤波器构成。时钟频率给定后,输出信号的频率取决于频率控制字,频率分辨率取决于累加器位数,相位分辨率取决于ROM的地址线位数,幅度量化噪声取决于ROM的数据位字长和D/A转换器位数。

8.4.2 DAC模块电路连接
这里我们以STEP BaseBoard V4.0底板上的DAC模块电路,其电路图如下:

如DAC模块电路所示,FPGA直接连接DAC081S101芯片的控制端,ADC有6个管脚,2脚VCC为VCC和Vref功能复用,即VCC = Vref。DAC后端是运放电路LMV721,运放模块为电压跟随电路,再往后端射频端子输出。
8.4.3 DAC模块驱动设计
前面我们了解DAC081S101芯片和FPGA之间连接有三根线(sync、clk、din),兼容三线SPI总线,关于SPI串行总线上节已详细介绍,这里我们直接查看DAC081S101的芯片手册。
DAC081S101管脚说明表:

注:Din信号在SCLK的节拍下传输数据,当SCLK下降沿时Din数据被锁存到移位寄存器,所以FPGA控制在上升沿更新Din数据。
DAC081S101串行通信时序如下图:

注:SCLK空闲时为低电平,CPOL = 0,上升沿(第二个边沿)采样,CPHA = 1,如果例化通用SPI核完成设计,需要采用SPI的第二种工作模式。

注: 16个时钟完成一次DAC转换,传输的16位数据,最高2位为无效数据,次2位为模式口控制数据,再次8位为DAC有效数据(DB7~DB0),最低4位为无效数据。
针对DAC081S101时序,我们用Verilog设计一个计数器,当计数器值不同时完成不同操作,实现一次DAC转换,程序实现如下:
reg [7:0] cnt;
always @(posedge clk or negedge rst_n)
if(!rst_n) cnt <= 1'b0;
else if(cnt >= 8'd34) cnt <= 1'b0;
else cnt <= cnt + 1'b1;
reg [7:0] data;
always @(posedge clk or negedge rst_n)
if(!rst_n) begin
dac_sync <= HIGH; dac_clk <= LOW; dac_dat <= LOW;
end else case(cnt)
8'd0 : begin dac_sync <= HIGH; dac_clk <= LOW; data <= dac_data; end
8'd1,8'd3,8'd5,8'd7,8'd9,8'd11,8'd13,8'd15,
8'd17,8'd19,8'd21,8'd23,8'd25,8'd27,8'd29,8'd31,
8'd33: begin dac_sync <= LOW; dac_clk <= LOW; end
8'd2 : begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= LOW; end //15
8'd4 : begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= LOW; end //14
8'd6 : begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= LOW; end //13
8'd8 : begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= LOW; end //12
8'd10: begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= data[7]; end //11
8'd12: begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= data[6]; end //10
8'd14: begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= data[5]; end //9
8'd16: begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= data[4]; end //8
8'd18: begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= data[3]; end //7
8'd20: begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= data[2]; end //6
8'd22: begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= data[1]; end //5
8'd24: begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= data[0]; end //4
8'd26: begin dac_sync <= LOW; dac_clk <= HIGH; dac_dat <= LOW; end //3
8'd28: begin dac_sync <= LOW; dac_clk <= HIGH; dac_done <= HIGH; end //2
8'd30: begin dac_sync <= LOW; dac_clk <= HIGH; dac_done <= LOW; end //1
8'd32: begin dac_sync <= LOW; dac_clk <= HIGH; end //0
8'd34: begin dac_sync <= HIGH; dac_clk <= LOW; end
default : begin dac_sync <= HIGH; dac_clk <= LOW; end
endcase
到这我们就完成了串行DAC芯片DAC081S101的驱动设计,整个采样周期用了35个系统时钟,如果我们采用12MHz时钟作为该模块系统时钟,转换率Fs = 12M / 35 = 342.86 Ksps,DAC主频Fsclk = 12 MHz / 2 = 6MHz,DAC081S101芯片手册Fsclk最高频率为30MHz,所以想要更高的转换率,可以将系统时钟的频率从12 MHz倍频到60 MHz。
模块接口如下:clk和rst_n为系统时钟及复位,dac_sync,dac_clk和dac_dat为DAC控制管脚,dac_data为DAC转换数据,dac_done脉冲对应一次DAC转换的完成。
input clk, //系统时钟
input rst_n, //系统复位,低有效
output reg dac_done, //DAC采样完成标志
input [7:0] dac_data, //DAC采样数据
output reg dac_sync, //SPI总线CS
output reg dac_clk, //SPI总线SCLK
output reg dac_dat //SPI总线MOSI