1.EP4CE10F17的DAC设计

前记:师夷长技以自强


                                                                                                                                                                                      p272

1.基本概念

DAC: Digital to Analog Conver,将数字信号转变为模拟信号的电子元件。由两个分组成,第一部分是电阻阵列,第二部分是n个电流开关(或者电压开关)。实验中使用的型号为TLV5618。

线性序列机:使用一个计数器不断计数,每个计数值根据芯片的时序对信号操作。

2.TLV5618简介

2.1.电气特性:

TLV5618是12位数字端输入2通道输出的DAC,实际控制只有3个管脚,兼容SPI接口。编程控制字有16位,其中4位控制为,12位数据位。

                                                               Terminal Functions

TERMINAL  NAME    

I/O/P DESCTRIPTION
AGND P Group
\CS I Chip select.Digital input active low,used to enable/disable inputs.
DIN I Digital serial data input
OUTA O DAC A analog voltage output
OUTB DAC B analog voltage output
REF I Analog reference voltage input
SCLK Digital serial clock input
VDD P Positive power supply

2.2电路设计

TLV5618与FPGA采用三线制SPI通信,REF端有LM4040-2.0提供,是一个专用于12位精度场合的精密参考电源。

1.EP4CE10F17的DAC设计_第1张图片

2.3输出电压计算原理

电阻网络型DAC的输出电压范围应该是0V~Vref,另外在每个DAC通道的电阻网络电压输出后级,连接了一个2倍增益放大器,则最终输出电压的范围是0V~4.096V。

                                             V_{o} =\frac{ 2*V_{REF}*CODE}{2^{12}}=\frac{2*2.048*CODE}{4096}=\frac{CODE}{1000}

2.4接口时序

接口时序有三个问题:什么时候开始传数据?每个数据什么时候移入芯片内部寄存器?什么时候所有数据位全部移完?什么时候真正开始转换而输出模拟电压?

应该什么时候给DAC传数据呢?当然是工作的时候,而什么时候工作呢?那就是\CS未低的时候。每个数据是在SCLK的下降沿被存入芯片内部寄存器的,因此应该是最后一个SCLK下降沿的上升沿后所有数据位全部移完。当\CS变为高电平时,SCLK不再影响数据芯片内部寄存器的数据,此时真正开始转换而输出模拟电压。

1.EP4CE10F17的DAC设计_第2张图片

那个输入数据的格式应该是怎么样的呢?

D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
R1 SPD PWR R0                                                                           12位数据

SPD:1-快速模式,0-低速模式

PWR:1-掉电模式,0-正常模式

芯片内部除了有DAC A和DAC B两个锁存器外,还有一个缓冲区用来辅助两个通道的同时控制。其中R1和R2就是用来控制数据输出到哪里的。

R1

R0 描述
0 写数据到DAC B和Buf
0 1 写数据到Buf
1 0 写数据到DAC A同时把缓冲区内容更新到DAC B
1 resever

3.基于线性序列机的DAC驱动设计

3.1 线性序列机思想

 在逻辑中使用一个计数器来计数,然后每个计数值就相当于在相应的时间点,在这个时间点上,各个信号需要进行什么操作直接赋值即可。这里有一个问题,DAC的工作频率如何选?通过查看芯片手册可以知道,SCLK的最大频率为20MHz,而FPGA的工作频率是50MHz,可选DAC的工作频率为12.5MHz,设置一个两倍于SCLK的采样时钟SCLK2X,使用50M系统时钟二分频即可得到SCLK2X。下面根据DAC的时序图列出芯片的线性序列机的操作表:

1.EP4CE10F17的DAC设计_第3张图片

时间点对应的信号操作表为:

计数值 对应信号状态
0 CS_N = 0;SCLK = 1;DIN = DATA[15];
1 SCLK = 0;
2 SCLK =1;DIN = DATA[14];
3 SCLK = 0;
4 SCLK =1;DIN = DATA[13];
5 SCLK = 0;
6 SCLK =1;DIN = DATA[12];
7 SCLK = 0;
8 SCLK =1;DIN = DATA[11];
SCLK = 0;
10 SCLK =1;DIN = DATA[10];
11 SCLK = 0;
12 SCLK =1;DIN = DATA[9];

13

SCLK = 0;
14 SCLK =1;DIN = DATA[8];
15 SCLK = 0;
16 SCLK =1;DIN = DATA[7];
17 SCLK = 0;
18 SCLK =1;DIN = DATA[6];
19 SCLK = 0;
20 SCLK =1;DIN = DATA[5];
21 SCLK = 0;
22 SCLK =1;DIN = DATA[4];

23

SCLK = 0;
24 SCLK =1;DIN = DATA[3];
25 SCLK = 0;
26 SCLK =1;DIN = DATA[2];
27 SCLK = 0;
28 SCLK =1;DIN = DATA[1];
29 SCLK = 0;
30 SCLK =1;DIN = DATA[0];
31 SCLK = 0;
32 SCLK = 1;
33 CS_N = 1;

3.2 DAC模块的接口设计

1.EP4CE10F17的DAC设计_第4张图片

模块端口功能描述如下

