DAC--TLV5618的使用

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值