一道简单的笔试题_时钟切换电路(Glitch-free clock switching circuit)

2020-07-23 17:05:38 浏览数 (2)

由一道某科笔试开始,如下:

解析:

电路功能:两个异步时钟源切换电路;

DFF1和DFF3作用:在选择路径插入一个上升沿触发器,用于缓存数据,将数据传递给下一级;若去掉,会电路产生由异步信号引起的亚稳态;

DFF2和DFF4采用负沿采用原因:SELECT与反馈输出相与,下降沿采样反馈可以保证一个时钟被完全取消选择后,输出才输出另一个时钟,从而避免产生毛刺。


前言

纯组合逻辑时钟切换电路:电平相反时,切换时钟不可避免产生毛刺;

相关时钟切换:下降沿切换(反馈实现),下个上升沿切换生效,消除毛刺;

无关时钟切换:下降沿触发之前添加一个上升沿触发器,消除亚稳态;

一、有毛刺的时钟切换

纯组合逻辑的时钟切换,由于为电平触发,不可避免会产生毛刺;

如图所示,这个时钟切换电路是一个纯组合逻辑,输出时钟(OUT CLOCK)由选择信号(SELECT)控制,当SELECT为1时输出CLK1,反之,输出CLK0.

看似很简单,实现了时钟的切换,实则存在着很大的隐患,如下图所示:

由图中可知,SELECT信号变化的位置没有和切换的时钟对齐;当SELECT信号发生改变时,当前时钟源(CLK0)正好处于高电平,因此,会在输出端产生毛刺。

对上图的Verilog描述:

代码语言:javascript复制
assign outclk = (clk1 & select) | (~select & clk0);

二、相关时钟源的时钟切换

以下为两个时钟源成倍数的关系的时钟切换电路:

在每个时钟源的选择路径中插入一个负边沿触发的D触发器。确保在切换时钟源时,即使时钟正处在高电平,也不会影响输出变化;

当时钟源切换时,这个反馈可以保证一个时钟被完全取消选择后,输出才输出另一个时钟,从而避免产生毛刺;

电路描述:

当SELECT为0时,CLK1的那部分通路到输出无效,仅看下半部分电路即可,在CLK0的下降沿采样SELECT(取反后)信号,与CLK0相与之后输出;

当SELECT为1时,同理上半部分电路有效;

如图首先SELECT为0,也就是在CLK0的下降沿采样寄存SELECT(取反后)信号与CLK0相与,输出时钟为CLK0;

当在图中时刻SELECT由低电平变为高电平,此时未到CLK0的下降沿,寄存器的输出还将一直是高电平(SELECT之前为0,取反为1),当到达CLK0的下降沿时刻,采样到SELECT为高电平,此时SELECT为1,也就是下半部分电路从此无效,上半部分电路有效,此时需要等到CLK1的下降沿采样SELECT值,在此之前,输出仍为 CLK0,到达CLK1的下降沿后,输出变成了CLK1和SELECT的与,也就是CLK1。由图可见,输出时钟完成切换,并没有出现毛刺。

代码语言:javascript复制
module glitch_2 (  
input clk0,      
input clk1,  
input select,  
input rst_n,  
output clkout); 
reg out1; 
reg out0; 
always @(negedge clk1 or negedge rst_n)begin     
    if(rst_n == 1'b0)begin         
        out1 <= 0;     
    end     
    else begin         
        out1 <= ~out0 & select;      
    end 
end 
always @(negedge clk0 or negedge rst_n)begin       
    if(rst_n == 1'b0)begin           
        out0 <= 0;       
    end       
    else begin           
        out0 <= ~select & ~out1;       
    end 
end 
assign clkout = (out1 & clk1) | (out0 & clk0); 
endmodule

三、异步时钟源的时钟切换

异步时钟源的切换是在相关时钟源切换的基础上插入一个上升沿D触发器,对选择信号进行同步处理,避免产生亚稳态

第一个触发器采样数据寄存,然后到第二个触发器输出第一个触发器寄存的数据。

还是按这张图进行仿真:

SELECT为0时候,clk0时钟上升沿采样得到DFF3Q,之后得到DFF4Q,下降沿采样得到DFF4_Q反馈,DFF4Q信号与clk0相与得到F;

DFF4_Q反馈到时钟域clk1,与SELECT相与,用clk1上升沿采样得到DFF1Q,之后得到DFF2Q,再用clk1下降沿采样得到DFF2_Q,DFF2Q信号与clk1相与得到输出E;

最终的输出为E与F的或,即输出clkout为无毛刺的时钟切换波形。

代码语言:javascript复制
module glitch_DFF (    
    input clk0,        
    input clk1,    
    input select,    
    input rst_n,    
    output clkout
);
wire B;
reg   DFF3Q, DFF4Q, DFF4_Q;   //DFF4Q=Q,DFF4_Q=~Q
wire A;
reg   DFF1Q, DFF2Q, DFF2_Q;  //DFF2Q=Q,DFF2_Q=~Q

assign A = select & DFF4_Q;
assign B = ~select & DFF2_Q;

//第一级触发器用上升沿采样,选择信号与反馈信号的与运算
always@(posedge clk1 or negedge rst_n) begin    
    if(~rst_n)        
        DFF1Q <= 0;    
    else        
        DFF1Q <= A;
    end 
//第二级触发器用下降沿采样
always@(negedge clk1 or negedge rst_n) begin    
    if(~rst_n) begin        
        DFF2Q <= 0;        
        DFF2_Q <= 1;    
    end    
    else begin        
        DFF2Q <= DFF1Q;        
        DFF2_Q <= ~DFF1Q;     
    end 
end //====================================================================
//第一级触发器用上升沿采样,选择信号与反馈信号的与运算
always@(posedge clk0 or negedge rst_n) begin    
    if(~rst_n)        
        DFF3Q <= 0;    
    else        
        DFF3Q <= B;
    end
//第二级触发器用下降沿采样
always@(negedge clk0 or negedge rst_n) begin    
    if(~rst_n) begin        
        DFF4Q <= 0;        
        DFF4_Q <= 1;    
    end    
    else begin        
        DFF4Q <= DFF3Q;        
        DFF4_Q <= ~DFF3Q;     
    end
end

wire E, F;
assign E = clk1 & DFF2Q;
assign F = clk0 & DFF4Q;
assign clkout = E | F;
endmodule

参考资料:

https://www.eetimes.com/techniques-to-make-clock-switching-glitch-free/

0 人点赞