同步FIFO設(shè)計(jì)詳解及代碼分享|環(huán)球短訊
1. FIFO 簡(jiǎn)介
FIFO (先入先出, First In First Out )存儲(chǔ)器,在 FPGA和數(shù)字 IC設(shè)計(jì)中非常常用。 根據(jù)接入的時(shí)鐘信號(hào),可以分為同步 FIFO 和異步 FIFO 。
**FIFO 底層基于雙口 RAM** ,同步 FIFO 的讀寫(xiě)時(shí)鐘一致,異步 FIFO 讀時(shí)鐘和寫(xiě)時(shí)鐘不同。 同步時(shí)鐘主要應(yīng)用于速率匹配(數(shù)據(jù)緩沖),類似于乒乓存儲(chǔ)提高性能的思想,可以讓后級(jí)不必等待前級(jí)過(guò)多時(shí)間; 異步 FIFO 主要用于多 bit 信號(hào)的跨時(shí)鐘域處理。
本文討論同步 FIFO 的結(jié)構(gòu)及控制邏輯設(shè)計(jì),并給出代碼。
(資料圖片僅供參考)
2. 同步 FIFO 接口
對(duì)于同步 FIFO ,包含必要的接口如下圖所示:
(1) clk : 時(shí)鐘信號(hào),讀寫(xiě)共用;
(2) rst_n : 復(fù)位信號(hào),視具體設(shè)計(jì)和芯片采用同步復(fù)位還是異步復(fù)位,此處默認(rèn)使用異步低電平復(fù)位;
(3) wdata : 寫(xiě)數(shù)據(jù)信號(hào),信號(hào)后帶“ \\ ”表示是多 bit 信號(hào);
(4) rdata : 讀數(shù)據(jù)信號(hào),信號(hào)后帶“ \\ ”表示是多 bit 信號(hào);
(5) wfull : 滿信號(hào),指示 FIFO 寫(xiě)滿了,不能再寫(xiě)了,如果再寫(xiě)會(huì)覆蓋掉還沒(méi)讀出的寫(xiě)入數(shù)據(jù),造成數(shù)據(jù)丟失;
(6) rempty : 空信號(hào),指示 FIFO 讀空了,不能在讀了,如果再讀相當(dāng)于有的數(shù)據(jù)重復(fù)讀了第二遍,造成數(shù)據(jù)錯(cuò)誤;
(7) winc : 寫(xiě)使能信號(hào),寫(xiě)使能有效時(shí)表示希望能寫(xiě)入數(shù)據(jù);
(8) rinc : 讀使能信號(hào),讀使能有效時(shí)表示希望能讀出數(shù)據(jù);
3. 雙口 RAM 接口
在實(shí)現(xiàn) FIFO 時(shí),無(wú)論是同步 FIFO 還是異步 FIFO ,通常會(huì)通過(guò)雙口 RAM ( Dual Port RAM )并添加一些必要的邏輯來(lái)實(shí)現(xiàn)。雙口 RAM 的接口如下圖所示。
**左側(cè)全部是寫(xiě)時(shí)鐘域的,包括寫(xiě)時(shí)鐘、寫(xiě)數(shù)據(jù)、寫(xiě)地址和寫(xiě)使能信號(hào);
**
右側(cè)全部是讀時(shí)鐘域的,包括讀時(shí)鐘、讀數(shù)據(jù)、讀地址和讀使能信號(hào);
4. 基于雙口 RAM 的同步 FIFO 結(jié)構(gòu)
根據(jù)同步 FIFO 的接口和雙口 RAM 的接口,在借助雙口 RAM 實(shí)現(xiàn)同步 FIFO 時(shí),如下圖所示結(jié)構(gòu),只需要加入讀、寫(xiě)控制邏輯即可。在寫(xiě)邏輯中,用于產(chǎn)生寫(xiě)地址和寫(xiě)滿信號(hào); 在讀邏輯中,用于產(chǎn)生讀地址和讀空信號(hào)。 讀寫(xiě)控制邏輯還需要受到讀寫(xiě)使能信號(hào)的控制。
5. 讀寫(xiě)地址產(chǎn)生邏輯
讀寫(xiě)地址什么時(shí)候能夠遞增?
顯然,對(duì)于寫(xiě)地址必須滿足:
(1) 寫(xiě)使能有效(要寫(xiě)入);
(2) 沒(méi)寫(xiě)滿(能寫(xiě)入);
即:
always @ (posedge clk ornegedge rst_n) begin if(~rst_n) begin waddr <= "b0; end else begin if( winc && ~wfull ) begin waddr <= waddr + 1"b1; end else begin waddr <= waddr; end end end
對(duì)于讀地址必須滿足:
(1) 讀使能有效(要讀出);
(2) 沒(méi)讀空(能讀出);
即:
always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin raddr<= "b0; end else begin if( rinc && ~rempty ) begin raddr <= raddr + 1"b1; end else begin raddr <= raddr; end end end
6. 空滿信號(hào)產(chǎn)生邏輯
搞定了讀寫(xiě)地址的控制邏輯,還差最后一步也是最關(guān)鍵的信號(hào):空滿信號(hào)如何產(chǎn)生。
空: 讀空,讀地址追上寫(xiě)地址;
滿: 寫(xiě)滿,寫(xiě)地址追上讀地址。
問(wèn)題來(lái)了: 怎么判地址斷追上了呢? 如果地址相等那應(yīng)該是追上了,即 raadr == waddr 或者 wddr == raddr 。 如果按照這種判斷,顯然這兩個(gè)地址追上對(duì)方的判斷是等效的,無(wú)法區(qū)分出來(lái)到底是寫(xiě)追上讀還是讀追上寫(xiě)。
可以考慮: 使用 1 個(gè)標(biāo)志位 flag 來(lái)額外指示寫(xiě)追上讀還是讀追上寫(xiě)。
參考前人的文獻(xiàn),判斷空滿的方式有多種,非常常用的一種是 Clifford E. Cummings 文章中提到的 擴(kuò)展 1 bit 的讀寫(xiě)地址方法,也就是說(shuō),將前面提到的 flag 指示信號(hào)和原本 N 位的讀寫(xiě)地址結(jié)合,使用 N+1 位的讀寫(xiě)地址,其中最高位用于判斷空滿信號(hào),其余低位還是正常用于讀寫(xiě)地址索引。
以一個(gè) 4 深度的 FIFO 實(shí)例來(lái)說(shuō)明, 4 深度原本需要 2 bit 的讀寫(xiě)地址,現(xiàn)在擴(kuò)展成 3 bit 。
使用低 2 位來(lái)進(jìn)行雙口 RAM 的地址索引,高位用于判斷空滿。 對(duì)于空信號(hào),可以知道當(dāng) FIFO 里沒(méi)有待讀出的數(shù)據(jù)時(shí)產(chǎn)生。** 也就是說(shuō),此時(shí)讀追上了寫(xiě),把之前寫(xiě)的數(shù)據(jù)剛剛?cè)慷汲觯x地址和寫(xiě)地址此時(shí)指向相同的位置,讀地址 - 寫(xiě)地址 =0** ,即
raddr == waddr
對(duì)于寫(xiě)滿信號(hào), **當(dāng)寫(xiě)入后還沒(méi)被讀出的數(shù)據(jù)恰好是 FIFO 深度的時(shí)候,產(chǎn)生滿信號(hào),即寫(xiě)地址 - 讀地址 = FIFO 深度 = 4 ** 。 對(duì)照下圖可以發(fā)現(xiàn),此時(shí)對(duì)于雙口 RAM 的 2 bit 的地址來(lái)說(shuō),讀寫(xiě)地址一致; 對(duì)于最高位來(lái)所,寫(xiě)是 1 而讀是 0 。
再考慮下圖所示的一種情況,寫(xiě)入待讀出的數(shù)據(jù)仍然是 4 個(gè),此時(shí)也是 4 深度的 FIFO 已經(jīng)滿了。 讀寫(xiě)地址的低位相同,高位是寫(xiě) 0 讀 1 。
對(duì)于寫(xiě)滿的 2 種情況,總結(jié)下來(lái),都是低位相同,最高位相反。
即:
raddr[N] = = ~waddr[N] raddr[N-1:0] = = waddr[N-1:0]
也就是:
raddr == {~waddr[N], waddr[N-1:0]}
所以,空滿邏輯產(chǎn)生的代碼為:
always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin wfull <= "b0; rempty <= "b0; end else begin wfull <= (raddr == {~waddr[ADDR_WIDTH], waddr[ADDR_WIDTH-1:0]}); rempty <= (raddr == waddr); end end
7. 全部代碼
`timescale 1ns/1ns /****************************/// 作者:FPGA探索者/****************************/module sfifo#( parameter WIDTH = 8, parameter DEPTH = 16)( input clk , input rst_n , input winc , input rinc , input [WIDTH-1:0] wdata , output reg wfull , output reg rempty , output wire [WIDTH-1:0] rdata); // 用localparam定義一個(gè)參數(shù),可以在文件內(nèi)使用 localparam ADDR_WIDTH = $clog2(DEPTH); reg [ADDR_WIDTH:0] waddr; reg [ADDR_WIDTH:0] raddr; always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin waddr <= "b0; end else begin if( winc && ~wfull ) begin waddr <= waddr + 1"b1; end else begin waddr <= waddr; end end end always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin raddr <= "b0; end else begin if( rinc && ~rempty ) begin raddr <= raddr + 1"b1; end else begin raddr <= raddr; end end end always @ (posedge clk or negedge rst_n) begin if(~rst_n) begin wfull <= "b0; rempty <= "b0; end else begin wfull <= (raddr == {~waddr[ADDR_WIDTH], waddr[ADDR_WIDTH-1:0]}); rempty <= (raddr == waddr); end end // 帶有 parameter 參數(shù)的例化格式 dual_port_RAM #( .DEPTH(DEPTH), .WIDTH(WIDTH) ) dual_port_RAM_U0 ( .wclk(clk), .wenc(winc), .waddr(waddr[ADDR_WIDTH-1:0]), .wdata(wdata), .rclk(clk), .renc(rinc), .raddr(raddr[ADDR_WIDTH-1:0]), .rdata(rdata) ); endmodule/**************RAM 子模塊*************/module dual_port_RAM #(parameter DEPTH = 16, parameter WIDTH = 8)( input wclk ,input wenc ,input [$clog2(DEPTH)-1:0] waddr //深度對(duì)2取對(duì)數(shù),得到地址的位寬。 ,input [WIDTH-1:0] wdata //數(shù)據(jù)寫(xiě)入 ,input rclk ,input renc ,input [$clog2(DEPTH)-1:0] raddr //深度對(duì)2取對(duì)數(shù),得到地址的位寬。 ,output reg [WIDTH-1:0] rdata //數(shù)據(jù)輸出);reg [WIDTH-1:0] RAM_MEM [0:DEPTH-1];always @(posedge wclk) begin if(wenc) RAM_MEM[waddr] <= wdata;end always @(posedge rclk) begin if(renc) rdata <= RAM_MEM[raddr];end endmodule
關(guān)鍵詞:
[責(zé)任編輯:xwzkw]
相關(guān)閱讀
- (2023-06-27)同步FIFO設(shè)計(jì)詳解及代碼分享|環(huán)球短訊
- (2023-06-27)我國(guó)首次高壓力多管材純氫試驗(yàn)取得成功
- (2023-06-27)北京多處公共場(chǎng)所貼出警示:穿洞洞鞋乘扶梯易受傷!|當(dāng)前通訊
- (2023-06-27)iPhone 15 Pro訂單占比飆升 蘋(píng)果調(diào)整產(chǎn)品組合
- (2023-06-27)聯(lián)合國(guó)教科文組織專家考察評(píng)估擬建臨夏世界地質(zhì)公園匯報(bào)會(huì)召開(kāi)-每日快報(bào)
- (2023-06-27)地企攜手 眾志成城 塔河縣塔河林業(yè)局春防工作取得全勝
- (2023-06-27)【天天速看料】未識(shí)別的網(wǎng)絡(luò)怎么處理內(nèi)網(wǎng)(未識(shí)別的網(wǎng)絡(luò)怎么處理)
- (2023-06-27)全球報(bào)道:主次節(jié)奏:黃金日內(nèi)沖高回落,下探上周五低點(diǎn)1910
- (2023-06-27)全球熱推薦:汽車與電子科技相互賦能,看極星汽車如何定義“新智能終端融合產(chǎn)業(yè)”
- (2023-06-27)美食盛宴!贛湘邊15名大廚同臺(tái)大比拼 世界時(shí)快訊
- (2023-06-27)筆記本內(nèi)存又大升級(jí) 48GB容量上市_全球快看
- (2023-06-27)天天微動(dòng)態(tài)丨木衛(wèi)四協(xié)議DLC曝光:新武器、怪物及boss戰(zhàn)
- (2023-06-27)2440億大手筆,創(chuàng)二季度之最!央行深意在此
- (2023-06-27)進(jìn)出口銀行董事長(zhǎng)吳富林會(huì)見(jiàn)斯里蘭卡外交部長(zhǎng)阿里·薩布里
- (2023-06-27)南國(guó)置業(yè)董事長(zhǎng)武琳辭職 總經(jīng)理李明軒接任|天天觀速訊
- (2023-06-27)少兒重疾保險(xiǎn)是30年好還是終身好?
- (2023-06-27)“回到中國(guó)是一種巨大的愉悅和驚喜”時(shí)隔四年 這場(chǎng)經(jīng)濟(jì)盛會(huì)重歸線下_全球觀焦點(diǎn)
- (2023-06-27)天天關(guān)注:北京傳統(tǒng)商場(chǎng)升級(jí)改造 “賽特+”著力打造高品質(zhì)社交場(chǎng)景消費(fèi)
- (2023-06-27)新疆今年跨省異地就醫(yī)結(jié)算已近70萬(wàn)人次
- (2023-06-27)玉足是什么網(wǎng)絡(luò)用語(yǔ)
- (2023-06-27)天天視點(diǎn)!杭州銀行(600926.SH)擬定增不超9億股募資不超125億元 用于補(bǔ)充公司核心一級(jí)資本
- (2023-06-27)世茂服務(wù)在上海:為業(yè)主辦實(shí)事,為生活添品質(zhì)
- (2023-06-27)電池板塊異動(dòng)拉升,恩捷股份漲超7%!電池50ETF(159796)臨近午盤(pán)強(qiáng)勢(shì)拉升翻紅漲超1%
- (2023-06-27)我市7人入選2023年度“燕趙秀林計(jì)劃” 天天快看
- (2023-06-27)小說(shuō)網(wǎng)游之我是死神(網(wǎng)游之我是死神)
- (2023-06-27)6月26日國(guó)內(nèi)鄰二甲苯企業(yè)報(bào)價(jià)暫穩(wěn)-每日熱文
- (2023-06-27)月均增長(zhǎng)達(dá)“百億級(jí)” 六問(wèn)快遞業(yè)如何實(shí)現(xiàn)提速發(fā)展_全球即時(shí)
- (2023-06-27)焦點(diǎn)資訊:足球報(bào):三鎮(zhèn)新帥需幫球員找回最好狀態(tài),韋世豪、鄧涵文已恢復(fù)
- (2023-06-27)以撒的結(jié)合1UP效果介紹_全球速看料
- (2023-06-27)迷你世界地心門怎么做更新版 迷你世界地心門怎么做