fifo
本質是ram,其重要引數是深度depth(需要存的資料個數)與寬度width(所存資料的位寬)。fifo有同步和非同步兩種,同步即讀寫時鐘相同,非同步則讀寫時鐘不同。同步fifo可做資料快取,非同步fifo可以解決跨時鐘域的問題,在實際應用中考慮好fifo的深度即可。
通常情況下fifo讀空/寫滿標誌分析
讀空:復位的時候,讀指標和寫指標相等,即位讀空(此處的讀指標即讀位址)。可以理解為,讀指標一直跟在寫指標後面讀資料,當讀指標終於追上寫指標的時候,意味著最後乙個資料被讀出來,讀空。
寫滿:當寫指標超越讀指標一圈的時候,寫指標等於讀指標意味著寫滿了。
由此,讀空的條件是寫指標等於讀指標,寫滿的條件也是寫指標等於讀指標,到底如何區分呢?
解決方法:將指標的位寬多定義一位
舉個例子說明:假設要設計深度為 8 的非同步fifo,此時定義讀寫指標只需要 3 位(2^3=8)就夠用了,
但是我們在設計時將指標的位寬設計成 4 位,最高位的作用就是區分是讀空還是寫滿, 對於二進位制數之間的空滿比較:
當最高位相同,其餘位相同認為是讀空
當最高位不同,其餘位相同認為是寫滿
跨時鐘域傳輸資料–非同步fifo
非同步fifo實現資料交換,防止亞穩態出現;fifo相當於乙個雙埠ram,先進先出,乙個埠由傳送資料的時鐘域控制,用於寫入資料,另乙個埠由接收資料的時鐘域控制,用於讀取資料,因此需要兩個控制訊號來標誌fifo是空、滿還是部分滿的狀態,在實際的實現資料交換的過程中,準確的指示fifo是滿還是空是比較由挑戰的;so,需要考慮一下問題。
1、讀寫時鐘不同,如何正確指示寫滿或者讀空的狀態?
方法:暫存器打兩拍+格雷碼
由於讀指標是屬於讀時鐘域的,寫時針是屬於寫時鐘域的,兩者是非同步的,自是不可不做處理之間進行比較,因此需要進行同步處理以後再比較。
另外將乙個二進位制的計數器數值從乙個時鐘域同步到另乙個時鐘域很容易出錯,因為二進位制計數器自加/減的時候變化的bit位太多,如7->8(0111–>1000)所有bit都變化;此時,同步到另乙個時鐘域的時候很容易出現亞穩態。而取樣格雷碼只有一位傳送變化,則不會出現這個問題。(格雷碼相鄰兩個資料之間只有一位變化,即使在同步過程**現錯誤如,000–>001,導致的結果不過是將原來的狀態同步過去,比如讀同步到寫,結果是在沒滿的時候提前報寫滿,不會覆蓋資料,<=滿。因為前後僅有1bit資料出現變化,也避免了因為多根線之間存在skew而帶來的亞穩態情況)。
so,需要設計乙個二進位製碼轉換格雷碼的電路,將位址值轉換為格雷碼,然後將該格雷碼同步到另外乙個時鐘域進行比對,進行空滿狀態的檢測。
簡述二進位制–>格雷碼的轉換電路實現:
二進位制數右移一位,最高空位補0,逐比特異或運算。
如:10110(二進位制)–>11101(格雷碼)
二進位制 10110
右移+補零 010110
異或 11101(格雷碼)
verilog實現:
assign gray_code=
(binary_code>
>1)
^binary_code;
2、非同步fifo的寫滿/讀空訊號指示如何利用格雷碼正確產生?即如何判斷空滿? 假設fifo空間大小為8,即0~7;當讀位址是0000(格雷碼0000),寫位址為1000(對應的格雷碼是1100,具體的轉換可以見筆記),此時已經是寫滿的狀態了,兩者高位和次高位不同,其餘位相同,標誌寫滿;讀空是二者格雷碼完全相同,因為是先寫入後讀出的,當讀指標追上了寫指標的時候,意味著最後乙個資料被讀完了,即讀空。
結論:
讀空:讀時鐘域的格雷碼rgray_next和被同步來的寫指標rd2_wp每一bit都完全相同;
寫滿:寫時鐘域的格雷碼wgray_next和被同步來的讀指標wr2_rp高2位不同,其餘相同;
硬體實現:rtl**
module fifo
#( parameter wsize =8;
parameter dsize =32;
)(input wr_clk,
input rst,
input wr_en,
input [wsize-1:
0]din,
input rd_clk,
input rd_en,
output [wsize-1:
0]dout,
output reg rempty,
output reg wfull);
//定義變數
reg [wsize-1:
0] mem [dsize-1:
0];reg [wsize-1:
0] waddr,raddr;
reg [wsize :
0] wbin,rbin,wbin_next,rbin_next;
reg [wsize :
0] wgray_next,rgray_next;
reg [wsize :
0] wp,rp;
reg [wsize :
0] wr1_rp,wr2_rp,rd1_wp,rd2_wp;
wire rempty_val,wfull_val;
//輸出資料
assign dout = mem[raddr]
;//輸入資料
always@(posedge wr_clk)
if(wr_en &&
!wfull)
mem[waddr]
<= din;
//1.產生儲存實體的讀位址raddr; 2.將普通二進位制轉化為格雷碼,並賦給讀指標rp
always@(posedge rd_clk or negedge rst_n)if(
!rst_n)
<=0;
else
<=
;assign raddr = rbin[wsize-1:
0];assign rbin_next = rbin +
(rd_en &
~rempty)
;assign rgray_next = rbin_next ^
(rbin_next >>1)
;//1.產生儲存實體的寫位址waddr; 2.將普通二進位制轉化為格雷碼,並賦給寫指標wp
always@(posedge wr_clk or negedge rst_n)if(
!rst_n)
<=0;
else
<=
;assign waddr = wbin[wsize-1:
0];assign wbin_next = wbin +
(wr_en &
~wfull)
;assign wgray_next = wbin_next ^
(wbin_next >>1)
;//將讀指標rp同步到寫時鐘域
always@(posedge wr_clk or negedge rst_n)if(
!rst_n)
<=0;
else
<=
;//將寫指標wp同步到讀時鐘域
always@(posedge rd_clk or negedge rst_n)if(
!rst_n)
<=0;
else
<=
;//產生讀空訊號rempty
assign rempty_val =
(rd2_wp == rgray_next)
;always@(posedge rd_clk or negedge rst_n)
if(rst_n)
rempty <=
1'b1;
else
rempty <= rempty_val;
//產生寫滿訊號wfull
assign wfull_val =((
~(wr2_rp[wsize : wsize-1]
),wr2_rp[wsize-2:
0])== wgray_next)
;always@(posedge wr_clk or negedge rst_n)if(
!rst_n)
wfull <=
1'b0;
else
wfull <= wfull_val;
endmodule
3 硬體實現的原理框圖 多時域設計中如何處理訊號跨時域。
多時鐘域的設計中,對於訊號跨時域的處理這裡可以採用桌球操作的方法來進行。桌球操作的處理流程為 輸入資料流通過 輸入資料選擇單元 將資料流等時分配到兩個資料緩衝區,資料緩衝模組可以為任何儲存模組,比較常用的儲存單元為雙口ram dpram 單口ram spram fifo等。在第1個緩衝週期,將輸入的...
資料庫資料跨機器傳輸
訪問不同電腦上的資料庫 遠端只要聯好網就一樣 如果經常訪問或資料量大,建議用鏈結伺服器 建立鏈結伺服器 exec sp addlinkedserver srv lnk sqloledb 遠端伺服器名或ip位址 exec sp addlinkedsrvlogin srv lnk false null,...
讓swf跨域傳輸資料
一 概述 位於www.mzwu.com域中的swf檔案要訪問www.163.com的檔案時,swf首先會檢查163伺服器目錄下是否有crossdomain.xml檔案,如果沒有,則訪問不成功 若crossdomain.xml檔案存在,且裡邊設定了允許www.mzwu.com域訪問,那麼通訊正常。所以...