DAC-TLC5620

前言

        之前做的dds信号发生器,输出的是数字量数据,如果需要实际使用产生的信号,则需要DA转换,就是数字量到模拟量的转换。Digital-Analog-Converter,数字模拟转换器。

正文

一、DAC的设计验证

        1.项目需求

        对dds信号发生器产生的数据通过DA芯片转换为模拟量(电压)。

之前dds信号发生器完成,幅度调节,相位调节,频率调节。这里使用的DA芯片为TLC5620,其特点为:

        4通道8位da转换器

        采用串行接口的数据输入

        输出电压范围参考电压和地之间1-2倍的范围

        命令字节11bit:数据格式2bit通道选择+1bit范围+8bit数据

        高位在前(msb)

数据在da clk的下降沿移入到串行接口寄存器(fpga发数据在da clk 的上升沿)

        load:高电平时没有数据更新,当ldac为低电平时,拉低load信号输出就会更新

        ldac:拉低ldac信号输出就可以更新

两种更新方式:

        (1)先拉低load信号,再拉低ldac信号(2)ldac信号一直为低电平,拉低load就可以更新

两种传输方式:

        (1)一次性传输11bit数据(2)分两个8时钟周期传输,第一个传输通道选择和范围,第二个传输数据

这里使用的为一次性11bit数据传输:

        2.技术介绍

        由上传输时序图和对应的时刻对应表可知,clk是1Mhz时钟但在传输完11bit数据的最后一位后一直拉低,直到下次数据传输,传输完11bit数据的最后一位后,先拉低load信号,再拉低ldac信号。

        由于需要的clk不连续,所以之前使用的状态机不适用于该工程。

        这里提出一种新的写法:序列机(相当于时钟树(可以理解为闹铃,告诉你在什么时刻该干什么)),我们使用的系统时钟为50Mhz,ad_clk为1Mhz = 1000ns = 50个clk周期,共需要11个周期,50*11 = 25*22,传输完数据后拉低250ns的load信号,这里使用20*13 = 260ns,再拉低ldac信号。把时序表列出来:

rst_ncnt= 0ad_clk  = 0,ad_data = 0,ad_load = 1,ad_ldac = 1
0ad_clk  = 0,ad_data = 0,ad_load = 1,ad_ldac = 1
1ad_clk  = 1,ad_data = data_in[10]
1+25*1ad_clk  = 0
1+25*2ad_clk  = 1,ad_data = data_in[9]
......
1+25*20da_clk=1   da_data=data_in[0]
1+25*21da_clk=0
1+25*22da_load = 0
1+25*22+13da_load=1   da_ldac=0
1+25*21+13+13da_ldac=1

        3.顶层架构

这里直接使用RTL视图了:

        4.端口描述

        通过芯片手册,可以看出在该DA芯片中有2级寄存器,LOAD管理前寄存,LDAC管理后寄存,当两个信号拉低时数据才能进入DAC转换模块。在这里简称LOAD为前寄存,LDAC为后寄存。

clk50Mhz
data_in[10:0]模拟量输入
rst_n复位
ad_clk1Mhz断续信号
data数字量输出
laod前寄存
laod后寄存

二、代码验证

        DAC芯片控制模块

module da_ctrl(
	input				clk		,//50Mhz
	input				rst_n		,
	input [10:0]	data_in	,
	
	output 	reg	data    	,
	output	reg	laod		,//前锁存
	output	reg	ldac		,//后锁存
	output 	reg	ad_clk	 //1Mhz
);
	
	reg [09:0]time_cnt;//总计时器
	reg [10:0]data_pa;//输入寄存器	
	
	always@(posedge clk,negedge rst_n)//输入寄存确保数据完整
	begin
		if(!rst_n)
			data_pa <= 0;
		else if(time_cnt == 0)
			data_pa <= data_in;
		else
			data_pa <= data_pa;	
	end
	
	always@(posedge clk,negedge rst_n)//计时器驱动
	begin
		if(!rst_n)
			time_cnt <= 0;
		else
			time_cnt <= time_cnt + 1;
	end
	
	always@(posedge clk,negedge rst_n)
	begin
		if(!rst_n)
			begin
				ad_clk<= 0;
				data  <= 0;
				laod	<= 1;
				ldac	<= 1;
			end
		else
			case(time_cnt)
				0:
					begin
						ad_clk<= 0;
						data  <= 0;
						laod	<= 1;
						ldac	<= 1;
					end
				1:
					begin
						ad_clk<= 1;
						data  <= data_pa[10];
					end
				1+25*1:
					ad_clk<= 0;
				1+25*2:
					begin
						ad_clk<= 1;
						data  <= data_pa[9];
					end
				1+25*3:
					ad_clk<= 0;
				1+25*4:
					begin
						ad_clk<= 1;
						data  <= data_pa[8];
					end
				1+25*5:
					ad_clk<= 0;
				1+25*6:
					begin
						ad_clk<= 1;
						data  <= data_pa[7];
					end
				1+25*7:
					ad_clk<= 0;
				1+25*8:
					begin
						ad_clk<= 1;
						data  <= data_pa[6];
					end
				1+25*9:
					ad_clk<= 0;
				1+25*10:
					begin
						ad_clk<= 1;
						data  <= data_pa[5];
					end
				1+25*11:
					ad_clk<= 0;
				1+25*12:
					begin
						ad_clk<= 1;
						data  <= data_pa[4];
					end
				1+25*13:
					ad_clk<= 0;
				1+25*14:
					begin
						ad_clk<= 1;
						data  <= data_pa[3];
					end
				1+25*15:
					ad_clk<= 0;
				1+25*16:
					begin
						ad_clk<= 1;
						data  <= data_pa[2];
					end
				1+25*17:
					ad_clk<= 0;
				1+25*18:
					begin
						ad_clk<= 1;
						data  <= data_pa[1];
					end
				1+25*19:
					ad_clk<= 0;
				1+25*20:
					begin
						ad_clk<= 1;
						data  <= data_pa[0];
					end
				1+25*21:
					ad_clk<= 0;
				1+25*22:
					laod<= 0;
				1+25*22+13:
					begin
						laod<= 1;
						ldac<= 0;
					end
				1+25*22+13+13:
					ldac<= 1;
					
			endcase
	end
	
endmodule

        仿真模块

`timescale 1ns/1ps
module da_ctrl_tp;
	reg		clk		;//50Mhz
	reg		rst_n		;
	reg[10:0]data_in	;

	wire		data    	;
	wire		laod		;//前锁存
	wire		ldac		;//后锁存
	wire		ad_clk	;//1Mhz

	da_ctrl da_ctrl(
		.clk		(clk		),//50Mhz
		.rst_n	(rst_n	),
		.data_in	(data_in	),
	     
		.data    (data    ),
		.laod		(laod		),//前锁存
		.ldac		(ldac		),//后锁存
		.ad_clk	(ad_clk	) //1Mhz
	);
	
	always #10 clk = ~clk;
	initial begin
		clk = 1;
		rst_n = 0;
		#30;
		rst_n = 1;
		data_in = 11'b110_0101_1001;
		#100000;
		$stop;
	end
	
	
endmodule

三、仿真验证

        1Mhz的ad_clk生成正确:

        260ns的laod,ldac产生正确

        后续需要将dds与该模块连接,通过示波器观察da芯片的对应输出通道,验证功能是否完全

参考资料

TLC5620芯片手册(本地文件,如有需要,私信即可)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张明阳.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值