DAC: Digital-to-Analog Converter,数字模拟转换器。是指将离散的数字信号转换为连续变量的模拟信号的器件,这些模拟信号通常以电流、电压或电荷的形式输出。常见的数字模拟转换器通常用来将一定比例电压值的数字信号转换为模拟信号。
DAC常见指标参数
分辨率:指最小输出电压(对应的输入数字量只有最低有效位为"1)与最大输出电压(对应的输入数字量所有有效位全为"1")之比。如N位DAC,其分辨率为1/(2^N-1)。
输出电压范围: DAC作为数字转模拟的器件,其能够进行转换的数字信号的范围总是有限的。不同型号的DAC,输出电压相差很大,对于电压输出型,最大输出电压一般为5~10V,也有高压输出型的,为24~30V。对于电流输出型DAC,输出电流一般为20ma左右,高者有的能达到3A,这类DAC由于本身输出电流,最终需要外部电阻和运放电路,才能实现电压输出。
假如一个DAC为8位,最大输出电压为5V
输入数字量: 255 电压: 5V
输入数字量: 128 电压: 2.5V
输入数字量: 64电压:1.25V
code = U* 2*8/5(理想情况下 实际情况下会有差异)
转换速率: DAC的转换速率由建立时间决定。从输入由全0突变为全1时开始,到输出电压稳定FSR±1/2LSB范围(或以FSR±x%FSR指明范围)内为止,这段时间称为建立时间,它是DAC的最大响应时间,所以该值用来衡量转换速度的快慢。
TLV5618型DAC芯片
查看TLV5618型DAC芯片手册电路以及时序。
先把传进来的数据Data B 存放到Buffer 然后等数据Data A 来时 ,数据Data A传到Latch A
Buffer中的Data B传到Latch B, 然后再经过数模转换和2倍放大器, 这样就实现了通道A,通道B的电压同时输出
其中REF电压需要查看实际芯片电路图(2.048V)
即 输出电压
化简就是
在芯片手册中查看芯片工作时序图
让通道A和B同时输出,要求通道A输出1V电压,通道B输出2V电压。假设DAC设置为快速模式,从DIN中输入的指令应该是什么?
时序分析
模块框图
线性序列机(1,最小时间的定时单元 2,序列计数器 3,驱动部分)
编写逻辑代码
module TLV5618_Driver(
Clk,
Reset_n,
DAC_Data,
Set_Go,
DAC_CS_N,
DAC_SCLK,
DAC_DIN,
Set_Done
);
//
input Clk;
input Reset_n;
input [15:0]DAC_Data;
input Set_Go;
output reg DAC_CS_N;
output reg DAC_SCLK;
output reg DAC_DIN;
output reg Set_Done;
parameter CLOCK_FREQ = 50_000_000;
parameter SCLK_FREQ = 12_500_000;
parameter MCNT_DIV_CNT = CLOCK_FREQ /(SCLK_FREQ * 2) - 1;
reg [7:0]DIV_CNT;
reg [5:0]LSM_CNT;
reg [15:0]r_DAC_Data;
always@(posedge Clk)
if(Set_Go)
r_DAC_Data <= DAC_Data;
else
r_DAC_Data <= r_DAC_Data;
reg Set_En; //转换使能
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Set_En <= 1'b0;
else if(Set_Go)
Set_En <= 1'b1;
else if((LSM_CNT == 6'd33)&&(DIV_CNT == MCNT_DIV_CNT))
Set_En <= 1'b0;
else
Set_En <= Set_En;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
DIV_CNT <= 1'd0;
else if(Set_En) begin
if(DIV_CNT == MCNT_DIV_CNT)
DIV_CNT <= 1'd0;
else
DIV_CNT <= DIV_CNT + 1'd1;
end
else
DIV_CNT <= 1'd0;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
LSM_CNT <= 6'd0;
else if(DIV_CNT == MCNT_DIV_CNT)begin
if(LSM_CNT == 6'd33)
LSM_CNT <= 6'b0;
else
LSM_CNT <= LSM_CNT + 1'b1;
end
else
LSM_CNT <= LSM_CNT;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n) begin
DAC_CS_N <= 1'd1;
DAC_SCLK <= 1'd1;
DAC_DIN <= 1'd1;
end
else if(DIV_CNT == MCNT_DIV_CNT) begin
case(LSM_CNT)
0 : begin DAC_SCLK <= 1'd1; DAC_CS_N <= 1'd0; DAC_DIN <= r_DAC_Data[15]; end
1 : begin DAC_SCLK <= 1'd0; end
2 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[14]; end
3 : begin DAC_SCLK <= 1'd0; end
4 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[13]; end
5 : begin DAC_SCLK <= 1'd0; end
6 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[12]; end
7 : begin DAC_SCLK <= 1'd0; end
8 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[11]; end
9 : begin DAC_SCLK <= 1'd0; end
10 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[10]; end
11 : begin DAC_SCLK <= 1'd0; end
12 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[9]; end
13 : begin DAC_SCLK <= 1'd0; end
14 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[8]; end
15 : begin DAC_SCLK <= 1'd0; end
16 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[7]; end
17 : begin DAC_SCLK <= 1'd0;end
18 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[6]; end
19 : begin DAC_SCLK <= 1'd0; end
20 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[5]; end
21 : begin DAC_SCLK <= 1'd0; end
22 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[4]; end
23 : begin DAC_SCLK <= 1'd0; end
24 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[3]; end
25 : begin DAC_SCLK <= 1'd0; end
26 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[2]; end
27 : begin DAC_SCLK <= 1'd0; end
28 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[1]; end
29 : begin DAC_SCLK <= 1'd0; end
30 : begin DAC_SCLK <= 1'd1; DAC_DIN <= r_DAC_Data[0]; end
31 : begin DAC_SCLK <= 1'd0; end
32 : begin DAC_SCLK <= 1'd1; end
33 : begin DAC_CS_N <= 1'd1; end
default : DAC_CS_N <= 1'd1;
endcase
end
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)
Set_Done <= 1'd0;
else if ((LSM_CNT == 6'd33)&&(DIV_CNT == MCNT_DIV_CNT))
Set_Done <= 1'd1;
else
Set_Done <= 1'd0;
endmodule
然后编写testbench测试文件
代码如下
`timescale 1ns / 1ns
module TLV51618_Driver_tb;
reg Clk;
reg Reset_n;
reg [15:0]DAC_Data;
reg Set_Go;
wire DAC_CS_N;
wire DAC_SCLK;
wire DAC_DIN;
wire Set_Done;
TLV5618_Driver TLV5618_Driver(
.Clk(Clk),
.Reset_n(Reset_n),
.DAC_Data(DAC_Data),
.Set_Go(Set_Go),
.DAC_CS_N(DAC_CS_N),
.DAC_SCLK(DAC_SCLK),
.DAC_DIN(DAC_DIN),
.Set_Done(Set_Done)
);
initial Clk = 1;
always #10 Clk = ~Clk;
initial begin
Reset_n = 0;
Set_Go = 0;
DAC_Data = 0;
#201;
Reset_n = 1;
#200;
DAC_Data = 16'hC_AAA;
Set_Go = 1;
#20;
Set_Go = 0;
#200;
wait(Set_Done);
#20001;
DAC_Data = 16'h4_555;
Set_Go = 1;
#20;
Set_Go = 0;
#200;
wait(Set_Done);
#20001;
DAC_Data = 16'h1_555;
Set_Go = 1;
#20;
Set_Go = 0;
#200;
wait(Set_Done);
#20001;
DAC_Data = 16'hf_555;
Set_Go = 1;
#20;
Set_Go = 0;
#200;
wait(Set_Done);
#20001;
$stop;
end
endmodule
仿真波形如下
对比芯片手册提供的时序图,可以看到与芯片手册的时序图一致。
至此,TLV5618型DAC芯片驱动逻辑设计完成。
如若需要板级验证,可加入数码管显示模块,按键消抖模块,LED,以及拨码开关设计需要输出的电压进行简单的板级验证。