zoukankan      html  css  js  c++  java
  • 每日一摘:跨时钟域

    假如设计有两个输入时钟,如图所示,一个时钟给接口1使用,另一个时钟给接口2使用,因此这里就会存在跨时钟域的问题。

     跨时钟域的的处理:

    1、单bit:两级D触发器同步

    2、多bit:采用异步fifo,异步双口RAM

    3、加握手信号

    4、格雷码转换


     多级寄存器处理:①慢到快②快到慢

    ①慢到快:输入信号从时钟频率慢同步到时钟频率快

     pulse_b是时钟clk_b下的寄存器信号,在时钟clk_a看来,这是一个很宽的电平信号,保持了多个时钟clk_a周期,所以一定能被clk_a采到。采集过程中必须寄存两拍:第一拍将pulse_b同步化,同步化的输出可能带来建立/保持时间的冲突,从而产生亚稳态,因此需要再寄存一拍,以减少亚稳态带来的影响。一般来说两级是最基本要求,如果是高频率设计,则需要增加寄存级数来大幅降低系统的不稳定性。也就是说采用多级寄存器来采样异步时钟域的信号,级数越多,同步过来的信号越稳定。一般代码设计如下:

    always @ (posedge clk_a or negedge rst_n)
        begin
            if (rst_n == 1'b0) 
                begin
                   pules_a_r1 <= 1'b0;
                   pules_a_r2 <= 1'b0;
                   pules_a_r3 <= 1'b0;
                end
            else 
                begin                                    //打3拍
                   pules_a_r1 <= pulse_b;
                   pules_a_r2 <= pules_a_r1;
                   pules_a_r3 <= pules_a_r2;
                end
        end
    
    assign pulse_a_pos    = pules_a_r2 & (~pules_a_r3);    //上升沿检测
    assign pulse_a_neg    = pules_a_r3 & (~pules_a_r2);    //下降沿检测
    assign pulse_a        = pules_a_r2;        //打了两拍,成功把时钟域clk_b的信号同步到时钟域clk_a

    ②快到慢:输入信号从时钟频率快同步到时钟频率慢

     如果输入的单bit信号从快时钟clk_a同步到慢时钟clk_b,那么存在两种不同的情况:输入信号是电平信号level_a、输入信号是脉冲信号pulse_a。

    实际上,在一般情况下只有电平信号level_a的宽度才能被clk_b采集到,并保证系统正常工作。同理,脉冲信号pulse_a的宽度不够,因此需要用一个展宽信号来替代pulse_a,实现跨时钟域的握手。主要原理就是先把脉冲信号pulse_a在clk_a下展宽,变成电平信号signal_a,再向clk_b传递,当确认clk_b已经“看见”信号同步过去之后,再清掉signal_a。

    //Synchronous
    module Sync_Pulse(
        input           clka,
        input           clkb,
        input           rst_n,
        input           pulse_ina,
        output          pulse_outb,
        output          signal_outb
    );
    
    //-------------------------------------------------------
    reg             signal_a;
    reg             signal_b;
    reg     [1:0]   signal_b_r;
    reg     [1:0]   signal_a_r;
    
    //-------------------------------------------------------
    //在clka下,生成展宽信号signal_a
    always @(posedge clka or negedge rst_n)begin
        if(rst_n == 1'b0)begin
            signal_a <= 1'b0;
        end
        else if(pulse_ina == 1'b1)begin
            signal_a <= 1'b1;
        end
        else if(signal_a_r[1] == 1'b1)
            signal_a <= 1'b0;
        else
            signal_a <= signal_a;
    end
    
    //-------------------------------------------------------
    //在clkb下同步signal_a
    always @(posedge clkb or negedge rst_n)begin
        if(rst_n == 1'b0)begin
            signal_b <= 1'b0;
        end
        else begin
            signal_b <= signal_a;
        end
    end
    
    //-------------------------------------------------------
    //在clkb下生成脉冲信号和输出信号
    always @(posedge clkb or negedge rst_n)begin
        if(rst_n == 1'b0)begin
            signal_b_r <= 2'b00;
        end
        else begin
            signal_b_r <= {signal_b_r[0], signal_b};
        end
    end
    
    assign    pulse_outb = ~signal_b_r[1] & signal_b_r[0];
    assign    signal_outb = signal_b_r[1];   //打了两拍,成功把时钟域clk_a的信号同步到时钟域clk_b
    
    //-------------------------------------------------------
    //在clka下采集signal_b[1],生成signal_a_r[1]用于反馈拉低signal_a
    always @(posedge clka or negedge rst_n)begin
        if(rst_n == 1'b0)begin
            signal_a_r <= 2'b00;
        end
        else begin
            signal_a_r <= {signal_a_r[0], signal_b_r[1]};
        end
    end
    
    endmodule
  • 相关阅读:
    CodeForces Gym 100500A A. Poetry Challenge DFS
    CDOJ 486 Good Morning 傻逼题
    CDOJ 483 Data Structure Problem DFS
    CDOJ 482 Charitable Exchange bfs
    CDOJ 481 Apparent Magnitude 水题
    Codeforces Gym 100637G G. #TheDress 暴力
    Gym 100637F F. The Pool for Lucky Ones 暴力
    Codeforces Gym 100637B B. Lunch 找规律
    Codeforces Gym 100637A A. Nano alarm-clocks 前缀和
    TC SRM 663 div2 B AABB 逆推
  • 原文地址:https://www.cnblogs.com/FPGAer/p/14121554.html
Copyright © 2011-2022 走看看