【Verilog HDL 训练】第 11 天(分频电路)

举报
李锐博恩 发表于 2021/07/15 03:25:53 2021/07/15
【摘要】 设计一个占空比50%的三分频电路。 针对这个分频器,博文的末尾会给出一个反面教材,这是我上次写的一个分频器,看起来很好,其实是不能综合的。针对其中的错误,我令立博文记录之:【 Verilog 】always@()的敏感源中为什么不能双边沿触发?为什么不能双时钟触发? 感谢学习道路上的前辈给予的指导:下面的分频器思路是: 画了个草图: 给出Verilog HD...

设计一个占空比50%的三分频电路。


针对这个分频器,博文的末尾会给出一个反面教材,这是我上次写的一个分频器,看起来很好,其实是不能综合的。针对其中的错误,我令立博文记录之:【 Verilog 】always@()的敏感源中为什么不能双边沿触发?为什么不能双时钟触发?

感谢学习道路上的前辈给予的指导:下面的分频器思路是:

画了个草图:

给出Verilog HDL描述:


  
  1. module Freq_divide(
  2. input clk,
  3. input rst_n,
  4. output clk_divide
  5. );
  6. //先写一个占空比为1/3的分频时钟
  7. reg clk_1_3;
  8. reg [2:0] count;
  9. always@(posedge clk or negedge rst_n) begin
  10. if(!rst_n) begin
  11. count <= 0;
  12. clk_1_3 <= 0;
  13. end
  14. else if(count == 1) begin
  15. clk_1_3 <= ~clk_1_3;
  16. count <= count + 1;
  17. end
  18. else if(count == 2) begin
  19. count <= 0;
  20. clk_1_3 <= ~clk_1_3;
  21. end
  22. else begin
  23. count <= count + 1;
  24. clk_1_3 <= clk_1_3;
  25. end
  26. end
  27. reg clk_1_3_r;
  28. //下降沿采样上述时钟
  29. always@(negedge clk or negedge rst_n) begin
  30. if(!rst_n) begin
  31. clk_1_3_r <= 0;
  32. end
  33. else begin
  34. clk_1_3_r <= clk_1_3;
  35. end
  36. end
  37. //产生分频时钟
  38. assign clk_divide = clk_1_3 | clk_1_3_r;
  39. endmodule

再给出testbench文件以及行为仿真时序图:


  
  1. `timescale 1ns / 1ps
  2. module clk_divide_tb(
  3. );
  4. reg clk;
  5. reg rst_n;
  6. wire clk_divide;
  7. initial begin
  8. clk = 0;
  9. forever
  10. #2 clk = ~clk;
  11. end
  12. initial begin
  13. rst_n = 0;
  14. #10
  15. rst_n = 1;
  16. end
  17. Freq_divide u0(
  18. .clk(clk),
  19. .rst_n(rst_n),
  20. .clk_divide(clk_divide)
  21. );
  22. endmodule

可见,功能完好;

再给出RTL电路图:

3分频占空比为50的分频器到底为止,下面是一个反面教材:


记住,这种写法万万不可!

对于奇分频电路,我的思路是:

以3分频为例,那么周期为原来的3倍,那么对原时钟clk,经历1.5个时钟上升沿,分频时钟翻转一次即可。

可是这里有一个问题就是如何实现1.5时钟上升沿呢?(上升沿和下降沿都算?)

我们先对原时钟取反,即相位相差180°,得到时钟clk_reverse;之后对时钟clk和clk_reverse的上升沿计数,计数到2,分频时钟翻转一次即可。

Verilog描述为:


  
  1. module Freq_divide(
  2. input clk,
  3. input rst_n,
  4. output reg clk_divide
  5. );
  6. wire clk_reverse;
  7. assign clk_reverse = ~clk;
  8. reg [3:0] count;
  9. always @ (posedge clk or posedge clk_reverse or negedge rst_n) begin
  10. if(!rst_n) begin
  11. count <= 0;
  12. end
  13. else if(count < 2) begin
  14. count <= count + 1;
  15. end
  16. else begin
  17. count <= 0;
  18. end
  19. end
  20. always @ (posedge clk or posedge clk_reverse or negedge rst_n) begin
  21. if(!rst_n) begin
  22. clk_divide <= 0;
  23. end
  24. else if(count == 2) begin
  25. clk_divide <= ~clk_divide;
  26. end
  27. else begin
  28. clk_divide <= clk_divide;
  29. end
  30. end
  31. endmodule

仿真文件:


  
  1. `timescale 1ns / 1ps
  2. module clk_divide_tb(
  3. );
  4. reg clk;
  5. reg rst_n;
  6. wire clk_divide;
  7. initial begin
  8. clk = 0;
  9. forever
  10. #2 clk = ~clk;
  11. end
  12. initial begin
  13. rst_n = 0;
  14. #10
  15. rst_n = 1;
  16. end
  17. Freq_divide u0(
  18. .clk(clk),
  19. .rst_n(rst_n),
  20. .clk_divide(clk_divide)
  21. );
  22. endmodule

行为仿真时序图:

可见,分频时钟clk_divide周期为原时钟clk的3倍,即完成了3分频的工作。

 

 

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

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

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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