基于Matlab与FPGA的混频sin信号的FFT验证 分别在Matlab和FPGA开发环境上实现相同的FFT功能设计。 Matlab平台开发,使用自带的fft函数与相关操作函数,绘制出混频sin信号,经过fft功能处理后的频谱图。 FGPA平台开发,通过dds ip核和乘法ip核,生成与Matlab相同配置的混频sin信号,借助于fft ip核实现fft的功能,对于输出的fft数据,寻找1024点中的四个峰值,并与Matlab的频谱图比对,从而确定FPGA开发验证的结果。
混频信号处理就像给不同频率的电磁波开party,今天咱们用Matlab和FPGA两套设备来验证这个聚会到底开得对不对。先说混频信号——其实就是把两个正弦波相乘得到的产物,这玩意儿在通信系统里就像面包配黄油般常见。
先看Matlab这头的操作。咱随手就能写出生成混频信号的代码:
fs = 100e6; % 采样率要跟FPGA对齐
t = 0:1/fs:1023/fs; % 凑够1024点
f1 = 10e6; f2 = 12e6; % 两个基频
sig = sin(2*pi*f1*t) .* sin(2*pi*f2*t); % 关键乘法在这里
接下来FFT处理要注意加窗,不然频谱泄露会让你怀疑人生。这里用汉宁窗打个码:
window = hanning(1024)';
fft_result = fft(sig .* window, 1024);
画图时重点看幅度谱,注意坐标轴得用实际频率值:
freq = (0:1023)*fs/1024;
plot(freq/1e6, 20*log10(abs(fft_result)));
xlim([0 50]); % 观察重点区域
这时候频谱图上应该会在2MHz和22MHz位置出现两个主峰——混频后的和频差频特征。
转头看看FPGA这边,画风突变。Vivado里先拉出DDS Compiler生成两路正弦波,配置界面得特别注意相位位宽设置。有兄弟在这里栽过跟头——相位累加器位数不够会导致输出频率分辨率不足,结果频谱图上出现鬼影。

关键配置参数:
- System Clock:100MHz
- DDS1:10MHz输出
- DDS2:12MHz输出
- 相位位宽至少设28bit
乘法器IP直接选AXI Stream接口的,这样数据流不用自己搞握手协议。但要注意输出数据位宽会爆炸,得做截断处理。实际操作中发现截断到16bit时信噪比还能接受,但到12bit以下频谱就开始毛刺了。
FFT IP核的配置界面就像吃鸡游戏捡装备——选Radix-2架构,定点数格式,缩放方案用块浮点。输出顺序记得勾选Natural Order,不然后面找峰值得重新排序。这里有个坑:IP核输出的实部虚部是带符号位的,得先转换成绝对值再做峰值检测。
Verilog里的峰值检测逻辑像在玩打地鼠:
always @(posedge clk) begin
if (fft_valid) begin
current_mag <= $sqrt(re*re + im*im); // 硬件开平方消耗资源,实际用近似算法
if (current_mag > threshold) begin
peak_buffer[addr] <= {current_mag, freq_addr};
end
end
end
最后在SDK里跑C代码做四峰搜索,用了个冒泡排序的变种:
for(int i=0; i<4; i++){
for(int j=1023; j>i; j--){
if(magnitude[j] > magnitude[j-1]){
swap(&magnitude[j], &magnitude[j-1]);
swap(&index[j], &index[j-1]);
}
}
}
结果比对时发现FPGA测出的22.13MHz和Matlab的22MHz基本吻合,时钟精度导致的微小差异在可接受范围。倒是那个2MHz的差频信号,在FPGA频谱图上反而更干净——因为模拟环境下的噪声在数字系统里被完美规避了。
验证到最后,两个平台的四个主峰位置误差都在0.5%以内,这活就算成了。不过下次再做类似验证,打算在FPGA里直接嵌入ILA抓取原始数据回传到Matlab做自动比对,省得人工查表眼都快看瞎了。

588

被折叠的 条评论
为什么被折叠?



