[Verilog HDL] Verilog设计分频器

[复制链接]
80|28
gaochy1126 发表于 2026-3-31 19:57 | 显示全部楼层 |阅读模式
分频器是指使输出信号频率为输入信号频率整数分之一的电子电路。在许多电子设备中如电子钟、频率合成器等,需要各种不同频率的信号协同工作,常用的方法是以稳定度高的晶体振荡器为主振源,通过变换得到所需要的各种频率成分,分频器是一种主要变换手段。
    早期的分频器多为正弦分频器,随着数字集成电路的发展,脉冲分频器(又称数字分频器)逐渐取代了正弦分频器。
下面以Verilog HDL 语言为基础介绍占空比为50%的分频器。
1、偶分频
  偶分可以看到,clk的上升沿,采样到cnt=2的时候,就翻转,采样到0和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.     parameter NUM_DIV = 6;
  12.     reg    [3:0] cnt;

  13. always @(posedge clk or negedge rst_n)
  14.     if(!rst_n) begin
  15.         cnt     <= 4'd0;
  16.         clk_div    <= 1'b0;
  17.     end
  18.     else if(cnt < NUM_DIV / 2 - 1) begin
  19.         cnt     <= cnt + 1'b1;
  20.         clk_div    <= clk_div;
  21.     end
  22.     else begin
  23.         cnt     <= 4'd0;
  24.         clk_div    <= ~clk_div;
  25.     end
  26. endmodule
  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
可以看到,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.     parameter NUM_DIV = 5;
  12.     reg[2:0] cnt1;
  13.     reg[2:0] cnt2;
  14.     reg    clk_div1, clk_div2;

  15. always @(posedge clk or negedge rst_n)
  16.     if(!rst_n)
  17.         cnt1 <= 0;
  18.     else if(cnt1 < NUM_DIV - 1)
  19.         cnt1 <= cnt1 + 1'b1;
  20.     else
  21.         cnt1 <= 0;

  22. always @(posedge clk or negedge rst_n)
  23.     if(!rst_n)
  24.         clk_div1 <= 1'b1;
  25.     else if(cnt1 < NUM_DIV / 2)
  26.         clk_div1 <= 1'b1;
  27.     else
  28.         clk_div1 <= 1'b0;

  29. always @(negedge clk or negedge rst_n)
  30.     if(!rst_n)
  31.        cnt2 <= 0;
  32.     else if(cnt2 < NUM_DIV - 1)
  33.        cnt2 <= cnt2 + 1'b1;
  34.     else
  35.        cnt2 <= 0;

  36. always @(negedge clk or negedge rst_n)
  37.     if(!rst_n)
  38.         clk_div2 <= 1'b1;
  39.     else if(cnt2 < NUM_DIV / 2)
  40.         clk_div2 <= 1'b1;
  41.     else
  42.         clk_div2 <= 1'b0;

  43.     assign clk_div = clk_div1 | clk_div2;
  44. endmodule
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.     reg [15:0] counter;

  11. always @(posedge clk or negedge rst_n)
  12.     if(!rst_n)
  13.         counter <= 0;
  14.     else if(counter==56817)
  15.         counter <= 0;
  16.     else
  17.         counter <= counter+1;

  18.    assign clk_div = counter[15];
  19. endmodule








本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
hellosdc 发表于 2026-3-31 20:37 来自手机 | 显示全部楼层
感谢分享,提供的例程很实用                                 

评论

赞一个  发表于 2026-3-31 21:02
usysm 发表于 2026-3-31 20:37 来自手机 | 显示全部楼层
具有一定的参考价值,需要的朋友可以参考一下。

评论

赞一个  发表于 2026-3-31 21:02
mickit 发表于 2026-3-31 20:38 来自手机 | 显示全部楼层
内容还是非常丰富的                                 

评论

赞一个  发表于 2026-3-31 21:02
phoenixwhite 发表于 2026-3-31 20:38 来自手机 | 显示全部楼层
有时间需要好好看看   不错                                 

评论

赞一个  发表于 2026-3-31 21:03
robertesth 发表于 2026-3-31 20:39 来自手机 | 显示全部楼层
以后多交流交流                  

评论

赞一个  发表于 2026-3-31 21:03
houjiakai 发表于 2026-3-31 20:39 来自手机 | 显示全部楼层
非常感谢楼主分享                                 

评论

赞一个  发表于 2026-3-31 21:03
lzbf 发表于 2026-3-31 20:40 来自手机 | 显示全部楼层
谢谢你共享的资料                                 

评论

赞一个  发表于 2026-3-31 21:03
bestwell 发表于 2026-3-31 20:41 来自手机 | 显示全部楼层
这些资料太全了!!!                 

评论

赞一个  发表于 2026-3-31 21:03
gygp 发表于 2026-3-31 20:41 来自手机 | 显示全部楼层
以后学习就方便了                                 

评论

赞一个  发表于 2026-3-31 21:03
mollylawrence 发表于 2026-3-31 20:42 来自手机 | 显示全部楼层
正准备学习的朋友推荐下载。                                 

评论

赞一个  发表于 2026-3-31 21:03
vivilyly 发表于 2026-3-31 20:42 来自手机 | 显示全部楼层
感谢分享,提供的例程很实用                                 

评论

赞一个  发表于 2026-3-31 21:03
zerorobert 发表于 2026-3-31 20:42 来自手机 | 显示全部楼层
共享的资料比较详细  谢谢                                 

评论

赞一个  发表于 2026-3-31 21:04
 楼主| gaochy1126 发表于 2026-3-31 21:42 | 显示全部楼层
Verilog分频器设计的核心是计数器逻辑的正确性和时序行为的可预测性,需通过非阻塞赋值、完整计数范围、同步复位及规范的时钟触发确保可靠性。
 楼主| gaochy1126 发表于 2026-3-31 21:42 | 显示全部楼层
需利用时钟双边沿(上升沿+下降沿)计数,通过两个计数器(分别在上升沿和下降沿触发)生成时钟,再通过或/与操作合并
 楼主| gaochy1126 发表于 2026-3-31 21:42 | 显示全部楼层
分频系数N需通过计数器循环计数实现(如0~N-1),确保计数器在达到N-1时翻转输出时钟,避免计数溢出或未达阈值导致分频错误
 楼主| gaochy1126 发表于 2026-3-31 21:42 | 显示全部楼层
在Verilog中设计分频器时,需关注时序逻辑、计数器行为、占空比控制及综合兼容性等问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:这个社会混好的两种人:一是有权有势,二是没脸没皮的。

1329

主题

12852

帖子

27

粉丝
快速回复 在线客服 返回列表 返回顶部
0