基于FPGA的CARRY4 抽头延迟链TDC延时设计

本文详细描述了如何利用FPGA实现CARRY4进位逻辑构建抽头延迟链TDC,用于精确测量信号与本地时钟的延迟。文章涉及原理、测试芯片XC7K325TFFG900-24的使用、Vivado工具限制以及顶层和延迟线模块的源代码。
摘要由CSDN通过智能技术生成


版权声明:本文为CSDN博主「FPGA入门」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sinat_39724439/article/details/115120380

基于FPGA的CARRY4 抽头延迟链TDC延时设计

1、参考

https://cas.tudelft.nl/fpga_tdc/TDC_basic.html

2、原理

采用FPGA的CARRY4进位单元,每个CARRY4的COUT连接到下一个CARRY4的CIN,这样级联起来,形成延时链;每个COUT做为抽头输出到触发器,通过本地时钟进行数据采样。假定每个延时链的延时是固定的(最后需要标定),可通过采样值大致估算所测信号与本地时钟上升沿之间的间隔,当得到适当的标定后,可获得较高的精度。

3、当前测试的芯片是XC7K325TFFG900 -2

仿真中的carry4 除第一级外,其他的carry4输出到输入延迟固定都是53ps,但是这是4个进位的延迟时间,只是vivado仿真工具有限制,且需要后仿真。
在这里插入图片描述

4、源代码

顶层
tdc_top.v

module tdc_top#(
	parameter STAGE 					 = 200,
	parameter GAP_BITS 					 = 8
)(
	input wire 							sg_start,
	input wire 							clk_sys,
	input wire 							reset    ,
	output wire                         cs_gap,
	output wire [GAP_BITS-1:0]			value_gap		
);

wire clk_bufg;

clk_wiz_0 clk_wiz_0_inst(
	.clk_out1(clk_bufg),
	.clk_in1(clk_sys)
);

wire valid_pre;

wire valid;
wire [STAGE-1:0]					value_latch;

wire bin_cs;
wire [GAP_BITS-1:0] bin;

wire sg_bufr;

BUFR #(
    .BUFR_DIVIDE("BYPASS"),   // Values: "BYPASS, 1, 2, 3, 4, 5, 6, 7, 8" 
    .SIM_DEVICE("7SERIES")  // Must be set to "7SERIES" 
 )
