<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] > # 簡介 **FIFO**(First input First output)簡單說就是指先進先出。 **FIFO的作用:** * 增加數據傳輸率 * 處理大量數據流 * 匹配不同傳輸率的系統 * 對連續的[數據流](https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E6%B5%81)進行緩存,防止在進機和存儲操作時丟失數據 * 數據集中起來進行進機和存儲,可避免頻繁的總線操作,減輕CPU的負擔 * 允許系統進行DMA操作,提高數據的傳輸速度 ## 一些關鍵點 * FIFO的本質是RAM,先進先出 * FIFO深度:簡單來說就是需要存多少個數據 * FIFO位寬:每個數據的寬度 * FIFO有同步和異步兩種,**同步即讀寫時鐘相同,異步即讀寫時鐘不相同** * 同步FIFO用的少,可以作為數據緩存 * 異步FIFO可以解決跨時鐘域的問題,在應用時需根據實際情況考慮好fifo深度即可 ># 同步FIFO的實現 fifo中的ram一般是雙端口ram,所以有獨立的讀寫地址。因此可以一種是設置**讀,寫指針**,寫指針指向下一個要寫入數據的地址,讀指針指向下一個要讀的地址,最后通過比較讀指針和寫指針的大小來確定空滿狀態。</br> 設置一個計數器,當寫使能有效的時候計數器加一;當讀使能有效的時候,計數器減一,將計數器與ram的size進行比較來判斷fifo的空滿狀態。這種方法設計比較簡單,但是需要的額外的計數器,就會產生額外的資源,而且當fifo比較大時,會降低fifo最終可以達到的速度。 ># 異步FIFO的設計 ## 讀空信號如何產生?寫滿信號如何產生? **讀空信號**:復位的時候,讀指針和寫指針相等,讀空信號有效(這里所說的指針其實就是讀地址、寫地址)當讀指針趕上寫指針的時候,寫指針等于讀指針意味著最后一個數據被讀完,此時讀空信號有效</br> **寫滿信號**:當寫指針比讀指針多一圈時,寫指針等于讀指針意味著寫滿了,此時寫滿信號有效。我們會發現讀空的條件是寫指針等于讀指針,寫滿的條件也是寫指針等于讀指針,到底如何區分呢?</br> **解決方法**:將指針的位寬多定義一位</br> 舉個例子說明:假設要設計深度為8的異步FIFO,此時定義讀寫指針只需要3位(2^3=8)就夠用了,但是我們在設計時將指針的位寬設計成4位,最高位的作用就是區分是讀空還是寫滿,具體**理論1**如下 >**當最高位相同,其余位相同認為是讀空** >**當最高位不同,其余位相同認為是寫滿** 注意:理論1試用的是二進制數之間的空滿比較判斷。 使用格雷碼時: 用格雷碼判斷是否為讀空或寫滿時應使用**理論2**,看最高位和次高位是否相等,具體如下: >**當最高位和次高位相同,其余位相同認為是讀空** >**當最高位和次高位不同,其余位相同認為是寫滿** 補:理論2這個判斷方法適用于用格雷碼判斷比較空滿</br> 在實際設計中如果不想用格雷碼比較,就可以利用格雷碼將讀寫地址同步到一個時鐘域后再將格雷碼再次轉化成二進制數再用理論1進行比較就好了。 ## 由于是異步FIFO的設計,讀寫時鐘不一樣,在產生讀空信號和寫滿信號時,會涉及到跨時鐘域的問題,如何解決? **跨時鐘域的問題:** 上面我們已經提到要通過比較讀寫指針來判斷產生讀空和寫滿信號,但是讀指針是屬于讀時鐘域的,寫指針是屬于寫時鐘域的,而異步FIFO的讀寫時鐘域不同,是異步的,要是將讀時鐘域的讀指針與寫時鐘域的寫指針不做任何處理直接比較肯定是錯誤的,因此我們需要進行同步處理以后仔進行比較 **解決方法**:**兩級寄存器同步****+格雷碼**</br> 同步的過程有兩個: **(1)將寫時鐘域的寫指針同步到讀時鐘域,將同步后的寫指針與讀時鐘域的讀指針進行比較產生讀空信號** **(2)將讀時鐘域的讀指針同步到寫時鐘域,將同步后的讀指針與寫時鐘域的寫指針進行比較產生寫滿信號**</br> 同步的思想就是用**兩級寄存器同步**,簡單說就是打兩拍,相信有點基礎的早都爛熟于心,就不再多做解釋,不懂的可以看看代碼結合理解。</br> 只是這樣簡單的同步就可以了嗎?no no no,可怕的亞穩態還在等著你。</br> 我們如果直接用二進制編碼的讀寫指針去完成上述的兩種同步是不行的,使用格雷碼更合適,為什么呢?</br> 因為二進制編碼的指針在跳變的時候有可能是多位數據一起變化,如二進制的7-->8即0111--> 1000 ,在跳變的過程中4位全部發生了改變,這樣很容易產生毛刺,例如異步FIFO的寫指針和讀指針分屬不同時鐘域,這樣指針在進行同步過程中很容易出錯,比如寫指針在從0111到1000跳變時4位同時改變,這樣讀時鐘在進行寫指針同步后得到的寫指針可能是0000-1111的某個值,一共有2^4個可能的情況,而這些都是不可控制的,你并不能確定會出現哪個值,那出錯的概率非常大,怎么辦呢?到了格雷碼發揮作用的時候了,而格雷碼的編碼特點是相鄰位每次只有1位發生變化,這樣在進行指針同步的時候,只有兩種可能出現的情況:1.指針同步正確,正是我們所要的;2.指針同步出錯,舉例假設格雷碼寫指針從000->001,將寫指針同步到讀時鐘域同步出錯,出錯的結果只可能是000->000,因為相鄰位的格雷碼每次只有一位變化,這個出錯結果實際上也就是寫指針沒有跳變保持不變,我們所關心的就是這個錯誤會不會導致讀空判斷出錯?答案是不會,最多是讓空標志在FIFO不是真正空的時候產生,而不會出現空讀的情形。所以gray碼保證的是同步后的讀寫指針即使在出錯的情形下依然能夠保證FIFO功能的正確性。在同步過程中的亞穩態不可能消除,但是我們只要保證它不會影響我們的正常工作即可。 ## 由于設計的時候讀寫指針用了至少兩級寄存器同步,同步會消耗至少兩個時鐘周期,勢必會使得判斷空或滿有所延遲,這會不會導致設計出錯呢? 異步FIFO通過比較讀寫指針進行滿空判斷,但是讀寫指針屬于不同的時鐘域,所以在比較之前需要先將讀寫指針進行同步處理,將寫指針同步到讀時鐘域再和讀指針比較進行FIFO空狀態判斷,因為在同步寫指針時需要時間,而在這個同步的時間內有可能還會寫入新的數據,因此同步后的寫指針一定是小于或者等于當前實際的寫指針,所以此時判斷FIFO為空不一定是真空,這樣更加保守,一共不會出現空讀的情況,雖然會影響FIFO的性能,但是并不會出錯,同理將讀指針同步到寫時鐘域再和寫指針比較進行FIFO滿狀態判斷,同步后的讀指針一定是小于或者等于當前的讀指針,所以此時判斷FIFO為滿不一定是真滿,這樣更保守,這樣可以保證FIFO的特性:FIFO空之后不能繼續讀取,FIFO滿之后不能繼續寫入。**總結來說異步邏輯轉到同步邏輯不可避免需要額外的時鐘開銷,這會導致滿空趨于保守,但是保守并不等于錯誤,這么寫會稍微有性能損失,但是不會出錯。**</br> **舉個例子:**大多數情形下,異步FIFO兩端的時鐘不是同頻的,或者讀快寫慢,或者讀慢寫快,慢的時鐘域同步到快的時鐘域不會出現漏掉指針的情況,但是將指針從快的時鐘域同步到慢的時鐘域時可能會有指針遺漏,**舉個例子**以讀慢寫快為例,進行滿標志判斷的時候需要將讀指針同步到寫時鐘域,因為讀慢寫快,所以不會有讀指針遺漏,同步消耗時鐘周期,所以同步后的讀指針滯后(小于等于)當前讀地址,所以可能滿標志會提前產生,滿并非真滿。進行空標志判斷的時候需要將寫指針同步到讀指針,因為讀慢寫快,所以當讀時鐘同步寫指針的時候,必然會漏掉一部分寫指針,我們不用關心那到底會漏掉哪些寫指針,我們在乎的是漏掉的指針會對FIFO的空標志產生影響嗎?比如寫指針從0寫到10,期間讀時鐘域只同步捕捉到了3、5、8這三個寫指針而漏掉了其他指針。當同步到8這個寫指針時,真實的寫指針可能已經寫到10,相當于在讀時鐘域還沒來得及覺察的情況下,寫時鐘域可能偷偷寫了數據到FIFO去,這樣在判斷它是不是空的時候會出現不是真正空的情況,漏掉的指針也沒有對FIFO的邏輯操作產生影響。 > # 異步FIFO深度計算 異步FIFO可以解決跨時終域的問題,但是需要注意深度。 ## 異步FIFO最小深度計算 計算FIFO深度是FIFO設計中常遇到的問題。當異步FIFO讀寫端口的throught-put(吞吐量)不同時,會遇到數據丟失的問題,這時就需要考慮FIFO的Deepth問題了,即**為滿足讀寫流暢不卡頓(數據不丟失)時,FIFO的Deepth的最小值**。</br> 計算異步FIFO的最小深度,首先必定是要了解清楚應用場景的,這關乎到FIFO的最小深度的計算。**FIFO主要是用于數據的緩存,用在讀慢寫快的場景下**。異步FIFO讀寫不同頻,我們選用的FIFO要能夠在極端的情況下仍然能夠保證數據的不溢出。因此,**考慮的前提一般都是讀慢寫快的情景(寫時鐘大于讀時鐘)**,但需要注意的是,這里的寫操作是**猝發傳輸**,而不能使連續操作。倘若寫快讀慢的場景下,寫數據流是連續的,那再大的FIFO都會有寫滿的時候,因此無法避免數據的溢出(下面有一個蓄水的例子)。</br> 當**寫快讀慢**時,FIFO便可被用作系統中元件或隊列。因此**FIFO的大小**其實也就暗示了所需**緩存數據的容量**,該**容量**取決于**讀寫數據的速率**。據統計,**系統的數據速率**取決于**系統的負載能力**。因此為了保證FIFO的大小,需要考慮FIFO傳輸的最壞情況。 > **所謂最壞情況,就是使得寫速率最大,讀速率最小;通常是考慮猝發傳輸。** 宏觀看,整個時間域上,"寫數據=讀數據",這個是異步FIFO正常工作最基本的要求,是大前提。由于**寫快讀慢**,在發送方"**突發傳輸**"的發送數據的T內,是很有可能發送方寫數據量>接收方讀取的數據量,那么剩下未讀取的數據必定需要存儲共接收方繼續讀取并不能丟棄,因此FIFO的深度要能夠保證,在這段時間T內,如果接收方未能將發送方發送的數據接收完畢的話,剩下的數據都是可以存儲在FIFO內部而且不會溢出的,那么在發送方停止發送數據的"空閑時隙"內,接收方可以從容地接收剩下來的數據。 ### 異步FIFO最小深度計算原理 **速率的概念** >想象一個場景,有一個水龍頭在不斷向下流水,水龍頭下放著一口缸在接水,而缸上有一個出水口也在源源不斷的出水。假如,水龍頭的單位時間進水量大于出水口的出水量,那么缸內就會開始不斷的積水。如果水龍頭按照這樣持續不斷的進水,那積水必將越來越多,結果就是無論缸多大,早晚都會盛滿溢出的。因此這種供水需要? ?間歇性? ?的地往缸里注水(數據的**猝發傳輸**)。 **全速讀寫,引起的溢出問題:** ![](https://img.kancloud.cn/31/7a/317abd187d846ea2f4393abd2272f8ad_502x315.png) 同樣的道理,如果數據流是在**連續不斷寫**,則FIFO無論多大,只要是讀寫時鐘**不同源同頻**就都會**丟數(****類比可能不太恰當,水缸空了,讀空;水缸滿了,寫數據會覆蓋****)**。這涉及到一個數據的最大連續寫長度(一個cycle寫一個數據)以保證數據的正確傳輸即FIFO能夠完整傳輸數據。</br> ?那到底如何利用異步FIFO呢?一般數據的傳輸會以一定格式的數據包,且以一定頻率進行傳輸,而不是永久的連續傳輸下去。這樣的話,就算是寫快,讀慢,只要保證在寫滿FIFO之前能把一個數據包發送完畢.</br> 很多場景比較簡單,沒有考慮性能和資源的問題,只要Deepth合理就行,比如有時候常取Deepth_value=? ?WR_Burst_len*(Wr_clk/Rd_clk),會選取大于Deepth_vlaue最接近的2^N數值,或是直接對Wr_clk/Rclk向上取整。</br> FIFO常用于緩沖塊數據,一般用在寫快讀慢的情況下,遵循如下規則: ![](https://img.kancloud.cn/2c/62/2c62cbed69d7c610012c1265e267d64e_488x45.png) 本質上就是: ![](https://img.kancloud.cn/3c/83/3c833f28a5eb59ddfb5c8b2ba1eb2100_468x45.png) **例**: A/D采樣速率50Mhz,dsp讀A/D的速率40Mhz,要不丟失地將將10萬個采樣數據送入DSP ,在A/D和DSP之間至少加多大容量的(深度)FIFO才行??(來源網絡) ![](https://img.kancloud.cn/d2/38/d238e05a079c1578e9925c60e7886762_822x539.png) **答**: Deepth/(50000000-40000000)>(100000/50000000) 即Deepth>10\_0000/5=20000。那么最小深度為20k。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看