天天看點

時鐘的奇數分頻

在時鐘分頻技術中,對于偶數倍分頻是比較好做的,實作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

繼續閱讀