0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

同步FIFO設(shè)計(下)

冬至子 ? 來源:兩猿社 ? 作者:IC猿 ? 2023-06-05 14:44 ? 次閱讀

00回顧

前面的文章我們講了亞穩(wěn)態(tài)的產(chǎn)生,是由于觸發(fā)器在工作過程中存在數(shù)據(jù)的建立時間和保持時間。在上升沿觸發(fā)電路中,建立時間就是在時鐘上升沿到來之前,觸發(fā)器數(shù)據(jù)保持穩(wěn)定的最小時間;而保持時間就是在時鐘上升沿到來之后,觸發(fā)器數(shù)據(jù)端數(shù)據(jù)還應(yīng)該保持的最小時間。如果數(shù)據(jù)在時鐘上升沿前后的這個窗口內(nèi)發(fā)生改變,即違反了建立保持時間,會使觸發(fā)器工作在一個不穩(wěn)定的狀態(tài),影響下一級觸發(fā)器,發(fā)生連鎖反應(yīng)使整個系統(tǒng)工作失常。

異步FIFO是一種重要的異步時鐘域的數(shù)據(jù)同步手段,在實際應(yīng)用中非常常見,面試時也作為??碱}型出現(xiàn)在視野中。但是如何設(shè)計一個高可靠性、高速的異步FIFO也是一個難點。

UART項目內(nèi)部雖然只使用了同步FIFO實現(xiàn)數(shù)據(jù)的緩存,但咱們趁熱打鐵,將異步FIFO的原理和設(shè)計中需要關(guān)注的地方一并講透,可以說干貨滿滿,建議收藏~

01異步FIFO結(jié)構(gòu)

圖片

異步FIFO架構(gòu)

異步FIFO主要是由 端口存儲器 、 寫指針產(chǎn)生邏輯 、讀指針產(chǎn)生邏輯空滿標(biāo)志產(chǎn)生邏輯4部分組成。讀寫操作是由兩個完全不同時鐘域的時鐘所控制。在寫時鐘域部分,由寫指針產(chǎn)生邏輯生成寫端口所需要的寫地址和寫控制信號;在讀時鐘域部分,由讀指針產(chǎn)生邏輯生成讀端口所需要的讀地址和讀控制信號;在空滿標(biāo)志產(chǎn)生部分,通常是把寫指針與讀指針相互比較產(chǎn)生空滿標(biāo)志。讀寫時鐘屬于不同的時鐘域,如何同步異步信號,使觸發(fā)器不產(chǎn)生亞穩(wěn)態(tài)及如何正確地設(shè)計空、滿信號的控制電路,使FIFO不會溢出,造成數(shù)據(jù)丟失是異步FIFO設(shè)計的兩個難點。

指針實現(xiàn)方式

  • 使用二進制方式實現(xiàn)指針

以寫指針為例。在寫請求有效時,寫指針在時鐘上升沿來時遞增。同樣在讀請求有效時,讀指針在讀時鐘沿來時遞增。在產(chǎn)生空滿信號時,需要比較讀寫指針,由于兩個指針分屬于不同的時鐘域,彼此之間異步,在使用二進制計數(shù)器實現(xiàn)指針時, 可能會導(dǎo)致用于比較的指針采樣錯誤 。

比如,二進制的值會從1111變?yōu)?000,這時所有位都會發(fā)生改變。雖然同步以后可以有效避免亞穩(wěn)態(tài),但是仍然可能得到錯誤的采樣值。

從1111到0000轉(zhuǎn)換可能的中間值:

1111 —> 0000

1111 —> 0001

1111 —> 0010

1111 —> 0011

1111 —> 0100

1111 —> 0101

1111 —> 0110

1111 —> 0111

1111 —> 1000

1111 —> 1001

1111 —> 1010

1111 —> 1011

1111 —> 1100

1111 —> 1101

1111 —> 1110

1111 —> 1111

如果同步時鐘沿在1111向0000轉(zhuǎn)換的中間某個位置到來,就可能將四位2進制的任何值采樣同步到新的時鐘域中。而FIFO空滿信號產(chǎn)生使用錯誤的指針將產(chǎn)生誤標(biāo)志,從而使FIFO滿時沒有正確產(chǎn)生滿標(biāo)志,導(dǎo)致數(shù)據(jù)丟失;FIFO空時沒有正確產(chǎn)生空標(biāo)志,導(dǎo)致讀出垃圾數(shù)據(jù)。

