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

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

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


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

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

画了个草图:

给出Verilog HDL描述:


      module Freq_divide(
      	input clk,
      	input rst_n,
      	output clk_divide
       );
     	//先写一个占空比为1/3的分频时钟
      	reg clk_1_3;
      	reg [2:0] count;
      	always@(posedge clk or negedge rst_n) begin
     		if(!rst_n) begin
      			count <= 0;
      			clk_1_3 <= 0;
     		end
     		else if(count == 1) begin
      			clk_1_3 <= ~clk_1_3;
      			count <= count + 1;
     		end
     		else if(count == 2) begin
      			count <= 0;
      			clk_1_3 <= ~clk_1_3;
     		end
     		else begin
      			count <= count + 1;
      			clk_1_3 <= clk_1_3;
     		end
     	end
      	reg clk_1_3_r;
     	//下降沿采样上述时钟
      	always@(negedge clk or negedge rst_n) begin
     		if(!rst_n) begin
      			clk_1_3_r <= 0;
     		end
     		else begin
      			clk_1_3_r <= clk_1_3;
     		end
     	end
     	//产生分频时钟
      	assign clk_divide = clk_1_3 | clk_1_3_r;
      endmodule
  
 

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


      `timescale 1ns / 1ps
      module clk_divide_tb(
      );
     	reg clk;
     	reg rst_n;
     	wire clk_divide;
     	initial begin
     		clk = 0;
     		forever
       #2 clk = ~clk;
     	end
     	initial begin
     		rst_n = 0;
      		#10
     		rst_n = 1;
     	end
     	Freq_divide u0(
     	.clk(clk),
     	.rst_n(rst_n),
     	.clk_divide(clk_divide)
      );
      endmodule
  
 

可见,功能完好;

再给出RTL电路图:

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


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

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

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

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

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

Verilog描述为:


      module Freq_divide(
      	input clk,
      	input rst_n,
      	output reg clk_divide
       );
      	wire clk_reverse;
      	assign clk_reverse = ~clk;
      	reg [3:0] count;
      	always @ (posedge clk or posedge clk_reverse or negedge rst_n) begin
     		if(!rst_n) begin
     			count <= 0;
     		end
     		else if(count < 2) begin
     			count <= count + 1;
     		end
     		else begin
     			count <= 0;
     		end
     	end
     	always @ (posedge clk or posedge clk_reverse or negedge rst_n) begin
     		if(!rst_n) begin
      			clk_divide <= 0;
     		end
     		else if(count == 2) begin
      			clk_divide <= ~clk_divide;
     		end
     		else begin
      			clk_divide <= clk_divide;
     		end
     	end
      endmodule
  
 

仿真文件:


      `timescale 1ns / 1ps
      module clk_divide_tb(
      );
     	reg clk;
     	reg rst_n;
     	wire clk_divide;
     	initial begin
     		clk = 0;
     		forever
       #2 clk = ~clk;
     	end
     	initial begin
     		rst_n = 0;
      		#10
     		rst_n = 1;
     	end
     	Freq_divide u0(
     	.clk(clk),
     	.rst_n(rst_n),
     	.clk_divide(clk_divide)
      );
      endmodule
  
 

行为仿真时序图:

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

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

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

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

作者其他文章

评论(0

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

    全部回复

    上滑加载中

    设置昵称

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

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

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