不想错过我的推送,记得右上角-查看公众号-设为星标,摘下星星送给我
上一期我们讲解了门控时钟电路的设计,当使用纯组合逻辑的方式实现时会产生毛刺(Glitch),这是异步电路最常见的问题。今天我们来讲解另一个笔试、面试中常见的去毛刺问题——时钟无毛刺切换(Glitch-Free)。IC岗位笔试常会出现,如给电路图画波形。
在SoC的设计中,根据实际需求,经常需要对不同频率、相位的时钟源进行选择与切换,最简单的时钟切换电路就是两个时钟切换,可以用纯组合逻辑来实现。我们先画一下用组合逻辑实现功能后的波形大概是怎样的,如下所示。 当sel为高时选通sclk1,当sel为低时选通sclk2,clk_out为切换输出的结果,我们可以清晰的发现①和②处有毛刺产生,我们用RTL代码来描述并仿真验证。 //-------------------------- 01 module test ( 02 input wire sclk1 , 03 input wire sclk2 , 04 input wire sel , 05 06 output wire clk_out 07 ); 08 09 assign clk_out = ( sel & sclk1 ) | (~ sel & sclk2 ); 10 11 endmodule//--------------------------
综合出的RTL视图如下所示: 经过仿真我们发现在①处和②处时钟选择信号变化的时候会导致切换后的输出时钟产生毛刺,这显然是我们不想要的结果,所以要对上述的电路结构进行修改。 我们先思考一下产生毛刺的原因,然后再想办法怎么修改。从上图可以看出,主要是选择信号sel导致的。由于我们使用的是组合逻辑实现的切换功能,所以当选择信号sel发生变化时,输出时钟立刻发生变化,也就是说选择信号sel是不受控制的,随时可以跳变,这样纯组合逻辑输出得到的clk_out就完全有可能会产生毛刺,所以我们需要改进电路。于是我们尝试着将sel信号分别同步于sclk1和sclk2后再实现切换的功能,RTL代码如下所示: //------------------------ 01 module test ( 02 input wire sclk1 , 03 input wire sclk2 , 04 input wire rst_n , 05 input wire sel , 06 07 output wire clk_out 08 ); 09 10 reg sel_sclk1 ; 11 reg sel_sclk2 ; 12 13 always @( posedge sclk1 or negedge rst_n ) 14 if ( rst_n == 1'b0 ) 15 sel_sclk1 <= 1'b0 ; 16 else 17 sel_sclk1 <= sel ; 18 19 always @( posedge sclk2 or negedge rst_n ) 20 if ( rst_n == 1'b0 ) 21 sel_sclk2 <= 1'b0 ; 22 else 23 sel_sclk2 <= ~ sel ; 24 25 assign clk_out = ( sel_sclk1 & sclk1 ) | ( sel_sclk2 & sclk2 ); 26 27 endmodule//---------------------
综合出的RTL视图如下所示: 我们可以看到如下所示的仿真结果,发现原来②处的毛刺已经消除了,而①处的毛刺还存在,这是怎么回事儿呢? 我们仔细分析未消除毛刺的原因,发现在①处附近sel信号分别同步于sclk1和sclk2后的信号sel_sclk1和sel_slck2同时为高,这样会在最后的组合逻辑运算的时候两个时钟同时有效,在或运算的时候产生毛刺。为了避免这种情况,我们需要做的就是让sel_sclk1和sel_slck2信号不能同时有效。所以我们使用一个小技巧,让彼此寄存器输出的信号取反后再和对应的sel信号相与即可,RTL代码如下所示: //-------------------------- 01 module test ( 02 input wire sclk1 , 03 input wire sclk2 , 04 input wire rst_n , 05 input wire sel , 06 07 output wire clk_out 08 ); 09 10 reg sel_sclk1 ; 11 reg sel_sclk2 ; 12 13 always @( posedge sclk1 or negedge rst_n ) 14 if ( rst_n == 1'b0 ) 15 sel_sclk1 <= 1'b0 ; 16 else 17 sel_sclk1 <= sel & ~ sel_sclk2 ; 18 19 always @( posedge sclk2 or negedge rst_n ) 20 if ( rst_n == 1'b0 ) 21 sel_sclk2 <= 1'b0 ; 22 else 23 sel_sclk2 <= ~ sel & ~ sel_sclk1 ; 24 25 assign clk_out = ( sel_sclk1 & sclk1 ) | ( sel_sclk2 & sclk2 ); 26 27 endmodule //----------------------- 综合出的RTL视图如下所示: 我们可以看到如下所示的仿真结果,发现毛刺已经完全消除了,因为sel_sclk1和sel_slck2信号不存在同时有效的情况,所以完美的实现了两个时钟的切换。 我们可以观察到sel_sclk1信号在sclk1时钟域产生,需要取反后再和sel信号相与到sclk2时钟域,这样会出现跨时钟域问题产生亚稳态现象,所以我们可以在sclk2时钟域多加一级寄存器通过打拍的方式处理亚稳态问题(sel_sclk2信号同理)。 其实在FPGA中有专门对应时钟切换的原语可以使用,既方便切换效果又好,也是一种不错的选择。 END目前,我们正在通过大疆硬件岗和FPGA逻辑岗的题目,为大家带来笔试题的解析,以及知识的补充。如果有想要解析的题目,可以发给达尔闻安排。同时,欢迎加入达尔闻求职技术交流群,进群方式:添加妮姐微信(459888529),并备注求职,即可邀请进群。
达尔闻求职系列: 华为海思校招机考范围 求职攻略| 运放压摆率&三运放仪表放大电路分析,含仿真文件 磁珠的用法、PCB布线3W规则