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

关于采用两级触发器实现双时钟域信号同步方法的分析与验证

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-6-11 13:26 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

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

x
引言
& I3 `9 Q7 d$ {+ ~( K  z3 B' ^实现双时钟域数据的交换,最常见的方法就是采用双时钟的异步fifo。但是对于单根信号线,如果仍然采用异步fifo就显得非常stupid,这时,往往通过两级触发器来实现同步。
) Q& n" W" W9 ]: W
, p- g% V# o0 I$ |那么,两级触发器是如何实现同步的呢?本小节就做一个简单的分析和验证。
2 V( D4 E" j# ~0 U  ~3 e: c# h

: X$ L' x" T  z( ^- l$ N1,一段代码* n! l8 x$ L$ t4 m- Z$ \
. X9 H; j' Y; M' H( q  \
下面是我刚刚从ORPSoC的工程里看到的一段代码:! e# X8 u: V4 G8 Z6 c, H4 ~3 ]8 o
3 y( C6 y4 _) A8 P
! B: S$ g" H5 [2 \
//'ddr2_writeback_done':generate in ddr2_if_clk domain' V% _( ~8 N6 ~, t2 F/ g2 ~
always @(negedge ddr2_if_clk)
7 k% U! F6 C# ?        if (ddr2_rst)
6 ]# u5 j9 e2 L                ddr2_writeback_done <= 0;
$ i# x* h7 z) J$ i        else if (ddr2_writeback_done_wb_sync2); r; M9 f- |* h- j; a8 n. k6 F
                ddr2_writeback_done <= 0;
9 r# e0 g$ Z/ [; ~  k        else if (ddr2_write_state_shr[6])1 X$ S6 t6 E) M) o0 T
                ddr2_writeback_done <= 1;$ |, C/ P% v0 M* ^) B
" r  m, s. O( E4 y. V* h+ S
//'ddr2_writeback_done' sync to 'wb_writeback_done' in wb_clk domain
  D- d- t6 S% E* i( zalways @(posedge wb_clk)
% ?  ]2 y" n# \% P' P1 P* V% s        if (wb_rst)
# H  _; q. C# X$ x6 S5 ~7 F2 L' g                begin
2 v: x  f4 _$ W7 n; y                        wb_writeback_done_sync <= 0;1 I. y" U! C1 ^8 a5 }0 g
                        wb_writeback_done_sync2 <= 0;4 K& s7 X2 c! k% P* S
                end
  U4 [' ?; U& y# d" Q& D     else
0 {8 _- j9 z$ b                begin6 a8 y" j" V8 b) N" m) `, ^% ^
                        wb_writeback_done_sync <= ddr2_writeback_done;
0 [' T5 f8 B) H; q                        wb_writeback_done_sync2 <= wb_writeback_done_sync;
5 }9 Q: u% k# s, y                end; W# Y/ h3 A. ]4 W

+ Q& p3 p% U: M. Tassign wb_writeback_done = !wb_writeback_done_sync2 & wb_writeback_done_sync;( ^! q% x5 U- b$ I

. P2 D6 R$ U# n# h+ K
- t1 F$ S7 L% \  m8 F+ T9 Z% P//use 'wb_writeback_done' in wb_clk domain
# c, ]" a5 K4 ]2 M3 q  Salways @(posedge wb_clk)# R$ [% ]# _8 z  h) d  C+ C
        if (wb_rst)
# M4 L% _) R. Z                do_writeback <= 0;
; t. k6 J4 L: F' I  x        else if (wb_writeback_done)
/ Z$ Q3 F7 A+ \9 _& t. c                do_writeback <= 0;
! V. e. t- s" O& Y* Y* }        else if (start_writeback)
. o+ F' F4 Q5 F1 S! n! s                do_writeback <= 1;* a- `3 c# `0 }) [. P
               
2 E6 |! V  F# N               
& ]8 R# M" z8 a+ r5 ?$ ~                / ^: o+ _/ _0 J

: Y0 k7 }) A& A: i
! }; R2 i! f. ]+ K: P这段代码就可以实现两个时钟域(wb_clk和ddr2_if_clk)间ddr2_writeback_done信号的同步。" Y9 h5 h) H8 e1 p5 o6 q6 k" y

