无毛刺时钟切换技术解析

无毛刺时钟切换电路,又叫glitch free电路,时钟无缝切换电路。在芯片运行时需要通过门控切换时钟源,其产生的毛刺现象可能会导致驱动电路产生亚稳态,且对于不相关时钟的切换也有可能会产生门控电路的亚稳态问题。注意不要和跨时钟处理和门控时钟弄混。

1.为什么切换的时候会产生毛刺?

先来看一个简单的时钟切换电路:是由一个两个与门和一个或门组成的MUX。

当select从0变到1时,时钟从clk0变到clk1,如果select切换的时机不对,则会引起一个时间很短的尖脉冲, 会导致产生了两个占空比既不为CLK0又不为CLK1的时钟,可以看作是对输出时钟的截断,也就是输出时钟不完整。导致这种情况的原因是因为在clk为高电平的时候(只要两个之中的一个为高电平就算)进行了时钟切换,导致输出高电平周期不完整,如果输出的时钟产生了该毛刺,并且驱动了一个电路,将很有可能因为不满足建立时间或者保持时间而发生亚稳态现象。

因此解决毛刺的办法就是在两个时钟都为低电平的时候进行切换。

 2.如何解决时钟毛刺现象

时钟切换有两种情况:一是两个时钟的频率有倍数关系。二是两个时钟不相关。

1)两个时钟的频率相关:在每个时钟源选择路径上插入一个下降沿有效的D触发器。

 利用时钟的下降沿寄存选择信号,保证了选择信号不会在两个时钟高电平的时候进行跳变,防止输出时钟被截断。

 2)两个时钟的频率不相关:异步行为可能来自于select,因此在每个时钟源选择路径上插入一个上升沿有效的D触发器来避免亚稳态。

 利用上升沿触发的寄存器(可以使用两级),寄存选择信号,降低由于异步select导致的亚稳态,同时配合下降沿触发的寄存器,使切换都发生在时钟低电平处。降低毛刺产生的概率。

3.双通道无毛刺时钟切换电路与任意通道无毛刺切换代码

1.双通道无毛刺时钟切换

 亚稳态处理采用了打两拍的方式,所以每一条路径上是两个上升沿的D触发器。

module double_clock_glitch_free(clk0,clk1,sel,rst_n,out_clk);
  input clk0;
  input clk1;
  input sel;
  input rst_n;
 
  output out_clk;

  reg sel0_r,sel0_rr,sel0_rrr;
  reg sel1_r,sel1_rr,sel1_rrr;

//一共两条路径,一个路径上有两个always块。一共四个always块 
always@(posedge clk0 or negedge rst_n)begin
  if(!rst_n)begin
     sel0_r<=0;
     sel0_rr<=0;
   end
   else begin
     sel0_r<=~sel&(~sel1_rrr);
     sel0_rr<=sel0_r;
   end
end
always@(negedge clk0 or negedge rst_n)begin
   if(!rst_n)begin
      sel0_rrr<=0;
   end
   else begin
      sel0_rrr<=sel0_rr;
   end
end

always@(posedge clk1 or negedge rst_n)begin
  if(!rst_n)begin
     sel1_r<=0;
     sel1_rr<=0;
   end
   else begin
     sel1_r<=sel&(~sel0_rrr);
     sel1_rr<=sel0_r;
   end
end
always@(negedge clk1 or negedge rst_n)begin
   if(!rst_n)begin
      sel1_rrr<=0;
   end
   else begin
      sel1_rrr<=sel0_rr;
   end
end
assign out_clk=(sel0_rrr&clk0)|(sel1_rrr&clk1);
endmodule

2.任意通道无毛刺时钟切换电路

对于任意通道的时钟切换电路都可以套用上述电路结构:上升沿触发的二级触发器以及下降沿触发的触发器,分别用于防止亚稳态和防止毛刺输出。任意通道的无毛刺切换电路代码如下:主要关注有效选择信号如何生成:输入选择信号&所有其他寄存选择信号的或非。

module gitch_free (clk,select,clk_out);
parameter NUM_CLOCKS=4;

input [NUM_CLOCKS-1:0] clk;
input [NUM_CLOCKS-1:0] select; //独热码
output clk_out;

wire [NUM_CLOCKS-1:0] gate_clk;
reg [NUM_CLOCKS-1:0] sel_r0;
reg [NUM_CLOCKS-1:0] sel_r1;
reg [NUM_CLOCKS-1:0] sel_r2;


//定义genvar,作为generate种的循环变量。
genvar i;

generate
//generate语句中定义的for语句,必须要有begin,为后续增加标签做准备。
for(i=0,i<NUM_CLOCKS,i++)
   begin:loop0
     wire [NUM_CLOCKS-1:0] temp_mask;
     assign temp_mask = {NUM_CLOCKS{1'b1}}^(1<<i);
     assign qualified_sel[i] = sel[i]&(~|(sel_r2&temp_mask));//有效输入信号,其他位的sel_r2只要有一个输出为1,就会阻塞第i位的输出,相当于将其他所有寄存器输出位或非。sel_r2&temp_mask表示第i位的输出保持为0,其他位的输出不变。
     assign gate_clk[i]=clk[i]&sel_r2[i];//将所有处理过的选择信号与时钟相与
     
     //上升沿触发寄存有效选择信号,防止亚稳态,此处采用两级寄存。 
     always@(posedge clk[i])begin
       sel_r0[i]<=qualified_sel[i];
       sel_r1[i]<=sel_r1[i];
     end

     //下降沿触发,消除毛刺
     always@(negedge clk[i])begin
       sel_r2[i]<=sel_r1[i];
     end  
    
end
endgenerate

assign clk_out=|gate_clk;//将所有与门输出信号相或,得到输出信号

endmodule
     

参考:FPGA/数字IC秋招笔试面试031——Glitch free 无毛刺时钟切换电路、时钟无缝切换、时钟无毛刺切换技术【2022届】 – 知乎

 【Verilog HDL 训练】第 14 天(glitch-free的两个时钟切换电路)_李锐博恩的博客-CSDN博客

物联沃分享整理
物联沃-IOTWORD物联网 » 无毛刺时钟切换技术解析

发表评论