分频器是指使输出信号频率为输入信号频率整数分之一的电子电路。在许多电子设备中如电子钟、频率合成器等,需要各种不同频率的信号协同工作,常用的方法是以稳定度高的晶体振荡器为主振源,通过变换得到所需要的各种频率成分,分频器是一种主要变换手段。
    早期的分频器多为正弦分频器,随着数字集成电路的发展,脉冲分频器(又称数字分频器)逐渐取代了正弦分频器。

下面以Verilog HDL 语言为基础介绍占空比为50%的分频器。

1、偶分频

  偶分频电路指的是分频系数为 2、4、6、8 ... 等偶数整数的分频电路,我们可以直接进行分频。
   例如下面 divider.v 中,对输入时钟进行6分频,即假设clk 为 50MHz ,分频后的时钟频率为 (50/6) MHz。程序如下:

设计代码:

 //rtl
module divider(
clk,
rst_n,
clk_div
);
input clk;
input rst_n;
output clk_div;
reg clk_div; parameter NUM_DIV = ;
reg [:] cnt; always @(posedge clk or negedge rst_n)
if(!rst_n) begin
cnt <= 'd0;
clk_div <= 'b0;
end
else if(cnt < NUM_DIV / - ) begin
cnt <= cnt + 'b1;
clk_div <= clk_div;
end
else begin
cnt <= 'd0;
clk_div <= ~clk_div;
end
endmodule

仿真程序:

 //tb
module divider_tb();
reg clk;
reg rst_n;
wire clk_div;
parameter DELY=;
divider U_divider(
.clk (clk ),
.rst_n (rst_n ),
.clk_div(clk_div)
);
always #(DELY/) clk=~clk;//产生时钟波形
initial begin
$fsdbDumpfile("divider_even.fsdb");
$fsdbDumpvars(,U_divider);
end
initial begin
clk=;rst_n=;
#DELY rst_n=;
#((DELY*)) $finish;
end
endmodule

可以看到,clk的上升沿,采样到cnt=2的时候,就翻转,采样到0和1的时候,保持。这样就可以做到一半高电平,一半低电平。

2、奇分频
  由于奇分频需要保持分频后的时钟占空比为 50% ,所以不能像偶分频那样直接在分频系数的一半时使时钟信号翻转(高电平一半,低电平一半)。
    在此我们需要利用输入时钟上升沿和下降沿来进行设计。
      接下来我们设计一个 5 分频的模块,设计思路如下:
     采用计数器 cnt1 进行计数,在时钟上升沿进行加 1 操作,计数器的值为 0、1 时,输出时钟信号 clk_div 为高电平;计数器的值为2、3、4 时,输出时钟信号 clk_div 为低电平,计数到 5 时清零,从头开始计数。我们可以得到占空比为 40% 的波形 clk_div1。
       采用计数器 cnt2进行计数,在时钟下降沿进行加 1 操作,计数器的值为 0、1 时,输出时钟信号 clk_div 为高电平;计数器的值为2、3、4 时,输出时钟信号 clk_div 为低电平,计数到 5 时清零,从头开始计数。我们可以得到占空比为 40% 的波形 clk_div2。
       clk_div1 和clk_div2 的上升沿到来时间相差半个输入周期,所以将这两个信号进行或操作,即可得到占空比为 50% 的5分频时钟。程序如下:
设计代码:
 //rtl
module divider(
clk,
rst_n,
clk_div
);
input clk;
input rst_n;
output clk_div;
reg clk_div; parameter NUM_DIV = ;
reg[:] cnt1;
reg[:] cnt2;
reg clk_div1, clk_div2; always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt1 <= ;
else if(cnt1 < NUM_DIV - )
cnt1 <= cnt1 + 'b1;
else
cnt1 <= ; always @(posedge clk or negedge rst_n)
if(!rst_n)
clk_div1 <= 'b1;
else if(cnt1 < NUM_DIV / )
clk_div1 <= 'b1;
else
clk_div1 <= 'b0; always @(negedge clk or negedge rst_n)
if(!rst_n)
cnt2 <= ;
else if(cnt2 < NUM_DIV - )
cnt2 <= cnt2 + 'b1;
else
cnt2 <= ; always @(negedge clk or negedge rst_n)
if(!rst_n)
clk_div2 <= 'b1;
else if(cnt2 < NUM_DIV / )
clk_div2 <= 'b1;
else
clk_div2 <= 'b0; assign clk_div = clk_div1 | clk_div2;
endmodule

仿真代码:

 //tb
module divider_tb();
reg clk;
reg rst_n;
wire clk_div;
parameter DELY=;
divider U_divider(
.clk (clk ),
.rst_n (rst_n ),
.clk_div(clk_div)
);
always #(DELY/) clk=~clk;//产生时钟波形
initial begin
$fsdbDumpfile("divider_odd.fsdb");
$fsdbDumpvars(,U_divider);
end
initial begin
clk=;rst_n=;
#DELY rst_n=;
#((DELY*)) $finish;
end
endmodule

