基于System Verilog的TDC实现求助:两种方案可行性咨询
System Verilog实现时间数字转换器(TDC)的方案建议请求
我正尝试用System Verilog实现时间数字转换器(TDC),目前试了两种方案,但不确定是否可行,恳请各位针对任一方案给出建议。
方案一:反相器链型TDC
原理说明
基于反相器延迟链+并行捕获寄存器的结构,通过捕获start信号经过多级反相器后的状态,量化start与progate_stop之间的时间差。
实现代码
module TDC #( parameter bits = 8 )( input logic start, input logic progate_stop, input logic reset, output logic [bits-1:0] comb_output ); logic comb_one, comb_two, comb_three, comb_four, comb_five, comb_six, comb_seven, comb_eight; logic pipo_one, pipo_two, pipo_three, pipo_four, pipo_five, pipo_six, pipo_seven, pipo_eight; always_comb begin comb_one = start; comb_two = ~comb_one; comb_three = ~comb_two; comb_four = ~comb_three; comb_five = ~comb_four; comb_six = ~comb_five; comb_seven = ~comb_six; comb_eight = ~comb_seven; end always_ff@(progate_stop) begin if (reset ) begin pipo_one <= 1'b0; pipo_two <= 1'b0; pipo_three <= 1'b0; pipo_four <= 1'b0; pipo_five <= 1'b0; pipo_six <= 1'b0; pipo_seven <= 1'b0; pipo_eight <= 1'b0; end else begin pipo_one <= comb_one; pipo_two <= comb_two; pipo_three <= comb_three; pipo_four <= comb_four; pipo_five <= comb_five; pipo_six <= comb_six; pipo_seven <= comb_seven; pipo_eight <= comb_eight; end end always_comb begin comb_output[0] = pipo_one; comb_output[1] = ~pipo_two; comb_output[2] = pipo_three; comb_output[3] = ~pipo_four; comb_output[4] = pipo_five; comb_output[5] = ~pipo_six; comb_output[6] = pipo_seven; comb_output[7] = ~pipo_eight; end endmodule
优化建议
- 延迟一致性优化:实际电路中,反相器延迟受工艺、电压、温度(PVT)影响极大,连续反相器难以保证每级延迟均匀。建议插入匹配缓冲单元,或在布局时保证所有反相器的走线、负载一致。
- 亚稳态规避:
progate_stop直接作为寄存器时钟,需确保其与反相器链输出的建立/保持时间满足要求。建议对progate_stop做两级同步处理,或改为边沿触发的采样逻辑。 - 参数化重构:当前代码硬编码8级反相器,可用
generate语句实现参数化延迟链,方便扩展位宽:generate genvar i; logic [bits-1:0] comb_chain; assign comb_chain[0] = start; for(i=1; i<bits; i++) begin assign comb_chain[i] = ~comb_chain[i-1]; end endgenerate - 输出编码优化:当前交替取反的输出方式易产生毛刺,可改用温度计码或格雷码,减少输出跳变次数。
方案二:计数器型TDC
原理说明
基于系统时钟计数器的结构,通过在start有效、stop无效期间对时钟计数,量化两者的时间差。
实现代码
module TDC ( output reg [7:0] out , // Output of the counter input wire enable , // enable for counter input wire clk , // clock Input input wire reset, // reset Input input logic start, input logic stop ); //-------------Code Starts Here------- always_ff @(posedge clk) begin if (reset) begin out <= 8'b0 ; end else begin if (start && !stop) begin out <= out+1; end else begin out <=out; end end end endmodule
优化建议
- 冗余信号处理:端口
enable未被使用,建议删除或补充逻辑(比如用enable与start && !stop做逻辑与,控制计数器使能)。 - 异步信号同步:
start和stop属于异步信号,直接控制计数器会引发时序违规,需先通过两级触发器同步到clk域:logic start_sync, stop_sync; always_ff @(posedge clk or posedge reset) begin if(reset) begin start_sync <= 1'b0; stop_sync <= 1'b0; end else begin start_sync <= start; stop_sync <= stop; end end // 后续逻辑使用start_sync和stop_sync - 精度提升方案:该方案精度由时钟周期决定,若需更高精度,可结合反相器延迟链做插值,或用PLL提高系统时钟频率。
- 溢出保护:8位计数器最大计数值为255,若
start到stop的时间超过255个时钟周期会溢出,需添加溢出标志位或扩展计数器位宽。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

