TLV5618 使用 CMOS 电平兼容的三线制串行总线与各种处理器进行连接,接收控制器发送的 16 位的控制字,这 16 位的控制字被分为 2 个部分,包括 4 位的编程位,12 位的数据位。
其传输为:先传高位,再传低位
时序图如下:
通过线性序列机的思想对DAC进行控制和数据传输
(当片选(CS)信号为低电平时,数据在每个SCLK信号的下降沿被移入芯片内部的寄存器。当 16 位的数据移入完毕后,在第 16个 SCLK 信号的下降沿之后的一个 SCLK 信号上升沿,据根数据中的控制位,将数据制位移入保持寄存器 A、B、缓冲器和控制寄存器。当片选信号进入上升沿时,再把数据送至12 位 A/D 转换器)
module DAC_drive (
input clk,
input rst_n,
input START,
input [15:0]data,
output reg CS_N,
output reg sclk,
output reg din,
output reg Set_Done,
output DAC_State
);
reg [3:0] cnt;
reg s_clk;
reg [5:0] slck_cnt;
reg en;
reg [15:0]r_data;
wire trans_done;
parameter DIV_param = 2;
assign DAC_State = CS_N;
//使能信号
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
en <= 0;
else if(START)
en <= 1;
else if(trans_done)
en <= 0;
else
en <= en;
end
//生成2倍sclk使能时钟计数器
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 0;
else if(en)
begin
if(cnt == (DIV_param - 1'b1))
cnt <= 0;
else
cnt <= cnt + 1'b1;
end
else
cnt <= 0;
end
//产生25m的时钟s_clk
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
s_clk <= 0;
else if(en && cnt == (DIV_param - 1'b1))
s_clk <= 1;
else
s_clk <= 0;
end
//对s_clk进行计数
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
slck_cnt <= 0;
else if(s_clk && en)
begin
if(slck_cnt == 6'd33)
slck_cnt <= 0;
else
slck_cnt <= slck_cnt + 1'b1;
end
else
slck_cnt <= slck_cnt;
end
//对需要传输的数据进行寄存
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
r_data <= 0;
else if(START)
r_data <= data;
else
r_data <= r_data;
end
//线性序列机--输出信号到dac芯片进行控制和数据传输
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
begin
CS_N <= 1;
sclk <= 0;
din <= 1;
end
else if(!Set_Done && s_clk)
begin
case (slck_cnt)
0:begin CS_N <= 0; sclk <= 1; din <= r_data[15]; end
2:begin sclk <= 1; din <= r_data[14]; end
4:begin sclk <= 1; din <= r_data[13]; end
6:begin sclk <= 1; din <= r_data[12]; end
8:begin sclk <= 1; din <= r_data[11]; end
10:begin sclk <= 1; din <= r_data[10]; end
12:begin sclk <= 1; din <= r_data[9]; end
14:begin sclk <= 1; din <= r_data[8]; end
16:begin sclk <= 1; din <= r_data[7]; end
18:begin sclk <= 1; din <= r_data[6]; end
20:begin sclk <= 1; din <= r_data[5]; end
22:begin sclk <= 1; din <= r_data[4]; end
24:begin sclk <= 1; din <= r_data[3]; end
26:begin sclk <= 1; din <= r_data[2]; end
28:begin sclk <= 1; din <= r_data[1]; end
30:begin sclk <= 1; din <= r_data[0]; end
1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31: sclk <= 0;
32: sclk <= 1;
33: CS_N <= 1;
default:;
endcase
end
end
//一次转换完成标志位
assign trans_done = ((slck_cnt == 6'd33) && s_clk);
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
Set_Done <= 0;
else if(trans_done)
Set_Done <= 1;
else
Set_Done <= 0;
end
endmodule
仿真测试
`timescale 1ns/1ns
`define clock_period 20
module DAC_drive_tb ();
reg clk,rst_n,START;
reg [15:0] data;
wire CS_N,sclk,din,Set_Done;
initial clk = 1;
always #(`clock_period/2) clk = ~clk;
DAC_drive DAC_drive(
.clk(clk),
.rst_n(rst_n),
.START(START),
.data(data),
.CS_N(CS_N),
.sclk(sclk),
.din(din),
.Set_Done(Set_Done)
);
initial begin
rst_n = 0;
START = 0;
data = 0;
#(`clock_period * 10)
rst_n = 1;
#(`clock_period * 11)
data = 16'hC_AAA;
START = 1;
#20;
START = 0;
#200;
wait(Set_Done);
#2000;
data = 16'hC_666;
START = 1;
#20;
START = 0;
#200;
wait(Set_Done);
#2000;
$stop;
end
endmodule
仿真结果:
通过建立顶层测试文件,使用ISSP进行板级验证
module DAC_top (
input clk,
input rst_n,
output CS_N,
output sclk,
output din
);
reg START;
wire trans_done;
reg [15:0] r_data;
wire [15:0] data;
wire DAC_State;
ISSP ISSP(
.probe(),
.source(data)
);
DAC_drive DAC_drive(
.clk(clk),
.rst_n(rst_n),
.START(START),
.data(data),
.CS_N(CS_N),
.sclk(sclk),
.din(din),
.Set_Done(trans_done),
.DAC_State(DAC_State)
);
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
r_data <= 0;
else if(DAC_State)
r_data <= data;
else
r_data <= 0;
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
START <= 0;
else if(r_data != data)
START <= 1;
else
START <= 0;
end
endmodule