题解 | #任意奇数倍时钟分频#
任意奇数倍时钟分频
https://www.nowcoder.com/practice/b058395d003344e0a74dd67e44a33fae
以5分频为例,实现一个计数值为5的计数器 (0-4),对原始时钟10分频得到两种时钟:一个传统的上升沿计数10分频,计数达4时切换;一个下降沿计数,在计数值为2 (5>>1或5//2)时切换。原理是下降沿采样2的点正好是需要的时钟的中间边沿,然后将两个时钟异或。也可以理解为原始时钟10分频后,左移5个半周期,然后异或得到。
`timescale 1ns/1ns
module clk_divider
#(parameter dividor = 5)
( input clk_in,
input rst_n,
output clk_out
);
reg clk1, clk2;
reg [$clog2(dividor)-1:0] cnt1;
always @(posedge clk_in, negedge rst_n) begin
if (!rst_n) begin
cnt1 <= 'd0;
end
else if (cnt1==dividor-1'b1) begin
cnt1 <= 'd0;
end
else
cnt1 <= cnt1 + 1'b1;
end
always @(posedge clk_in, negedge rst_n) begin
if (!rst_n) begin
clk1 <= 1'b0;
end
else if (cnt1==(dividor-1'b1)) begin
clk1 <= ~clk1;
end
else
clk1 <= clk1;
end
always @(negedge clk_in, negedge rst_n) begin
if (!rst_n) begin
clk2 <= 1'b0;
end
else if (cnt1==(dividor>>1)) begin
clk2 <= ~clk2;
end
else
clk2 <= clk2;
end
assign clk_out = clk1 ^ clk2;
endmodule