• 每日一摘:跨时钟域


    假如设计有两个输入时钟,如图所示,一个时钟给接口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
  • 相关阅读:
    【eclipse】Server Tomcat v9.0 Server at localhost failed to start.
    【eclipse】运行maven项目clean tomcat7:run报错
    window下安装redis报错: creating server tcp listening socket 127.0.0.1:6379: bind No error
    【eclipse】svn在线安装
    【eclipse】点Clean后没反应
    谷歌浏览器&360浏览器安装——有道云笔记插件
    阿里云企业邮箱设置
    PyTorch 高级实战教程:基于 BI-LSTM CRF 实现命名实体识别和中文分词
    最全Pycharm教程(43)——Pycharm扩展功能之UML类图使用 代码结构
    精选Pycharm里6大神器插件
  • 原文地址:https://www.cnblogs.com/FPGAer/p/14121554.html
Copyright © 2020-2023  润新知