题解 | #任意奇数倍时钟分频#
任意奇数倍时钟分频
http://www.nowcoder.com/practice/b058395d003344e0a74dd67e44a33fae
正确解法:使用一个计数器cnt1,当计数器计数到(n-1)/2=2和(n-1)=4时,发生跳变(即取反)。
思考,这和常规的不太一样,为什么不能在0和(n-1)/2之间进行计数跳变呢?防止不稳定吗
`timescale 1ns/1ns
module clk_divider
#(parameter dividor = 5)
( input clk_in,
input rst_n,
output clk_out
);
reg [$clog2(dividor):0] cnt1;
reg clk1, clk2;
always @ (posedge clk_in, negedge rst_n) begin
if(!rst_n) begin
cnt1 <= 0;
end
else if(cnt1 == dividor-1) begin
cnt1 <= 0;
end
else begin
cnt1 <= cnt1 + 1;
end
end
always @ (posedge clk_in, negedge rst_n)begin
if(!rst_n) begin
clk1 <= 1'b0;
end
else if(cnt1 == (dividor - 1)>>1) begin
clk1 <= ~clk1;
end
else if (cnt1 == (dividor-1)) begin
clk1 <= ~clk1;
end
else begin
clk1 <= clk1;
end
end
always @ (negedge clk_in, negedge rst_n)begin
if(!rst_n) begin
clk2 <= 1'b0;
end
else if(cnt1 == (dividor - 1)>>1) begin
clk2 <= ~clk2;
end
else if (cnt1 == (dividor-1)) begin
clk2 <= ~clk2;
end
else begin
clk2 <= clk2;
end
end
assign clk_out = clk1 || clk2;
endmodule
错误解法1:使用了两个计数器cnt1,cnt2.没有详细分析原因
`timescale 1ns/1ns
module clk_divider
#(parameter dividor = 5)
( input clk_in,
input rst_n,
output clk_out
);
reg [dividor:0] cnt1, cnt2;
reg clk1, clk2;
always @ (posedge clk_in, negedge rst_n)begin
if(!rst_n) begin
cnt1 <= 0;
clk1 <= 1'b0;
end
else if(cnt1 == 0) begin
clk1 <= ~clk1;
cnt1 <= cnt1 + 1;
end
else if(cnt1 == (dividor - 1)/2) begin
clk1 <= ~clk1;
cnt1 <= cnt1 + 1;
end
else if (cnt1 == (dividor-1)) begin
cnt1 <= 0;
end
else begin
cnt1 <= cnt1 + 1;
end
end
always @ (negedge clk_in, negedge rst_n)begin
if(!rst_n) begin
cnt2 <= 0;
clk2 <= 1'b0;
end
else if(cnt2 == 0) begin
clk2 <= ~clk1;
cnt2 <= cnt2 + 1;
end
else if(cnt1 == (dividor - 1)/2) begin
clk2 <= ~clk2;
cnt2 <= cnt2 + 1;
end
else if (cnt2 == (dividor-1)) begin
cnt2 <= 0;
end
else begin
cnt2 <= cnt2 + 1;
end
end
assign clk_out = clk1 | clk2;
endmodule