Bootstrap

FPGA实现希尔伯特变换的全流程解析:从原理到硬件实现

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)]=π1tτ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} 215 的系数归零,优化硬件资源

滤波器频响图

图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核配置

  1. 打开IP界面 → \rightarrow 搜索"fir"关键字 → \rightarrow 双击“FIR Compiler” 进入FIR IP的参数配置界面

  2. 设置IP名称“fir_hilbert” → \rightarrow 选择Filter Options栏 → \rightarrow 选择“COE File”选项采用coe文件的方式导入滤波系数 → \rightarrow 选择之前matlab生成的“fir_data.coe”文件 → \rightarrow 滤波器类型选择“Single Rate”

  3. 选择Implementation栏 → \rightarrow 设置输出数据为从低位截取“Truncate LSBs” → \rightarrow 输出数据位宽设置为“16”

  4. 其他参数保持默认,最后点击“OK”完成FIR IP的参数配置

四、关键实现技术

4.1 相位补偿技术

由于FIR滤波器引入固定延迟 D = ( N − 1 ) 2 + D 0 D= \frac {(N-1)} {2} + D_0 D=2(N1)+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 资源优化策略

  1. 系数对称性利用:希尔伯特滤波器系数满足 h ( n ) = − h ( N − 1 − n ) h(n)=-h(N-1-n) h(n)=h(N1n),减少50%乘法器
  2. 折叠结构:采用4级折叠,将64阶滤波器分解为16个基本单元
  3. 位宽压缩:中间结果采用18位动态位宽,输出截断至16位

五、系统验证与误差分析

5.1 MATLAB-FPGA联合验证流程

  1. 测试信号生成:
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);
  1. 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
  1. 误差分析:
% 读取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

FPGA结果与实际的误差图

  1. 资源消耗:

资源消耗图

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上的具体实现过程。感兴趣的小伙伴可以关注一下博主

;