【FPGA】分频电路设计(Verilog HDL设计)(良心博文)

举报
李锐博恩 发表于 2021/07/15 07:21:57 2021/07/15
【摘要】 目录 前言 分频器分类 偶分频 奇分频 占空比为50%的奇分频 占空比不限定的奇数分频器 前言 虽然在实际工程中要产生分频时钟一般采用FPGA的时钟管理器来进行分频、倍频,通过设置一下IP核中的参数即可,这样做有很多别的方法(例如:直接用Verilog HDL设计分频电路)达不到的效果,产生时钟的质量也更好,因此,一般而言,也推荐这种方法,但这并非意味着直...

目录

前言

分频器分类

偶分频

奇分频

占空比为50%的奇分频

占空比不限定的奇数分频器



前言

虽然在实际工程中要产生分频时钟一般采用FPGA的时钟管理器来进行分频、倍频,通过设置一下IP核中的参数即可,这样做有很多别的方法(例如:直接用Verilog HDL设计分频电路)达不到的效果,产生时钟的质量也更好,因此,一般而言,也推荐这种方法,但这并非意味着直接用Verilog HDL设计分频电路一无是处,毫无用途。

如果对时钟的性能要求不高,我就自然就可以用这种方法产生分频时钟,这样就只消耗了少量的资源而实现了时钟的分频要求,我们把这种设计叫做分频器设计。

注意:分频电路可以这么设计,但倍频电路呢?恐怕写不出来吧!只能用IP核来产生。

本博文直接给出设计原理和Verilog HDL设计程序以及测试程序和仿真图,是不是够贴心?


分频器分类

分频器分为偶分频、奇分频,下面分别介绍二者的设计原理。



偶分频

