当前位置:   article > 正文

FPGA_分频(信号使能分频与计数器分频)(奇偶分频)_fpga实现六分频

fpga实现六分频

时钟对于 FPGA 是非常重要的,但板载晶振提供的时钟信号频率是固定的,不一定满
足工程需求,所以分频和倍频还是很有必要的。

一、计数器分频

这里通过计数的方式来实现分频。

1.通过计数器来实现6分频。两种方式。第一种直接通过计数方式直接获取获取。输入信号sys_clk和sys_rst_n,输出分频的信号clk_out,还有一个变量计数器cnt。

在这里插入图片描述

 cnt:计数器说明,要进行6分频,原始信号6个周期变一个周期输出,输出6分频周期的半个周期占三个原始时钟周期,对原始时钟计数3(0 1 2)

  1. module divider_six
  2. (
  3. input wire sys_rst,
  4. input wire sys_clk,
  5. output reg clk_out
  6. );
  7. reg [2:0] cnt;
  8. always@(posedge sys_clk or negedge sys_rst)
  9. if(sys_rst == 1'b0)
  10. cnt <= 2'd0;
  11. else if(cnt == 2'd2)
  12. cnt <= 2'd0;
  13. else
  14. cnt <= cnt+2'd1;
  15. always@(posedge sys_clk or negedge sys_rst)
  16. if(sys_rst == 1'b0)
  17. clk_out <= 1'b0;
  18. else if(cnt == 2'd2)
  19. clk_out <= ~clk_out;
  20. else
  21. clk_out <= clk_out;
  22. endmodule

testbench

  1. `timescale 1ns/1ns
  2. module tb_divider_six();
  3. reg sys_rst;
  4. reg sys_clk;
  5. wire clk_out;
  6. initial
  7. begin
  8. sys_clk = 1'b1;
  9. sys_rst = 1'b0;
  10. #20
  11. sys_rst = 1'b1;
  12. end
  13. always #10 sys_clk = ~sys_clk;
  14. divider_six divider_six_inst
  15. (
  16. .sys_rst(sys_rst),
  17. .sys_clk(sys_clk),
  18. .clk_out(clk_out)
  19. );
  20. endmodule

在这里插入图片描述

 此时输出时钟就是clk_out ,如果直接用clk_out当作系统工作时钟

  1. //直接使用clk_out作为工作时钟
  2. always@(posedge clk_out or negedge sys_rst_n)
  3. if(sys_rst_n == 1'b0)
  4. a <= 0;
  5. else
  6. a <= a + 1;

二、 通过计数器控制标志信号,通过标志信号当作系统工作时钟

  1. module divider_six
  2. (
  3. input wire sys_rst,
  4. input wire sys_clk,
  5. output reg clk_flag
  6. );
  7. reg [2:0] cnt;
  8. always@(posedge sys_clk or negedge sys_rst)
  9. if(sys_rst == 1'b0)
  10. cnt <= 2'd0;
  11. else if(cnt == 3'd5)
  12. cnt <= 3'd0;
  13. else
  14. cnt <= cnt+3'd1;
  15. always@(posedge sys_clk or negedge sys_rst)
  16. if(sys_rst == 1'b0)
  17. clk_flag <=1'b0;
  18. else if(cnt == 3'd4)
  19. clk_flag <=1'b1;
  20. else
  21. clk_flag <=1'b0;
  22. endmodule

此时产生使能信号flag(实际还是周期变化的信号理解为时钟,但是不当作时钟信号使用,当作使能信号触发,但是组合逻辑还是用系统源时钟)。

  1. //工作时钟还是系统时钟
  2. always@(posedge sys_clk or negedge sys_rst_n)
  3. if(sys_rst_n == 1'b0)
  4. a <= 1'd0;
  5. else if(clk_flag == 1'b1)
  6. a <= a + 1'b1;

总结:两种方式的区别

这里为什么要说明这两种方式呢?
这里就要说到FPGA中的全局时钟网络,因为在 FPGA 中凡是时钟信号都要连接到全局时钟网络上,全局时钟网络也称为全局时钟树,是 FPGA 厂商专为时钟路径而特殊设计的,它能够使时钟信号到达每个寄存器的时间都尽可能相同,以保证更低的时钟偏斜(Skew)和抖动(Jitter)。然而我们采用第一种方式产生的时钟clk_out信号并没有连接到全局时钟网络上,这种做法所衍生的潜在问题在低速系统中不易察觉,而在高速系统中就很容易出现问题,但 sys_clk 则是由外部晶振直接通过管脚连接到了 FPGA 的专用时钟管脚上,自然就会连接到全局时钟网络上,所以在 sys_clk 时钟工作下的信号要比在 clk_out 时钟工作下的信号更容易在高速系统中保持稳定。所以第二种方式相对来说更加安全。

上述已经说到6分频,属于偶数分频。下面就来介绍奇数分频。奇数分频采用上述第二种方式来实现的话,思路和步骤都差不多。我这里介绍一下奇数分频采用上述的第一种方式。那么问题又来了,既然上述第一种方式没有第二种好,为什么还有讲的,哈哈,是的。我记录他并不是因为他的好,而是因为这里奇数分频时的思路和逻辑思维。这里实现一个5分频

首先是输入时钟和复位,一个计数器,两个变量分频时钟,一个输出时钟。要实现N奇数分频,计数器计数到N-1,这里5分频最大计数到4。然后变量clk1初始状态为高电平,系统时钟上升沿到来时有效,这里计数到2时拉低,其实这里可以计数到0,1,2,3都是可以的。clk2初始状态也是高电平,系统时钟下降沿到来时有效。这里计数到与clk1计数最大值一致就行,然后clk1与clk2做与运算就可以得到输出5分频时钟clk_out。

两个四分频,计数值范围不一样,造成相位偏移半个周期,两个四分频信号相与,输出5分频时钟信号,(最好该信号依然当作flag使能信号使用,在时序逻辑输入时钟还是使用原始时钟)
 

  1. module divider_five
  2. (
  3. input wire sys_clk ,
  4. input wire sys_rst_n ,
  5. output wire clk_out
  6. );
  7. reg [2:0] cnt;
  8. reg clk1;
  9. reg clk2;
  10. always@(posedge sys_clk or negedge sys_rst_n)
  11. if(sys_rst_n == 1'b0)
  12. cnt <= 3'd0;
  13. else if(cnt == 3'd4)
  14. cnt <= 3'd0;
  15. else
  16. cnt <= cnt + 1'b1;
  17. always@(posedge sys_clk or negedge sys_rst_n)
  18. if(sys_rst_n == 1'b0)
  19. clk1 <= 1'b1;
  20. else if(cnt == 3'd2)
  21. clk1 <= 1'b0;
  22. else if(cnt == 3'd4)
  23. clk1 <= 1'b1;
  24. else
  25. clk1 <= clk1;
  26. always@(negedge sys_clk or negedge sys_rst_n)
  27. if(sys_rst_n == 1'b0)
  28. clk2 <= 1'b1;
  29. else if(cnt == 3'd2)
  30. clk2 <= 1'b0;
  31. else if(cnt == 3'd4)
  32. clk2 <= 1'b1;
  33. else
  34. clk2 <= clk2;
  35. assign clk_out = clk1 & clk2;
  36. endmodule

 testbench

  1. `timescale 1ns/1ns
  2. module tb_divider_five();
  3. reg sys_clk;
  4. reg sys_rst_n;
  5. wire clk_out;
  6. initial
  7. begin
  8. sys_clk = 1'b1;
  9. sys_rst_n <= 1'b0;
  10. #30
  11. sys_rst_n <= 1'b1;
  12. end
  13. always #10 sys_clk = ~sys_clk;
  14. divider_five divider_five_inst
  15. (
  16. .sys_clk (sys_clk),
  17. .sys_rst_n (sys_rst_n),
  18. .clk_out (clk_out)
  19. );
  20. endmodule

仿真

在这里插入图片描述

分频系数:50MHz晶振输入

        输出1KHz时钟频率,50_000_000/1000=50_000

        输出100KHz时钟频率,50_000_000/100_000=500

来源:有所更改,加入自己理解(175条消息) FPGA——分频器_fpga分频器_rοckman的博客-CSDN博客​​​​​https://blog.csdn.net/a17377547725/article/details/125927896

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/421606
推荐阅读
相关标签
  

闽ICP备14008679号