找回密码
 注册
关于网站域名变更的通知
查看: 626|回复: 3
打印 上一主题 下一主题

转——基于超前进位延时链的时间数字转换器

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-4-19 11:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
转——基于超前进位延时链的时间数字转换器

+ W5 r' |  }* X' l2 V8 z* |
1.1 工作原理
待测的时间间隔s对应一个正脉冲,图 1给出了测量正脉冲下降沿到紧邻的时钟上升沿之间的延时tf原理注意1(a)tf的测量起点时刻为正脉冲的下降沿到达延时链输入端的时刻1(b)为利用延时链测量tf原理图。1(b)的每个三角表示一个延时单元,可以是任何一个带来延时的电路。当代表时间间隔的正脉冲在延时连中到来之前延时链的输出均为0;在正脉冲进入延时链后,在紧邻正脉冲时钟上升沿锁存延时链的输出,延时链1-0跳变f处对应正脉冲的下降沿,延时链输出含有mf1表示正脉冲下降沿经过的mf延时单元,

$ z$ W1 d3 n# r/ N

  Y& f: R# C/ r
用一个延时链测量时间间隔正脉冲需要考虑两种情况,如图 2图 3所示。则待测的时间间隔t可得:
8 F& O% J  @; }. z' Z) }

. E1 w7 P6 g" q7 s
7 A5 z/ ~1 K4 g8 B" |
图 4为实际的测量原理框图,s待测量的时间间隔正脉冲,clk为系统时钟,ENC统计mf和mr编码器,counter为统计n的计数器计数器在s为高时开始计数。s正脉冲进入延时链时,counter开始计数,在紧邻正脉冲的第一个时钟上升沿D触发器组对延时链的输出进行锁存,然后由ENC计算mfmr,最后nmf和mr存入FIFO

