分享一个自己写的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 , // 33MHZinput [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 // 50MHZP_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)
beginif (!i_rstn) beginr_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)
beginif (!i_rstn)r_run <= 0;else if (w_end_flag)r_run <= 0;else if (!ro_ad5754r_sync)r_run <= 1;elser_run <= r_run;
end// 分频计数器
always @ (posedge i_clk or negedge i_rstn)
beginif (!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;elser_div_cnt <= r_div_cnt;
end//同步信号sync
always @ (posedge i_clk or negedge i_rstn)
beginif (!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;elsero_ad5754r_sync <= ro_ad5754r_sync;
end//SCLK
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)ro_ad5754r_sclk <= 1;else if (r_div_cnt == P_DIV_CNT_MAX)ro_ad5754r_sclk <= ~ro_ad5754r_sclk;elsero_ad5754r_sclk <= ro_ad5754r_sclk;
end//辅助信号
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_clk_flag <= 1;else if (r_div_cnt == P_DIV_CNT_MAX)r_clk_flag <= ~r_clk_flag;elser_clk_flag <= r_clk_flag;
end//时钟计数
always @ (posedge i_clk or negedge i_rstn)
beginif (!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;elser_clk_cnt <= r_clk_cnt;
end//传输的数据
always @ (posedge i_clk or negedge i_rstn)
beginif (!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;elser_data <= r_data;
end//串行输出的信号 23bit,MSB --> LSB
always @ (posedge i_clk or negedge i_rstn)
beginif (!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];elsero_ad5754r_sdin <= ro_ad5754r_sdin;
end//sync 拉高后需要至少130ns时间延时 拉低LDAC,这里延时超过130ns
always @ (posedge i_clk or negedge i_rstn)
beginif (!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;elser_ld_cnt <= r_ld_cnt;
endalways @ (posedge i_clk or negedge i_rstn)
beginif (!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;elser_ld_delay_cnt <= r_ld_delay_cnt;
end//LDAC 持续60ns
always @ (posedge i_clk or negedge i_rstn)
beginif (!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;elsero_ad5754r_ldac <= ro_ad5754r_ldac;
endendmodule