% E6 d* r' v: B$ [& l2 x' G
% L* r! V# L% I( w2 y  d3 p' X
( S" B4 v; J2 a6 ]' t4 ^2,编写test case3 K! q" F. L8 j. b; R. j  ^
为了更清晰的展示其具体的同步过程,我写了一个简单的test case。
, w! v/ r; ]. G* v3 U0 x7 ?; \3 _
* P0 }. \0 l2 f$ v+ Ma,可综合的sync.v:! W# i  c1 j* b' s7 ?: G5 `

/ A. h) v" E6 k7 e) u/ c! j1 y' s! Q; r) \6 i3 F+ X

) L; ?1 u) K0 p! R1 g/*9 l% w$ R7 Z! \# `
* file name                :sync.v
2 ~+ t4 y, G/ w4 a9 f* author                :Rill4 f& q' ~' K1 D8 F
* date                        :2014-04-12. s2 u0 S4 i. d0 c5 {& h3 C% W+ {
*/
6 D7 ]* F4 K2 k' {" x& c- s9 p) [7 }1 [9 ?! i% {) A  D0 F2 z

, n' q5 ?2 O& mmodule sync6 q" I! w7 _0 w7 ^
(' F* u3 q3 X' B
input clk_a,. b: }1 X# k7 m. c1 |' }
input rst_a,+ k8 ?9 H( c$ j9 b  z
input enable_a,, p3 }- o# o" g* g8 }2 p
0 w* U% }; N( w* a- c1 {
input clk_b,
! I" I  w4 F8 |( a' _, E# O. w2 xinput rst_b,
3 e& G9 L; L- J% q) s! v; e1 Q" Poutput enable_b
$ Q8 V$ V% I* ~* W" K) f3 g);
/ X9 z. ?8 }  C8 f. \
  C" T1 ^4 c2 x2 Jreg signal_a;
; I; T  K- M- \+ X. N$ C/ |$ {: U! c* D. n' u! r+ L
reg sync1;
/ _% c/ ~$ R2 G+ q- ?5 ureg sync2;
; t1 F$ @& q7 c, r! s' K
# A9 B" [- F, K5 Zwire signal_b;
  i8 G, b; z4 _4 k% areg enable;* e/ m6 ^9 h8 a

) I  ^: K- L  H" W9 Nassign enable_b = enable;
2 m- m% ~" `. b# a9 J; W5 n7 P
: ~5 k8 |  o# t! V$ U//'signal_a':generated in clk_a domain# m- d4 O7 w8 p% L  m5 e
always @(negedge clk_a)0 G7 _9 L6 K9 ~
begin6 x+ Q2 V# z' n$ T
        if (rst_a)  @! C' Z! g1 N5 y! N
                signal_a <= 0;5 L% d2 y4 r8 X  M
        else if (sync2)
( i2 C" L1 Y7 m" _                signal_a <= 0;. {) g" _  `# o( Z3 g( C
        else if (enable_a)3 i$ D& M! v5 x0 c  {
                signal_a <= 1;3 T; a) B+ ]9 G0 M$ L+ l" t+ S- w1 W
end1 D1 b' ~# k: C/ D' Y2 k
//'signal_a' sync to 'signal_b' in wb_clk domain$ c: i2 u7 Y1 D  t1 D3 }, i5 J
always @(posedge clk_b)
; D+ @% K3 O1 }) M  R$ Gbegin
1 S8 \' e7 e4 k! R2 [        if (rst_b)
, Q) D3 {. T. _' b                begin
9 x$ m) P5 P9 F: p  }                        sync1 <= 0;. S& x) Q: F9 X5 k6 ~9 H" @$ l
                        sync2 <= 0;