0 ]- v* o4 @  h" j1.2 超前进位延时链的实现
图 5中的红色箭头部分即是FPGA用于实现多位快速加法运算的超前进位链,图中的1~5表示资源的位置编号,例如左上角的组合逻辑编号为X16_Y79_N0,则右下角使用的触发器逻辑编号为X16_Y79_N4,根据这些编号可以锁定设计中使用的逻辑资源。根据TimeQuest的分析结果,进位链的延时最小为45ps,最大为728ps,如图 6所示。
利用一下脚本查看延时链的延时,最终结果如图 6所示。
create_timing_netlist -model slow -speed 6   
read_sdc
report_path -from [get_pins {inst|Add0~1|datac}] -npaths 300 -panel_name {Report  Path}
; q8 ^! t) Q! x0 ]3 d0 y+ V6 r8 y
2 @; }/ N. Z* q. D5 [
图 5 一个LABCELL原理图

( e, F' r/ k5 T& }/ u
图 6 超前进位链延时

' w( t# w! X& t' s
图 6中1为延时链输入点,第一个超前进位延时0.728ns,此为延时链中最大的延时,最小的为2~4的45ps延时,其余的还有5的57ps延时,6的153ps延时为cin输入到和sumout输出延时和7的217ps延时为寄存器d输入到寄存器输出的延时。由此可见最坏情况,最终的测量误差由728ps决定。为了提高测量精度,可以考虑延时链从第二个延时单元开始,另外通过多通道测量取平均的方法以及Wave UnionB等方法亦可以进一步提升测量精度。
系统时钟clk250MHz后,为了保证能正确锁存待测信号s的边沿,要求延时链的总延时必须大于时钟周期4ns延时链中延时单元个数应该大于4/0.045 = 88个。图 6中的3~4完成了两位二进制加法,但是延时值只有一个45ps可知在图3的一个LABCELL内部的两个全加器的cincout的延时只有一个45ps这样每个LAB10LABCELL最大可以提供450ps的延时,所以延时链使用10LAB,共200加法器。
具体实现的思路:
( b' c9 B5 Q2 H: d# w' a

" n" ?# m  |3 D% I
图 7 获得200位长进位延时链的顶层原理图
各个模块的程序如下:
module l_add (
        input clock,
        input st1,
        output reg [199:0] result);
! ?9 {, n2 f! i" A- _
        always @(posedge clock )
        begin
                if(st1) result <= result + 2;
        end
; h3 f# t! [& x, \
endmodule
  @" f9 T# _# J3 u* l6 K

! H: {, I6 j& E" y
module r_add (
        input clock,
        input st1,
        output reg [199:0] result);

* O' Q/ g, x6 ?, g4 t: w0 c
        always @(posedge clock )
        begin
                if(st1) result <= result + 6;
        end

* I  F' U) c8 L4 d9 v
endmodule
. `8 Z0 T2 j6 Y% P
module add200 (
        clock,
        dataa,
        data_a,
        result);
  O1 g. I4 Z: _$ `% ^
        input          clock;
        input          [199:0]dataa,data_a;
        output        reg [199:0]  result;
8 h( j8 I5 N+ ]. A( s, Q
        always @(posedge clock)
        begin
                 result <= dataa + data_a;
        end
5 p1 z4 `% W6 n; j# o! Z
endmodule

+ G; Z3 N! j1 N4 H8 n; {4 D1 k, \# ^- {; O
module o_add (
        input [199:0] result,
        output reg s_o);

5 l7 D, n  m* B
        always @(result)
        begin
                 if(result > {{100{1'b1}},{100{1'b0}}}) s_o <= 1'b1; else s_o <= 1'b0;
        end
+ ~4 P) ?2 k8 F9 F( y; c0 r. F/ V1 b
endmodule

2 [* s) g( h2 t4 u7 w, p2 V9 w
其中的add200模块需要进行分区设定,逻辑区域锁定在一列上共10个LAB。最终的Chip Planner视图如图 8所示。

; k1 U& n( m# z1 m
! s* n4 ^( T  p7 j) o, Z
# T/ y9 c+ ~; j$ M) u5 ~; {. k8 ~

图 8 200位延时链的Chip Planner视图

" g( M& w" \; k* K! R


' b, e4 j! m, T
+ M1 S" X1 N4 o/ K9 n# T( B  S6 U7 @( [

图 9 输出分区信息1


8 S$ I- V7 P  q& d. L

' v, }0 u+ N5 c. a

2 p  d* f, }) q7 e+ \3 Q9 \
3 |: G+ v. Y2 o  Z" V- ]9 n  ~

图 10 输出分区信息2

经过图 9和图 10的操作,可以得到add200netlistrouting信息add200-inst.qxp重新建一个工程,添加add200作为设计的一个分区,使用图7Import Design Partion命令导入add200-int.qxp即可得到延时链。最终的超前进位延时链的原理图如图 11所示。
! _4 N0 ~, J6 X8 M* S1 n

图 11 超前进位延时链

图 11与图 1 (b)的区别是,延时链输出中的0-1对应的输入s的下降沿。
4 W% v- O* n" u- v' a  e
1.3 边沿检测电路
时钟clk上升沿要锁存延时链输出中的0-11-0跳变,这种在时钟边沿处的跳变必定会违反触发器的时序约束关系,导致触发器的输出处于亚稳态状态,例如:“000011111”锁存后会出现“000101111”、“000010011”等情况,通过公式的上升沿检测电路可以抑制三位突变的情况并正确识别上升沿输出”000010000”

. `- C6 l; Y5 b& i7 I" j' H! P  }

. ^% Y4 ~9 K/ ^7 w- n5 F' C5 C- J
其中r为边沿检测电路输出;d为锁存器输出;m为rd的总位数;k表示第几位。
源程序:
module ris_g (
        input [199:0] d,
        output reg [199:0] r);
   integer k;
        always @(d)
        begin
            r[0] <= ~d[0] & d[1];
                 r[1] <= ~d[0] & ~d[1] & d[2];
                 for(k=2;k<199;k=k+1)
                    r[k] <= ~d[k-2] & ~d[k-1] & ~d[k] & d[k+1];
                 r[199] <= 1'b0;
        end
+ B8 W* |( H0 Q; l
endmodule
同理下降沿检测电路如公式所示。
, L6 ]0 O  }# c  X' {/ |4 c
源程序:
module fal_g (
        input [199:0] d,
        output reg [199:0] f);
   integer k;
        always @(d)
        begin
            f[0] <= d[0] & ~d[1];
                 f[1] <= d[0] & d[1] & ~d[2];
                 for(k=2;k<199;k=k+1)
                    f[k] <= d[k-2] & d[k-1] & d[k] & ~d[k+1];
                 f[199] <= 1'b0;
        end
( f8 e* l: {' G# i5 A
endmodule
1.4 编码器
边沿检测电路的输出最终为”…0001000…”的形式,1表示0-11-0跳变的位置。求出1的位置编号的方法主要MUX结构、Fat Tree结构、Wallace Tree结构和ROM结构,此处不对这些方法进行介绍和比较,从程序编写的难易程度、路径延时、资源使用上最终选择ROM结构的编码器
* I& A8 s6 i; s, x6 _

1 b- U. n! C3 T6 z" r6 t
其中rp编码器输出;i为位置编号;m为编码器输入的位数;OR表示或运算。
源程序:
        module encoder(
         input [199:0] srin,
         output [8:0] tenout        
        );
        integer i,k,j;
        reg cen_valid;
        reg [8:0] cen_tenout;
        reg [255:0] cen_srin;
   always @(srin)
        begin
        cen_srin = {{58{1'b0}},srin[199:2]};
        cen_tenout = {9{1'b0}};
        for(i=0;i<8;i=i+1)
                   for(k=0;k<2**(7-i);k=k+1)
                            for(j=(2**i)*(2*k+1)-1;j<=(2**(i+1))*(k+1)-2;j=j+1)
                                      cen_tenout = cen_srin[j] | cen_tenout;
        end
        assign tenout = cen_tenout;
        endmodule

; s: m8 _; y2 X# n& I
" C5 d0 s( F, {; A* J1 H5 n; Z" [" @# D, ^5 e
1.5总结
最终的顶层原理图:

3 o: t* a1 Y1 v$ g# r

* Z4 i( w( O1 p/ _
图 12  系统顶层原理图
: l  I; P' Y* s8 x2 p8 Y6 X
源程序:
module do_in (
   din,
        dataa,
        data_a);

/ z5 w" D( f! y& n
        input          din;
        output          [199:0] dataa,data_a;
   assign dataa = {{199{1'b0}},din};
        assign data_a = {200{1'b1}};
7 @# a( U' E) y7 Z

) r4 q. c0 r9 i# A" [
endmodule
0 Z& Y! ]& f# e
module n_counter (
        input clock,
        input st1,
        output reg [199:0] n);
" [! Y: M0 l8 @8 r: g- D+ Z2 j
        always @(posedge clock )
        begin
                if(st1) n <= n + 1;
        end

# p9 I: r4 _5 G. E% c& i" f
endmodule

/ j9 K# a+ }! ^0 ~' @8 N2 v% d6 }6 \: \7 u5 a! }* N% v( M5 L' }: F4 e
module for_store (
   input clk,
   input [199:0] m_in,
        input [8:0] f_in,
        input [8:0] r_in,
        output reg wr,
        output reg [255:0] d_store);
        always @(posedge clk)
        begin
           if(f_in  && r_in ) begin   d_store <=  f_in - r_in; wr <= 1'b1; end
                else begin
                if(r_in) begin  d_store <= (m_in << 9) + f_in - r_in; wr <= 1'b1; end         
           else wr <= 1'b0;        
                end

/ a( S+ u; ]/ q3 d+ @! I# r
        end

# d: m* Z% b) E7 b3 ^9 W% G# o) J, m3 x- D" I6 L
endmodule
# f/ g& g8 |2 k
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module d_fifo (
        data,
        rdclk,
        rdreq,
        wrclk,
        wrreq,
        q,
        rdempty,
        wRFull);
& J7 L9 Q- l3 z  N1 `, R
        input        [255:0]  data;
        input          rdclk;
        input          rdreq;
        input          wrclk;
        input          wrreq;
        output        [255:0]  q;
        output          rdempty;
        output          wrfull;

! S# |( y& j1 f$ q# s" E: L7 ~
        wire [255:0] sub_wire0;
        wire  sub_wire1;
        wire  sub_wire2;
        wire [255:0] q = sub_wire0[255:0];
        wire  rdempty = sub_wire1;
        wire  wrfull = sub_wire2;

! P% @  T! ]9 o( @; _  N1 a
        dcfifo        dcfifo_component (
                                .data (data),
                                .rdclk (rdclk),
                                .rdreq (rdreq),
                                .wrclk (wrclk),
                                .wrreq (wrreq),
                                .q (sub_wire0),
                                .rdempty (sub_wire1),
                                .wrfull (sub_wire2),
                                .aclr (),
                                .rdfull (),
                                .rdusedw (),
                                .wrempty (),
                                .wrusedw ());
        defparam
                dcfifo_component.intended_device_family = "Cyclone V",
                dcfifo_component.lpm_numwords = 256,
                dcfifo_component.lpm_showahead = "OFF",
                dcfifo_component.lpm_type = "dcfifo",
                dcfifo_component.lpm_width = 256,
                dcfifo_component.lpm_widthu = 8,
                dcfifo_component.overflow_checking = "ON",
                dcfifo_component.rdsync_delaypipe = 4,
                dcfifo_component.underflow_checking = "ON",
                dcfifo_component.use_eab = "ON",
                dcfifo_component.wrsync_delaypipe = 4;
3 I/ Q  Q' s5 j0 _0 @2 U

" z* ~6 O2 b- ?( x. Z
endmodule
- }' ^9 x; N1 @  m  x7 H+ y  `
系统的250MHz的时钟可以使用一个PLL生成,最终的输出结果,可以由Nios II或者ARM进行读取按照公式进行计算得到结果,所以在时间数字转换器和CPU之间必须增加一个FIFO来实现异步时钟的读写。另外:
1. FIFO长度和连续测量的次数有关,此处可以缩小至所期望的,不需要256个存储空间
2. 最终的准确计算结果应该对tf和tr进行除以2修正,因为在芯片一个LABCELL中两个全加器只有一个延时值。
3. 从测量的角度来看,采用多通道测量最后求平均可以进一步提升测量精度。

9 [& N$ ]9 x( `+ K  F3 ]" E+ K

该用户从未签到

2#
发表于 2019-4-19 18:03 | 只看该作者
最近正在找这方面的资料 谢谢楼主分享
  • TA的每日心情
    奋斗
    2019-11-15 15:47
  • 签到天数: 1 天

    [LV.1]初来乍到

    3#
    发表于 2019-11-15 15:55 | 只看该作者
    也是到处找这方面的资料,目前还是看不大懂,表示热烈的感谢!

    该用户从未签到

    4#
    发表于 2022-11-23 13:25 | 只看该作者
    基于超前进位延时链的时间数字转换器
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-10-30 04:44 , Processed in 0.156250 second(s), 23 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表