国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【小白入門】Verilog實現(xiàn)異步FIFO

這篇具有很好參考價值的文章主要介紹了【小白入門】Verilog實現(xiàn)異步FIFO。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

?文章來源地址http://www.zghlxwxcb.cn/news/detail-483852.html

?之前也在CSDN上面寫過兩個FIFO相關的文章,不過代碼看起來比較復雜,且注釋也比較少,不利于新手入門。很多時候都沒有耐心繼續(xù)看下去。

http://t.csdn.cn/0dPX6

http://t.csdn.cn/lYvoY?

因為自己本身是一個初學者,就從初學者的視角來看待并學習FIFO。

為什么選擇學習FIFO?

在學完雙端口RAM之后看待FIFO,會覺得為什么要用FIFO呢?雙端口的RAM也可以實現(xiàn)數(shù)據(jù)的存儲與讀取,讀寫的時鐘也可以不一樣,為什么不用RAM而要基于RAM來設計一個FIFO呢?

FIFO與RAM的區(qū)別是先進先出,不需要讀地址和寫地址。?寫時鐘下,將數(shù)據(jù)寫入FIFO中,在讀時鐘下將先寫入的數(shù)據(jù)先讀出來,不需要向FIFO輸入寫地址和讀地址即可完成數(shù)據(jù)的存儲以及不同時鐘下的讀寫操作,這樣一聽是非常方便的。在SDRAM的學習過程中,我們知道有突發(fā)長度這個東西,當突發(fā)長度為1的時候,即一個寫地址對應一個寫數(shù)據(jù),這樣是非常麻煩的,所以很多SDRAM如DDR3這種,都會將突發(fā)長度設置為8,即給一個首地址,后面連續(xù)讀取8個數(shù)據(jù)。

【小白入門】Verilog實現(xiàn)異步FIFO

?

再貼一張異步FIFO的圖

【小白入門】Verilog實現(xiàn)異步FIFO

?

在寫代碼之前,需要了解幾個概念。

?先思考,F(xiàn)IFO的存儲空間和RAM是一樣的,就像一個n行x1列的表格,每個表格里面存放一個數(shù)據(jù),并且對應一個地址,在讀寫的過程中肯定會存在表格寫滿的情況和讀的時候里面沒有數(shù)據(jù)的情況,那應該怎么判斷呢?

讀寫同時進行時

①首先是在讀的視角,如果如果讀一行數(shù)據(jù)的時候,剛好也在往這一行數(shù)據(jù)里面寫數(shù)據(jù),那這個時候即可判斷讀空了,如果再繼續(xù)向下讀的話,里面就沒有寫進的數(shù)據(jù),讀出的數(shù)據(jù)也不是我們寫進去的,就是無效的。

所以讀空的判斷條件是:在讀時鐘的視角下,寫時鐘同步過來的地址等于我目前正在讀的地址。

【小白入門】Verilog實現(xiàn)異步FIFO

關于跨時鐘域的問題,大家可以去搜索一下跨時鐘域以及亞穩(wěn)態(tài)。也可以看我的這篇文章。

http://t.csdn.cn/hvJTa

②在寫的視角下,?那什么時候寫滿呢?因為地址是有限的嘛,當讀完一個數(shù)據(jù)的時候,讀對應哪個地址的數(shù)據(jù)就已經(jīng)不需要了,因為我們以及讀了,即讀完的那個“位置”空了。所以當寫完一圈,并且追上下一輪的讀的時候,就代表寫滿了。

所以寫滿判斷的條件是:在寫的時鐘下,寫完一圈對應的地址,等于同步過來的讀地址。

【小白入門】Verilog實現(xiàn)異步FIFO

?

其次在寫代碼的時候,還需要了解格雷碼,地址是按照0000-0001-0010-xxxx這種增長的,但是在地址變化的過程中,地址中的位數(shù)會存在”跳變“,如從0001-0010這兩個相鄰碼的時候,有兩位發(fā)生了變化,這樣是不好的。?具體可以參考這篇文章

http://t.csdn.cn/OiesB

以下是代碼Verilog的代碼

