专栏首页FPGA开源工作室Verilog实现偶数、奇数、半整数、分数(小数)分频,画电路图用D触发器实现分频

Verilog实现偶数、奇数、半整数、分数(小数)分频,画电路图用D触发器实现分频

通常我们说对原时钟进行N分频,即分频后的时钟的一个周期是原时钟周期的N倍。N可以为偶数、奇数、半整数、分数(小数)。

1.偶数分频

Verilog:N为偶数,使用一个计数器循环0-(N-1)进行计数,在N/2-1与N-1分别将输出取反,即完成了N分频。

若果采用D触发器画出分频器,单个D触发器的反向输出到输入就构成了一个简单的2分频器,以此为基础,其分频输出作为下一级D触发器的时钟,如此串联起来,x个串联就是2^x分频,属于偶数分频,如图1[1].

图1 用D触发器分频

2.奇数分频

Verilog:N为奇数,使用一个计数器循环0-(N-1)进行计数,控制(N-1)/2个高电平,(N+1)/2个低电平,称为A;然后将此A电平信号延迟半个时钟周期称为B,最后输出C = A|B,即为占空比为50%的奇数分频器。另一种方案是(N+1)/2个高电平,(N-1)/2个低电平,那么最后输出C=A&B。

以C = A|B为例,将A延时半个时钟周期的方法有2种,方法1是直接使用下降沿的锁存器对A锁存得到B,方法2得到B的原理与A相同,不过是在下降沿检测(假设A是上升沿检测)。

图2 奇数分频波形

采用D触发器的话,采用方法1,用一个下降沿的D触发器锁存A=clkp1得到信号B=clkn1,把信号A和信号B做逻辑“与”就得到了占空比50%的分频时钟信号clkout[1]。

图3奇数分频

下面给出N为正整数的分频器设计,主要原理是N[0]=1为奇数分频,0为偶数分频。

module practice_demo(
    input clk,
    input arst,
    
    output clk_div
    );   
parameter N = 5;
reg [2:0] cnt;
reg clk_a;
reg clk_b;
wire clk_c;
 
always@(posedge clk or posedge arst)
begin
    if(arst)
        cnt <= 0;
    else if(cnt == N-1)
        cnt <= 0;
    else
        cnt <= cnt + 1;    
end
 
always@(posedge clk or posedge arst)
begin
    if(arst)
        clk_a<= 0;
    else if(cnt == (N-1)/2 || cnt == N-1)
        clk_a<= ~clk_a;
    else
        clk_a<= clk_a;    
end
 
/*****************方法1**********************/
always@(negedge clk or posedge arst)
begin
    if(arst)
        clk_b <= 0;
    else 
        clk_b <= clk_a;
end
/******************方法2********************/
//always@(negedge clk or posedge arst)
//begin
//    if(arst)
//        clk_b<= 0;
//    else if(cnt == (N-1)/2 || cnt == N-1)
//        clk_b<= ~clk_b;
//    else
//        clk_b<= clk_b;    
//end
/*********************************************/
 
assign clk_c = clk_a | clk_b;
//N[0]=1奇数,否则偶数
assign clk_div = N[0] ? clk_c : clk_a;
 
endmodule

3 半整数分频

说明:占空比非50%

网上广为流传的一种分频结果是,半分频多出来那半个周期为高电平,其余为低电平。例如N=5.5,以原时钟的一半为单位,可以分频输出1高10低。原理是用计数器循环计数0-10即11个周期,控制输出X前6周期高电平,后5周期低电平,然后再使用计数器得到一个下降沿触发的5低6高的输出Y,最后输出Z = X&Y。

图4半整数分频的波形

给出Verilog设计:

module for_practice(
input clk,
input arst,
output  clk_div         
    );
parameter N = 5;//5.5分频
reg[31:0]cnt1;
reg clkx;
reg clky;
always@(posedge clk or posedge arst)
begin
    if(arst)
        cnt1 <= 0;
    else if(cnt1 == 2*N)
        cnt1 <= 0;
    else
        cnt1 <= cnt1+ 1;          
end
 
always@(posedge clk or posedge arst)
begin
    if(arst)
        clkx <= 0;
    else if(cnt1 == 2*N)//////
        clkx <= 1;
    else if(cnt1 == N)///////
        clkx <= 0;          
end
 
