微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 最近小作:Verilog版的dpll

最近小作:Verilog版的dpll

时间:10-02 整理:3721RD 点击:
大家好,经过断断续续的努力,我得Verilog版的数字锁相环终于初步有了结果。这个锁相环纯粹是我的个人爱好。大概一个月前,我曾与小编讨论过这个问题,小编也给大家发了一篇这方面的文章。之后,经过查阅资料,我弄明白锁相工作的原理。接着,动手写自己的锁相环。写程序并没有用去多少时间,但是为了排除那些 的错误,却用了大量的时间。还好,总算看到了结果。
曾经答应小编做完了就给他发一份,现在,还是公开发给大家吧。由于时间及经验的原因,这个只能锁相的环可能还不够专业,但我希望对锁相环感兴趣的朋友们能一起来研究它,大家一起分享自己劳动成果,使它更加完善,谢谢。
上面是这个dpll的原理图:

最近小作:Verilog版的dpll
异或门鉴相器就是一个异或门。
K可变模计数器的源代码如下:
module KCounter(rst,clk,ud,Kmode,INC_plus,DEC_plus);
       input rst,clk,ud;
   input [2:0] Kmode;
   output INC_plus,DEC_plus;
   reg [8:0] CounterINC,CounterDEC;
   reg [8:0] Kvalue;
       //K±äÄ£
   always@(Kmode)
   begin
   case(Kmode)
   3'b001:Kvalue<=9'b000000111;
       3'b010:Kvalue<=9'b000001111;
   3'b011:Kvalue<=9'b000011111;
   3'b100:Kvalue<=9'b000111111;
   3'b101:Kvalue<=9'b001111111;
   3'b110:Kvalue<=9'b011111111;
   3'b111:Kvalue<=9'b111111111;
   default:Kvalue<=9'b000001111;
   endcase
   end
      
   //&frac14;&AElig;&Ecirc;&yacute;&AElig;÷&micro;&Auml;&Iuml;&Acirc;&Ograve;&raquo;&cedil;&ouml;&Ecirc;&yacute;&Ouml;&micro;&pound;¨&frac14;&Oacute;1&raquo;ò&frac14;&otilde;1&pound;&copy;
   wire [8:0] INC_cnt,DEC_cnt;
   assign INC_cnt=CounterINC+1;
       assign DEC_cnt=CounterDEC-1;
      
   //&ETH;&Icirc;&sup3;&Eacute;&Ouml;&Atilde;&Icirc;&raquo;&ordm;&Iacute;&Ccedil;&aring;&Aacute;&atilde;&Acirc;&ouml;&sup3;&aring;&pound;¨&acute;&oslash;&Oacute;&ETH;&Atilde;&laquo;&acute;&Igrave;&pound;&copy;
   wire E_Kvalue,E_zero;
   assign E_Kvalue=(CounterINC==Kvalue)?1:0;
       assign E_zero=(CounterDEC==0)?1:0;
   wire C_set,C_clr;
   assign C_clr=E_Kvalue&~ud;
   assign C_set=E_zero&ud;
      
   //&ETH;&Icirc;&sup3;&Eacute;&Ouml;&Atilde;&Icirc;&raquo;&ordm;&Iacute;&Ccedil;&aring;&Aacute;&atilde;±ê&Ouml;&frac34;&pound;¨&Atilde;&raquo;&Oacute;&ETH;&Atilde;&laquo;&acute;&Igrave;&pound;&copy;
       reg clr_flag;
       reg set_flag;
   always@(posedge rst or negedge clk)
   begin
     if(rst)   clr_flag<=1'b0;
else      clr_flag<=C_clr;
   end
   always@(posedge rst or negedge clk)
   begin
     if(rst)   set_flag<=1'b0;
else      set_flag<=C_set;
   end
       //&Ograve;&Ocirc;&Iuml;&Acirc;&Ecirc;&Ccedil;&ETH;&Icirc;&sup3;&Eacute;&frac14;&Oacute;&frac14;&otilde;&Acirc;&ouml;&sup3;&aring;&micro;&Auml;&cedil;¨&Ouml;ú&micro;&ccedil;&Acirc;·&pound;&not;&Ecirc;&sup1;&AElig;&auml;&iquest;&Eacute;&Ograve;&Ocirc;±&pound;&sup3;&Ouml;3&cedil;&ouml;clk
   reg [2:0] INCshift,DECshift;
   always@(posedge rst or negedge clk)
   begin
     if(rst)   INCshift[2:0]<=3'b000;
else   begin
           INCshift[2]<=clr_flag;
                   INCshift[1]<=INCshift[2];
                   INCshift[0]<=INCshift[1];
end
   end
   always@(posedge rst or negedge clk)
   begin
     if(rst)   DECshift[2:0]<=3'b000;
else   begin
           DECshift[2]<=set_flag;
                   DECshift[1]<=DECshift[2];
                   DECshift[0]<=DECshift[1];
