基于FPGA进位链的高精度TDC设计:从RTL到码密度校准实战

发布时间:2026/10/7 23:35:11
基于FPGA进位链的高精度TDC设计:从RTL到码密度校准实战
做高精度时间测量这块很多人一开始想的是用专用TDC芯片比如ACAM那类但做到后面你会发现通道数、集成度、成本各种受限。而在FPGA上直接用进位链做TDC延时链材料成本几乎为零资源还灵活精度做到几十皮秒完全可行。这篇文章就围绕FPGA进位链、TDC这些核心关键词把我从架构设计、RTL实现到码密度校准、实测数据的完整过程写一遍包括踩过的坑和调出来的经验希望能给正在做激光测距、粒子物理实验、PET或者高速接口时间戳的朋友们一个可复现的参考方案。1. 从工程痛点说起高精度时间测量为什么难做TDC前先得搞明白一件事我们要测的时间到底是什么。拿激光测距举例发射脉冲打出去接收端的光电探测器捕获回波这个飞行时间往往只有几十纳秒到几百微秒但测距精度要求却是毫米级甚至亚毫米级别。光速大概0.3mm/ps也就是说想达到1mm的分辨率时间测量的精度就得在3皮秒左右。这个数字对绝大多数电子系统来说都是极其苛刻的。另一个常见的场景是PET和粒子物理实验。这类系统动辄几百上千个通道每个通道都要记录粒子到达的精确时刻时间分辨率直接决定了符合事件判别的准确率。假如用传统的模拟TDC通道数一多成本和功耗立刻失控;用商用芯片单通道几百上千块的报价也扛不住大批量。相比之下FPGA上直接实现TDC延伸出的高精度延时链通道数只要资源够就能做采样逻辑、数据缓存、通信接口全在同一个芯片里搞定系统级设计的难度反而更低。那为什么说时间测量“难”?难在跨尺度。一次测量可能覆盖从纳秒到毫秒乃至更长的范围这是粗计数的活;但分辨率要去到几十皮秒这就是细计数的活。普通计数器累加一个时钟周期是4纳秒或5纳秒远达不到要求;直接拿模拟比较器搭延迟线又很难做稳定因为模拟电路的分立元件延迟受温度、电压影响很大而且难以批量校准。所以主流的思路只有两条要么用足够高频率的时钟采样比如把时钟倍频到GHz级别但这在普通FPGA上既不现实也耗电;要么用抽头延迟线让待测信号在一个延迟链里跑再用参考时钟把所有抽头状态锁存下来通过解码锁存结果反推时间。这条路线恰好是FPGA的强项——芯片内部的进位链本来就带有规则且极短的延迟每个进位级的延迟通常只有几十皮秒比任何外部分立延迟线都均匀可控。从系统角度还要分清“测量分辨率”和“测量精度”的区别。分辨率是这把尺子的最小刻度也就是单个bin的宽度决定了你能读出多细的时间差;而精度是刻度的均匀性和稳定性bin宽参差不齐、温度漂移都会让读数偏离真实值。所以进位链TDC的设计表面上是把延时链做出来实质上是把一个高精度的时间量化器做出来后面的校准、误差分析都必不可少。2. 进位链的物理基础它凭什么能当TDC的“时间尺子”2.1 为什么选进位链而不是LUT链很多第一次接触TDC的同学问过我同样的问题FPGA里到处都是LUT为什么不用LUT串联来做延迟线?答案是LUT到LUT之间的布线路径不可控。LUT和LUT要走通用布线资源每条路径的延迟取决于布局布线结果今天综合出来的延迟和明天重新综合可能就完全不一样而且同一片FPGA上不同位置的路径也各不相同。这种不确定性对做普通逻辑没影响但对需要精细量化时间的TDC来说直接导致每个抽头的位置不确定量化误差完全得不到控制。进位链则完全是另一回事。以Xilinx 7系列为例一个CARRY4由4个MUX级联而成MUX之间是硬连线Cin到Cout的路径是完全固定的硅级路径不经过任何通用布线资源。这样一级一级串下去每一级之间的延迟虽然也受工艺、电压、温度影响但在同一时刻、同一芯片上却是相对一致的。换句话说进位链是一把刻度相对均匀的硬连接时间尺子而LUT链是一把刻度位置飘忽不定的软尺子做测量当然选前者。还有个细节值得留意进位链每一级除了提供延迟还能再往外引出抽头。CARRY4内有4个进位级每一级都有对应的COUT端口。把COUT接出去给触发器采样就能得到信号传播到哪一级的二进制信息。一个CARRY4可以贡献4个采样抽头一个CLB列可以串几十个CARRY4整条链做到256级、512级都很容易。2.2 延迟参数从哪来怎么估精度上限进位链单级的延迟到底是多少?不同厂家、不同速度等级的器件差异不小。以Artix-7为例常规速度等级下CARRY4单个进位级延迟大致在10到50皮秒这个范围工业级和商业级也有差异具体数值要查对应器件的时序手册。不过手册给的是典型值真正的延迟分布还要靠码密度测试来测这一点后面专门讲。估算TDC能达到的理论分辨率有一个简单公式分辨率 参考时钟周期 / 抽头总数。比如参考时钟200MHz5ns一个周期延时链做到512个抽头平均每个bin约9.7ps。当然这只是平均bin宽实际因为PVT波动每个bin会参差不齐这就是后面要校准的原因。为什么参考时钟往往只取几百MHz而不是拉满?因为参考时钟同时驱动采样触发器和粗计数器。时钟频率越高粗计数粒度越细细计数的展开范围也越小对进位链长度的要求就越低但高速时钟带来的动态功耗和时序收敛压力也直线上升。200M到400M是一个比较均衡的区间在这个区间内用中等长度的进位链就能拿到几十皮秒的综合精度。2.3 采样触发器和亚稳态问题延时链做出来后每一级抽头都要挂一个触发器在参考时钟的上升沿把进位链上的电平状态锁存下来。关键点在于信号在进位链里传播到哪一级才停下来和时钟沿到来时刻完全是异步的所以总有一级触发器会落在亚稳态窗口附近。亚稳态的结果是那一位的值不确定你可能在锁存数据里看到“气泡”——比如本应是连续的1或0中间却冒出个反跳。处理气泡的基本原则是不要精确解析每一位而是寻找“最后一个稳定为1的抽头位置”只对连续稳定的区域做判断。多数工程实现里一级采样触发器再跟一级同步触发器能大幅度降低亚稳态向后级传播的概率。实际编码时从进位链读到的数据是一个温度计码的形式信号刚进入的位置全为1还没传到的位置全为0因为被测信号沿是逐个进位级往前推进的谁先到谁先置1。只要能找到1/0的交界位置就能得出时间。交界位置的查找可以用优先级编码器也可以用二分网络;考虑到进位链长度通常几百级优先做好组合逻辑传播延迟控制否则解码逻辑本身会拖慢整体频率。3. 整体架构粗计数、细计数与温度计码的转换逻辑TDC的系统架构其实就是一把“粗刻度尺细刻度尺”的双级尺子。参考时钟覆盖宏观时间范围由计数器实现粗计数;进位链覆盖一个时钟周期内的微观时间由抽头锁存实现细计数。两部分拼起来才能既保证量程又保证分辨率。3.1 粗计数部分为什么要两个计数器粗计数的通常做法是用两个自由运行的计数器。一个在待测信号的起始沿到来时锁定当前值另一个在停止沿到来时锁定当前值两个计数值相减乘上时钟周期就是粗时间。听起来用一个计数器就能完成但实际上需要两个因为START和STOP是异步事件无法预测它们各自落在哪个时钟沿附近现场不可能用一个FIFO或寄存器同时保存两个时刻的值。两个计数器方案的好处是结构简单、时序清晰。每个事件触发时通过专用的捕获寄存器把对应计数器的输出锁存随后再统一处理。假如一个通道既要测START也要测STOP那就得给START和STOP各配一对计数器或者用同一个计数器在不同时刻分别锁存状态机里做好标记即可。粗计数的时间基准必须与细计数的采样时钟完全同源否则粗计数的时钟域和采样TDC的时钟域存在相位差拼接时会引入系统偏差。通常做法是把同一个PLL输出的时钟既送到计数器又送到进位链采样触发器这样两边天然对齐。3.2 细计数部分进位链抽头锁存器阵列细计数部分是整个TDC的核心也是温度和电压敏感性最强的地方。参考时钟上升沿到来的一瞬间进位链上正在传播的信号水平会被全部锁到触发器阵列里。传播位置越靠后说明START沿距离这个时钟上升沿的时间越近;传播位置越靠前说明它还停留在链的前段。这里有一个容易混淆的概念TDC测量的是两个事件的时间差而进位链上锁存的是单个事件相对下一个时钟沿的相位差。实际计算时必须同时得到START和STOP各自相对时钟的相位差然后做减法。所以一条完整的TDC链路通常需要两条进位链或者一条进位链分时复用分别测量起始沿和停止沿的相位再用粗计数器给出整周期数。分时复用的做法能省资源但状态机复杂不少。我自己的经验是如果FPGA资源允许直接给START和STOP各配独立的进位链两条链完全对称地布局可以少操很多心。对称布局还能天然抵消一部分PVT共模漂移因为两条链在同一片硅片上、同一温度下、同一电压下误差方向一致做差值时大部分被消掉了。3.3 温度计码到二进制的转换锁存出来的原始数据是一长串温度计码没法直接算时间必须转换成二进制表示的抽头位置。最简单的转换方法是逐位比较找边界也就是从低位往高位扫找到第一个0的位置或者从高位往低位扫找到最后一个1的位置。这条扫描链如果用纯组合逻辑做几百位宽延迟会很大在高速时钟下容易成为时序瓶颈。比较稳妥的做法是两级转换第一级把温度计码转为独热码用“N位温度计码按相邻两位相与”的办法生成边界指示再用一个优先编码器把独热码转成二进制。对于512位的温度计码可以做成4路并行的小优先编码器再汇总把转换延迟控制在几个逻辑级以内。另外转换逻辑的结果不能立刻送出去最好加一拍寄存器缓存。因为温度计码可能会有气泡边界位置存在个位数的不确定性加一拍之后可以顺便做一个简单的气泡修正——比如检查边界位置附近几位如果只有一位异常把它规整掉。这个修正在低速测试时可能看不出差别但高精度应用里很关键特别是温度变化大的场景。4. 从RTL到布局布线的关键实现4.1 RTL原语例化与综合约束用普通组合逻辑去“隐式”构造进位链在综合时容易被优化或改结构稳定性不够。要做高精度TDC推荐直接例化CARRY4原语强制让工具知道你要的是进位链。以Xilinx 7系列为例CARRY4原语端口包括CI、CYINIT、DI、S、CO、O。TDC场景下通常把DI全部置0S全部置1这样MUX的输入变成“当前进位值”信号就可以沿进位链逐级传播。每级CO接出来作为抽头送入FDRE触发器采样。例化时用generate循环按级展开每一级都加上布局约束禁止综合器移动或复制。// 以Xilinx 7系列CARRY4为例生成64级进位链的简化伪代码 (* KEEP TRUE *) wire [63:0] carry_co; (* KEEP TRUE *) wire [63:0] tap_ff; genvar g; generate for (g 0; g 64; g g 1) begin : gen_carry CARRY4 c4 ( .CI(g 0 ? start_in : carry_co[g-1]), .CYINIT(1b0), .DI(4b0), .S(4b1111), .CO(carry_co[g*43 -: 4]), .O() ); end for (g 0; g 64; g g 1) begin : gen_tap FDRE #(.INIT(1b0)) f ( .Q(tap_ff[g]), .C(clk_ref), .CE(1b1), .R(1b0), .D(carry_co[g]) ); end endgenerate核心是综合时别对这些网络做手脚。在XDC或综合属性里给进位链和抽头信号标上DONT_TOUCH、KEEP防止被优化成LUT逻辑。这段代码里每级CARRY4展开4个进位级每级CO都引出到触发器。实际工程里要把64改成你需要的级数级数越多分辨率越高但代价是触发器和布线资源显著增加。Vivado里还要注意综合策略。默认的策略会优先考虑面积和时序优化可能把阶乘链拆掉或折叠。我的做法是给整个TDC模块设置KEEP_HIERARCHY把模块做成一个独立的design partition然后在模块内部用网表级的约束限定进位链的位置区域。这个方法稍微繁琐但换来的稳定性是值得的。4.2 布局约束把进位链锁成一条直线进位链的延迟均匀性很大程度上取决于它在芯片上的几何形状。如果进位链绕来绕去CARRY4级与级之间的路径不是在同一个纵列里延迟的离散度会明显变大。所以布局阶段要把进位链锁在一个CLB列里做成竖直直线。XDC里可以用set_property BEL去指定每个CARRY4在SLICE中的物理位置也可以用create_pblock把TDC模块圈在特定区域内。实践中最省事的方法是把TDC模块单独放一列用Pblock限定区域然后让工具自动摆放。摆完之后再检查报告确保所有CARRY4都在同一列且连续不要有跳列。有个容易被忽略的点采样触发器FF要尽量靠近对应的CO输出。虽然每个CLB里本身就带有触发器但如果布局器把采样FF放到了远处信号需要走通用布线采样时序就会恶化。正确做法是把采样FF和CARRY4做成同一个SLICE里的配对Vivado通常能自动完成前提是你没把KEEP属性漏掉。我遇到过一种情况进位链看起来全约束在同一列但实测bin宽分布却出现两个明显的“高台阶”。最后查下来是一段进位链走了两个不同的CLB列中间绕了路由。把这个布局错误修掉之后bin宽分布立刻平滑了很多。所以约束完成后务必认真看Device视图人眼检查比跑报告更快。4.3 时钟树与采样时钟质量所有采样触发器的时钟必须是同一个时钟且这个时钟要尽量均匀地到达每一个抽头。FPGA的时钟树BUFG在这方面做得很好但即便这样几百个触发器分布在同一个长列上时钟到达时间也会有细微偏差这在几十皮秒量级不可忽略。缓解的方法很简单给采样时钟接上BUFG让时钟树延迟占主要地位;然后调整进位链的摆放方向让它和时钟树的走向尽量一致。实际上我常常先让工具自动布线然后看时序报告里寄存器时钟端的skew如果超过某个阈值就手动调整Pblock位置把skew压到最小。如果你用的是多通道TDC要特别留意不同通道之间的时钟偏斜。解决思路有两种所有通道共享同一个低skew的全局时钟;或者每条链路都用自己的相位补偿。第一种办法简单直接PCB上时钟进来后先到FPGA的专用时钟引脚再分发给所有通道是最推荐的做法。5. 精度兑现的关键码密度校准与bin-by-bin修正5.1 为什么一定要校准进位链的单级延迟在出厂时是未知的、每个芯片都不同同一芯片上不同级的延迟也并非严格一致。温度变化会改变晶体管开关速度进而改变每级进位延迟;内核电压VCCINT的微小波动也会直接影响延迟。这些因素叠加起来如果直接把每个bin当成等宽来算时间累积误差会达到几十甚至上百皮秒精度大打折扣。所以校准不是可选项是必选项。行业内最常用的方法是码密度测试原理非常朴素向TDC输入大量时间间隔均匀分布的事件统计事件落入每个bin的次数。事件是完全随机的理论上落入每个bin的概率应当与bin的宽度成正比。哪些bin计数多说明那些bin的实际时间宽度大。在校准前先明确需要的校准精度。比如你的bin宽平均10ps想要测到1ps的平均修正精度理论上每个bin至少需要几百次以上的击中统计整个链所有bin累计就要几百万次事件。这个测试量在自动化测试台上完全可行但如果你用手动信号源一个个调会非常痛苦。建议写一个自动化脚本让信号源自动扫移时间逐点归档。5.2 码密度测试的具体操作步骤码密度测试需要产生大量相对参考时钟相位近似均匀的事件。实际操作中可以用任意波形发生器输出脉冲脉冲的重复周期和参考时钟周期设置成不相干的频率比如参考时钟200MHz信号源设成10.37MHz这样两个频率的相位关系会在整个周期上逐渐扫动等效于均匀分布。当然更严格的做法是用真随机源但工程上用两个不相干频率已经足够。有一次实测时我用一个自由运行的低频振荡器作为触发源持续灌入约500万次事件通过串口回传锁存原始码。500万次听上去很多但以10kHz触发率跑起来实际只用了不到十分钟。在线处理时芯片内部可以直接维护一个bin计数器数组每次事件进来就把对应抽头位置的计数器加一。这个操作可以用BRAM做。测试完成后把每个bin的计数读出来做归一化得到的就是每个bin的相对宽度。理想情况下各bin宽度接近;但如果某个bin明显偏宽或偏窄说明进位链在该处存在工艺偏差或布线异常。bin宽分布图出来后先看整体形状再定位异常点。5.3 bin-by-bin修正与实际换算校准的核心输出是每个bin的宽度修正系数也就是bin-by-bin数据表。计算方式为先统计N次事件总共落在L个bin里理想平均每个bin应有N/L次;实际第i个bin的计数为C_i则该bin的实际宽度约等于(C_i / N) * T_cycle其中T_cycle为参考时钟周期。把所有bin的实际宽度求出来之后建立一个查找表记录“从链头到第i个bin的累计时间宽度”。测量时把温度计码解码出的抽头位置i映射到累计时间宽度即可。这个查找表可以直接存成ROM表放在BRAM里每次测量查一次表延迟很小。更高级的做法是根据实时温度对校准表做插值。因为温度变化会导致所有bin宽度等比缩放只需在出厂时测出不同温度点的bin宽表运行中读板载温度传感器选取对应温度表或做线性插值。这样做的精度提升很可观尤其在有空调和没有空调的实验室之间搬运设备时。6. 实测数据与波形分析6.1 测试平台搭建验证TDC精度的平台建议这样搭FPGA开发板一块任意波形发生器或者精密延时发生器一台参考时钟用板载高稳定度晶振或外部铷钟。我用的一块Artix-7开发板板载100MHz晶振倍频到250MHz作为参考时钟进位链做了512级抽头。信号源输出两路脉冲一路触发START另一路经可调延时后触发STOP。通过改变两路之间的延时逐步扫描0到两个时钟周期的时间差范围记录TDC输出和设定真值之间的偏差。每一步延时都要稳定信号源本身的抖动最好小于TDC预期精度否则测出来的误差会被信号源抖动污染。回传数据用串口就够但要注意如果TDC事件速率很高串口会成为瓶颈。我一般板上先做统计压缩连续测100次记录平均值和方差再回传上位机这样既减少通信量又能用来评估单次精度。6.2 码密度分布与bin宽下面是一组我在室温下测得的典型数据。参考时钟250MHz周期4ns512个bin理想平均bin宽约7.8ps。码密度测试灌入约380万次事件统计结果归一化后bin宽度集中在5到11ps之间整体呈现小幅波动。项目实测数据触发模式START沿与STOP沿分双链锁存参考时钟250MHz实测板载晶振偏频12ppm总抽头数512理想bin宽约7.8psbin宽实测范围约5.2ps ~ 11.4ps单次精度RMS约24ps差分非线性DNL±0.9 LSB积分非线性INL±2.7 LSB注意表里这个INL的数值在温度稳定情况下还可以如果温度从25°C变到70°Cbin宽整体会变化大约百分之几对应的INL会明显变大。这也是很多“实验室数据好看、现场数据拉胯”现象的根源。单次精度不是直接看bin宽而是用多次测量标准差来评估。做法是固定两路延时连续测量1000次分析输出码的直方图。直方图的主要峰宽就对应TDC的单次分辨精度。由于进位链抽头本身有离散量化直方图会呈现“梳状”相邻峰的间距就是bin宽整体包络的标准差就是你要的精度。实测时梳状峰之间的分布能看出进位链的均匀性;如果某个抽头特别宽直方图里对应位置就会出现异常高的峰。6.3 不同温度下的漂移趋势温度漂移是TDC精度的大敌也是实测中最容易暴露问题的地方。我用热风枪对FPGA局部加热同时监测码密度统计和固定延时测量值发现在70°C时平均bin宽相对室温增加了约4%到6%这个趋势在不同器件上是稳定的但具体系数完全不同。这意味着你的测量系统如果工作环境温度变化大必须在软件里做温度补偿。最简单的补偿方式是比例缩放把校准时的bin宽表乘以一个温度系数这个系数可以通过出厂前在几个温度点标定得到。很多商用TDC就是采用了类似的标定方案。另外器件自热也不可忽视。TDC跑起来之后FPGA内部功耗上升、温度缓慢升高前十分钟和后一小时测出来的延迟漂移能到几皮秒。等器件完全热稳定后再做正式测试是非常必要的流程。7. 温度漂移、电压敏感与几个血的教训7.1 内核电压纹波对进位链延迟的影响VCCINT是FPGA内核逻辑的电源进位链延迟和VCCINT的关系非常紧密。电源纹波大进位链每级的延迟就会跟着抖动导致TDC的测量噪声增大。做高精度TDC时供电纹波必须控制在很低水平。我踩过一个大坑开发板用普通开关电源给内核供电码密度测试时发现bin宽随负载动态变化反复查了很久才定位到是开关电源纹波在作怪。后来在VCCINT入口处加了一级低噪声LDO同时增加LC滤波纹波从几十mV降到几mV以内测试数据立刻稳定了一个数量级。如果你是自己画PCB建议内核电源单独走线避免和数字IO大电流线路共用。黑板级调试时示波器量VCCINT波形看有没有周期性纹波是排查TDC不稳定最快的方法之一。7.2 布局布线的小细节进位链尽量竖直摆放抽头顺序和触发器的物理位置一一对应。如果为了省事让工具随便布局很可能出现进位链绕两个Column的情况bin宽分布一片狼藉。检查方法很简单在Vivado的Device视图里把CARRY4和采样FF高亮人眼扫一遍有没有明显的跳列、绕线。很多项目的采样FF比特错误地使用了普通LUT的FF而不是紧邻进位链的FF导致走线长度不同。虽然综合器一般会尽量靠近但如果你自己加了奇怪的逻辑在抽头和FF之间就打破了贴近关系。不要在D路径上加任何组合逻辑这一位永远只保留采样触发器的D端。7.3 信号输入的接收与同步待测的START/STOP信号通常来自板外经过接口、电平转换、IBUF之后才到FPGA内部逻辑。如果信号上升沿不够陡峭在进位链里传播的边沿就会模糊锁存时更容易出现气泡和误判。我在输入级加了IBUFDS或者IBUFGDS然后通过一个专用的时钟缓冲进入逻辑阵列。同时建议在输入路径上加一个可选的数字化整形电路比如施密特触发器或者高速比较器。这样可以显著改善边沿质量。还有一点如果START/STOP信号频率很高事件之间间隔小于进位链的冲洗时间会互相干扰。进位链从事件进入到最后被锁存需要一个参考时钟周期来完成。事件速率超过参考时钟频率的一半时就必须做双缓冲或流水线处理否则上一轮的残余信号会污染下一轮测量。7.4 多通道扩展时容易忽略的坑单通道TDC做到高精度不算太难最难的是多通道一致性。多个通道之间的延迟偏差会直接导致时间戳误差所以各通道的进位链必须做完全相同的物理布局最好镜像对称。还有通道间的信号串扰。两条进位链靠得太近时一侧的快速翻转会通过基板耦合影响另一侧。我因此吃过亏把相邻通道的进位链隔了两个SLICE的距离串扰造成的抖动明显下降。如果需要极致密度可以在两条链之间插入哑单元做隔离。多通道还有一个时间交织问题。假如每个通道有各自的粗计数器那么通道间计数器的同步状态必须锁存同一个时钟沿不然可能出现“通道A比通道B多计了一个数”的地狱级Bug。所有通道的粗计数器必须全局同步并且捕获信号要用同一条触发网络。7.5 调试定位利器内嵌环形振荡器TDC调试过程中很难直接观测进位链内部状态我最后是加了一个简单的辅助手段——在FPGA里例化一个由进位链构成的环形振荡器。通过测量这个环振的频率可以间接估算进位链的当前延迟。环振频率越高说明进位链延迟越小同一时刻的TDC量测数据就更可信。这个环振不用一直开着只在校准或怀疑温度异常时短暂启用把频率值读出来配合温度传感器做修正。实测下来环振频率和实测bin宽有很好的线性关系可以当作片上的“温度计”和“延迟基准”。这个思路在工业级TDC设计里也是常见做法。最后再分享两个小技巧第一个是参考时钟频率的选择。不要盲目追求越高越好我之前在另一块板上试过500MHz参考时钟进位链级数虽然可以缩短但DDR采样的难度和时钟抖动带来的问题让整体精度反而下降了。250MHz到400MHz之间通常是最容易收敛的甜蜜点。第二个是校准表的存储与更新。校准表做完后烧进Flash上电时加载到BRAM运行时查询。但如果你工作环境温度变化剧烈建议在系统里加一个温度传感器每隔一段时间重新测一次码密度并更新表。这个过程放在后台跑不用停机因为TDC通常有多种工作模式可以挑选空闲时隙执行。我现在的系统就是这么设计的实测在现场环境跑了半年的设备精度曲线基本保持平稳。