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;

  • 相关阅读:
    随便 构思 一个 计算 解析积分 的 简单 的 数学软件
    为什么要 拿 光 的 干涉条纹 宽度 变化 作为 判断 光速 变化 的 依据 ?
    相对论 的 几个问题
    设计 逻辑电路 的 开关元件 (2)
    设计 逻辑电路 的 开关元件
    用 逻辑电路 实现一个 开平方 算法
    小梦 在 民科吧 发了一个 用 四则运算 开平方 的 帖
    物理学 的 基本原理
    和 小梦 探讨 一个 经典力学 问题
    二分法 比 跨越步进法 快
  • 原文地址:https://www.cnblogs.com/fpga-design/p/14187393.html
Copyright © 2011-2022 走看看