对其进行测试和验证(此仿真波形是三分频,占空比50%),即上述程序吧NUM_DIV改成3即可,得到如下波形:

3.任意占空比的任意分频

在verilog程序设计中,我们往往要对一个频率进行任意分频,而且占空比也有一定的要求这样的话,对于程序有一定的要求。
  现在在前面两个实验的基础上做一个简单的总结,实现对一个频率的任意占空比的任意分频。
  比如: FPGA系统时钟是50M Hz,而我们要产生的频率是880Hz,那么,我们需要对系统时钟进行分频。很容易想到用计数的方式来分频:50000000/880 = 56818。
  显然这个数字不是2的整幂次方,那么我们可以设定一个参数,让它到56818的时候重新计数就可以实现了。程序如下:

设计代码:

 //rtl
module div(
clk,
rst_n,
clk_div
);
input clk,rst_n;
output clk_div;
reg clk_div; reg [:] counter; always @(posedge clk or negedge rst_n)
if(!rst_n)
counter <= ;
else if(counter==)
counter <= ;
else
counter <= counter+; assign clk_div = counter[];
endmodule

仿真代码:

 //tb
module div_tb();
reg clk;
reg rst_n;
wire clk_div;
parameter DELY=;
div U_div(
.clk (clk ),
.rst_n (rst_n),
.clk_div(clk_div)
);
always #(DELY/) clk=~clk;//产生时钟波形
initial begin
$fsdbDumpfile("div_any.fsdb");
$fsdbDumpvars(,U_div);
end
initial begin
clk=;rst_n=;
#DELY rst_n=;
#((DELY*)) $finish;
end
endmodule

分频的应用很广泛,一般的做法是先用高频时钟计数,然后使用计数器的某一位输出作为工作时钟进行其他的逻辑设计,上面的程序就是一个体现。
  下面我们来算一下它的占空比:
  我们清楚地知道,这个输出波形在counter为0到32767(2的14次方)的时候为低,在32768到56817的时候为高,占空比为40%多一些,
  如果我们需要占空比为50%,那么我们需要再设定一个参数,使它为56817的一半,使达到它的时候波形翻转,就可以实现结果了。
  程序如下:28408=56818/2-1,计数到28408就清零,翻转,其余的计数期间,保持不变。

设计代码:

 //rtl
module div(
clk,
rst_n,
clk_div
);
input clk,rst_n;
output clk_div;
reg clk_div;
reg [:] counter;
always @(posedge clk or negedge rst_n)
if(!rst_n)
counter <= ;
else if(counter==)
counter <= ;
else
counter <= counter+; always @(posedge clk or negedge rst_n)
if(!rst_n)
clk_div <= ;
else if(counter==)
clk_div <= ~clk_div;
endmodule

仿真代码:

 //tb
module div_tb();
reg clk;
reg rst_n=;
wire clk_div;
parameter DELY=;
div U_div(
.clk (clk ),
.rst_n (rst_n),
.clk_div(clk_div)
);
always #(DELY/) clk=~clk;//产生时钟波形
initial begin
$fsdbDumpfile("div_any.fsdb");
$fsdbDumpvars(,U_div);
end
initial begin
clk=;rst_n=;
#DELY rst_n=;
#((DELY*)) $finish;
end
endmodule
继续让我们来看如何实现任意占空比,比如还是由50M分频产生880Hz,而分频得到的信号的占空比为30%。
56818×30%=17045
设计代码:
 //rtl
module div(
clk,
rst_n,
clk_div,
counter
);
input clk,rst_n;
output clk_div;
reg clk_div;
output [:] counter;
reg [:] counter; always @(posedge clk)
if(!rst_n)
counter <= ;
else if(counter==)
counter <= ;
else counter <= counter+; always @(posedge clk)
if(!rst_n)
clk_div <= ;
else if(counter<)
clk_div <= ;
else
clk_div <= ;
endmodule

仿真代码:

 //tb
module div_tb();
reg clk;
reg rst_n;
wire clk_div;
wire [:] counter;
parameter DELY=;
div U_div(
.clk (clk ),
.rst_n (rst_n ),
.counter(counter),
.clk_div(clk_div)
);
always #(DELY/) clk=~clk;//产生时钟波形
initial begin
$fsdbDumpfile("div_any.fsdb");
$fsdbDumpvars(,U_div);
end
initial begin
clk=;rst_n=;
#DELY rst_n=;
#((DELY*)) $finish;
end
endmodule
4 小结
 通过以上几个例子对比不难发现,借助计数器来实现任意点空比的任意分频的方法简单,且用verilog语言进行行为描述时,代码简洁、易懂、通用。
 通过以上的学习,对分频器有了比较深刻的认识,将在以后的学习中会有广泛的应用。

原出处:https://www.chipist.cn/article/166  如有什么疑问,欢迎讨论:QQ:447574829