end
   end
       reg clrINC,clrDEC;
   always@(posedge rst or negedge clk)
   begin
     if(rst)   clrINC<=1'b0;
else      clrINC<=INCshift[0];
   end
   always@(posedge rst or negedge clk)
   begin
     if(rst)   clrDEC<=1'b0;
else      clrDEC<=DECshift[0];
   end
      //&Ograve;&Ocirc;&Iuml;&Acirc;&Ecirc;&Ccedil;&frac14;&Oacute;&Acirc;&ouml;&sup3;&aring;&ordm;&Iacute;&frac14;&otilde;&Acirc;&ouml;&sup3;&aring;&micro;&Auml;&ETH;&Icirc;&sup3;&Eacute;&pound;&not;&Euml;ü&Atilde;&Ccedil;±&pound;&sup3;&Ouml;4&cedil;&ouml;clk
   reg INC_plus,DEC_plus;
   always@(posedge rst or posedge set_flag or posedge clrDEC)
   begin
     if(rst)              DEC_plus<=1'b0;
else  if(set_flag)   DEC_plus<=1'b1;
else                 DEC_plus<=1'b0;
   end
   always@(posedge rst or posedge clr_flag or posedge clrINC)
   begin
     if(rst)              INC_plus<=1'b0;
else  if(clr_flag)   INC_plus<=1'b1;
else                 INC_plus<=1'b0;
   end
       ///&Ograve;&Ocirc;&Iuml;&Acirc;&Ecirc;&Ccedil;&Aacute;&frac12;&cedil;&ouml;&frac14;&AElig;&Ecirc;&yacute;&AElig;÷(&AElig;&auml;&Ecirc;&micro;&sup2;&raquo;&iquest;&Eacute;&Auml;&aelig;)
   wire INC,DEC;
   assign INC=~ud&clk;
   assign DEC=ud&clk;
   always@(posedge rst or negedge DEC or posedge set_flag)
   begin
     if(rst)                  CounterDEC<=9'b000000000;
else  if(set_flag)       CounterDEC<=Kvalue;
else                     CounterDEC<=DEC_cnt;
   end
   always@(posedge rst or negedge INC or posedge clr_flag)
   begin
     if(rst)                  CounterINC<=9'b000000000;
else  if(clr_flag)       CounterINC<=9'b000000001;
else                     CounterINC<=INC_cnt;
   end
endmodule

最近小作:Verilog版的dpll
加减脉冲计数器源代码如下:
module IDCnt(clk,rst,INC,DEC,serout);
    input clk,rst,INC,DEC;
output serout;
/////2·&Ouml;&AElig;&micro;&frac14;&AElig;&Ecirc;&yacute;&AElig;÷&pound;&not;&AElig;&auml;&Ecirc;&auml;&sup3;&ouml;&Ecirc;&Ccedil;&Iuml;à&sup2;&icirc;&Icirc;&ordf;pi&pound;&not;&Otilde;&frac14;&iquest;&Otilde;±&Egrave;&Icirc;&ordf;50&pound;&yen;&micro;&Auml;·&frac12;&sup2;¨
    reg div2;
wire cdiv2;
always@(posedge rst or negedge clk)
begin
   if(rst)  div2<=0;
   else     div2<=~div2;
end
assign cdiv2=~div2;
////INC&Oacute;&euml;DEC&micro;&Auml;±&szlig;&Ntilde;&Oslash;&frac14;ì&sup2;&acirc;
    reg [1:0] INC_det,DEC_det;
wire INC_edge,DEC_edge;
    wire  ser1,ser2;
assign ser1=div2&clk;
assign ser2=cdiv2&clk;
always@(posedge rst or negedge ser1)
begin
  if(rst)   INC_det[1]<=0;
  else      INC_det[1]<=INC;
end
always@(posedge rst or negedge ser1)
begin
  if(rst)   INC_det[0]<=0;
  else      INC_det[0]<=INC_det[1];
end
assign INC_edge=~INC_det[1]&INC_det[0];
always@(posedge rst or posedge ser2)
begin
  if(rst)   DEC_det[1]<=0;
  else      DEC_det[1]<=DEC;
end
always@(posedge rst or posedge ser2)
begin
  if(rst)   DEC_det[0]<=0;
  else      DEC_det[0]<=DEC_det[1];
end
assign DEC_edge=~DEC_det[1]&DEC_det[0];
//////&Ecirc;&auml;&sup3;&ouml;&micro;&Auml;&Ecirc;&yacute;&frac34;&Yacute;&Agrave;&acute;&Ocirc;&acute;&Oacute;&euml;×&acute;&Igrave;&not;
    reg INC_flag;
reg DEC_flag;
always@(posedge rst or negedge INC)
begin
if(rst)  INC_flag<=1'b0;
else     INC_flag<=~INC_flag;
end
always@(posedge rst or negedge DEC)
begin
if(rst)  DEC_flag<=1'b0;
else     DEC_flag<=~DEC_flag;
end
wire iddet;
//assign iddet=INC_edge|DEC_edge;
reg ioed;
always@(posedge rst or posedge INC_edge or posedge DEC_edge)
begin
if(rst)             ioed<=1'b0;
else if(INC_edge)   ioed<=1'b1;
else                ioed<=1'b0;
end
    wire detenable;
