当前位置: 首页 > news >正文

时间数字转换器TDC的FPGA方案及核心代码

目录

简介

方案

方案项目:


简介

时间到数字转换器(TDC)是将时间间隔(TI)转换为数字代码的高精度时间传感器。它们被广泛应用于时间分辨应用,如粒子物理等。大多数F使用级联携带链来形成抽头延迟线(TDL),因为携带链是现代fpga中的标准链,并有专用的路由资源。

方案

本方案采用FPGA的延时链进行设计,重点采用FPGA的carry4(ultrascale 系列是carry8)

方案项目:

时间分辨率和时间线性度是任何基于FPGA的TDC设计中的关键问题。

分辨率(最小可检测的时间值,通常称为最不显著位,LSB)是TDC的主要度量。对于TDL-TDC,它由携带链的传播延迟决定,可以定义为:

Q=T/n;

其中,T是采样时钟的周期,n是bin的数量。与XILINX 7系列相比,UltraScale系列的CY8的N数量增加了一倍,。然而,当分辨率提高时,线性度就会降低,气泡问题尤为突出。

延时链的不均匀和时钟的抖动(时钟边界)是造成非线性的两个主要因素。

原先方案采用40nm

FPGA 中的延迟链,并采用C0和C3作为触发器编码,时间精度可以达到23ps。

优化后方案如下,采用20nmFPGA,时间精度可以达到5ps。

这里采用双采样模式,理论上精度为原先的4倍数。虽然输出是由DFFs采样的,但它们不能直接编码,因为有意外的逻辑转换(例如,“1”之间的意外的“0”或“0”之间的“1”),通常称为气泡。气泡是由于不均匀传输和时钟倾斜产生的。为了解决气泡问题,采用子sub的方式,子sub采用分解延长方式来减小,最小化时钟倾斜的影响,来减小气泡的输出。

核心代码

粗延时代码

module CoarseCounter(

input CLK_IN,

input RESET_IN,

output [23:0] Q_OUT

);

//wire declaration*****

wire [5:0] q1_i; wire [5:0] q2_i; wire [5:0] q3_i; wire [5:0] q4_i; wire ce1_i; wire ce2_i; wire ce3_i; wire ce4_i;

//*begin of code

counterX counterX_i1 ( .CLK (CLK_IN), // input clk .CE (ce1_i), // input ce .SCLR (RESET_IN), // input sclr .Q (q1_i) ); counterX counterX_i2 ( .CLK (CLK_IN), // input clk .CE (ce2_i), // input ce .SCLR (RESET_IN), // input sclr .Q (q2_i) ); counterX counterX_i3 ( .CLK (CLK_IN), // input clk .CE (ce3_i), // input ce .SCLR (RESET_IN), // input sclr .Q (q3_i) ); counterX counterX_i4 ( .CLK (CLK_IN), // input clk .CE (ce4_i), // input ce .SCLR (RESET_IN), // input sclr .Q (q4_i) ); assign ce1_i = 1'b1; assign ce2_i = (q1_i == 6'b111111) ? 1'b1 : 1'b0; assign ce3_i = (q1_i == 6'b111111 && q2_i == 6'b111111) ? 1'b1 : 1'b0; assign ce4_i = (q1_i == 6'b111111 && q2_i == 6'b111111 && q3_i == 6'b111111) ? 1'b1 : 1'b0; assign Q_OUT = {q4_i,q3_i,q2_i,q1_i};

endmodule

细延时代码

module carrychain_whole #(

parameter StepLength = 192)

(

input RESET_IN,

input CLK_IN,

input STRETCHHIT_IN,

output CO_OUT, output CHNLFIFOWR_OUT, output [7:0] CHNLFIFODATA_OUT, output LATCH_OUT, output HITCLR_OUT

);

//wire declaration******

localparam FineDataWidth = 8;

(* MARK_DEBUG="true" ) wire co_i;( MARK_DEBUG="true" *) wire en_latch_i;

(* MARK_DEBUG="true" *) reg [FineDataWidth-1:0] FineData_r; (* MARK_DEBUG="true" *) reg latch_r;

(* MARK_DEBUG="true" ) reg dataready_r;( MARK_DEBUG="true" ) reg dataready_r1;( MARK_DEBUG="true" *) reg dataready_r2;

