FPGA驱动LTC1856 ADC芯片
本文分享一个FPGA驱动LTC1856 ADC代码。可根据具体需求修改。
主要功能:受用户接口控制,获取相应8个通道的ADC数据。
芯片操作时序如下:
注意要点:
- 在第六个时钟下降沿开始进入采集模式,在conv上升沿结束
- 通过SGL/DIFF 选择 差分模式还是单端模式
- SDO数据有效相对于BUSY时间
- SCK 下降沿传输数据,上升沿捕获数据,全双工,数据同时接受和发送
- 差分和单端模式如下
代码如下:
`timescale 1 ns / 1 ns
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: felixgao
//
// Create Date:
// Design Name:
// Module Name:
// Project Name:
// Target Devices:
// Tool Versions: quartus 13.0
// Description:
//
// Dependencies:
//
// Revision:
// date version author
// V0.1 felixgao
// //////////////////////////////////////////////////////////////////////////////////module ltc1856_ctrl(input i_clk , // 50MHZinput i_rstn ,input [7:0] i_ch , input i_ch_en , input i_conv_start , output [15:0] o_get_mad_data ,output o_get_mad_data_valid , output o_lane0_7_sclk ,output o_lane0_7_sdi ,output o_lane0_7_conv ,input i_lane0_7_sdo // input i_lane0_7_busy );// 10MHZ
// 50MHZ 分频得到 10MHZ 的 SCLK ,占空比 60%
// parameter P_DIV = 5 , // 5 分频 ---> 10MHZ
// P_DIV_HIGH = P_DIV - 4 ,
// P_DIV_LOW = P_DIV - 1 ; // 50MHZ 分频得到 5MHZ 的 SCLK ,占空比 50%
parameter P_DIV = 10 , // 10 分频 ---> 5MHZP_DIV_HIGH = P_DIV - 9 , P_DIV_LOW = P_DIV - 4 ; // power mode
parameter P_POWER_ON = 0 , P_NAPP_NAP = 2 , P_SLEEP = 1 ; // channel sel
parameter P_CH0 = 4'b1000 , P_CH1 = 4'b1100 , P_CH2 = 4'b1001 , P_CH3 = 4'b1101 , P_CH4 = 4'b1010 , P_CH5 = 4'b1110 , P_CH6 = 4'b1011 , P_CH7 = 4'b1111 ; wire w_run_fall ; reg r_rd_run ;
reg r_run ;
reg r_run_1d ;
reg [3:0] r_div_cnt ;
reg [3:0] r_ch_sel ;
reg [1:0] r_power_mode ;
reg ro_lane0_7_sclk ;
reg ro_lane0_7_sdi ;
reg ro_lane0_7_conv ;
reg r_sclk ;
reg [4:0] r_clk_cnt ;
reg [15:0] r_sdi_data ;
reg [8:0] r_delay3_5us_cnt ;
reg [8:0] r_delay5us_cnt ;
reg [1:0] r_conv_cnt ;
reg [15:0] r_read_ad_data ;
reg r_read_ad_data_valid ;
reg [8:0] r_run_cnt ;
reg r_conv_f ;assign o_lane0_7_sclk = ro_lane0_7_sclk ;
assign o_lane0_7_sdi = ro_lane0_7_sdi ;
assign o_lane0_7_conv = ro_lane0_7_conv ;
assign w_run_fall = !r_run && r_run_1d ;
assign o_get_mad_data = r_read_ad_data ;
assign o_get_mad_data_valid = r_read_ad_data_valid ;always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn) beginr_power_mode <= 0;r_run_1d <= 0;end else beginr_power_mode <= P_POWER_ON;r_run_1d <= r_run;end
end always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_ch_sel <= P_CH0;else if (i_ch_en) case (i_ch)0 : r_ch_sel <= P_CH0 ;1 : r_ch_sel <= P_CH1 ;2 : r_ch_sel <= P_CH2 ;3 : r_ch_sel <= P_CH3 ;4 : r_ch_sel <= P_CH4 ;5 : r_ch_sel <= P_CH5 ;6 : r_ch_sel <= P_CH6 ;7 : r_ch_sel <= P_CH7 ;default : r_ch_sel <= P_CH0 ;endcaseelser_ch_sel <= r_ch_sel;
end//运行标志
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_run <= 0;else if (r_clk_cnt == 16 && r_div_cnt == P_DIV_LOW)r_run <= 0;else if (r_run_cnt == 300)r_run <= 1;elser_run <= r_run;
end// 方便赋初值
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_run_cnt <= 0;else if (r_run_cnt == 300)r_run_cnt <= 0;else if ((i_ch_en && i_conv_start) || r_run_cnt )r_run_cnt <= r_run_cnt + 1;elser_run_cnt <= r_run_cnt;
end// 分频计数器
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_div_cnt <= 0;else if (r_clk_cnt == 16 && r_div_cnt == P_DIV_LOW )r_div_cnt <= 0;else if (r_div_cnt == P_DIV -1)r_div_cnt <= 0; else if (r_run || r_rd_run)r_div_cnt <= r_div_cnt + 1;elser_div_cnt <= r_div_cnt;
endalways @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)ro_lane0_7_sclk <= 0;else if (r_div_cnt == P_DIV_LOW)ro_lane0_7_sclk <= 0;else if (r_div_cnt == P_DIV_HIGH)ro_lane0_7_sclk <= 1;elsero_lane0_7_sclk <= ro_lane0_7_sclk;
endalways @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_sclk <= 0;else if (r_div_cnt == P_DIV_LOW)r_sclk <= 0;else if (r_div_cnt == P_DIV_HIGH)r_sclk <= 1;elser_sclk <= r_sclk;
endalways @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_clk_cnt <= 0;else if (r_clk_cnt == 16 && r_div_cnt == P_DIV_LOW)r_clk_cnt <= 0;else if (r_div_cnt == P_DIV_HIGH)r_clk_cnt <= r_clk_cnt + 1;elser_clk_cnt <= r_clk_cnt;
end//需要控制的 SDI 数据,串行数据,将需要抓取的通道信息给到 ADC 芯片
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_sdi_data <= 0;else if ((i_ch_en && i_conv_start) || (r_conv_cnt == 1))r_sdi_data <= {r_ch_sel,2'b00,r_power_mode,8'd0};else if (r_sclk && r_div_cnt == 3)r_sdi_data <= r_sdi_data << 1;elser_sdi_data <= r_sdi_data;
endalways @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)ro_lane0_7_sdi <= 0;else if (!r_sclk && (r_div_cnt == 7) && (r_run || r_rd_run))ro_lane0_7_sdi <= r_sdi_data[15];else if (r_run_cnt == 2 || r_conv_cnt == 3)ro_lane0_7_sdi <= r_sdi_data[15];elsero_lane0_7_sdi <= ro_lane0_7_sdi;
end//采样延时 手册上描述,从第六个SCLK 下降沿 到 convst 上升沿 最大 4us
//500 10us
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_delay3_5us_cnt <= 0;else if (r_delay3_5us_cnt == 125)r_delay3_5us_cnt <= 0;else if (w_run_fall || r_delay3_5us_cnt)r_delay3_5us_cnt <= r_delay3_5us_cnt + 1;elser_delay3_5us_cnt <= r_delay3_5us_cnt;
end//输出 convst 信号 ,并保持 大于 手册上最小40 ns 时间
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)ro_lane0_7_conv <= 0;else if (r_conv_cnt == 3)ro_lane0_7_conv <= 0; else if (i_ch_en && i_conv_start) ro_lane0_7_conv <= 1; else if (r_delay3_5us_cnt == 125)ro_lane0_7_conv <= 1;elsero_lane0_7_conv <= ro_lane0_7_conv;
endalways @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_conv_f <= 0; else if (r_rd_run)r_conv_f <= 0; else if (w_run_fall)r_conv_f <= 1;elser_conv_f <= r_conv_f;
endalways @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_conv_cnt <= 0; else if (ro_lane0_7_conv)r_conv_cnt <= r_conv_cnt + 1;elser_conv_cnt <= r_conv_cnt;
end// 开始采集转换后的数据 , 控制 conv 信号后 需要等待最大5usalways @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_delay5us_cnt <= 0;else if (r_delay5us_cnt == 250)r_delay5us_cnt <= 0;else if ((r_conv_cnt == 2 && r_conv_f) || r_delay5us_cnt)r_delay5us_cnt <= r_delay5us_cnt + 1;elser_delay5us_cnt <= r_delay5us_cnt;
end// 读采样数据 运行期间always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_rd_run <= 0;else if (r_clk_cnt == 16 && r_div_cnt == P_DIV_LOW)r_rd_run <= 0;else if (r_delay5us_cnt == 250)r_rd_run <= 1;elser_rd_run <= r_rd_run;
end// 获取 ADC 相应 通道数据
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_read_ad_data <= 0;else if (r_div_cnt == 2 && r_rd_run && r_sclk)r_read_ad_data <= {r_read_ad_data[14:0],i_lane0_7_sdo};elser_read_ad_data <= r_read_ad_data;
end//数据有效
always @ (posedge i_clk or negedge i_rstn)
beginif (!i_rstn)r_read_ad_data_valid <= 0;else if (!i_ch_en || r_run)r_read_ad_data_valid <= 0; else if (r_div_cnt == P_DIV_LOW && r_rd_run && r_sclk && r_clk_cnt == 16)r_read_ad_data_valid <= 1;elser_read_ad_data_valid <= r_read_ad_data_valid;
endendmodule