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

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

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

    [LV.1]初来乍到

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

    EDA365欢迎您登录!

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

    x
    基于Verilog的奇数偶数小数分频器设计
    一:背景
    7 Z- v- u7 y; ~. e6 O) x  n
    ( w: f& h3 p/ ^* J      关于光纤通道时钟同步模块的设计。里面需要用到一个10M的时钟,而我的PCIe时钟为125M,所以需要一个12.5分频的分频器。小编偷懒从网上搜了一个,代码简洁,行为仿真也没问题,直接就用上了。昨天组长调用我的设计,发现综合出现了问题,一查代码,把我批了一通,还暂时取消了我带小弟的资格,原因就出在这分频器上。
    / n2 Q0 P- j! E( U" k* ^0 f$ f
    6 F5 {, }9 [3 c8 I7 y二:问题代码分析6 I; l+ L1 `0 m. G$ z, W  K

    # O9 @, `" x/ t; X3 ~+ S复制代码
    6 s' C9 N" {) @' {8 P* l1 module divf #
    9 u. m" T$ ^0 }2 (    parameter N = 12 ,    // 分频数& d5 o# a& n; y) w
    3      parameter state=1     //奇偶分频为0,半分频为1& `( E/ A4 b3 M  L4 e
    4 )
    ! y2 Q" ?0 j7 |% M/ [5 (
    & Q; H& @3 g: H7 s6 input                 clr,                          + ~8 z1 ^5 a# K! i* F
    7 input                 clk,   4 h. n% h, E# k7 _- P0 |
    8 output                clkout
    2 a1 s& S, w% H9 );9 E: b& @- B- @, l
    10
    ' F; r& }0 Z; S1 ~0 G8 s) F- J+ S11 reg [5:0]  M;7 S) R8 u  V5 m4 }* ]. [
    12 reg [24:0]  count;6 e4 s% Z. t5 K* A
    13
    + j8 H7 C1 x8 S; S3 q14 always@(posedge clk or negedge clk)8 J; a  ~& S1 {  M. ~
    15 begin" t1 t- g+ a8 Q
    16 case(state)
    8 H3 U1 @6 C$ b. [% u17   0:begin
    , h+ g$ a9 N; m" t, [18       if(!clr) count<=2*N-1;  f# |6 }$ ^& J) l+ k3 S8 D) b9 h
    19       else if(count==2*N-1)3 ]; Z. d6 H+ O+ s
    20                  begin * z3 Z% |& W0 Y7 P
    21                        count<=0;1 u7 k9 `; t# H0 ]: `: S5 l* Z
    22                        M<=2;    //只on一个clk/ \' D( A8 @0 V" `9 E
    23                  end2 z8 E6 q- k4 n* q) _8 x) d
    24            else count<=count+1;
    4 q5 g. a' P/ w/ [25     end
    $ Y/ e7 A# a, b! [8 ?* j8 e* `/ `26   
    % _( L* o5 e7 Q; `9 K9 }. E27   1:begin: `9 R  H: f8 T. E) T; I" v1 Z
    28       if(!clr) count<=2*N;
    9 j9 c& G5 K/ E# O: W4 q29       else if(count==2*N)
    3 @! \  L8 |8 F' D! r* p: D30                  begin , @/ e4 E, ^) S5 B
    31                        count<=0;) ~; K. T5 f8 d" v
    32                        M<=N+1;3 H$ p7 J: D7 w0 I# [* @: z
    33                  end
    1 L7 W) O5 M; g+ u. N# I34            else count<=count+1;
    8 y1 R6 J$ F5 h2 o7 D; m35     end   I- b2 _% J& p* L' H1 ^# [
    36     
    ! w# t5 X9 V: m2 {8 a. ?4 N; u4 b37    default:;4 h& `( U, Z! ~( ^  I' S
    38 endcase- Q( w5 v! i/ e& u2 f% S: x
    39 end, Z) ^+ Y; J7 D7 X( ?8 q" f5 j
    40
    ! a9 C+ Z% v2 O' ?, _41 assign clkout=(count<M)?1:0;' f  H2 g' u( l: s, A6 Q, M+ @
    42 7 t( o  j. a+ ]1 a$ W4 T2 e
    43 endmodule
    4 T, k! l; L& q0 w' f- b复制代码
    1 ~. `7 ]! @  k& C看到这样的代码,像我一样的菜鸟见了都会怦然心动,但仔细分析,问题就出来了。
    / r3 I% J, m3 w) ]' S( ^+ Q* C) q. r
    & [# H2 I4 U2 d  T4 ?" K: i① always@(posedge clk or negedge clk)4 `$ Z: s) j+ G
    ) n) t; d& e0 U# n  z+ E+ q6 U' H* M
          触发器(FF)一般是上升沿触发,我做过实验,即使想要下降沿触发,布局布线后也会有一个反相器反相后用上升沿去触发。若同时使用上升沿和下降沿触发,例如always@(posedge clk or negedge clk),布局布线后等效于always@(posedge clk)。所以上面这种写法,若不是采用特定器件如ODDR,是很难完成上下时钟沿都采数据的(应该还有别的方法,请大牛不吝赐教)。所以如果用在高速时钟上,建议不要采用这种写法。+ T9 G) D8 r# I+ ~# K

    " J1 I  ~4 f- C$ U9 v. p$ q② assign clkout=(count<M)?1:0;
    1 K- }1 S! {$ q& n* W
    0 J0 v) i, n: T3 [2 d1 F* c7 j- c      组合逻辑输出问题,如果时钟频率较高,100M以上,组合逻辑的延时很有可能超过时钟的建立时间,会产生毛刺,所以我们一般都要求寄存器打一拍输出。上面这个例子中,clkout=(count<M)?1:0; 比较器是个延时比较多的器件,所以对时钟要求高的情况下不能使用。
    + x& Z& G& _! r  x; T" L, ~0 a6 P/ z' Q8 X: `3 @

    / W( Q& I& y+ W$ J" r; F# r! _6 w$ ~2 [
    三:解决方案
    * ?1 z3 c/ N9 a) b; V/ B
    6 o1 i* ?% N/ [; Z1 s$ F$ |① 使用两个always块,但两个always块不能对同一变量进行操作。
    9 S5 t$ G4 e# a6 H8 [; Q6 h& C  E- B. J$ v2 Q  ]; d
    Always@(posedge clk) begin  … end% \8 i+ R) z5 n- l5 o1 I

    ! {# q& O$ v' ]- xAlways@(negedge clk) begin  … end
    ' I( t4 e* Q2 u- S6 z  c' B3 r" d( E& w9 k# X5 S
    或者使用锁相环产生两个频率相同,相位差180度的clk,然后在每个上升沿输出
    3 b4 A* B/ }- `8 C
    8 A- u& `1 E+ SAlways@(posedge clk1) begin  … end, L* U, w' c! Z( U! T
    ' T" }; B% R2 C* Z$ J* P4 i
    Always@(negedge clk2) begin  … end
    ! j/ D/ h  P; ?2 Y. e2 x: a
    , x$ j' N# _+ ~( s* ?% D② 针对组合逻辑输出问题,能避免使用则避免使用,如果非要使用,也只能使用足够简单的组合逻辑,比如与或非逻辑。
    ; P! \/ r/ `) t2 W
    / j/ `+ y/ ?  G8 [$ r  {, |6 u+ h% c! t) u) v: L: I

    2 v, Y$ x! f( ]+ w% W+ `四:代码示例0 b7 D% `( G, C( R
    & u8 x' P7 w4 v
    说明:用一个大case分三类讨论,看上去很挫,实际是为了裁剪方便。
    / b, C. n. Y; o$ }. j: S0 q  P1 n! o0 Q) j9 [8 k, [% B
    代码功能:完成奇数分频和偶数分频,占空比50%。完成n+0.5分频,占空比无要求。) h7 ]. c6 w  N3 c1 y, R7 ?; Q# {3 F

    ; g- O. o7 p$ ^# Y9 L; C) j" t1 {+ ?复制代码
    5 A* R- c) {! q# C2 E% V1 module divf #/ F9 `" z5 j. i4 ~8 J' c
    2 (    parameter Div_num = 12 ,    // 分频数( b7 {) Z: }! M$ G' i
    3      parameter state=0        //半分频为0,奇数分频为1,偶数分频为2% R! Q2 _+ Q" X! m8 A  p  J
    4 )     
    & p- x( R6 Q, s7 e  N5 (% w* m# N: b: z( _7 z
    6 input                 clr,                          
    3 k* U8 j8 J. U! r0 y7 input                 clk,   ; m4 @/ K9 E) F9 X4 m7 b
    8 output                Div_clk; ]0 x  H- D1 @3 X
    9 );
    ( A$ @# W' }% Z9 g10 reg [24:0]  count;
    3 i, {) [9 s2 l3 p6 ?# C7 t" I& z5 }9 W11
    ( y/ |: \2 S8 w( t3 B+ h12 case(state)
    7 I+ Z$ Y9 w0 f) ^; K$ J9 Y13 1:   begin  //ji_shu
    * J) b) s" z  ?# j% C7 E  M; l14           reg         pos_clk;
    2 ^& f0 B$ h4 h1 ~" }$ Z( Y: y' M15           reg         neg_clk;
    8 Y+ u; t  F0 W% O4 j/ W% q16           
    ' {- n# v& P( Z, Z- `1 }4 }. ?8 Y17           always@(posedge clk or negedge clr)3 Q4 X' f0 d; R) D3 B* s& y1 z) A
    18           if(!clr)                     count<=0;
    ; H0 B7 g, H1 k7 x19           else if(count==0 & pos_clk)  count<=Div_num/2-1;( L& P) L0 U. Q8 y% H
    20           else if(count==0)            count<=Div_num/2;
    0 A2 R; F4 Y; {. S* e8 B21           else                         count<=count-1;
    1 d+ M1 ~6 D5 i* R/ K4 F& ^22           $ w9 W! U" R. b0 `# ]5 L: W
    23           always@(posedge clk or negedge clr)
    " @+ k7 o# _9 T0 J1 Q24           if(!clr)                     pos_clk<=0;
    3 I3 a2 O0 e4 T7 W# R8 G! _6 H25           else if(count==0)            pos_clk<=~pos_clk;, f* t& {1 P) e2 W& o9 g: ?
    26           else                         pos_clk<=pos_clk;
    + s$ g. h, l5 a6 u6 A  X27           
    4 k" h& [0 P/ P9 d+ b, X# C* Y28           always@(negedge clk or negedge clr)
    : F) P+ V8 ~, f+ O7 B29           if(!clr)                     neg_clk<=0;
    7 T7 ]/ d/ r3 Z, t6 e4 f3 d30           else                         neg_clk<=pos_clk;; ]$ d8 F5 N4 ^* D, t8 Q" E! X
    31           2 i* V& j. j+ @8 [
    32           assign Div_clk = pos_clk & neg_clk;          " d7 ]# D+ R# B
    33      end5 Z9 f$ y  K) X3 _3 {+ O0 S7 O
    34 + {1 h* s: t9 x% L0 s
    35 2:   begin  //ou_shu7 m8 w3 U- ^/ D8 S
    36           reg          Div_clk1;        * W2 K' F  O: x  `: Q3 G1 l
    37            
    ' o( e6 `3 f- O& b3 N& m38           always@(posedge clk or negedge clr)                  
    " M. g1 |% U; }) Y$ Q, b# s39           if(!clr)                     count<=0;                        
    9 z6 R1 j2 u( ~( W; Q6 p40           else if(count==0)            count<=Div_num/2-1;       $ L$ ]& k' I6 v+ p' }1 v( a; \
    41           else                         count<=count-1;
    " C5 b; \$ I$ D" Y$ \0 w42
    % i1 ?; V3 |4 O; R0 `; `7 ~' L43           always@(posedge clk or negedge clr)                  , }1 s) b* o: A
    44           if(!clr)                     Div_clk1<=0;                        0 F# W+ v0 g% m& j$ r
    45           else if(count==0)            Div_clk1<=~Div_clk1;   
    ; W5 A1 ~/ I  p" U9 S46               . C, Q8 u  J6 ~" R  ~3 Z) r' G
    47           assign Div_clk = Div_clk1; + X! H7 d2 `' e2 ~
    48      end  
    - W5 G7 e4 \! v1 F$ e" r49           
    4 M/ W, i% w, ?2 H% d, N2 e  C2 ~50           / A& T! g. h6 x" m6 M( N
    51 0:   begin   //ban_fen_pin  N" m; E5 Q6 w5 J/ Y! i7 A; D
    52           reg         count_div;. X0 I: V+ N1 a( E5 a, F
    53           reg         count_div2; , e- l4 W+ }+ M
    54           wire        clk_half;
    % c3 Y0 P2 ^7 u2 }3 S# ?7 R55           
    ; L: T: h' N* [/ c" O6 C+ p56           assign  clk_half = clk^count_div2;& k/ y% L- H1 k
    57           always@(posedge clk_half or negedge clr)   //模Div_num 计数            
    4 [. e/ ~3 p/ n: H% @( y+ x58           if(!clr)                       count<=0;               
    % ~- k' R" I8 Z* k* b: Q; Y6 A7 o/ \59           else if(count== Div_num-1)      count<=0;         
    3 m. Y  L6 O' y60           else                         count<=count+1; 1 K. B( S8 `9 [  x  b' x- H4 q3 i
    61  ! h8 |7 m5 i+ a1 r$ G% j7 |  S2 B, Y
    62           always@(posedge clk_half or negedge clr)   //模Div_num 计数            " {; _% Z& g4 n" ]6 H& X
    63           if(!clr)                       count_div<=0;               $ l, z; D, s# Y1 w. G! u
    64           else if(count== Div_num-1)      count_div<=1;         
    : b( H2 ]- @3 c4 P65           else                         count_div<=0;  
    4 y% V* @9 @% D66           
    : c% e. }1 G2 \: A67           always@(posedge count_div or negedge clr)   //对count_div二分频            $ h: c8 {7 I  D4 ^
    68           if(!clr)                       count_div2<=0;                : W7 k8 e1 V; M" B9 u
    69           else                         count_div2<=~count_div2;  
    & m/ N2 q  G& n1 {' q70         . ?' N' m2 k( N; @; V
    71           assign Div_clk = count_div;
    9 t  ?' t) w) v* s/ y" ?" Y( q% `72      end
    7 y/ f! X- V" d' g3 ]* B2 ^4 X73 endcase    " r$ {' z+ V; }. Y8 }' s6 s
    74 1 ]* z* Q& V9 P$ ^1 T
    75 endmodule! Y: D! k8 k6 P/ N8 _' k  }, s
    复制代码/ x, r; k( \: i$ _7 `/ V* {
    五:仿真代码及结果
    $ G9 }/ _1 [8 m9 s% {& l; M9 ]
    0 J0 Q4 o! c! N1 N复制代码
    ( O: z3 s* C- }1 module test_divf;$ r. A3 @  Q8 R( A0 T
    2 reg clk;0 i2 Z. ^  n/ N8 l( w% _& N& t
    3 reg clr;% [) |& G1 h( K9 C% ~
    4 wire Div_clk;
    4 H6 K' r5 o# p: V) _- s9 ^, o5
    & x. r3 f7 b9 C* Y, R" S5 y6 always #1 clk=~clk;  h( O: R2 t6 G; @7 Q6 V9 g
    7
    ; @  j$ p* C7 y' O; @8 r8 initial
      d  y* v% K" L3 A0 E9 begin- }0 s5 h) P/ s7 b
    10  #0 clr=0;clk=1;5 k7 Z- @& P; Y# p  A9 Y
    11  #99 clr=1;
    + h8 F" r" z3 J; C- M12  //#1000 $stop;
    ) {+ w- L1 R* f13 end
    * r  z0 Q) \' `( c- z6 ~2 m: \14 ( ~* E* @7 D% m# I
    15 divf #
    - Q, u" ?6 j  H1 `4 p" o) K16 (7 q! `5 z8 O& L% D4 E
    17    .Div_num    (          5            ),
    8 w/ c7 e. T1 A  M) w$ N+ O" m18    .state      (          1            )
    0 y. D2 K6 X0 W; i5 `& J19 )divf(+ {. `2 q) N$ N1 k5 G( i
    20    .clr        (         clr           ),
    + p: S" _$ c" b) J21    .clk        (         clk           ),% b, ?6 S4 K1 {1 f# w; h
    22    .Div_clk    (        Div_clk        )
    2 c$ M# H7 I, @  ]23 );  + \; |( m) c3 M+ c; n2 D7 ^2 p6 z
    24                                                           ) Y1 V  ]1 q! Y6 N1 H* B
    25 endmodule   

    ; W& T  H; {5 l+ g8 f* c# k
    " j3 q5 o% p5 K) Z9 C( Z% z+ M
    / y3 A+ P2 j8 V2 r4 K5 o# g( t2 B3 o2 `) n
    - c- `9 @6 [+ K1 T8 y
      s- A# u! T$ ~7 X! O: Z5 \" Y2 A  j
    2 |8 I4 M$ }$ s% K
    " V8 v' N8 }% S/ \8 q* D/ i
    # a) K6 ]+ ?4 y1 F. U
    % c  {: b. l" O1 g7 o3 k( }
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

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

    EDA365公众号

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

    GMT+8, 2025-7-23 13:49 , Processed in 0.140625 second(s), 23 queries , Gzip On.

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

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

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