那曲檬骨新材料有限公司

電子發燒友App

硬聲App

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示
電子發燒友網>電子資料下載>可編程邏輯>【ZYNQ Ultrascale+ MPSOC FPGA教程】第八章FPGA片內FIFO讀寫測試實驗

【ZYNQ Ultrascale+ MPSOC FPGA教程】第八章FPGA片內FIFO讀寫測試實驗

2021-02-02 | pdf | 708.05KB | 次下載 | 3積分

資料介紹

作者: ALINX
* 本原創教程由芯驛電子科技(上海)有限公司(ALINX)創作,版權歸本公司所有,如需轉載,需授權并注明出處。

適用于板卡型號:
AXU2CGA/AXU2CGB/AXU3EG/AXU4EV-E/AXU4EV-P/AXU5EV-E/AXU5EV-P /AXU9EG/AXU15EG

實驗Vivado工程為“fifo_test”。

FIFO是FPGA應用當中非常重要的模塊,廣泛用于數據的緩存,跨時鐘域數據處理等。學好FIFO是FPGA的關鍵,靈活運用好FIFO是一個FPGA工程師必備的技能。本章主要介紹利用XILINX提供的FIFO IP進行讀寫測試。

1.實驗原理

FIFO: First in, First out代表先進的數據先出,后進的數據后出。Xilinx在VIVADO里為我們已經提供了FIFO的IP核, 我們只需通過IP核例化一個FIFO,根據FIFO的讀寫時序來寫入和讀取FIFO中存儲的數據。

其實FIFO是也是在RAM的基礎上增加了許多功能,FIFO的典型結構如下,主要分為讀和寫兩部分,另外就是狀態信號,空和滿信號,同時還有數據的數量狀態信號,與RAM最大的不同是FIFO沒有地址線,不能進行隨機地址讀取數據,什么是隨機讀取數據呢,也就是可以任意讀取某個地址的數據。而FIFO則不同,不能進行隨機讀取,這樣的好處是不用頻繁地控制地址線。

雖然用戶看不到地址線,但是在FIFO內部還是有地址的操作的,用來控制RAM的讀寫接口。其地址在讀寫操作時如下圖所示,其中深度值也就是一個FIFO里最大可以存放多少個數據。初始狀態下,讀寫地址都為0,在向FIFO中寫入一個數據后,寫地址加1,從FIFO中讀出一個數據后,讀地址加1。此時FIFO的狀態即為空,因為寫了一個數據,又讀出了一個數據。

可以把FIFO想象成一個水池,寫通道即為加水,讀通道即為放水,假如不間斷的加水和放水,如果加水速度比放水速度快,那么FIFO就會有滿的時候,如果滿了還繼續加水就會溢出overflow,如果放水速度比加水速度快,那么FIFO就會有空的時候,所以把握好加水與放水的時機和速度,保證水池一直有水是一項很艱巨的任務。也就是判斷空與滿的狀態,擇機寫數據或讀數據。

根據讀寫時鐘,可以分為同步FIFO(讀寫時鐘相同)和異步FIFO(讀寫時鐘不同)。同步FIFO控制比較簡單,不再介紹,本節實驗主要介紹異步FIFO的控制,其中讀時鐘為75MHz,寫時鐘為100MHz。實驗中會通過VIVADO集成的在想邏輯分析儀ila,我們可以觀察FIFO的讀寫時序和從FIFO中讀取的數據。

2. 創建Vivado工程
2.1 添加FIFO IP核

在添加FIFO IP之前先新建一個fifo_test的工程, 然后在工程中添加FIFO IP,方法如下:

2.1.1點擊下圖中IP Catalog,在右側彈出的界面中搜索fifo,找到FIFO Generator,雙擊打開。

2.1.2 彈出的配置頁面中,這里可以選擇讀寫時鐘分開還是用同一個,一般來講我們使用FIFO為了緩存數據,通常兩邊的時鐘速度是不一樣的。所以獨立時鐘是最常用的,我們這里選擇“Independent Clocks Block RAM”,然后點擊“Next”到下一個配置頁面。

2.1.3 切換到Native Ports欄目下,選擇數據位寬16;FIFO深選擇512,實際使用大家根據需要自行設置就可以。Read Mode有兩種方式,一個Standard FIFO,也就是平時常見的FIFO,數據滯后于讀信號一個周期,還有一種方式為First Word Fall Through,數據預取模式,簡稱FWFT模式。也就是FIFO會預先取出一個數據,當讀信號有效時,相應的數據也有效。我們首先做標準FIFO的實驗。