`timescale 1ns / 1ps

module asyn_fifo1
(
		input		             rst_n		,
		
		input			         wr_clk		,
		input	                 wr_en		,
		input		 [7:0]       data_in	,
		input			         rd_clk		,
		input			         rd_en		,
		
		output		             full	    ,
		output			         empty		,
		output reg	[7:0]	     data_out	
);

		reg		[7:0]    ram_mem[255:0]    	;    //定義一個位寬為8bit深度為256的雙端口RAM
		
		wire	[7:0]        rd_addr	    ;
		wire	[7:0]        wr_addr		;
		reg		[8:0]    rd_addr_ptr	    ;    //格雷碼需要移位運算,且判斷寫滿信號也需要多一位
		reg		[8:0]    wr_addr_ptr	    ;    
		
		wire  	[8:0]    rd_addr_gray	    ;
		reg		[8:0]    rd_addr_gray1	    ;
		reg		[8:0]    rd_addr_gray2	    ;
		wire	[8:0]    wr_addr_gray	    ;
		reg		[8:0]    wr_addr_gray1	    ;
		reg		[8:0]    wr_addr_gray2	    ;
		
		assign	rd_addr[7:0] = rd_addr_ptr[7:0];
		assign	wr_addr[7:0] = wr_addr_ptr[7:0];
		assign	rd_addr_gray = (rd_addr_ptr>>1) ^ rd_addr_ptr;		//bin to gray
		assign	wr_addr_gray = (wr_addr_ptr>>1) ^ wr_addr_ptr;
		
		//dual port ram
		integer	i;
		always @(posedge wr_clk or negedge rst_n)        //寫時鐘下初始化RAM
		begin
			if(rst_n == 1'b0)
				for(i=0;i<256;i=i+1)
					ram_mem[i] <= 1'b0;
			else if(wr_en && ~full)                      //寫使能且沒有寫滿
				ram_mem[wr_addr] = data_in;
			else
				ram_mem[wr_addr] = ram_mem[wr_addr];
		end
		
		//rd_addr_ptr++ and wr_addr_ptr++
		always @(posedge rd_clk or negedge rst_n)        //讀時鐘下,對讀地址進行操作
		begin
			if(rst_n == 1'b0)
				rd_addr_ptr <= 1'b0;
			else if(rd_en && ~empty)
				rd_addr_ptr <= rd_addr_ptr + 1'b1;
			else
				rd_addr_ptr <= rd_addr_ptr;
		end
		always @(posedge wr_clk or negedge rst_n)        //寫時鐘下,對寫地址進行操作
		begin
			if(rst_n == 1'b0)
				wr_addr_ptr <= 1'b0;
			else if(wr_en && ~full)
				wr_addr_ptr <= wr_addr_ptr + 1'b1;
			else
				wr_addr_ptr <= wr_addr_ptr;
		end
		
		//gray and two regsiter
		always @(posedge wr_clk or negedge rst_n)       //寫時鐘視角下,把讀時鐘同步到自己的時鐘下
		begin
			if(rst_n == 1'b0)begin
				rd_addr_gray1 <= 1'b0;
				rd_addr_gray2 <= 1'b0;
			end
			else begin
				rd_addr_gray1 <= rd_addr_gray;
				rd_addr_gray2 <= rd_addr_gray1;
			end
		end
		always @(posedge rd_clk or negedge rst_n)        //讀時鐘視角下,把寫時鐘同步到自己的時鐘下
		begin
			if(rst_n == 1'b0)begin
				wr_addr_gray1 <= 1'b0;
				wr_addr_gray2 <= 1'b0;
			end
			else begin
				wr_addr_gray1 <= wr_addr_gray;
				wr_addr_gray2 <= wr_addr_gray1;
			end
		end
		
		//data_out
		always @(posedge rd_clk or negedge rst_n)
		begin
			if(rst_n == 1'b0)
				data_out <= 1'b0;
			else if(rd_en && ~empty)
				data_out <= ram_mem[rd_addr];
			else
				data_out <= 1'b0;
		end
		
		assign empty = (rd_addr_gray == wr_addr_gray2)?1'b1:1'b0;    //判斷讀沒讀空
		assign full = (wr_addr_gray[8:7] != rd_addr_gray2[8:7]) && (wr_addr_gray[6:0] == rd_addr_gray2[6:0]);        //判斷是否寫滿
endmodule

?

以下是tb仿真文件代碼

`timescale 1ns / 1ps


module asyn_fifo1_tb();

        reg	                       	rst_n		;
		reg			                wr_clk		;
		reg	          	            wr_en		;
		reg		 [7:0]              data_in	    ;
		reg			                rd_clk		;
		reg			                rd_en		;

		wire		                full	    ;
		wire			            empty		;
		wire     [7:0]	            data_out	;
		