对于偶分频电路,一般做法是通过计数器计数,达到计数值上限(上限值为N/2-1,N为分频数目)后输出时钟取反同时计数器归零。例如10分频,用计数器计数基准时钟周期个数cnt(cnt初值为0)(计数上升沿出现的次数即可),当cnt计数为4时候,分频时钟翻转一次,同时cnt清零,继续计数。

  • Verilog HDL设计程序为:

  
  1. //偶分频电路的Verilog HDL设计(10分频为例)
  2. module even_freq_div(clk, rst, clk_div10,cnt);
  3. input clk;
  4. input rst;
  5. output clk_div10;
  6. reg clk_div10;
  7. output [2:0] cnt; //输出cnt的原因是为了看到计数次数,便于分析仿真结果。
  8. reg [2:0] cnt;
  9. always @(posedge clk)
  10. begin
  11. if(rst) //复位信号有效;
  12. begin
  13. cnt <= 0; //计数器清零
  14. clk_div10 <= 0; //输出清零;
  15. end
  16. else //复位信号无效;
  17. begin
  18. if(cnt == 4) //每一次时钟上升沿到来时,都检查一次计数值是否达到4;
  19. begin
  20. clk_div10 <= ~clk_div10;
  21. cnt <= 0; //计数器计数到4后,重新清零;计数值为4意味着已经计了5个周期,这时10分频时钟翻转一次;
  22. end
  23. else //如果计数器未计数到4,则来一个上升沿加1,同时分频时钟继续保持原值不变。
  24. begin
  25. cnt <= cnt + 1;
  26. clk_div10 <= clk_div10; //否则继续保持;
  27. end
  28. end
  29. end
  30. endmodule
  • 测试文件为:

  
  1. //10分频电路的测试文件
  2. `timescale 1ns/1ps;
  3. module even_freq_div_tb;
  4. reg clk;
  5. reg rst;
  6. wire clk_out;
  7. wire [2:0] cnt;
  8. always //时钟电路
  9. begin
  10. #10 clk = ~clk;
  11. end
  12. //初始化
  13. initial
  14. begin
  15. clk = 0;
  16. rst = 1;
  17. #20 rst = 0;
  18. end
  19. even_freq_div u1( .clk(clk), .rst(rst), .clk_div10(clk_out),.cnt(cnt) );
  20. endmodule
  • 在modelsim中仿真的结果为:

奇分频

占空比为50%的奇分频

首先看占空比为50%的奇分频,也就分频后的时钟的占空比为50%,高低电平持续时间一致。

如何设计呢?

设计方法很简单,在博文:3分频电路设计中,我们设计了三分频电路,设计方法是先产生一个占空比为1:3的3分频时钟,之后用下降沿采样,采样得到的时钟与三分频时钟相或即可。

对于N分频时钟,N为奇数,我们可以先通过计数的方法来产生一个占空比为(N-1)/2:N的分频时钟clk_div1,之后用下降沿采样得到clk_div2,再之后将clk_div1 | clk_div2即可。

以5分频为例,我们写一个Verilog程序:

更新于20190728


  
  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer: CSDN 李锐博恩
  5. //
  6. // Create Date: 2019/07/28 15:15:27
  7. // Design Name:
  8. // Module Name: FRE_DIV5
  9. //
  10. module FRE_DIV5(
  11. input clk,
  12. input rst_n,
  13. output clk_div5
  14. );
  15. reg [2:0] div_cnt;
  16. always@(posedge clk or negedge rst_n) begin
  17. if(~rst_n) begin
  18. div_cnt <= 0;
  19. end
  20. else if(div_cnt <4) begin
  21. div_cnt <= div_cnt + 1;
  22. end
  23. else
  24. div_cnt <= 0;
  25. end
  26. reg clk_div_r, clk_div_rr;
  27. always@(posedge clk or negedge rst_n) begin
  28. if(~rst_n) begin
  29. clk_div_r <= 1;
  30. end
  31. else if(div_cnt == 1) begin
  32. clk_div_r <= ~clk_div_r;
  33. end
  34. else if(div_cnt == 4) begin
  35. clk_div_r <= ~clk_div_r;
  36. end
  37. else clk_div_r <= clk_div_r;
  38. end
  39. always@(negedge clk or negedge rst_n) begin
  40. if(~rst_n) begin
  41. clk_div_rr <= 1;
  42. end
  43. else clk_div_rr <= clk_div_r;
  44. end
  45. assign clk_div5 = clk_div_r | clk_div_rr;
  46. endmodule

仿真程序:


  
  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2019/07/28 15:24:37
  7. // Design Name:
  8. // Module Name: fre_div5_tb
  9. //
  10. module fre_div5_tb(
  11. );
  12. reg clk;
  13. reg rst_n;
  14. wire clk_div5;
  15. initial begin
  16. clk = 0;
  17. forever
  18. #2 clk = ~clk;
  19. end
  20. initial begin
  21. rst_n = 0;
  22. #23
  23. rst_n = 1;
  24. end
  25. FRE_DIV5 INST_FRE_DIV5(
  26. .clk(clk),
  27. .rst_n(rst_n),
  28. .clk_div5(clk_div5)
  29. );
  30. endmodule

仿真波形:

有了占空比为50%的奇数分频器,其实不必写占空比不限定的奇数分频器了。下面还是给出吧。

占空比不限定的奇数分频器

对于占空比不限定的奇数分频器,一般将计数器的上限值为N-1,当计数值到(N-1)/2时,输出时钟取反,当计数器达到上限值N-1时,输出时钟再取反同时计数器归零。(占空比为(N-1)/2 : N的奇分频)

例如,设计一个5分频器,计数器初值为0,那么基准时钟的上升沿计数,计数值为2时,输出时钟反转一次,然后继续计数,计数值到达上限4时候,再反转一次,同时计数器清零,并继续上述过程。

  • Verilog HDL设计程序为:

  
  1. //奇分频电路的Verilog HDL设计(5分频为例)
  2. module odd_freq_div(clk, rst, clk_div, cnt);
  3. input clk;
  4. input rst;
  5. output clk_div;
  6. reg clk_div;
  7. output [2:0] cnt; //输出cnt的原因是为了看到计数次数,便于分析仿真结果。
  8. reg [2:0] cnt;
  9. always @(posedge clk )
  10. begin
  11. if(rst) //复位信号有效;
  12. begin
  13. cnt <= 0; //计数器清零
  14. clk_div <= 0; //输出清零;
  15. end
  16. else //复位信号无效;
  17. begin
  18. if(cnt == 2) //每一次时钟上升沿到来时,都检查一次计数值是否达到4;
  19. begin
  20. clk_div <= ~clk_div;
  21. cnt <= cnt + 1;
  22. end
  23. else if (cnt == 4)
  24. begin
  25. clk_div <= ~clk_div;
  26. cnt <= 0;
  27. end
  28. else //如果计数器未计数到4,则来一个上升沿加1,同时分频时钟继续保持原值不变。
  29. begin
  30. cnt <= cnt + 1;
  31. clk_div <= clk_div; //否则继续保持;
  32. end
  33. end
  34. end
  35. endmodule
  • 测试文件为:

  
  1. //5分频电路的测试文件
  2. `timescale 1ns/1ps;
  3. module odd_freq_div_tb;
  4. reg clk;
  5. reg rst;
  6. wire clk_out;
  7. wire [2:0] cnt;
  8. always //时钟电路
  9. begin
  10. #10 clk = ~clk;
  11. end
  12. //初始化
  13. initial
  14. begin
  15. clk = 0;
  16. rst = 1;
  17. #20 rst = 0;
  18. end
  19. odd_freq_div u1( .clk(clk), .rst(rst), .clk_div(clk_out),.cnt(cnt) );
  20. endmodule
  • 仿真图为:


最后,想说一句,其实写了这么多,有什么用呢?

关键是写熟练,会变通,你会了奇数分频,偶数分频自然也会了。参数化编程也会了。

可是笔试时候,人家又要求,写出可以任意切换1-8分频的分频器,对于这个任意切换的分频器见我的博文:https://blog.csdn.net/Reborn_Lee/article/details/97553078

 

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/81298123

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。