前言
本次方案除增益为 1 的加法器部分外,核心处理逻辑均由 FPGA 配合 STM32 完成。主要目标是输入混合信号 C,从中解调出原始的两路波形 A'和 B'。
题目背景
题目要求从信号发生器输出两路波形 A 和 B,通过加法器生成信号 C。我们需要做的就是从 C 中将 A'和 B'解出来。常见的思路是对 C 进行傅里叶变换识别成分后分离,但考虑到重构波形与原信号时钟不同步会导致相位漂移,本方案采用了锁相环技术来锁定相位。
系统架构
数据流向如下: C 信号 → 高速 ADC → FPGA → FIFO → 串口 → STM32 → FFT 分析 → 识别波形/频率 → 串口 → DDS 重构 → 锁相环 → 高速 DAC → A',B'
核心模块实现
1. 数据采集与传输(FPGA)
这部分主要解决跨时钟域问题。ADC 采样率为 1MHz,而串口发送速率仅为 12.5KHz,中间必须使用 FIFO 缓冲。
FIFO 控制逻辑 写入侧跟随 ADC 时钟(1MHz),读取侧跟随串口波特率分频后的时钟。状态机控制读写使能,防止溢出或下溢。
assign ad9238_clk_ch0 = clk_1M;
wire wr_en, rd_en, full, empty;
reg [7:0] w_data;
localparam W_IDLE = 1, W_FIFO = 2;
reg[2:0] write_state, next_write_state;
always@(posedge clk_1M or negedge rst) begin
if(rst == 1'b0) write_state <= W_IDLE;
else write_state <= next_write_state;
end
always@(*) begin
case(write_state)
W_IDLE: if(empty == 1'b1) next_write_state <= W_FIFO; else next_write_state <= W_IDLE;
W_FIFO: if(full == 1'b1) next_write_state <= W_IDLE; else next_write_state <= W_FIFO;
default: next_write_state <= W_IDLE;
endcase
end
assign wr_en = (next_write_state == W_FIFO) ? 1'b1 : 1'b0;
// ... 后续 FIFO 实例化代码 ...
串口通信
FPGA 端负责将采集到的数据打包发送,并接收 STM32 返回的分析结果。帧头设为 0xFF,帧尾 0xFE,中间包含波形类型和频率信息。
注意:实际工程中 tx_vilid 拼写有误,应修正为 tx_valid,这里保留原意但建议统一命名规范。
2. 信号分析与识别(STM32)
STM32 通过串口中断接收数据,利用 DSP 库进行 FFT 运算。由于题目不要求峰峰值完全一致,我们主要关注频谱特征。
FFT 处理流程
- 确定频率范围 20KHz-100KHz,步进 5KHz。
- 计算各频段能量,找出能量最大的两个点作为主波频率。
- 根据基波幅值判断波形:正弦波单音集中,三角波含三次谐波导致基波削弱。设定阈值区分正弦波与三角波。
// FFT 能量聚集与峰值查找
for (int i=35; i<1000; i++) {
freq = (int)(((float)i*1000000/2048/5000)+0.5);
if(freq==freq_last) {
v_max = FFT_output[i]*FFT_output[i]+v_max;
} else {
v_max = sqrt(v_max);
freq_change[cnt] = v_max;
fre[cnt] = freq;
freq_last=freq;
cnt++;
}
}
// 筛选最大两个能量点
for(int i=0; i<100; i++) {
if(freq_change[i]>max[0]) { /* 更新最大值 */ }
else if(freq_change[i]>max[1] && freq_change[i]<max[0]) { /* 更新次大值 */ }
}
// 判定波形类型
if(max[0]>5.7) wave[0] = 0; // 正弦波
else wave[0] = 1; // 三角波
串口回传 根据识别结果,按协议格式打包波形类型和频率索引,发回 FPGA。
3. 波形重构与锁相(FPGA)
收到反馈后,FPGA 内部启动 DDS 模块重构波形。这里有个关键问题:重构时钟与源信号时钟存在微小差异,长期运行会产生相位漂移,因此必须引入锁相环。
DDS 模块 使用 ROM 存储正弦和三角波表,通过相位累加器寻址。支持动态调整频率和相位。
数字锁相环(DPLL) 鉴相环节将输入信号与输出信号相乘并通过低通滤波器得到误差电压,经 PI 调节后反馈给 DDS 的相位寄存器,实现相位同步。
mult_mix mult_mix_A (.A(ADC_signed), .B(DAC_A), .P(mix_A));
LPF LPF_A (.s_axis_data_tdata(A_filter), .m_axis_data_tdata(A_filter_out));
Loop_filter Loop_filter_A(.i_pd(A_filter_out), .o_frequency_df(A_phase));
4. 人机交互与输出
移相控制 通过按键设置相位差,数码管实时显示当前相位值。按键需做消抖处理,避免误触发。
DAC 输出 最终数据送入高速 DAC 转换为模拟信号输出。注意 DAC 数据需进行偏移处理以匹配双极性输出范围。
总结
整个系统通过软硬件协同,实现了信号的实时分离与重构。关键点在于跨时钟域的数据传输稳定性、FFT 算法的精度以及锁相环参数的整定。实际调试中,环路滤波器的 Kp 和 Ki 参数需要反复微调,确保波形无抖动且跟踪迅速。

