EETOP 创芯网论坛 (原名:电子顶级开发网)

标题: Verilog基本电路设计之二(时钟无缝切换) [打印本页]

作者: 杰克淡定    时间: 2016-6-16 17:01
标题: Verilog基本电路设计之二(时钟无缝切换)
时钟切换分成两种方式,普通切换和去毛刺无缝切换。

普通切换,就是不关心切出的时钟是否存在毛刺,这种方式电路成本小。如果时钟切换时,使用此时钟的模块电路处于非工作状态,或者模块内电路被全局复位信号reset住的,即使切出毛刺也不会导致DFF误触发,这样的模块可以选择用此种切换方式。
写法很简单 assign clk_o = sel_clkb ? clkb : clka ,当sel_clkb为1时选择clkb,否则选择clka。不过在实际设计中,建议直接调用库里的MUX单元并set_dont_touch,不要采用这里的assign写法,因为这种写法最后综合得到的可能不是MUX而是复杂组合逻辑,给前后端流程的时钟约束和分析带来不便。


无缝切换,就是切换时无毛刺时钟平稳过渡。在时钟切换中,只要出现比clka或者clkb频率更高的窄脉冲,不论是窄的高电平还是窄的低电平,都叫时钟毛刺。工作在切换后时钟clk_o下的电路模块,综合约束是在max{clka,clkb}频率下的,也就是说设计最后signoff的时候,只保证电路可以稳定工作的最高频率是max{clka,clkb},如果切换中出现更高频的时钟毛刺,电路可能出现无法预知的结果而出错。无缝切换,一般用在处于工作状态的模块需要调频或者切换时钟源,比如内部系统总线,CPU等。你刚用手机打完游戏后马上关屏听音乐,这两种场景中,CPU在满足性能前提下为了控制功耗,其工作频率会动态地从很高调至较低,此时就可能是在CPU一直处于工作状态下,通过无缝切换时钟源头实现的。

在无缝切换电路中,切换信号sel_clkb可以是任意时钟域下的信号,包括但不限于clka或者clkb域,但是sel_clkb必须是一个DFF输出信号;clka与clkb的频率大小相位关系可以任意。无缝切换需要解决两个问题,一是异步切换信号的跨时钟域同步问题,这里需要使用《Verilog基本电路设计之一》里的同步电路原理消除亚稳态;二是同步好了的切换信号与时钟信号如何做逻辑,才能实现无毛刺。

下面写出无缝切换电路的主体部分,忽略了内部信号的定义声明等。

module clk_switch (
                rst_n          , //
                clka            , //
                clkb            , //
                sel_clkb      , //
                clk_o            //
                );

//assign clka_n = ~clka;
//assign clkb_n = ~clkb;

// part1
//always @ (posedge clka_n or negedge rst_n)
always @ (posedge clka or negedge rst_n)
begin
    if (!rst_n) begin
        sel_clka_d0 <= 1'b0;
        sel_clka_d1 <= 1'b0;
    end
    else begin
        sel_clka_d0 <= (~sel_clkb) & (~sel_clkb_dly3) ;
        sel_clka_d1 <= sel_clka_d0 ;
    end
end

// part2
//always @ (posedge clka_n or negedge rst_n)
always @ (posedge clka or negedge rst_n)
begin
    if (!rst_n) begin
        sel_clka_dly1 <= 1'b0;
        sel_clka_dly2 <= 1'b0;
        sel_clka_dly3 <= 1'b0;
    end
    else begin
        sel_clka_dly1 <= sel_clka_d1;
        sel_clka_dly2 <= sel_clka_dly1 ;
        sel_clka_dly3 <= sel_clka_dly2 ;
    end
end

// part3
//always @ (posedge clkb_n or negedge rst_n)
always @ (posedge clkb or negedge rst_n)
begin
    if (!rst_n) begin
        sel_clkb_d0 <= 1'b0;
        sel_clkb_d1 <= 1'b0;
    end
    else begin
        sel_clkb_d0 <= sel_clkb & (~sel_clka_dly3) ;
        sel_clkb_d1 <= sel_clkb_d0 ;
    end
end

// part4
//always @ (posedge clkb_n or negedge rst_n)
always @ (posedge clkb or negedge rst_n)
begin
    if (!rst_n) begin
        sel_clkb_dly1 <= 1'b0;
        sel_clkb_dly2 <= 1'b0;
        sel_clkb_dly3 <= 1'b0;
    end
    else begin
        sel_clkb_dly1 <= sel_clkb_d1   ;
        sel_clkb_dly2 <= sel_clkb_dly1 ;
        sel_clkb_dly3 <= sel_clkb_dly2 ;
    end
end

