FPGA实现希尔伯特变换的全流程解析:从原理到硬件实现
引言
上一篇文章介绍了实信号转换为复信号的两种方法:希尔伯特变换和混频法,这篇文章就结合实际的项目详细的讲解一下FPFA实现希尔伯特变换的全部过程。
希尔伯特变换作为信号处理中的核心工具,在通信系统、医学成像、雷达信号处理等领域广泛应用。FPGA因其并行处理能力和可重构特性,成为实现实时希尔伯特变换的理想平台。本文将深入探讨基于FPGA的希尔伯特变换实现全流程,涵盖数学原理、滤波器设计、硬件架构和代码实现,并结合MATLAB仿真与FPGA验证案例进行剖析。
一、希尔伯特变换原理与数学建模
1.1 希尔伯特变换的定义
希尔伯特变换的时域表达式为:
H
[
x
(
t
)
]
=
1
π
∫
−
∞
∞
x
(
τ
)
t
−
τ
d
τ
H[x(t)] = \frac{1}{\pi} \int_{- \infty}^{\infty} \frac{x( \tau)}{t- \tau} d \tau
H[x(t)]=π1∫−∞∞t−τx(τ)dτ
其频域传递函数为:
H
(
ω
)
=
−
j
(
sin
(
ω
)
)
=
{
−
j
,
ω
>
0
j
,
ω
<
0
H( \omega) = -j( \sin (\omega)) = \begin{cases} -j, \omega >0 \\ j\quad, \omega < 0 \end{cases}
H(ω)=−j(sin(ω))={−j,ω>0j,ω<0
该变换将正频率分量相移-90°,负频率分量相移+90°,生成正交信号对。
1.2 解析信号的构造
将原信号 $ x(t) $ 与其希尔伯特变换 $\hat{x}(t) $ 组合为解析信号:
z
(
t
)
=
x
(
t
)
+
j
x
^
(
t
)
=
A
(
t
)
e
j
ϕ
(
t
)
z(t) = x(t) + j \hat{x}(t) = A(t) e^{j \phi (t)}
z(t)=x(t)+jx^(t)=A(t)ejϕ(t)
其中
A
(
t
)
A(t)
A(t) 为瞬时幅度,
ϕ
(
t
)
ϕ(t)
ϕ(t) 为瞬时相位,可进一步解调出频率和相位信息。
二、希尔伯特滤波器的设计
2.1 FIR滤波器设计要点
- 幅度特性:全通滤波器,通带增益为1
- 相位特性:正频率-90°相移,负频率+90°相移
- 阶数选择:必须为偶数阶(N=2k),且在0Hz和Nyquist频率处增益为0
2.2 MATLAB滤波器设计流程
1、生成滤波器系数的matlab代码
% 使用fdesign.hilbert 设计滤波器
d = fdesign.hilbert('N,TW', 64, 0.1); % 64阶,过渡带宽0.1*Fs
Hd = design(d, 'equiripple', 'SystemObject', true);
% 系数量化(16位定点)
coef = Hd.Numerator;
q_coef = fi(coef, 1, 16, 15); % 符号位1,总位宽16,小数位15
%绘制滤波器系数的频率响应图
[h,w] = freqz(coef); % 频率响应
% 幅度谱(幅度取线性值)
figure()
subplot(2,1,1)
plot(w/pi,abs(h),'r','LineWidth',1.5)
grid on
axis([0 1 -0.1 1.2])
title('Magnitude spectrum of the filter')
ylabel('Magnitude')
% 幅度谱(幅度取dB值)
subplot(2,1,2)
plot(w/pi,db(h),'b','LineWidth',1.5)
grid on
axis([0 1 -80 10])
xlabel('Normalized Frequency (\times\pi rad/sample)')
ylabel('Magnitude (dB)')
关键参数:
- 通带波纹:<0.1dB(对应绝对误差<5‰)
- 阻带衰减:>60dB(确保正交精度)
- 量化处理:将< 2 − 15 2^{-15} 2−15 的系数归零,优化硬件资源
图1 滤波器的频率响应图
2 滤波器系数保存为.coe文件
h = q_coef.int; %获取滤波器系数的十进制表示法
len = length(h);
fp = fopen('fir_data.coe','wt');%创建并打开存储滤波器系数的文件
fprintf(fp,'Radix = 10;\n');%以十进制的方式写入滤波器系数
fprintf(fp,'CoefData =');
for i=1 : len
dat = h(i);
if(i == len)
fprintf(fp,'%d;',dat);
else
fprintf(fp,'%d,\n',dat);
end
end
fclose(fp);%关闭文件
最终生成一个存储滤波器系数的文件“fir_data.coe”。在FPGA实现中需要调用这个文件用于实现希尔伯特滤波器。
三、FPGA实现架构
3.1 系统架构设计
module hilbert_transform (
input i_clk, // 系统时钟
input i_rst, // 复位信号
input [15:0] i_din, // 输入信号(16位定点)
input i_en, // 输入信号有效
output [15:0] o_idata, // 同相分量
output [15:0] o_qdata, // 正交分量
output o_vld // 输出信号有效
);
wire [15:0] w_qdata;
wire w_qvld;
wire [15:0] w_idata;
wire w_ivld;
// FIR滤波器IP核实例化
fir_hilbert u_fir_hilbert (
.aresetn (~i_rst ),
.aclk (i_clk ), // input wire aclk
.s_axis_data_tvalid (i_en ), // input wire s_axis_data_tvalid
.s_axis_data_tready ( ), // output wire s_axis_data_tready
.s_axis_data_tdata (i_din ), // input wire [15 : 0] s_axis_data_tdata
.m_axis_data_tvalid (w_qvld ), // output wire m_axis_data_tvalid
.m_axis_data_tdata (w_qdata ) // output wire [15 : 0] m_axis_data_tdata
);
// 延迟补偿模块
delay_data u_delay_data (
.i_clk (i_clk ),
.i_rst (i_rst ),
.i_din (i_din ),
.i_en (i_en ),
.o_dout (w_idata ),
.o_vld (w_ivld )
);
assign o_qdata = w_qdata;
assign o_idata = w_idata;
assign o_vld = w_ivld & w_qvld;
endmodule
3.2 Xilinx FIR IP核配置
-
打开IP界面 → \rightarrow → 搜索"fir"关键字 → \rightarrow → 双击“FIR Compiler” 进入FIR IP的参数配置界面
-
设置IP名称“fir_hilbert” → \rightarrow → 选择Filter Options栏 → \rightarrow →选择“COE File”选项采用coe文件的方式导入滤波系数 → \rightarrow →选择之前matlab生成的“fir_data.coe”文件 → \rightarrow → 滤波器类型选择“Single Rate”
-
选择Implementation栏 → \rightarrow → 设置输出数据为从低位截取“Truncate LSBs” → \rightarrow → 输出数据位宽设置为“16”
-
其他参数保持默认,最后点击“OK”完成FIR IP的参数配置
四、关键实现技术
4.1 相位补偿技术
由于FIR滤波器引入固定延迟 D = ( N − 1 ) 2 + D 0 D= \frac {(N-1)} {2} + D_0 D=2(N−1)+D0 ( D 0 D_0 D0 表示IP核引入的延时,在IP核的配置界面可以看到具体数值,界面见下图红框)
所以在具体工程中需要对原始信号进行延迟匹配的操作:
// 延迟补偿模块
module delay_data(
input i_clk,
input i_rst,
input [15:0] i_din,// 输入的原始数据
input i_en,
output [15:0] o_dout,// 对齐延迟后的数据
output o_vld
);
parameter S_DELAY = 32 + 40 + 1; // 65阶滤波器延迟32周期,IP延时40,输出打一拍
reg [15:0] r_delay_chain [0:S_DELAY-1];
reg [S_DELAY-1:0] r_delay_chain_en;
integer i;
always @(posedge i_clk) begin
r_delay_chain[0] <= i_din;
for (i=1; i<S_DELAY; i=i+1)
r_delay_chain[i] <= r_delay_chain[i-1];
end
always @(posedge i_clk) begin
if(i_rst)
r_delay_chain_en <= 'h0;
else
r_delay_chain_en <= {r_delay_chain_en[S_DELAY-2:0],i_en};
end
assign o_dout = r_delay_chain[S_DELAY-1]; // 对齐延迟后的数据
assign o_vld = r_delay_chain_en[S_DELAY-1];
endmodule
4.2 资源优化策略
- 系数对称性利用:希尔伯特滤波器系数满足 h ( n ) = − h ( N − 1 − n ) h(n)=-h(N-1-n) h(n)=−h(N−1−n),减少50%乘法器
- 折叠结构:采用4级折叠,将64阶滤波器分解为16个基本单元
- 位宽压缩:中间结果采用18位动态位宽,输出截断至16位
五、系统验证与误差分析
5.1 MATLAB-FPGA联合验证流程
- 测试信号生成:
fs = 100e3; % 采样率100kHz
t = 0:1/fs:0.1;
f1 = 10e3;
f2 = 30e3;
x = 0.5*sin(2*pi*f1*t) + 0.3*cos(2*pi*f2*t);
- FPGA仿真数据导出:
generate
string file_iq_i = "fpga_i.txt";
string file_iq_q = "fpga_q.txt";
integer out_file_iq_i;
integer out_file_iq_q;
initial begin
out_file_iq_i = $fopen(file_iq_i,"w");
out_file_iq_q = $fopen(file_iq_q,"w");
end
always @(posedge i_clk)begin
if(w_iqvld)begin
$fwrite(out_file_iq_i,"%d\n",$signed(w_idata));
$fwrite(out_file_iq_q,"%d\n",$signed(w_qdata));
end
end
endgenerate
- 误差分析:
% 读取FPGA输出数据
fpga_i = load('fpga_i.txt');
fpga_q = load('fpga_q.txt');
% 计算正交误差
ideal_phase = angle(hilbert(x))’;
actual_phase = angle(fpga_i + 1j*fpga_q);
phase_error = rms(ideal_phase - actual_phase); % 典型值<0.05 rad
- 资源消耗:
5.2 实测性能指标
参数 | 指标 |
---|---|
相位误差 | <1° RMS |
资源消耗 | 443 LUTs |
最大时钟频率 | 200 MHz |
信噪比(SNR) | >72 dB |
六、结论
本文详细论述了FPGA实现希尔伯特变换的完整流程。通过MATLAB的fdesign.hilbert设计64阶等纹波FIR滤波器,结合Xilinx 的FIR Compiler IP核实现,最终在Virtex-7 FPGA硬件平台实现200MHz处理速率的希尔波特变换。实测结果表明,该方案相位误差小于1°,满足多数通信系统的正交解调需求。
七、预告
本篇文章介绍了实信号转换为复信号的第一种方法(希尔伯特变换)在FPGA上的实现的具体过程,下一篇文章将详细讲解实信号转换为复信号的第二种方法(混频法)在FPGA上的具体实现过程。感兴趣的小伙伴可以关注一下博主