分享一个自己写的AD5754R DAC驱动。
芯片时序图:
上板调试图:
核心代码:
`timescale 1 ns / 1 ns
//
// Company:
// Engineer: felixgao
//
// Create Date:
// Design Name:
// Module Name: ad5754r_ctrl
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// date version author
//
//
//
module ad5754r_ctrl (
input i_clk , // 输入50MHZ 时钟
input i_rstn ,
input i_mmda_conv_flag ,
input i_mmda_ch_valid ,
input i_mmda_data_valid ,
input [31:0] i_reg0x4c_mmda_data , // 33MHZ
input [31:0] i_reg0x50_mmda_ch ,
output o_ad5754r_sync ,
output o_ad5754r_ldac ,
output o_ad5754r_sclk ,
output o_ad5754r_sdin ,
input i_ad5754r_sdo
);
parameter P_DIV = 10 , // 10 分频 ---> 5MHZ // 50MHZ
P_DIV_CNT_MAX = (P_DIV >> 1) - 1 , // 计数器最大值
P_DIV_CNT_WIDTH = 3 ,
P_CLK_CNT_WIDTH = 5 ,
P_TRANS_BIT_WIDTH = 24 ;
wire w_run_fall ;
wire w_end_flag ;
reg ro_ad5754r_sync ;
reg ro_ad5754r_ldac ;
reg ro_ad5754r_sclk ;
reg ro_ad5754r_sdin ;
reg r_run ;
reg r_run_1d ;
reg [P_DIV_CNT_WIDTH - 1:0] r_div_cnt ;
reg [23:0] r_data ;
reg [P_CLK_CNT_WIDTH - 1:0] r_clk_cnt ;
reg [4:0] r_ld_cnt ;
reg [1:0] r_ld_delay_cnt ;
reg r_clk_flag ;
reg ri_mmda_data_valid ;
reg ri_mmda_data_valid_1d ;
reg ri_mmda_data_valid_2d ;
// reg ri_mmda_conv_flag ;
// reg ri_mmda_conv_flag_1d ;
assign w_run_fall = !r_run && r_run_1d ;
assign w_end_flag = (r_clk_cnt == P_TRANS_BIT_WIDTH) && (r_div_cnt == P_DIV_CNT_MAX ) && (!r_clk_flag);
assign o_ad5754r_sync = ro_ad5754r_sync ;
assign o_ad5754r_ldac = ro_ad5754r_ldac ;
assign o_ad5754r_sclk = ro_ad5754r_sclk ;
assign o_ad5754r_sdin = ro_ad5754r_sdin ;
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn) begin
r_run_1d <= 0;
// ri_mmda_conv_flag <= 0;
// ri_mmda_conv_flag_1d <= 0;
ri_mmda_data_valid <= 0;
ri_mmda_data_valid_1d <= 0;
ri_mmda_data_valid_2d <= 0;
end else begin
r_run_1d <= r_run;
// ri_mmda_conv_flag <= i_mmda_conv_flag;
// ri_mmda_conv_flag_1d <= ri_mmda_conv_flag;
ri_mmda_data_valid <= i_mmda_data_valid;
ri_mmda_data_valid_1d <= ri_mmda_data_valid;
ri_mmda_data_valid_2d <= ri_mmda_data_valid_1d ;
end
end
//运行标志
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
r_run <= 0;
else if (w_end_flag)
r_run <= 0;
else if (!ro_ad5754r_sync)
r_run <= 1;
else
r_run <= r_run;
end
// 分频计数器
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
r_div_cnt <= 0;
else if (w_end_flag)
r_div_cnt <= 0;
else if (r_div_cnt == P_DIV_CNT_MAX)
r_div_cnt <= 0;
else if (r_run)
r_div_cnt <= r_div_cnt + 1;
else
r_div_cnt <= r_div_cnt;
end
//同步信号sync
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
ro_ad5754r_sync <= 1;
else if (w_end_flag)
ro_ad5754r_sync <= 1;
else if (ri_mmda_data_valid_1d)
ro_ad5754r_sync <= 0;
else
ro_ad5754r_sync <= ro_ad5754r_sync;
end
//SCLK
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
ro_ad5754r_sclk <= 1;
else if (r_div_cnt == P_DIV_CNT_MAX)
ro_ad5754r_sclk <= ~ro_ad5754r_sclk;
else
ro_ad5754r_sclk <= ro_ad5754r_sclk;
end
//辅助信号
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
r_clk_flag <= 1;
else if (r_div_cnt == P_DIV_CNT_MAX)
r_clk_flag <= ~r_clk_flag;
else
r_clk_flag <= r_clk_flag;
end
//时钟计数
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
r_clk_cnt <= 0;
else if (w_end_flag)
r_clk_cnt <= 0;
else if (r_div_cnt == P_DIV_CNT_MAX && r_clk_flag)
r_clk_cnt <= r_clk_cnt + 1;
else
r_clk_cnt <= r_clk_cnt;
end
//传输的数据
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
r_data <= 0;
else if (ri_mmda_data_valid_1d)
r_data <= i_reg0x4c_mmda_data[23:0];
else if (!r_clk_flag && r_div_cnt == 2)
r_data <= r_data << 1;
else
r_data <= r_data;
end
//串行输出的信号 23bit,MSB --> LSB
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
ro_ad5754r_sdin <= 0;
else if (ri_mmda_data_valid_2d)
ro_ad5754r_sdin <= r_data[23];
else if (!r_clk_flag && r_div_cnt == P_DIV_CNT_MAX)
ro_ad5754r_sdin <= r_data[23];
else
ro_ad5754r_sdin <= ro_ad5754r_sdin;
end
//sync 拉高后需要至少130ns时间延时 拉低LDAC,这里延时超过130ns
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
r_ld_cnt <= 0;
else if (r_ld_cnt == 20)
r_ld_cnt <= 0;
else if (w_run_fall || r_ld_cnt)
r_ld_cnt <= r_ld_cnt + 1;
else
r_ld_cnt <= r_ld_cnt;
end
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
r_ld_delay_cnt <= 0;
else if (r_ld_cnt == 20 || r_ld_delay_cnt)
r_ld_delay_cnt <= r_ld_delay_cnt + 1;
else
r_ld_delay_cnt <= r_ld_delay_cnt;
end
//LDAC 持续60ns
always @ (posedge i_clk or negedge i_rstn)
begin
if (!i_rstn)
ro_ad5754r_ldac <= 1;
else if (r_ld_delay_cnt == 3)
ro_ad5754r_ldac <= 1;
else if (r_ld_cnt == 20)
ro_ad5754r_ldac <= 0;
else
ro_ad5754r_ldac <= ro_ad5754r_ldac;
end
endmodule