BUFR_INST (
    .O(sg_bufr),        // 1-bit output: Clock output port
    .CE(1'b1),          // 1-bit input: Active high, clock enable (Divided modes only)
    .CLR(1'b0),         // 1-bit input: Active high, asynchronous clear (Divided modes only)
    .I(sg_start)        // 1-bit input: Clock buffer input driven by an IBUF, MMCM or local interconnect
);

FDCE #(
	.INIT(1'b0) // Initial value of register (1'b0 or 1'b1)
) 
FDCE_INST2 (
	.Q(valid_pre),      // 1-bit Data output
	.C(clk_bufg),      	// 1-bit Clock input
	.CE(1'b1),    		// 1-bit Clock enable input
	.CLR(1'b0),  		// 1-bit Asynchronous clear input
	.D(sg_bufr)       	// 1-bit Data input
);

FDCE #(
	.INIT(1'b0) // Initial value of register (1'b0 or 1'b1)
) 
FDCE_INST3 (
	.Q(valid),      // 1-bit Data output
	.C(clk_bufg),      // 1-bit Clock input
	.CE(1'b1),    // 1-bit Clock enable input
	.CLR(1'b0),  // 1-bit Asynchronous clear input
	.D(valid_pre)       // 1-bit Data input
);

line_tdc#(
	.STAGE								(STAGE)

) line_tdc_inst(
	.sg_start 							(sg_bufr),
	.clk_bufg 							(clk_bufg),
	.reset 								(reset),
	.value_latch 						(value_latch)
);

latch2bin#(
	.GAP_BITS						    (GAP_BITS)
) latch2bin_inst(
	.clk_bufg 							(clk_bufg),
	.reset 								(reset),
	.valid 								(valid),
	.value_latch 						(value_latch),
	.bin_cs                             (cs_gap),
	.bin                                (value_gap)
);

延迟线代码

module line_tdc#(
	parameter STAGE 					 = 256
)(
	input wire 							sg_start,
	input wire 							clk_bufg,
	input wire 							reset,
	output wire [STAGE - 1:0]			value_latch	
);

wire [STAGE - 1:0] dat_reg0;
wire [STAGE - 1:0] dat_reg1;

genvar i;
generate
	for (i = 0; i <= STAGE/4 - 1; i = i+1) begin
		if(i == 0) begin :carry4_first
			CARRY4 CARRY4_INST (
				.CO				(dat_reg0[3:0]),      			// 4-bit carry out
				.O				(),           				// 4-bit carry chain XOR data out
				.CI				(1'b0),         			// 1-bit carry cascade input
				.CYINIT			(sg_start), 				// 1-bit carry initialization
				.DI				(4'b0000),      			// 4-bit carry-MUX data in
				.S				(4'b1111)       			// 4-bit carry-MUX select input
			);
		end
		if (i > 0) begin :carry4_others
			CARRY4 CARRY4_OTHERS (
				.CO				(dat_reg0[4*(i+1)-1:4*i]),	// 4-bit carry out
				.O				(),           				// 4-bit carry chain XOR data out
				.CI				(dat_reg0[4*i-1]),       	// 1-bit carry cascade input
				.CYINIT			(1'b0), 					// 1-bit carry initialization
				.DI				(4'b0000),      			// 4-bit carry-MUX data in
				.S				(4'b1111)       			// 4-bit carry-MUX select input
			);
		end
	end
endgenerate
   
genvar j;
generate 
	for (j = 0; j <= STAGE - 1; j = j+1) begin:loop_fdre
		FDRE #(
			.INIT				(1'b0) 						// Initial value of register (1'b0 or 1'b1)
		) FDRE_INST0 (			
			.Q					(dat_reg1[j]),   			// 1-bit Data output
			.C					(clk_bufg),      			// 1-bit Clock input
			.CE					(1'b1), 					// 1-bit Clock enable input
			.R					(reset),  					// 1-bit Synchronous reset input
			.D					(dat_reg0[j])    			// 1-bit Data input
		);
		
		FDRE #(
			.INIT				(1'b0) 						// Initial value of register (1'b0 or 1'b1)
		) FDRE_INST1 (		
			.Q					(value_latch[j]),			// 1-bit Data output
			.C					(clk_bufg),      			// 1-bit Clock input
			.CE					(1'b1),    					// 1-bit Clock enable input
			.R					(reset),      				// 1-bit Synchronous reset input
			.D					(dat_reg1[j])       			// 1-bit Data input
		);
	end
endgenerate

endmodule

延迟线数字码转换二进制输出
latch2bin.v

module latch2bin#(
	parameter GAP_BITS 					 = 8

)(
	input wire 							clk_bufg,
	input wire 							reset,
	input wire 							valid,
	input wire  [(2**GAP_BITS)-1:0]     value_latch,
	output reg                          bin_cs,
	output reg [GAP_BITS-1:0]			bin		
);

(* dont_touch="true" *)reg [(2**GAP_BITS)-2:0] decoding [0:GAP_BITS-4];

(* dont_touch="true" *)reg [GAP_BITS:0] binary [0:GAP_BITS-3];

(* dont_touch="true" *)reg [GAP_BITS-2:0] data_valid;

(* dont_touch="true" *)reg [15:0] decode_final;

(* dont_touch="true" *)reg [GAP_BITS-1:0] bin_final;

(* dont_touch="true" *)reg [3:0] ones;

(* dont_touch="true" *)reg [GAP_BITS:0] binary_r;

always@(*) begin
    decoding[0] = value_latch[(2**GAP_BITS)-2:0];
    data_valid[0] <= valid;
end

genvar i;
generate
	for (i = 0; i <= GAP_BITS-5; i = i+1) begin
        always@(posedge clk_bufg) begin
            if(reset) begin
                decoding[i+1] <= 'd0;
                binary[i+1] <= 1'b0;
                data_valid[i+1] <= 1'b0;
            end
            else begin
                binary[i+1][GAP_BITS:GAP_BITS-1-i] <= {binary[i][GAP_BITS:GAP_BITS-i],decoding[i][((2**(GAP_BITS-i))-2)/2]};    
                data_valid[i+1] <= data_valid[i];
                if(decoding[i][((2**(GAP_BITS-i))-2)/2]==1'b1) begin
					decoding[i+1][((2**(GAP_BITS-i))-2)/2-1:0] <= decoding[i][((2**(GAP_BITS-i))-2):((2**(GAP_BITS-i))-2)/2+1];
				end
				else begin
					decoding[i+1][((2**(GAP_BITS-i))-2)/2-1:0]	<= decoding[i][((2**(GAP_BITS-i))-2)/2-1:0];
				end
			end
		end
	end
endgenerate

always@(posedge clk_bufg) begin
    if(reset) begin
        ones <= 4'd0;
        data_valid[GAP_BITS-3] <= 1'b0;
        binary[GAP_BITS-3] <= 'd0;
        bin_final <= 'd0;
    end
    else begin
        ones <= 
        decoding[GAP_BITS-4][0] + decoding[GAP_BITS-4][1] + decoding[GAP_BITS-4][2] + decoding[GAP_BITS-4][3] +
        decoding[GAP_BITS-4][4] + decoding[GAP_BITS-4][5] + decoding[GAP_BITS-4][6] + decoding[GAP_BITS-4][7] +
        decoding[GAP_BITS-4][8] + decoding[GAP_BITS-4][9] + decoding[GAP_BITS-4][10] + decoding[GAP_BITS-4][11] +
        decoding[GAP_BITS-4][12] + decoding[GAP_BITS-4][13] + decoding[GAP_BITS-4][14] + decoding[GAP_BITS-4][15];
        
        data_valid[GAP_BITS-3] <= data_valid[GAP_BITS-4];
        binary[GAP_BITS-3] <= {binary[GAP_BITS-4][GAP_BITS-1:4],4'b0};
        
        data_valid[GAP_BITS-2] <= data_valid[GAP_BITS-3];
        bin_final <= {binary[GAP_BITS-3][GAP_BITS-1:4],ones[3:0]};
    end
end

always@(posedge clk_bufg) begin
    if(reset) begin
        bin_cs <= 1'b0;
        bin <= 'b0;
    end
    else begin
        if(data_valid[GAP_BITS-2] == 1'b1) begin
            bin_cs <= 1'b1;
            bin <= bin_final;
        end
        else begin
            bin_cs <= 1'b0;
            bin <= 'b0;
        end
    end
end

endmodule


测试

tb_tdc_top.v

module tb_tdc_top;

reg clk_sys;
reg sg_start;
reg reset;
wire [7:0] value_gap;

tdc_top tdc_top_inst(
	.sg_start		(sg_start),
	.clk_sys		(clk_sys),
	.reset			(reset),
	.value_gap		(value_gap)
);

initial begin
	clk_sys = 0;
	sg_start = 0;
	reset = 1;
	#1000;
	reset = 0;
	#116;
	sg_start = 1;
	#3;
	sg_start = 0;
end

always #(5) clk_sys = ~clk_sys;

endmodule

时钟模块100M输入,400M输出,并经过BUFG资源。
在这里插入图片描述
由于每个carry4的延迟时间是53ps,每个时钟周期是2.5ns,最多需要50个carry4级联即可。

5、约束
手册上有写,对于carry4的第一级约束后,下一级的carry4会以最邻近的摆放。
tdc.xdc

set_property PACKAGE_PIN AD21 [get_ports reset]
set_property PACKAGE_PIN AE23 [get_ports sg_start]
set_property PACKAGE_PIN AD23 [get_ports clk_sys]
set_property IOSTANDARD LVCMOS33 [get_ports {value_gap[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {value_gap[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {value_gap[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {value_gap[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {value_gap[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {value_gap[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {value_gap[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {value_gap[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports cs_gap]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports sg_start]
set_property IOSTANDARD LVCMOS33 [get_ports clk_sys]

set_property LOC SLICE_X0Y0 [get_cells line_tdc_inst/genblk1[0].carry4_first.CARRY4_INST]

6、后仿真测试结果在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7、以上可以对sg_start和clk_bufg两个信号的间隔进行大致估算,通过计算大致可计算出第一级carry4输入的延时。

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Designing with Low-Level Primitives Chapter 2. Primitive Reference Primitives ................................................................................................................................................ 2–1 ALT_INBUF ...................................................................................................................................... 2–1 ALT_OUTBUF .................................................................................................................................. 2–3 ALT_OUTBUF_TRI .......................................................................................................................... 2–6 ALT_IOBUF ....................................................................................................................................... 2–8 ALT_INBUF_DIFF ......................................................................................................................... 2–11 ALT_OUTBUF_DIFF ..................................................................................................................... 2–13 ALT_OUTBUF_TRI_DIFF ............................................................................................................. 2–14 ALT_IOBUF_DIFF .......................................................................................................................... 2–19 ALT_BIDIR_DIFF ........................................................................................................................... 2–22 ALT_BIDIR_BUF ............................................................................................................................ 2–25 LCELL .............................................................................................................................................. 2–27 DFF ................................................................................................................................................... 2–28 CARRY and CARRY_SUM ........................................................................................................... 2–29 CASCADE ....................................................................................................................................... 2–30 LUT_INPUT .................................................................................................................................... 2–31 LUT_OUTPUT ................................................................................................................................ 2–32
基于FPGA的FIR滤波器设计可以通过以下步骤进行: 1. 设计滤波器:使用Matlab的fdatool工具进行滤波器设计,根据设计要求选择参数,并导出滤波器的抽头系数。\[2\] 2. IP核配置:将导出的抽头系数应用到FPGA的IP核中。IP核是FPGA中的可重用模块,可以实现各种功能。在这里,我们可以使用FIR滤波器IP核来实现滤波器功能。\[3\] 3. 实现:将配置好的IP核与其他必要的模块连接起来,并进行适当的时钟和数据接口设置。这样,FPGA就可以实现FIR滤波器的功能。 需要注意的是,FIR滤波器是有限长单位冲激响应滤波器,也称为非递归型滤波器。它具有严格的线性相频特性和稳定的系统特性。\[2\] 以上是基于FPGA的FIR滤波器设计的详细过程。如果您需要更多的工程文件或有其他疑问,可以添加QQ:236395527进行进一步交流。\[1\] #### 引用[.reference_title] - *1* *2* [【FPGA 】Altera基于IP核的FIR数字滤波器(上板成功)](https://blog.csdn.net/qq_54671271/article/details/126459409)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [基于FPGA的希尔伯特滤波器实现](https://blog.csdn.net/m0_46644103/article/details/126542638)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值