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

基于Verilog的奇数偶数小数分频器设计

[复制链接]
  • TA的每日心情
    开心
    2019-11-19 15:19
  • 签到天数: 1 天

    [LV.1]初来乍到

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

    EDA365欢迎您登录!

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

    x
    基于Verilog的奇数偶数小数分频器设计
    一:背景
    , C. @+ D5 l8 \8 k' ~
    0 f, E/ ?$ e. V5 e7 O' Y      关于光纤通道时钟同步模块的设计。里面需要用到一个10M的时钟,而我的PCIe时钟为125M,所以需要一个12.5分频的分频器。小编偷懒从网上搜了一个,代码简洁,行为仿真也没问题,直接就用上了。昨天组长调用我的设计,发现综合出现了问题,一查代码,把我批了一通,还暂时取消了我带小弟的资格,原因就出在这分频器上。- u" V5 b" r" H/ p# S$ X$ A

    , Q. g2 v- W/ z8 Z# q7 c# ^二:问题代码分析
    / C" t/ j8 s: y: a/ I0 ]' B* \. m! s1 R. B- R+ i/ h' x
    复制代码
    ! n! Q% |9 v( V- s2 M8 c1 module divf #& `$ [6 y  [1 s6 `( g0 z% }/ c. D
    2 (    parameter N = 12 ,    // 分频数7 K- g, l3 w* r7 B5 m  i2 }
    3      parameter state=1     //奇偶分频为0,半分频为18 c) m6 w; t3 w6 n
    4 )
    , C$ u$ V! n5 B1 e5 (
    0 t- L7 F1 c% u  J/ r1 v- T6 input                 clr,                          2 S! W4 j) V+ R7 m
    7 input                 clk,   * z% o! v3 _' J6 ~" ?, w" g
    8 output                clkout
    7 z' m# P' \. P: F% d9 );1 t  R! ]! {7 V( z7 |! ^  p6 ^2 u# A
    10 1 ?4 S9 a& |! C! b
    11 reg [5:0]  M;
    ; }/ n- s2 J# P$ f' }' d. L0 _) O12 reg [24:0]  count;
    : C* X! a- G9 d5 g* i; u3 i4 ]13
    % w2 y/ S. A! z# W1 k1 W; x% J14 always@(posedge clk or negedge clk)
    8 I* j8 A$ i$ R% M" g" u% g+ c15 begin  Q' P7 F  C" _/ i! z- l$ |0 @" l6 l
    16 case(state)
    ; Z% Q! [# Q+ U* A+ |2 \( H17   0:begin
    9 f, ?& b- M" y/ w, k0 i18       if(!clr) count<=2*N-1;
    ' Z9 ^: v% [4 {) W' P19       else if(count==2*N-1)3 q3 E3 \( k3 I6 F* a/ u1 z8 P- c
    20                  begin
    & }' b5 d2 I0 x6 N( L* q  ?21                        count<=0;' b5 s: ~* B4 p: S
    22                        M<=2;    //只on一个clk
    ( g! e2 `# p4 W23                  end
    + E0 J1 y2 K) m24            else count<=count+1;9 H8 m* w2 Z/ Z3 B; \0 X; Y
    25     end3 }6 j1 R  J0 v+ L: S1 @5 ?: O7 b, h
    26   : B0 {% k/ k3 s/ C
    27   1:begin1 b' a+ s' [+ P
    28       if(!clr) count<=2*N;/ j; {! c* h& @' R  c6 S4 k
    29       else if(count==2*N)
    8 E1 U$ F" `' Y30                  begin 5 Q; t1 J3 n2 W; ~$ p
    31                        count<=0;$ K$ l) j- n5 x
    32                        M<=N+1;
      N9 g! S6 J4 Q2 K6 L& B33                  end1 S& }5 o' J& o9 G  T0 v2 h% l# R! @
    34            else count<=count+1;3 S% g* y+ f  ~% r3 i" H' }
    35     end " F4 K7 m" p' Y6 e/ Q* w
    36     
    0 V0 t, Z6 T, {/ n. E% m/ ]4 z37    default:;: z. ?% {' r- T8 Z; \
    38 endcase9 \5 b: H  H: ^
    39 end
    : s" z& x5 d' @40 3 @; @* `) {6 w# q9 l( e
    41 assign clkout=(count<M)?1:0;  y7 t- ]/ M& C' ]6 r3 z
    42 # z2 {' X& Q$ r
    43 endmodule
    ' J+ l7 Q: n9 ^1 T$ [) a复制代码0 k1 g' X0 X) T/ U& D8 M
    看到这样的代码,像我一样的菜鸟见了都会怦然心动,但仔细分析,问题就出来了。
    9 G3 C& i/ o: Q" n
      s; O9 r8 \" w) n  }# V① always@(posedge clk or negedge clk)3 S, N7 I6 k, z* j! ]) D
    9 M' u2 _/ E( x( {* b" _; t! x; [
          触发器(FF)一般是上升沿触发,我做过实验,即使想要下降沿触发,布局布线后也会有一个反相器反相后用上升沿去触发。若同时使用上升沿和下降沿触发,例如always@(posedge clk or negedge clk),布局布线后等效于always@(posedge clk)。所以上面这种写法,若不是采用特定器件如ODDR,是很难完成上下时钟沿都采数据的(应该还有别的方法,请大牛不吝赐教)。所以如果用在高速时钟上,建议不要采用这种写法。: p- M3 k2 _8 K* m7 F/ H
    8 D# _) {: h7 [' q" z7 E$ W
    ② assign clkout=(count<M)?1:0;
    7 p, j- ]/ x) s9 [1 D+ D6 R/ z( |6 a4 n/ V
          组合逻辑输出问题,如果时钟频率较高,100M以上,组合逻辑的延时很有可能超过时钟的建立时间,会产生毛刺,所以我们一般都要求寄存器打一拍输出。上面这个例子中,clkout=(count<M)?1:0; 比较器是个延时比较多的器件,所以对时钟要求高的情况下不能使用。( n7 C6 {: T0 H7 ^7 G! b4 x

    , w3 O; \# [4 X/ [
    ; h7 W  g$ W, q$ p7 f% W  F; D  s' V4 k" E3 F0 m
    三:解决方案+ ]+ T* I" k8 G8 Y, J9 I
    ( s& f1 K4 M* E8 i0 S
    ① 使用两个always块,但两个always块不能对同一变量进行操作。
    % t: M) r2 F* T2 m* A( W
    % L: k; b: C+ x. r7 ^" @Always@(posedge clk) begin  … end
    4 F5 P& Y- ]% b# E. z- }" ~8 d" S4 d
    Always@(negedge clk) begin  … end
    9 S( z2 k+ ]: w8 u4 N5 V( C* `5 M9 N
    或者使用锁相环产生两个频率相同,相位差180度的clk,然后在每个上升沿输出
    ( w0 _: C8 @/ p' l0 m: t3 q& C  J  b5 l- S: V9 D) ?) H& D; ^+ S
    Always@(posedge clk1) begin  … end( ^1 i4 l7 D- w1 v, b- H' _

    ( D1 _  K0 h& i5 j6 s- ZAlways@(negedge clk2) begin  … end
    " I3 h# `2 P! R- w0 i0 ]) o: U  X3 P) |8 u# ?! ?/ e/ e3 c
    ② 针对组合逻辑输出问题,能避免使用则避免使用,如果非要使用,也只能使用足够简单的组合逻辑,比如与或非逻辑。
    4 \. r4 B1 H, a" K9 c+ y! F" P
      R  J5 Q4 E, d0 f+ I* S8 r" }$ _6 B& e7 C( L5 y4 v: q7 a" X
    7 L* v7 c' |* w" r
    四:代码示例+ i7 o0 `- a* r9 B5 Y) s
    ' ?4 O% P* ^* P7 X8 b
    说明:用一个大case分三类讨论,看上去很挫,实际是为了裁剪方便。
      V/ E" M  p1 i& F+ t& C. G8 V+ j  y: f3 y/ \# _/ B& e
    代码功能:完成奇数分频和偶数分频,占空比50%。完成n+0.5分频,占空比无要求。
    / k' ]2 {8 G7 q! r0 H/ s: L# m9 ?; w, V0 S- x$ h7 [- t3 K
    复制代码+ ?( _7 \, l; C
    1 module divf #3 p" F+ h: M' r6 u  Y: H8 Z# O/ a
    2 (    parameter Div_num = 12 ,    // 分频数
    ( U# Q' s$ \& }8 o9 H/ f3      parameter state=0        //半分频为0,奇数分频为1,偶数分频为2
    6 f" r( Z" m& j& O4 )     8 n. n8 J1 j/ Z& i, v, g
    5 (+ v, H# n" p# L& x) l; q! A" d0 z" ]
    6 input                 clr,                          % X: ]" V0 t8 v* Y: X7 M# V! F
    7 input                 clk,   
    / u! D5 Y' F) O6 Q' W  @8 output                Div_clk
    9 c2 X9 `5 V+ s& p9 );
    . X+ |1 I. W- R* x& v/ k10 reg [24:0]  count;  j! x' d) ?; O' q; h7 H, [
    11   T. r0 i$ B/ E; y9 ~
    12 case(state)6 L% c  W" g- r' ~2 U/ k( P
    13 1:   begin  //ji_shu' H7 o, H: r  c  a" s2 a5 G7 a
    14           reg         pos_clk;: u$ S2 ^  a" P2 r( q
    15           reg         neg_clk;
    9 r9 x+ l( V& Y/ @16           4 [4 p# N+ g$ f0 R6 v
    17           always@(posedge clk or negedge clr)
    ! z! `2 }) y3 @! c) N! a/ B18           if(!clr)                     count<=0;
    9 n. {: J  e" I0 v19           else if(count==0 & pos_clk)  count<=Div_num/2-1;
    3 o0 ^% L& @. |  o. |20           else if(count==0)            count<=Div_num/2;
    & y+ ?. s9 H* Z+ y21           else                         count<=count-1;2 z4 M& {) {" d2 z
    22           8 L; c# S& D, J# |* e+ J! f
    23           always@(posedge clk or negedge clr)$ l9 |0 w7 n" y+ D- x
    24           if(!clr)                     pos_clk<=0;
    2 K& |) O8 M3 z' v25           else if(count==0)            pos_clk<=~pos_clk;
    / I: P' o" _( ^( D" }26           else                         pos_clk<=pos_clk;
    ) d) k7 {3 Y5 r27           3 Z2 e2 t3 i7 i  G
    28           always@(negedge clk or negedge clr)
    9 ~2 G7 ]$ U1 h8 s( F& G29           if(!clr)                     neg_clk<=0;
    : }5 \6 b+ _1 V0 ^) H4 k) K30           else                         neg_clk<=pos_clk;( T1 V: j" x6 @6 D$ w! M  T
    31           
    ( C+ S+ j. K5 D. |& J& ^32           assign Div_clk = pos_clk & neg_clk;          : N3 e$ j1 A" Q8 {5 F4 k- _
    33      end
    . T6 {8 j% Z6 }5 `( A7 S34
    / A, J' G, P6 v0 R7 A35 2:   begin  //ou_shu
    & V/ c4 [5 d1 I  |5 @( S4 [; e0 R36           reg          Div_clk1;        
    9 E0 x" }+ E9 a( `( L37            
    $ d1 R$ W& h; D5 F0 `38           always@(posedge clk or negedge clr)                  4 J8 V/ @+ d% `5 _4 B* k
    39           if(!clr)                     count<=0;                        
    # m& z2 |: S! C' v$ s: w- p! Q40           else if(count==0)            count<=Div_num/2-1;      
    - ^" m, F; [1 F8 R1 X1 J9 y; E41           else                         count<=count-1;
    ; a; v" \9 d$ m1 D  L# y42 / @9 N" d$ f* N1 t( W3 N4 f
    43           always@(posedge clk or negedge clr)                  
    ; `+ X' [8 n' E7 i+ |44           if(!clr)                     Div_clk1<=0;                        
    : W8 e- r, t6 \45           else if(count==0)            Div_clk1<=~Div_clk1;   ; ?7 c, E$ I, ]
    46               
    $ f- q2 q/ j, V8 V+ m- l' F% L" O& ?47           assign Div_clk = Div_clk1;
    & L2 K. b7 O$ Y7 Q9 x48      end  
    7 Y, P9 ?" w! E# B0 H1 U. v* d49           6 Y+ C+ U+ ]; O+ z! Y, q0 a
    50           
    . @9 S5 Y* @  R: ]. c9 |4 F# S51 0:   begin   //ban_fen_pin& E8 V/ q$ d5 n- R* {& A" T4 ^" i
    52           reg         count_div;
    ' V* g# }  w, v' k9 @3 C  l/ |53           reg         count_div2; - d! d0 W5 o5 e7 p' o) C! L* s8 Z
    54           wire        clk_half;. X! G! Z% f* @6 v
    55           * X& p' a9 q1 R: W
    56           assign  clk_half = clk^count_div2;, q: ^4 t4 {# g
    57           always@(posedge clk_half or negedge clr)   //模Div_num 计数            , i* e+ m; B9 B6 Y# P2 C7 L) _9 j# g
    58           if(!clr)                       count<=0;               
    6 z# y# _0 J6 v; d% c% n59           else if(count== Div_num-1)      count<=0;         1 f3 T' `# z6 I! J* i
    60           else                         count<=count+1; - g- ?) z4 \8 b
    61  % j+ o, t( c, }* |: p: K. X/ _% b
    62           always@(posedge clk_half or negedge clr)   //模Div_num 计数            
    3 E7 j' A1 v& f5 g63           if(!clr)                       count_div<=0;               
    , _/ D* s$ S5 |7 Z: Q64           else if(count== Div_num-1)      count_div<=1;         
      n% B! B: a# O& y65           else                         count_div<=0;  
      |! C" Q$ D$ ^5 R2 J66           7 \% r  V! b) q5 i
    67           always@(posedge count_div or negedge clr)   //对count_div二分频            
    4 m% b( S$ _( W' s( B68           if(!clr)                       count_div2<=0;               
    # A) }0 B3 ^; A$ D% e: M) z6 p69           else                         count_div2<=~count_div2;  
    5 R$ i+ s5 `9 o2 F3 {" Z5 d70         
    0 F# V7 \" |% r6 B71           assign Div_clk = count_div;' f. C2 m2 Z% O2 V
    72      end7 e( O4 ?8 K7 h
    73 endcase   
    : Q' d6 @4 ]) v5 O4 f4 Y0 L& A74 9 ]2 @$ U5 i7 ?; N# t
    75 endmodule3 A6 t) n# e; J( [4 z# i- A
    复制代码7 ~# U7 P6 N7 n: n
    五:仿真代码及结果3 \0 p/ E3 ]2 f4 \1 r2 l

    3 H& B: z  l2 \' Q复制代码0 z5 U9 C2 e' }; W- ~
    1 module test_divf;
      k: Y9 [- w2 t2 b7 B2 reg clk;1 A4 V4 q$ {% {" _0 S) {1 W
    3 reg clr;' y! [# k0 ?6 Q$ r3 O! j
    4 wire Div_clk;8 y3 X9 t0 a! c  I3 u
    5 / P- U+ v* j' E
    6 always #1 clk=~clk;1 D$ z( o  {( D* I0 _
    7 1 Z4 C2 Q0 A  m
    8 initial- _4 M3 ?0 E1 f- l; ]3 ^2 }
    9 begin
    1 Z2 U2 {0 a2 b( q$ U) J10  #0 clr=0;clk=1;- I, p! W+ y( G/ [% E) M; \
    11  #99 clr=1;3 R- N+ _# ?$ ]; D
    12  //#1000 $stop;
    4 K/ L' I- H( I& ]: I! C13 end
    % k8 a5 Q. L7 [6 c14 & s) a- j% F. P! b  }
    15 divf #
    6 t' f" {8 H# o, ?3 V3 ?16 (
    - w" S7 ^" y2 K- `" y" g17    .Div_num    (          5            ),
    3 i  L+ u6 X( ]! Y1 Z18    .state      (          1            )3 Y' X. E5 G* o
    19 )divf(
    5 l1 l8 D9 m2 H% i20    .clr        (         clr           ),
    & {7 S# q7 t0 T6 D; l21    .clk        (         clk           ),
      O" h7 K8 J* }, W$ X  c22    .Div_clk    (        Div_clk        )
    & W5 l( i6 I- T4 e) M* d! D9 U23 );  
    1 c8 U1 M* A9 X24                                                           
    % E% P7 L, I4 Y( w1 @( `25 endmodule   
    / Y: A* I  p% _4 D9 b
    4 q' \& H4 z" X: D6 S; V

    % C, _# _% G- U0 Y' P3 q3 z- s
    7 N- j# N3 x6 z2 o5 Z# @' A
    " @6 m* o0 H6 D8 A9 c0 ]2 E& E5 G6 s5 M3 f: N3 e

    ) \* {0 I, p4 U- X" F* R# ?
    0 E! p" b  F: K5 _: }

    - Q' i2 L3 O0 |4 L$ S) F# p! [
    + X7 K! f3 b3 N
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-7-23 10:36 , Processed in 0.109375 second(s), 23 queries , Gzip On.

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

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

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