所以采用二進制方式實現(xiàn)指針不是最終的方案,建議盡量避免使用二進制計數(shù)產(chǎn)生指針。

** 使用格雷碼方式實現(xiàn)指針

1.jpg

2.jpg

格雷碼(gray)相對于二進制的優(yōu)勢在于:格雷碼 從一個數(shù)變?yōu)橄乱粋€數(shù)時只有一位發(fā)生變化 。

所以格雷碼在轉(zhuǎn)換時最多只會出現(xiàn)一位錯誤。比如從1000變?yōu)?000時,兩級同步器采樣要么為1000(舊值),要么為0000(新值),而不會出現(xiàn)其他的值。這樣就可以避免產(chǎn)生錯誤的空滿標(biāo)志。

在格雷碼實現(xiàn)FIFO指針時需要注意, 對于寫邏輯部分,產(chǎn)生寫滿信號需要對讀指針(格雷碼)進行同步;對于讀邏輯部分,產(chǎn)生讀空信號需要對寫指針(格雷碼)進行同步 。

有人要問了,使用兩級同步器對指針同步時,不可避免的會產(chǎn)生兩個時鐘的延遲,這個延遲會不會對讀寫數(shù)據(jù)產(chǎn)生?別急,我會掰開來講清楚的。我們先講講二進制和格雷碼的相互轉(zhuǎn)換。

  • 兩種格雷碼計數(shù)器

上面我們已經(jīng)講了格雷碼這種編碼方式可以有效的避免絕大部分錯誤。那怎么產(chǎn)生格雷碼編碼方式的讀寫指針呢?別看格雷碼計數(shù)器看起來復(fù)雜,實現(xiàn)起來其實很簡單。這里有兩種方案產(chǎn)生讀寫指針。

方案A:

圖片

方案A

步驟1:將格雷碼轉(zhuǎn)換為二進制值;

步驟2:根據(jù)條件遞增二進制值;

步驟3:將二進制值轉(zhuǎn)換為格雷碼;

步驟4:將計數(shù)器的最終格雷碼值保存到寄存器中。方案B:

圖片

方案B

步驟1:根據(jù)條件遞增二進制值;

步驟2:將二進制值保存到寄存器中,同時將二進制值轉(zhuǎn)換為格雷碼;

步驟3:將計數(shù)器的最終格雷碼值保存到寄存器中。這兩種方案有什么區(qū)別?

可以發(fā)現(xiàn),方案A的讀寫指針產(chǎn)生必須經(jīng)過相對復(fù)雜的二進制和格雷碼的相互轉(zhuǎn)換邏輯和遞增邏輯,這條組合邏輯極有可能 限制FIFO的最高工作頻率 ,成為關(guān)鍵路徑。

方案B將二進制值的結(jié)果保存在一組額外的寄存器中,雖然增加了電路的面積(這點面積基本沒有影響),但避免了復(fù)雜的組合邏輯,可以 提高系統(tǒng)工作頻率 。

格雷碼和二進制相互轉(zhuǎn)換

  • 格雷碼到二進制的轉(zhuǎn)換

格雷碼轉(zhuǎn)換為二進制的公式為:

1.jpg

對于n位計數(shù)器來說,i

例如當(dāng)n=4時,對應(yīng)的格雷碼到二進制的轉(zhuǎn)換為:

bin[0] = gray[0] ^ gray[1] ^ gray[2] ^ gray[3]

bin[1] = gray[1] ^ gray[2] ^ gray[3]

bin[2] = gray[2] ^ gray[3]

bin[3] = gray[3]

可以看出,bin[3]是通過將格雷值右移3位得到;bin[2]是通過將格雷值右移2位得到;bin[1]是將格雷值右移1位得到;bin[0]是將格雷值右移0位得到。(右移后需按位異或)

下面是格雷碼到二進制轉(zhuǎn)換的Verilog代碼。

module gray_to_bin(bin,gray);
parameter SIZE=4;
input  [SIZE-1:0]   gray;
output [SIZE-1:0]   bin;
reg    [SIZE-1:0]   bin;

integer i;
always @(*) begin
    for(i=0;i<=SIZE;i=i+1)
        bin = ^(gray >>i);
end
endmodule
  • 二進制到格雷碼的轉(zhuǎn)換

二進制到格雷碼的轉(zhuǎn)換公式為:

1.jpg

同樣,對于n位計數(shù)器來說,i

例如當(dāng)n=4時,對應(yīng)的二進制到格雷碼的轉(zhuǎn)換為:

