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

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

1、偶分频

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

设计代码:

 1 //rtl
 2 module divider(
 3     clk,
 4     rst_n,
 5     clk_div
 6 );
 7     input clk;
 8     input rst_n;
 9     output clk_div;
10     reg clk_div;
11
12     parameter NUM_DIV = 6;
13     reg    [3:0] cnt;
14
15 always @(posedge clk or negedge rst_n)
16     if(!rst_n) begin
17         cnt     <= 4'd0;
18         clk_div    <= 1'b0;
19     end
20     else if(cnt < NUM_DIV / 2 - 1) begin
21         cnt     <= cnt + 1'b1;
22         clk_div    <= clk_div;
23     end
24     else begin
25         cnt     <= 4'd0;
26         clk_div    <= ~clk_div;
27     end
28  endmodule

View Code

仿真程序:

 1 //tb
 2  module divider_tb();
 3     reg clk;
 4     reg rst_n;
 5     wire clk_div;
 6     parameter DELY=100;
 7 divider U_divider(
 8     .clk    (clk    ),
 9     .rst_n    (rst_n    ),
10     .clk_div(clk_div)
11 );
12     always #(DELY/2) clk=~clk;//产生时钟波形
13 initial begin
14     $fsdbDumpfile("divider_even.fsdb");
15     $fsdbDumpvars(0,U_divider);
16  end
17  initial begin
18           clk=0;rst_n=0;
19     #DELY rst_n=1;
20     #((DELY*20)) $finish;
21 end
22 endmodule 

View Code

可以看到,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分频时钟。程序如下:
设计代码:

 1 //rtl
 2 module divider(
 3     clk,
 4     rst_n,
 5     clk_div
 6 );
 7     input clk;
 8     input rst_n;
 9     output clk_div;
10     reg clk_div;
11
12     parameter NUM_DIV = 5;
13     reg[2:0] cnt1;
14     reg[2:0] cnt2;
15     reg    clk_div1, clk_div2;
16
17 always @(posedge clk or negedge rst_n)
18     if(!rst_n)
19         cnt1 <= 0;
20     else if(cnt1 < NUM_DIV - 1)
21         cnt1 <= cnt1 + 1'b1;
22     else
23         cnt1 <= 0;
24
25 always @(posedge clk or negedge rst_n)
26     if(!rst_n)
27         clk_div1 <= 1'b1;
28     else if(cnt1 < NUM_DIV / 2)
29         clk_div1 <= 1'b1;
30     else
31         clk_div1 <= 1'b0;
32
33 always @(negedge clk or negedge rst_n)
34     if(!rst_n)
35        cnt2 <= 0;
36     else if(cnt2 < NUM_DIV - 1)
37        cnt2 <= cnt2 + 1'b1;
38     else
39        cnt2 <= 0;
40
41 always @(negedge clk or negedge rst_n)
42     if(!rst_n)
43         clk_div2 <= 1'b1;
44     else if(cnt2 < NUM_DIV / 2)
45         clk_div2 <= 1'b1;
46     else
47         clk_div2 <= 1'b0;
48
49     assign clk_div = clk_div1 | clk_div2;
50 endmodule

View Code

仿真代码:

 1 //tb
 2 module divider_tb();
 3     reg clk;
 4     reg rst_n;
 5     wire clk_div;
 6     parameter DELY=100;
 7 divider U_divider(
 8     .clk    (clk    ),
 9     .rst_n    (rst_n    ),
10     .clk_div(clk_div)
11 );
12     always #(DELY/2) clk=~clk;//产生时钟波形
13 initial begin
14     $fsdbDumpfile("divider_odd.fsdb");
15     $fsdbDumpvars(0,U_divider);
16  end
17  initial begin
18           clk=0;rst_n=0;
19     #DELY rst_n=1;
20     #((DELY*20)) $finish;
21 end
22 endmodule

View Code

对其进行测试和验证,得到如下波形:

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

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

设计代码:

 1 //rtl
 2 module div(
 3     clk,
 4     rst_n,
 5     clk_div
 6 );
 7     input clk,rst_n;
 8     output clk_div;
 9     reg clk_div;
10
11     reg [15:0] counter;
12
13 always @(posedge clk or negedge rst_n)
14     if(!rst_n)
15         counter <= 0;
16     else if(counter==56817)
17         counter <= 0;
18     else
19         counter <= counter+1;
20
21    assign clk_div = counter[15];
22 endmodule

View Code