. R$ f6 M9 i6 V( q8 v5 Q$ [                end
: Z) T) b5 t2 M( _8 l; R! R        else
  I1 i9 W# u2 `! w( q! i                begin9 l. |  N! a1 ~" b2 q; O
                        sync1 <= signal_a;
! K, {. g( T4 d7 t3 \0 t                        sync2 <= sync1;/ b/ X/ L2 G2 h& U" b  s$ |2 t5 d
                end4 b1 `" K, S% x3 q2 {
end6 X. W& l8 o" J( t0 v$ y

5 M- Z- A3 G& [! E, N6 u$ Zassign signal_b = !sync2 & sync1;
( \3 Z) _* p. D4 \" G" L
0 s9 D2 ]) a5 P1 @" }4 R7 @# l+ |
//use 'signal_b' in wb_clk domain
& A, k$ `5 r; X' _2 b8 ?) k) Lalways @(posedge clk_b)
  k2 g) B; R( o: Ibegin+ @) y) B$ ?; b4 R; ~: y
        if (rst_b)
' y, R+ Q' M4 `# p                enable <= 1'b0;
- p" k! C: n1 k# ^+ f0 C  f        else if (signal_b)
( \9 Z" R% }" `8 X! K. ~4 V                enable <= 1'b1;( o8 b% Q. u8 {3 Q5 F  q: ]- `$ w
        else$ M% c- E: H! N0 ^: U8 j4 x
                enable <= 1'b0;
$ J4 _5 Y3 {6 |# h/ r; Oend9 Y! d+ {2 U7 T& ^' M8 o- Y

# K+ c  |* L% o- G* Q+ B$ p
+ n5 a8 k, u  B9 d9 ~6 Zendmodule: f4 ]" W/ [, h
               
; I* U- p) R2 l. y: ]. b& m* u/********* EOF *************/
! V0 }' E3 F" B+ A
) P. {8 d, Z( N
9 J* \5 [+ Z9 |8 c: g7 t5 ]b,不可综合的sync_tb.v:9 a' a4 a+ c4 W$ t
- N3 f1 I& c$ A. u
. u1 D& U* b% Z* n4 h8 N( q
7 q% z2 g: t8 k
/*
4 U3 \3 y3 l& L: ?# C* file name                :sync_tb.v
+ T' n% v0 E+ z6 p* author                :Rill
1 a/ {/ t' C5 g0 J* date                        :2014-04-12" M# p, f' r% a' r, n
*/# I1 A% |/ Q6 E; B: {! g
: S2 F. x9 J7 ?1 W0 W1 N" f
`timescale 1ns/1ns0 t: x8 F' s; X

+ J& |  I8 T: F+ ^4 R: o) ?7 r. J6 z9 k( n1 r( a5 C& R: S
module sync_tb;
/ p1 I% W; |7 ~+ M+ [
/ t# i0 {% j( r1 K+ {reg clk_a;
$ u2 Y$ u! j  }3 @( Preg rst_a;% g: A! ^4 R: X# a1 i
reg enable_a;
6 |( ?# E: a: R9 A+ s; _/ h2 d6 L$ h8 F. U+ X# g* W
reg clk_b;" `- F9 O# ]1 @7 m
reg rst_b;4 L" j8 q" r! w/ U/ B4 Z& I; Y
wire enable_b;; l+ [3 b' _8 ~2 e7 K7 e. ^* H
+ ]5 u9 z5 i6 x3 J
) n2 @9 ?4 K2 s8 d7 g$ O) v
parameter CLK_A_PERIOD = 10;3 ?. [+ y3 S9 O2 ]- w; [
parameter CLK_B_PERIOD = 30;
5 V" |* t; T/ D! @: X& z
6 r2 t0 I2 ^) ]# u% k//gen clk_a
  W: v% _/ l: |0 Y$ kalways #(CLK_A_PERIOD/2) clk_a = ~clk_a;