wire select;
assign select=(ioed&INC_flag&~DEC_flag)|(~ioed&~INC_flag&~DEC_flag)|(~ioed&INC_flag&DEC_flag)|(ioed&~INC_flag&DEC_flag);
assign detenable=select?cdiv2:div2;
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   ///////////
reg idedge1,idedge2;
always@(posedge rst or negedge clk)
begin
if(rst) idedge1<=1'b0;
else if(detenable)  idedge1<=INC_edge;
end
always@(posedge rst or negedge clk)
begin
if(rst) idedge2<=1'b0;
else if(detenable)  idedge2<=DEC_edge;
end
reg state;
always@(posedge rst or posedge idedge1 or posedge idedge2)
begin
  if(rst)                                     state<=1'b0;
  else if(idedge1)                            state<=~state;
  else                                        state<=~state;                  
      
end
////&Ecirc;&auml;&sup3;&ouml;&Ntilde;&iexcl;&Ocirc;&ntilde;
   assign serout=state?ser1:ser2;
endmodule

最近小作:Verilog版的dpll
8分频计数器很简单,采用异步即可,代码如下(图中标为4分频,该其为8分频):
module div4(rst,clk,out);
   input rst,clk;
   output  out;
   reg out;
   reg a,b;
   always@(posedge rst or negedge clk)
   begin
       if(rst)   a<=1'b0;
   else      a<=~a;
   end
   always@(posedge rst or negedge a)
   begin
       if(rst)   b<=1'b0;
   else      b<=~b;
   end
   always@(posedge rst or negedge b)
   begin
       if(rst)   out<=1'b0;
   else      out<=~out;
   end
endmodule
按照这个程序,clk的频率为datain的16倍不同步即可。

最近小作:Verilog版的dpll
好东西!
多谢你为大家做的贡献!

最近小作:Verilog版的dpll
从理论上来说,这个锁相环的占空比为7/16~9/16。
这种锁相环的优点是锁定速度快,缺点是只能锁相,不能锁频。

最近小作:Verilog版的dpll
小编,什么时候帮我加点威望阿
^_^,不错啊

最近小作:Verilog版的dpll
对了,还有顶层模块:
module dplltop(rst,clk,datain,Kmode,dataout);
  input rst,clk,datain;
  input [2:0] Kmode;
  output dataout;
  wire div4out,ud;
  assign ud=datain^div4out;
  
  wire incsin,decsin;
  KCounter KCounter1(.rst(rst),.clk(clk),.ud(ud),.Kmode(Kmode),.INC_plus(incsin),.DEC_plus(decsin));
  wire idout;
  IDCnt    IDCnt1(.clk(clk),.rst(rst),.INC(incsin),.DEC(decsin),.serout(idout));
  div4     div41(.rst(rst),.clk(idout),.out(div4out));
  assign dataout=div4out;
endmodule
整套软件我用的是FPGA Advantage5.4(正版的)综合仿真(前仿)都没有问题。
我希望有兴趣的朋友能做进一步的改进或完善,也希望大家把结果公布出来,共同提高。

最近小作:Verilog版的dpll
这个锁相环只能实现2倍频,即信号ud。

最近小作:Verilog版的dpll
up 一下

***** 小编模式 *****
<a href=topic.cgi?forum=20&topic=2>该贴子已被管理员转移,请点击这里查看</a>

BU  DING BUXINGAbu 不顶不行啊 PLL一直是我的瓶经

一般软件里都有相关ip

非常好的资料对初学者来说非常实用。顶一下

good! up!

正需要这个
谢谢了!

顶也要顶,不顶也要顶,哎

谢谢了
多点注释更好了

顶一下,大家都研究看看

小编辛苦,支持原创。

很好,顶!

切中要害!不过好人应该得到嘉奖,赞!

Support!

好人啊

也谢谢小编,如果有相关资料以及testbench,希望能够不吝赐教,可以发进我的个人信箱或者放在网上提供下载,非常感谢。
Email : navy.berry@gmail.com

非常感谢诸位的努力,我是做模拟电路的,但是现在需要使用FPGA,而其最近希望能够学学DPLL,不知哪位可以提供一些这方面的基本资料,我最近开始学了基本的verilog,仅仅皮毛而已,希望大家不吝赐教。我希望哪位能够传一些testench提供验证。非常感谢guanfree,粗粗一看,没有发现phadis的源代码,不知是否可以提供,如果合适,也希望您能提供相关的testbench以供借鉴,非常感谢。我的邮件地址 navy.berry@gmail.com

定啊。好人啊。!支持

好东西。

Thanks a lot!

好人啊,吾临电脑涕零,不知所言。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top