仿真代码:

 1 //tb
 2 module div_tb();
 3     reg clk;
 4     reg rst_n;
 5     wire clk_div;
 6     parameter DELY=100;
 7 div U_div(
 8     .clk    (clk    ),
 9     .rst_n  (rst_n),
10     .clk_div(clk_div)
11 );
12     always #(DELY/2) clk=~clk;//产生时钟波形
13 initial begin
14     $fsdbDumpfile("div_any.fsdb");
15     $fsdbDumpvars(0,U_div);
16  end
17  initial begin
18           clk=0;rst_n=0;
19     #DELY rst_n=1;
20     #((DELY*80000)) $finish;
21 end
22 endmodule

View Code

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

设计代码:

 1 //rtl
 2 module div(
 3     clk,
 4     rst_n,
 5     clk_div
 6 );
 7     input clk,rst_n;
 8     output clk_div;
 9     reg clk_div;
10     reg [14:0] counter;
11 always @(posedge clk or negedge rst_n)
12     if(!rst_n)
13         counter <= 0;
14     else if(counter==28408)
15         counter <= 0;
16     else
17         counter <= counter+1;
18
19 always @(posedge clk or negedge rst_n)
20     if(!rst_n)
21         clk_div <= 0;
22     else if(counter==28408)
23         clk_div <= ~clk_div;
24 endmodule

View Code

仿真代码:

 1 //tb
 2 module div_tb();
 3     reg clk;
 4     reg rst_n=0;
 5     wire clk_div;
 6     parameter DELY=100;
 7 div U_div(
 8     .clk    (clk    ),
 9     .rst_n  (rst_n),
10     .clk_div(clk_div)
11 );
12     always #(DELY/2) clk=~clk;//产生时钟波形
13 initial begin
14     $fsdbDumpfile("div_any.fsdb");
15     $fsdbDumpvars(0,U_div);
16  end
17  initial begin
18           clk=0;rst_n=0;
19     #DELY rst_n=1;
20     #((DELY*80000)) $finish;
21 end
22 endmodule

View Code

继续让我们来看如何实现任意占空比,比如还是由50M分频产生880Hz,而分频得到的信号的占空比为30%。
56818×30%=17045
设计代码:

 1 //rtl
 2 module div(
 3     clk,
 4     rst_n,
 5     clk_div,
 6     counter
 7 );
 8     input clk,rst_n;
 9     output clk_div;
10     reg clk_div;
11     output [15:0] counter;
12     reg [15:0] counter;
13
14 always @(posedge clk)
15     if(!rst_n)
16         counter <= 0;
17     else if(counter==56817)
18         counter <= 0;
19     else counter <= counter+1;
20
21 always @(posedge clk)
22   if(!rst_n)
23     clk_div <= 0;
24   else if(counter<17045)
25     clk_div <= 1;
26   else
27     clk_div <= 0;
28  endmodule

View Code

仿真代码:

 1 //tb
 2 module div_tb();
 3     reg clk;
 4     reg rst_n;
 5     wire clk_div;
 6     wire [15:0] counter;
 7     parameter DELY=100;
 8 div U_div(
 9     .clk    (clk    ),
10     .rst_n  (rst_n  ),
11     .counter(counter),
12     .clk_div(clk_div)
13 );
14     always #(DELY/2) clk=~clk;//产生时钟波形
15 initial begin
16     $fsdbDumpfile("div_any.fsdb");
17     $fsdbDumpvars(0,U_div);
18  end
19  initial begin
20           clk=0;rst_n=0;
21     #DELY rst_n=1;
22     #((DELY*80000)) $finish;
23 end
24 endmodule

View Code

4 小结
通过以上几个例子对比不难发现,借助计数器来实现任意点空比的任意分频的方法简单,且用verilog语言进行行为描述时,代码简洁、易懂、通用。
 通过以上的学习,对分频器有了比较深刻的认识,将在以后的学习中会有广泛的应用。

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

转载于:https://www.cnblogs.com/zhangxianhe/p/11083208.html

