verilog 时钟无缝切换电路
电路
基本原理是依靠两级缓冲完成时钟的切换
上图就是时钟无缝切换的一种电路图,通过两级dff级联加上反馈电路形成,分析它的工作过程,可以看到,当select由0→1时,
Q1在下图的clk0的这一时刻,会有1→0
紧接着 Q2在下图的clk0的这一时刻,会有1→0
所以Q2N就有0→1
在这之后,同样在clk1的这两个时刻,它的触发器会有变化,从0→1,
所以,在这之后的上升沿,时钟就切换到了clk1
所以切换过程,会有一个被切时钟的“上升沿+下降沿”,然后是切换后时钟的一个“上升沿+下降沿”,然后再切换完成。如下图,注意必须是完整的,只有下降沿是不行的
模块
module glitchfreeclkswitch(
input clk0,
input clk1,
input select,
output outclk
);
/* wire clk0; */
/* wire clk1; */
/* wire select; */
/* wire outclk; */
reg clk0q1=0;
reg clk0q2=0;
reg clk1q1=0;
reg clk1q2=0;
、、
[email protected](posedge clk0)
begin
clk0q1 <= (!select) & (!clk1q2);
end
[email protected](negedge clk0)
begin
clk0q2 <= (clk0q1);
end
[email protected](posedge clk1)
begin
clk1q1 <= (select) & (!clk0q2);
end
[email protected](negedge clk1)
begin
clk1q2 <= (clk1q1);
end
assign outclk = (clk1&clk1q2)|(clk0&clk0q2);
endmodule
Tb
module tb_clkswitc();
reg clk0;
reg clk1;
reg select;
wire outclk;
initial
begin
clk0 <= 0 ;
clk1 <= 0 ;
select <= 0 ;
end
always #5 clk0 <= ~clk0;
always #8 clk1 <= ~clk1;
initial
begin
#100 select <= 1;
#150 select <= 0;
#167 select <= 1;
end
glitchfreeclkswitch gc(.clk0(clk0),.clk1(clk1),.select(select),.outclk(outclk));
endmodule
仿真波形
Select从0→1 经过原时钟的一个上升沿+下降沿,再经过目标始终的一个上升沿+下降沿,时钟切换完成
Select从1→0,经过原时钟的一个上升沿+下降沿,再经过目标始终的一个上升沿+下降沿,时钟切换完成