Verilog设计分频器(面试必看)的更多相关文章

  1. 面试必看!靠着这份字节和腾讯的面经,我成功拿下了offer!

    准备 敲定了方向和目标后就开始系统准备,主要分为以下几个方面来准备. 算法题 事先已经看过别人的社招面经知道头条每轮技术面都有算法题,而这一块平时练习的比较少,校招时刷的题也忘记了很多.因此系统复习的 ...

  2. linux c++ 服务器端开发面试必看书籍

    摘自别人博客,地址:http://blog.csdn.net/qianggezhishen/article/details/45951095 打算从这开始一本一本开始看 题外话: 推荐一个 githu ...

  3. 面试必看!凭借着这份 MySQL 高频面试题,我拿到了京东,字节的offer!

    前言 本文主要受众为开发人员,所以不涉及到MySQL的服务部署等操作,且内容较多,大家准备好耐心和瓜子矿泉水. 前一阵系统的学习了一下MySQL,也有一些实际操作经验,偶然看到一篇和MySQL相关的面 ...

  4. iOS面试必看

    转载:http://www.jianshu.com/p/5d2163640e26 序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了.今年,找过工作人可能会更深刻地体会到今年的就业形 ...

  5. iOS面试必看,最全梳理

    序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了.今年,找过工作人可能会更深刻地体会到今年的就业形势不容乐观,加之,培训机构一火车地向用人单位输送iOS开发人员,打破了生态圈的动态 ...

  6. iOS,面试必看,最全梳理

    序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了.今年,找过工作人可能会更深刻地体会到今年的就业形势不容乐观,加之,培训机构一火车地向用人单位输送iOS开发人员,打破了生态圈的动态 ...

  7. iOS面试必看经典试题分析

    > **不用临时变量怎么实现两个数据的交换?** 方式一:加减法的运算方式求解new_b = a - b + b = a;new_a = a + b - a = b;一个简单的运算方式,最重要的 ...

  8. 百度搜索 “Java面试题” 前200页(面试必看)

    前言 本文中的题目来源于网上的一篇文章<百度搜索 "Java面试题" 前200页>,但该文章里面只有题目,没有答案.因此,我整理了一些答案发布于本文.本文整理答案的原则 ...

  9. iOS - 基础知识总结(OC版) 面试必看 再不看就要用swift了

    OC的理解与特性 OC作为一门面向对象的语言,自然具有面向对象的语言特性:封装.继承.多态.它既具有静态语言的特性(如C++),又有动态语言的效率(动态绑定.动态加载等).总体来讲,OC确实是一门不错 ...

随机推荐

  1. iOS内购流程一(协议、税务和银行业务)

    协议.税务和银行业务,这一选项是当你App使用了In-app purchaes时候,你跟苹果签订协议的,需要签订合同和填写你的银行收款等信息 一.填写法人信息 1.登录iTunes Store,点击协 ...

  2. 51nod1110(xjb)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1110 题意:中文题诶- 思路:可以将在 xi 位置,权值为 w ...

  3. python 之 序列化与反序列化、os模块

    6.6 序列化与反序列化 特殊的字符串 , 只有:int / str / list / dict 最外层必须是列表或字典,如果包含字符串,必须是双引号"". 序列化:将Python ...

  4. SpringBoot2.0 基础案例(08):集成Redis数据库,实现缓存管理

    一.Redis简介 Spring Boot中除了对常用的关系型数据库提供了优秀的自动化支持之外,对于很多NoSQL数据库一样提供了自动化配置的支持,包括:Redis, MongoDB, Elastic ...

  5. Luogu P3065 [USACO12DEC]第一!First!【字典树/拓扑排序】By cellur925

    题意:给你许多字符串,你可以改变字母序大小,问有哪些字符串可能成为字典序最小的字符串. 我们考虑把这些字符串都塞到\(trie\)树上.之后检索每一个字符串的时候,我们看和他同一层的地方是否有字符,如 ...

  6. js new Date("2016-07-01 08:00:00") 格式在IE内核浏览器中显示NaN的问题

    js new Date("2016-07-01 08:00:00") 格式在IE内核浏览器中显示NaN的问题 废话就不多了,var dd = new Date("2016 ...

  7. Java基础笔记(一)——JDK、JRE、JVM

    JDK.JRE和JVM三者的关系 Java程序执行过程 JVM(java virtual machine) 注:由于各种操作系统(windows.linux等)支持的指令集(二进制可执行代码)不同,程 ...

  8. [题解](同余)POJ_3696_The Luckiest Number

    还是挺难的吧......勉强看懂调了半天 首先表达式可以写成 8(10^x -1)/9,题意为求一个最小的x使L | 8(10^x -1)/9 设d=gcd(L,8) L | 8(10^x -1)/9 ...

  9. Swing 100行画图示例

    关键内容,可以自行扩展 package main; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt ...

  10. Python web前端 11 form 和 ajax

    Python web前端 11 form 和 ajax 一.打开服务器 将handlers.py.httpd.py和libs.py三个文件放入新文件夹中,双击打开httpd.py文件即可 二.ajax ...