FPGA基带与中频算法实现:从DDC到同步均衡的工程实践
2026/9/7 1:48:03 网站建设 项目流程

跟很多做FPGA的兄弟聊天时发现一个普遍现象:数字信号处理的理论课都学过,但一到“基带”和“中频”这些词在FPGA工程里落地,就很容易懵。中频算法到底是谁在管?基带算法又该放在哪一级?为什么板子上同时接了ADC、LVDS、PCIe、MIPI,算法链路一复杂,资源和时序就开始打架?这些问题我在不同项目里反复遇到过,所以这篇把基带与中频的FPGA算法实现与应用技术做一个系统梳理。内容会涵盖整体设计思路、DDC/DUC、同步、均衡、信道估计、编解码等核心算法的FPGA落地方案,以及FMC通信、PCIe、LVDS这些实际工程中离不开的接缝技术。无论你是刚入门FPGA通信开发,还是已经在做软件无线电、雷达信号处理,这篇文章应该都能帮你把脑子里那团算法云变成一张可以施工的图纸。

这个领域最讨巧的地方在于:FPGA的并行性和算法的高吞吐需求天生合拍。中频侧的信号速率动辄上百Msps,靠DSP串行处理往往捉襟见肘,FPGA则可以把抽取、混频、滤波拆成多个并行支路,用面积换速度。基带侧的同步和均衡虽然算法复杂,但符号速率相对低,给FPGA留出了大量流水线调优空间。所以说,中频和基带在FPGA上其实各有各的难题,理解清楚它们的分工,后面实现起来才能有的放矢。

1. 基带与中频算法在FPGA上的整体设计思路

1.1 先分清分工:中频处理的是“波形”,基带处理的是“符号”

很多项目一上来就铺开整个收发链路,结果大家讨论问题时驴唇不对马嘴。我习惯先画一条红线:中频处理的是实信号波形,基带处理的是复基带符号流。这条线画清楚了,模块划分就顺了。

中频侧的典型任务包括DDC(数字下变频)、DUC(数字上变频)、中频检波、AGC、CIC滤波、半带滤波、IQ不平衡校正等。这些模块处理的都是“点”,也就是ADC采样出来的一个个数据点,采样率越高,每秒过的点数越多,对并行度要求就越苛刻。基带侧的典型任务则是符号同步、载波同步、均衡、信道估计、解映射、信道编解码等,处理的是“符号”,符号速率远低于采样率,每个符号对应多个采样点,数据率更友好,但算法逻辑更复杂,状态更多。

FPGA平台上的经典结构是:ADC进来的射频/中频信号,先经过数字下变频变成零中频的I/Q基带信号,经过抽取降速,交给基带算法。发射侧反过来,基带I/Q数据经过成型滤波、插值、数字上变频,变成中频实信号送给DAC。这条链路的每个环节都可以在FPGA里用Verilog或SystemVerilog实现,难点不在单个模块,而在相邻模块之间怎么握手、怎么对齐延迟、怎么控制增益和溢出。

这里有个工程细节容易被忽略:中频侧模块的位宽设计要非常小心。ADC输出通常是14位或16位,但经过混频、滤波、抽取后,中间节点的位宽如果只按理论信噪比去设计,往往在强信号下直接溢出。我一般建议每经过一个固定增益级,至少增加2比特余量,直到数据率降下来之后再通过移位或截位恢复满幅度。

1.2 方案选型的三个关键判断

FPGA上实现基带中频算法,方案选型决定了后面八成的工作量。我总结了三个最关键的判断点,基本每个项目都绕不开。

第一是采样结构的选择。是实采样还是正交采样,直接决定中频链路的复杂度。实采样只需要一路ADC,但带通采样之后频谱会有镜像,必须靠希尔伯特滤波器或者混频器来恢复复信号,后续处理比较绕。正交采样需要两路ADC和一整套I/Q通道校准,硬件成本高,但频谱干净,基带算法实现起来直观很多。现在主流的高速ADC和射频收发芯片多半内置了正交采样开关,FPGA侧重点反而是IQ校准和镜像抑制,这个选型一定要提前看硬件,不能光从算法角度拍脑袋。

