zoukankan      html  css  js  c++  java
  • 关于双独立时钟fifo的一些细节探讨

       最近遇到一个项目,就是接收数据转换成本地数据。两个时钟是频率是基本一样,但是存在5%偏差,而且存在相位差。

     这是基本需求。一般转换的办法就是fifo写入有效数据,然后用empty读取出来。但是发现有个问题。就是如果两个帧之间间隔太短了,会导致读取的时候,两帧的数据会连续成一帧数据。解决办法就是把写使能也要加入到fifo中,把前后使能无效+数据,也是写入到fifo,恢复的时候再恢复到有效数据。

    wire wrfifo_wren;
    assign wrfifo_wren = serdes_en_d2 | serdes_en;

    wire[32:0] wrfifo_wrdata;
    assign wrfifo_wrdata = { serdes_en_d0,rx_data_lock_d0};

        二个关于频率偏差问题,很多人都是内部count 来判断,好在xilinx由prog-empty,可以编程的empty,选择两个状态。这样在拉低信号,判断fifo是否写入数据,再读取。

          .prog_empty(fifo_almost_empty)
       );
      
     reg fifo_almost_empty_d0;
     reg fifo_almost_empty_d1;
     reg fifo_almost_empty_d2;
     reg fifo_almost_empty_d3;
     reg fifo_almost_empty_d4;
      always @(posedge    ref_clk)
     begin
        fifo_almost_empty_d0 <= fifo_almost_empty;
        fifo_almost_empty_d1 <= fifo_almost_empty_d0;
        fifo_almost_empty_d2 <= fifo_almost_empty_d1;
        fifo_almost_empty_d3 <= fifo_almost_empty_d2;
        fifo_almost_empty_d4 <= fifo_almost_empty_d3;
     end
     
     reg fifo_rd_en_temp ;
     always @(posedge    ref_clk)
     begin
        if( fifo_almost_empty_d4 == 0)
            fifo_rd_en_temp <= 1;
         else if( fifo_empty)
            fifo_rd_en_temp <= 0; 
      end 

    三个问题,fifo其中写的时钟会波动,中途可能会停掉,因为上电复位过程会停止时钟,中途也会停止时钟。很多fifo对这个时钟是没有讲解的,发现的现象竟然是full信号一直为慢的信号。empty也是空的信号,后面的数据根本写入不了。解决办法就是,直接判断full信号,复位fifo。这样稳定时钟又可以写入数据。

    注意同步复位,要求是最慢的时钟的三个时钟以上有效。

    wire lock_fail_rising;
    assign lock_fail_rising = (( lock_fail_temp_d1 == 1'b0) & (lock_fail_temp_d0 ==1'b1));

    wire       fifo_full;
    reg fifo_full_d0;
    reg fifo_full_d1;
    reg fifo_full_d2;
    always @(posedge    ref_clk)
    begin
        fifo_full_d0 <= fifo_full;
        fifo_full_d1 <= fifo_full_d0;
        fifo_full_d2 <= fifo_full_d1;
    end
    reg lock_fail_rising_d0;
    reg lock_fail_rising_d1;
    reg lock_fail_rising_d2;
    reg lock_fail_rising_d3;
    reg lock_fail_rising_d4;
    reg lock_fail_rising_d5;
    reg lock_fail_rising_d6;
    always @(posedge    ref_clk)
    begin
        lock_fail_rising_d0 <= lock_fail_rising| fifo_full_d2 ;
        lock_fail_rising_d1 <= lock_fail_rising_d0;
        lock_fail_rising_d2 <= lock_fail_rising_d1;
        lock_fail_rising_d3 <= lock_fail_rising_d2; 
        lock_fail_rising_d4 <= lock_fail_rising_d3; 
        lock_fail_rising_d5 <= lock_fail_rising_d4; 
        lock_fail_rising_d6 <= lock_fail_rising_d5; 
    end


    assign rd_rst = lock_fail_rising_d6 | lock_fail_rising_d0;

  • 相关阅读:
    poj-1001 求高精度幂
    ECS训练营Day1—基于阿里云ECS、VuePress搭建静态网站
    阿里云免费领马克杯答案
    白盒测试之逻辑覆盖 简单易懂~
    如何合并多个PPT?
    failed to connect to gitee.com/github/gitlab port 443: timed out之类的错误
    解决 These dependencies were not found: * core-js/modules/es6.array.fill in xxx 之类的问题
    vue内嵌iframe跨域通信
    Luffy之课程详情页
    Flask之SQLAlchemy,flask_session以及蓝图
  • 原文地址:https://www.cnblogs.com/fpga-design/p/14187393.html
Copyright © 2011-2022 走看看