FPGA控制AD5754R DAC芯片

发布于:2025-06-30 ⋅ 阅读:(20) ⋅ 点赞:(0)

分享一个自己写的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

网站公告

今日签到

点亮在社区的每一天
去签到