第二是数据流组织的选择。FPGA里没有“按需取数”这种事,所有数据都是流式处理。同一个FIR滤波器,是做成串行MAC结构共用DSP48,还是做成多相并行结构用BRAM存数据,直接决定了吞吐率和资源占用。举个例子,一个128阶FIR,采样率250Msps,如果用串行结构,单周期做一个乘法累加,那几乎不可能跑到250MHz;反过来,把它拆成8路多相子滤波器,每路子滤波器工作在31.25MHz,资源开销增加,但时序压力小得多。选哪个,取决于你手里是什么型号的FPGA,以及板卡留给FPGA的时钟资源。

第三是资源和功耗的平衡。基带侧算法里,信道编解码和均衡往往是资源大户,而中频侧的滤波和混频则是DSP48消耗大户。我见过不少项目在中频滤波上下了血本,结果基带的LDPC译码器没有BRAM放软信息,最后不得不返工。正确做法是先估算整个算法链路的DSP48、BRAM、FF资源需求,留出20%余量,再决定滤波器阶数和并行度。这点在Xilinx的Vivado和Intel的Quartus里都有资源评估工具,千万别偷懒。

2. 中频侧核心算法:DDC/DUC、中频检波与AGC

2.1 DDC为什么绕不开CIC加补偿FIR这套组合

DDC就是把中频实信号搬到零中频,再抽取降速。很多新手上来就写一个混频器再加一个大阶FIR抽取,结果算一下乘法器开销,直接傻眼。实际工程里最常用的组合是CIC滤波器和补偿FIR配合,原因很简单:抽取滤波器需要的阶数太高,单独用FIR做不现实。

CIC(级联积分梳状滤波器)的最大优势是没有乘法器,只有加法器和延迟,很适合放在抽取链路的最前面。它的频率响应是经典的Sinc形状,通带不够平坦,旁瓣衰减也一般,所以不能单独用。标准做法是CIC负责降速,把它后面的普通FIR设计成补偿滤波器,把CIC的通带滚降补回来。

我做一个具体项目时的参数供参考:ADC采样率245.76Msps,中频信号70MHz,目标是输出30.72Msps的基带I/Q数据,总抽取倍数为8。我选用4级CIC,抽取4倍加上后面的半带滤波器抽取2倍。CIC的微分延迟取1,归一化增益需要仔细计算。4级CIC的增益是4的4次方,也就是256,输出位宽比输入要增加8位。如果ADC输出是14位,CIC输出至少22位。很多人在这块截位太激进,信号动态范围直接损失,星座图糊成一团。

补偿FIR设计成63阶,通带边缘按照信号带宽的1.2倍设置,用来补偿CIC的Sinc跌落。这里有个小技巧:Vivado的FIR Compiler里可以直接导入CIC补偿系数,MATLAB里用fdesign.ciccomp函数生成一组系数,再量化为16位定点导入IP核。补偿FIR放在抽取后,工作时钟只有61.44Msps,单路串行MAC就够,DSP48消耗并不多。整套DDC用下来,资源消耗不超过一块中等FPGA的百分之十五。

2.2 中频检波的几种方法及FPGA实现差异

中频检波这个概念在雷达和通信里经常出现,本质是从中频信号里提取幅度、相位或者频率信息。最常见的几种方法包括包络检波、乘积检波(同步检波)、以及基于数字锁相环的相干检波。三者适用场景完全不同,放在FPGA上的实现代价也差很多。

包络检波最简单,就是取绝对值再加低通滤波,适合AM解调和简单的幅度检测。FPGA里甚至不需要DSP48,用加法器和移位就能做一个递归平均低通。缺点是它丢掉了相位信息,如果后续需要做相干处理就没法用。

同步检波是工程里最实用的方案。它的核心是本地产生一个与输入中频载波同频同相的参考信号,然后用乘法器把中频信号搬回基带,再通过低通滤波得到I/Q分量。FPGA实现时需要一个NCO(数控振荡器)做本地载波,NCO的频率控制字由中频频率和系统时钟决定,相位则通过锁相环或者Costas环来锁定。热词里提到“中频检波有几种方法(如同步检波)”,在这个语境下点一下:同步检波的优点是能够同时获得I/Q幅度,灵敏度高;缺点是必须在频偏范围内维持相位锁定,否则解调误差直线上升。

