OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 10308|回复: 25

小梅哥和你一起深入学习FPGA之DAC驱动

[复制链接]

40

主题

177

帖子

0

精华

高级会员

Rank: 4

积分
921
金钱
921
注册时间
2013-10-23
在线时间
94 小时
发表于 2014-11-25 16:22:50 | 显示全部楼层 |阅读模式
 本实验中,我们使用FPGA来驱动了一片DAC芯片TLC5620,该芯片的特性如下所示:  

 

TLC5620特性:

48位电压输出;

单电源5V供电;

串行接口;

参考电压输入高阻;

可编程的1次或2次输出范围;

同时更新的能力;

内部自带上电复位功能;

低功耗;

半缓冲输出。

 

小梅哥设计的该芯片的驱动模块的接口如下所示:



各个端口定义如下:

     input Clk;

     input Rst_n;

     input Do_DA;   /*使能单次转换*/

     input [10:0]Data;/*{Addr1,Addr0,Range,Data_bit[7:0]}*/

    

     output reg DAC_Dout;    /*DAC数据线*/

     output reg DAC_Clk;        /*DAC时钟线,最高速度1M*/

     output reg DAC_LDAC;   /**/

     output reg DAC_LOAD;   /**/

    

     output reg DA_Done;      /*单次转换完成标志信号*/

 

该芯片提供了类似于SPI的数字接口,因此,我们只需要使用该接口与芯片进行通信,再配合LOADLDAC两个控制线,即可实现对该DAC芯片的控制。TLC5620一次转换的操作时序如下:

 

1  TLC5620单次转换时序图

 

TLC5620每次写入的数据为11位,其中前两位为DAC选择位A1A0,通过不同的组合可以选择不同通道的DAC,具体分配为:

 

A1

A0

DAC通道

0

0

DACA

0

1

DACB

1

0

DACC

1

1

DACD



1  DAC通道选择位与对应通道关系

 

第三位是电压输出增益位,0代表不变,1代表两倍,当设定参考电压为2.5V时,取这一位为1就可以得到最高5V的输出电压。后面8位是数据位,其中第四位是数据的最高位。对于TLC5620的输出电压公式是:

VOVREF ×CODE/256×(1+RNG

VREF是参考电压,CODE是待转换的8位二进制代码,RNG是增益倍数。

 

写入数据时,首先LOADLDAC写高电平,这样在CLK的每个下降沿写入的每位数据被锁存到DATA端,当11位数据传送完毕后,拉低LOAD,芯片根据前两位数据,判断是哪一路DAC通道,然后将8位数据移入相应的通道,进行DA转换,这时拉低LDAC,再拉高LDAC,就可以再下次转化之前,保持此次的模拟输出。

TLC5620正常工作时的具体电压和时间参数如下表所示,通过该表,可知该芯片串行数字接口的时钟信号(CLK)最高为1MHz。该参数将作为我们采用FPGA产生TLC5620数字接口时钟的依据。同时,还有输入数据建立时间tsu(data-clk)50ns,即,FPGA数据送出,到能够被TLC5620正常读取,至少需要50ns,因此FPGA单位数据输出保持时间不得少于50nstv(data-clk)为时钟下降沿到来后多久时间数据线上的数据才能被芯片内部采集,该时间确定了,时钟下降沿出现多久后,数据线上的数据可以被更新。tsu(LOAD-LDAC)LOAD的上升沿到LDAC下降沿的建立时间,这里最小为0ns,因此忽略,即两者同时发生即可。tw(LDAC)LDAC低电平所需的最短时间,为250ns

2  TLC5620关键参数

 

通过对TLC5620一次完整转换的时序进行分析,列出以下序列机对应的序列点:该序列机总共包含26个点,其中,当Cnt1=0ST0)时,为空闲态,ST1ST22为数据发送状态,ST23时拉低LOAD,即将数据加载入对应通道的DAC中,ST24时释放LOAD,同时拉低LDAC,以产生LDAC的下降沿,将对应通道的模拟输出保持住。ST25拉高LDAC,完成一次转换。

 

