消除glitch的时钟切换
glitch的产生
在多时钟切换电路中,如果多个时钟频率之间可能彼此完全无关联,或者它们可以是彼此之间存在倍数的关系。在这两种情况下,都有可能在切换时在时钟线上产生毛刺(glitch),假如某个寄存器恰好捕获到该毛刺,则会引起整个系统数据混乱。
glitch产生主要是由于在时钟选择模块中多个时钟毫无关联,消除glitch需要做的是两件事:
1.异步信号的跨时钟域处理
2.对同步的信号做一个逻辑关系的处理
glitch消除电路
电路设计上,由于涉及到多时钟切换,必须有一个跨时钟域同步,在每个时钟域上分别打两拍,同时,由于假如我们在时钟为高电平将时钟进行切换,极大可能会产生毛刺,所以这里的电路运算结果要保证一个时钟域反馈到另一个时钟域的值为“0”,这样再通过最后的逻辑与运算“&”得出所选择的时钟信号。该电路逻辑运算设计思想就在于
" 0 | X=X "
" 1 | X=1 "
“1 & X=X”
这里用“1|X=1”来屏蔽clk的时钟变化,再用“1 & X=X”来选择输出时钟信号
当select =0时应选clk_b输出,select=1应选clk_a输出
当select=0时,输出应为clk_b,此时(!select)=1,在clk_a域做或运算,使屏蔽掉clk_a信号,此时q3
输出为1,在最后一级与运算运用“1 &X=X”得clk_b信号;当select=1时过程亦如此
电路对应RTL代码如下:
module clk_swich (
out_clk,
clk_a, clk_b, select
);
input clk_a;//输入时钟a
input clk_b;//输入时钟b
input select; //select =0选b,select=1选a
output out_clk;
wire out_clk;
reg q1,q2,q3,q4; //四个寄存器
wire or_one, or_two,or_three,or_four; //四个或门逻辑
always @ (posedge clk_a)
begin
if (clk_a == 1'b1)
begin
q1 <= q4;
q3 <= or_one;
end
end
always @ (posedge clk_b)
begin
if (clk_b == 1'b1)
begin
q2 <= q3;
q4 <= or_two;
end
end
assign or_one = (!q1) | (!select);
assign or_two = (!q2) | (select);
assign or_three = (q3) | (clk_a);
assign or_four = (q4) | (clk_b);
assign out_clk = or_three & or_four;
endmodule
仿真结果如下:
上面方法采用或门搭配select信号来实现时钟选择,在逻辑上也可以采用与门来运算,但采用与门做逻辑处理有一个缺点:需要较多的寄存器来进行打拍寄存,否则仍然会产生毛刺,产生这种原因是因为电路采用的逻辑运算“&”逻辑与“|”逻辑做信号选择时方式不同(“1| X=1”,“0 &X=0”),如下波形所示,and_4=q4 & clk_b ,select由0切换到1时,q4由1切换到0,以通过“0 & X =0”来屏蔽clk_b时钟,但在q4下降沿过程中,由于clk_b上升沿的到来,仍会引起“&”逻辑置1,导致在q4下降沿和clk_b上升沿交错的地方跳变为高电平而产生一个毛刺。
用与门搭建的时钟切换电路的如下:
RTL code如下:
module clk_switch_and (clk_a,
clk_b,
select,
rst_n,
out_clk);
input clk_a;
input clk_b;
input select;
input rst_n;
output out_clk;
reg q1,q2,q3,q4,q5,q6;
wire and_1,and_2,and_3,and_4;
always@(posedge clk_a or negedge rst_n)begin
if(!rst_n)begin
q1<=0;
q2<=0;
q5<=0;
end
else if(clk_a==1'b1)begin
q1<=q4;
q2<=and_1;
q5<=q2;
end
end
always@(posedge clk_b or negedge rst_n)begin
if(!rst_n)begin
q3<=0;
q4<=0;
q6<=0;
end
else if(clk_b==1'b1)begin
q3<=q2;
q4<=and_3;
q6<=q4;
end
end
assign and_1=(!q1) & select;
assign and_3=(!q3) & (!select);
assign and_2=clk_a & q5;
assign and_4=clk_b & q6;
assign out_clk=and_2 |and_4;
endmodule
下图中圈出来的部分就是glitch的产生,可见and_4仍会有毛刺,但经过寄存器打拍后,最后的输出时钟out_clk并没有glitch
在三级寄存器打拍下,仍有部分信号会产生glitch,对于通过与门实现的电路,由于是“1”—>“0”的变化,因而在该下降沿时刻与clk上升沿时刻会经逻辑运算会在内部信号产生一个glitch