Verilog设计分频器(面试必看)相关推荐

  1. (95)FPGA二四译码器设计,面试必问(十九)(第19天)

    (95)FPGA二四译码器设计,面试必问(十九)(第19天) 1 文章目录 1)文章目录 2)FPGA初级课程介绍 3)FPGA初级课程架构 4)FPGA二四译码器设计,面试必问(十九)(第19天) ...

  2. (89)FPGA三分频设计,面试必问(十三)(第18天)

    (89)FPGA三分频设计,面试必问(十三)(第18天) 1 文章目录 1)文章目录 2)FPGA初级课程介绍 3)FPGA初级课程架构 4)FPGA三分频设计,面试必问(十三)(第18天) 5)技术 ...

  3. (88)FPGA二分频设计,面试必问(十二)(第18天)

    (88)FPGA二分频设计,面试必问(十二)(第18天) 1 文章目录 1)文章目录 2)FPGA初级课程介绍 3)FPGA初级课程架构 4)FPGA二分频设计,面试必问(十二)(第18天) 5)技术 ...

  4. Java常见面试题 Java面试必看 (一)

    本篇博客是本人收集网上Java相关的资料整理所得,仅供参考. 一.Java基础 1.JDK 和 JRE区别 JDK(Java Development Kit)是针对Java开发员的产品,是整个Java ...

  5. Java常见面试题 Java面试必看 (二)

    Java常见面试题 Java面试必看 (一) 十一.Spring Boot/Spring Cloud 104.什么是 spring boot? Spring Boot 是由 Pivotal 团队提供的 ...

  6. python开发工程师面试题-超实用面试必看,Python工程师面试题

    原标题:超实用面试必看,Python工程师面试题 面试是公司挑选职工的一种重要方法.它给公司和应招者提供了进行双向交流的机会,能使公司和应招者之间相互了解,从而双方都可更准确做出聘用与否.受聘与否的决 ...

  7. 最新iOS面试必看题视频教程(附大神简历要素)

    2019独角兽企业重金招聘Python工程师标准>>> 本文是由尚学堂iOS学院总结的ios开发者在求职时会遇到的一些面试题 ,并通过实际代码演练将课程详尽的讲解出来,希望对学习io ...

  8. 面试必看:java面试考点精讲视频教程

    面试必看:java面试考点精讲视频教程 Java作为目前比较火的计算机语言之一,连续几年蝉联最受程序员欢迎的计算机语言榜首,因此每年新入职Java程序员也数不胜数.很多java程序员在学成之后,会面临 ...

  9. 网络工程师面试题(面试必看)(3)

    作者简介:一名云计算网络运维人员.每天分享网络与运维的技术与干货.   座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 前言 本系列将会提供网络工程师面试题,由多位专家整合出本系列面试 ...

  10. 2019年黑马新版Java学习路线图(内含大纲+视频+工具+书籍+面试)面试必看!

    非常好的java学习路线,伴有配套资源. 面试必看! 黑马程序员:http://bbs.itheima.com/thread-386464-1-1.html

最新文章

  1. 文本输入框、密码输入框
  2. setTimeOut函数和setInterval函数
  3. mysql表格导入java_使用java技术将Excel表格内容导入mysql数据库
  4. Addin and Automation Development In VB.NET 2003 (3)
  5. HDU1512 (左偏树)
  6. 小程序中 swiper设置圆角在真机上不显示问题
  7. Flume Channel
  8. python实现以及所有排序大总结【转】
  9. ThinkPHP5最新URL访问:PATH_INFO和兼容模式
  10. 安装logstash5.4.1,并使用grok表达式收集nginx日志
  11. android ui设计最新字体,UI设计常用字体规范
  12. iOS面试题与核心基础之性能优化
  13. 2019 Multi-University Training Contest 6:Snowy Smile(线段树查询最大子段和)
  14. Javascript多功能计算器
  15. 说说某音d赞zhang粉那点事
  16. 学生党必备读书笔记app推荐
  17. 电脑配置jdk环境变量_苹果电脑配置环境变量
  18. 服务器里vm启动不了共享虚拟机,VMware Workstation Server共享服务不能启动
  19. tinyipa make
  20. 根据灰度直方图调整图象亮度

热门文章

  1. windows常用命令netstat
  2. CentOS 7 解决丢失 nginx.pid 1
  3. php 重定向 cookie,php – 如何在CURL重定向上传递Cookie?
  4. kali mysql停止服务器_第 2 篇 MySQL 安装
  5. JSTL 与 JSP 代码段 相互调用变量
  6. java获取数据库MetaData
  7. php程序员学什么语言好就业_php语言是什么?学好php需要掌握什么?
  8. linux中的ftp是什么意思,什么是linux的ftp
  9. android xml 未能解析文件,Android Studio中“无法解析符号R”
  10. linux如何判断光盘是否挂载,LInux下如何挂载光盘找rpm包的方法步骤