天天看点

时钟的奇数分频

在时钟分频技术中,对于偶数倍分频是比较好做的,实现2N倍的分频,只需计数到N,然后让时钟进行翻转即可。

但是在奇数倍分频中,我们总会面0.5的关系。例如实现5倍分频,也就是计数到2.5,然后时钟进行翻转。可是2.5是没有办法计数的。因此我们就得另寻它法了。

假如我们有两个时钟,clk1和clk2。如果时钟clk1的高电平持续2个周期,而clk2的低电平持续3个时钟周期,并且两者的时间错开半个周期,将两者进行或运算就ok了。

如下图所示:

时钟的奇数分频

其实主要的算法就是在不同的时钟沿进行技术,目的就是为了找到那半个周期。

需要有两个计数器cnt1和cnt2:如果是5分频则:cnt1=5/2=2(从0到2共3个clk周期),cnt2=5-1=4(从2到4共2个clk周期);

如果是7分频则:cnt1=7/2=3(从0到3共4个clk周期),cnt2=7-1=6(从3到6共3个clk周期);

如此就可以进行奇数倍的分频了!

`timescale 1ns / 1ps

//

// Company: 

// Engineer: 

// 

// Create Date:    08:21:02 07/15/2015 

// Design Name: 

// Module Name:    CLK_DCM 

// Project Name:  

// Target Devices: 

// Tool versions: 

// Description:  实现时钟的奇数分频;此工程实现5分频,此时5/2=2(0--2);5-1=4(2--4);3-0.5=2+0.5

//

// Author: ganggang

//

//

module CLK_DCM( 

//---input pin----

clk,rst_n,

//---output pin---

clk_out

    );

//--------------------------------

//parameter declation

//--------------------------------

parameter DLY = 1;

//---------------------------------

//input declation

//---------------------------------

input clk; //100MHZ

input rst_n; //active low

//----------------------------------

//output declation

//----------------------------------

output clk_out;

//----------------------------------

//wire or reg declation

//----------------------------------

reg clk_out;

reg[2:0] cnt1; 

reg[2:0] cnt2; 

reg clk1;

reg clk2;

///

//

//LOGIC

//

//

// posedge clk

always @(posedge clk or negedge rst_n)

begin

if(rst_n==1'b0)

begin

cnt1 <=#DLY 2'd0;

clk1 <=#DLY 1'b0;

end

else 

begin

if(cnt1==3'd4)

begin

cnt1 <=#DLY 3'd0;

clk1 <=#DLY ~clk1;

end

else

begin

if(cnt1==3'd2)

begin

clk1 <=#DLY ~clk1;

cnt1 <= #DLY cnt1 +1'b1;

end

else

begin

clk1 <= #DLY clk1;

cnt1 <=#DLY cnt1 +1'b1;

end

end

end

end

//negedge clk

always @(negedge clk or negedge rst_n)

begin

if(rst_n==1'b0)

begin

cnt2 <=#DLY 3'd0;

clk2 <=#DLY 1'b0;

end

else

begin

if(cnt2==3'd4)

begin

clk2 <=#DLY ~clk2;

cnt2 <=#DLY 3'd0;

end

else

begin

if(cnt2 == 3'd2)

begin

clk2 <=#DLY ~clk2;

cnt2 <=#DLY cnt2 +1'b1;

end

else

begin

clk2 <=#DLY clk2;

cnt2 <=#DLY cnt2 +1'b1;

end

end

end

end

always @(clk1 or clk2 )

begin

clk_out <= clk1 ||clk2;

end

endmodule

继续阅读