gray[0] = bin[0] ^ bin[1]

gray[1] = bin[1] ^ bin[2]

gray[2] = bin[2] ^ bin[3]

gray[3] = bin[3]

可以看出,可以通過逐位異或,或者將二進制碼右移后與自身異或的操作,計算出對應(yīng)的格雷碼。

下面是二進制到格雷碼轉(zhuǎn)換的Verilog代碼:

module bin_to_gray(bin,gray);
parameter SIZE=4;
input  [SIZE-1:0]   bin;
output [SIZE-1:0]   gray;

assign gray = (bin >>1) ^ bin;
endmodule

格雷碼計數(shù)器實現(xiàn)

本格雷碼計數(shù)器采用方案B實現(xiàn),可有效提高FIFO的最大操作頻率。所以不會涉及到格雷碼到二進制的轉(zhuǎn)換。

根據(jù)上文中格雷碼和二進制碼的特點,細(xì)心的同學(xué)可以發(fā)現(xiàn),格雷碼和二進制碼的最高位是相同的,所以只需對低三位進行格雷碼的轉(zhuǎn)換。以寫指針為例,具體實現(xiàn)方式如下:

parameter   SIZE=4;
reg  [SIZE:0] wbin,wbnext;
reg  [SIZE:0] wptr,wgnext;

always @(posedge wclk ornegedge rst_n) begin
    if(!rst_n) begin
        wbin           <= 'h0;
        wptr[SIZE-1:0] <= 'h0;
    end
    elsebegin
        wbin           <= wbnext;
        wptr[SIZE-1:0] <= wgnext[SIZE-1:0];
    end
end

always @(*) wptr[SIZE] = wbin[SIZE];

assign wbnext = !wfull ? wbin+winc : wbin;
assign wgnext[SIZE-1:0] = (wbnext[SIZE-1:0] >>1) ^ wbnext[SIZE-1:0];

指針同步后的影響

在FIFO中,F(xiàn)IFO寫滿時不應(yīng)該再向FIFO中寫數(shù)據(jù),避免造成FIFO溢出,導(dǎo)致數(shù)據(jù)丟失。所以在寫時鐘域,需要將寫指針和同步后的讀指針進行比較,產(chǎn)生寫滿標(biāo)志。下面我將舉例說明將讀指針同步到寫時鐘域后對寫滿標(biāo)志和寫數(shù)據(jù)的影響。

在最初的t0時刻,讀寫指針都為0。隨著后續(xù)數(shù)據(jù)寫入FIFO,寫指針遞增。當(dāng)?shù)竭_t5時刻時,F(xiàn)IFO寫滿,讀寫指針相等,寫滿信號wfull由0變?yōu)?。

如果在t6時刻發(fā)生了讀操作,由于兩級同步器包含兩個觸發(fā)器,將讀指針同步到寫時鐘域會導(dǎo)致讀指針在兩個寫時鐘后出現(xiàn),寫滿信號wfull在t6和t7時刻都為1,t7時刻后變?yōu)?。這雖然增加了阻止數(shù)據(jù)寫入的周期(2 wclk cycle),但是對數(shù)據(jù)的準(zhǔn)確性無任何影響。

圖片

空滿邏輯同步后效果

類似的,在FIFO空時也會阻止FIFO的讀操作。

FIFO的讀空信號產(chǎn)生是把寫指針同步到讀時鐘域和讀指針進行比較。

在t10時刻,寫指針等于讀指針,此時FIFO為空。若t11時刻時開始向FIFO寫入數(shù)據(jù),t11,t12時刻雖然FIFO不為空,但是由于兩級同步器的延時,此時讀空信號rempty仍然為1,這會阻止FIFO的讀操作,但這是無害的。在t12時刻后,rempty釋放,此時FIFO可以開始讀操作。

在將滿時通知寫的一邊FIFO已滿,在將空時通知讀的一邊FIFO已空都是可以的,即使同步后的指針存在延時,阻止寫/讀的影響會使FIFO掛起一段時間,但不會導(dǎo)致任何錯誤。

空滿信號產(chǎn)生

空滿標(biāo)志的產(chǎn)生是異步FIFO設(shè)計的核心。如何正確設(shè)計此部分的邏輯,會直接影響到FIFO的性能。空滿標(biāo)志的產(chǎn)生原則是: 寫滿不溢出,讀空不多讀 。

