天天看點

Verilog 時鐘分頻

看了網上的很多例子,有很多的成長。記錄下來。

1.二分頻

module sp6(
    input ext_clk_25m,
    input ext_rst_n,
    output  reg  clk_12m5
    );
always @(posedge ext_clk_25m or negedge ext_rst_n)
		if(!ext_rst_n)
			clk_12m5 <= 1'b0;
		else
			clk_12m5 <= ~clk_12m5;

endmodule
           

2.偶數分頻

module spfen(
		input 			sclk,
		input 			rst_n,
		output	reg	clk_div
    );
reg [3:0]	cnt;
parameter 	Num_Div = 6;
always @(posedge sclk or negedge rst_n)
	if(!rst_n)
		cnt<=1'b0;
	else if(cnt<Num_Div/2-1)
		cnt<=cnt+1'b1;
	else 
		cnt<=1'b0;
		
always @(posedge sclk or negedge rst_n)
	if(!rst_n)
		clk_div<=1'b0;
	else if(cnt<Num_Div/2-1)
		clk_div<=clk_div;
	else 
		clk_div<=~clk_div;
		


endmodule
           

3.奇數分頻

module single_div(
	input 			sclk,
	input				rst_n,
	output			clk_div
    );
reg	[2:0]	cnt_p;
reg	[2:0] cnt_n;
reg	clk_p,clk_n;
parameter	Clk_Div = 5;
always @(posedge sclk or negedge rst_n)
	if(!rst_n)
		cnt_p <= 1'b0;
	else if(cnt_p == (Clk_Div-1))
		cnt_p <= 1'b0;
		
	else 
		cnt_p <= cnt_p+1'b1;
		
always @(negedge sclk or negedge rst_n)
	if(!rst_n)
		cnt_n <= 1'b0;
	else if(cnt_n == (Clk_Div-1))
		cnt_n<=1'b0;
	else
		cnt_n <= cnt_n+1'b1;
		
always @(posedge sclk or negedge rst_n)
	if(!rst_n)
		clk_p <= 1'b1;
	else if(cnt_p == (Clk_Div-1)/2-1)
		clk_p <= ~clk_p;
	else if(cnt_p == (Clk_Div-1))
		clk_p <= ~clk_p;	
		
always @(negedge sclk or negedge rst_n)
	if(!rst_n)
		clk_n <= 1'b1;
	else if(cnt_n == (Clk_Div-1)/2-1)
		clk_n <= ~clk_n;
	else if(cnt_n == (Clk_Div-1))
		clk_n <= ~clk_n;
		
 //always @(posedge sclk or negedge rst_n)
//	if(!rst_n)
//		clk_div <= 1'b0;
//	else 
//		clk_div <= clk_p | clk_n;
assign  clk_div = clk_p | clk_n;
endmodule
           

但是值得注意的是:當把output的類型改成reg 類型的時候,用always塊指派,得到的時鐘并不理想,剛入門還沒搞明白,希望高手能在評論區指點。

4.半整數分頻

module half_divider(
input 				sclk,
input					rst_n,
output	reg		clk_div

    );
reg	[4:0]		cnt;
wire				clk1;
reg				flag;
parameter  	N = 3;//N-0.5分頻

always @(posedge clk1 or negedge rst_n)
		if(!rst_n)
			flag <= 1'b0;
		else if(cnt==(N-1)/2)
			flag <= ~flag;
			
assign clk1 = flag?(~sclk):sclk;

always @(posedge clk1 or negedge rst_n)
		if(!rst_n)
			cnt <= 1'b0;
		else if(cnt == N-1)
			cnt <= 1'b0;
		else
			cnt <= cnt+1'b1;
	
always @(posedge clk1 or negedge rst_n)
		if(!rst_n)
			clk_div <= 1'b0;
		else if(cnt == 5'd0)
			clk_div <= 1'b0;
		else if(cnt == (N+1)/2)
			clk_div <= ~clk_div;
		else
			clk_div <= clk_div;
	


endmodule
           

5.任意整數分頻

module random_divider(
input 				sclk,
input					rst_n,
output				clk_p,
output				clk_n,
output				clk_div
    );
	 
reg 					clk1,clk2;
reg	[3:0]			cnt_n,cnt_p;
parameter	N = 5;

always @(posedge sclk or negedge rst_n)
	if(!rst_n)
		cnt_p <= 1'b0;
	else if(cnt_p == (N/2-1))
		cnt_p <= 1'b0;
	else
		cnt_p <= cnt_p + 1'b1;
		
always @(negedge sclk or negedge rst_n)
	if(!rst_n)
		cnt_n <= 1'b0;
	else if(cnt_n == (N/2-1))
		cnt_n <= 1'b0;
	else
		cnt_n <= cnt_n + 1'b1;
always @(posedge sclk or negedge rst_n)
	if(!rst_n)
		clk1 <= 1'b0;
	else if(cnt_p < (N/2-1))
		clk1 <= clk1;
	else 
		clk1 <= ~clk1;
	
	
		
always @(negedge sclk or negedge rst_n)
	if(!rst_n)
		clk2 <= 1'b0;
	else if(cnt_n < (N/2-1))
		clk2 <= clk2;
	else 
		clk2 <= ~clk2;

	
		
//always @(posedge sclk or negedge rst_n)
//	if(!rst_n)
//	clk_div <= 1'b0;
//	else 
//		clk_div<=(N%2)?(clk1|clk2):clk1;

assign clk_div = (N==1)?sclk:(N[0])?(clk1 | clk2):clk1;
assign clk_p = clk1;
assign clk_n = clk2;

endmodule
           

不過這塊的代碼還有待改善, 我想和奇數分頻一樣實作占空比為50%的時鐘,可是并沒有得到。會繼續解決的,還是希望有路過的大牛能提點一二。這塊的實作思路由https://blog.csdn.net/u014183456/article/details/76695465提供。