整数倍分频
源代码在线查看: clk_div.v
module clk_div (
clk_in,
reset,
e,
div,
clk_out
);
input clk_in;
input reset;
input e;
input[31:0] div;
output clk_out;
wire[31:0] M;
wire clk_out_odd ;
reg clk_out_even;
// bit_of_N: N_odd的二进制位宽
reg [31:0] cnt_p; // 上升沿计数单位
reg [31:0] cnt_n; // 下降沿计数单位
reg [31:0] count;
reg clk_p; // 上升沿时钟
reg clk_n; // 下降沿时钟
assign M = (div>>1'b1);
assign clk_out_odd = (clk_n & clk_p); // 按位与(作用:掩码)
assign clk_out = (e==0) ? clk_in : div[0:0] ? (~clk_out_odd) : clk_out_even; // 按位与(作用:掩码)
// 上升沿计数器: 0~(div)
always @ (posedge clk_in or posedge reset)
begin
if (reset)
cnt_p else
begin
if (cnt_p == (div-32'b1))
cnt_p else
cnt_p end
end
// 生成上升沿时钟
// 0~(N>>1) ↑ -> 1; ((N/2)+1)~(div) ↑ -> 0
always @ (posedge clk_in or posedge reset)
begin
if (reset)
clk_p else
begin
if (cnt_p clk_p else
clk_p end
end
// 下降沿计数器: 0~(div)
always @ (negedge clk_in or posedge reset)
begin
if (reset)
cnt_n else
begin
if (cnt_n == (div-32'b1))
cnt_n else
cnt_n end
end
// 生成下降沿时钟
// 0~(N>>1) ↓ -> 1; ((N/2)+1)~(div) ↓ -> 0
always @ (negedge clk_in or posedge reset)
begin
if (reset)
clk_n else
begin
if (cnt_n clk_n else
clk_n end
end
//============================================================
always @(posedge clk_in or posedge reset)
begin
if(reset)
begin
count=32'd1;
clk_out_even=0;
end
else
begin
if(count==(div>>1'b1))
begin
count=32'd1;
clk_out_even=~clk_out_even;
end
else
count=count+32'd1;
end
end
endmodule