always@(negedge clk or posedge arst)
begin
    if(arst)
        clky <= 0;
    else if(cnt1 == 0)///////
        clky <= 0;
    else if(cnt1 == N)//////
        clky <= 1;          
end
 
assign clk_div =  clkx & clky;
 
endmodule 

另外一种做法是想得到接近50%的占空比,例如5分频得到3个高电平,2.5个低电平,其思路是控制clk,使得计数器值等于某一值只保持半个周期。参考[3]

4分数(小数)分频

此部分主要参考[1][2].

说明:占空比非50%

比如8.7分频。因为没办法用计数器表示0.7这种数字,所以就用一个等效的概念来进行8.7分频,原时钟87个周期的总时间等于分频后的时钟10个周期的总时间;

先做3次8分频得到时钟周期数是24,再做7次9(8加1)分频得到时钟周期数63,总共就87个时钟周期;在这87个时钟周期里面分频时钟跳变20次总共10个周期。分数分频器的原理可以用下图来概括。

图5分数分频的原理

用整数部分zn(=8)作为一个分频系数,zn加1(=9)作为另外一个分频系数组成一个小数分频器。

根据上面的原理可以列出下面的二元一次方程组

zn*N+(zn+1)*M=87 ……(1)

N+M=10 ……(2)

可以解出N和M的值分别是3和7。

ACC计数器设计,在这里ZN=8:

ACC计数器就是控制做N次ZN分频和M次ZN+1次分频,具体控制过程可以分为以下几种情况:

第1种情况 :先做N次ZN分频,再做M次ZN+1次分频;

第2种情况:先做M次ZN+1次分频,再做N次ZN分频;

第3种情况 :把N次ZN分频平均插入到M次ZN+1分频中;

第4种情况 :把M次ZN+1次分频平均插入到N次ZN分频中。

组合N次ZN分频和M次ZN+1次分频的情况很多。第1、2种情况前后时钟频率不太均匀,因此相位抖动比较大;

第3、4种情况前后时钟频率均匀性稍好,因此相位抖动会减小,因此最终采用3或4。如图6

图6分数分频的几种控制过程

具体Verilog设计请参考[2].

作者:king阿金

原文链接:

https://blog.csdn.net/qq_34070723/article/details/100731708

本文分享自微信公众号 - FPGA开源工作室(leezym0317),作者:king阿金

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-03-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Vivado约束学习】 时钟约束

    在数字设计中,时钟代表从寄存器(register)到寄存器可靠传输数据的时间基准。Xilinx Vivado集成设计环境(IDE)时序引擎使用ClocK特征计算...

    FPGA开源工作室
  • 【vivado约束学习三】 时钟网络分析

    B,Tcl命令:report_clock_networks -name {network_1}

    FPGA开源工作室
  • 【vivado约束学习四】跨时钟域路径分析

    A, Reports > Timing > Report Clock Interaction

    FPGA开源工作室
  • 通过Jenkins发布php代码

    我们都知道Jenkins是一个用于持续集成的工具,所以本文简单介绍一下如何通过Jenkins来发布php代码到远程的机器上,实验环境如下: 两台机器,一台安装了...

    端碗吹水
  • Windows Mobile上的小宇宙

      在codeproject上看到了一个非常有意思的应用,windows mobile上看星座图。试想下面一个场景,在北京寒冷冬天的一个晚上,西北风把城市上空的...

    ShiJiong
  • Java 水题系列(3)回文素数

    思路:从2开始枚举,然后先判断素数再判断回文数,判断素数用经典的根号算法就够了,之后回文数的判断就是将数字转字符串、将其反转判断是不是和原来相等,找100个这样...

    glm233
  • 论文想法跟别人撞车了,我还要不要继续?

    最近,一位硕士研究生在 reddit 上发帖提问:论文想法撞车之后到底要不要放弃?以下是原帖摘要:

    机器之心
  • 一个很low的问题,forEach怎么跳出循环?

    本文作者:IMWeb 黄龙 原文出处:IMWeb社区 未经同意,禁止转载 方法一: try catch const arr = [0, 1, 2, 3...

    IMWeb前端团队
  • 一个很low的问题,forEach怎么跳出循环?

    代码偷自https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Obj...

    IMWeb前端团队
  • 一起挖矿病毒事件的深度分析

    有了攻击脚本的话,我们就能更加快速的了解他的攻击方式了,所以让我们来分析下脚本到底干了些什么:

    FB客服

扫码关注云+社区

领取腾讯云代金券