端口名称 I/O 描述
Clk I 系统时钟,50MHz
Rst_n I 系统复位信号,低电平有效
Start I 模块使能控制
Dac_data[15:0] I 控制字
Set_Done O 每次更新完成产生一个宽度为1个时钟周期的高电平脉冲
CS_N O TLV5618的片选信号
DIN O TLV5618的DIN信号
SCLK O TLV5618的SCLK信号
DAC_STATE O 0-忙碌,1-空闲

3.3 代码编写

为了辅助生成模块的输出信号,需要的内部信号有:

reg [15:0]Dac_data_r;//暂存输入的数据

reg en;//转换使能信号,标识ADC是否在工作

reg [7:0]DIV_CNT;//分频计数器

reg SCLK2X;//根据DIV_CNT生成的时钟信号

reg [5:0]SCL2X_CNT;//SCLK2X的计数器

wire Trans_done;//转换完成信号

需要注意的一点是,一次转换结束的标志是(SCL2X_CNT == 33 && SCLK2X)

module TLV5618(
	input Clk,
	input Rst_n,
	input Start,
	input [15:0]Dac_data,
	output reg Set_Done,
	output reg CS_N,
	output reg DIN,
	output reg SCLK,
	output DAC_STATE
);
	localparam DIV_PARAM = 2;//div system clock
	reg en;
	reg [15:0]Dac_data_r;
	reg [7:0]DIV_CNT;
	reg SCLK2X;
	reg [5:0]SCLK2X_CNT;
	wire Trans_done;
	
	always@(posedge Clk,negedge Rst_n)//en
	if(!Rst_n)
		en <= 0;
	else if(Start)
		en <= 1;
	else if(Set_Done)
		en <= 0;
	else 
		en <= en;
	
	always@(posedge Clk,negedge Rst_n)//DIV_CNT
	if(!Rst_n)
		DIV_CNT <= 0;
	else if(en)
		if(DIV_CNT == DIV_PARAM - 1)
			DIV_CNT <= 0;
		else
			DIV_CNT <= DIV_CNT + 8'b1;
	else 
		DIV_CNT <= 0;
		
	always@(posedge Clk,negedge Rst_n)//SCLK2X
	if(!Rst_n)
		SCLK2X <= 0;
	else if(en&&(DIV_CNT == (DIV_PARAM - 1)))
		SCLK2X <= 1;
	else 
		SCLK2X <= 0;
		
	always@(posedge Clk,negedge Rst_n)//SCLK2X_CNT
	if(!Rst_n)
		SCLK2X_CNT <= 0;
	else if(en&&SCLK2X)
		if(SCLK2X_CNT == 6'd33)
			SCLK2X_CNT <= 0;
		else
			SCLK2X_CNT <= SCLK2X_CNT + 6'b1;
	else
		SCLK2X_CNT <= SCLK2X_CNT;
		
	always@(posedge Clk,negedge Rst_n)
	if(!Rst_n)begin
		SCLK <= 1;
		DIN <= 1;
		CS_N <= 1;
		Dac_data_r <= 0;
	end
	else if(!Set_Done&&SCLK2X)begin
		case(SCLK2X_CNT)
			0:
				begin
					SCLK <= 1;
					DIN <= Dac_data_r[15];
					Dac_data_r <= Dac_data_r << 1;
					CS_N <= 0;
				end
			1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31:
				begin
					SCLK <= 0;
				end
			2,4,6,8,10,12,14,16,18,20,22,24,26,28,30:
				begin
					SCLK <= 1;
					DIN <= Dac_data_r[15];
					Dac_data_r <= Dac_data_r << 1;
				end
			32:SCLK <= 1;
			33:CS_N <= 1;
			default:;
		endcase
	end
	else if(Start)
		Dac_data_r <= Dac_data;
	
	assign Trans_done = (SCLK2X_CNT == 33)&&SCLK2X;
	
	always@(posedge Clk,negedge Rst_n)
	if(!Rst_n)
		Set_Done <= 0;
	else if(Trans_done)
		Set_Done <= 1;
	else
		Set_Done <= 0;
		
   assign DAC_STATE = !en;
endmodule

3.4仿真测试

`timescale 1ns/1ns
`define period 20

module TLV5618_tb;
	reg Clk;
	reg Rst_n;
	reg Start;
	reg [15:0]Dac_data;
	wire set_Done;
	wire CS_N;
	wire DIN;
	wire SCLK;
	wire DAC_STATE;
	TLV5618 TLV5618_1(
		.Clk(Clk),
		.Rst_n(Rst_n),
		.Start(Start),
		.Dac_data(Dac_data),
		.Set_Done(set_Done),
		.CS_N(CS_N),
		.DIN(DIN),
		.SCLK(SCLK),
		.DAC_STATE(DAC_STATE)
	);
	
	initial Clk <= 0;
	always #10 Clk <= ~ Clk;
	
	initial begin
		Rst_n = 0;
		Start = 0;
		Dac_data = 0;
		#`period;
		Rst_n = 1;
		#`period;
		Dac_data = 16'hC_AAA;
		Start = 1;
		#`period;
		Start = 0;
		#200
		wait(set_Done);
		#20000;
		Dac_data = 16'h4_555;
		Start = 1;
		#`period;
		Start = 0;
		#200;
		wait(set_Done);
		$stop;
	end
endmodule

全局图

1.EP4CE10F17的DAC设计_第5张图片

局部图

1.EP4CE10F17的DAC设计_第6张图片

你可能感兴趣的:(FPGA)