Verilog筆記——奇數分頻和小數分頻

1.偶數分頻

簡單,只是注意時鐘翻轉的條件是(N/2)還是(N/2)-1,非阻塞賦值在下一個時鐘纔會更新值。

2.奇數分頻

奇數分頻比偶數分頻複雜一些,當不要求分頻的佔空比時,對輸入時鐘clk上升沿計數,可以設置兩個計數的翻轉點,一個是(N-1)/2,一個是(N-1),計數到(N-1)時輸出時鐘翻轉且將計數器清零,假設計數器計數0~(N-1)/2區間輸出低電平,則輸出時鐘的低電平有(N-1)/2 + 1個clk週期,高電平的計數是(N-1)/2+1 ~ (N-1),共(N-1)/2個clk週期,可見不是50%佔空比。
當要求佔空比爲50%時,對輸入時鐘clk的上升沿下降沿分別計數,根據兩個計數器得到兩個錯位輸出的時鐘,將兩個時鐘做“或”運算,可以彌補相差的時鐘,達到50%佔空比。
在這裏插入圖片描述
以7分頻爲例,代碼如下:

/********************************************
		計數器實現 7 分頻
*********************************************/
module Odd_Divider(
	input clk,
	input rst_n,
	output clk_divider
);

reg [2:0] count_p;	//上升沿計數
reg [2:0] count_n;	//下降沿計數
reg clk_p;				//上升沿分頻
reg clk_n;				//下降沿分頻

//上升沿計數
always @ ( posedge clk or negedge rst_n )
begin 
	if( !rst_n ) 
		count_p <= 3'b0;
	else if( count_p == 3'd6 ) 
		count_p <= 3'b0;
	else  
		count_p <= count_p + 1'b1;
end

//上升沿分頻
always  @ ( posedge clk or negedge rst_n )
begin 
	if( !rst_n ) begin 
		clk_p <= 1'b0;
	end 
	else begin 
		if( count_p == 3'd3 || count_p == 3'd6 ) begin 
			clk_p <= ~clk_p;
		end
	end
end 

//下降沿計數
always @ ( negedge clk or negedge rst_n )
begin 
	if( !rst_n ) 
		count_n <= 3'b0;
	else if( count_n == 3'd6 ) 
		count_n <= 3'b0;
	else  
		count_n <= count_n + 1'b1;
end

//下降沿分頻
always  @ ( negedge clk or negedge rst_n )
begin 
	if( !rst_n ) begin 
		clk_n <= 1'b0;
	end 
	else begin 
		if( count_n == 3'd3 || count_n == 3'd6 ) begin 
			clk_n <= ~clk_n;
		end
	end
end 

assign clk_divider = clk_p | clk_n;

endmodule

仿真如下:
在這裏插入圖片描述
在這裏插入圖片描述

3.小數分頻

N+0.5分頻,如N=3時進行3.5分頻。
先將clk時鐘週期的一半記作clk_half,即一個高電平或一個低電平時間。
對2*(N+0.5) = 2N+1,這個數一定是奇數,按照奇數分頻的思路做,也取clk_p和clk_n,但是計數值不一樣,一個計數N個clk時鐘週期(2N個clk_half週期),一個計數2N+2個clk_half,且兩者的位置關係如圖所示,這樣,兩者做“與”運算,則所得信號一個週期的高低電平共有2N+1個clk_half週期,即(N+0.5)個clk週期
在這裏插入圖片描述

/********************************************
		計數器實現 3.5 分頻,N=3,2N=6
*********************************************/
module Npoint5_Divider(
	input clk,
	input rst_n,
	output clk_divider
);

reg [2:0] count_p;	//上升沿計數
reg [2:0] count_n;	//下降沿計數
reg clk_p;				//上升沿分頻
reg clk_n;				//下降沿分頻

//上升沿計數
always @ ( posedge clk or negedge rst_n )
begin 
	if( !rst_n ) 
		count_p <= 3'b0;
	else if( count_p == 3'd6 ) 
		count_p <= 3'b0;
	else  
		count_p <= count_p + 1'b1;
end

//上升沿分頻
always  @ ( posedge clk or negedge rst_n )
begin 
	if( !rst_n ) begin 
		clk_p <= 1'b0;
	end 
	else begin 
		if( count_p == 3'd4 || count_p == 3'd0 ) begin 
			clk_p <= ~clk_p;
		end
	end
end 

//下降沿計數
always @ ( negedge clk or negedge rst_n )
begin 
	if( !rst_n ) 
		count_n <= 3'b0;
	else if( count_n == 3'd6 ) 
		count_n <= 3'b0;
	else  
		count_n <= count_n + 1'b1;
end

//下降沿分頻
always  @ ( negedge clk or negedge rst_n )
begin 
	if( !rst_n ) begin 
		clk_n <= 1'b1;
	end 
	else begin 
		if( count_n == 3'd4 || count_n == 3'd1 ) begin 
			clk_n <= ~clk_n;
		end
	end
end 

assign clk_divider = clk_p & clk_n;

endmodule

仿真結果:
在這裏插入圖片描述

歡迎關注:FPGA探索者
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章