ST0

Cnt1 == 0

DAC_Dout = 1; DAC_Clk = 0; DAC_LOAD = 1; DAC_LDAC = 1; DA_Done = 1;

ST1

Cnt1 == 1

DAC_Dout = Data_r[10]; DAC_Clk = 1; DA_Done = 0;

ST2

Cnt1 == 2

DAC_Clk = 0;

ST3

Cnt1 == 3

DAC_Dout = Data_r[9]; DAC_Clk = 1;

ST4

Cnt1 == 4

DAC_Clk = 0;

ST5

Cnt1 == 5

DAC_Dout = Data_r[8]; DAC_Clk = 1;

ST6

Cnt1 == 6

DAC_Clk = 0;

ST7

Cnt1 == 7

DAC_Dout = Data_r[7]; DAC_Clk = 1;

ST8

Cnt1 == 8

DAC_Clk = 0;

ST9

Cnt1 == 9

DAC_Dout = Data_r[6]; DAC_Clk = 1;

ST10

Cnt1 == 10

DAC_Clk = 0;

ST11

Cnt1 == 11

DAC_Dout = Data_r[5]; DAC_Clk = 1;

ST12

Cnt1 == 12

DAC_Clk = 0;

ST13

Cnt1 == 13

DAC_Dout = Data_r[4]; DAC_Clk = 1;

ST14

Cnt1 == 14

DAC_Clk = 0;

ST15

Cnt1 == 15

DAC_Dout = Data_r[3]; DAC_Clk = 1;

ST16

Cnt1 == 16

DAC_Clk = 0;

ST17

Cnt1 == 17

DAC_Dout = Data_r[2]; DAC_Clk = 1;

ST18

Cnt1 == 18

DAC_Clk = 0;

ST19

Cnt1 == 19

DAC_Dout = Data_r[1]; DAC_Clk = 1;

ST20

Cnt1 == 20

DAC_Clk = 0;

ST21

Cnt1 == 21

DAC_Dout = Data_r[0]; DAC_Clk = 1;

ST22

Cnt1 == 22

DAC_Clk = 0;

ST23

Cnt1 == 23

DAC_LOAD = 0;

ST24

Cnt1 == 24

DAC_LOAD = 1; DAC_LDAC = 0;

ST25

Cnt1 == 25

DAC_LDAC = 1; DA_Done = 1;

3  TLC5620单次转换控制序列机

 

序列机的计数器计数条件如下,

Cnt_state == 0 | Cnt1 == 25

Cnt1 <= 0;

Cnt_state == 1 &  Cnt1 < 25

Cnt1 <= Cnt1 + 1’b1

4  TLC5620序列机计数器计数条件

线性序列机计数器Cnt1的控制代码如下:

   