还有一种数字相干检波,本质是带锁频功能的同步检波。它在同步检波的基础上,把频差检测也加进来,通过频率控制字自动跟踪输入信号的载波漂移。FPGA里实现通常用一个二阶环路,频率字和相位字各自用一个积分器控制。这套结构在卫星通信和雷达多普勒测量里非常常见,参数调起来比Costas环复杂一些,但只要环路带宽设计合理,长期稳定性很好。

2.3 AGC的实现要防“阶梯感”

AGC的作用是把波动很大的中频信号幅度拉到ADC满量程附近,让后面的基带算法有足够比特数去表现信号细节。FPGA里的数字AGC一般不直接控制硬件增益,而是通过时变增益乘子对数据流做幅度缩放。听起来简单,实际做的时候有个很头疼的问题:如果增益调整步长太大,输出波形会出现明显的“阶梯感”,星座图上一圈一圈的散点。

我的做法是分级处理。第一级用较慢的时间常数做平均幅度检测,平滑系数取0.001左右,负责跟踪长时间衰落;第二级用较快的包络检测做瞬时保护,防止强干扰把后续滤波器推饱和。两级综合出一个增益控制字,用查表法映射成浮点增益的定点近似。

这里必须提醒一点:AGC增益更新频率不能太高,否则会引入额外的频谱扩展。通常增益字每符号周期更新一次就够了,不要在每采样点都跳。实测下来这个方案在20MHz带宽信号下,能把输入动态范围60dB的信号压到±0.5dB的输出波动范围,后面的同步和均衡工作压力能小很多。

3. 基带侧核心算法:同步、均衡、信道估计与编解码

3.1 符号同步:Gardner定时恢复的FPGA实现要点

符号同步是基带处理里出Bug最多的地方。接收端采样时钟和发送端存在频偏相偏,必须靠插值滤波器在任意时刻重新采样,才能在每个符号的最佳点取数。工程中最常见的架构是Gardner定时恢复环:它由定时误差检测器、环路滤波器和内插滤波器三部分组成,好处是每个符号只需要两个采样点(中间点和边缘点),实现代价低。

FPGA里做Gardner环的核心模块是内插器。最常用的是Farrow结构的立方插值器,它用四阶多项式拟合采样点之间的任意时刻值。Farrow结构的优点是不需要存放大量插值系数,而是用固定系数加当前位置μ值来计算,非常适合流水线实现。我做过一个8路并行的Gardner环,每路子通道独立计算误差,再用平均误差去调整全局的插值位置。这样做的原因很简单:并行路数多了之后,单路误差抖动很大,平均之后环路才稳定。

环路滤波器的系数决定了同步的速度和抖动。我通常用二阶环路,比例系数决定跟踪带宽,积分系数决定对频偏的补偿能力。一个经验值是把环路等效噪声带宽设到符号速率的0.1%左右,既能跟上晶振的ppm级频偏,又不会被噪声带偏。实测下来,一个16QAM的调制信号,在SNR约25dB时,Gardner环的定时抖动可以做到符号周期的1%以内。

3.2 载波同步:QPSK/QAM解调绕不开Costas环

基带信号如果存在残余频偏和相偏,星座图会旋转,任何判决都没有意义。所以载波同步是解调器里必须有的模块。低速场景可以用帧头做数据辅助估计,但连续流解调几乎都用判决反馈环,比如QPSK的Costas环,以及QAM用的通用DD(Decision-Directed)环。

QPSK的Costas环实现比较巧妙:它用解调后的I/Q符号极性乘出来一个误差信号,误差信号经过环路滤波器控制NCO,最终让本地载波相位锁定到输入信号。FPGA里实现时,乘法器和环路滤波器都不难,难的是锁相环的启动流程。冷启动时频偏可能达到数kHz,这时候需要先用频率扫描或FFT粗估频偏,把误差压到环路捕获范围内,再切到Costas细跟踪。我吃过亏的地方就在这里,直接上Costas环捕获大频偏,环路要么失锁要么锁定在错误相位上。

QAM高阶调制不能用简单的极性判决做误差,标准做法是用最近星座点做硬判决,然后计算判决误差。这个误差可以同时驱动载波环和均衡器,组成联合盲均衡结构。FPGA里的DSP48实现一个复数乘法需要4个实数乘法,设计时一定要预先估算好乘法器资源。128阶均衡器加符号率30Msps的QAM信号,很容易吃掉几百个DSP48,选型阶段就要留够余量。