最直接的做法是采用讀寫指針相比較來產(chǎn)生空滿標(biāo)志。當(dāng)讀寫指針的差值等于一個預(yù)設(shè)值時,空滿信號被置位。這種實現(xiàn)方式邏輯簡單,但是它的減法器形成了一個比較大的組合邏輯。限制了FIFO的速度。

所以一般采用相等或是不相等的比較邏輯,避免使用減法器。采用直接比較的方法必須區(qū)分當(dāng)讀寫地址相等的時候是空還是滿,所以必須增加額外的1位控制信號來區(qū)分空滿標(biāo)志。

以16x16異步FIFO為例,寫指針wptr[4:0],讀指針rptr[4:0],其中低三位為真正的讀寫地址,最高位用來區(qū)分空滿。

若讀寫指針完全相等,表示讀地址追上了寫地址,此時FIFO為空;若最高位相反但其余位相同,表示寫地址領(lǐng)先讀地址一個周期,此時FIFO為滿。

讀寫指針比較產(chǎn)生空滿標(biāo)志rempty和wfull,將寫指針同步到讀時鐘域,產(chǎn)生讀空信號rempty控制異步FIFO的讀操作;將讀指針同步到寫時鐘域,產(chǎn)生寫滿信號wfull控制異步FIFO的寫操作。

空滿信號的Verilog實現(xiàn)如下:

wire            wfull;
wire            rempty;
reg  [SIZE:0]   wptr_reg1;
reg  [SIZE:0]   wptr_reg2;
reg  [SIZE:0]   rptr_reg1;
reg  [SIZE:0]   rptr_reg2;

// 寫指針在讀時鐘域的兩級同步
always @(posedge rclk ornegedge rst_n) begin
    if(!rst_n) begin
        wptr_reg1 <= 'h0;
        wptr_reg2 <= 'h0;
    end
    elsebegin
        wptr_reg1 <= wptr;
        wptr_reg2 <= wptr_reg1;
    end
end
// 讀指針在寫時鐘域的兩級同步
always @(posedge wclk ornegedge rst_n) begin
    if(!rst_n) begin
        rptr_reg1 <= 'h0;
        rptr_reg2 <= 'h0;
    end
    elsebegin
        rptr_reg1 <= rptr;
        rptr_reg2 <= rptr_reg1;
    end
end

//空滿標(biāo)志產(chǎn)生
assign wfull  = ({!wptr[SIZE],wptr[SIZE-1:0]}==rptr_reg2)? 1'b1 : 1'b0;
assign rempty = (wptr_reg2==rptr)? 1'b1:1'b0;

好了,異步FIFO到這里講完了,大家可以試試自己寫一個異步FIFO,調(diào)整讀寫時鐘的頻率和比例,進行前后仿真看看性能怎樣呢~

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 存儲器
    +關(guān)注

    關(guān)注

    38

    文章

    7376

    瀏覽量

    163143
  • 控制電路
    +關(guān)注

    關(guān)注

    81

    文章

    1696

    瀏覽量

    135593
  • 觸發(fā)器
    +關(guān)注

    關(guān)注

    14

    文章

    1990

    瀏覽量

    60911
  • FIFO存儲
    +關(guān)注

    關(guān)注

    0

    文章

    103

    瀏覽量

    5946
  • 異步時鐘
    +關(guān)注

    關(guān)注

    0

    文章

    17

    瀏覽量

    9394
