verilog任意小数分频的实现

原理

假设19/9分频,利用公式

(19/9) * (a+b)=2a+3b
===>
a=8
b=1

即可以由8个2分频+1个3分频,在8*2+1*3=19个参考时钟周期内,实现19/9分频。
优点是算法简单。
缺点是占空比不是50%,因为2分频和3分频交叉组合而成,所以周期性抖动较差。

总之,用于普通的数字逻辑实现基于频率的带宽精细微调,还是很有用处的。

波形

这里写图片描述

module代码

分频系数=分子/分母。

module clkFracDiv(
                  output reg   clkout,
                  input        rstn,
                  input        refclk,
                  input [31:0] fenzi,//fenzi/fenmu must equal or more than 2
                  input [31:0] fenmu //fenzi/fenmu must equal or more than 2
);
   reg [2:0]                   rstn_syn;
   reg [31:0]                  cnt;

   //1. reset synchronization;
   //2. indicate that refclk is already stable
   always @(posedge refclk) begin
      rstn_syn[0] <= rstn;
      rstn_syn[1] <= rstn_syn[0];
      rstn_syn[2] <= rstn_syn[1];
   end

   //1. main algorithm
   always @(posedge refclk or negedge rstn_syn[2]) begin
      if(!rstn_syn[2]) cnt <= 0;
      else begin
         if(cnt < fenzi) cnt <= cnt + fenmu;
         else cnt <= cnt + fenmu - fenzi;
      end
   end

   //1. base the above algorithm, deduce clkout
   always @(posedge refclk or negedge rstn_syn[2]) begin
      if(!rstn_syn[2]) clkout <= 0;
      else begin
         if(((cnt > (fenzi>>1)) || (cnt == (fenzi>>1))) && (cnt < fenzi)) clkout <= 1;
         else clkout <= 0;
      end
   end
endmodule

testbench代码

`timescale 1ns/10ps
module tb_top;
   reg refclk;
   initial begin
      refclk = 0;
   end
   always #0.2 refclk = !refclk;

   reg rstn;
   initial begin
      rstn = 0;
      #100;
      rstn = 1;
   end

   reg [31:0] fenzi;
   reg [31:0] fenmu;
   reg        enable_clkFracDiv;
   initial begin
      fenzi=32'd19;
      fenmu=32'd9;
      enable_clkFracDiv=0;
      #200;
      enable_clkFracDiv=1;
   end

   clkFracDiv clkFracDiv(
                         /*output reg   */.clkout (clkout),
                         /*input        */.rstn   (rstn && enable_clkFracDiv ),
                         /*input        */.refclk (refclk),
                         /*input [31:0] */.fenzi  (fenzi ),//fenzi/fenmu must equal or more than 2
                         /*input [31:0] */.fenmu  (fenmu ) //fenzi/fenmu must equal or more than 2
                         );
endmodule

算法解析

主要算法,在clkFracDiv.v的第二段实现代码里。
第三段实现代码,只是基于这个算法推演clkout波形而已。

基于实例说明,19/9分频。换个说法,即19个参考时钟refclk里,划分9段。
因为分母是9,所以计数器是+9计算的,如果超过19,意味着当前两个上升沿之间的周期大于期望周期值,余数需要考虑进下一个周期里。总共需要的周期数,就是前文的8*2+1*3=19个参考时钟周期内。

理论上,只要分频系数大于或者等于2的各种整数分频、小数分频,都是可以的。

参考文档

32任意分数分频Verilog实现
http://3y.uu456.com/bp-4ecb3facd1f346q3daef3e2e-1.html

  • 6
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值