3.3 均衡与信道估计:LMS、RLS和卡尔曼滤波的FPGA选型

无线信道难免有多径,多径带来时延扩展,符号间干扰就会冒出来。均衡器的作用就是用一个自适应滤波器去逼近信道逆响应,把符号间干扰压下去。最常用的自适应算法有LMS和RLS。LMS实现简单,每个系数更新只需要一次乘加,FPGA里一个DSP48可以做多个系数的时分复用更新,但收敛慢,信噪比低时表现一般。RLS收敛快,但涉及协方差矩阵更新和矩阵求逆,FPGA实现复杂得多,通常只在OFDM系统的频域均衡里用。

另一个热词“卡尔曼滤波FPGA”也值得说几句。卡尔曼滤波在FPGA上的常见应用是信道估计和联合跟踪,但它本身需要矩阵运算和状态协方差更新,传统上更偏DSP处理。现在很多新架构把卡尔曼滤波用在时变信道的预测上,与LMS构成两级联合均衡:卡尔曼预测信道变化趋势,LMS负责细调。这种组合在高速移动场景下效果不错,但代价是资源和时序压力都上去了。我的建议是,如果信道变化速率不高,直接用LMS加少量训练序列就够了,没必要为了“技术先进”硬上卡尔曼。

均衡器拆分时还要注意符号速率与采样率的关系。常用的均衡器结构是符号间隔均衡器(T-spaced)和分数间隔均衡器(T/2-spaced),后者对采样相位不敏感,性能更好,代价是滤波器长度翻倍。FPGA里处理T/2间隔均衡,常见做法是把奇数时刻和偶数时刻拆成两条子滤波器,再组合输出。这个拆分技巧在很多基带解调器里都能复用。

3.4 信道编解码是真正的资源大户

基带侧最吃资源的往往不是同步和均衡,而是信道编解码。尤其LDPC译码器,需要大量BRAM存放软信息,迭代次数和块长决定时延。对于通信基带SoC来说,LDPC一般是单独核,甚至放在专用硬件加速器里。FPGA上做LDPC也有成熟IP,但项目中的传输块大小和码率经常变化,IP配置灵活性会是一大痛点。

相比之下,卷积码加Viterbi译码在FPGA里实现传统且稳定。约束长度7的卷积码,(2,1,7)结构,Viterbi译码器需要64个状态,每个状态做加比选运算,整体并行展开后大概占用不到500个FF和几百个LUT,在FPGA里非常轻量。RS码则常用于突发错误纠正场景,比如存储和深空通信,FPGA里可以做成有限域乘法器阵列,但逻辑规模取决于生成多项式的复杂度。

信道编解码这块最大的坑是帧同步和软信息位宽。很多项目在仿真时用浮点模型跑得挺好,一上硬件就变差,问题多半出在软信息量化位宽。我一般把软信息至少量化为6比特,低于这个数值,LDPC性能损失就会超过0.5dB。Viterbi译码的软判决输入建议用8比特,配合适当的归一化因子,性能损失可以控制在零点几dB以内。

4. 实操过程:完整链路搭建与关键模块代码实现

4.1 一个可落地的基带加中频FPGA处理链路

拿一个具体的通信接收机链路来举例,可以让大家更直观看到各模块是怎么串起来的:

射频前端输出中频信号进入ADC,ADC的采样数据和随路时钟通过LVDS送到FPGA。FPGA内部先做LVDS转并行数据,再由DDC做数字下变频,把中频实信号变成零中频I/Q复信号,经过CIC和半带抽取降到基带。基带信号接下来进入符号同步模块,用Farrow内插器恢复最佳采样点,经过匹配滤波和均衡器后,完成载波同步和相位补偿,得到干净的星座点。最后通过符号判决、解交织、信道译码,恢复出比特流,再通过PCIe DMA或以太网口输出到上位机。

发射路径反过来走:基带比特经过信道编码、符号映射,再经过成型滤波(根升余弦)得到基带I/Q波形,通过半带插值和CIC滤波把数据率拉高,最后经过DUC数字上变频到中频,送给DAC输出。

