小梅哥FPGA:基于线性序列机的TLC5620型DAC驱动设计

小梅哥FPGA:基于线性序列机的TLC5620型DAC驱动设计

目标:学会使用线性序列机的思想设计常见的有串行执行特征的时序逻辑
实验现象:在QuartusⅡ软件中,使用ISSP工具,输入希望输出的电压值,则AC620开发板上,FPGA控制的TLC5620芯片输出对应的电压值

TLC5620型DAC芯片概述:

  • TLC5620C是一个具有4个独立8位电压输出型DAC的数模转换器
  • 单电源5V供电
  • 采用串行接口时序
  • 具备4个高阻抗参考电压输入端口(对应四个DAC输出通道)
  • 可编程的电压倍增模式
    每个DAC可以输出一倍或者两倍的参考电压与GND之间的电压值。
    下图为TCL5620内部框图:(一定要理解!!!
    在这里插入图片描述

TLC5620型DAC芯片引脚说明:

在这里插入图片描述
在这里插入图片描述
TLC5620的输出电压公式:
Vo(DAC A|B|C|D) = REF * CODE/256 *(1 + RNG bit value)

其中,Vo为输出电压值,REF为DAC的输出参考电压,CODE为输出电压值的数字量化量,如255表示按照参考电压的满幅输出(关闭电压倍增模式),0则0V输出,RNG bit value表示电压倍增模式,为0则关闭输出电压倍增模式,为1则打开输出电压倍增模式。

其中我们输入的Data是11位的数据,其中前两位{D10,D9}为DAC选择位,第三位D8为电压放大位,若为1则放大,若为0则不放大在这里插入图片描述

TLC 5620型DAC接口时序:

控制器对TLC5620的单个DAC设置包括两个主要操作

  • 将数字量化值以及控制位发送到TLC5620中对应的寄存器中
  • 控制DAC将寄存器中接收到的数据值更新到DAC输出上 数据的更新,使用LOAD和LDAC配合以实现。

当LOAD为高电平时,在每个CLK的下降沿,数据被移入DAC的移位寄存器中。当所有的数据位被移入完成后,LOAD被拉低,以将数据从串行输入移位寄存器中转入选中的DAC中,如下图所示:在这里插入图片描述
TLC5620串行数字接口的关键时序参数:
在这里插入图片描述

  • tsu(DATA-CLK):clk的高脉冲最小为50ns
  • tv:clk的低脉冲最小是50ns
  • tsu(clk - LOAD):从D0发送完成到LOAD拉低最少需要50ns
  • tsu(LOAD - clk):从LOAD升高到下一次发送最少需要50ns
  • tw(LOAD):LOAD从低到高最少需要250ns
  • Clk最大频率为1MHZ,意味着时钟周期最小为1000ns

我将CLK的时钟周期定为1200ns,此时tsu(DATA-CLK),tv已经满足,将其余的50ns改为60ns,250ns改为260ns

我定义一个计数器cnt来对时间进行计数(线性序列机思想)

在CLK上升沿的时候将DATA写入

注意注意:我们本章做的是产生输送给TCL5620的信号!!!!!!!所以是在上升沿将数据写入
在这里插入图片描述在这里插入图片描述

TCL5620接口逻辑的编写(代码)

我们接下来进行TCL5620接口逻辑的编写:
在这里插入图片描述

UpdateReq是开关:当按下的时候开始产生信号,当传输结束UpdateDone出现一个时钟的高电平
以下是我编写的代码:

module DAC_ctrl(
	clk,
	Rst_n,
	CtrlWord,
	UpdateReq,
	
	UpdateDone,
	TCL5620_DATA,
	TCL5620_clk,
	TCL5620_LOAD,
	TCL5620_LDAC
);
	input	clk;
	input	Rst_n;
	input[10:0]CtrlWord;
	input	UpdateReq;
	
	output reg	UpdateDone;
	output reg	TCL5620_DATA;
	output reg	TCL5620_clk;
	output reg	TCL5620_LOAD;
	output reg	TCL5620_LDAC;
	
	reg[9:0]cnt;
//计时器逻辑
	always@(posedge clk or negedge Rst_n)
	if(!Rst_n)
		cnt <= 10'd0;
	else if(UpdateReq || cnt != 10'd0)begin
		if(cnt == 10'd660)
			cnt <= 10'd0;
		else 
			cnt <= cnt +1'b1;
	end
	else 
		cnt <= 10'd0;
		
//
	always@(posedge clk or negedge Rst_n)
	if(!Rst_n)begin
		UpdateDone <= 1'b0;
		TCL5620_DATA <=1'b0;
		TCL5620_clk <=1'b0;
		TCL5620_LOAD <=1'b0;
		TCL5620_LDAC <= 1'b0;
	end
	else begin
		case(cnt)
			0:begin
				TCL5620_DATA <=1'b0;
				TCL5620_clk <=1'b0;
				TCL5620_LOAD <=1'b1;
				TCL5620_LDAC <= 1'b0;//一直为低电平
			end
			10:begin
				TCL5620_DATA <=CtrlWord[10];
				TCL5620_clk <=1'b1;
			end
			40:	TCL5620_clk <=1'b0;
			70:begin
				TCL5620_DATA <=CtrlWord[9];
				TCL5620_clk <=1'b1;
			end
			100:TCL5620_clk <=1'b0;
			130:begin
				TCL5620_DATA <=CtrlWord[8];
				TCL5620_clk <=1'b1;
			end
			160:TCL5620_clk <=1'b0;
			190:begin
				TCL5620_DATA <=CtrlWord[7];
				TCL5620_clk <=1'b1;
			end
			220:TCL5620_clk <=1'b0;
			250:begin
				TCL5620_DATA <=CtrlWord[6];
				TCL5620_clk <=1'b1;
			end
			280:TCL5620_clk <=1'b0;
			310:begin
				TCL5620_DATA <=CtrlWord[5];
				TCL5620_clk <=1'b1;
			end
			340:TCL5620_clk <=1'b0;
			370:begin
				TCL5620_DATA <=CtrlWord[4];
				TCL5620_clk <=1'b1;
			end
			400:TCL5620_clk <=1'b0;
			430:begin
				TCL5620_DATA <=CtrlWord[3];
				TCL5620_clk <=1'b1;
			end
			460:TCL5620_clk <=1'b0;
			490:begin
				TCL5620_DATA <=CtrlWord[2];
				TCL5620_clk <=1'b1;
			end
			520:TCL5620_clk <=1'b0;
			550:begin
				TCL5620_DATA <=CtrlWord[1];
				TCL5620_clk <=1'b1;
			end
			580:TCL5620_clk <=1'b0;
			610:begin
				TCL5620_DATA <=CtrlWord[0];
				TCL5620_clk <=1'b1;
			end
			640:TCL5620_clk <=1'b0;
			643:TCL5620_LOAD <=1'b0;
			656:TCL5620_LOAD <=1'b1;
			660:UpdateDone <= 1'b1;
			default:;
		endcase
	end
endmodule

testbench的编写

`timescale 1ns/1ns
`define clk_period 20

module DAC_ctrl_tb;
	reg	clk;
	reg	Rst_n;
	reg [10:0]CtrlWord;
	reg	UpdateReq;
	
	wire	UpdateDone;
	wire	TCL5620_DATA;
	wire	TCL5620_clk;
	wire	TCL5620_LOAD;
	wire	TCL5620_LDAC;
	
	DAC_ctrl DAC_ctrl(
	.clk(clk),
	.Rst_n(	Rst_n),
	.CtrlWord(CtrlWord),
	.UpdateReq(UpdateReq),
	
	.UpdateDone(UpdateDone),
	.TCL5620_DATA(TCL5620_DATA),
	.TCL5620_clk(TCL5620_clk),
	.TCL5620_LOAD(TCL5620_LOAD),
	.TCL5620_LDAC(TCL5620_LDAC)
);
	initial clk =1;
	always#(`clk_period/2)clk = ~clk;
	
	initial begin
		Rst_n = 1'b0;
		CtrlWord = 0;
		UpdateReq = 1'b0;
		#(`clk_period*100+1);
		Rst_n =1'b1;
		#(`clk_period*20);
		CtrlWord = {2'd0,1'b0,8'haa};
		UpdateReq = 1'b1;
		#(`clk_period);
		UpdateReq = 1'b0;
		@(posedge UpdateDone);
		#(`clk_period*20);
		CtrlWord = {2'd0,1'b0,8'haa};
		UpdateReq = 1'b1;
		#(`clk_period);
		UpdateReq = 1'b0;
		@(posedge UpdateDone);
		#(`clk_period*20);
		$stop;
	end
endmodule

仿真结果

在这里插入图片描述

顶层文件编写

需要建立一个ISSP的ip核来给CtrlWord提供数据

module DAC_ctrl_top(
	clk,
	Rst_n,
	
	TCL5620_DATA,
	TCL5620_clk,
	TCL5620_LOAD,
	TCL5620_LDAC
);
	input	clk;
	input	Rst_n;
	
	output 	TCL5620_DATA;
	output 	TCL5620_clk;
	output 	TCL5620_LOAD;
	output 	TCL5620_LDAC;
	
	wire[10:0]CtrlWord;
	ISSP ISSP(
					.probe(),
					.source(CtrlWord)
					);
	DAC_ctrl DAC_ctrl(
	.clk(clk),
	.Rst_n(	Rst_n),
	.CtrlWord(CtrlWord),
	.UpdateReq(1'b1),
	.UpdateDone(),
	.TCL5620_DATA(TCL5620_DATA),
	.TCL5620_clk(TCL5620_clk),
	.TCL5620_LOAD(TCL5620_LOAD),
	.TCL5620_LDAC(TCL5620_LDAC)
);
endmodule

因为没有电压表所以板机验证就不上传了,以下给出分配引脚的图片:
在这里插入图片描述

  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TLC5620是一款12位串行数字-模拟转换器,可以将数字信号转换为模拟信号。下面是基于51单片TLC5620程序设计的一些步骤: 1. 确定TLC5620的控制信号,包括数据输入信号、时钟信号和片选信号。 2. 定义51单片的I/O口,用于控制TLC5620的三个控制信号。可以使用P0口控制数据输入信号和时钟信号,使用P1口控制片选信号。 3. 初始化TLC5620的控制信号,包括将片选信号拉高,将时钟信号拉低,将数据输入信号拉低。 4. 将需要转换的数字信号按照位数分解成多个字节,每次将一个字节的数据通过数据输入信号发送给TLC5620。 5. 每发送一个字节的数据后,将时钟信号拉高再拉低,触发TLC5620进行一次转换。 6. 所有字节的数据发送完毕后,将片选信号拉低,结束转换。 下面是一个简单的51单片控制TLC5620进行数字-模拟转换的程序示例: ```C #include <reg51.h> sbit DAC_CS = P1^0; sbit DAC_CLK = P0^0; sbit DAC_DIN = P0^1; void writeDAC(unsigned int data) { unsigned char i; DAC_CS = 0; for(i=0;i<12;i++) { DAC_DIN = (data & 0x800) ? 1 : 0; data <<= 1; DAC_CLK = 1; DAC_CLK = 0; } DAC_CS = 1; } void main() { unsigned int data = 0x7ff; // 12位最大值 while(1) { writeDAC(data); data--; } } ``` 在这个示例中,我们通过P0口的第0位和第1位控制TLC5620的时钟信号和数据输入信号,通过P1口的第0位控制TLC5620的片选信号。我们定义了一个writeDAC函数,用于将一个16位的数字数据写入TLC5620进行转换。在主函数中,我们通过循环不断地将数字数据递减,并调用writeDAC函数进行转换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值