ADS1675 24位ADC的FPGA采集设计(CMOS与LVDS双版本)
一、芯片简介
ADS1675 是 TI 推出的 24 位 Delta-Sigma 模数转换器,最高采样率 4MSPS,TQFP-64 封装。主要参数:动态范围 103dB@4MSPS,INL ±3ppm,功耗 575mW。模拟 5V/数字 3V 供电,参考电压 VREF=3.0V。
内部集成 Delta-Sigma 调制器 + 双路可编程数字滤波器 + PLL 时钟倍频器,支持 CMOS 和 LVDS 两种数字接口。
二、三种工作模式
ADS1675 通过 FPATH 和 LL_CONFIG 引脚组合,提供三种滤波器模式(f_CLK=32MHz,DRATE=011 时 1MSPS):
模式一:LL Fast-Response(推荐)
配置:FPATH=1, LL_CONFIG=1。滤波器以指数衰减权重累积历史数据,1MSPS 下 tDRDY=1µs,阶跃响应约 4µs 恢复 99.9%。采样率最高 4MSPS(需 LVDS)。适合绝大多数数据采集场景,兼顾高精度与快速响应。
模式二:LL Single-Cycle
配置:FPATH=1, LL_CONFIG=0。每个转换周期完全独立,无滤波器历史记忆。最高 277.78kSPS,每笔数据 100% 有效。适合对确定性要求极高的静态测量。
模式三:Wide-Bandwidth
配置:FPATH=0。55 阶线性相位 FIR 滤波器,通带纹波 <0.00002dB,阻带衰减 86dB。阶跃恢复需 55 个周期(55µs@1MSPS)。适合 AC 频谱分析等频域精度要求高的场景,不适合信号快速变化的场合。
三、CMOS 与 LVDS 接口对比
| 项目 | CMOS | LVDS |
|---|---|---|
| 信号线 | 3 根单端 | 3 对差分(6 根) |
| SCLK 频率 | f_CLK = 32MHz | 3×f_CLK = 96MHz(PLL 倍频) |
| 最高数据率 | 1MSPS | 4MSPS(HS 模式) |
| FPGA 时钟要求 | ≥100MHz | ≥300MHz(需 >3× SCLK) |
| FPGA 原语 | 无 | IBUFDS × 3 |
| 时序参考 | 手册 Figure 3 | 手册 Figure 1 |
| DRDY 脉宽 | ~1 T_SCLK(~31ns) | 2~4 T_SCLK(~20-40ns) |
| tLSCLKDR | 2.2~4.4ns | 2.0~3.0ns |
| tLDOPD | 1.9~2.8ns | 1.5~2.5ns |
CMOS 版本 FPGA 100MHz,SCLK 32MHz,频率比 3.1:1,满足过采样要求。
LVDS 版本 PLL 将 32MHz 主时钟 3 倍频至 96MHz SCLK,FPGA 需 ≥300MHz 才能可靠采样(>3× 奈奎斯特)。HS 模式(2M/4M)强制使用 LVDS,分辨率降为 23-bit。
四、数据编码
二进制补码,MSB 先行输出:+VREF(3.0V) → 7FFFFFh,0V → 000000h,-VREF(-3.0V) → 800000h。超出量程时输出钳位并触发报警。LL/WB 模式 24-bit,HS 模式 23-bit。
五、FPGA 采集设计(CMOS 版本)
5.1 整体架构
100MHz FPGA 过采样 32MHz SCLK 和 DRDY。三段式状态机:
- S_IDLE:等待首个 DRDY,忽略所有 SCLK,不产生任何 FIFO 写入
- S_WAIT_MSB:DRDY 已出现,等待 MSB SCLK 边沿
- S_CAPTURE:移位采集 24-bit 数据,完成后回到 S_WAIT_MSB
5.2 MSB 双路径检测(核心设计)
手册 Figure 3 的关键细节:MSB(D23) 在 DRDY 拉高的那个 SCLK 上升沿呈现,与 DRDY 是同一个 SCLK 边沿,不是下一个 ------ 这是最常见的 RTL 设计错误,会导致数据整体左偏 1 bit。
由于 DRDY 在 SCLK↑ 后 2.2~4.4ns 才拉高,100MHz(10ns 周期)采样存在相位不确定性,采用双路径检测保证可靠:
- 主检测(实时命中):SCLK↑ 的同时 DRDY 已经为高 → 直接确认 MSB 边沿
- 回退检测 (延迟确认):上一拍记录潜在 MSB 边沿(SCLK↑ 但 DRDY 尚未确认),本拍 DRDY 确认后回退确认