这套收发链路中,最容易出问题的地方是接收路径的DDC输出位宽和符号同步之间的接口。CIC/HB/FIR多级滤波都做了抽取,每级如果都规范化,低位数据很容易被丢掉。我提供了一个经验法则:在FPGA内部保留定点小数位,直到最后一步符号判决前再截位,中间尽量保持高精度。这个做法虽然增加一点BRAM消耗,但能避免动态范围损失。

如果板卡里MCU是STM32H743这类器件,FPGA和MCU之间的FMC通信也是常见的接缝工程。FMC本质上是一个并行内存接口,FPGA可以把基带解调后的数据块映射到某个地址区间,MCU直接以总线读取。配置时要注意FMC的读写时序参数,比如ADDST和数据建立保持时间,必须和FPGA内部状态机匹配。我通常在FPGA里把FMC接口设计成伪双口RAM:MCU通过FMC地址总线访问,FPGA逻辑通过AXI接口写入,两边用乒乓缓冲避免读写冲突。

4.2 NCO、混频器和Farrow内插器的关键代码结构

中频链路的核心基础模块是NCO。NCO相位累加器本质上就是一个不断累加频率控制字的寄存器:

// 相位累加器 always @(posedge clk) begin if (rst) begin phase_acc <= 0; end else begin phase_acc <= phase_acc + phase_inc; end end // 通过查表输出正余弦 assign sin_out = sin_rom[phase_acc[PHASE_WIDTH-1 : PHASE_WIDTH-ADDR_WIDTH]]; assign cos_out = cos_rom[phase_acc[PHASE_WIDTH-1 : PHASE_WIDTH-ADDR_WIDTH]];

相位累加器位宽决定了频率分辨率。系统时钟245.76MHz,NCO位宽32位,频率分辨率可以做到0.057Hz,完全满足大多数载波跟踪需求。为了改善SFDR,可以在低位加抖动(dithering),把量化杂散摊平到整个频带。工程中建议加上这个抖动,代价只是几个寄存器和一张小的LUT表。

混频器就是两个实数乘法器组合成复乘:

// I/Q混频 assign i_mix = i_in * cos_out - q_in * sin_out; assign q_mix = i_in * sin_out + q_in * cos_out;

这里的重点是DSP48的流水线寄存器一定要打深一些。我习惯在乘法器输出加两级寄存器再做加减,这样时序会好很多。Vivado综合时把宏定义成DSP48映射,资源利用率会明显改善。

Farrow内插器的核心是一个四阶多项式,用μ值做当前插值位置。简化代码如下:

// 一阶加权版本 assign y = (1 - mu) * d1 + mu * d2; // 立方Farrow需要四个相邻采样点,通过子滤波器组实现 // c0 = -0.5*x1 + 1.5*x2 - 1.5*x3 + 0.5*x4 // c1 = x1 - 2.5*x2 + 2*x3 - 0.5*x4 // c2 = -0.5*x1 + 0.5*x3 // c3 = x2 // y = ((c0*mu + c1)*mu + c2)*mu + c3

这段代码是立方Farrow的简化实现,实际工程中还需要对μ值做溢出保护,因为环路滤波器输出的μ可能略微超出0到1范围。我通常对μ做饱和处理,超过1就回绕为0并给定时误差检测器一个“调整完成”的脉冲。

4.3 仿真验证与上板调试的衔接

FPGA开发中,仿真和上板往往是两套思路。仿真时用MATLAB或Python生成带有频偏、相偏、噪声和衰落的测试向量,导入Verilog testbench作为激励源;上板后则通过ILA(集成逻辑分析仪)或SignalTap抓取中间节点数据,在电脑上对波形和星座图。

我建议在RTL设计阶段就预留几个调试探针端口。比如DDC的I/Q输出、Gardner误差信号、AGC增益字、均衡器抽头系数,这些信号不用都接到外部引脚,但要在模块顶层引出。上板调试时不要光盯着星座图看,先把环路的误差信号波形抓下来。环路参数是否振荡、锁定时间是否过长,误差信号的波形里都写得明明白白,比瞎调系数高效得多。

仿真模型和RTL实现之间最容易出现偏差的是CIC滤波器的增益控制。MATLAB里的浮点模型不会溢出,但定点RTL在强信号时可能饱和。所以仿真测试向量里一定要加入满量程信号,验证CIC的中间位宽和截位是否合理。这一步没做好,上板之后信号稍强一点,星座图会在某个固定位置撕裂,排查起来相当费劲。

