概述
目录
step1:查询器件手册,了解TLV5618基本信息。
step2:引脚功能及输出电压范围
step3 16位控制字数据格式
step4 接口时序
step5 系统框图
step6 verilog代码
step7 testbench
step8 仿真结果
DAC(Digital to Analog Conver),即数模转换器D/A,简称ADC,是指将数字信号转变为模拟信号的电子元件。
step1:查询器件手册,了解TLV5618基本信息。
TLV5618是一个基于电压输出型的双通道 的12 位单电源数模转换器,其由串行接口、一个速度和电源控制器、 电阻网络、2 倍增益的输出缓冲器组成。
TLV5618 使用 CMOS 电平兼容的三线制SPI串行总线与各种处理器进行连接,接收控制器发送的 16 位的控制字,这 16 位的控制字被分为 2 个部分,包括 4 位的编程位,12 位的数据位。
step2:引脚功能及输出电压范围
TLV5618 的参考电压由 LM4040-2.0 提供,LM4040-2.0 是一个专用于12 位精度场合的精密参考源,输出电压为 2.048V。
TLV5618芯片实际输出电压范围为0~2*VREF。在AC620开发板上,对应为0~4.096V。当芯片上电时,DAC 的值全部被复位到0。每个 DAC 通道的输出可由下列公式计算得出:
其中,REF 是基准电压,本电路中为 2.048V;CODE 是数字电压输入值,范围 0 到2^12 - 1。
step3 16位控制字数据格式
step4 接口时序
step5 系统框图
step6 verilog代码
module tlv5618(
input sys_clk_i,//50M
input ext_Rst_n,
input start_en,//模块使能信号
input [15:0]DAC_DATA,//控制器控制字
output reg DAC_DIN,//TLV5618的DAC_DIN接口
output reg DAC_SCLK,//TLV5618的DAC_SCLK接口,不高于20M设置12.5M
output reg DAC_CS_N,//TLV5618的DAC_CS_N接口
output reg set_done,//更新DAC完成标志,1表示完成
output DAC_state//模块状态表示,1表示空闲,0表示忙碌
);
assign DAC_state = DAC_CS_N;//开始工作DAC_CS_N为0
reg [1:0]div_cnt;//25M分频计数器
parameter cnt_max = 2;
reg en;
wire trans_done; //转换序列完成标志信号
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
en <= 1'b0;
else if(start_en)
en <= 1'b1;
else if(trans_done)
en <= 1'b0;
else en <= en;
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
div_cnt <= 2'd0;
else if(en) begin
if(div_cnt< 1'b1)
div_cnt <= div_cnt +1'b1;
else
div_cnt <= 2'd0;end
else
div_cnt <= 2'd0;
reg SCLK2x;//25M时钟信号
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
SCLK2x <= 1'b0;
else if(en && (div_cnt == 2'd1))
SCLK2x <= 1'b1;
else
SCLK2x <= 1'b0;
/*25M信号的第二种写法
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
div_cnt <= 2'd0;
else if(start_en) begin
if(div_cnt<= 2'd0)
div_cnt <= 2'd0;
else
div_cnt <= 2'd0;end
else
div_cnt <= 2'd0;
reg SCLK2x;//25M时钟信号
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
SCLK2x <= 1'b0;
else if(div_cnt == 2'd0)
SCLK2x <= ~SCLK2x;
else
SCLK2x <= SCLK2x;
*/
/*12.5M信号的写法
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
div_cnt <= 2'd0;
else if(start_en) begin
if(div_cnt< 2'd1)
div_cnt <= div_cnt +1'b1;
else
div_cnt <= 2'd0;end
else
div_cnt <= 2'd0;
reg SCLK2x;//25M时钟信号
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
SCLK2x <= 1'b0;
else if(div_cnt == 2'd1)
SCLK2x <= ~SCLK2x;
else
SCLK2x <= SCLK2x;
*/
reg [5:0]SCLK2x_num;
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
SCLK2x_num <= 6'd0;
else if(en&&SCLK2x) begin
if(SCLK2x_num <= 6'd32)
SCLK2x_num <= SCLK2x_num +1'b1;
else SCLK2x_num <= 6'd0;end
else
SCLK2x_num <= SCLK2x_num;
/*计数至33,33自加一清0(此时en和sclk的有效信号最后一次被采集),
此后,en无效,div_cnt不计数,sclk2x保持为0*/
reg [15:0]r_DAC_DATA;
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
r_DAC_DATA <= 16'd0;
else if(start_en)
r_DAC_DATA <= DAC_DATA;//收到开始发送命令时,寄存DAC_DATA值
else
r_DAC_DATA <= r_DAC_DATA;
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)begin
DAC_DIN <= 1'b1;//空闲拉高
DAC_SCLK <= 1'b0;
DAC_CS_N <= 1'b1;//空闲拉高
end
else if(!set_done&&SCLK2x)begin
case(SCLK2x_num)
0:begin
DAC_DIN <=r_DAC_DATA[15];
DAC_SCLK <=1'b1;
DAC_CS_N <=1'b0;//空闲拉高
end
1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31: DAC_SCLK <=1'b0;
2:begin DAC_DIN <=r_DAC_DATA[14];DAC_SCLK <= 1'b1;end
4:begin DAC_DIN <=r_DAC_DATA[13];DAC_SCLK <= 1'b1;end
6:begin DAC_DIN <=r_DAC_DATA[12];DAC_SCLK <= 1'b1;end
8:begin DAC_DIN <=r_DAC_DATA[11];DAC_SCLK <= 1'b1;end
10:begin DAC_DIN <=r_DAC_DATA[10];DAC_SCLK <= 1'b1;end
12:begin DAC_DIN <=r_DAC_DATA[9];DAC_SCLK <= 1'b1;end
14:begin DAC_DIN <=r_DAC_DATA[8];DAC_SCLK <= 1'b1;end
16:begin DAC_DIN <=r_DAC_DATA[7];DAC_SCLK <= 1'b1;end
18:begin DAC_DIN <=r_DAC_DATA[6];DAC_SCLK <= 1'b1;end
20:begin DAC_DIN <=r_DAC_DATA[5];DAC_SCLK <= 1'b1;end
22:begin DAC_DIN <=r_DAC_DATA[4];DAC_SCLK <= 1'b1;end
24:begin DAC_DIN <=r_DAC_DATA[3];DAC_SCLK <= 1'b1;end
26:begin DAC_DIN <=r_DAC_DATA[2];DAC_SCLK <= 1'b1;end
28:begin DAC_DIN <=r_DAC_DATA[1];DAC_SCLK <= 1'b1;end
30:begin DAC_DIN <=r_DAC_DATA[0];DAC_SCLK <= 1'b1;end
32: DAC_SCLK <= 1'b1;
33: DAC_CS_N <=1'b1;
endcase
end
assign trans_done = (SCLK2x_num==6'd33)&&SCLK2x;//assign 和clk对齐的信号,立即有效操作
always@(posedge sys_clk_i or negedge ext_Rst_n)
if(!ext_Rst_n)
set_done <= 1'b0;
else if(trans_done)
set_done <= 1'b1;//和clk对齐的信号,需要等待下一个clk到来时,进行有效操作
else
set_done <= 1'b0;
endmodule
step7 testbench
`timescale 1ns/1ns
`define clk_period 20
module tlv5618_tb;
reg sys_clk_i;//50M
reg ext_Rst_n;
reg start_en;//模块使能信号
reg [15:0]DAC_DATA;//控制器控制字
wire DAC_DIN;//TLV5618的DAC_DIN接口
wire DAC_SCLK;//TLV5618的DAC_SCLK接口,不高于20M设置12.5M
wire DAC_CS_N;//TLV5618的DAC_CS_N接口
wire set_done;//更新DAC完成标志,1表示完成
wire DAC_state;//模块状态表示,1表示空闲,0表示忙碌
tlv5618 tlv5618(
.sys_clk_i(sys_clk_i),
.ext_Rst_n(ext_Rst_n),
.start_en(start_en),
.DAC_DATA(DAC_DATA),
.DAC_DIN(DAC_DIN),
.DAC_SCLK(DAC_SCLK),
.DAC_CS_N(DAC_CS_N),
.set_done(set_done),
.DAC_state(DAC_state)
);
initial sys_clk_i = 0;
always#(`clk_period/2) sys_clk_i = ~sys_clk_i;
initial begin
ext_Rst_n = 0;
start_en = 0;
DAC_DATA = 0;
#201;
ext_Rst_n = 1;
#200;
DAC_DATA = 16'hC_AAA;
start_en = 1;
#20;
start_en = 0;
wait(set_done);
#20000;
DAC_DATA = 16'h4_555;
start_en = 1;
#20;
start_en = 0;
wait(set_done);
#20000;
DAC_DATA = 16'h1_555;
start_en = 1;
#20;
start_en = 0;
wait(set_done);
#20000;
DAC_DATA = 16'hF_555;
start_en = 1;
#20;
start_en = 0;
wait(set_done);
$stop;
end
endmodule
step8 仿真结果
最后
以上就是曾经水池为你收集整理的FPGA实现DAC驱动设计(以TLV5618为例)的全部内容,希望文章能够帮你解决FPGA实现DAC驱动设计(以TLV5618为例)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复