• 【Verilog 设计】Verilog 实现偶数、奇数分频和任意小数分频


    目录

    写在前面

    偶数分频

    Verilog 实现

    TestBench 测试文件

    RTL 视图

    仿真波形

    奇数分频

    Verilog 实现

    TestBench 测试文件

    RTL 视图

    仿真波形

    任意小数分频

    Verilog 实现

    TestBench 测试文件

    RTL 视图

    仿真波形


    写在前面

    在实际的项目工程中,经常需要不同的时钟频率工作,或者在一些笔试面试中,时钟分频也会被问到,因此这篇文章介绍几种常见的时钟分频的案例:偶数分频、奇数分频、任意小数分频。

    偶数分频

    偶数分频是最常见的分频方式也是最简单的,只需要一个简单的计数器即可,如果要实现4分频的时钟,只需要计数器从0计数到3,然后输出的时钟在计数到1和3的时钟翻转即可。

    Verilog 实现

    1. //`timescale 100ps / 1ps
    2. //
    3. // Engineer:
    4. // Create Date: 2022/07/24
    5. // Design Name:
    6. // Module Name: freq_div_even
    7. // Tool Versions: Vivado 2021.2
    8. // Encode: GBK
    9. // Description: 实现偶数四分频
    10. // Additional Comments:
    11. //
    12. //
    13. module freq_div_even(
    14. input clk,
    15. input rst,
    16. output reg clk_out
    17. );
    18. reg [1:0] cnt;
    19. always @(posedge clk or posedge rst) begin
    20. if (rst) begin
    21. cnt <= 'd0;
    22. end
    23. else if (cnt == 'd3) begin
    24. cnt <= 'd0;
    25. end
    26. else begin
    27. cnt <= cnt + 'd1;
    28. end
    29. end
    30. always @(posedge clk or posedge rst) begin
    31. if (rst) begin
    32. clk_out <= 'd0;
    33. end
    34. else if (cnt == 'd1) begin
    35. clk_out <= 'd1;
    36. end
    37. else if (cnt == 'd3) begin
    38. clk_out <= 'd0;
    39. end
    40. else begin
    41. clk_out <= clk_out;
    42. end
    43. end
    44. endmodule

    TestBench 测试文件

    1. `timescale 10ps / 1ps
    2. //
    3. // Engineer:
    4. // Create Date: 2022/07/24
    5. // Design Name:
    6. // Module Name: tb_freq_div_even
    7. // Tool Versions: Vivado 2021.2
    8. // Encode: GBK
    9. // Description:
    10. // Additional Comments:
    11. //
    12. //
    13. module tb_freq_div_even();
    14. reg clk;
    15. reg rst;
    16. wire clk_out;
    17. initial begin
    18. clk = 'd0;
    19. rst = 'd1;
    20. #20
    21. rst = 'd0;
    22. end
    23. always #10 clk = ~clk;
    24. freq_div_even inst_freq_div_even (
    25. .clk(clk),
    26. .rst(rst),
    27. .clk_out(clk_out)
    28. );
    29. endmodule

    RTL 视图

    仿真波形

    可以看到原时钟为50Mhz,在四分频后时钟为12.5Mhz,符合设计要求。如果要设计八分频甚至更大的分频也是如此操作。


    奇数分频

    相对于偶数分频,奇数分频要复杂一些,不仅要实现奇数分频而且占空比为50%,这里需要多加一个计数器,一个计数器由输入时钟上升沿触发,另一个计数器由输入时钟下降沿触发,最后将两个计数器的输出做相运算,即可得到奇数分频并且占空比为50%的时钟。

    Verilog 实现

    1. //`timescale 100ps / 1ps
    2. //
    3. // Engineer:
    4. // Create Date: 2022/07/24
    5. // Design Name:
    6. // Module Name: freq_div_odd
    7. // Tool Versions: Vivado 2021.2
    8. // Encode: GBK
    9. // Description: 实现奇数五分频
    10. // Additional Comments:
    11. //
    12. //
    13. module freq_div_odd(
    14. input clk,
    15. input rst,
    16. output wire clk_out
    17. );
    18. reg [2:0] cnt1;
    19. reg [2:0] cnt2;
    20. reg clk1;
    21. reg clk2;
    22. always @(posedge clk or posedge rst) begin
    23. if (rst) begin
    24. cnt1 <= 'd0;
    25. end
    26. else if (cnt1 == 'd4) begin
    27. cnt1 <= 'd0;
    28. end
    29. else begin
    30. cnt1 <= cnt1 + 'd1;
    31. end
    32. end
    33. always @(posedge clk or posedge rst) begin
    34. if (rst) begin
    35. clk1 <= 'd0;
    36. end
    37. else if (cnt1 < 'd2) begin
    38. clk1 <= 'd1;
    39. end
    40. else begin
    41. clk1 <= 'd0;
    42. end
    43. end
    44. always @(negedge clk or posedge rst) begin
    45. if (rst) begin
    46. cnt2 <= 'd0;
    47. end
    48. else if (cnt2 == 'd4) begin
    49. cnt2 <= 'd0;
    50. end
    51. else begin
    52. cnt2 <= cnt2 + 'd1;
    53. end
    54. end
    55. always @(negedge clk or posedge rst) begin
    56. if (rst) begin
    57. clk2 <= 'd0;
    58. end
    59. else if (cnt2 < 'd2) begin
    60. clk2 <= 'd1;
    61. end
    62. else begin
    63. clk2 <= 'd0;
    64. end
    65. end
    66. assign clk_out = clk1 | clk2;
    67. endmodule

    TestBench 测试文件

    1. `timescale 10ps / 1ps
    2. //
    3. // Engineer:
    4. // Create Date: 2022/07/24
    5. // Design Name:
    6. // Module Name: tb_freq_div_odd
    7. // Tool Versions: Vivado 2021.2
    8. // Encode: GBK
    9. // Description:
    10. // Additional Comments:
    11. //
    12. //
    13. module tb_freq_div_odd();
    14. reg clk;
    15. reg rst;
    16. wire clk_out;
    17. initial begin
    18. clk = 'd0;
    19. rst = 'd1;
    20. #20
    21. rst = 'd0;
    22. end
    23. always #10 clk = ~clk;
    24. freq_div_odd inst_freq_div_odd (
    25. .clk(clk),
    26. .rst(rst),
    27. .clk_out(clk_out)
    28. );
    29. endmodule

    RTL 视图

    仿真波形


    任意小数分频

    任意小数分频如果要分的更细一些,可以分成半整数分数和非半整数的小数分频,因为半整数也属于小数,所以这里统一用任意小数分频的设计方法实现。

    在设计时也可以选择直接调用 PLL 锁相环实现,比如要实现 6.3 的分频,可以先将源时钟 10 倍频,得到源时钟的 10 倍频率的时钟,再进行 63 分频实现,这样就可以得到 63 分频的时钟。

    另外也可以自己设计实现,分频结果 N = M + P,其中 M 为小数分频值得整数部分,P 为小数分频值得小数部分,同时小数可以用分式表示 b/a+b,比如 0.3 可以表示为3/7+3,此时b = 3,则原式可以表示为 N = M + b/a+b,对 M 进行通分得到 N = M(a+b) + b/a+b = [aM + b(M+1)]/a+b,这样就可以列出二元一次方程,6.3分频可以写成分式63/10。

    可以得到以下二元一次不等式:

    6a + 7b = 63

    a + b = 10

    解得:a = 7,b = 3

    表示先做 7 次 6 分频,再做 3 次 7 分频即可达到 6.3 分频的目的。

    Verilog 实现

    1. //`timescale 100ps / 1ps
    2. //
    3. // Engineer:
    4. // Create Date: 2022/07/24
    5. // Design Name:
    6. // Module Name: freq_div_decimal
    7. // Tool Versions: Vivado 2021.2
    8. // Encode: GBK
    9. // Description: 实现任意小数分频,以6.3分频为例
    10. // Additional Comments:
    11. // 先做 7 次 6 分频,再做 3 次 7 分频
    12. //
    13. //
    14. module freq_div_decimal(
    15. input clk,
    16. input rst,
    17. output reg clk_out
    18. );
    19. reg [3:0] cnt1;
    20. reg [3:0] cnt2;
    21. always @(posedge clk or posedge rst) begin
    22. if (rst) begin
    23. cnt1 <= 'd0;
    24. end
    25. else if ((cnt2 < 'd7) &&(cnt1 == 'd5)) begin
    26. cnt1 <= 'd0;
    27. end
    28. else if (cnt1 == 'd6) begin
    29. cnt1 <= 'd0;
    30. end
    31. else begin
    32. cnt1 <= cnt1 + 'd1;
    33. end
    34. end
    35. always @(posedge clk or posedge rst) begin
    36. if (rst) begin
    37. cnt2 <= 'd0;
    38. end
    39. else if ((cnt2 == 'd9) && (cnt1 == 'd6)) begin
    40. cnt2 <= 'd0;
    41. end
    42. else if ((cnt1 == 'd5) && (cnt2 < 'd7)) begin
    43. cnt2 <= cnt2 + 'd1;
    44. end
    45. else if (cnt1 == 'd6) begin
    46. cnt2 <= cnt2 + 'd1;
    47. end
    48. else begin
    49. cnt2 <= cnt2;
    50. end
    51. end
    52. always @(posedge clk or posedge rst) begin
    53. if (rst) begin
    54. clk_out <= 'd0;
    55. end
    56. else if ((cnt1 == 'd5) && (cnt2 < 'd7)) begin
    57. clk_out <= 'd1;
    58. end
    59. else if (cnt1 == 'd6) begin
    60. clk_out <= 'd1;
    61. end
    62. else begin
    63. clk_out <= 'd0;
    64. end
    65. end
    66. endmodule

    TestBench 测试文件

    1. `timescale 10ps / 1ps
    2. //
    3. // Engineer:
    4. // Create Date: 2022/07/24
    5. // Design Name:
    6. // Module Name: tb_freq_div_even
    7. // Tool Versions: Vivado 2021.2
    8. // Encode: GBK
    9. // Description:
    10. // Additional Comments:
    11. //
    12. //
    13. module tb_freq_div_even();
    14. reg clk;
    15. reg rst;
    16. wire clk_out;
    17. initial begin
    18. clk = 'd0;
    19. rst = 'd1;
    20. #20
    21. rst = 'd0;
    22. end
    23. always #10 clk = ~clk;
    24. freq_div_decimal inst_freq_div_decimal (
    25. .clk(clk),
    26. .rst(rst),
    27. .clk_out(clk_out)
    28. );
    29. endmodule

    RTL 视图

    仿真波形

    可以看到仿真波形,先经过了 7 次的 6 分频,再经过 3 次的 7 分频,最终形成 6.3 分频的时钟输出。

  • 相关阅读:
    SAP 重复制造简介
    pretrained model的参数修改,满足自己创建的net
    黑马程序员RabbitMQ入门到实战教程【高级篇】学习笔记
    mac电脑系统清理软件CleanMyMac X2024破解版下载
    python基于PHP+MySQL的教学资源管理平台
    [iOS]使用MonkeyDev完成Hook
    如何用seay对dvwa起始页面进行代码审计
    win10桌面图标全部变成白色的怎么办
    Tomcat部署及优化
    0035【Python】小白学习Python大纲
  • 原文地址:https://blog.csdn.net/m0_61298445/article/details/126003886