利用Xilinx FPGA的CARRY4实现抽头延迟链TDC,关键在于理解其进位路径和锁存机制。这篇文章不是手册的翻译,而是梳理一下我验证过的仿真思路,把几个核心部分串起来讲清楚。
1. 基本工作方式
CARRY4内部有4个级联的MUXCY选择器,CIN进、COUT出,每一级的进位节点都引出一根抽头(CO0~CO3)。把多个CARRY4首尾串联,就得到一条连续延迟链。起始信号从链首CIN灌进去,像多米诺骨牌一样沿级传播。当停止信号到来时,各级抽头处的触发器同时锁存当前状态,输出就是一个'温度计码'——哪几级已经翻转,哪几级还没到。
温度计码经过编码器转换为细时间值T_fine,再叠加上粗计数器(比如系统时钟)给出的T_coarse,就得到最终测量结果。单级进位延迟一般在10~30 ps量级,想覆盖更大的量程就要串联更多CARRY4,同时用粗计数器扩展到微秒甚至毫秒。
2. 行为级仿真模型
设计TDC逻辑之前,需要一个能反映延迟特性的仿真模型。下面这个Verilog模块没有综合意图,纯粹是行为级的,用来验证温度计码生成和编码逻辑。
`timescale 1ps/1ps
module CARRY4(
output [3:0] CO,
output [3:0] O,
input CI,
input CYINIT,
input [3:0] DI,
input [3:0] S
);
reg [3:0] co_int;
always @* begin
co_int[0] = (CYINIT & S[0]) | (CI & S[0]) | DI[0];
co_int[1] = (co_int[0] & S[1]) | DI[1];
co_int[2] = (co_int[1] & S[2]) | DI[2];
co_int[3] = (co_int[2] & S[3]) | DI[3];
end
assign CO = co_int;
assign O = co_int;
endmodule
这里直接把进位链逻辑写成了组合环,每一级依赖前一级的输出,仿真器会自然引入传播延迟(timescale 1ps/1ps下通常按ps级步进)。如果要更精确地控制延迟,可以在assign前加上#(delay),但一般用不着,因为行为仿真的核心是验证编码器能否正确解析温度计码。
3. 级联与锁存
实际使用时,CARRY4原语实例化之后,上一级的COUT接到下一级的CIN,所有抽头输出打到一组寄存器上,寄存器的时钟接停止信号(或者取沿)。这样停止信号一触发,就能锁住整个链的瞬时状态。
温度计码的编码器很简单:找第一个出现0的位置,乘以单级延迟,就是细时间。如果链长是N级,编码器就是一个优先编码器。网上常见的做法是先把温度计码取反,再用前导1检测逻辑。
4. 几点提醒
- 行为仿真的延迟分布是均匀的,但真实FPGA里每一级延迟受工艺、电压、温度影响会有差异,需要做校准(bin-by-bin校准)。这个仿真模型帮不了你,只是功能验证的起点。
timescale 1ps/1ps下,仿真器用整数ps步进,但实际的延迟可能是零点几ps,如果要更细致的时序验证,需要改timescale或者用SDF反标。- 温度计码可能会出现冒泡(比如中间跳变),真实器件里触发器亚稳态也会产生错误码,编码器最好做点容错设计,比如校正到最近的有效码。
这个模型没什么花哨,但它能帮你快速看到延迟链的行为,尤其是编码器和粗计数器之间的握手逻辑。


