1. 项目概述与核心需求
在工业测量和通信系统中,两路正弦信号的相位差检测是个经典问题。传统模拟电路方案受温度漂移和噪声影响较大,而基于FPGA的数字信号处理方案具有精度高、稳定性好的优势。本次项目采用Altera Cyclone IV系列FPGA,通过FFT算法实现两路1MHz正弦波的相位差检测,目标分辨率达到0.5度以内。
选择FFT方案而非过零检测法,主要考虑三个因素:一是FFT对噪声不敏感,二是可以同时获取幅值和相位信息,三是便于后续扩展为多频点分析。实测表明,在50MHz采样率下,1024点FFT的相位检测标准差仅为0.12度,完全满足电机控制、超声波测距等应用场景的需求。
2. 硬件平台选型与配置
2.1 FPGA芯片选择
采用Cyclone IV EP4CE15F23C8N芯片主要基于以下考量:
- 内置36个18x18乘法器(满足FFT核计算需求)
- 15K逻辑单元(LE)资源裕量充足
- 支持100MHz以上系统时钟
- 成本控制在工业级应用可接受范围
注意:若选用更小规模的EP4CE6系列,FFT核运行时会面临资源紧张问题,可能导致时序违例。
2.2 时钟架构设计
系统采用分层时钟方案:
verilog复制PLL_100M u_pll(
.inclk0(50M_osc),
.c0(clk_100M), // 主时钟
.c1(clk_50M) // ADC采样时钟
);
关键参数:
- FFT计算时钟:100MHz(确保1024点FFT在10μs内完成)
- ADC采样时钟:50MHz(满足奈奎斯特采样定理)
- 时钟偏斜控制:小于0.5ns(通过TimeQuest约束文件保证)
3. FFT核配置与优化
3.1 IP核参数设置
在Quartus II 13.1中配置FFT IP核时,重点调整以下参数:
- 变换长度:1024点(相位分辨率=360°/1024≈0.35°)
- 数据格式:单精度浮点(避免定点数运算的量化误差)
- 流水线级数:4级(平衡速度和资源消耗)
- 旋转因子存储:使用Block RAM(节省逻辑资源)
3.2 实信号处理技巧
对于实信号输入,采用虚部接地法优化资源:
verilog复制fft_core fft_inst (
.sink_real(adc_data_real), // 12位ADC数据
.sink_imag(12'd0), // 虚部强制置零
/* 其他信号连接 */
);
此方法相比复数FFT可节省约40%的乘法器资源,但需注意:
- 输出频谱存在镜像对称性
- 相位计算时需取前512点有效数据
4. 相位计算实现细节
4.1 CORDIC算法优化
采用Q31定点数格式的CORDIC核计算相位角:
verilog复制cordic_atan cordic_inst(
.x_in(abs_real[30:0]), // 取绝对值后的实部
.y_in(abs_imag[30:0]), // 取绝对值后的虚部
.phase_out(raw_phase) // 输出[-π, +π]
);
符号位处理采用流水线设计:
verilog复制always @(posedge clk) begin
quad_judge <= {fft_imag[31], fft_real[31]};
abs_real <= fft_real[30:0];
abs_imag <= fft_imag[30:0];
end
此设计比传统if-else分支节省2个时钟周期。
4.2 相位差补偿算法
针对±π跳变问题,设计环形补偿逻辑:
verilog复制always @(posedge clk) begin
phase_diff_raw <= phase_a - phase_b;
phase_diff <= (phase_diff_raw > 32'h40000000) ? phase_diff_raw - 32'h80000000 :
(phase_diff_raw < 32'hC0000000) ? phase_diff_raw + 32'h80000000 :
phase_diff_raw;
end
其中:
- 32'h40000000 对应π(Q31格式)
- 32'h80000000 对应2π
- 32'hC0000000 对应-π
5. 系统同步与调试
5.1 双通道同步方案
采用深度为8的同步FIFO确保采样对齐:
verilog复制sync_fifo fifo_dual(
.data({adc_a, adc_b}), // 两路ADC输入
.wrreq(adc_valid), // ADC数据有效
.rdreq(fft_sink_ready), // FFT核就绪
.q({sync_a, sync_b}) // 同步输出
);
关键参数:
- FIFO宽度:24bit(12bit x 2通道)
- 几乎满阈值:6(防止溢出)
- 读写时钟比:1:1(同源时钟)
5.2 SignalTap调试技巧
配置触发条件为:
- FFT帧起始脉冲(sink_sop)
- 相位差超限报警(phase_diff >阈值)
存储设置:
- 采样深度:2048点
- 触发位置:50%预触发
- 捕获信号:包含原始ADC数据和相位差结果
常见问题排查:
- 频谱泄漏:检查窗函数应用(建议使用Hanning窗)
- 相位跳变:确认环形补偿逻辑生效
- 结果抖动:检查FIFO同步状态
6. 资源优化与性能测试
6.1 资源占用分析
编译报告显示:
- 逻辑单元:8923/15408(57%)
- 乘法器:36/56(64%)
- 存储器:128Kb/516Kb(24%)
优化建议:
- 降频到80MHz可节省15%逻辑资源
- 改用定点数FFT节省30%乘法器
- 减少FFT点数到512可降低50%存储消耗
6.2 实测性能指标
测试条件:
- 输入信号:1MHz正弦波,-1dBFS幅值
- 相位差设置:45°阶跃变化
测试结果:
| 指标 | 测量值 |
|---|---|
| 分辨率 | 0.35° RMS |
| 线性误差 | <0.5° |
| 温度漂移 | 0.01°/℃ |
| 处理延迟 | 25.6μs |
7. 工程移植与扩展
7.1 跨平台移植要点
迁移到Xilinx平台需注意:
- 替换FFT IP为XFFT核
- 调整CORDIC核接口(相位输出格式不同)
- 修改时钟约束文件(XDC替代SDC)
7.2 多通道扩展方案
通过时分复用支持4通道检测:
verilog复制mux_4ch u_mux(
.sel(cnt[1:0]),
.in({ch1, ch2, ch3, ch4}),
.out(adc_data)
);
需配套修改:
- FFT核配置为4倍时钟
- 增加通道标识缓存
- 调整相位差计算流水线
我在实际项目中发现,当处理1MHz以上信号时,建议在ADC输入端增加抗混叠滤波器。某次现场调试就因忽略了200kHz的干扰信号,导致相位检测出现周期性误差。后来通过增加二阶Butterworth滤波器(fc=1.5MHz)彻底解决了问题。
