剑侠盟·网游特攻队

  • 首页
  • 门派特辑
  • 情缘系统
  • 帮派战报
  • HOME> 门派特辑> SOC设计——时钟切换的MUX设计 glitch free技术(一种防止毛刺产生的多路选择器设计)
    SOC设计——时钟切换的MUX设计 glitch free技术(一种防止毛刺产生的多路选择器设计)
    门派特辑

    SOC设计——时钟切换的MUX设计 glitch free技术(一种防止毛刺产生的多路选择器设计)

    0. 为何需要时钟Glitch Free技术

    在SOC的设计中,经常需要用到大量的时钟源的选择与切换,以及时钟的分频,其中对于时钟的切换就显得尤为重要,并且如何在切换时钟源的过程中消除毛刺(glitch)。对于时钟的分频技术后续会介绍。 我们首先看一下如果不适用glitch free技术,来看时钟源的切换对电路的影响。

    glitch毛刺的产生的危害

    对于一个时钟切换电路,输入两个异步时钟clk0、clk1,以及一个选择信号sel。我们直接使用2MUX就可以实现两个时钟源的切换,RTL代码也很简单:

    assign clk_out = sel? clk1 :clk0;

    其RTL结构如下:

    下面分析这个设计的问题: 因为我们的clk0,clk1是异步的关系,所以就存在 时钟切换会发生在任意时刻,也就会存在glitch的产生。当寄存器捕获到时钟沿其他没捕获到,极有可能造成系统的不稳定。下如下图所示: 仿真的结果也可以看到有glitch毛刺的产生,如果被寄存器捕捉到,传播到下一级的电路,会产生不稳定的状态。

    1. Glitch Free技术介绍

    对于需要无缝切换时钟源,我们需要解决的问题有: 1.异步切换信号的跨时钟域同步问题,即可以用到异步复位,同步释放电路。 2.同步后的切换信号与时钟信号的逻辑设计。

    方法一:

    module stsoc_gf_ckmux

    (

    input rstn ,

    input [ 1:0] i_clk ,

    input sel ,

    output o_clk

    );

    wire [1:0] src_clk_lb, clk_en ;

    reg [1:0] n_en_reg ;

    reg [1:0] n_en_reg_dly ;

    wire [1:0] sync_clken_out ;

    wire [1:0] src_clk_inv ;

    wire [1:0] out_clk_and ;

    genvar index;

    generate for(index=0;index<2;index=index+1)

    assign src_clk_lb[index] = i_clk[index];

    assign src_clk_inv[index] = i_clk[index];

    //sync 三拍

    stsoc_sync_l3 sync_clk_en (

    .ck (src_clk_lb[0]),

    .clb (rstn),

    .d (clk_en[0]),

    .o (sync_clken_out[0])

    );

    //sync 三拍

    stsoc_sync_l3 sync_clk_en (

    .ck (src_clk_lb[1]),

    .clb (rstn),

    .d (clk_en[1]),

    .o (sync_clken_out[1])

    );

    always @(posedge src_clk_inv[index] or negedge rstn)

    if(!rstn)

    begin

    n_en_reg[0] <= 1'b1 ;

    n_en_reg_dly[0] <= 1'b1 ;

    n_en_reg[1] <= 1'b0 ;

    n_en_reg_dly[1] <= 1'b0 ;

    end

    else

    begin

    n_en_reg[index] <= sync_clken_out[index] ;

    n_en_reg_dly[index] <= n_en_reg[index] ;

    end

    endgenerate

    assign clk_en[0] = ~sel & (!n_en_reg_dly[1]) ;

    assign clk_en[1] = sel & (!n_en_reg_dly[0]) ;

    //and gate

    assign out_clk_and[0] = n_en_reg[0] & i_clk[0];

    assign out_clk_and[1] = n_en_reg[1] & i_clk[1];

    //or gate

    assign o_clk = out_clk_and[0] | out_clk_and[1];

    endmodule

    仿真结果图: 多时钟源的源码可以参考下面这篇文章:多是中源切换MUX

    方法二:

    `timescale 1ns/100ps

    module clk_switch (

    out_clk, // Outputs

    clk_a, clk_b, select // Inputs

    );

    input clk_a;

    input clk_b;

    input select;

    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

    测试文件:

    module clk_switch_tb;

    reg clk_a,clk_b;

    reg select;

    wire out_clk;

    clk_switch clk_switch(clk_a,clk_b,select,out_clk);

    initial begin

    clk_a = 0;

    forever #50 clk_a = !clk_a;

    end

    initial begin

    clk_b = 0;

    forever #10 clk_b = !clk_b;

    end

    initial begin

    select = 0;

    #1000;

    select = 1;

    #1000;

    select = 0;

    #1000;

    select = 1;

    #1000;

    $finish;

    end

    endmodule

    仿真结果图:

    方法三:

    `timescale 1ns/10ps

    module clock_mux (

    // OUTPUTs

    //=========

    output clk_out, // Clock output

    // INPUTs

    //=========

    input clk_in0, // Clock input 0

    input clk_in1, // Clock input 1

    input reset, // Reset

    input select_in // Clock selection

    );

    //----------------------------------------

    // Regs declare

    //----------------------------------------

    reg dff0a,dff0b;

    reg dff1a,dff1b;

    wire clk_in0_inv = ~clk_in0;

    wire clk_in1_inv = ~clk_in1;

    //----------------------------------------

    // clk_in0 path

    //----------------------------------------

    // negedge of clk_in0

    always @(posedge clk_in0_inv or posedge reset)

    if(reset)

    dff0a <= 1'b1;

    else

    dff0a <= !select_in & !dff1b;

    always @(posedge clk_in0 or posedge reset)

    if(reset)

    dff0b <= 1'b1;

    else

    dff0b <= dff0a;

    wire clk_in0_gate = ~(~clk_in0 & dff0b);

    //----------------------------------------

    // clk_in1 path

    //----------------------------------------

    // negedge of clk_in1

    always @(posedge clk_in1_inv or posedge reset)

    if(reset)

    dff1a <= 1'b0;

    else

    dff1a <= select_in & !dff0b;

    always @(posedge clk_in1 or posedge reset)

    if(reset)

    dff1b <= 1'b0;

    else

    dff1b <= dff1a;

    wire clk_in1_gate = ~(~clk_in1 & dff1b);

    //-----------------------

    // clock mux out

    //-----------------------

    assign clk_out = clk_in0_gate & clk_in1_gate;

    endmodule

    欢迎关注下面公众号,每周精选一篇原创文章!!!

    凭什么说天蝎座为什么是12星座之王
    植物种子的传播方式有哪些?10种植物的传播方式介绍

    友情链接:


    Copyright © 2022 剑侠盟·网游特攻队 All Rights Reserved.