Artix-7 FPGA DPLL 实现 50Hz 工频同步 ADC 采样完整方案
目录
核心需求说明
一、整体系统架构框图
模块划分
二、关键参数设计(50Hz 工频标准配置)
1. 系统主时钟(MMCM 生成)
2. 采样点数配置(电力标准 256 点 / 周波)
3. DPLL 环路参数(Type2 二阶)
三、分模块 Verilog 完整实现(Artix-7 通用)
模块 1:输入同步打拍(消除亚稳态)
模块 2:PFD 鉴频鉴相器(提取相位误差 Δφ)
模块 3:二阶数字 PI 环路滤波器(DSP48 定点乘加)
模块 4:32 位 NCO 数控振荡器(生成 50Hz 反馈 + 同步相位)
模块 5:同步采样脉冲生成(256 点 / 工频周期)
模块 6:锁定检测模块(稳定后开启 ADC 采样)
模块 7:DPLL 顶层集成
四、ADC 同步对接方案(AD4134/AD7768-4)
1. AD4134 同步模式
2. AD7768-4 同步模式
3. 多片 ADC 级联同步
五、Artix-7 资源占用评估(XC7A35T)
六、时序约束(xdc 关键约束)
七、工程调参与故障优化
1. 捕获速度慢
2. 锁定后相位抖动大
3. 无法锁定 50Hz
4. ADC 采样频谱泄漏
八、核心优势(对比固定晶振采样)
核心需求说明
互感器校验仪 / 电力采集设备核心诉求:
- 以电网 50Hz 工频为基准,产生同步采样时钟,ADC 每个采样点严格对齐工频相位;
- 消除晶振频偏带来的采样相位漂移,保证多通道 ADC(AD4134/AD7768)同步采集、角差测量高精度;
- 采用 FPGA 内部数字 DPLL(Type-II 二阶 DPLL)锁定外部 50Hz 工频信号,输出同步采样时序给 ADC;
- 适配 Artix-7(XC7A35T/XC7A10T),使用 DSP48 做滤波乘加、BRAM 做 NCO 相位表,无模拟 PLL 依赖。
一、整体系统架构框图
工频输入调理 → 施密特整形 → 同步两级寄存器(消除亚稳态)→ DPLL鉴相器PFD ↓ NCO反馈方波 ← 数字PI环路滤波器 ← 相位误差Δφ ↓ 同步采样时钟分频器 → ADC SPI时序/同步触发信号(同步AD4134/AD7768)模块划分
- 工频同步输入同步器(两级打拍,跨时钟域亚稳态抑制)
- PFD 鉴频鉴相器(检测 50Hz 输入与 NCO 反馈相位差)
- 二阶数字 PI 环路滤波器(Type2,无稳态相位误差)
- 32 位 NCO 数控振荡器(输出 50Hz 基准反馈 + 高频采样时钟)
- 采样时序分频模块(按每周期采样点数输出同步采样脉冲)
- Lock 锁定检测模块(连续多周期误差接近 0 输出同步使能)
二、关键参数设计(50Hz 工频标准配置)
1. 系统主时钟(MMCM 生成)
外部晶振 50MHz → MMCM 倍频输出200MHz 系统时钟 clk_sys
- 系统时钟周期:5ns
- NCO 相位累加器位宽:32bit
- NCO 频率分辨率:fres=fsys/232≈0.046566Hz,足够锁定 50Hz 微小频偏
2. 采样点数配置(电力标准 256 点 / 周波)
- 工频周期 Tgrid=20ms
- 单采样间隔 Ts=20ms/256=78.125μs
- 同步采样脉冲由 NCO 分频生成,保证每 256 点严格对齐工频过零点
3. DPLL 环路参数(Type2 二阶)
传递函数离散域: F(z)=Kp+Ki⋅1−z−1z−1 工程定点参数(200MHz 系统时钟):
- KP = 16’d128(比例系数,加快捕获速度)
- KI = 16’d2(积分系数,消除稳态相位差) 环路带宽≈5Hz,兼顾锁定速度与工频噪声抑制。
三、分模块 Verilog 完整实现(Artix-7 通用)
模块 1:输入同步打拍(消除亚稳态)
工频整形后为 50Hz 方波,属于异步信号,两级寄存器同步到 200MHz 系统时钟域
module grid_sync_two_ff( input wire clk_sys, input wire rst_n, input wire grid_50hz_in, // 外部整形后50Hz方波 output reg grid_sync_out ); reg sync_r1; always @(posedge clk_sys or !rst_n) begin if(!rst_n) begin sync_r1 <= 1'b0; grid_sync_out <= 1'b0; end else begin sync_r1 <= grid_50hz_in; grid_sync_out <= sync_r1; end end endmodule模块 2:PFD 鉴频鉴相器(提取相位误差 Δφ)
检测参考 50Hz 与 NCO 反馈时钟上升沿,输出有符号误差计数
module pfd_phase_detector( input wire clk_sys, input wire rst_n, input wire ref_clk, // 同步后50Hz参考 input wire fb_clk, // NCO输出50Hz反馈方波 output reg signed [15:0] phase_err ); reg ref_r, fb_r; always @(posedge clk_sys or !rst_n) begin if(!rst_n) begin ref_r <= 1'b0; fb_r <= 1'b0; phase_err <= 16'sd0; end else begin ref_r <= ref_clk; fb_r <= fb_clk; // 参考上升沿:反馈滞后,误差+1 if(ref_r == 1'b0 && ref_clk == 1'b1) begin phase_err <= phase_err + 16'sd1; end // 反馈上升沿:参考滞后,误差-1 if(fb_r == 1'b0 && fb_clk == 1'b1) begin phase_err <= phase_err - 16'sd1; end end end endmodule模块 3:二阶数字 PI 环路滤波器(DSP48 定点乘加)
Artix-7 DSP48E1 原生支持 32 位乘累加,无 LUT 资源浪费
module pi_loop_filter( input wire clk_sys, input wire rst_n, input wire signed [15:0] err_in, output reg signed [31:0] freq_word_out // NCO频率控制字 ); localparam KP = 16'd128; localparam KI = 16'd2; reg signed [31:0] integral_acc; wire signed [31:0] prop_term; assign prop_term = $signed(err_in) * KP; always @(posedge clk_sys or !rst_n) begin if(!rst_n) begin integral_acc <= 32'sd0; freq_word_out <= 32'sd0; end else begin integral_acc <= integral_acc + $signed(err_in) * KI; freq_word_out <= prop_term + integral_acc; end end endmodule模块 4:32 位 NCO 数控振荡器(生成 50Hz 反馈 + 同步相位)
输出两路信号:
- fb_clk:50Hz 方波,反馈给 PFD 形成闭环
- phase_addr:相位索引,用于分频产生 ADC 同步采样脉冲
module nco_dco_50hz( input wire clk_sys, input wire rst_n, input wire signed [31:0] freq_word, output reg fb_clk, // 50Hz反馈方波 output wire [15:0] phase_addr ); reg [31:0] phase_acc; always @(posedge clk_sys or !rst_n) begin if(!rst_n) begin phase_acc <= 32'd0; fb_clk <= 1'b0; end else begin phase_acc <= phase_acc + freq_word[31:0]; fb_clk <= phase_acc[31]; // 最高位输出50Hz方波 end end assign phase_addr = phase_acc[31:16]; // 取高16位相位 endmodule模块 5:同步采样脉冲生成(256 点 / 工频周期)
基于 NCO 相位均匀分频,每个工频周期输出 256 个同步采样触发,送给 ADC 同步启动引脚
module adc_sync_sample_gen( input wire clk_sys, input wire rst_n, input wire [15:0] phase_addr, output reg adc_sync_trig // ADC同步采样脉冲 ); localparam SAMPLE_POINT_PER_CYC = 256; localparam PHASE_STEP = 16'hFFFF / SAMPLE_POINT_PER_CYC; reg [15:0] last_phase; always @(posedge clk_sys or !rst_n) begin if(!rst_n) begin last_phase <= 16'd0; adc_sync_trig <= 1'b0; end else begin last_phase <= phase_addr; // 相位跨过采样间隔,产生1拍同步脉冲 if((phase_addr - last_phase) >= PHASE_STEP) begin adc_sync_trig <= 1'b1; end else begin adc_sync_trig <= 1'b0; end end end endmodule模块 6:锁定检测模块(稳定后开启 ADC 采样)
连续 4096 个时钟相位误差极小判定锁定,未锁定禁止 ADC 采集,避免相位乱码
module dpll_lock_detector( input wire clk_sys, input wire rst_n, input wire signed [15:0] phase_err, output reg dpll_locked ); reg [12:0] lock_cnt; always @(posedge clk_sys or !rst_n) begin if(!rst_n) begin lock_cnt <= 13'd0; dpll_locked <= 1'b0; end else if(phase_err >= -8 && phase_err <= 8) begin lock_cnt <= lock_cnt + 1'b1; if(lock_cnt == 13'd4095) dpll_locked <= 1'b1; end else begin lock_cnt <= 13'd0; dpll_locked <= 1'b0; end end endmodule模块 7:DPLL 顶层集成
module top_grid_dpll_adc_sync( input wire clk_50m_ext, // 外部50M晶振 input wire rst_n_ext, input wire grid_50hz_raw, // 调理后50Hz工频输入 output wire adc_sync_pulse,// ADC同步采样触发 output wire dpll_lock_flag // 锁定标志,给MCU/ADC使能 ); // 1. MMCM生成200MHz系统时钟 wire clk_sys, rst_sys_n; clk_wiz_200m mmcm_inst( .clk_in1(clk_50m_ext), .reset(!rst_n_ext), .clk_out1(clk_sys), .locked(rst_sys_n) ); // 2. 工频信号两级同步 wire grid_sync_50hz; grid_sync_two_ff sync_inst( .clk_sys(clk_sys), .rst_n(rst_sys_n), .grid_50hz_in(grid_50hz_raw), .grid_sync_out(grid_sync_50hz) ); // 3. PFD鉴相 wire signed [15:0] err_w; wire fb_50hz_w; pfd_phase_detector pfd_inst( .clk_sys(clk_sys), .rst_n(rst_sys_n), .ref_clk(grid_sync_50hz), .fb_clk(fb_50hz_w), .phase_err(err_w) ); // 4. PI环路滤波 wire signed [31:0] fw_w; pi_loop_filter lf_inst( .clk_sys(clk_sys), .rst_n(rst_sys_n), .err_in(err_w), .freq_word_out(fw_w) ); // 5. NCO本振 wire [15:0] phase_addr_w; nco_dco_50hz nco_inst( .clk_sys(clk_sys), .rst_n(rst_sys_n), .freq_word(fw_w), .fb_clk(fb_50hz_w), .phase_addr(phase_addr_w) ); // 6. ADC同步采样脉冲生成 adc_sync_sample_gen sample_gen_inst( .clk_sys(clk_sys), .rst_n(rst_sys_n), .phase_addr(phase_addr_w), .adc_sync_trig(adc_sync_pulse) ); // 7. 锁定检测 dpll_lock_detector lock_inst( .clk_sys(clk_sys), .rst_n(rst_sys_n), .phase_err(err_w), .dpll_locked(dpll_lock_flag) ); endmodule四、ADC 同步对接方案(AD4134/AD7768-4)
1. AD4134 同步模式
AD4134 支持外部 SYNC 同步输入:
- 将
adc_sync_pulse接入 AD4134SYNC引脚; - DPLL 锁定后,每一个同步脉冲触发 4 通道同步转换;
- 所有通道采样点严格对齐工频同一相位,消除通道间相位偏移,满足 0.02 级互感器角差测量。
2. AD7768-4 同步模式
AD7768-4SYNC_IN全局同步引脚:
- FPGA 输出同步脉冲同步所有调制器;
- 配合 DPLL 50Hz 基准,FFT 谐波分析无频谱泄漏,21 次谐波测量精度达标。
3. 多片 ADC 级联同步
多片 AD4134/AD7768 共用同一路adc_sync_pulse,全局同步采样,标准 CT 与被测 CT 采样时刻完全一致,无分时 MUX 固有相位误差。
五、Artix-7 资源占用评估(XC7A35T)
| 模块 | LUT | FF | DSP48E1 | BRAM |
|---|---|---|---|---|
| DPLL 顶层全套 | 180 | 240 | 3(PI 滤波乘加) | 0 |
| 200MHz MMCM | 0 | 0 | 0 | 0(CMT 硬核) |
| 采样脉冲分频 | 30 | 40 | 0 | 0 |
总资源极低,剩余大量逻辑用于 ADC SPI、数据缓存、FFT 运算。
六、时序约束(xdc 关键约束)
# 外部50M晶振输入时钟 create_clock -name clk_50m -period 20 [get_ports clk_50m_ext] # MMCM生成200MHz系统时钟 create_generated_clock -name clk_sys_200m -source [get_ports clk_50m_ext] -multiply_by 4 [get_pins mmcm_inst/clk_out1] # 异步工频输入约束(虚假路径,两级同步消除亚稳态) set_false_path -from [get_ports grid_50hz_raw] -to [get_regs {sync_r1}] # 同步输出到ADC引脚IO约束 set_output_delay -max 3 -min 0 -clock clk_sys_200m [get_ports adc_sync_pulse]七、工程调参与故障优化
1. 捕获速度慢
增大 KP 比例系数,环路带宽加宽,快速锁定工频;缺点是噪声变大。
2. 锁定后相位抖动大
减小 KP、KI,降低环路带宽,抑制电网谐波噪声。
3. 无法锁定 50Hz
- 工频整形电路幅值不足,方波畸变;
- NCO 初始频率字偏移过大,修改 NCO 初始累加值;
- PFD 输入同步打拍失效,亚稳态导致相位误差错乱。
4. ADC 采样频谱泄漏
DPLL 未锁定时禁止 ADC 采集;锁定后 256 点均匀等分工频周期,无截断误差。
八、核心优势(对比固定晶振采样)
- 消除晶振频偏:不受 FPGA 内部晶振温漂影响,始终跟随电网真实 50Hz;
- 相位同步精度 ns 级,多通道 ADC 同一时刻采样,0.02 级互感器角差测量基础;
- 纯数字逻辑,无模拟 PLL 漂移,全温稳定性强;
- 可灵活配置每周期采样点数(128/256/512),适配谐波、电能计量不同场景;
- Artix-7 资源占用极小,可和 ADC 数据采集、FFT、串口逻辑共存。
