• FPGA——时钟分频


    时钟分频也是笔试题里面经常出现的,(我已经遇到过了),看完这一篇,分分钟掌握!

    目录

    偶数分频

    D触发器级联法

     计数器法

    奇数分频

    占空比50% 的奇数分频

    占空比无要求的奇数分频

    任意小数分频


    偶数分频

     如上图输入给clk,输出将其变成周期为2倍的clk_out2, 将其变成周期为4倍的clk_out4,将其变成周期为8倍的clk_out8,占空比为50%

    D触发器级联法

    对于偶数分频电路,在不考虑时钟同步时钟延迟的问题时,直接使用D触发器级联来实现:关键在于,上升沿才能触发翻转,但是一个周期只有一个上升沿,因此周期翻倍

    1. `timescale 1ns/1ns
    2. module even_div
    3. (
    4. input wire rst ,
    5. input wire clk_in,
    6. output wire clk_out2,
    7. output wire clk_out4,
    8. output wire clk_out8
    9. );
    10. reg clk_out2_r, clk_out4_r, clk_out8_r;
    11. always@(posedge clk_in or negedge rst) begin
    12. if(~rst)
    13. clk_out2_r <= 0;
    14. else
    15. clk_out2_r <= ~clk_out2_r;
    16. end
    17. always@(posedge clk_out2 or negedge rst) begin
    18. if(~rst)
    19. clk_out4_r <= 0;
    20. else
    21. clk_out4_r <= ~clk_out4_r;
    22. end
    23. always@(posedge clk_out4 or negedge rst) begin
    24. if(~rst)
    25. clk_out8_r <= 0;
    26. else
    27. clk_out8_r <= ~clk_out8_r;
    28. end
    29. assign clk_out2 = clk_out2_r;
    30. assign clk_out4 = clk_out4_r;
    31. assign clk_out8 = clk_out8_r;
    32. endmodule

     计数器法

    2、4、8恰好是2的次方,可构造一个3位计数器,依靠第0位,第1位,第2位的变化速度来实现:

    2分频的输出=cnt第0位(由于计数器在clk=高电平时才+1,因此本身就是2倍的周期)

    4分频输出=cnt第1位

    8分频输出=cnt第2位

    eg 4分频:000 001 010 011 100 101 110 111 000

    1. `timescale 1ns/1ns
    2. module even_div
    3. (
    4. input wire rst ,
    5. input wire clk_in,
    6. output wire clk_out2,
    7. output wire clk_out4,
    8. output wire clk_out8
    9. );
    10. reg [2:0]cnt;
    11. always@(posedge clk_in or negedge rst)
    12. if(!rst)
    13. cnt <= 3'b111;//初始赋全1
    14. else
    15. cnt <= cnt+1;
    16. assign clk_out2 = ~cnt[0];//根据波形,一开始全为高电平
    17. assign clk_out4 = ~cnt[1];
    18. assign clk_out8 = ~cnt[2];
    19. endmodule

    奇数分频

    占空比50% 的奇数分频

    设计一个同时输出7分频的时钟分频器,占空比要求为50% 

    对于奇数分频电路,主要难点在于50%占空比的实现。单触发沿在奇数分频中是没有办法实现50%占空比的,因此需要考虑使用双边沿加组合逻辑实现50%占空比

    设置计数器,计数器从0→6,当计数器==3,上升沿触发得到clk_pos,下降沿触发得到clk_neg,

    而输出的7分频clk,上升沿在clk_neg触发,下降沿在clk_pos触发,是clk_neg和clk_pos进行或运算的结果

    根据这个思路,我们可以得到任意奇数分频,占空比为50%的输出,修改N值即可,代码如下:

    1. `timescale 1ns/1ns
    2. module odo_div_or
    3. #(parameter N = 7)
    4. (
    5. input wire rst ,
    6. input wire clk_in,
    7. output wire clk_out7
    8. );
    9. reg [3:0] cnt ;
    10. always @(posedge clk_in or negedge rst) begin
    11. if (!rst) begin
    12. cnt <= 'b0 ;
    13. end
    14. else if (cnt == N-1) begin
    15. cnt <= 'b0 ;
    16. end
    17. else begin
    18. cnt <= cnt + 1'b1 ;
    19. end
    20. end
    21. reg clkp ;
    22. always @(posedge clk_in or negedge rst) begin
    23. if (!rst) begin
    24. clkp <= 1'b0 ;
    25. end
    26. else if (cnt == (N>>1)) begin
    27. clkp <= 1 ;
    28. end
    29. else if (cnt == N-1) begin
    30. clkp <= 0 ;
    31. end
    32. end
    33. reg clkn ;
    34. always @(negedge clk_in or negedge rst) begin
    35. if (!rst) begin
    36. clkn <= 1'b0 ;
    37. end
    38. else if (cnt == (N>>1) ) begin
    39. clkn <= 1 ;
    40. end
    41. else if (cnt == N-1) begin
    42. clkn <= 0 ;
    43. end
    44. end
    45. assign clk_out7 = clkp | clkn ;
    46. endmodule

    占空比无要求的奇数分频

    实现一个5分频clk,占空比可修改

    由于一个cnt其实=2个clk_in ,所以在占空比不要求的情况下,即使是奇数分频也=一个偶数,我们可以把这个偶数分成2个偶数的和,(例如5分频相当于10clk_in,10=4+6,可以4clk_in低电平,6clk_in高电平)(而要求占空比的时候,10=5+5,需要参考上面的做法)

    一个完整的clk周期要包含5个clk_in,但是占空比不要求,那么设置一个计数器cnt,计数范围0-4,每个clk_in周期加1。当计数器数值在0~1时,clk_out5==1;当计数器数值在2~4时,clk_out5==0。这样就实现了周期为5、占空比为3/5 ​的clk_out5

    1. `timescale 1ns/1ns
    2. module odd_div (
    3. input wire rst ,
    4. input wire clk_in,
    5. output wire clk_out5
    6. );
    7. reg [2:0] cnt;
    8. reg clk_out5_r;
    9. always@(posedge clk_in or negedge rst) begin
    10. if(~rst)
    11. clk_out5_r <= 0;
    12. else
    13. clk_out5_r <=1;
    14. end
    15. always@(posedge clk_in or negedge rst) begin
    16. if(~rst)
    17. cnt <= 0;
    18. else
    19. cnt <= cnt==4? 0: cnt+1;
    20. end
    21. assign clk_out5 = clk_out5_r;
    22. endmodule

    任意小数分频

     小数分频器是分频器中最难的一种,而且不能像整数分频那样得到均匀且占空比为50%的分频输出

    1. `timescale 1ns/1ns
    2. module div_M_N(
    3. input wire clk_in,
    4. input wire rst,
    5. output wire clk_out
    6. );
    7. parameter M_N = 8'd87;
    8. parameter c89 = 8'd24; // 8/9时钟切换点
    9. parameter div_e = 5'd8; //偶数周期
    10. parameter div_o = 5'd9; //奇数周期
    11. //*************code***********//
    12. reg [3:0] clk_cnt;
    13. reg [6:0] cyc_cnt;
    14. reg div_flag;
    15. reg clk_out_r;
    16. always@(posedge clk_in or negedge rst) begin
    17. if(~rst)
    18. clk_cnt <= 0;
    19. else if(~div_flag)
    20. clk_cnt <= clk_cnt==(div_e-1)? 0: clk_cnt+1;
    21. else
    22. clk_cnt <= clk_cnt==(div_o-1)? 0: clk_cnt+1;
    23. end
    24. always@(posedge clk_in or negedge rst) begin
    25. if(~rst)
    26. cyc_cnt <= 0;
    27. else
    28. cyc_cnt <= cyc_cnt==(M_N-1)? 0: cyc_cnt+1;
    29. end
    30. always@(posedge clk_in or negedge rst) begin
    31. if(~rst)
    32. div_flag <= 0;
    33. else
    34. div_flag <= cyc_cnt==(M_N-1)||cyc_cnt==(c89-1)? ~div_flag: div_flag;
    35. end
    36. always@(posedge clk_in or negedge rst) begin
    37. if(~rst)
    38. clk_out_r <= 0;
    39. else if(~div_flag)
    40. clk_out_r <= clk_cnt<=((div_e>>2)+1);
    41. else
    42. clk_out_r <= clk_cnt<=((div_o>>2)+1);
    43. end
    44. assign clk_out = clk_out_r;
    45. //*************code***********//
    46. endmodule

  • 相关阅读:
    Web 网页性能及性能优化
    H5新Api | requestIdleCallback - requestAnimationFram
    Vue 源码解读(11)—— render helper
    Apache Doris物化视图使用详解
    unicode/utf8/utf16/utf32笔记
    MONGODB 的基础 NOSQL注入基础
    Linux下整合Apache和WebLogic
    系列文章|云原生时代下微服务架构进阶之路 - Spring Boot
    GCP/临床试验基础知识集锦
    Hadoop HA高可用环境搭建
  • 原文地址:https://blog.csdn.net/weixin_46188211/article/details/126270944