5 R" `7 E  }- R- r& h$ W9 e. B! _* ^7 ?# b
//gen clk_b3 \# B9 f& d3 Y- I+ D! B8 Y
always #(CLK_B_PERIOD/2) clk_b = ~clk_b;
% {% G6 z& t$ P( y6 M" A
" H/ }! d& A0 M2 d. |( k5 u
( d6 p' U1 a  Y$ S7 I5 g2 |//gen clk_a domain test pattern* c% `3 y% [8 S! t" Y( L
integer m;/ g9 K6 O5 T! d* w% f6 k

$ f! B7 k) e* ], B. a! J7 uinitial( q, t' d6 a$ |# @9 l; o/ V
begin
- O- T/ Q3 t. x% S, n6 y2 v/ L        //rst
' k5 f: p2 U$ p: [        #0
+ r) X  u1 q* A9 h9 w5 f        clk_a = 1'b0;
  c4 D' H- S4 H, h! h/ Q' x5 t        repeat (10) @(negedge clk_a);
0 N$ a: k+ _4 l( u' _: w        rst_a = 1'b1;
! ?* C5 k1 E. p2 t/ x- B        repeat (10) @(negedge clk_a);
1 t( B  f1 l9 X5 C( z        rst_a = 1'b0;
- K; R: _2 x2 P5 p5 T        1 {/ ^/ {; J4 a( ^/ |- x; \
        //wait clk_b domain rst done3 M7 |/ b0 d+ b% I$ Z' Q
        repeat (1000) @(negedge clk_a);; d+ X6 i& X9 R( q
        0 m$ F+ E6 T3 d# N. }+ y8 e: W( L4 ~- B
        //gen test signal
9 V9 h% A- J$ ]; U1 ^        for(m=0;m<10;m=m+1)
8 D& j) k6 [! j; k7 P; q        begin9 l& D! R/ G+ E  m$ s- r+ y6 X3 I
                enable_a =1'b1;
7 [/ \& K2 I+ i7 B                @(negedge clk_a);: ~% r$ \9 e" {
                enable_a =1'b0;7 M  Z: d# _4 \& P' A1 k! A* `

+ R. C: I; Y$ l                repeat (100) @(negedge clk_a);8 R) H9 y) Z/ N/ q0 A& ?
        end
  i# a1 B# l9 _. t, M  @       
. I* T' P, p1 ~        repeat (1000) @(negedge clk_a);9 h* {5 W- G6 ^' c- v2 w0 ^  n
        $stop;
5 T: @" K$ O0 q4 C6 m( A' L* B        1 }3 t( j/ t2 G( N# [3 E" q
end, }7 O" j8 g4 n4 ?& L

( b: c6 V$ N- C& ~2 s* T  |initial6 @& {( S, I6 V$ S
begin6 K1 M; ~9 w" R5 I. B
        //rst# J( N' @* E+ g6 r. p5 A
        #0
  S3 P* v" Z2 O  i2 `        clk_b = 1'b0;
! ?3 W9 Y- W( g- i        repeat (10) @(posedge clk_b);' V: r/ Z  s; J6 @' K5 n8 |
        rst_b = 1'b1;
9 a" U( @8 A. |  F+ h        repeat (10) @(posedge clk_b);
0 O2 h! o* ?) b' |7 K        rst_b = 1'b0;8 y! X* e& t+ U4 w
       
7 x! a7 m0 e  W# ~0 i. O8 |, U& nend
0 e4 y1 R$ Y% t3 V- w: p. m' c0 c5 P) F

' A4 P, e5 `5 k5 q$ osync SYNC0; G) @' i0 T: c$ ^1 S1 q
(
; f3 e6 j& e% J; i: R# _1 |.clk_a (clk_a),
& P8 l8 ?! T. M! @. w: N.rst_a (rst_a),
( Y/ \6 Y9 M( \% j' i0 g.enable_a (enable_a),& A( V' K1 Z! {2 E! [. w, z. d4 x
# x8 }* l; X* w% E6 i" N
.clk_b (clk_b),
" j) m3 x$ _' k9 O5 Z.rst_b (rst_b),
6 L) N0 p- i- i1 b( v9 l.enable_b (enable_b)
! m' z& ?0 p7 t2 E);8 q, J3 V7 I2 Q8 I
* A1 q4 _( ^$ q+ W' J
endmodule( g+ F( G. h/ E3 R2 o  r
, |3 X8 i8 |$ S( ~! d
/********* EOF *************/
# J1 f8 g! m! u) K1 I4 q% h; G" ]$ r4 r, C4 c- \; _" m) u

( {4 _* L* z9 e/ K4 J; F
1 o6 X! F/ j- r- v- `& g& u/ u" |+ v/ p# I8 R5 q* a
3,前仿验证A+ s  ^8 f2 O* g* d
下面是前仿的波形:
( W& B7 I4 W( c+ r% s! J# F% r, F  t) B/ |' O
' m3 J5 W( B3 o
7 I& S# e& C7 s
/ p9 Z) b: e) K- i# z
& z0 q- e. ]* ^: Z5 u. d2 v
从中可以看出:
6 b' E' [9 {4 S  N7 c
% V/ C" C$ R, X0 ^; Ia,clk_a是下降沿触发,clk_b是上升沿触发。; ?; k% t. e5 _

/ Y/ ]8 _6 R( D* ]5 W1 J0 }/ ob,先看m信号上面的波形:# v% v, j  v! L9 t! n; K
3 K, J* v- H3 W& r" |
clk_a时钟域产生了一个enable_a信号,这个信号被clk_b时钟域detect到了(enable_b信号)。
* H1 b  S, {  T% ^/ M# n- t. f& l) a) O+ i( a: P& n0 L
enable_a信号是clk_a时钟域下降沿同步的。enable_b信号是clk_b时钟域上升沿同步的。
" O; ]' u: T, ~
; n" ?% s; ?& P. c2 l4 b6 ~8 @那么具体是如何实现同步的呢?我们再看m信号下面的波形。
) R% j% ?% i) t% j) ^
8 C1 k1 ]( Q0 S% K6 v  Cc,首先clk_a时钟域下降沿产生一个周期enable_a信号。
7 X9 ^0 I* c2 d1 O" {" I: s) {  o2 m& t
d,这个信号寄存到和他同一时钟域的signal_a。
- y5 n1 D; j+ V( [/ q' K  c: _  U
e,异步的,clk_b时钟域上升沿采集到signal_a并将之寄存到本时钟域的sync1。* H  q. {7 ~8 b% [6 B

, a8 s9 F/ @( d1 ]8 Q1 S) @6 B: @. Sf,在clk_b时钟域,经过一个cycle,将sync1传给sync2。这时,即可采集到signal_b信号,而这个signal_b信号就是在clk_b时钟域的。
) V3 G+ k# d- h; S. E9 V6 b: \6 }( |' k
g,异步的,在clk_a时钟域,在检测到sync2有效以后的第一个下降沿,将寄存enable_a信号的signal_a清除。8 i/ E, `* Q- v1 M/ T; I2 _+ N9 t
! G" S2 {7 `+ j
h,整个同步过程用了6个clk_a周期,2个clk_b周期。, U) v* y. f" r1 s  ?$ v' A

9 M' l# y0 X5 J6 d4 w2 z8 q; \/ t' @5 t: B% c

; ~! N3 U+ {) Q1 G, u$ s% H! e8 q4,前仿验证B& }9 K$ L! r# v  y/ o4 H) y
从上面的分析,我们可以看出,采用两级触发器确实可以实现双时钟域信号的同步,但是这种方式也不是随便任何时候都能使用的,如果是慢时钟域同步快时钟域的信号,则要求快时钟域的信号产生的不能过快,否则将会丢失部分信号。7 K( @4 t/ X1 t0 o4 i( F# _

. ~5 q: ~" A! A# K$ x# r4 g3 \还是上面的sync.v,我们修改sync_tb.v中enable_a产生之后等待的时间,就会发现有丢失的情况发生。
* M* E( S! B' `8 C4 }
7 Z" r" D- z; Q1 b% c0 T; F- q修改后的sync_tb.v:
* h  i* R, S6 B) F$ ]
2 `+ e  E* U; k, M1 {, |! t4 D; B* p

- E# V6 @3 F' P0 D/ |/*
* B5 p9 C$ ?2 W+ H" T* l* file name                :sync_tb.v
! [: t' f! k# D3 ^3 a# A5 y5 a4 K* author                :Rill
. W4 E% r. B! s' X7 f! n* date                        :2014-04-12  m3 B$ _+ P. ?, P5 ]( m" r
*/
- }9 i+ Z1 B& P) y
5 [. X! V- n# F8 S- R9 p4 \3 [`timescale 1ns/1ns
) F1 z! o* X9 b5 I1 F
8 H2 p! X% z" r# b5 ~* f& K* ?. S3 |' y8 m+ q0 v, f- f0 H- J
module sync_tb;
; i8 N, @# U; O3 Z- W9 w$ v2 ^9 M
4 [  B( ^& f; Q" Z$ Z6 k0 c' creg clk_a;$ q5 u( S9 q1 e* k6 [
reg rst_a;+ c  Q$ x: e9 m
reg enable_a;
! \) e  R+ s. t! _1 w8 u! e. j, c( T0 z0 v
reg clk_b;4 m- p+ {( i" \! y+ E
reg rst_b;' A$ V7 b5 E$ b4 f
wire enable_b;
/ n; _! j/ q" a3 C8 |
6 l0 @9 A% J0 n- R$ y
% J, u9 Y4 D0 o+ Xparameter CLK_A_PERIOD = 10;
/ X. I6 R' B( Oparameter CLK_B_PERIOD = 30;: p, X) F4 ^3 x1 k
1 R# z" J/ R. O% P6 A6 Y8 Y/ }
//gen clk_a+ `7 _1 N' w# Q5 H5 j
always #(CLK_A_PERIOD/2) clk_a = ~clk_a;
1 w$ j9 h4 T$ b0 n1 T+ q$ }5 B0 J1 U: V+ @5 H
//gen clk_b
  ?) p8 Y! }% \6 d  Yalways #(CLK_B_PERIOD/2) clk_b = ~clk_b;
2 \4 R% l, \/ A. b3 X! W$ A; ?4 v2 S/ r' `$ {) D; K; ~
# e/ f# U7 T) q6 a
//gen clk_a domain test pattern# c7 p+ v+ z# E3 |2 d. a
integer m;
4 o' m& E! E4 ^9 u1 e; q+ ~- {1 g' K
initial
% S; v9 v9 s7 ~; F( e5 _0 I* |: ^! I3 \begin9 i( u2 R; v6 Q/ t
        //rst
+ }! X/ d' m( z- I        #0' ?, ^- D- M+ i( b$ Z- }
        clk_a = 1'b0;
& G: p! P& F5 m- u# S9 t2 Q        repeat (10) @(negedge clk_a);
2 o1 _: c5 N+ C5 `        rst_a = 1'b1;
4 p/ b5 ~# x/ U$ b, h* V        repeat (10) @(negedge clk_a);
$ S, Y1 a# a' @  P4 ~        rst_a = 1'b0;
9 e: l, [# J) S- J& m# _8 A* Y' h       
' J3 d3 p& c# ?$ G# z% u        //wait clk_b domain rst done1 e- M8 @6 p4 f7 F2 T  @
        repeat (1000) @(negedge clk_a);/ \0 Z9 H# l$ d) H  Z+ l% y/ A' r
        5 K0 p' _; F, L4 r
        //gen test signal
2 T! f5 A* o+ P        for(m=0;m<10;m=m+1)* z3 Z' U: y( D) z- z- ^9 t
        begin( h4 u: V1 y1 d9 L
                enable_a =1'b1;
; p, m9 B; c- |                @(negedge clk_a);
2 L6 p$ C; ^$ J- C, p0 b3 g5 N                enable_a =1'b0;
4 x, D) a% F* s9 Z/ s
6 ]  ~7 b, r+ j2 Q. j                repeat (3) @(negedge clk_a);//modify!!!/ {9 i' z. D5 K  f- I: ^& j# p
        end
( c# V, \: B& u  t9 m$ h       
- Z# i+ M. y: @) ~8 j        repeat (1000) @(negedge clk_a);
) V2 v& C( F5 e7 p1 S8 i        $stop;$ b# H3 R) z) V0 O, t  K. R
       
" |( I. p. k) F# b1 R8 rend
" a: Z2 B, _, N6 o% m! t
9 a, B6 T" Q/ [1 X& g3 D. minitial% c' D$ j, g, \- {- X9 T# d6 p
begin
. t" n, `6 N( T& p: i( z0 f        //rst
' P4 ?  b  f  ]  D& I2 I        #05 c3 w7 u7 ?) E
        clk_b = 1'b0;0 U' A: e7 X! O; E5 Q9 U# W6 z- z
        repeat (10) @(posedge clk_b);' \5 m/ R6 O3 q& S; u6 V9 a4 R
        rst_b = 1'b1;
. m2 G* A; S$ D6 u        repeat (10) @(posedge clk_b);
- _- C/ g% |! N& D4 g3 ]        rst_b = 1'b0;
7 f, U8 D4 B# r" x9 d        . G2 W( M+ I# g% D5 A# G; x. N
end
/ d* O' S8 a  a3 W. l# N  O3 A# `% f. V0 t: |; B6 X7 o

% g& l1 [+ E5 j& G" nsync SYNC0. ^+ _& n% b/ n0 q% k# V6 o
(; {  w/ j% ]% r$ v0 c% c
.clk_a (clk_a),) b$ L5 ~7 b/ U$ l( h
.rst_a (rst_a),
9 v% ~( j% W. |/ R! y3 @.enable_a (enable_a),
+ b+ v: K! E# [0 T8 F- c+ _  n1 t/ i+ \2 n7 ~
.clk_b (clk_b),
0 p/ W& f- y7 ?. C( x% R.rst_b (rst_b),
6 Z2 [9 V* [# r) P! Q. O- O2 j.enable_b (enable_b); R& B  }; O! R  J: U
);
% P0 h$ q9 I9 e9 K- H4 e. c  q, G! z; J% _
endmodule
; O  i+ g* a4 T3 [
: H9 W) ~7 a1 f  L8 ~/********* EOF *************/8 o% t: C, J* v9 u8 r9 @4 F

% M7 L4 e6 v( [4 D2 Q% s下面是修改后的前仿波形,如下图所示:' r# u! i: }9 @# X3 N4 _
从中可以看出,clk_a时钟域一共产生了10次enab_a,但是clk_b时钟域只detect到了4次。
3 }  ^2 W' u" L" [9 J3 M3 w3 v" w( W  c3 ~/ @" c  J
9 f: z# l7 D! l. ^9 M, }5 u9 q# |
* o  `# I  M& g3 j! E

5 e& J$ S; k& f. Y) F  m2 H* a4 G; E: r. A, n- M- }
5,前仿验证C4 a8 j( z' ?/ M: ^+ L3 I: T$ v1 _
上面是从快时钟同步到慢时钟,如果快时钟域的信号产生频率太高的话,就会造成丢失。
+ b( j- \& K# W. V) @
$ w/ u. a$ c  Z6 U3 i& J/ O7 x那么如果是从慢时钟同步到快时钟呢?$ M( p2 f# s6 J$ ^
5 _: {2 @$ o  S6 `0 y
将clk_a和clk_b的时钟周期互换,每隔一个clk_a就产生一个enable_a信号,结果如何呢?
$ N8 P  i4 e/ S- _& ~4 h: z3 O  {) m7 A
修改后的sync_tb.v:) _3 U0 |4 y8 s' G, p+ G

- G% A; n0 R. v: ]
, n( U) D5 C9 \3 x7 Q2 m' c* t' @+ f- U: _4 ^8 Q3 V+ [
/*4 U  x5 W" y5 k* J- O
* file name                :sync_tb.v
7 J" P0 a' O7 G8 T7 W* author                :Rill
- I3 a" a* ^7 W* date                        :2014-04-12& w' L% \" @' E, W
*/- W$ L  y  U* X; Y; E  L4 F1 h
5 m4 i5 `- s% _7 U
`timescale 1ns/1ns9 j* C, s; c  u, `
/ E1 a% R5 [) p) n+ x$ @+ m
: L6 x' P% V/ B1 `
module sync_tb;
7 V# F* l: Q1 p; x$ v$ b' l6 k6 t# q1 G3 S3 g
reg clk_a;3 B, D! K. K4 p: h0 L) @
reg rst_a;0 p  ^2 r$ o6 k. n  X
reg enable_a;! Y( M9 k( ^/ w; g, k# _
  f8 K! Z  w% j, s: i
reg clk_b;
- Z3 V9 E+ E' M6 a4 `  M& Greg rst_b;
+ V1 a1 z4 E2 }wire enable_b;
+ V. N) p! I( h. d) D9 z: N& Q
2 U0 \: V" C3 S0 G% W! g' T0 J# x  g, v: X/ N2 r+ v
parameter CLK_A_PERIOD = 30;
& U, Z) V- o$ c- d+ j; D+ pparameter CLK_B_PERIOD = 10;' m- L4 y5 t: v. f

  g6 u2 c" W) ?" k8 O- _//gen clk_a- w4 L) @2 G2 Z- `
always #(CLK_A_PERIOD/2) clk_a = ~clk_a;
' b" @4 [' M1 \1 G) z: o; v- I1 W& b5 f" V4 R2 S/ G0 O3 W, V
//gen clk_b
3 G9 [+ b0 i; n3 y  f# W; _2 calways #(CLK_B_PERIOD/2) clk_b = ~clk_b;
2 m0 G! ?4 W) \! B& v. F  Z0 z# q5 w7 Z
" J* ~( |: T; K# M
//gen clk_a domain test pattern% ]# l; u: M* h0 N2 J' T7 h( V
integer m;1 }6 Y9 S# H( K& m1 _

- z3 _0 X3 V6 o) C6 Iinitial( o3 ^- y; t" }+ r- d1 I- ?6 W
begin2 u3 \5 U2 _7 L) |& U3 }" ?
        //rst9 T: C; W$ I3 ]9 O" J
        #0, r3 j4 }$ M. z. c/ D+ ]
        clk_a = 1'b0;
4 j- b9 L: b/ E9 @        repeat (10) @(negedge clk_a);5 ^3 T# {7 D6 b2 I, ~! C# ]9 g
        rst_a = 1'b1;
  X, q' w9 ~% f        repeat (10) @(negedge clk_a);
% A8 _) J' @/ B* h        rst_a = 1'b0;
# e: m" T: ~+ Y8 \1 ]. l       
5 K5 h( w; @8 d  }        //wait clk_b domain rst done
( ^" I3 V, @2 x        repeat (1000) @(negedge clk_a);
9 o- ]. c7 x) c8 d/ O       
. z3 s" ]4 |3 l7 t9 L        //gen test signal
4 P# X+ a% S( K# R2 A+ B        for(m=0;m<10;m=m+1)
9 c- V4 v+ U1 ^5 C5 ]$ W        begin% C* J  k6 s4 M
                enable_a =1'b1;; m" f1 _" S/ L+ l4 E1 @+ W; e
                @(negedge clk_a);, `' n3 ?) q: y' t8 t
                enable_a =1'b0;, A7 F# j0 G6 N/ q
8 t( a# j4 N1 B  W4 F# Y( ~
                repeat (1) @(negedge clk_a);//modify!!!/ o% `2 Z9 E# S+ E$ h4 @
        end
( R: O1 S( a1 V- j1 m, [- i; h       
- l6 Q+ r( f- p        repeat (1000) @(negedge clk_a);
; }3 H8 ^1 z, R6 X        $stop;+ L3 `; A. d* K5 L  g
          J+ T9 u4 E* ~! B
end; R& P1 h: L: O7 n  r
/ S9 F  X: Y8 Z9 {3 O) M' x, V. v( v
initial; S0 R8 v4 T2 G) x7 S0 }6 {
begin/ j, J0 Y  r. A# }5 r% b% B8 Z( g
        //rst6 R1 T8 Z/ R" N/ j/ S8 p) a+ {% g
        #0
, i+ T( k3 Q$ o% Y0 d) d        clk_b = 1'b0;3 k5 V6 s6 i9 W
        repeat (10) @(posedge clk_b);
2 @! F( d* C1 H7 N7 q        rst_b = 1'b1;/ V6 i* K+ o9 ~2 s! {# z
        repeat (10) @(posedge clk_b);2 k- N* y! z9 Q& j/ n& s8 c
        rst_b = 1'b0;2 I' x6 z0 o" }
        5 E/ s8 m- K8 s5 l  e
end
" Y6 |3 J( S$ V5 e
/ R' J- C* l- B& `
6 v( M' ]3 A0 E/ \$ P4 X9 zsync SYNC00 E" m5 y4 P( ?0 ~+ }( r
(
9 c/ H( @1 I' }.clk_a (clk_a),
9 O6 ?. z. o& Y4 ?- h% U.rst_a (rst_a),
. Y- W6 [) z0 ~" p0 }.enable_a (enable_a),- R0 k# e8 x- D  Q; g
# ^0 q  f/ @" J0 N9 m: X
.clk_b (clk_b),
' x" ~# }' F* `4 r9 r8 @3 \" R; U.rst_b (rst_b),
& }4 n$ G2 F5 F# S- t" s.enable_b (enable_b)- y9 S/ C* I) h0 e  p9 w0 Q. c
);
" q9 }; J4 S( Q# e0 ^* D4 S
" M4 q* g$ r! ?" |5 Nendmodule2 s# {& }' ^7 |$ v. j
2 {4 e) E# X9 Q8 V9 ~" w0 \
/********* EOF *************/) G4 U# o2 l% L+ p2 `3 h7 r, W' w+ e

2 T3 o; t0 E& Q" r  V, Q
0 N, v  i  g# J" r" d下面是修改后的前仿波形:
) S% l) z+ O6 z4 a% C& O! p
0 i( L$ M' U- T从中可以看出,即使慢时钟域每隔一个周期产生一个enable_a信号(一共10次),快时钟域也不会丢失(也检测到10次)。
+ k& Q! Q3 D; E: J, C2 D
1 }0 d1 o4 p* G" G! B! k
3 Z8 Y+ \" W" E6 q8 R& o
# S  e3 T- N# W" o/ a0 ~: J0 j5 k" \; z4 ?+ W1 ^, u

8 s% G1 t3 T$ D* Y. W
' T/ j( u% z, ?
( G) [5 n& y. R& n6,小结
" H% A+ A" |+ a1 z% J本小节我们对采用两级触发器实现双时钟域同步的问题进行了简单分析,其实除了快慢时钟的问题,还有亚稳态的问题,由于是前仿,没有延迟信息,所以看不到亚稳态情况。
1 _# E4 @+ v6 @$ [8 h' O0 Y  ]6 h& L
2 J) c5 U: O" J3 u  O

0 l; [! e! R7 X. y
) o. _, w; |1 J  _" L4 D" P( g7 b& [2 o: F1 ~. X0 U+ b
/ _3 B1 y" U; L* }; S

8 E# {& A  B3 E) I: D

该用户从未签到

2#
发表于 2020-6-11 14:37 | 只看该作者
关于采用两级触发器实现双时钟域信号同步方法的分析与验证
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-11-25 20:04 , Processed in 0.187500 second(s), 26 queries , Gzip On.

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

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

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