1.芯片简介:
TLC5620是一个内部具备4个独立 8位电压输出型数字-模拟转换器,每个DAC转换器都拥有一个带缓冲(高输入阻抗)的参考电压输入端口。每个DAC可以输出Vref x1或者Vref x2的参考电压与GND之间的电压值。
2.参考应用电路:
3.驱动端口及寄存器:
芯片端口名 | 网络名 | 方向 | 说明 |
---|---|---|---|
CLK | DAC_CLK | input | 串行接口的时钟输入 |
DATA | DAC_DATA | input | 串行接口的数据输入 |
LOAD | DAC_LOAD | input | 加载DAC(更新DAC待输出数据) |
LDAC | DAC_LDAC | input | 串行数据的加载控制 |
DACA~DACD | DOUTA~DOUTD | output | 芯片电压输出 (可使用万用表,或者ARM通过ADC转换测试) |
A1 | A0 | RNG | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|
DAC选择译码信号 | 控制DAC输出范围 | 输出电压值的数字量化量 |
A1 | A0 | 被更新的DAC通道 |
---|---|---|
0 | 0 | DACA |
0 | 1 | DACB |
1 | 0 | DACC |
1 | 1 | DACD |
4.驱动时序及驱动代码:
对于TLC5620芯片数据的传输,有连续传输(11个连续的时钟周期传输11位的控制字,如Figure1和Figure2)和分段传输方式(使用两次8时钟周期的传输来实现11位数据的传输,如Figure3和Figure4)。
驱动时序1:
驱动时序1,当LOAD为高电平时,在CLK的下降沿,数据被移入DAC的移位寄存器中。当所有的数据位被移入完成后,拉低LOAD,将数据从串行输入移位寄存器中转入选中的DAC中,由于此时LDAC始终为拉低状态,数据由寄存器到选中的DAC通道的更新路径畅通无阻,选中的通道的输出电压在LOAD变为低电平时更新。
驱动代码:
module tlc5620_driver
(
input sys_clk,
input sys_rstn,
input da_enable, // 0, 不配置; 1, 进入配置时序
input da_range, // 0, 参考电压*1; 1, 参考电压*2
input [7:0] da0_data, // 0~255
input [7:0] da1_data, // 0~255
input [7:0] da2_data, // 0~255
input [7:0] da3_data, // 0~255
output reg dac_clk,
output reg dac_data,
output reg dac_load,
output reg dac_ldac
);
/*驱动时序
__ __ __ __ _ __
DCLK __/ \__/ \__/ \__/ \_... \__/ \________
__ ____ ____ ____ __......__ ___
DATA __X_____X_____X_____X___......__X____
_____________________________________
LOAD \__/
LDAC ___________________________________________
*/
parameter SYSCLK_FREQ = 50000000; //50MHz
parameter CHIPCLK_FREQ = 1000000;
localparam CNT_CYCLE = SYSCLK_FREQ/CHIPCLK_FREQ*4;
localparam TICK_T_MAX = 47;
wire tick_t = 0;
reg [31:0] cnt;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
cnt <= 0;
else
begin
if(cnt < (CNT_CYCLE) )
cnt <= cnt + 1'b1;
else cnt <= 0;
end
end
// 250ns 的 tick_t
assign tick_t = (cnt == (CNT_CYCLE)-1) ? 1 : 0;
wire tick_c = 0;
reg [15:0] da_ref_cnt;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_ref_cnt <= 0;
else
begin
if(!da_enable)
da_ref_cnt <= 0;
else
begin
if(tick_t)
begin
if(da_ref_cnt < TICK_T_MAX)
da_ref_cnt <= da_ref_cnt + 1'b1;
else da_ref_cnt <= 0;
end
end
end
end
// 单通道配置完成的标志
assign tick_c = (da_ref_cnt == TICK_T_MAX) ? 1 : 0;
//通道切换
reg [1:0] da_sel;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_sel <= 2'b0;
else if (tick_c)
begin
if(da_sel < 3)
da_sel <= da_sel + 1'b1;
else da_sel <= 2'b0;
end
end
//加载对应通道数据
reg [7:0] da_data;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_data <= 8'b0;
else
begin
case(da_sel)
2'b00: da_data <= da0_data;
2'b01: da_data <= da1_data;
2'b10: da_data <= da2_data;
2'b11: da_data <= da3_data;
endcase
end
end
//DATA数据传输
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_data <= 0;
end
else
begin
if(tick_t)
begin
// 送入串型数据DAC_DATA
case(da_ref_cnt)
3: dac_data <= da_sel[1];
7: dac_data <= da_sel[0];
11: dac_data <= da_range;
15: dac_data <= da_data[7];
19: dac_data <= da_data[6];
23: dac_data <= da_data[5];
27: dac_data <= da_data[4];
31: dac_data <= da_data[3];
35: dac_data <= da_data[2];
39: dac_data <= da_data[1];
43: dac_data <= da_data[0];
default : ;
endcase
end
end
end
//LOAD控制
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_load <= 1;
end
else
begin
if(tick_t)
begin
// 生成DAC_LOAD信号
case(da_ref_cnt)
0: dac_load <= 1;
46: dac_load <= 0;
default : ;
endcase
end
end
end
//LDAC控制
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_ldac <= 1;
end
else
begin
if(tick_t)
begin
// 生成DAC_LDAC信号
case(da_ref_cnt)
0: dac_ldac <= 0;
default : ;
endcase
end
end
end
// DAC_CLK信号生成 ,设计为1MHz
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_clk <= 0;
end
else
begin
if(tick_t)
begin
// 生成DAC_CLK信号
case(da_ref_cnt)
2,6,10,14,18,22,26,30,34,38,42: dac_clk <= 1;
4,8,12,16,20,24,28,32,36,40,44: dac_clk <= 0;
default : ;
endcase
end
end
end
endmodule
驱动时序2:
和驱动时序1的差异在于,驱动时序2中的LDAC并不是始终为拉低状态,此时数据由寄存器到对应的DAC需要经过LDAC的允许,数据在LDAC拉低时传入DAC的输出。
驱动代码:
module tlc5620_driver
(
input sys_clk,
input sys_rstn,
input da_enable, // 0, 不配置; 1, 进入配置时序
input da_range, // 0, 参考电压*1; 1, 参考电压*2
input [7:0] da0_data, // 0~255
input [7:0] da1_data, // 0~255
input [7:0] da2_data, // 0~255
input [7:0] da3_data, // 0~255
output reg dac_clk,
output reg dac_data,
output reg dac_load,
output reg dac_ldac
);
/*驱动时序
__ __ __ __ _ __
DCLK __/ \__/ \__/ \__/ \_... \__/ \________
__ ____ ____ ____ __......__ ___
DATA __X_____X_____X_____X___......__X____
_____________________________________
LOAD \__/
________________________________________
LDAC \__/
*/
parameter SYSCLK_FREQ = 50000000; //50MHz
parameter CHIPCLK_FREQ = 1000000;
localparam CNT_CYCLE = SYSCLK_FREQ/CHIPCLK_FREQ*4;
localparam TICK_T_MAX = 48;
wire tick_t = 0;
reg [31:0] cnt;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
cnt <= 0;
else
begin
if(cnt < (CNT_CYCLE) )
cnt <= cnt + 1'b1;
else cnt <= 0;
end
end
// 250ns 的 tick_t
assign tick_t = (cnt == (CNT_CYCLE)-1) ? 1 : 0;
wire tick_c = 0;
reg [15:0] da_ref_cnt;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_ref_cnt <= 0;
else
begin
if(!da_enable)
da_ref_cnt <= 0;
else
begin
if(tick_t)
begin
if(da_ref_cnt < TICK_T_MAX)
da_ref_cnt <= da_ref_cnt + 1'b1;
else da_ref_cnt <= 0;
end
end
end
end
// 单通道配置完成的标志
assign tick_c = (da_ref_cnt == TICK_T_MAX) ? 1 : 0;
//通道切换
reg [1:0] da_sel;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_sel <= 2'b0;
else if (tick_c)
begin
if(da_sel < 3)
da_sel <= da_sel + 1'b1;
else da_sel <= 2'b0;
end
end
//加载对应通道数据
reg [7:0] da_data;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_data <= 8'b0;
else
begin
case(da_sel)
2'b00: da_data <= da0_data;
2'b01: da_data <= da1_data;
2'b10: da_data <= da2_data;
2'b11: da_data <= da3_data;
endcase
end
end
//DATA数据传输
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_data <= 0;
end
else
begin
if(tick_t)
begin
// 送入串型数据DAC_DATA
case(da_ref_cnt)
3: dac_data <= da_sel[1];
7: dac_data <= da_sel[0];
11: dac_data <= da_range;
15: dac_data <= da_data[7];
19: dac_data <= da_data[6];
23: dac_data <= da_data[5];
27: dac_data <= da_data[4];
31: dac_data <= da_data[3];
35: dac_data <= da_data[2];
39: dac_data <= da_data[1];
43: dac_data <= da_data[0];
default : ;
endcase
end
end
end
//LOAD控制
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_load <= 1;
end
else
begin
if(tick_t)
begin
// 生成DAC_LOAD信号
case(da_ref_cnt)
0: dac_load <= 1;
46: dac_load <= 0;
47: dac_load <= 1;
default : ;
endcase
end
end
end
//LDAC控制
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_ldac <= 1;
end
else
begin
if(tick_t)
begin
// 生成DAC_LDAC信号
case(da_ref_cnt)
0: dac_ldac <= 1;
47: dac_ldac <= 0;
default : ;
endcase
end
end
end
// DAC_CLK信号生成 ,设计为1MHz
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_clk <= 0;
end
else
begin
if(tick_t)
begin
// 生成DAC_CLK信号
case(da_ref_cnt)
2,6,10,14,18,22,26,30,34,38,42: dac_clk <= 1;
4,8,12,16,20,24,28,32,36,40,44: dac_clk <= 0;
default : ;
endcase
end
end
end
endmodule
驱动时序3:
驱动时序3,使用两个8时钟周期的传输数据,此时也是LDAC始终拉低的状态,数据在LOAD为低时传入对应DAC的输出。
驱动代码:
module tlc5620_driver
(
input sys_clk,
input sys_rstn,
input da_enable, // 0, 不配置; 1, 进入配置时序
input da_range, // 0, 参考电压*1; 1, 参考电压*2
input [7:0] da0_data, // 0~255
input [7:0] da1_data, // 0~255
input [7:0] da2_data, // 0~255
input [7:0] da3_data, // 0~255
output reg dac_clk,
output reg dac_data,
output reg dac_load,
output reg dac_ldac
);
/*驱动时序
__ __ __ __ __ __
DCLK __/ \__/ \__/ \__/ \__..__..__/ \__/ \___
__ ____ ____ ____ __.........._ ___ ___
DATA __X_____X_____X_____X___........._X_____X___
_____________________________________________
LOAD \__/
LDAC __________________________________________________
*/
parameter SYSCLK_FREQ = 50000000; //50MHz
parameter CHIPCLK_FREQ = 1000000;
localparam CNT_CYCLE = SYSCLK_FREQ/CHIPCLK_FREQ*4;
localparam TICK_T_MAX = 87;
wire tick_t = 0;
reg [31:0] cnt;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
cnt <= 0;
else
begin
if(cnt < (CNT_CYCLE) )
cnt <= cnt + 1'b1;
else cnt <= 0;
end
end
// 250ns 的 tick_t
assign tick_t = (cnt == (CNT_CYCLE)-1) ? 1 : 0;
wire tick_c = 0;
reg [15:0] da_ref_cnt;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_ref_cnt <= 0;
else
begin
if(!da_enable)
da_ref_cnt <= 0;
else
begin
if(tick_t)
begin
if(da_ref_cnt < TICK_T_MAX)
da_ref_cnt <= da_ref_cnt + 1'b1;
else da_ref_cnt <= 0;
end
end
end
end
// 单通道配置完成的标志
assign tick_c = (da_ref_cnt == TICK_T_MAX) ? 1 : 0;
//通道切换
reg [1:0] da_sel;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_sel <= 2'b0;
else if (tick_c)
begin
if(da_sel < 3)
da_sel <= da_sel + 1'b1;
else da_sel <= 2'b0;
end
end
//加载对应通道数据
reg [7:0] da_data;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_data <= 8'b0;
else
begin
case(da_sel)
2'b00: da_data <= da0_data;
2'b01: da_data <= da1_data;
2'b10: da_data <= da2_data;
2'b11: da_data <= da3_data;
endcase
end
end
//DATA数据传输
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_data <= 0;
end
else
begin
if(tick_t)
begin
// 送入串型数据DAC_DATA
case(da_ref_cnt)
3: dac_data <= 1;
7: dac_data <= 1;
11: dac_data <= 1;
15: dac_data <= 1;
19: dac_data <= 1;
23: dac_data <= da_sel[1];
27: dac_data <= da_sel[0];
31: dac_data <= da_range;
//停摆
55: dac_data <= da_data[7];
59: dac_data <= da_data[6];
63: dac_data <= da_data[5];
67: dac_data <= da_data[4];
71: dac_data <= da_data[3];
75: dac_data <= da_data[2];
79: dac_data <= da_data[1];
83: dac_data <= da_data[0];
default : ;
endcase
end
end
end
//LOAD控制
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_load <= 1;
end
else
begin
if(tick_t)
begin
// 生成DAC_LOAD信号
case(da_ref_cnt)
0: dac_load <= 1;
86: dac_load <= 0;
default : ;
endcase
end
end
end
//LDAC控制
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_ldac <= 1;
end
else
begin
if(tick_t)
begin
// 生成DAC_LDAC信号
case(da_ref_cnt)
0: dac_ldac <= 0;
default : ;
endcase
end
end
end
// DAC_CLK信号生成 ,设计为1MHz
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_clk <= 0;
end
else
begin
if(tick_t)
begin
// 生成DAC_CLK信号
case(da_ref_cnt)
2,6,10,14,18,22,26,30: dac_clk <= 1;
4,8,12,16,20,24,28,32: dac_clk <= 0;
//停摆
54,58,62,66,70,74,78,82: dac_clk <= 1;
56,60,64,68,72,76,80,84: dac_clk <= 0;
default : ;
endcase
end
end
end
endmodule
驱动时序4:
驱动时序4,与驱动时序3的差异也是在于LDAC的状态不同,此时的数据由寄存器到对应的DAC需要经过LDAC的允许,数据在LDAC拉低时传入DAC的输出。
驱动代码:
module tlc5620_driver
(
input sys_clk,
input sys_rstn,
input da_enable, // 0, 不配置; 1, 进入配置时序
input da_range, // 0, 参考电压*1; 1, 参考电压*2
input [7:0] da0_data, // 0~255
input [7:0] da1_data, // 0~255
input [7:0] da2_data, // 0~255
input [7:0] da3_data, // 0~255
output reg dac_clk,
output reg dac_data,
output reg dac_load,
output reg dac_ldac
);
/*驱动时序
__ __ __ __ __ __
DCLK __/ \__/ \__/ \__/ \__..__..__/ \__/ \___
__ ____ ____ ____ __.........._ ___ ___
DATA __X_____X_____X_____X___........._X_____X___
_____________________________________________
LOAD \__/
________________________________________________
LDAC \__/
*/
parameter SYSCLK_FREQ = 50000000; //50MHz
parameter CHIPCLK_FREQ = 1000000;
localparam CNT_CYCLE = SYSCLK_FREQ/CHIPCLK_FREQ*4;
localparam TICK_T_MAX = 88;
wire tick_t = 0;
reg [31:0] cnt;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
cnt <= 0;
else
begin
if(cnt < (CNT_CYCLE) )
cnt <= cnt + 1'b1;
else cnt <= 0;
end
end
// 250ns 的 tick_t
assign tick_t = (cnt == (CNT_CYCLE)-1) ? 1 : 0;
wire tick_c = 0;
reg [15:0] da_ref_cnt;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_ref_cnt <= 0;
else
begin
if(!da_enable)
da_ref_cnt <= 0;
else
begin
if(tick_t)
begin
if(da_ref_cnt < TICK_T_MAX)
da_ref_cnt <= da_ref_cnt + 1'b1;
else da_ref_cnt <= 0;
end
end
end
end
// 单通道配置完成的标志
assign tick_c = (da_ref_cnt == TICK_T_MAX) ? 1 : 0;
//通道切换
reg [1:0] da_sel;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_sel <= 2'b0;
else if (tick_c)
begin
if(da_sel < 3)
da_sel <= da_sel + 1'b1;
else da_sel <= 2'b0;
end
end
//加载对应通道数据
reg [7:0] da_data;
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
da_data <= 8'b0;
else
begin
case(da_sel)
2'b00: da_data <= da0_data;
2'b01: da_data <= da1_data;
2'b10: da_data <= da2_data;
2'b11: da_data <= da3_data;
endcase
end
end
//DATA数据传输
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_data <= 0;
end
else
begin
if(tick_t)
begin
// 送入串型数据DAC_DATA
case(da_ref_cnt)
3: dac_data <= 1;
7: dac_data <= 1;
11: dac_data <= 1;
15: dac_data <= 1;
19: dac_data <= 1;
23: dac_data <= da_sel[1];
27: dac_data <= da_sel[0];
31: dac_data <= da_range;
//停摆
55: dac_data <= da_data[7];
59: dac_data <= da_data[6];
63: dac_data <= da_data[5];
67: dac_data <= da_data[4];
71: dac_data <= da_data[3];
75: dac_data <= da_data[2];
79: dac_data <= da_data[1];
83: dac_data <= da_data[0];
default : ;
endcase
end
end
end
//LOAD控制
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_load <= 1;
end
else
begin
if(tick_t)
begin
// 生成DAC_LOAD信号
case(da_ref_cnt)
0: dac_load <= 1;
86: dac_load <= 0;
87: dac_load <= 1;
default : ;
endcase
end
end
end
//LDAC控制
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_ldac <= 1;
end
else
begin
if(tick_t)
begin
// 生成DAC_LDAC信号
case(da_ref_cnt)
0: dac_ldac <= 1;
87: dac_ldac <= 0;
default : ;
endcase
end
end
end
// DAC_CLK信号生成 ,设计为1MHz
always@(posedge sys_clk, negedge sys_rstn)
begin
if(!sys_rstn)
begin
dac_clk <= 0;
end
else
begin
if(tick_t)
begin
// 生成DAC_CLK信号
case(da_ref_cnt)
2,6,10,14,18,22,26,30: dac_clk <= 1;
4,8,12,16,20,24,28,32: dac_clk <= 0;
//停摆
54,58,62,66,70,74,78,82: dac_clk <= 1;
56,60,64,68,72,76,80,84: dac_clk <= 0;
default : ;
endcase
end
end
end
endmodule