在工业测量和通信系统中,两路正弦信号的相位差检测是个经典需求。比如电机控制中需要检测转子位置,超声波测距中要处理回波相位,电力系统监控中要分析电压电流相位关系。传统模拟电路方案受温漂和噪声影响大,而基于FPGA的数字信号处理方案具有精度高、稳定性好的优势。
这次我们要在Altera Cyclone IV FPGA上实现一个实时相位差检测系统,核心指标要求:
为什么选择FFT方案而不是过零检测或相关分析法?这里有个实际项目中的教训:去年用Xilinx Artix-7做过一个过零检测方案,当信号含有谐波时,相位误差会达到3°以上。而FFT方法通过频谱分析能有效抑制谐波干扰,实测在相同条件下误差<0.5°。
系统由三个关键模块构成:
选择Cyclone IV EP4CE115的理由:
注意:新项目建议改用Cyclone 10 LP系列,同等资源下功耗降低40%
在Quartus II 13.1中配置FFT IP核时,这些参数需要特别注意:
verilog复制fft_core fft_inst (
.transform_size(10'd10), // 1024点FFT
.twiddle_width(18), // 旋转因子位宽
.data_in_width(16), // 匹配ADC输出
.data_out_width(32), // 保留足够精度
.use_ram_for_twiddles(1) // 用Block RAM存旋转因子
);
实测发现三个影响精度的关键点:
传统方案是用浮点运算器做atan2计算,但在FPGA中会占用大量DSP资源。我们采用三级流水线CORDIC实现:
verilog复制// 第一级:象限预处理
always @(posedge clk) begin
if(fft_valid) begin
quad <= {fft_imag[31], fft_real[31]};
x_in <= fft_real[30:0] >> 2; // 防止溢出
y_in <= fft_imag[30:0] >> 2;
end
end
// 第二级:CORDIC迭代
cordic_phase #(
.ITER(16)
) u_cordic (
.clk(clk),
.x_in(x_in),
.y_in(y_in),
.phase_out(raw_phase)
);
// 第三级:象限补偿
always @(posedge clk) begin
case(quad)
2'b00: phase <= raw_phase;
2'b01: phase <= raw_phase + 32'h40000000;
2'b10: phase <= raw_phase - 32'h40000000;
2'b11: phase <= raw_phase;
endcase
end
这个设计在150MHz时钟下仅消耗412个LE和2个DSP,比浮点方案节省68%资源。
初期测试发现相位差存在±5°的随机跳动,用SignalTap抓取波形发现是两路信号采样不同步导致。解决方案:
verilog复制sync_fifo #(
.WIDTH(32),
.DEPTH(16)
) fifo_ab (
.wr_clk(adc_clk),
.rd_clk(sys_clk),
.data_in({adc_a, adc_b}),
.data_out({sync_a, sync_b})
);
当FFT点数从1024降到512时:
折中方案:采用768点FFT,资源占用7120LE,分辨率0.46°,满足大多数应用需求。
测试条件:
| 指标 | 实测值 | 理论值 |
|---|---|---|
| 相位分辨率 | 0.38° | 0.35° |
| 动态范围 | 86dB | 90dB |
| 处理延迟 | 42μs | 40μs |
| 资源占用 | 68% | 70% |
在电机控制现场测试中,相比传统Resolver方案,该设计将转子位置检测误差从±1.5°降低到±0.4°,同时成本降低60%。