天天看点

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提供。