always @(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		Cnt1 <= 5'd0;
	else if(Cnt_State == DO_CNT)
	begin
		if(Cnt1 == 5'd25)
			Cnt1 <= 5'd0;
		else if(Cnt2 == Cnt2_Top)
			Cnt1 <= Cnt1 + 1'b1;
		else
			Cnt1 <= Cnt1;	
	end
	else
		Cnt1 <= 5'd0;
[/mw_shl_code]
	


 

其中,涉及到了两个状态,当Cnt_State = 0时,表示没有转换请求,即系统处于空闲状态,DAC不工作,当外部有转换请求时,则系统进入转换状态,每当计数使能信号到来时,Cnt1自加一,当Cnt1=25后,表明一次转换完成,将计数器清零,同时状态跳回空闲态,等待下一次使能信号的到来。具体的状态转移图如下所示:


2  系统状态转移图

该状态机的代码对应如下:

localparam 	IDEL = 1'b0,
	        DO_CNT	= 1'b1;

	always @(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		Cnt_State <= IDEL;
	else
	begin
		case(Cnt_State)
			IDEL:
				if(Do_DA)
					Cnt_State <= DO_CNT;
				else
					Cnt_State <= IDEL;
			
			DO_CNT:
				if(Cnt1 == 5'd25)
					Cnt_State <= IDEL;
				else
					Cnt_State <= DO_CNT;
			default:;
		endcase	
	end
[/mw_shl_code]
		


因此,我们,只需要将Do_DA给出1个时钟周期的高脉冲,即可启动一次转换。同时,在检测到该脉冲时,模块内部会将数据端口Data上的数据读入到内部数据寄存器中,代码如下:

         

	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		Data_r <= 10'd0;
	else if(Do_DA)
		Data_r <= Data;
	else
		Data_r <= Data_r;
[/mw_shl_code]
			

同时,为了产生1MHz的时钟,系统中使用了一个计数器Cnt2来专门产生该信号,该计数器对系统时钟进行计数,如当系统时钟为50M(周期为20ns)时,Cnt2计数到24,即计数了500ns,产生一个时钟周期的标志信号,则Cnt1在检测到这个标志信号后,便会自加1,因此,该标志信号出现两次则表明计时1000ns,对应时钟频率为1Mhz,即DAC芯片数字接口的时钟频率。该部分代码如下:

         always @ (posedge Clk or negedge Rst_n)

         if(!Rst_n)

                   Cnt2 <= 5'd0;

         else if(Cnt_State == DO_CNT)

         begin

                   if(Cnt2 == Cnt2_Top)

                            Cnt2 <= 5'd0;

                   else

                            Cnt2 <= Cnt2 + 1'b1;       

         end

         else

                   Cnt2 <= 5'd0;

 

为了兼容不同的系统时钟,这里采用参数化定制,得出对应的计数最大值,具体代码如下:

         Localparam   system_clk = 50_000_000;     /*系统时钟*/

         Localparam   Cnt2_Top = system_clk / 1_000_000 / 2 - 1;  /*500ns技术器计数最大值*/

系统时钟设置为50M,则计数最大值为50000000/1000000/2 – 1 = 24,当系统时钟改变后,只需要修改system_clk的值,即可保证Cnt2计数一次的时间为500ns

 

最后,附上主序列中的操作代码:

 

always@(posedge Clk or negedge Rst_n)

         if(!Rst_n)

         begin

                   DAC_Dout <= 1;

                   DAC_Clk <= 0;

                   DAC_LOAD <= 1;

                   DAC_LDAC <= 1;

                   DA_Done <= 1;        

         end

         else

         begin

                   case(Cnt1)

                            0:

                                     begin

                                               DAC_Dout <= 1;

                                               DAC_Clk <= 0;

                                               DAC_LOAD <= 1;

                                               DAC_LDAC <= 1;

                                               DA_Done <= 1;        

                                     end

                            1:begin DAC_Dout <= Data_r[10]; DAC_Clk <= 1;DA_Done <= 0;end

                            2AC_Clk <= 0;

                            3:begin DAC_Dout <= Data_r[9]; DAC_Clk <= 1;end

                            4AC_Clk <= 0;

                            5:begin DAC_Dout <= Data_r[8]; DAC_Clk <= 1;end

                            6AC_Clk <= 0;

                            7:begin DAC_Dout <= Data_r[7]; DAC_Clk <= 1;end

                            8AC_Clk <= 0;

                            9:begin DAC_Dout <= Data_r[6]; DAC_Clk <= 1;end

                            10AC_Clk <= 0;

                            11:begin DAC_Dout <= Data_r[5]; DAC_Clk <= 1;end

                            12AC_Clk <= 0;

                            13:begin DAC_Dout <= Data_r[4]; DAC_Clk <= 1;end

                            14AC_Clk <= 0;

                            15:begin DAC_Dout <= Data_r[3]; DAC_Clk <= 1;end

                            16AC_Clk <= 0;

                            17:begin DAC_Dout <= Data_r[2]; DAC_Clk <= 1;end

                            18AC_Clk <= 0;

                            19:begin DAC_Dout <= Data_r[1]; DAC_Clk <= 1;end

                            20AC_Clk <= 0;

                            21:begin DAC_Dout <= Data_r[0]; DAC_Clk <= 1;end

                            22:DAC_Clk <= 0;

                            23:DAC_LOAD <= 0;

                            24:begin DAC_LOAD <= 1; DAC_LDAC <= 0; end

                            25:begin DAC_LDAC <= 1; DA_Done <= 1; end

                            default:;

                   endcase                     

         end

 

该设计的仿真结果如下如所示:

 

 

由该仿真结果可知,时钟频率为1MHz,满足芯片工作要求,其它时序均与手册给出的时序保持一致。为了设计简洁,这里将LOADLDAC的低电平脉冲时间都设置为了500ns,而非最小时间250ns,这里主要是为了方便序列机的设计。当然,如此设计在一定程度上会影响DAC 的转换速率,不过在大多数应用场合已经足够,如需更加高效的设计,只需要对代码稍加修改即可。

 

本驱动的testbench编写较为简单,这里只附上对应代码,不做详细解释:

`timescale 1ns/1ns

 

module TLC5620_Driver_tb;

 

         reg Clk;

         reg Rst_n;

         reg Do_DA;      /*使能单次转换*/

         reg [10:0]Data;/*{Addr1,Addr0,Range,Data_bit[7:0]}*/

        

         wire DAC_Dout;       /*DAC数据线*/

         wire DAC_Clk; /*DAC时钟线,最高速度1M*/

         wire DAC_LDAC;      /**/

         wire DAC_LOAD;     /**/

        

         wire DA_Done;         /*单次转换完成标志信号*/

        

         TLC5620_Driver u1(

                   .Clk(Clk),

                   .Rst_n(Rst_n),

                   .Do_DA(Do_DA),

                   .Data(Data),

                   .DAC_Dout(DAC_Dout),

                   .DAC_Clk(DAC_Clk),

                   .DAC_LDAC(DAC_LDAC),

                   .DAC_LOAD(DAC_LOAD),

                   .DA_Done(DA_Done)

         );

        

         initial begin

                   Clk = 1;

                   Rst_n = 0;

                   Do_DA = 0;

                   Data = 11'd0;

                   #200;

                   Rst_n = 1;

                   #400;

                   Data = 11'b110_1011_1001;

                   Do_DA = 1;

                   @(posedge DA_Done)

                   Data = 11'b110_0000_1111;

                   #20

                   Do_DA = 1;

                   #20;

                   Do_DA = 0;

                   @(posedge DA_Done)

                   Data = 11'b110_1111_0000;

                   #20

                   Do_DA = 1;

                   #20;

                   Do_DA = 0;

                   @(posedge DA_Done)

                   #400;

                   $stop;      

         end 

        

         always #10 Clk = ~Clk;

        

endmodule

 

因为时间关系,这里只开发了该芯片的驱动,并用modelsim对该驱动进行了仿真,详细的调试和应用,小梅哥将在下一个实验中介绍。 

http://xiaomeige.taobao.com。做最用心的FPGA学习板和教程资料
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2014-11-25 16:37:48 | 显示全部楼层
不错,谢谢分享。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

4

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
148
金钱
148
注册时间
2013-1-11
在线时间
12 小时
发表于 2014-11-25 17:22:17 | 显示全部楼层
对了, 问下楼主是否学了nios ii 啊?
回复 支持 反对

使用道具 举报

40

主题

177

帖子

0

精华

高级会员

Rank: 4

积分
921
金钱
921
注册时间
2013-10-23
在线时间
94 小时
 楼主| 发表于 2014-11-25 17:51:52 | 显示全部楼层
回复【3楼】xiao4ck:
---------------------------------
这个自然学了
http://xiaomeige.taobao.com。做最用心的FPGA学习板和教程资料
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
6
金钱
6
注册时间
2016-2-10
在线时间
1 小时
发表于 2016-3-12 17:02:17 | 显示全部楼层
可以可以
回复 支持 反对

使用道具 举报

6

主题

40

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
215
金钱
215
注册时间
2015-7-26
在线时间
36 小时
发表于 2016-3-28 09:40:24 | 显示全部楼层
很好啊
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2016-4-6
在线时间
0 小时
发表于 2016-4-6 23:48:36 | 显示全部楼层
*高速并行ADC的驱动开发;(AD9280)这个在哪下啊
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
69
金钱
69
注册时间
2016-2-28
在线时间
22 小时
发表于 2016-4-16 15:11:31 | 显示全部楼层
楼主,想你了
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2016-5-4
在线时间
0 小时
发表于 2016-5-4 20:31:26 | 显示全部楼层
kanknale
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2016-5-4
在线时间
0 小时
发表于 2016-5-4 20:31:37 | 显示全部楼层
看看了
回复 支持 反对

使用道具 举报

1

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2012-11-29
在线时间
11 小时
发表于 2016-5-11 11:31:02 | 显示全部楼层
要恢复才能看吗
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
8
金钱
8
注册时间
2016-6-1
在线时间
1 小时
发表于 2016-6-1 16:08:42 | 显示全部楼层
怎么看
回复 支持 反对

使用道具 举报

2

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2015-4-6
在线时间
14 小时
发表于 2016-6-3 09:47:29 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

35

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
362
金钱
362
注册时间
2014-7-30
在线时间
49 小时
发表于 2016-7-11 17:12:14 | 显示全部楼层
噢噢,看看
回复 支持 反对

使用道具 举报

35

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
362
金钱
362
注册时间
2014-7-30
在线时间
49 小时
发表于 2016-7-11 17:12:56 | 显示全部楼层
怎么找不到额,只见标题,哪里能下载额
我就是我,是颜色不一样的烟火。
回复 支持 反对

使用道具 举报

0

主题

9

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
304
金钱
304
注册时间
2016-5-25
在线时间
42 小时
发表于 2016-8-9 10:02:58 | 显示全部楼层
谢谢学习
回复 支持 反对

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

积分
29
金钱
29
注册时间
2010-12-24
在线时间
0 小时
发表于 2016-9-19 08:37:13 | 显示全部楼层
看看吸收下
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
4
金钱
4
注册时间
2017-7-13
在线时间
0 小时
发表于 2017-7-13 22:28:26 | 显示全部楼层
kankan
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
4
金钱
4
注册时间
2017-7-13
在线时间
0 小时
发表于 2017-7-13 22:28:56 | 显示全部楼层
怎么看不到呢
回复 支持 反对

使用道具 举报

70

主题

231

帖子

0

精华

高级会员

Rank: 4

积分
976
金钱
976
注册时间
2013-8-14
在线时间
103 小时
发表于 2017-7-23 09:44:40 | 显示全部楼层
回复了,但是没有内容啊??
谢谢!
回复 支持 反对

使用道具 举报

2

主题

4

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2016-12-1
在线时间
10 小时
发表于 2017-7-27 11:12:48 | 显示全部楼层
dghdghfhgdfghdfhdgdfhgh
回复 支持 反对

使用道具 举报

1

主题

2

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2011-11-18
在线时间
5 小时
发表于 2017-8-3 10:28:34 | 显示全部楼层
学习学习!!!!
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
14
金钱
14
注册时间
2017-8-3
在线时间
4 小时
发表于 2017-8-3 17:24:02 | 显示全部楼层
学习学习
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
7
金钱
7
注册时间
2019-3-17
在线时间
0 小时
发表于 2019-3-17 09:37:16 | 显示全部楼层
看看,学习学习
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2019-1-24
在线时间
5 小时
发表于 2019-3-17 19:53:32 | 显示全部楼层
学习一下一下。。
回复 支持 反对

使用道具 举报

4

主题

13

帖子

0

精华

新手上路

积分
27
金钱
27
注册时间
2019-3-11
在线时间
4 小时
发表于 2019-3-21 09:13:56 | 显示全部楼层
什么内容也看不到啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 10:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表