5.3 采集与同步
- 移位寄存器:MSB 先行左移
r_shift_reg <= {r_shift_reg[22:0], i_ads_dout} - FIFO 对齐:r_fifo_wr_pre 在第 24 个 SCLK↑ 产生,延迟 1 拍与 r_data_out 锁存时刻对齐
- 同步器:DRDY 3 级、SCLK 2 级,消除亚稳态
c
`timescale 1 ns / 1 ns
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: felix
//
// Create Date:
// Design Name:
// Module Name: ads1675_capture
// Project Name:
// Target Devices: Xilinx ZYNQ7030
// Tool Versions:
// Description:
// ADS1675 24-bit 串行数据采集模块。
// 模式: LL Fast-Response, DRATE=011 (1MSPS)
// 接口: CMOS + 内部 SCLK (SCLK_SEL=0)
// 控制: START=高 (连续转换), CS=低
//
// 手册 Figure 3 关键时序 (内部 SCLK 模式):
// - SCLK = 连续自由运行, f_SCLK = f_CLK = 32MHz, 周期 31.25ns
// - DRDY = 数据就绪脉冲, 在 SCLK↑ 后 tLSCLKDR 拉高
// - tLSCLKDR = SCLK↑ → DRDY↑ = 2.2~4.4ns
// - tLDOPD = SCLK↑ → DOUT 有效 = 1.9~2.8ns
// - DOUT = MSB 先行, 24-bit 二进制补码
// - MSB(D23) = 在 DRDY 拉高的那个 SCLK 边沿呈现 (与 DRDY 同一 SCLK↑!)
//
// Dependencies: 无
//
// Revision:
// date version author description
// 2026-06-22 V0.1 felix
//
//////////////////////////////////////////////////////////////////////////////////
module ads1675_capture
#(
parameter P_DATA_WIDTH = 24 // ADC 数据位宽
)
(
input logic i_clk ,// FPGA 100MHz 时钟
input logic i_rstn ,// 异步复位 (低有效)
input logic i_ads_drdy ,// ADS1675 数据就绪脉冲
input logic i_ads_sclk ,// ADS1675 串行时钟 (连续 32MHz)
input logic i_ads_dout ,// ADS1675 串行数据
output logic o_fifo_wr ,// FIFO 写脉冲 (单周期)
output logic [P_DATA_WIDTH-1:0] o_fifo_data // FIFO 并行数据 (24-bit)
);
localparam L_CNT_W = $clog2(P_DATA_WIDTH) ;// 位计数器位宽 (5bit)
localparam L_CNT_M = P_DATA_WIDTH ;// 位计数器最大值 (24)
typedef enum logic [1:0] {
S_IDLE = 2'b00 ,// 空闲态: 等待首个 DRDY
S_WAIT_MSB = 2'b01 ,// 等待MSB: DRDY已见, 等MSB SCLK边沿
S_CAPTURE = 2'b10 // 采集态: 移位采集24bit数据
} state_t ;// 状态机类型
state_t r_cu_state ;// 现态寄存器
state_t r_nx_state ;// 次态寄存器 (三段式用)
logic r_drdy_r0 ;// DRDY 同步0 (1级采样)
logic r_drdy_r1 ;// DRDY 同步1
logic r_drdy_r2 ;// DRDY 同步2
logic r_sclk_r0 ;// SCLK 同步0 (1级采样)
logic r_sclk_r1 ;// SCLK 同步1
logic r_sclk_pos_d1 ;// w_sclk_pos 延迟1拍
logic r_potential_msb ;// 潜在MSB边沿标记 (SCLK↑但DRDY未确认)
logic r_saved_dout ;// 潜在MSB边沿时保存的DOUT值
logic [P_DATA_WIDTH-1:0] r_shift_reg ;// 移位寄存器 (MSB先行左移)
logic [L_CNT_W-1:0] r_bit_cnt ;// 位计数器 (0=空闲, 1~24=采集)
logic [P_DATA_WIDTH-1:0] r_data_out ;// 并行数据输出
logic r_fifo_wr_pre ;// FIFO写预脉冲 (SCLK边沿产生)
logic r_fifo_wr ;// FIFO写使能 (延迟1拍对齐data_out)
logic w_drdy_pos ;// DRDY 上升沿 (0→1)
logic w_sclk_pos ;// SCLK 上升沿 (0→1)
logic w_msb_primary ;// MSB主检测 (SCLK↑ 且 DRDY=1 同拍)
logic w_msb_fallback ;// MSB回退检测 (潜在边沿+DRDY后确认)
logic w_msb_detected ;// MSB边沿已确认 (主+回退)
assign w_drdy_pos = r_drdy_r1 && !r_drdy_r2 ;// DRDY上升沿: r1=1且r2=0
assign w_sclk_pos = r_sclk_r0 && !r_sclk_r1 ;// SCLK上升沿: r0=1且r1=0
assign w_msb_primary = (r_cu_state == S_WAIT_MSB)
&& w_sclk_pos && r_drdy_r0 ;// 主检测: SCLK↑同拍DRDY=1
assign w_msb_fallback = (r_cu_state == S_WAIT_MSB)
&& r_potential_msb && r_drdy_r0 ;// 回退检测: 潜在边沿+DRDY确认
assign w_msb_detected = w_msb_primary || w_msb_fallback ;// MSB确认: 主检测或回退检测
assign o_fifo_wr = r_fifo_wr ;// FIFO写使能输出
assign o_fifo_data = r_data_out ;// FIFO并行数据输出
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_cu_state <= S_IDLE ;// 复位→空闲态
else
r_cu_state <= r_nx_state ;// 次态→现态
end
always_comb begin
case (r_cu_state)
S_IDLE: begin
r_nx_state = S_WAIT_MSB ;// MSB边沿确认→进入采集态
end
S_WAIT_MSB: begin
if (w_msb_detected)
r_nx_state = S_CAPTURE ;// MSB边沿确认→进入采集态
else
r_nx_state = r_cu_state ;// 保持等待态
end
S_CAPTURE: begin
if (w_sclk_pos && r_bit_cnt == L_CNT_W'(L_CNT_M - 1))
r_nx_state = S_WAIT_MSB ;// 采集完24bit→等待下次DRDY
else
r_nx_state = r_cu_state ;// 保持采集态
end
default: r_nx_state = S_IDLE ;// 安全回退→空闲态
endcase
end
//DRDY 同步链 (3级打拍, 同类信号同块)
always_ff @(posedge i_clk) begin
r_drdy_r0 <= i_ads_drdy ;// 第0级: 捕获IO
r_drdy_r1 <= r_drdy_r0 ;// 第1级: 同步
r_drdy_r2 <= r_drdy_r1 ;// 第2级: 同步
end
//SCLK 同步链 (2级打拍)
always_ff @(posedge i_clk) begin
r_sclk_r0 <= i_ads_sclk ;// 第0级: 捕获IO
r_sclk_r1 <= r_sclk_r0 ;// 第1级: 同步
end
//SCLK 上升沿延迟1拍 (MSB回退检测用)
always_ff @(posedge i_clk) begin
r_sclk_pos_d1 <= w_sclk_pos ;// 延迟1拍
end
//潜在MSB边沿记录 (S_WAIT_MSB态, SCLK↑但DRDY尚未确认)
always_ff @(posedge i_clk) begin
if (!i_rstn) begin
r_potential_msb <= 1'b0 ;// 复位清除
r_saved_dout <= 1'b0 ;// 复位清除
end else if (r_cu_state == S_WAIT_MSB && w_sclk_pos && !r_drdy_r0) begin
r_potential_msb <= 1'b1 ;// 标记潜在MSB边沿
r_saved_dout <= i_ads_dout ;// 保存当前DOUT (可能为MSB)
end else if (r_drdy_r0) begin
r_potential_msb <= 1'b0 ;// DRDY确认或超时→清除标记
r_saved_dout <= r_saved_dout ;
end else if (w_sclk_pos) begin
r_potential_msb <= 1'b0 ;// 新SCLK边沿→上次非MSB, 清除
r_saved_dout <= r_saved_dout ;
end else begin
r_potential_msb <= r_potential_msb ;
r_saved_dout <= r_saved_dout ;
end
end
//位计数器
// S_IDLE/S_WAIT_MSB: 保持0
// MSB确认瞬间: 初始化为1 (MSB=第1个bit)
// S_CAPTURE + SCLK↑: 递增计数
// 计到L_CNT_M(24)后: 自动回到S_WAIT_MSB, 计数器被下一状态清零
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_bit_cnt <= '0 ;
else if (r_cu_state == S_WAIT_MSB && w_msb_detected)
r_bit_cnt <= L_CNT_W'(1) ;// MSB确认→bit_cnt=1
else if (r_cu_state == S_CAPTURE && w_sclk_pos)
r_bit_cnt <= r_bit_cnt + L_CNT_W'(1) ;// 采集态+SCLK↑→计数递增
else if (r_cu_state != S_CAPTURE)
r_bit_cnt <= '0 ;// 非采集态→清零
else
r_bit_cnt <= r_bit_cnt ;
end
//移位寄存器 (MSB先行, 左移)
// MSB确认瞬间: 装入MSB (主检测用当前DOUT, 回退检测用保存的DOUT)
// S_CAPTURE + SCLK↑: 左移1位, LSB装入当前DOUT
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_shift_reg <= '0 ;
else if (r_cu_state == S_WAIT_MSB && w_msb_primary)
r_shift_reg <= {r_shift_reg[P_DATA_WIDTH-2:0], i_ads_dout} ;// 主检测: 当前DOUT即MSB
else if (r_cu_state == S_WAIT_MSB && w_msb_fallback)
r_shift_reg <= {r_shift_reg[P_DATA_WIDTH-2:0], r_saved_dout} ;// 回退检测: 用保存的DOUT
else if (r_cu_state == S_CAPTURE && w_sclk_pos)
r_shift_reg <= {r_shift_reg[P_DATA_WIDTH-2:0], i_ads_dout} ;// 采集态+SCLK↑: 左移装入
else
r_shift_reg <= r_shift_reg ;
end
//数据锁存 (bit_cnt==24时锁存完整的24bit并行数据)
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_data_out <= '0 ;
else if (r_bit_cnt == L_CNT_W'(L_CNT_M))
r_data_out <= r_shift_reg ;// bit_cnt=24→锁存移位寄存器
else
r_data_out <= r_data_out ;
end
// FIFO写预脉冲 (bit_cnt==23 且 SCLK↑ 时产生, 即第24个bit移入时刻)
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_fifo_wr_pre <= 1'b0 ;
else if (r_cu_state == S_CAPTURE && w_sclk_pos
&& r_bit_cnt == L_CNT_W'(L_CNT_M - 1))
r_fifo_wr_pre <= 1'b1 ;// 第24bit移入→预写脉冲
else
r_fifo_wr_pre <= 1'b0 ;// 单周期脉冲, 其余时刻清零
end
//FIFO写使能 (延迟r_fifo_wr_pre 1拍, 对齐r_data_out锁存时刻)
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_fifo_wr <= 1'b0 ;
else
r_fifo_wr <= r_fifo_wr_pre ;// 延迟1拍: 与data_out同时有效
end
endmodule
六、FPGA 采集设计(LVDS 版本)
6.1 与 CMOS 版本的差异
LVDS 版本核心采集逻辑(状态机、MSB 检测、移位寄存、FIFO 对齐)完全复用 CMOS 版本代码,仅物理层不同:
- FPGA 时钟提升至 300MHz(96MHz SCLK 需 >3× 采样率)
- 输入管脚改为差分对(DRDY_P/N、SCLK_P/N、DOUT_P/N)
- 例化 3 个 IBUFDS 原语,DIFF_TERM="TRUE" 使能内部 100Ω 终端
- IBUFDS 输出的单端信号接入相同的同步器和状态机
6.2 IBUFDS 例化
IBUFDS #(.DIFF_TERM("TRUE")) u_ibuf_drdy (.I(drdy_p), .IB(drdy_n), .O(w_drdy));
IBUFDS #(.DIFF_TERM("TRUE")) u_ibuf_sclk (.I(sclk_p), .IB(sclk_n), .O(w_sclk));
IBUFDS #(.DIFF_TERM("TRUE")) u_ibuf_dout (.I(dout_p), .IB(dout_n), .O(w_dout));
FPGA 管脚约束需设置 IOSTANDARD = LVDS_25。
6.3 时序(手册 Figure 1)
LVDS 模式下 PLL 将 CLK 倍频至 96MHz。tLSCLKDR=2.03.0ns,tLDOPD=1.52.5ns,DRDY 脉宽 2~4 个 SCLK 周期。数据帧 24×10.417ns≈250ns,远小于 1MSPS 的 1024ns 周期,裕量充足。

c
`timescale 1 ns / 1 ns
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: felix
//
// Create Date:
// Design Name:
// Module Name: ads1675_capture_lvds
// Project Name:
// Target Devices: Xilinx ZYNQ7030
// Tool Versions:
// Description:
// ADS1675 24-bit 串行数据采集模块 (LVDS 接口版本)。
// 模式: LL Fast-Response, DRATE=011 (1MSPS)
// 接口: LVDS 差分对 (SCLK/DOUT/DRDY) + 内部 SCLK (SCLK_SEL=0)
// 控制: START=高 (连续转换), CS=低
//
// 手册 Figure 1 关键时序 (LVDS 模式, 内部 SCLK):
// - SCLK = 差分, 连续自由运行, f_SCLK = 3×f_CLK = 96MHz, 周期 10.417ns
// - DRDY = 差分, 数据就绪脉冲, 脉宽 2~4 T_SCLK ≈ 20~40ns
// - tLSCLKDR = SCLK↑ → DRDY↑ = 2.0~3.0ns (本设计取 2.5ns)
// - tLDOPD = SCLK↑ → DOUT 有效 = 1.5~2.5ns (本设计取 2.0ns)
// - MSB(D23) = 在 DRDY 拉高的那个 SCLK 边沿呈现 (与 DRDY 同一 SCLK↑)
// - 数据帧 = 24 SCLK 周期 ≈ 250ns, DRDY 周期 = 1024ns@1MSPS (裕量充足)
// - 24-bit 二进制补码, MSB 先行
//
// 设计: FPGA 300MHz 过采样 (96MHz SCLK 需 >3× 采样率确保可靠),
// IBUFDS 转换差分→单端, 三段式 FSM 采集
//
// Dependencies:
//
// Revision:
// date version author description
//
//
//////////////////////////////////////////////////////////////////////////////////
module ads1675_capture_lvds
#(
parameter P_DATA_WIDTH = 24 // ADC 数据位宽
)
(
input logic i_clk ,// FPGA 300MHz 时钟
input logic i_rstn ,// 异步复位 (低有效)
input logic i_ads_drdy_p ,// ADS1675 DRDY 差分正端
input logic i_ads_drdy_n ,// ADS1675 DRDY 差分负端
input logic i_ads_sclk_p ,// ADS1675 SCLK 差分正端
input logic i_ads_sclk_n ,// ADS1675 SCLK 差分负端
input logic i_ads_dout_p ,// ADS1675 DOUT 差分正端
input logic i_ads_dout_n ,// ADS1675 DOUT 差分负端
output logic o_fifo_wr ,// FIFO 写脉冲 (单周期)
output logic [P_DATA_WIDTH-1:0] o_fifo_data // FIFO 并行数据 (24-bit)
);
localparam L_CNT_W = $clog2(P_DATA_WIDTH) ;// 位计数器位宽 (5bit)
localparam L_CNT_M = P_DATA_WIDTH ;// 位计数器最大值 (24)
typedef enum logic [1:0] {
S_IDLE = 2'b00 ,// 空闲态: 等待首个 DRDY
S_WAIT_MSB = 2'b01 ,// 等待MSB: DRDY已见, 等MSB SCLK边沿
S_CAPTURE = 2'b10 // 采集态: 移位采集24bit数据
} state_t ;// 状态机类型
state_t r_cu_state ;// 现态寄存器
state_t r_nx_state ;// 次态寄存器 (三段式用)
logic r_drdy_r0 ;// DRDY 同步0 (1级采样)
logic r_drdy_r1 ;// DRDY 同步1
logic r_drdy_r2 ;// DRDY 同步2
logic r_sclk_r0 ;// SCLK 同步0 (1级采样)
logic r_sclk_r1 ;// SCLK 同步1
logic r_sclk_pos_d1 ;// w_sclk_pos 延迟1拍
logic r_potential_msb ;// 潜在MSB边沿标记 (SCLK↑但DRDY未确认)
logic r_saved_dout ;// 潜在MSB边沿时保存的DOUT值
logic [P_DATA_WIDTH-1:0] r_shift_reg ;// 移位寄存器 (MSB先行左移)
logic [L_CNT_W-1:0] r_bit_cnt ;// 位计数器 (0=空闲, 1~24=采集)
logic [P_DATA_WIDTH-1:0] r_data_out ;// 并行数据输出
logic r_fifo_wr_pre ;// FIFO写预脉冲 (SCLK边沿产生)
logic r_fifo_wr ;// FIFO写使能 (延迟1拍对齐data_out)
logic w_drdy ;// DRDY 单端 (IBUFDS输出)
logic w_sclk ;// SCLK 单端 (IBUFDS输出)
logic w_dout ;// DOUT 单端 (IBUFDS输出)
logic w_drdy_pos ;// DRDY 上升沿 (0→1)
logic w_sclk_pos ;// SCLK 上升沿 (0→1)
logic w_msb_primary ;// MSB主检测 (SCLK↑ 且 DRDY=1 同拍)
logic w_msb_fallback ;// MSB回退检测 (潜在边沿+DRDY后确认)
logic w_msb_detected ;// MSB边沿已确认 (主+回退)
IBUFDS #(.DIFF_TERM("TRUE")) u_ibuf_drdy (
.I (i_ads_drdy_p) ,// 差分正端
.IB (i_ads_drdy_n) ,// 差分负端
.O (w_drdy) // 单端输出
);
IBUFDS #(.DIFF_TERM("TRUE")) u_ibuf_sclk (
.I (i_ads_sclk_p) ,// 差分正端
.IB (i_ads_sclk_n) ,// 差分负端
.O (w_sclk) // 单端输出
);
IBUFDS #(.DIFF_TERM("TRUE")) u_ibuf_dout (
.I (i_ads_dout_p) ,// 差分正端
.IB (i_ads_dout_n) ,// 差分负端
.O (w_dout) // 单端输出
);
assign w_drdy_pos = r_drdy_r1 && !r_drdy_r2 ;// DRDY上升沿: r1=1且r2=0
assign w_sclk_pos = r_sclk_r0 && !r_sclk_r1 ;// SCLK上升沿: r0=1且r1=0
assign w_msb_primary = (r_cu_state == S_WAIT_MSB)
&& w_sclk_pos && r_drdy_r0 ;// 主检测: SCLK↑同拍DRDY=1
assign w_msb_fallback = (r_cu_state == S_WAIT_MSB)
&& r_potential_msb && r_drdy_r0 ;// 回退检测: 潜在边沿+DRDY确认
assign w_msb_detected = w_msb_primary || w_msb_fallback ;// MSB确认: 主检测或回退检测
assign o_fifo_wr = r_fifo_wr ;// FIFO写使能输出
assign o_fifo_data = r_data_out ;// FIFO并行数据输出
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_cu_state <= S_IDLE ;// 复位→空闲态
else
r_cu_state <= r_nx_state ;// 次态→现态
end
always_comb begin
case (r_cu_state)
S_IDLE: begin
r_nx_state = S_WAIT_MSB ;
end
S_WAIT_MSB: begin
if (w_msb_detected)
r_nx_state = S_CAPTURE ;// MSB边沿确认→进入采集态
else
r_nx_state = r_cu_state ;// 保持等待态
end
S_CAPTURE: begin
if (w_sclk_pos && r_bit_cnt == L_CNT_W'(L_CNT_M - 1))
r_nx_state = S_WAIT_MSB ;// 采集完24bit→等待下次DRDY
else
r_nx_state = r_cu_state ;// 保持采集态
end
default: r_nx_state = S_IDLE ;// 安全回退→空闲态
endcase
end
//DRDY 同步链 (3级打拍, 同类信号同块)
always_ff @(posedge i_clk) begin
r_drdy_r0 <= w_drdy ;// 第0级: 捕获IBUFDS输出
r_drdy_r1 <= r_drdy_r0 ;// 第1级: 同步
r_drdy_r2 <= r_drdy_r1 ;// 第2级: 同步
end
//SCLK 同步链 (2级打拍)
always_ff @(posedge i_clk) begin
r_sclk_r0 <= w_sclk ;// 第0级: 捕获IBUFDS输出
r_sclk_r1 <= r_sclk_r0 ;// 第1级: 同步
end
//SCLK 上升沿延迟1拍 (MSB回退检测用)
always_ff @(posedge i_clk) begin
r_sclk_pos_d1 <= w_sclk_pos ;// 延迟1拍
end
//潜在MSB边沿记录 (S_WAIT_MSB态, SCLK↑但DRDY尚未确认)
always_ff @(posedge i_clk) begin
if (!i_rstn) begin
r_potential_msb <= 1'b0 ;// 复位清除
r_saved_dout <= 1'b0 ;// 复位清除
end else if (r_cu_state == S_WAIT_MSB && w_sclk_pos && !r_drdy_r0) begin
r_potential_msb <= 1'b1 ;// 标记潜在MSB边沿
r_saved_dout <= w_dout ;// 保存当前DOUT (可能为MSB)
end else if (r_drdy_r0) begin
r_potential_msb <= 1'b0 ;// DRDY确认或超时→清除标记
r_saved_dout <= r_saved_dout ;// 保持
end else if (w_sclk_pos) begin
r_potential_msb <= 1'b0 ;// 新SCLK边沿→上次非MSB, 清除
r_saved_dout <= r_saved_dout ;// 保持
end else begin
r_potential_msb <= r_potential_msb ;// 保持
r_saved_dout <= r_saved_dout ;// 保持
end
end
//位计数器
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_bit_cnt <= '0 ;// 复位清零
else if (r_cu_state == S_WAIT_MSB && w_msb_detected)
r_bit_cnt <= L_CNT_W'(1) ;// MSB确认→bit_cnt=1
else if (r_cu_state == S_CAPTURE && w_sclk_pos)
r_bit_cnt <= r_bit_cnt + L_CNT_W'(1) ;// 采集态+SCLK↑→计数递增
else if (r_cu_state != S_CAPTURE)
r_bit_cnt <= '0 ;// 非采集态→清零
else
r_bit_cnt <= r_bit_cnt ;// 保持
end
//移位寄存器 (MSB先行, 左移)
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_shift_reg <= '0 ;// 复位清零
else if (r_cu_state == S_WAIT_MSB && w_msb_primary)
r_shift_reg <= {r_shift_reg[P_DATA_WIDTH-2:0], w_dout} ;// 主检测: 当前DOUT即MSB
else if (r_cu_state == S_WAIT_MSB && w_msb_fallback)
r_shift_reg <= {r_shift_reg[P_DATA_WIDTH-2:0], r_saved_dout} ;// 回退检测: 用保存的DOUT
else if (r_cu_state == S_CAPTURE && w_sclk_pos)
r_shift_reg <= {r_shift_reg[P_DATA_WIDTH-2:0], w_dout} ;// 采集态+SCLK↑: 左移装入
else
r_shift_reg <= r_shift_reg ;// 保持
end
//数据锁存 (bit_cnt==24时锁存完整的24bit并行数据)
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_data_out <= '0 ;// 复位清零
else if (r_bit_cnt == L_CNT_W'(L_CNT_M))
r_data_out <= r_shift_reg ;// bit_cnt=24→锁存移位寄存器
else
r_data_out <= r_data_out ;// 保持
end
//FIFO写预脉冲 (bit_cnt==23 且 SCLK↑ 时产生, 即第24个bit移入时刻)
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_fifo_wr_pre <= 1'b0 ;// 复位清零
else if (r_cu_state == S_CAPTURE && w_sclk_pos
&& r_bit_cnt == L_CNT_W'(L_CNT_M - 1))
r_fifo_wr_pre <= 1'b1 ;// 第24bit移入→预写脉冲
else
r_fifo_wr_pre <= 1'b0 ;// 单周期脉冲, 其余时刻清零
end
//FIFO写使能 (延迟r_fifo_wr_pre 1拍, 对齐r_data_out锁存时刻)
always_ff @(posedge i_clk) begin
if (!i_rstn)
r_fifo_wr <= 1'b0 ;// 复位清零
else
r_fifo_wr <= r_fifo_wr_pre ;// 延迟1拍: 与data_out同时有效
end
endmodule
七、关键注意事项
- MSB 在同一 SCLK 边沿:手册明确 MSB 与 DRDY 同一 SCLK↑,不是下一个。错位导致数据整体左偏 1 bit。
- 首 DRDY 前不写 FIFO:FSM 初始态 S_IDLE 屏蔽所有 SCLK 活动。
- 同步器必不可少:DRDY/SCLK 均与 FPGA 异步,需 2~3 级同步。
- FIFO 写对齐:r_fifo_wr 必须延迟 1 拍与 data_out 对齐,确保下游采样正确。
- LVDS 需高速 FPGA:96MHz SCLK 要求 FPGA ≥300MHz,保证边沿检测可靠。
- WB 模式慎用:55 周期滤波器记忆导致输入突变后数据不可靠,快变信号必须用 LL Fast-Response。
- 上电等待:START 拉高后需等待 tSETTLE(@1MSPS≈3.6ms)才有有效 DRDY。
- 参考电压旁路:VREFP/VREFN 各需 10µF+0.1µF 陶瓷电容紧靠芯片。
- 架构推荐:FPGA 硬件盲采 + 上位机后处理。FPGA 不做数据过滤,前 3~5 笔丢弃。
- HS 模式注意:2M/4M 采样率强制 LVDS,分辨率降为 23-bit。
可自行仿真。
两版本个人仿真均通过。