2.1.4 切換到Data Counts欄目下,使能Write Data Count(已經FIFO寫入多少數據)和Read Data Count(FIFO中有多少數據可以讀),這樣我們可以通過這兩個值來看FIFO內部的數據多少。點擊OK,Generate生成FIFO IP。

2.2 FIFO的端口定義與時序

FIFO的數據寫入和讀出都是按時鐘的上升沿操作的,當wr_en信號為高時寫入FIFO數據,當almost_full信號有效時,表示FIFO只能再寫入一個數據,一旦寫入一個數據了,full信號就會拉高,如果在full的情況下wr_en仍然有效,也就是繼續向FIFO寫數據,則FIFO的overflow就會有效,表示溢出。

標準FIFO寫時序

當rd_en信號為高時讀FIFO數據,數據在下個周期有效。valid為數據有效信號,almost_empty表示還有一個數據讀,當再讀一個數據,empty信號有效,如果繼續讀,則underflow有效,表示下溢,此時讀出的數據無效。

標準FIFO讀時序

而從FWFT模式讀數據時序圖可以看出,rd_en信號有效時,有效數據D0已經在數據線上準備好有效了,不會再延后一個周期。這就是與標準FIFO的不同之處。

FWFT FIFO讀時序

關于FIFO的詳細內容可參考pg057文檔,可在xilinx官網下載。

3. FIFO測試程序編寫

我們按照異步FIFO進行設計,用PLL產生出兩路時鐘,分別是100MHz和75MHz,用于寫時鐘和讀時鐘,也就是寫時鐘頻率高于讀時鐘頻率。