5. 常见问题排查技巧与工程经验总结

5.1 典型问题速查表

我把这些年项目里碰到的高频问题整理成一个速查表,按这个顺序排查,基本能解决八成基带中频FPGA的疑难杂症。

异常现象可能原因排查手段解决思路
星座图整体旋转载波频偏未消除ILA抓Costas误差信号,看是否收敛增设粗频偏估计,扩大捕获范围
星座图发散但有规则圆环定时相位抖动过大检查Gardner误差输出调整环路滤波器带宽,减少积分系数
信号带宽内出现明显杂散NCO SFDR不足抓混频前/FFT观察增加NCO抖动,提高输出位宽
CIC输出强信号时星座图撕裂中间节点溢出定点仿真加入满量程信号增加CIC输出位宽,提前留出增益余量
均衡器不收敛训练序列与数据错位检查训练序列同步状态机先验证训练序列检测,再开自适应更新
FMC读回数据全是FF/00读写时序不匹配示波器抓FMC总线时序调整FMC读周期/等待状态数
LDPC译码性能急剧下降软信息位宽不足或归一化错误对比定点与浮点仿真软信息统计提升软信息位宽并校准LUT归一化系数
板卡功耗异常偏高DSP48翻转率过高查看功耗报告,定位高频翻转模块增加流水线级数,降低单周期逻辑深度

5.2 基带中频FPGA调试的几条硬经验

调试这套系统,最忌讳一上来就开所有模块的仿真,然后把波形窗口铺满整个屏幕。经验做法是先让各模块“孤立可测”。每个算法模块独立成IP,外部能输入测试向量,内部有探针输出,这样做的好处是出问题时能立刻定位到具体模块,而不是在两个模块的接口处扯皮。

第二个经验是环路参数一定要在仿真里先用定点模型扫一遍边界。比如Gardner环的比例系数从1/16扫到1/128,积分系数从1/1024扫到1/4096,找出锁定时间和抖动都能接受的区间。上板后再根据实际信道特征在这个区间里微调,不要指望一次半调就能最优。

第三个经验跟时序收敛有关系。中频侧的高采样率时钟域和基带侧的低速时钟域之间,必须用异步FIFO做隔离,绝不能用同一时钟硬跑到底。很多工程师为了让设计简单,把所有模块都挂在同一个时钟树上,结果基带侧的组合逻辑把中频侧的时序拖到崩溃。正确做法是“中频时钟域只管采样点级处理,基带时钟域只管符号级处理”,时钟域交叉处用异步FIFO加AXI-Stream握手。

5.3 工具链与学习路线的建议

Xilinx平台建议用Vivado加ModelSim/Questa做联合仿真,Vivado自带的ILA调试工具配合VIO可以实时修改环路参数,非常实用。Intel平台则推荐Quartus加SignalTap,两者调试思路一致,差异在IP核配置界面。仿真阶段强烈建议在MATLAB里完成浮点模型和定点模型的完整对照,RTL代码先不急着写,先把算法级验证彻底,后面改RTL的时间会大幅缩短。

关于学习路线,我建议新入行的朋友先从中频链路入手,把NCO、CIC、半带滤波器、FIR补偿这套“搬移和降速”的功夫练扎实,再进入基带的同步和均衡。因为有太多项目的失败原因是中频链路设计不合理,导致基带模块一直面对质量很差的输入信号。中频链路质量上去了,基带算法的调试难度会降低一个量级。等这两块都熟练了,可以再看LDPC、RS这类纠错码的硬件实现,那时你已经具备完整的系统观念,再复杂的编解码模块也不会觉得无从下手。

最后再补充一个小技巧。如果你的项目里同时涉及多个不同采样率的数据流,我建议在RTL代码里用宏定义把所有采样率、抽取倍数、滤波器阶数都参数化。不要直接写死数字。每次改参数只需要改一处,仿真和综合都能快速验证。这件事看似不起眼,但在项目后期调整信号带宽时,能帮你省下大量来回查找的时间。基带和中频的FPGA实现,说到底是一个系统工程,参数管理、时钟规划和调试手段决定了你能否从“调通一个模块”走向“调通一张网”。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询