1、異步FIFO
在ASIC設計或者FPGA設計中,我們常常使用異步fifo(first in first out)(下文簡稱為afifo)進行數據流的跨時鐘,可以說沒使用過afifo的Designer,其設計經歷是不完整的。廢話不多說,直接上接口信號說明。
2、afifo接口信號說明
如下表格為常見的afifo接口信號,非必須指的部分場景的afifo可能不存在此信號。不同公司對afifo接口的設計可能不一樣,但是基本都包含了如下接口:wr表示write,寫側時鐘域信號,rd表示read,讀側時鐘域信號。
信號名稱 | 位寬 | 必要性 | 含義 |
almost_full | 1 | 非必須 | 將滿信號,1表示afifo快滿了,當afifo的有效數量大于配置時,置1 |
full | 1 | 非必須 | afifo滿信號,1表示afifo已滿 |
empty | 1 | 非必須 | 1表示 |
rd_data | [DATA_WIDTH-1:0] | 必須 | 有效數據 |
ovf_int | 1 | 非必須 | 1表示上溢出,即afifo滿了還有數據寫入 |
udf_int | 1 | 非必須 | 1表示下溢出,即afifo空了外部邏輯還產生了讀使能 |
data_count | [ADDR_WIDTH:0] | 非必須 | afifo存儲的數據量 |
cfg_almost_full_value | [ADDR_WIDTH:0] | 非必須 | 將滿配置信號,一般由配置寄存器模塊提供驅動 |
wr_rst_n | 1 | 必須 | 寫側復位 |
wr_clk | 1 | 必須 | 寫側時鐘 |
wr_en | 1 | 必須 | 寫使能,1表示有數據寫入 |
wr_data | [DATA_WIDTH-1:0] | 必須 | 寫數據 |
rd_rst_n | 1 | 必須 | 讀時鐘與復位 |
rd_clk | 1 | 必須 | 讀時鐘 |
rd_en | 1 | 必須 | 讀使能 |
3、設計原理
為了方便描述,本章節將以深度為8的afifo進行講解,其中讀寫地址位寬為3,格雷碼地址位寬為4。
圖1 afifo結構圖(來自eetop ThinkSpark)
圖2:讀寫地址計算圖
(1)存儲模塊:
中間區域為memory存儲模塊,用于存儲數據data,要么是1R1W的ram,要么是普通的寄存器。項目自研代碼中,存儲模塊通常使用1R1W的ram,其需要memory生成器生成,需要與制造工藝匹配。而在soft IP中,針對小規格的afifo,為了方便,常常使用寄存器作為afifo的存儲。
(2)寫地址產生邏輯
寫地址waddr在wr_clk時鐘域產生,有兩個作用,作為存儲模塊的寫地址并且產生格雷碼waddr_gray。此種需要注意:waddr是遞增的,且會翻轉。如果afifo深度為8(n),則waddr位寬為3(log2(n) ),waddr計數到7后,再次寫入則翻轉為0。
(3)讀地址產生邏輯
讀地址raddr在rd_clk時鐘域產生,有兩個作用,作為存儲模塊的讀地址并且產生格雷碼raddr_gray。此種需要注意:raddr是遞增的,且會翻轉。如果afifo深度為8(n),則raddr位寬為3(log2(n) ),raddr計數到7后,再次讀出則翻轉為0。
(4)讀地址同步
使用2級或者3級單bit同步器Synchronizer將讀地址格雷碼raddr_gray同步到wr_clk時鐘域得到raddr_gray_sync,raddr_gray_sync進行格雷碼逆轉成二進制編碼得到raddr_sync,用于產生將滿信號和滿信號。
在fpga設計中,2級單bit同步器Synchronizer就是2個串聯的寄存器,在ASIC設計中,通常是定制的cell(會將兩個/三個寄存器擺放靠得很近)。
(5)寫地址同步器
使用2級或者3級單bit同步器Synchronizer將寫地址格雷碼waddr_gray同步到rd_clk時鐘域得到waddr_gray_sync,waddr_gray_sync進行格雷碼逆轉成二進制編碼得到waddr_sync,用于產生將空信號和空信號。
(6)滿信號產生邏輯
此模塊首先計算在wr_clk時鐘域的剩余可寫afifo深度,即wr_gap[3:0]=raddr_sync[2:0]+4’d8(FIFO深度)-waddr[2:0],然后根據wr_gap[3:0]產生amost_full和full信號
always @(posedge wr_clk or negedge wr_rst_n) if(~wr_rst_n) full <= 1'b0; else full <= (!(|wr_gap)) || ((wr_gap==1)&wr_en);
always @(posedge wr_clk or negedge wr_rst_n) if(~wr_rst_n) begin almost_full <= 1'b0; end else begin if( wr_data_cnt>=cfg_almost_full_value ) almost_full <= 1'b1; else almost_full <= almost_full; end
(7)空信號產生邏輯
此模塊首先計算在rd_clk時鐘域的可讀afifo深度,即assign {ovf_nc1,rd_gap} = waddr_sync - raddr,然后根據rd_gap[3:0]產生empty信號。
always @(posedge rd_clk or negedge rd_rst_n) if(~rd_rst_n) empty <= 1'b1; else empty <= (!(|rd_gap)) || ((rd_gap==1)&rd_en);? ? ? ? ?
4、重點說明
(1)格雷碼的優勢
格雷碼的特點就是在遞增,遞減,或者翻轉過程中,只會有1個bit位發生變化。因此單bit同步器Synchronizer同步后,只有存在變化的那一個bit可能會發生亞穩態。即使發生了亞穩態,體現的結果要么是0,要么是1,在格雷碼上的同步效果就是當前clk周期沒有同步(相當于delay了一個目的周期)到或者當前周期已采樣到。
同時它也有自己的局限性,那就是循環計數深度必須是2的n次冪(也可以不是2的n次冪哦),否則就失去了每次只變化一位的特性。深度為16的二進制及格雷碼遞變表如下:
Binary Gray
0 0000 0000
1 0001 0001
2 0010 0011
3 0011 0010
4 0100 0110
5 0101 0111
6 0110 0101
7 0111 0100
8 1000 1100
9 1001 1101
10 1010 1111
11 1011 1110
12 1100 1010
13 1101 1011
14 1110 1001
15 1111 1000
0 0000 0000
(2)空信號計算方法的妙處
在rd_clk時鐘域計算可讀數據量以及empty信號,看圖2會發現,實際rd_gap永遠小于等于真實可讀數據量,能夠保證empty為0時永遠不會發生空讀現象,即afifo沒有數據,也進行了讀操作。
(3)滿信號計算方法的妙處
在wd_clk時鐘域計算可寫數據量以及full信號,看圖2會發現,實際wr_gap永遠小于等于真實可寫數據量,能夠保證full為0時永遠不會發生寫溢出現象,即full為0時,afifo可能存在空閑位置。
(4)格雷碼轉二進制代碼
function [ADDR_WIDTH:0] gray2bin; //to change the gray code to bin code input [ADDR_WIDTH:0] gray_in; //input gray code reg [ADDR_WIDTH:0] gray_code; //reg gray reg [ADDR_WIDTH:0] bin_code; //bin code result integer i,j; //integer reg tmp; //tmp begin gray_code = gray_in; for(i=0;i<=ADDR_WIDTH;i=i+1) begin tmp=1'b0; for(j=i;j<=ADDR_WIDTH;j=j+1) tmp=gray_code[j]^tmp; bin_code[i]=tmp; end gray2bin= bin_code; end endfunction
(5)二進制轉格雷碼
always @(posedge rd_clk or negedge rd_rst_n) if(~rd_rst_n) raddr_gray <= {(ADDR_WIDTH + 1){1'b0}}; else raddr_gray <= raddr ^ {1'b0,raddr[ADDR_WIDTH:1]};
5、結束語
Afifo代碼寫出來還不夠,還需要設置約束條件,后期我們會再講講afifo的格雷碼如何約束。
-
FPGA
+關注
關注
1626文章
21678瀏覽量
602005 -
asic
+關注
關注
34文章
1195瀏覽量
120346 -
接口
+關注
關注
33文章
8526瀏覽量
150861 -
fifo
+關注
關注
3文章
387瀏覽量
43559 -
時鐘
+關注
關注
10文章
1721瀏覽量
131377
原文標題:
文章出處:【微信號:處芯積律,微信公眾號:處芯積律】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論