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

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

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

    [LV.1]初来乍到

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

    EDA365欢迎您登录!

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

    x
    基于Verilog的奇数偶数小数分频器设计
    一:背景/ r% K& E8 s0 a0 f6 q
    + o4 R3 o* F( D8 R, Y/ K
          关于光纤通道时钟同步模块的设计。里面需要用到一个10M的时钟,而我的PCIe时钟为125M,所以需要一个12.5分频的分频器。小编偷懒从网上搜了一个,代码简洁,行为仿真也没问题,直接就用上了。昨天组长调用我的设计,发现综合出现了问题,一查代码,把我批了一通,还暂时取消了我带小弟的资格,原因就出在这分频器上。
    ) D6 i; P1 U+ I( D0 b" \. I& l& t1 ?2 H/ n( m  X
    二:问题代码分析
    / ^8 P% d0 p8 e6 e, E: L. h* e0 u( z0 |* i- D, d
    复制代码, f3 Q, f) k& h9 P# s: d6 y" T
    1 module divf #, q4 g& F, n6 ]: N
    2 (    parameter N = 12 ,    // 分频数6 E- J6 x' f( w# K6 I3 S
    3      parameter state=1     //奇偶分频为0,半分频为1- y  A4 v6 A+ Z( M7 m& f2 F" Z
    4 )
    : Z+ |7 j; C; ]5 n$ K5 (
    2 C" L& H9 i5 T4 p$ p  Y8 {6 input                 clr,                          
    * z. f9 [/ U) M. D' G7 input                 clk,   # w; P' N& _/ L0 r1 H2 `- d
    8 output                clkout4 T  H# z* j) s
    9 );% K  [( j$ ~( [9 Q* V  C+ q
    10 ; K; g: ^7 [# T' C2 L4 x( C4 h5 B4 i
    11 reg [5:0]  M;
    ; o9 r( X/ X- u% _9 i% [. G12 reg [24:0]  count;0 t% ^8 Z1 X! l
    13
    " x/ B2 g3 B1 m14 always@(posedge clk or negedge clk)8 y3 G3 r1 W8 v- L( t" B, |1 h6 E
    15 begin/ W& O3 \; j. o! ~; b2 Q2 d3 g* P  E
    16 case(state)" h5 L, ~+ A* H( o
    17   0:begin! }" \* L4 y" B0 m0 B
    18       if(!clr) count<=2*N-1;
    ( M5 c. g$ D( H# d, z4 s19       else if(count==2*N-1)$ P! k# @0 a$ u% g7 g5 P7 Q
    20                  begin
    4 U/ k$ P, ^8 D: Y. s" K& ?21                        count<=0;. ~4 E  J  z# u# a5 m  Q) W) H5 w
    22                        M<=2;    //只on一个clk
    - i5 r3 P: E+ `$ ]$ G) e/ l& C" }23                  end
    " @0 S( J) I1 T, P" I24            else count<=count+1;
    5 Q0 [. L6 p4 b+ p$ I25     end% {# J, [! t  [6 x
    26   
    + a8 ^" a0 S* r; ]1 U6 H1 g4 V* M27   1:begin; Z% l& j4 _  ~2 J% y
    28       if(!clr) count<=2*N;" Y% h7 ?" r2 p: Q& {
    29       else if(count==2*N)
    & `# k' h* E" a30                  begin
    ) ?3 a/ C7 Q) J31                        count<=0;
    - }) o7 L5 N9 Y# {32                        M<=N+1;$ ?1 d! O* z- |
    33                  end' x' q$ c! f/ R9 N+ ^! }
    34            else count<=count+1;
    5 T9 [3 ]  ^4 V6 n35     end
    / F" E% Q8 r! c& G% z6 }36     
    1 z0 ]+ C  Q' @5 c37    default:;
    / m% g4 a2 h) Q: `$ |7 F& h38 endcase
    . S  t0 }9 P4 F% d+ R, t39 end3 M4 G8 v$ G* ^+ a" Z6 m$ g0 z
    40 , c, ^7 e# V% X! D! X- O  j2 O) w
    41 assign clkout=(count<M)?1:0;6 i7 X' _) [6 A7 f
    42
    8 m0 d: ]. [* V( C/ w43 endmodule6 ^$ y5 m6 K) c' L2 A
    复制代码
    . E5 g! n& L5 j3 |看到这样的代码,像我一样的菜鸟见了都会怦然心动,但仔细分析,问题就出来了。/ ?! ^5 [% A7 R' `4 F& z& j: |' H4 _
    % R; M, `) N) P, T! n% O
    ① always@(posedge clk or negedge clk)' T$ k1 t4 `, b4 O
    $ f* L1 o) p' H! [: J) a1 w
          触发器(FF)一般是上升沿触发,我做过实验,即使想要下降沿触发,布局布线后也会有一个反相器反相后用上升沿去触发。若同时使用上升沿和下降沿触发,例如always@(posedge clk or negedge clk),布局布线后等效于always@(posedge clk)。所以上面这种写法,若不是采用特定器件如ODDR,是很难完成上下时钟沿都采数据的(应该还有别的方法,请大牛不吝赐教)。所以如果用在高速时钟上,建议不要采用这种写法。, K* u9 r( u& l& F  v  F, g( O: ^

    # `* Y9 w1 ^/ Y$ l: ?5 x② assign clkout=(count<M)?1:0;1 i  H7 i9 L1 H) G4 V

    * T/ J! [6 v1 H- U5 J% o7 V      组合逻辑输出问题,如果时钟频率较高,100M以上,组合逻辑的延时很有可能超过时钟的建立时间,会产生毛刺,所以我们一般都要求寄存器打一拍输出。上面这个例子中,clkout=(count<M)?1:0; 比较器是个延时比较多的器件,所以对时钟要求高的情况下不能使用。
    ! Y6 H0 b* L; I+ C/ b+ @2 I: E5 S. v# b$ ~
    " E! Z: h/ h9 P# d- a

    ; G- V5 R% t; D) L三:解决方案2 v( @. s+ G" `; S4 ?

    1 O+ E, u' T! W7 l9 F4 g① 使用两个always块,但两个always块不能对同一变量进行操作。
    ( P' @% @( V. v' k
    7 X7 r! Y) Q1 f1 U; T6 Y% O; \  cAlways@(posedge clk) begin  … end
    $ \2 S- N7 o( T( m; Y! C$ N. I5 S( y% |  p
    Always@(negedge clk) begin  … end
    1 b1 E- ?4 ]9 M% I2 I! @, l! g# d
    或者使用锁相环产生两个频率相同,相位差180度的clk,然后在每个上升沿输出
    % P/ A  x" Q7 X; ~/ k  h
    $ x# S; l2 ^; S- n: |Always@(posedge clk1) begin  … end
    ! g" r8 w' J" q2 D. i6 T, s4 _
    $ ^) o9 g8 c, pAlways@(negedge clk2) begin  … end& V0 G2 J+ ^; i, Z! t' f

    / ~7 J, L% g- b0 N0 Z+ D$ S8 y② 针对组合逻辑输出问题,能避免使用则避免使用,如果非要使用,也只能使用足够简单的组合逻辑,比如与或非逻辑。
    " U+ V- [$ d) ]. A2 [
    $ K  a8 `3 q+ X3 W& [3 w  o- o4 w  u7 H: C

    ! I1 d( N6 I8 E1 f; T% b四:代码示例# M' b$ R5 n9 i0 S+ J5 ?

    6 t) x  e$ r! o; d! M说明:用一个大case分三类讨论,看上去很挫,实际是为了裁剪方便。5 R4 E( ^2 z7 F% [* K
    ! G8 x' l/ X, B  E
    代码功能:完成奇数分频和偶数分频,占空比50%。完成n+0.5分频,占空比无要求。7 Q* g" R5 A& {! O6 H9 D. l; B

    + Y$ ^' H0 ~. ?' U! N, D$ X复制代码
    * A) F  @* }6 m, Y1 module divf #
    " s. E1 c/ U' {' z0 L' J2 (    parameter Div_num = 12 ,    // 分频数
    4 l+ z! k6 ]# `/ M) ]& v; E3      parameter state=0        //半分频为0,奇数分频为1,偶数分频为2
    # L! d" M" o( v) g; w4 )     
    & b8 u5 C. z* a: w: z5 (
      g) [2 T. k, q  x+ t+ }6 input                 clr,                          0 Y$ X+ @. a' q* E' t% p3 ~) B
    7 input                 clk,   
    ! h$ N  R8 _4 {4 x0 q5 l% M' q8 output                Div_clk& _( C7 L  B1 ~+ h6 V" R/ ^* ]. l- e
    9 );
    ; K  O. F; a  O1 P! F10 reg [24:0]  count;5 i/ h7 G$ W. C! k0 ]
    11
    / F' T; Z* q7 f) W  j5 \6 R9 W0 x3 d12 case(state)
    5 A$ Z4 m. a! k5 r13 1:   begin  //ji_shu" [9 W" ?' f: a0 w6 ?
    14           reg         pos_clk;
    : I6 ]8 B1 A  V9 r% b15           reg         neg_clk;, A' Q, Z2 |9 X8 u
    16           
    1 X7 |6 j) L  s17           always@(posedge clk or negedge clr)# u8 a3 b. v! T: B: h: H: d
    18           if(!clr)                     count<=0;9 N( @* B, ?, \# z, S
    19           else if(count==0 & pos_clk)  count<=Div_num/2-1;% ?( n$ ]- Q9 p7 h: `1 Z/ Q
    20           else if(count==0)            count<=Div_num/2;& J* l# x- `) s% e' l; o8 s
    21           else                         count<=count-1;
    3 G+ c$ a9 Z4 X' e2 c7 o1 c, S$ t22           3 j% L7 J) S2 s. _5 p3 Z
    23           always@(posedge clk or negedge clr)
    0 @) U9 g, \' j# X' W! b4 D; m24           if(!clr)                     pos_clk<=0;! w5 t- M! d; J! |
    25           else if(count==0)            pos_clk<=~pos_clk;
    " K- U5 \  H) @0 j26           else                         pos_clk<=pos_clk;; M  P+ S6 U; H2 F4 C+ ]! [  x
    27           
    2 f+ ?- V6 ^( M1 N, e/ b" V/ z/ D28           always@(negedge clk or negedge clr)
    0 h# a1 k$ F' b( A( a" N29           if(!clr)                     neg_clk<=0;
    7 h  d5 u  B. i9 C) |% E30           else                         neg_clk<=pos_clk;0 z( X% L9 L: ^8 G
    31           
    " i/ c2 b+ }* y* A( N& g# y32           assign Div_clk = pos_clk & neg_clk;          1 Q( F& J) ^, }8 i/ z. z
    33      end
    ) Z& ?, x3 d( {8 v34   O( z, {( j$ g2 a. |% l
    35 2:   begin  //ou_shu
    5 i4 R% H+ M1 \* s7 g6 e) d/ h36           reg          Div_clk1;        ( k( |7 j8 ~9 [* E5 k: G( C8 s
    37            
    8 _7 J1 q  X4 }38           always@(posedge clk or negedge clr)                  
    ) d; I3 g! y: ?% Z# Y: t/ Y39           if(!clr)                     count<=0;                        ) M, z  }& U$ o9 R
    40           else if(count==0)            count<=Div_num/2-1;       - Q( V' \5 W' d% V, k6 M
    41           else                         count<=count-1;
      O5 t- j  c9 \5 s# O; g+ m4 ]42
      O5 |: C3 W3 F5 L- L! ?- h" [43           always@(posedge clk or negedge clr)                  
    ; A4 c5 f; Q& b44           if(!clr)                     Div_clk1<=0;                        
    7 h( P: p, }, z5 @: J6 [! i/ {* K45           else if(count==0)            Div_clk1<=~Div_clk1;   7 A& R3 ]  s8 `/ b( _" H
    46               - _( H1 {$ c' \
    47           assign Div_clk = Div_clk1; , o  W/ }& }8 p: K  u
    48      end  
    1 t$ w5 ^0 i: L$ j& P# q, Z; b49           2 v1 ]  g7 }8 ~# I9 w' R  z
    50           
    ! ^2 H3 z& {8 t" ]0 X0 [( H" V51 0:   begin   //ban_fen_pin9 _' @* r/ g  B; A
    52           reg         count_div;  k+ Z+ ?$ i" h2 m' o
    53           reg         count_div2;
    / Z, ~0 j8 {0 `0 p54           wire        clk_half;9 w4 [9 c2 m2 ~# U- U0 V8 h
    55           
    5 e! m7 a& Y. l) _7 J4 u6 O56           assign  clk_half = clk^count_div2;: ~- d0 G: @  I" V4 D$ c
    57           always@(posedge clk_half or negedge clr)   //模Div_num 计数            
    0 y7 S  I' g/ S, w58           if(!clr)                       count<=0;               
    / z4 Q  Z( j  l0 G1 A59           else if(count== Div_num-1)      count<=0;         & B1 _4 G3 F1 X; t9 y/ A) j
    60           else                         count<=count+1;
    / ]) L. k1 t: {5 j61  & L" b: C& i* H/ v9 w+ `' w% ]3 K
    62           always@(posedge clk_half or negedge clr)   //模Div_num 计数            
    ' {% x2 B; C9 H63           if(!clr)                       count_div<=0;               
    * u' ^8 R6 {; A# u64           else if(count== Div_num-1)      count_div<=1;         
    ' x( i4 ?  p# `; }2 I" ^/ g' W) @65           else                         count_div<=0;  
    ) I3 r* A/ H1 u5 x1 g- l6 j: G66           , t1 Z+ Z3 j2 q- ]
    67           always@(posedge count_div or negedge clr)   //对count_div二分频            
    , {! ]7 L# \3 [/ l2 s68           if(!clr)                       count_div2<=0;               
    4 N1 ^$ e1 n3 m9 V9 M69           else                         count_div2<=~count_div2;  
    % \! M7 \; P+ a* d  L/ h70         
    . y" U4 u& W& B) x71           assign Div_clk = count_div;
    & B* i+ m' A: |' H1 l# z7 h72      end9 x6 W2 n' ^2 m" p
    73 endcase    6 J7 V6 }( g# k$ f# o( C; E
    74
    ; p% G1 F9 l# v$ k# s75 endmodule, p% _- Q* i( z5 W% I& D4 G
    复制代码! o2 t; a0 J; R1 K. l) q# M$ \
    五:仿真代码及结果
    + H5 ]) I0 g) e# c6 |
      K1 z* }+ Q# M. _6 y复制代码, o3 B& `+ P' S4 r
    1 module test_divf;
    " ?$ L% W) ]  _5 U6 I8 k0 [' B2 reg clk;
    & \" E( v* k$ J1 y1 Q  z* a3 reg clr;
    6 W" V# m1 c8 C+ x5 W4 wire Div_clk;* i- h5 G2 v) U; [6 o3 R
    5 + Q" |0 Y' K; z) _) t$ ^: U) b
    6 always #1 clk=~clk;( A9 A! ^. `0 S7 s4 f1 {' M
    7
    1 _+ l: B! J6 ^, P  q  x, ?# \8 initial$ L' {* T, B; F9 N- r5 G& G
    9 begin
    ; v! [# y7 s3 d4 h) k" p10  #0 clr=0;clk=1;
    3 a# X4 T8 r2 ^* ~% H11  #99 clr=1;
    , j+ A" K4 ]! b# M1 o12  //#1000 $stop;; z4 ~# P" r! W& R' ~
    13 end
    * @$ R  b9 i6 \14 1 w! J' g( E; Z) P0 l0 }, Z5 o
    15 divf #
    ; T' ^+ s* i! v3 U+ j' M$ D- M16 (* r1 ^, s% `4 w" Q6 y, q# w$ a! F
    17    .Div_num    (          5            ),
    & d+ |, L1 r6 e18    .state      (          1            )' T7 t( q" c" y3 ?# e/ x/ G
    19 )divf(
    6 q. O( z. i: N- i+ I/ Y$ x" a: t: j20    .clr        (         clr           ),
    7 e  s" ^4 m) Z5 w( p' {) p21    .clk        (         clk           ),
    6 x0 i& e8 M/ U7 G- J& r3 p) y22    .Div_clk    (        Div_clk        )
    / F! r1 V4 _! ~# i23 );    v- t. X4 J" {
    24                                                           
    0 e5 y9 a+ |' e6 w* T. _  f3 G25 endmodule   
    0 b1 r9 }2 I0 c! P
    ! M& K1 B: a, P( c% v

    4 ?1 U6 x1 i! r5 N
    # @6 T( I& m4 h2 M* u/ w
    6 l- T/ E2 L0 w5 v0 p3 M; g
    " q% r1 |  G& W: b6 W8 e7 R
      o/ y6 ?& h% }' X! _0 I
    3 t/ E* Z' U$ j4 V6 h$ P5 Y3 r
    - z' k5 z6 G( k- ?+ H5 z9 S: A
    4 o7 ]5 P: Z# S! y* p% D
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-10-6 15:06 , Processed in 0.171875 second(s), 23 queries , Gzip On.

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

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

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