我是靠谱客的博主 矮小柚子,最近开发中收集的这篇文章主要介绍时钟分频,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

时钟分频器

  • 偶数分频
  • 奇数分频(占空比50%)
  • 非整数分频(占空比也非50%)

本文参考《硬件架构的艺术》,主要介绍偶数分频时钟,计数分频(3,5分频),以及非整数分频(4.5分频)

1、偶数分频

偶数分频比较容易实现。实现一个N分频(N为偶数),每隔N/2个源时钟,分频时钟信号翻转一次。比如N=6时,在计数器等于2时,源时钟上升沿使信号翻转。

 

module even_clk_div#(
            parameter N=8
)
(
            input         sys_clk,
            input         rst_n,
            output reg    div_clk
);

//===================================
    reg [15:0]clk_cnt;
    
    always@(posedge sys_clk,negedge rst_n)begin
        if(~rst_n)
            clk_cnt <= 'h0;
        else if(clk_cnt == (N/2-1))
            clk_cnt <= 'h0;
        else
            clk_cnt <= clk_cnt + 1'b1;
    end

    always@(posedge sys_clk,negedge rst_n)begin
        if(~rst_n)
            div_clk <= 'b0;
        else if(clk_cnt == (N/2-1))
            div_clk <= ~div_clk;
    end

endmodule

仿真波形图如下:

图1、8分频波形

2、奇数分频

奇数分频要复杂一些,但原理是一样的。N(奇数),即在2N个时钟周期内,分频信号翻转四次。以N=3为例,如图2所示

图2、3分频

先产生一个6分频时钟div1,然后在将div1移动270度相位,得到div2时钟,最后将div1与div2进行异或,得到3分频时钟。

设计代码如下:

`timescale 1ns/1ns

module odd_clk_div#(
			parameter N=3
)
(
			input 		sys_clk,
			input 		rst_n,
			output		div_clk 		
);

	reg [15:0] div_cnt;
	always@(posedge sys_clk,negedge rst_n)begin
		if(~rst_n)
			div_cnt <= 'h0;
		else if(div_cnt == 2*N-1)
			div_cnt <= 'h0;
		else
			div_cnt <= div_cnt + 1'b1;
	end
	
	reg 	div1;
	reg		div2;
	always@(posedge sys_clk,negedge rst_n)begin
		if(~rst_n)
			div1 <= 1'b0;
		else if((div_cnt == 2*N-1)||(div_cnt==N-1))
			div1=~div1;
	end
	
	always@(negedge sys_clk,negedge rst_n)begin
		if(~rst_n)
			div2 <= 1'b0;
		else if(div_cnt==(N-1)/2||div_cnt==(3*N-1)/2)
			div2=~div2;
	end
	
	assign div_clk = div1^div2;
	
endmodule
图3、3分频
图4、5分频

 3、非整数分频(占空比非50%)

经常会使用N分频电路来产生于参考时钟不同步的时钟。设计N为非整数的分频电路并不想看起来那样难。对1.5分频,简单来说,就是每三个参考时钟包含两个对称的脉冲。

本节介绍一种不产生毛刺的分频方法。

使用4.5倍分频为例子,即每9个参考时钟包含2个对称脉冲。

步骤1:使用复位值为000000001的9位移位寄存器,可以在每个时钟上升沿使移位寄存器循环左移一位。

步骤2:要产生第1个脉冲,必须在半周期是移动第1位并将第1位与第2位进行或操作。

步骤3:要产生第2个脉冲,第5位和第6位必须在半周期是移动并与原始第6位进行或操作。

图5、4.5倍分频实现

 代码如下:

`timescale 1ns/1ns

module Nointer_clk_div#(
			parameter Double_N=4.5
)(
			input 		sys_clk,
			input		rst_n,
			output		div_clk
);

	//localparam	Double_N=2*N;
	
	reg	[Double_N-1:0] count;
	
	always@(posedge sys_clk,negedge rst_n)begin
		if(~rst_n)
			count <= 'h1;
		else if(count[Double_N-1]==1)
			count <= 'h1;
		else
			count <= count<<1;
	end
	
	reg	div1,div2,div3;
	always@(negedge sys_clk,negedge rst_n)begin
		if(~rst_n)
			div1 <= 1'b0;
		else if(count[0]==1)
			div1 <= ~div1;
		else if(count[1]==1)
			div1 <= ~div1;
	end
	always@(negedge sys_clk,negedge rst_n)begin
		if(~rst_n)
			div2 <= 1'b0;
		else if(count[4]==1)
			div2 <= ~div2;
		else if(count[5]==1)
			div2 <= ~div2;
	end
	always@(negedge sys_clk,negedge rst_n)begin
		if(~rst_n)
			div3 <= 1'b0;
		else if(count[5]==1)
			div3 <= ~div3;
		else if(count[6]==1)
			div3 <= ~div3;
	end
	assign div_clk = (count[0]||count[1]||div1)||(div2||div3);
	
endmodule
图6、4.5分频

 

最后

以上就是矮小柚子为你收集整理的时钟分频的全部内容,希望文章能够帮你解决时钟分频所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部