asyn_fifo1    asyn_fifo1_inst
(
		.rst_n	       (rst_n)	     ,	
		.wr_clk	       (wr_clk)      ,
		.wr_en	       (wr_en) 	     ,
		.data_in       (data_in)	 ,
		.rd_clk        (rd_clk)	     ,
		.rd_en	       (rd_en) 	     ,
		.full	       (full)        ,
		.empty	       (empty)       ,
		.data_out	   (data_out)
);
		initial wr_clk = 0;
		always #10 wr_clk = ~wr_clk;        //寫時鐘為50MHz
		
		initial rd_clk = 0;
		always #30 rd_clk = ~rd_clk;        //讀時鐘頻率為寫時鐘的1/3
		
		always @(posedge wr_clk or negedge rst_n)    //不停的向FIFO中寫0-255的數(shù)據(jù)
		begin
			if(rst_n == 1'b0)
			     data_in <= 0;
			else if (wr_en)
			     data_in <= data_in+1'b1;
			 else
			      data_in <= data_in;
		  end
			  initial  begin        
			     rst_n = 0;
			     wr_en = 0;
			     rd_en = 0;
			     #200;                //時間為200ns時,允許寫入
			     rst_n = 1;
			     wr_en = 1;
			     #20000;               //時間再過20000ns時,不允許寫,開始讀
			     wr_en = 0;
			     rd_en = 1;
			     #20000;                //時間再過20000ns時,讀停止
			     rd_en=0;
			     $stop;
			  end
endmodule

波形分析

200ns時,數(shù)據(jù)開始寫入FIFO中,如下圖

【小白入門】Verilog實現(xiàn)異步FIFO?寫滿時,full信號拉高,后面繼續(xù)不停寫入,但滿了,都是無效的寫入。

【小白入門】Verilog實現(xiàn)異步FIFO?

20200ns時,開始讀數(shù)據(jù)

【小白入門】Verilog實現(xiàn)異步FIFO?讀完后,empty信號拉高,表示讀空。

【小白入門】Verilog實現(xiàn)異步FIFO?

由于寫時鐘為讀時鐘的三倍,從整體的波形圖中也可以看出,寫滿數(shù)據(jù)的時間是讀完數(shù)據(jù)時間的1/3.

【小白入門】Verilog實現(xiàn)異步FIFO?

?

?

?

?

?

?

到了這里,關于【小白入門】Verilog實現(xiàn)異步FIFO的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • IC設計入門——異步FIFO

    IC設計入門——異步FIFO

    在異步FIFO中,數(shù)據(jù)讀取和寫入操作使用不同的時鐘頻率。由于寫入和讀取時鐘不同步,因此稱為異步FIFO。通常,這些用于數(shù)據(jù)需要從一個時鐘域傳遞到另一個時鐘域的系統(tǒng)中,這通常稱為“時鐘域交叉”。因此,異步FIFO有助于在兩個工作于不同時鐘的系統(tǒng)之間同步數(shù)據(jù)流。

    2024年02月19日
    瀏覽(25)
  • 【Verilog】同步FIFO原理及verilog實現(xiàn)(參數(shù)化)

    【Verilog】同步FIFO原理及verilog實現(xiàn)(參數(shù)化)

    ????????旨在學習理解,項目中還是用成熟IP靠譜~ 目錄 一、FIFO原理 二、同步FIFO設計 2.1 位寬和深度 2.2 空、滿標志 2.3 FIFO計數(shù) 2.4 ram模型 2.5 讀/寫操作 三、???????verilog代碼 四、仿真驗證 后記 FIFO( First Input First Output)是指先進先出。模型如下: ? ????????F

    2024年02月05日
    瀏覽(24)
  • <FPGA>異步FIFO的Verilg實現(xiàn)方法

    <FPGA>異步FIFO的Verilg實現(xiàn)方法

    ? ? ? ? 在上篇文章:同步FIFO的兩種Verilog設計方法(計數(shù)器法、高位擴展法)中我們介紹了FIFO的基本概念,并對同步FIFO的兩種實現(xiàn)方法進行了仿真驗證。而異步FIFO因為讀寫時鐘不一致,顯然無法直接套用同步FIFO的實現(xiàn)方法,所以在本文我們將用Verilog實現(xiàn)異步FIFO的設計。

    2024年02月07日
    瀏覽(23)
  • Verilog基礎之十四、FIFO實現(xiàn)

    Verilog基礎之十四、FIFO實現(xiàn)

    目錄 一、FIFO 1.1 定義 1.2 實現(xiàn)方式 1.3 實現(xiàn)原理?? 二、代碼實現(xiàn) 三、仿真結果 3.1 復位階段 3.2 寫入階段 3.3?讀取階段 3.4?同時讀寫或不讀不寫 四、參考資料 ????FIFO(First in First out)為先進先出隊列,具有存儲功能,可用于不同時鐘域間傳輸數(shù)據(jù)以及不同的數(shù)據(jù)寬度進行數(shù)據(jù)

    2024年02月13日
    瀏覽(20)
  • 【Verilog】用雙口RAM實現(xiàn)同步FIFO

    【Verilog】用雙口RAM實現(xiàn)同步FIFO

    端口說明如下表。 雙口RAM端口說明: 同步FIFO端口說明: 輸入描述: 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 雙口RAM和代碼框架: 同步FIFO,就是我們學習其他經(jīng)典計算機語言(如C語言)的數(shù)據(jù)結

    2024年02月07日
    瀏覽(20)
  • 同步FIFO的verilog實現(xiàn)(2)——高位擴展法

    同步FIFO的verilog實現(xiàn)(2)——高位擴展法

    ? ? ? ? 在之前的文章中,我們介紹了同步FIFO的verilog的一種實現(xiàn)方法:計數(shù)法。其核心在于:在同步FIFO中,我們可以很容易的使用計數(shù)來判斷FIFO中還剩下多少可讀的數(shù)據(jù),從而可以判斷空、滿。 ? ? ? ? 關于計數(shù)法實現(xiàn)同步FIFO的詳細內(nèi)容,請參考:同步FIFO的verilog實現(xiàn)(

    2024年02月09日
    瀏覽(22)
  • 【FIFO】異步 FIFO 設計

    【FIFO】異步 FIFO 設計

    目錄 ? 寫在前面 簡介 傳遞多個異步信號 同步 FIFO 指針 異步FIFO指針 二進制 FIFO 指針注意事項 FIFO測試問題 格雷碼計數(shù)器 ? 樣式 #1 格雷碼模式 格雷碼計數(shù)器基礎 額外的格雷碼計數(shù)器注意事項 格雷碼計數(shù)器 ? 樣式 #2 處理滿空情況 產(chǎn)生空標志 產(chǎn)生滿標志 不同的時鐘速度

    2024年02月02日
    瀏覽(18)
  • FPGA中FIFO的應用(二)——異步FIFO設計

    FPGA中FIFO的應用(二)——異步FIFO設計

    ??作者簡介: 小瑞同學 ,一個努力精進的 FPGA 和通信學習者。 ??個人主頁:小瑞同學的博客主頁 ??個人信條:越努力,越幸運! ?日期:2023.12.3 ??來源:自學經(jīng)歷 ??文章內(nèi)容概述:介紹了 異步FIFO 的基本工作原理和深度計算,通過仿真觀察了其讀寫過程。 連載系列

    2024年02月03日
    瀏覽(25)
  • 基于異步FIFO的串口回環(huán)測試

    基于異步FIFO的串口回環(huán)測試

    ??當涉及到串口通信的硬件設計和軟件開發(fā)時,進行有效的測試是至關重要的。串口回環(huán)測試是一種常見的測試方法,用于驗證串口通信的功能和穩(wěn)定性。在許多應用中,為了確保串口通信的正常運行,往往需要使用緩沖區(qū)或FIFO來管理數(shù)據(jù)的傳輸和接收。 ??基于異步F

    2024年02月16日
    瀏覽(25)
  • Verilog同步FIFO設計

    Verilog同步FIFO設計

    同步FIFO(synchronous)的 寫時鐘和讀時鐘為同一個時鐘,F(xiàn)IFO內(nèi)部所有邏輯都是同步邏輯 ,常常用于交互數(shù)據(jù)緩沖。 異步FIFO:數(shù)據(jù)寫入FIFO的時鐘和數(shù)據(jù)讀出FIFO的時鐘是異步的(asynchronous) 典型同步FIFO有三部分組成: (1) FIFO寫控制邏輯; (2)FIFO讀控制邏輯; (3)FIFO 存儲實體(

    2024年02月12日
    瀏覽(48)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包