(* MARK_DEBUG="true" ) wire [StepLength-1:0] stepdata_i;( MARK_DEBUG="true" *) wire [FineDataWidth-1:0] FineData_i;

//begin of code******

//--------fine data encode---------------- carrychain_plain #( .StepLength (StepLength)) carrychain_plain_i ( .CYINIT_IN (STRETCHHIT_IN), .CLK_IN (CLK_IN), .CO_OUT (co_i), .STEPDATA_OUT (stepdata_i) ); generate if (StepLength == 128) begin encoder_128 #( .StepLength (StepLength) ) encoder_i ( .reset (RESET_IN), .CLK (CLK_IN), .stepdata (stepdata_i), .Finedata (FineData_i) ); end else if (StepLength == 144) begin encoder_144 #( .StepLength (StepLength) ) encoder_i ( .reset (RESET_IN), .CLK (CLK_IN), .stepdata (stepdata_i), .Finedata (FineData_i) ); end else if (StepLength == 160) begin encoder_160 #( .StepLength (StepLength) ) encoder_i ( .reset (RESET_IN), .CLK (CLK_IN), .stepdata (stepdata_i), .Finedata (FineData_i) ); end else begin encoder_192 #( .StepLength (StepLength) ) encoder_i ( .reset (RESET_IN), .CLK (CLK_IN), .stepdata (stepdata_i), .Finedata (FineData_i) ); end endgenerate //---------control signals generate----------------- always @(posedge CLK_IN) begin latch_r <= stepdata_i[0]; dataready_r <= (~latch_r)&(stepdata_i[0]); dataready_r1 <= dataready_r; dataready_r2 <= dataready_r1; end //-----------output data generate------------- always @(posedge CLK_IN) if(RESET_IN) FineData_r <= 8'b0; else if(dataready_r1) FineData_r <= FineData_i; else FineData_r <= FineData_r; //-----------output assignment------------ assign CHNLFIFODATA_OUT = FineData_r; assign LATCH_OUT = latch_r; assign CHNLFIFOWR_OUT = dataready_r2; assign HITCLR_OUT = latch_r & stepdata_i[0]; assign CO_OUT = co_i;

endmodule

http://www.dtcms.com/a/302787.html

相关文章:

  • 51单片机如何实现round函数
  • Java 大视界 -- 基于 Java 的大数据实时流处理在智能电网分布式能源接入与电网稳定性保障中的应用(368)
  • 【Linux】重生之从零开始学习运维之mysql用户管理
  • live-server的使用以及离线环境安装
  • CMake、CMakeLists.txt 基础语法
  • Linux系统之Ansible安装与入门
  • WPF,窗口拖动事件与窗口内控件点击事件
  • c++ 中的字符串相关的操作
  • python办自动化--利用vba或者python按需求读取excel文件指定列,更改列名后,按照要求将列排序,最后填充空白单元格
  • k8s中Nvidia节点驱动的配置问题
  • Go 语言-->指针
  • 2025年人工智能三大突破:多模态推理、具身智能与全球治理
  • ATF简介
  • 汽车膨胀水箱(副水箱)液位传感器的作用
  • Linux DNS解析3 -- DNS解析代理配置使用
  • Android 媒体播放开发完全指南
  • 量子计算新势力,微美全息FPGA方案解锁大幅优化与性能提升密码
  • 在Windows下读写Linux EXT文件系统文件
  • 为什么bert是双向transformer
  • vue2 基础学习 day02 (案例、watch侦听器(监视器))
  • API产品升级丨全知科技发布「知影-API风险监测平台」:以AI重构企业数据接口安全治理新范式
  • 深入探索Linux:忙碌的车间“进程”间通信
  • Datawhale AI夏令营--Task2:理解项目目标、从业务理解到技术实现!
  • Linux知识回顾总结----基础IO
  • Muduo库
  • Effective Modern C++条款18:为什么在独占资源管理中使用`std::unique_ptr`?
  • getdents64系统调用及示例
  • 搭建HAProxy高可用负载均衡系统
  • 四、计算机组成原理——第2章:数据的表示和运算
  • OpenLayers 综合案例-动态闪烁