// part5
clk_gate_xxx clk_gate_a ( .CP(clka), .EN(sel_clka_dly1), .Q(clka_g)  .TE(1'b0) );
clk_gate_xxx clk_gate_b ( .CP(clkb), .EN(sel_clkb_dly1), .Q(clkb_g)  .TE(1'b0) );
//assign clka_g = clka & sel_clka_dly1 ;
//assign clkb_g = clkb & sel_clkb_dly1 ;
assign clk_o = clka_g | clkb_g ;

endmodule


上面是我认为比较合理的无缝切换电路,其他切换方式跟这个会有些许出入,但基本大同小异原理是一样的。有几点说明:
1、抛开注释掉的电路不看,由于part5部分直接调用库里的clock gating cell,使得整个切换电路全部只需要用到时钟上升沿,无需额外定义反向时钟,精简了DC综合的时钟约束;直接调用gating cell的 另一个好处是,前后端工具会自动检查gating cell的CP信号与EN信号的setup/hold时间,使得gating后的Q时钟输出无毛刺尖峰。TE端可以根据实际需要接上scan测试模式信号。如果使用part5部分的gating cell实现,前面的part1,2,3,4全部替换成注释掉的反相时钟也是没有问题。

2、part2和part4部分,具体需要多少级DFF,甚至完全不要也是可以的,这就回到了《Verilog基本电路设计之一》里讨论的到底多少级DFF消除亚稳态才算合理的问题。时钟频率很低可能无所谓,如果时钟频率达到GHz,这部分建议至少保留三级DFF,因为三级DFF延时也仅仅只有3ns的时间裕度。没必要为了省这么几个DFF降低电路可靠性,在复杂IP以及大型SOC系统中,你会发现多几十个DFF,面积上可以忽略,系统可靠性和稳定性才是首要的。

3、如果part5部分希望使用注释掉的两行“与”逻辑实现时钟gating,此时part1与part3使用正相或者反相时钟都可以,但是必须把part2和part4部分改为注释掉的反相时钟实现,目的是初步从RTL设计上避免“与”逻辑的毛刺,同时还需要后端配合,因为很多后端工具对时钟“与”逻辑的clock gating check未必会检查。用clk下降沿拍出的en信号,再跟clk做与逻辑得到的门控时钟,在RTL仿真阶段看到的一定不会有毛刺,但是布线完成后,如果clk相对en后移,那与逻辑得到的门控时钟就有毛刺了。这就是用与逻辑做门控的缺点,由于后端工具可能不会去检查这个与门的时序关系而导致出错。但直接调用库里的gating cell,工具天然就会去检查这个时序,免去人工确认的后顾之忧。

最后,请大家仔细看看sel_clka_d0 <= (~sel_clkb) & (~sel_clkb_dly3)  和sel_clkb_d0 <= sel_clkb & (~sel_clka_dly3) 这两处逻辑,按理说,sel_clkb跟sel_clka_dly3以及sel_clkb_dly3之间相互都是异步的,而按照异步信号同步处理原则,两个不同时钟域下的信号是不允许直接做组合逻辑的,为什么这里可以这样使用?



作者: 老阮    时间: 2016-6-16 19:04
写得很好!
对于最后那个问题,我的理解是:因为后级是对这个与门的输出进行同步,所以是允许的。
而且这里必须进行这样的与操作,保证在一个时钟输出关闭后才开启另一个时钟输出,否则在时钟频率相差较大时,两路时钟可能都输出了。
作者: 07048097    时间: 2016-6-16 22:26
good
关于最后的问题:因为(~sel_clkb_dly3)或者 (~sel_clka_dly3)最后都是会保持为1的,也就是说他们的0/1变换仅发生时钟切换点上,而这个切换点又经过目标时钟的同步(以及处理亚稳态的过程),所以最后的选通信号不会有问题
作者: yariyari    时间: 2016-6-16 22:57
写的不错
作者: orlye    时间: 2016-6-17 08:55
学习了。
作者: haimo    时间: 2016-6-17 09:41
问一个问题,part1和part3中的组合逻辑 (~sel_clkb) & (~sel_clkb_dly3)和sel_clkb & (~sel_clka_dly3) 已经做同步处理了,为啥还有经过part2和part4。
作者: 杰克淡定    时间: 2016-6-17 09:50
回复 6# haimo

这个问题请看后面的第2点注解,连同最后面抛出的那个问题一起思考,理解清楚了,你就可以根据不同的时钟应用条件对于part2以及part4部分游刃有余地做灵活增减处理。
作者: haimo    时间: 2016-6-17 09:53
回复 7# 杰克淡定

就是说是也是可以完全不要的,理由就是我说的已经在part1和part3做过同步了。
作者: 杰克淡定    时间: 2016-6-17 10:44
回复 2# 老阮

嗯,你从时钟切换中需要先关clk1再开clk2角度,回答了要做这个与逻辑的原因。我问的侧重点在于,为什么这里能够把异步时钟域的组合逻辑信号后再往另一个时钟域去同步,在上一篇帖子里特别指出过,被两级同步过去的异步信号输入,必须是另一个时钟域的DFF信号,不能是组合逻辑信号。对于c=a&b的逻辑,如果信号a来自clk1域,信号b来自clk2域,信号c又将在clk3域被使用,从常规设计规则里是不允许的,原因在于组合逻辑会产生毛刺,更何况这里是两个异步时钟域下的信号在做与逻辑,而毛刺信号却可能被另一个异步时钟clk3抓到。


你楼下那位兄弟基本回答了同步这个组合逻辑信号过去不会存在问题的原因,重点就是在于设计中保证a和b信号不会同时变化,得到的c不会有毛刺,我后面再详细回复。
作者: tuohit    时间: 2016-6-17 10:57
好东西啊 好东西啊
作者: 杰克淡定    时间: 2016-6-17 12:00
本帖最后由 杰克淡定 于 2016-6-17 12:42 编辑

回复 3# 07048097


   正解!多谢你的探讨回复,能考虑到问题这一层面的,说明你也是深究过问题本质的。

   对此问题,那我就来做个总结吧。
   回到part1和part3中的两处组合逻辑sel_clka_d0 <= (~sel_clkb) & (~sel_clkb_dly3) 和sel_clkb_d0 <= sel_clkb & (~sel_clka_dly3) ,等价抽象为c=a&b的逻辑,其中a来自clk1域,b来自clk2域,信号c将会在clk3域被同步。当a,b两个信号同时变化时,得到的c会存在毛刺,毛刺可能被clk3抓到而导致错误,避免错误的唯一办法:保证a和b不要同时跳变!


看我们的设计中,sel_clka_dly3和sel_clkb_dly3通过part2和part4电路delay,实际上就是错开了和sel_clkb的跳变沿,part2和part4部分用的DFF越多,它们与sel_clkb的变化沿相隔的越远而越安全,大家可以仿真模拟看看波形。也许有人说去掉part2和part4部分,通过前面的part1和part3两级同步电路,已经可以让它们之间的跳变沿相差两个cycle了。如果你考虑1GHz高频时钟切换就不会这么想了,两个cycle的差异仅仅是2个ns,而且再去做c=a&b这个与逻辑输入端时,由于a与b的异步时序关系以及信号传递差异,此时它们之间的跳变沿相差是无法保证还有两个ns的。因此,对于高频时钟切换,只能通过尽量增加part2和part4的级数,提高绝对跳变沿的延时,从而留给c=a&b这个与逻辑更多的时间裕量。


所以,part2和part4部分的作用:1、如果part5用与逻辑做gating,保留part2和part4的反相沿设计初步避免时钟gating毛刺;2、高频时钟切换中,增加级数降低part1和part3同步的亚稳态概率;3,高频时钟切换中,增加级数降低part1和part3中“与”逻辑毛刺风险。清楚了原因,就可以根据自己的实际情况对part2和part4做取舍。
作者: yaya126    时间: 2016-6-17 16:21
我想把glitch free clock switch简单化下,如果给两bit的选择信号,2'b01表示选clka, 2'b10表示选clkb, 2‘b00和2'b11表示全部gating, 是不是对clockswitch 的要求非常简单,就是2'b01变 2'b10的时候需要保证一定gap来gating 两个clock, 反之亦然。
那问题来了,如何由1bit的select信号转换出上面写的两bits select 信号, 并保证一定的gap.

always@(posedge  clka or negedge rstn) begin
    if(~rstn)
        clka_d1 <= 1'b1;
        clka_d2 <= 1'b1;
    end else begin
        clka_d1    <=  clka_sel;
        clka_d2    <= clka_d1;
   end
end

always@(posedge  clkb or negedge rstn) begin
    if(~rstn)
        clkb_d1 <= 1'b0;
        clkb_d2 <= 1'b0;
    end else begin
        clkb_d1    <=  clkb_sel;
        clkb_d2    <= clkb_d1;
   end
end

wire clka_sel =   select & ~clkb_d2 ;  //better to  use standard cell with don't touch
wire clkb_sel = ~select & ~clka_d2 ;  //better to  use standard cell with don't touch

wire clka_out = clka_d2 & clka;   //better to  use standard cell with don't touch
wire clkb_out = clkb_d2 & clkb;  //better to  use standard cell with don't touch
wire clk_out    = clka_out | clkb_out;

clka_sel和clkb_sel就是两bit的信号,
作者: 杰克淡定    时间: 2016-6-17 17:18
本帖最后由 杰克淡定 于 2016-6-17 17:20 编辑

回复 12# yaya126

你的意思是说,你要求用一个两bit的select【1:0】信号,实现2'b01选clka, 2'b10选clkb, 2‘b00和2'b11不输出时钟,是这样吗?灵活变通一下嘛,主体切换电路直接调用我的模块,外围信号再简单处理一下先得到sel_clkb,最后输出时钟做个门控关断即可。

always@(posedge  clkx or negedge rst_n)
begin
    if (~rst_n)
          sel_clkb <= 1'b0;
    else
         sel_clkb <= (select==2'b10);
end

clk_switch clk_switch (
                .rst_n           (rst_n   ) , //
                .clka            (clka      ), //
                .clkb            (clkb      ), //
                .sel_clkb       (sel_clkb), //
                .clk_o          (clk_tmp )  //
                );

always@(posedge  clkx or negedge rst_n)
begin
    if  (~rst_n)
         clk_en <= 1'b0;
    else
         clk_en <= (^select);
end

clk_gate_xxx clk_gate_o ( .CP(clk_tmp ), .EN(clk_en ), .Q(clk_o)  .TE(1'b0) );

clk_o就是最后你需要的时钟了。select是哪个时钟域的信号,上面的两个always中的clkx就用哪个时钟。如果想使用与门代替上面的clk_gate_xxx,用clk_tmp下降沿把clk_en抓两拍后再跟clk_tmp做与逻辑得到最后的clk_o
作者: yaya126    时间: 2016-6-17 17:38
回复 13# 杰克淡定
不是,我的意思是说, 设计1bit控制的glitch free clock switch, 可以转换角度,设计一个两bit的控制,核心问题转变成如何产生2'b01-N*2'B00-2'b10这样的pattern.   保证没有glitch,只需要select信号和各自的时钟对齐,且10/01之间的gap足够。
作者: yaya126    时间: 2016-6-17 17:44
你仔细看看我的那段code,也是由单bit select产生sela和selb, 但我的思路和你略有不同。
作者: 杰克淡定    时间: 2016-6-17 17:56
回复 15# yaya126

思考问题的方式差异而已,你没发现你写出的code跟我的其实本质是一样的吗,是我写的电路简化掉part2和part4部分后的版本。而对于part2和part4能否随意简化,前面已经有过讨论了。另外对于你的:wire clka_out = clka_d2 & clka;   //better to  use standard cell with don't touch
wire clkb_out = clkb_d2 & clkb;  //better to  use standard cell with don't touch
这里clka_d2和clkb_d2必须要用下降沿产生,否则有毛刺,其中原因帖子里也分析过了。
作者: 07048097    时间: 2016-6-17 19:22
多谢楼主肯定,另外我有一个问题就是楼主的时钟切换电路中间有一段时间是没有clk输出的,如果后面delay选择信号越多拍,那么这个gap会越大,是吗?
作者: yaya126    时间: 2016-6-17 20:15
回复 16# 杰克淡定
果然,再仔细看下,实质是一样的, 保证一定的gap,其实也是通过增加pile来实现。
不过你说的会有毛刺,这个不是必然的,为什么建议采用standard cell在手动搭,就是考虑到这个问题,当clka和sela有固定的相位关系是没有毛刺的。
作者: 杰克淡定    时间: 2016-6-18 10:28
回复 17# 07048097

是的,在切换过程中,会有一段时间没有时钟输出。增加的DFF级数越多,切换过程花更长的时间来完成,也就是带来gap段更大,这是增加DFF级数的弊端。无缝切换,你是希望切换过程更安全,还是追求切换快速完成,这就是矛盾。所以大家才需要根据自己的实际应用条件,对part2和part4部分进行灵活增减处理。
作者: 小武哥225    时间: 2016-9-5 14:34
楼主分析的很透彻,尤其是最后一个问题的解释很精彩,之前一直没考虑到,学习了!
作者: yaphetszyj    时间: 2016-9-8 22:06
突然之间觉得这里的信息量好大,学到了!!
作者: 李九阳    时间: 2016-9-10 10:51
找工作刚好用得着
作者: guokaile0529    时间: 2016-9-14 19:43
多谢楼主分享,受益匪浅。
作者: 诠释幸福    时间: 2016-9-15 21:48
好好看看!!!!
作者: 诠释幸福    时间: 2016-9-15 23:04
花了波形图,才看懂了大部分,真心不错!!!!
作者: amandafly    时间: 2016-9-18 10:16
期待楼主的其他分享,我已经做成WORD,留下来好好学习了。谢谢,祝楼主您健康幸福!
作者: 转-轮-王    时间: 2016-9-19 18:22
复位完后,若选择信号一直为1或0,同步完的dly3信号是不是每经过延时时间就在0/1间变一次,为0的这段时间就没时钟信号输出?
作者: 我没逗你玩儿    时间: 2016-9-24 19:57
多谢分享~~受益匪浅~~~
作者: silencefpga    时间: 2016-9-25 19:37
great ! This is a classic circuit, a deep analysis
作者: xiangpeis    时间: 2016-9-26 16:17
学习了,感谢楼主。
还望继续多发这种贴子啊,我会追踪学习的。
作者: 杰克淡定    时间: 2016-9-29 17:09
回复 27# 转-轮-王


   显然不是,源头的时钟选择信号输入保持不变,内部的切换信号肯定是维持在某种稳定状态,不会出现你说的这种0/1来回跳变的情况。
作者: 杰克淡定    时间: 2016-9-29 17:46
回复 1# 杰克淡定

发现有些同学都不去仔细看看文字说明部分,完全只看了RTL部分,就来说什么时钟上升沿啊下降沿啊之类的,没有懂得将原设计灵活变通。下面用大家更喜欢用的与逻辑实现gating重写一遍,下面设计不如原设计好,原因自己去看原文说明。
    module clk_switch (
                rst_n          , //
                clka            , //
                clkb            , //
                sel_clkb      , //
                clk_o            //
                );

assign clka_n = ~clka;
assign clkb_n = ~clkb;

always @ (posedge clka or negedge rst_n)
begin
    if (!rst_n) begin
        sel_clka_d0 <= 1'b0;
        sel_clka_d1 <= 1'b0;
    end
    else begin
        sel_clka_d0 <= (~sel_clkb) & (~sel_clkb_dly3) ;
        sel_clka_d1 <= sel_clka_d0 ;
    end
end

always @ (posedge clka_n or negedge rst_n)
begin
    if (!rst_n) begin
        sel_clka_dly1 <= 1'b0;
        sel_clka_dly2 <= 1'b0;
        sel_clka_dly3 <= 1'b0;
    end
    else begin
        sel_clka_dly1 <= sel_clka_d1;
        sel_clka_dly2 <= sel_clka_dly1 ;
        sel_clka_dly3 <= sel_clka_dly2 ;
    end
end

always @ (posedge clkb or negedge rst_n)
begin
    if (!rst_n) begin
        sel_clkb_d0 <= 1'b0;
        sel_clkb_d1 <= 1'b0;
    end
    else begin
        sel_clkb_d0 <= sel_clkb & (~sel_clka_dly3) ;
        sel_clkb_d1 <= sel_clkb_d0 ;
    end
end

always @ (posedge clkb_n or negedge rst_n)
begin
    if (!rst_n) begin
        sel_clkb_dly1 <= 1'b0;
        sel_clkb_dly2 <= 1'b0;
        sel_clkb_dly3 <= 1'b0;
    end
    else begin
        sel_clkb_dly1 <= sel_clkb_d1   ;
        sel_clkb_dly2 <= sel_clkb_dly1 ;
        sel_clkb_dly3 <= sel_clkb_dly2 ;
    end
end

assign clka_g = clka & sel_clka_dly3 ;
assign clkb_g = clkb & sel_clkb_dly3 ;
assign clk_o  = clka_g | clkb_g ;

endmodule
作者: 小蓉蛋蛋    时间: 2016-9-30 14:54
瞅瞅
作者: xiaogou1233    时间: 2016-12-27 19:38
相见恨晚啊,不错了,学习中。。。
作者: xiaogou1233    时间: 2016-12-28 14:58
楼主,有个问题哎,两个时钟切换过程中,有一段空白期,这好像不太好吧,你手机的CPU没有时钟了,岂不是很危险?
作者: ddh99    时间: 2016-12-29 09:03
感谢分享,学习了
作者: novel_qin    时间: 2017-1-5 11:43
本帖最后由 novel_qin 于 2017-1-5 11:59 编辑

楼主写得不错,
但经过推导,从慢时钟切换快到时钟,可能存在时钟交叠的情况,楼主看看是不是会有问题
作者: novel_qin    时间: 2017-1-5 11:58


楼主写得不错,
但经过推导,从快时钟切换到慢时钟,可能存在时钟交叠的情况,楼主看看是不是会有问题
novel_qin 发表于 2017-1-5 11:43




    写错了,是从慢时钟切换到时钟,可能存在时钟交叠的情况,
作者: onetoend    时间: 2017-1-5 12:24
谢谢分享
作者: 杰克淡定    时间: 2017-1-5 19:26
回复 35# xiaogou1233


   你所说的有一段时间没有时钟,其实就是时钟低电平停留的时间变长,时钟频率变低而已。你把它理解为此时CPU是工作在一个较低低频率的时钟下就好了。再者,即使某一段时间真的没有时钟,也没有你说的危险。没有时钟,整个系统hold住不动而已,而且这都是纳秒级的时间。
作者: 杰克淡定    时间: 2017-1-5 19:31
回复 38# novel_qin


   不明白你说的交叠是什么意思。无缝切换直观点说是无毛刺切换,本质意义是指切换过程中,不能产生比被切换的两个时钟频率都高的时钟,但允许出现比被切换时钟频率都低的时钟,以保障电路工作的安全稳定。
作者: anytao    时间: 2017-1-10 09:23
必须点赞
作者: xiaogou1233    时间: 2017-1-10 20:35
根据楼主的代码画的电路图,供参考 (, 下载次数: 166 )
作者: xiaogou1233    时间: 2017-1-10 20:37
以及对应的波形图 (, 下载次数: 155 )
作者: xiaohanhaowei    时间: 2017-1-10 21:10
回复 1# 杰克淡定
LZ,很6么,这种帖子已收,抓紧学习
作者: clare20    时间: 2017-3-1 11:17
回复 44# xiaogou1233


好赞!
作者: billlowe    时间: 2017-3-16 21:02
回复 11# 杰克淡定

你好,看了你的帖子受益匪浅,谢谢了。不过我还有一个小小的疑问,希望你能帮我解答一下。
你说到:part2和part4部分的作用:1、如果part5用与逻辑做gating,保留part2和part4的反相沿设计初步避免时钟gating毛刺;
我的问题是: 为什么反相沿设计可以初步避免时钟gating毛刺呢?
我的理解是:难道不应该是上升沿设计才能避免选择信号和时钟不是往相反的方向变化,从而才能避免毛刺吗?
甚是不解,求解答,谢谢了!
作者: 杰克淡定    时间: 2017-3-16 21:12
回复 47# billlowe

如果是CLK上升沿拍出一个EN信号,实际EN信号相对上升沿肯定有一定延迟,当与CLK做与逻辑得到gating出来的时钟,会导致EN变1的那个周期的时钟高电平被削短,EN变0的那个周期的时钟产生高电平尖峰毛刺。你画一下时序结果就出来了
作者: billlowe    时间: 2017-3-16 21:43
回复 48# 杰克淡定


   大概是明白了,之前我没有去考虑EN信号由高变低的情况了,谢谢!
作者: 547420883    时间: 2017-4-14 16:57
Modelsim仿真的话能把毛刺仿出来么。
作者: 三石哥哥    时间: 2017-5-2 13:48
请问一下楼主是用什么工具做的?
是工具中包含gating cell?
作者: masterleego    时间: 2017-5-2 21:15
真好速度啊
作者: eecsseu    时间: 2017-5-23 15:21
回复 11# 杰克淡定


解释的无法理解,就算增加在多级数也没有价值。
作者: eecsseu    时间: 2017-5-23 15:26
回复 32# 杰克淡定


  你的这个电路经过工程验证过?
作者: 杰克淡定    时间: 2017-5-26 15:40
回复 38# novel_qin


   回头仔细看了你的回复,发现了原设计中一个笔误,会导致你说的问题。
// part5
clk_gate_xxx clk_gate_a ( .CP(clka), .EN(sel_clka_dly1), .Q(clka_g)  .TE(1'b0) );
clk_gate_xxx clk_gate_b ( .CP(clkb), .EN(sel_clkb_dly1), .Q(clkb_g)  .TE(1'b0) );
//assign clka_g = clka & sel_clka_dly1 ;
//assign clkb_g = clkb & sel_clkb_dly1 ;


这部分要使用*dly1的信号,而不是*dly3,*dly1相比*dly3会将两个时钟切换gap变大避免毛刺,part4用的dly寄存器越多,*dly1就把切换点gap越大。帖子这么久没有其他人提出这个疑问,看起来只有你拿去仿真验证了
作者: haimo    时间: 2017-6-14 17:15
回复 55# 杰克淡定


这样也可以吧。
clk_gate_xxx clk_gate_a ( .CP(clka), .EN(sel_clka_d1), .Q(clka_g)  .TE(1'b0) );
clk_gate_xxx clk_gate_b ( .CP(clkb), .EN(sel_clkb_d1), .Q(clkb_g)  .TE(1'b0) );
作者: 杰克淡定    时间: 2017-6-14 17:19
回复 56# haimo


   目前主贴中的错误已经更正过来了,与你这个一致
作者: haimo    时间: 2017-6-15 09:29
回复 57# 杰克淡定

您用的是sel_clka_dly1,我用的是sel_clka_d1,
   

sel_clka_dly1 <= sel_clka_d1;

但我觉得都行

我之前也发现这个问题,采用的方法是加多part2/4的级数的方法,这样gap就大了
作者: capcomwf    时间: 2017-6-26 17:41
本帖最后由 capcomwf 于 2017-6-26 22:47 编辑

回复 55# 杰克淡定
我这边RTL仿真的结果:
电路第一次工作时会出现第一次的混叠,可能由
sel_clka_dly1 <= 1'b0;
sel_clka_dly2 <= 1'b0;
sel_clka_dly3 <= 1'b0;

sel_clkb_dly1 <= 1'b0;
sel_clkb_dly2 <= 1'b0;
sel_clkb_dly3 <= 1'b0;
初值互斥引起.
(, 下载次数: 179 )

只要将切换的初始状态赋对(即默认输出clka)
sel_clka_d0 <= 1'b1;
sel_clka_d1 <= 1'b1;
sel_clka_dly1 <= 1'b1;
sel_clka_dly2 <= 1'b1;
sel_clka_dly3 <= 1'b1;
即可.
(, 下载次数: 189 )

另外,本题的切换的电平持续最短时间是要至少维持较长周期的5倍才可在慢时钟到快时钟切换时正确输出较快的那一个.
至于38楼及55楼楼主提到的频率混叠情况,是否可以给个波形图看看?我这边没有太理解....
作者: thundersnark    时间: 2017-6-28 10:08
回复 55# 杰克淡定


   楼主您好,看了您的帖子,我把这部分电路推理了一遍,有点不理解的地方想向楼主请教,从楼主的代码中可以看到,楼主的MUX采用“与门+或门”的结构来实现,而后级采用“与门+或门”的时候,用于输出"与门"的门控信号的寄存器一定要下降沿触发       “3、如果part5部分希望使用注释掉的两行“与”逻辑实现时钟gating,此时part1与part3使用正相或者反相时钟都可以,但是必须把part2和part4部分改为注释掉的反相时钟实现,目的是初步从RTL设计上避免“与”逻辑的毛刺”         您在第三点中也说明了,这一点,那么为啥在代码中采用“clk_gate_xxx clk_gate_a ( .CP(clka), .EN(sel_clka_dly1), .Q(clka_g)  .TE(1'b0) );
clk_gate_xxx clk_gate_b ( .CP(clkb), .EN(sel_clkb_dly1), .Q(clkb_g)  .TE(1'b0) );”的时候可以采用上升沿触发?按道理来讲,clk_gate不就是一个与门吗?如果想要采用全上升沿触发,那么就应该是原始时钟上升沿触发‘控制原始时钟的触发器’,关断原始时钟,锁定输出到高电平,目的时钟上升沿后触发‘目的时钟的触发器
’,开启目的时钟,从而在高电平完成时钟切换,要达到这个目的,后级的MUX的实现方法,应该是采用“或门+与门”的结构,而不是楼主代码里的"与门+或门"的结构吧?还请楼主不吝赐教,谢谢!
作者: 杰克淡定    时间: 2017-6-29 08:59
回复 60# thundersnark


   你可以学习楼上的做法,把这个设计和你认为正确的设计,仿真一下,对着仿真波形就很容易理解了,光这么疑惑纠结也没用啊
作者: haimo    时间: 2017-6-29 09:54
回复 59# capcomwf

clk_o 和 clk_o1是什么关系

你说的第一次工作,指的是selb第一次由0变1
作者: capcomwf    时间: 2017-6-29 11:00
回复 62# haimo


    不好意思,我那个回复里面没有说清楚:
    clk_o是用sel_clka_dly3和sel_clkb_dly3门控时钟的输出,clk_o1是用sel_clka_dly1和sel_clkb_dly1门控时钟的输出。可以发现在时钟从慢速切换到高速时使用sel_clka_dly1和sel_clkb_dly1确实可以让切换的间隔更加大一点,但是使用sel_clka_dly3和sel_clkb_dly3产生混叠的情况我这边没有发现,请问可否帮忙解答一下。
   我说的第一次切换的确是sel_clkb第一次由0变1时由于初值设置,可能出现时钟混叠。
作者: haimo    时间: 2017-6-29 11:20
回复 63# capcomwf
那么你看看当第二次selb从低到高切换的情况,最好能贴个图
作者: haimo    时间: 2017-6-29 11:43
回复 63# capcomwf

这个原因是因为时钟在rst_n后不久,就进行selb的切换了

如果你将clka和clkb的频率差拉大,比如一个10M,一个200M,看看会不会交叠
作者: 杰克淡定    时间: 2017-6-29 13:45
回复 63# capcomwf

正如haimo所说,你所说的第一次出现的混叠是由于复位后马上进行了切换,而设计中sel_clka_*与sel_clkb_*的复位值全部使用的是0,所以出现了你看到的情况。你的解法也是合理的,可以根据输入信号sel_clkb的复位初始值,来设定sel_clka_*与sel_clkb_*的复位值分别为0或者1,从而避免这种情况。

另外,使用sel_clka_dly3以及sel_clkb_dly3做gating,可能出现的混叠,你可以加大clka和clkb的频率差,比如200M和30K再仿真看看是不是就出现问题了
作者: capcomwf    时间: 2017-6-29 14:18
本帖最后由 capcomwf 于 2017-6-29 14:21 编辑

回复 65# haimo
确实会有混叠出现,问题的本质是切换的持续时间太短造成:
(, 下载次数: 105 )

每次切换的时间如果大于5倍以上(因为代码中使用的DFF的级数)的较慢的那个时钟的周期则不会出现这个状况,这个条件应该说在实际应用中还是不难实现的,时钟切换不可能过于频繁.至于使用sel_clka_dly3/sel_clkb_dly3还是sel_clka_dly1/sel_clkb_dly1似乎并不影响混叠出现与否,中间的分别只是把gap从一边移到另一边.
下面这个波形是满足切换时间足够长的情况下的仿真结果,由此可以看到,初始条件的互斥其实也可以归到切换时间这类原因中去:
(, 下载次数: 113 )
只要复位到首次切换的时间足够长,就不会有混叠出现.所以楼主的代码在实际应用中应该是没问题的.
作者: capcomwf    时间: 2017-6-29 14:30
补充一点:在上面那一层回复第一张图中,我们可以看到使用sel_clka_dly1/sel_clkb_dly1作为时钟门控,如果切换时间太短,一样会有混叠出现(如clk_o1所示)
作者: haimo    时间: 2017-6-29 15:10
这就是说根据自己的实际应用,可以灵活增减dff的级数,
而且也不一定要用同一层级的dff输出作为gate信号,根据两个信号的频率差
可以用sel_clka_dly1和和sel_clkb_dly3作为gate信号也是可以的。
设计中通过验证来灵活设置。
作者: capcomwf    时间: 2017-6-29 15:25
回复 69# haimo

其实,细细看来,这个切换时间的限制,在楼主在19楼的答复中已经涵盖到了:



回复 17# 07048097

是的,在切换过程中,会有一段时间没有时钟输出。增加的DFF级数越多,切换过程花更长的时间来完成,也就是带来gap段更大,这是增加DFF级数的弊端。无缝切换,你是希望切换过程更安全,还是追求切换快速完成,这就是矛盾。所以大家才需要根据自己的实际应用条件,对part2和part4部分进行灵活增减处理。
杰克淡定 发表于 2016-6-18 10:28



用的DFF级数越多,切换过程也许要更长时间来完成,如果实际给的sel_clkb切换时间不够,那就出现混叠。
作者: capcomwf    时间: 2017-6-29 16:06
回复 69# haimo

和频率差没关,和频率值有关,和实际应用的切换时间有关。

PS:楼主发的这些topic都很有价值阿,我想和楼主学做菜,啊不,学FPGA,能否交流下QQ啥的随时请教呢?
话说我咋还有个回复发不出来在审核了咧?
作者: 杰克淡定    时间: 2017-6-29 18:58
回复 69# haimo


   看你这么回答,应该是能熟练使用这个电路了。目前这个设计对于某些应用场景,可能存在冗余的设计;而在另外的应用场景中,可能健壮性又有欠缺。只有真正理解了原理,才能游刃有余地灵活变通,增减这个设计以满足自己的实际应用场景。
作者: 泪相随    时间: 2017-7-10 10:25
通俗易懂,好样的
作者: galaxyhaha    时间: 2017-8-13 21:22
感谢!最近找工作正好用得到!
作者: sunflower_csy    时间: 2017-8-23 08:56
学习了
作者: window_blinds    时间: 2017-8-23 13:40
good,学习了。
作者: wenmyx    时间: 2017-8-23 13:42
学习下~~~~~~~~~~~~~
作者: window_blinds    时间: 2017-9-8 10:38
向楼主求教一个问题,做了时钟切换,对于切换的位置以及切换后的时钟,在DC综合的时候该如何去约束?PT怎么设置时序检查呢?
作者: 杰克淡定    时间: 2017-9-8 11:19
回复 78# window_blinds


   一般应用场景,切换后得到的时钟clk_mux与切换前的clka和clkb是异步关系。重新定义create_clock clk_mux即可。
作者: window_blinds    时间: 2017-9-8 13:49
回复 79# 杰克淡定

谢谢楼主解答!
   我切换的是clk和它的分频clk_div,那么切换后的clk_mux时钟域抓取clk、clk_div时钟域的信号需要做同步处理吗?
作者: window_blinds    时间: 2017-9-8 15:11
回复 79# 杰克淡定


   还有一个问题,如果重新定义create_clock clk_mux的话,由于clk_mux来源于两个不同频率的时钟,那么-period以及-waveform等参数又该如何确定呢?
作者: 杰克淡定    时间: 2017-9-8 15:47
本帖最后由 杰克淡定 于 2017-9-8 15:49 编辑

回复 81# window_blinds


你得先把因果顺序弄清楚。
因为你的应用场景需要切换后的时钟与两个源时钟保持同步,所以切换后的时钟你必须定义为create_generated_clock;
因为你的应用场景无需切换后的时钟与两个源时钟保持同步,所以切换后的时钟你可以定义为create_clock。

切换前后同步与否,不是受切换电路限制的,是根据你的应用需要来的。

如果切换后时钟可以定义为create_clock,说明它就是一个全新的异步时钟域,相位设置自然不用受限于前面的两个源头,频率则根据前面两个源头的最大可能值确定即可。
作者: window_blinds    时间: 2017-9-8 16:37
回复 82# 杰克淡定


   受教了,谢谢楼主耐心解答。
作者: 河源皮    时间: 2017-9-13 19:03
mark,自我总结,这并不是一个general的设计,还需要根据具体场景进行灵活修改,主要是下面两个因素:
1,切换的快慢,即sel_clkb的变化时间
2,时钟频率的绝对值
这两个因素会影响输出是否有混叠。混叠指的是两个时钟叠加到一块了。
作者: wide_road    时间: 2017-9-14 15:21
學習了,棒。
作者: piigle    时间: 2017-9-15 11:37
深圳-南山区(浙江赛思电子)招聘数字IC设计工程师,IC验证工程师(待遇从优)
                                                                有意向者可联系,陆先生:15067338277
作者: 张安    时间: 2017-9-20 16:35
clk_gate_xxx 怎么调用的啊?我在Quartus里没找到,能指点一下吗?
作者: 河源皮    时间: 2017-9-28 01:19
回复 87# 张安


    FPGA上就不要用门控时钟了,直接用与门,注意part2/4用下降沿。  然后切换出来的时钟再走bufg就可以了
作者: 马奎高    时间: 2017-11-4 15:33
回复 1# 杰克淡定


   楼主你好,这个电路是如何保证低电平切换的,我们知道,在3个和4个甚至更多时钟选择时,这很重要
作者: zqq624723237    时间: 2017-11-7 12:04
新手学习中!持续关注大佬的其他文章!
作者: 杰克淡定    时间: 2017-11-8 08:44
回复 89# 马奎高


  有了两个时钟切换,自己举一反三,实现3个4个甚至更多时钟切换,不困难吧
作者: vc9181    时间: 2017-11-9 09:39
写的不错
作者: ICTV    时间: 2017-11-9 15:34
好文,值得看看
作者: 马奎高    时间: 2017-11-13 15:54
本帖最后由 马奎高 于 2017-11-13 16:00 编辑

回复 91# 杰克淡定


    嗯,我的意思是这个电路不在时钟低电平去切换是不是可能有问题,或者里面已经做了处理,那可能是你的门控单元里面是在时钟低电平切换的,如果直接assign我觉得可能有问题
作者: jackstrive    时间: 2018-5-17 14:04
Thanks
作者: onlymortal    时间: 2018-9-18 17:22
你好,这种方法虽然可以无缝切换时钟,但是是否会在切换过程中出现很长的一段时钟低电平。
作者: zzzjjjqqq666    时间: 2018-9-19 07:24
回复 1# 杰克淡定
感谢分享!!!
作者: yanzhang98    时间: 2018-9-19 07:41
多谢,也发一个
https://codereview.stackexchange ... asynchronous-clocks
作者: yanzhang98    时间: 2018-9-19 07:42
https: //codereview.stackexchange.com/questions/62097/clock-mux-for-allowing-glitch-free-muxing-of-asynchronous-clocks
作者: edward2013    时间: 2018-9-30 08:55
回复 1# 杰克淡定


   楼主,代码中rst_n,是否也要注意一下同步问题?因为没有指明rst_n是属于哪个时钟域的,权且认为是异步时钟,则需要考虑removal时的时序问题,最好对rst_n做同步移除后再使用




欢迎光临 EETOP 创芯网论坛 (原名:电子顶级开发网) (https://bbs.eetop.cn/) Powered by Discuz! X3.4