`timescale1ns/1ps
//////////////////////////////////////////////////////////////////////////////////
module fifo_test
	(
		input		clk,		//25MHz時鐘
		input		rst_n	//復位信號,低電平有效	
	);


reg	[15:0]		w_data			;			//FIFO寫數據
wire			wr_en			;			//FIFO寫使能
wire			rd_en			;			//FIFO讀使能
wire[15:0]		r_data			;			//FIFO讀數據
wire			full			;			//FIFO滿信號
wire			empty			;			//FIFO空信號
wire[8:0]		rd_data_count	;			//可讀數據數量	
wire[8:0]		wr_data_count	;			//已寫入數據數量
	
wire				clk_100M 		;			//PLL產生100MHz時鐘
wire				clk_75M 		;			//PLL產生100MHz時鐘
wire				locked 			;			//PLL lock信號,可作為系統復位信號,高電平表示lock住
wire				fifo_rst_n 		;			//fifo復位信號, 低電平有效

wire				wr_clk 			;			//寫FIFO時鐘
wire				rd_clk 			;			//讀FIFO時鐘
reg	[7:0]			wcnt 			;			//寫FIFO復位后等待計數器
reg	[7:0]			rcnt 			;			//讀FIFO復位后等待計數器

wire               clkbuf          ;

   BUFG BUFG_inst (
.O(clkbuf),// 1-bit output: Clock output.
.I(clk)// 1-bit input: Clock input.
);


//例化PLL,產生100MHz和75MHz時鐘
clk_wiz_0 fifo_pll
(
// Clock out ports
.clk_out1(clk_100M),		// output clk_out1
.clk_out2(clk_75M),		// output clk_out2
// Status and control signals
.reset(~rst_n),				// input reset
.locked(locked),		// output locked
// Clock in ports
.clk_in1(clkbuf)					// input clk_in1
);			

assign fifo_rst_n 	= locked	;	//將PLL的LOCK信號賦值給fifo的復位信號
assign wr_clk 		= clk_100M 	;	//將100MHz時鐘賦值給寫時鐘
assign rd_clk 		= clk_75M 	;	//將75MHz時鐘賦值給讀時鐘


/* 寫FIFO狀態機 */
localparam      W_IDLE      =1	;
localparam      W_FIFO     	=2	;

reg[2:0]  write_state;
reg[2:0]  next_write_state;

always@(posedge wr_clk ornegedge fifo_rst_n)
begin
	if(!fifo_rst_n)
		write_state <= W_IDLE;
	else
		write_state <= next_write_state;
end

always@(*)
begin
	case(write_state)
		W_IDLE:
			begin
				if(wcnt ==8'd79)//復位后等待一定時間,safety circuit模式下的最慢時鐘60個周期
					next_write_state <= W_FIFO;
				else
					next_write_state <= W_IDLE;
			end
		W_FIFO:
			next_write_state <= W_FIFO;			//一直在寫FIFO狀態
		default:
			next_write_state <= W_IDLE;
	endcase
end
//在IDLE狀態下,也就是復位之后,計數器計數
always@(posedge wr_clk ornegedge fifo_rst_n)
begin
	if(!fifo_rst_n)
		wcnt <=8'd0;
	elseif(write_state == W_IDLE)
		wcnt <= wcnt +1'b1;
	else
		wcnt <=8'd0;
end
//在寫FIFO狀態下,如果不滿就向FIFO中寫數據
assign wr_en =(write_state == W_FIFO)?~full :1'b0;
//在寫使能有效情況下,寫數據值加1
always@(posedge wr_clk ornegedge fifo_rst_n)
begin
	if(!fifo_rst_n)
		w_data <=16'd1;
	elseif(wr_en)
		w_data <= w_data +1'b1;
end

/* 讀FIFO狀態機 */

localparam      R_IDLE      =1	;
localparam      R_FIFO     	=2	;
reg[2:0]  read_state;
reg[2:0]  next_read_state;

///產生FIFO讀的數據
always@(posedge rd_clk ornegedge fifo_rst_n)
begin
	if(!fifo_rst_n)
		read_state <= R_IDLE;
	else
		read_state <= next_read_state;
end

always@(*)
begin
	case(read_state)
		R_IDLE:
			begin
				if(rcnt ==8'd59)	//復位后等待一定時間,safety circuit模式下的最慢時鐘60個周期
					next_read_state <= R_FIFO;
				else
					next_read_state <= R_IDLE;
			end
		R_FIFO:	
			next_read_state <= R_FIFO ;			//一直在讀FIFO狀態
		default:
			next_read_state <= R_IDLE;
	endcase
end

//在IDLE狀態下,也就是復位之后,計數器計數
always@(posedge rd_clk ornegedge fifo_rst_n)
begin
	if(!fifo_rst_n)
		rcnt <=8'd0;
	elseif(write_state == W_IDLE)
		rcnt <= rcnt +1'b1;
	else
		rcnt <=8'd0;
end
//在讀FIFO狀態下,如果不空就從FIFO中讀數據
assign rd_en =(read_state == R_FIFO)?~empty :1'b0;

//-----------------------------------------------------------
//實例化FIFO
fifo_ip fifo_ip_inst 
(
.rst            (~fifo_rst_n    	),// input rst
.wr_clk         (wr_clk          	),// input wr_clk
.rd_clk         (rd_clk          	),// input rd_clk
.din            (w_data       	),// input [15 : 0] din
.wr_en          (wr_en        	),// input wr_en
.rd_en          (rd_en        	),// input rd_en
.dout           (r_data       	),// output [15 : 0] dout
.full           (full         	),// output full
.empty          (empty        	),// output empty
.rd_data_count  (rd_data_count	),// output [8 : 0] rd_data_count
.wr_data_count  (wr_data_count	)// output [8 : 0] wr_data_count
);

//寫通道邏輯分析儀
ila_m0 ila_wfifo (
	.clk		(wr_clk			),
	.probe0		(w_data			),	
	.probe1		(wr_en			),	
	.probe2		(full			),		
	.probe3		(wr_data_count	)
);
//讀通道邏輯分析儀
ila_m0 ila_rfifo (
	.clk		(rd_clk			),
	.probe0		(r_data			),	
	.probe1		(rd_en			),	
	.probe2		(empty			),		
	.probe3		(rd_data_count	)
);
	
endmodule

在程序中采用PLL的lock信號作為fifo的復位,同時將100MHz時鐘賦值給寫時鐘,75MHz時鐘賦值給讀時鐘。

有一點需要注意的是,FIFO設置默認為采用safety circuit,此功能是保證到達內部RAM的輸入信號是同步的,在這種情況下,如果異步復位后,則需要等待60個最慢時鐘周期,在本實驗中也就是75MHz的60個周期,那么100MHz時鐘大概需要(100/75)x60=80個周期。

因此在寫狀態機中,等待80個周期進入寫FIFO狀態

在讀狀態機中,等待60個周期進入讀狀態

如果FIFO不滿,就一直向FIFO寫數據

如果FIFO不空,就一直從FIFO讀數據

例化兩個邏輯分析儀,分別連接寫通道和讀通道的信號

4. 仿真

以下為仿真結果,可以看到寫使能wr_en有效后開始寫數據,初始值為0001,從開始寫到empty不空,是需要一定周期的,因為內部還要做同步處理。在不空后,開始讀數據,讀出的數據相對于rd_en滯后一個周期。

在后面可以看到如果FIFO滿了,根據程序的設計,滿了就不向FIFO寫數據了,wr_en也就拉低了。為什么會滿呢,就是因為寫時鐘比讀時鐘快。如果將寫時鐘與讀時鐘調換,也就是讀時鐘快,就會出現讀空的情況,大家可以試一下。

如果將FIFO的Read Mode改成First Word Fall Through

仿真結果如下,可以看到rd_en有效的時候數據也有效,沒有相差一個周期

5. 板上驗證

生成好bit文件,下載bit文件,會出現兩個ila,先來看寫通道的,可以看到full信號為高電平時,wr_en為低電平,不再向里面寫數據。

而讀通道也與仿真一致

如果以rd_en上升沿作為觸發條件,點擊運行,然后按下復位,也就是我們綁定的PL KEY1,會出現下面的結果,與仿真一致,標準FIFO模式下,數據滯后rd_en一個周期。

下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評論

查看更多

下載排行

本周

  1. 1電子電路原理第七版PDF電子教材免費下載
  2. 0.00 MB  |  1491次下載  |  免費
  3. 2單片機典型實例介紹
  4. 18.19 MB  |  95次下載  |  1 積分
  5. 3S7-200PLC編程實例詳細資料
  6. 1.17 MB  |  27次下載  |  1 積分
  7. 4筆記本電腦主板的元件識別和講解說明
  8. 4.28 MB  |  18次下載  |  4 積分
  9. 5開關電源原理及各功能電路詳解
  10. 0.38 MB  |  11次下載  |  免費
  11. 6100W短波放大電路圖
  12. 0.05 MB  |  4次下載  |  3 積分
  13. 7基于單片機和 SG3525的程控開關電源設計
  14. 0.23 MB  |  4次下載  |  免費
  15. 8基于AT89C2051/4051單片機編程器的實驗
  16. 0.11 MB  |  4次下載  |  免費

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234313次下載  |  免費
  3. 2PADS 9.0 2009最新版 -下載
  4. 0.00 MB  |  66304次下載  |  免費
  5. 3protel99下載protel99軟件下載(中文版)
  6. 0.00 MB  |  51209次下載  |  免費
  7. 4LabView 8.0 專業版下載 (3CD完整版)
  8. 0.00 MB  |  51043次下載  |  免費
  9. 5555集成電路應用800例(新編版)
  10. 0.00 MB  |  33562次下載  |  免費
  11. 6接口電路圖大全
  12. 未知  |  30320次下載  |  免費
  13. 7Multisim 10下載Multisim 10 中文版
  14. 0.00 MB  |  28588次下載  |  免費
  15. 8開關電源設計實例指南
  16. 未知  |  21539次下載  |  免費

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935053次下載  |  免費
  3. 2protel99se軟件下載(可英文版轉中文版)
  4. 78.1 MB  |  537793次下載  |  免費
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420026次下載  |  免費
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234313次下載  |  免費
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費
  11. 6電路仿真軟件multisim 10.0免費下載
  12. 340992  |  191183次下載  |  免費
  13. 7十天學會AVR單片機與C語言視頻教程 下載
  14. 158M  |  183277次下載  |  免費
  15. 8proe5.0野火版下載(中文版免費下載)
  16. 未知  |  138039次下載  |  免費
德州扑克加注规则| 伊川县| 百家乐官网赌场牌路分析| 百家乐去哪里玩最好| 大发888游戏优惠| 老虎机派通娱乐| 7人百家乐官网桌子| 百家乐视频小游戏| 998棋牌游戏| 百家乐官网三国| 黄金城百家乐安卓版| 百家乐官网庄闲多少| 百家乐注册下注平台| 大发888娱乐场解码器| 澳门百家乐官网备用网址| 百家乐双龙出海注码法| 皇冠网小说推荐| 来博百家乐游戏| 博亿娱乐| 百家乐赌假的工具| 博客国际娱乐| 八卦24方位| 真人轮盘游戏| 正品百家乐官网玩法| 大发888合营商| 新澳门百家乐官网的玩法技巧和规则 | 大发888下载娱乐场| 赌百家乐官网的玩法技巧和规则| 威尼斯人娱乐场棋牌| 里尼的百家乐官网策略| 全讯网123| 菲律宾百家乐官网娱乐| 大发888官方免费下载| 状元百家乐官网的玩法技巧和规则 | 百家乐官网画面| 全讯网新3| 网上百家乐官网信誉度| 钱隆百家乐破解版| 广东百家乐官网主论坛| 大发888国际赌场娱乐网规则| 御匾会百家乐官网的玩法技巧和规则|