收藏 人收藏

    評論

    相關(guān)推薦

    同步FIFO設(shè)計詳解及代碼分享

    FIFO (先入先出, First In First Out )存儲器,在 FPGA 和數(shù)字 IC 設(shè)計中非常常用。 根據(jù)接入的時鐘信號,可以分為同步 FIFO 和異步 FIFO
    發(fā)表于 06-27 10:24 ?1864次閱讀
    <b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>設(shè)計詳解及代碼分享

    握手型接口的同步FIFO實現(xiàn)

    按照正常的思路,在前文完成前向時序優(yōu)化和后向時序優(yōu)化后,后面緊跟的應(yīng)該是雙向時序優(yōu)化策略了,不過不急,需要先實現(xiàn)一握手型同步FIFO。
    的頭像 發(fā)表于 12-04 14:03 ?551次閱讀
    握手型接口的<b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>實現(xiàn)

    關(guān)于同步fifo做緩存的問題

    異步fifo是用于跨時域時鐘傳輸?shù)?,但?b class='flag-5'>同步fifo做緩存我就不是很理解了,到底這個緩存是什么意思,這樣一進一出,不是數(shù)據(jù)的傳輸嗎,為什么加個fifo,還有,如果是兩組視頻流傳輸,在切
    發(fā)表于 08-27 19:23

    同步FIFO和異步FIFO各在什么情況應(yīng)用

    我想問一什么情況需要用異步FIFO,什么情況同步FIFO?
    發(fā)表于 11-03 17:19

    異步FIFO的設(shè)計分析及詳細(xì)代碼

    (每個數(shù)據(jù)的位寬) FIFO同步和異步兩種,同步即讀寫時鐘相同,異步即讀寫時鐘不相同 同步FIFO用的少,可以作為數(shù)據(jù)緩存 異步
    發(fā)表于 11-15 12:52 ?8456次閱讀
    異步<b class='flag-5'>FIFO</b>的設(shè)計分析及詳細(xì)代碼

    FPGA之FIFO練習(xí)3:設(shè)計思路

    根據(jù)FIFO工作的時鐘域,可以將FIFO分為同步FIFO和異步FIFO。同步
    的頭像 發(fā)表于 11-29 07:08 ?1798次閱讀

    同步FIFO之Verilog實現(xiàn)

    FIFO的分類根均FIFO工作的時鐘域,可以將FIFO分為同步FIFO和異步FIFO。
    的頭像 發(fā)表于 11-01 09:57 ?1735次閱讀

    FIFO設(shè)計—同步FIFO

    FIFO是異步數(shù)據(jù)傳輸時常用的存儲器,多bit數(shù)據(jù)異步傳輸時,無論是從快時鐘域到慢時鐘域,還是從慢時鐘域到快時鐘域,都可以使用FIFO處理。
    發(fā)表于 05-26 16:12 ?1416次閱讀
    <b class='flag-5'>FIFO</b>設(shè)計—<b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>

    FIFO設(shè)計—異步FIFO

    異步FIFO主要由五部分組成:寫控制端、讀控制端、FIFO Memory和兩個時鐘同步
    發(fā)表于 05-26 16:17 ?1461次閱讀
    <b class='flag-5'>FIFO</b>設(shè)計—異步<b class='flag-5'>FIFO</b>

    一個簡單的RTL同步FIFO設(shè)計

    FIFO 是FPGA設(shè)計中最有用的模塊之一。FIFO 在模塊之間提供簡單的握手和同步機制,是設(shè)計人員將數(shù)據(jù)從一個模塊傳輸?shù)搅硪粋€模塊的常用選擇。
    發(fā)表于 06-14 08:59 ?387次閱讀

    基于寄存器的同步FIFO

    ? FIFO 是FPGA設(shè)計中最有用的模塊之一。FIFO 在模塊之間提供簡單的握手和同步機制,是設(shè)計人員將數(shù)據(jù)從一個模塊傳輸?shù)搅硪粋€模塊的常用選擇。 在這篇文章中,展示了一個簡單的 RTL
    的頭像 發(fā)表于 06-14 09:02 ?664次閱讀

    基于Verilog的同步FIFO的設(shè)計方法

    同步FIFO的設(shè)計主要包括讀寫地址的產(chǎn)生、數(shù)據(jù)的讀寫、以及狀態(tài)的控制。下面我們將分別介紹這三個方面的設(shè)計。
    發(fā)表于 08-31 12:53 ?586次閱讀

    同步FIFO設(shè)計分析

    模塊雖小但是要有新意,首先寫一個同步FIFO,這是一個爛大街的入門級項目,但是我肯定不會寫的那么簡單
    的頭像 發(fā)表于 09-11 17:11 ?529次閱讀
    <b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>設(shè)計分析

    同步FIFO和異步FIFO的區(qū)別 同步FIFO和異步FIFO各在什么情況應(yīng)用

    同步FIFO和異步FIFO的區(qū)別 同步FIFO和異步FIFO各在什么情況
    的頭像 發(fā)表于 10-18 15:23 ?1492次閱讀

    同步FIFO和異步FIFO區(qū)別介紹

    1. FIFO簡介 FIFO是一種先進先出數(shù)據(jù)緩存器,它與普通存儲器的區(qū)別是沒有外部讀寫地址線,使用起來非常簡單,缺點是只能順序讀寫,而不能隨機讀寫。 2. 使用場景 數(shù)據(jù)緩沖:也就是數(shù)據(jù)寫入過快
    的頭像 發(fā)表于 06-04 14:27 ?832次閱讀
    <b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>和異步<b class='flag-5'>FIFO</b>區(qū)別介紹