目錄
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