verilog时钟分频设计(整合模块)

这里对之前写的时钟分频模块做了整合,整合为完整的时钟分频模块,可以进行偶分频、奇分频和半分频。

接口如下:
clk:输入时钟
rst:复位信号
adv_select:分频类型选择,0->偶分频,1->奇分频,2->半分频
M:分频系数,在半分频情况下为向下取整(4.5分频->M=4)
clk_out:输出时钟

通过testbench进行了仿真,分别仿了4分频、9分频和5.5分频
	initial begin  
		adv_select = 2'b00;
		M = 4;
		#1086 adv_select = 2'b01;
		M = 9;
		#1086 adv_select = 2'b10;
		M = 5;
	end

结果如图所示:
verilog时钟分频设计(整合模块)_第1张图片

代码如下:
module work(
	clk
	,rst
	,adv_select
	,M
	,clk_out
	);
input clk, rst;
input [1:0]adv_select;  //0->even 1->odd 2->half
input [31:0]M;
output clk_out;

wire clk_out_even, clk_out_odd, clk_out_half;

assign clk_out = (adv_select == 0) ? clk_out_even : 
												 (adv_select == 1) ? clk_out_odd : 
																		   (adv_select == 2) ? clk_out_half : 0;
wire clk_even, clk_odd, clk_half;
assign clk_even = (adv_select == 0) ? clk : 0;
assign clk_odd  = (adv_select == 1) ? clk : 0;
assign clk_half = (adv_select == 2) ? clk : 0;

 time_adv_even u0
		(
    	.clk 		(clk_even)
    	,.rst 		(rst)
		,.M		(M)
    	,.clk_out 	(clk_out_even)
    	);
		
time_adv_odd u1
		(
    	.clk 		(clk_odd)
    	,.rst 		(rst)
		,.M		(M)
    	,.clk_out 	(clk_out_odd)
    	);
		
time_adv_half u2
		(
    	.clk 		(clk_half)
    	,.rst 		(rst)
		,.M		(M)
    	,.clk_out 	(clk_out_half)
    	);

endmodulemodule time_adv_even
(
    input clk,
    input rst,
	 input [31:0]M,
    output reg clk_out
    );

wire [31:0]N;
assign N = M>>1;

reg [7:0]counter;
always @(posedge clk or posedge rst) begin
	if (rst) begin
		// reset
		counter <= 0;
	end
	else if (counter == N-1) begin
		counter <= 0;
	end
	else begin
		counter <= counter + 1;
	end
end

always @(posedge clk or posedge rst) begin
	if (rst) begin
		// reset
		clk_out <= 0;
	end
	else if (counter == N-1) begin
		clk_out <= !clk_out;
	end
end
endmodulemodule time_adv_odd (
    input clk,
    input rst,
	 input [31:0]M,
    output clk_out
    );

wire [31:0]N;
assign N = (M-1)>>1;

reg [7:0]counter;
always @(posedge clk or posedge rst) begin
	if (rst) begin
		// reset
		counter <= 0;
	end
	else if (counter == (N << 1)) begin
		counter <= 0;
	end
	else begin
		counter <= counter + 1;
	end
end

reg clk_out1;
always @(posedge clk or posedge rst) begin
	if (rst) begin
		// reset
		clk_out1 <= 0;
	end
	else if (counter == N-1) begin
		clk_out1 <= !clk_out1;
	end
	else if (counter == (N << 1)) begin
		clk_out1 <= !clk_out1;
	end
end

reg clk_out2;
always @(negedge clk or posedge rst) begin
	if (rst) begin
		// reset
		clk_out2 <= 0;
	end
	else if (counter == N-1) begin
		clk_out2 <= !clk_out2;
	end
	else if (counter == (N << 1)) begin
		clk_out2 <= !clk_out2;
	end
end

assign clk_out = clk_out1 & clk_out2;
endmodulemodule time_adv_half(
    input clk,
    input rst,
	 input [31:0]M,
    output reg clk_out
    );

wire clk_cnt;
assign clk_cnt = (clk_vld) ? !clk : clk;

reg [7:0]counter;
always @(posedge clk_cnt or posedge rst) begin
	if (rst) begin
		// reset
		counter <= 0;
	end
	else if (counter == M) begin
		counter <= 0;
	end
	else begin
		counter <= counter + 1;
	end
end

reg clk_vld;
always @(posedge clk_out or posedge rst) begin
	if (rst) begin
		// reset
		clk_vld <= 0;
	end
	else begin
		clk_vld <= !clk_vld;
	end
end

always @(posedge clk_cnt or posedge rst) begin
	if (rst) begin
		// reset
		clk_out <= 0;
	end
	else if (counter == M-1) begin
		clk_out <= !clk_out;
	end
	else if (counter == M) begin
		clk_out <= !clk_out;
	end
end
endmodulemodule testbench;

	// Inputs
	reg clk;
	reg rst;
	reg [1:0] adv_select;
	integer M;

	// Outputs
	wire clk_out;

	// Instantiate the Unit Under Test (UUT)
	work uut(
		.clk(clk), 
		.rst(rst), 
		.adv_select(adv_select), 
		.M(M),
		.clk_out(clk_out)
	);

	initial begin  
		clk = 1'b0;  
		forever #10 clk = ~clk;  
	end
	
	initial begin  
		rst = 1'b0;  
		#2 rst = 1'b1; 
		#9 rst = 1'b0; 
	end
	
	initial begin  
		adv_select = 2'b00;
		M = 4;
		#1086 adv_select = 2'b01;
		M = 9;
		#1086 adv_select = 2'b10;
		M = 5;
	end
      
endmodule

你可能感兴趣的:(芯片前端设计,verilog)