<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 電源與新能源 > 設(shè)計(jì)應(yīng)用 > 異步fifo的設(shè)計(jì)(FPGA)

          異步fifo的設(shè)計(jì)(FPGA)

          作者: 時(shí)間:2018-07-24 來源:網(wǎng)絡(luò) 收藏

          本文首先對(duì)異步 FIFO 設(shè)計(jì)的重點(diǎn)難點(diǎn)進(jìn)行分析,最后給出詳細(xì)代碼。

          本文引用地址:http://www.ex-cimer.com/article/201807/383738.htm

          一、FIFO簡單講解

          FIFO的本質(zhì)是RAM, 先進(jìn)先出

          重要參數(shù):fifo深度(簡單來說就是需要存多少個(gè)數(shù)據(jù))

          fifo位寬(每個(gè)數(shù)據(jù)的位寬)

          FIFO有同步和異步兩種,同步即讀寫時(shí)鐘相同,異步即讀寫時(shí)鐘不相同

          同步FIFO用的少,可以作為數(shù)據(jù)緩存

          異步FIFO可以解決跨時(shí)鐘域的問題,在應(yīng)用時(shí)需根據(jù)實(shí)際情況考慮好fifo深度即可

          本次要設(shè)計(jì)一個(gè)異步FIFO,深度為8,位寬也是8.

          代碼是學(xué)習(xí)Simulation and Synthesis Techniques for Asynchronous FIFO Design Clifford E. Cummings, Sunburst Design, Inc.這篇文章的,百度搜搜很容易找到,雖然是英文的但是寫的確實(shí)值得研究。

          下面我會(huì)對(duì)設(shè)計(jì)的要點(diǎn)進(jìn)行分析,也是對(duì)自己學(xué)習(xí)過程的一個(gè)總結(jié),希望能和大家交流共同進(jìn)步。

          二、設(shè)計(jì)要點(diǎn)解析

          1、讀空信號(hào)如何產(chǎn)生?寫滿信號(hào)如何產(chǎn)生?

          讀空信號(hào):復(fù)位的時(shí)候,讀指針和寫指針相等,讀空信號(hào)有效(這里所說的指針其實(shí)就是讀地址、寫地址)

          當(dāng)讀指針趕上寫指針的時(shí)候,寫指針等于讀指針意味著最后一個(gè)數(shù)據(jù)被讀完,此時(shí)讀空信號(hào)有效

          寫滿信號(hào):當(dāng)寫指針比讀指針多一圈時(shí),寫指針等于讀指針意味著寫滿了,此時(shí)寫滿信號(hào)有效

          我們會(huì)發(fā)現(xiàn) 讀空的條件是寫指針等于讀指針,寫滿的條件也是寫指針等于讀指針,到底如何區(qū)分呢?

          解決方法:將指針的位寬多定義一位

          舉個(gè)例子說明:假設(shè)要設(shè)計(jì)深度為 8 的異步FIFO,此時(shí)定義讀寫指針只需要 3 位(2^3=8)就夠用了,

          但是我們?cè)谠O(shè)計(jì)時(shí)將指針的位寬設(shè)計(jì)成 4 位,最高位的作用就是區(qū)分是讀空還是寫滿,具體理論 1 如下

          當(dāng)最高位相同,其余位相同認(rèn)為是讀空

          當(dāng)最高位不同,其余位相同認(rèn)為是寫滿

          注意:理論1試用的是二進(jìn)制數(shù)之間的空滿比較判斷。

          但是這篇文章中確不是這樣比較的,而是用的理論2,這里我解釋一下

          由于文章在設(shè)計(jì)中判斷是讀指針是否等于寫指針的時(shí)候,用的是讀寫指針的格雷碼形式(為什么用格雷碼后面解釋),此時(shí)若用上面的理論1就會(huì)出問題,因?yàn)楦窭状a是鏡像對(duì)稱的,若只根據(jù)最高位是否相同來區(qū)分是讀空還是寫滿是有問題的,詳情我會(huì)慢慢說,請(qǐng)看圖 1

          綠色框起來的是0--15的格雷碼,用紅線將格雷碼分為上下兩部分

          通過觀察格雷碼相鄰位每次只有1位發(fā)生變化,且上下兩部分,除了最高位相反,其余位全都關(guān)于紅線鏡像對(duì)稱,

          7 --> 8 ,格雷碼從 0100 --> 1100 ,只有最高位發(fā)生變化其余位相同

          6 --> 9 , 格雷碼從 0101 --> 1101 , 只有最高位發(fā)生變化其余位相同

          以此類推,為什么要說鏡像對(duì)稱呢?

          試想如果讀指針指向 8,寫指針指向 7 ,我們可以知道此時(shí)此刻并不是讀空狀態(tài)也不是寫滿狀態(tài)

          但是如果在此刻套用理論 1 來判斷,看會(huì)出現(xiàn)什么情況,我們來套一下

          7的格雷碼與8的格雷碼的最高位不同,其余位相同,所以判斷出為寫滿。這就出現(xiàn)誤判了,同樣套用在 6 和 9,5 和 10等也會(huì)出現(xiàn)誤判。

          因此用格雷碼判斷是否為讀空或?qū)憹M時(shí)應(yīng)使用理論 2,看最高位和次高位是否相等,具體如下:

          當(dāng)最高位和次高位相同,其余位相同認(rèn)為是讀空

          當(dāng)最高位和次高位不同,其余位相同認(rèn)為是寫滿

          補(bǔ):理論2這個(gè)判斷方法適用于用格雷碼判斷比較空滿

          在實(shí)際設(shè)計(jì)中如果不想用格雷碼比較,就可以利用格雷碼將讀寫地址同步到一個(gè)時(shí)鐘域后再將格雷碼再次轉(zhuǎn)化成二進(jìn)制數(shù)再用理論1進(jìn)行比較就好了。。

          圖 1

          2、由于是異步FIFO的設(shè)計(jì),讀寫時(shí)鐘不一樣,在產(chǎn)生讀空信號(hào)和寫滿信號(hào)時(shí),會(huì)涉及到跨時(shí)鐘域的問題,如何解決?

          跨時(shí)鐘域的問題:上面我們已經(jīng)提到要通過比較讀寫指針來判斷產(chǎn)生讀空和寫滿信號(hào)

          但是讀指針是屬于讀時(shí)鐘域的,寫指針是屬于寫時(shí)鐘域的,而異步FIFO的讀寫時(shí)鐘域不同,是異步的,

          要是將讀時(shí)鐘域的讀指針與寫時(shí)鐘域的寫指針不做任何處理直接比較肯定是錯(cuò)誤的,因此我們需要進(jìn)行同步處理以后仔進(jìn)行比較

          解決方法:兩級(jí)寄存器同步 + 格雷碼

          同步的過程有兩個(gè):

          (1)將寫時(shí)鐘域的寫指針同步到讀時(shí)鐘域,將同步后的寫指針與讀時(shí)鐘域的讀指針進(jìn)行比較產(chǎn)生讀空信號(hào)

          (2)將讀時(shí)鐘域的讀指針同步到寫時(shí)鐘域,將同步后的讀指針與寫時(shí)鐘域的寫指針進(jìn)行比較產(chǎn)生寫滿信號(hào)

          同步的思想就是用兩級(jí)寄存器同步,簡單說就是打兩拍,相信有點(diǎn)基礎(chǔ)的早都爛熟于心,就不再多做解釋,不懂的可以看看代碼結(jié)合理解。

          只是這樣簡單的同步就可以了嗎?no no no ,可怕的亞穩(wěn)態(tài)還在等著你。

          我們?nèi)绻苯佑枚M(jìn)制編碼的讀寫指針去完成上述的兩種同步是不行的,使用格雷碼更合適,為什么呢?

          因?yàn)槎M(jìn)制編碼的指針在跳變的時(shí)候有可能是多位數(shù)據(jù)一起變化,如二進(jìn)制的7-->8 即 0111 --> 1000 ,在跳變的過程中 4 位全部發(fā)生了改變,這樣很容易產(chǎn)生毛刺,例如:

          異步FIFO的寫指針和讀指針分屬不同時(shí)鐘域,這樣指針在進(jìn)行同步過程中很容易出錯(cuò),比如寫指針在從0111到1000跳變時(shí)4位同時(shí)改變,這樣讀時(shí)鐘在進(jìn)行寫指針同步后得到的寫指針可能是0000-1111的某個(gè)值,一共有2^4個(gè)可能的情況,而這些都是不可控制的,你并不能確定會(huì)出現(xiàn)哪個(gè)值,那出錯(cuò)的概率非常大,怎么辦呢?到了格雷碼發(fā)揮作用的時(shí)候了,而格雷碼的編碼特點(diǎn)是相鄰位每次只有 1 位發(fā)生變化, 這樣在進(jìn)行指針同步的時(shí)候,只有兩種可能出現(xiàn)的情況:1.指針同步正確,正是我們所要的;2.指針同步出錯(cuò),舉例假設(shè)格雷碼寫指針從000->001,將寫指針同步到讀時(shí)鐘域同步出錯(cuò),出錯(cuò)的結(jié)果只可能是000->000,因?yàn)橄噜徫坏母窭状a每次只有一位變化,這個(gè)出錯(cuò)結(jié)果實(shí)際上也就是寫指針沒有跳變保持不變,我們所關(guān)心的就是這個(gè)錯(cuò)誤會(huì)不會(huì)導(dǎo)致讀空判斷出錯(cuò)?答案是不會(huì),最多是讓空標(biāo)志在FIFO不是真正空的時(shí)候產(chǎn)生,而不會(huì)出現(xiàn)空讀的情形。所以gray碼保證的是同步后的讀寫指針即使在出錯(cuò)的情形下依然能夠保證FIFO功能的正確性。在同步過程中的亞穩(wěn)態(tài)不可能消除,但是我們只要保證它不會(huì)影響我們的正常工作即可。

          3、由于設(shè)計(jì)的時(shí)候讀寫指針用了至少兩級(jí)寄存器同步,同步會(huì)消耗至少兩個(gè)時(shí)鐘周期,勢(shì)必會(huì)使得判斷空或滿有所延遲,這會(huì)不會(huì)導(dǎo)致設(shè)計(jì)出錯(cuò)呢?

          異步FIFO通過比較讀寫指針進(jìn)行滿空判斷,但是讀寫指針屬于不同的時(shí)鐘域,所以在比較之前需要先將讀寫指針進(jìn)行同步處理,

          將寫指針同步到讀時(shí)鐘域再和讀指針比較進(jìn)行FIFO空狀態(tài)判斷,因?yàn)樵谕綄懼羔槙r(shí)需要時(shí)間,而在這個(gè)同步的時(shí)間內(nèi)有可能還會(huì)寫入新的數(shù)據(jù),因此同步后的寫指針一定是小于或者等于當(dāng)前實(shí)際的寫指針,所以此時(shí)判斷FIFO為空不一定是真空,這樣更加保守,一共不會(huì)出現(xiàn)空讀的情況,雖然會(huì)影響FIFO的性能,但是并不會(huì)出錯(cuò),同理將讀指針同步到寫時(shí)鐘域再和寫指針比較進(jìn)行FIFO滿狀態(tài)判斷,同步后的讀指針一定是小于或者等于當(dāng)前的讀指針,所以此時(shí)判斷FIFO為滿不一定是真滿,這樣更保守,這樣可以保證FIFO的特性:FIFO空之后不能繼續(xù)讀取,F(xiàn)IFO滿之后不能繼續(xù)寫入??偨Y(jié)來說異步邏輯轉(zhuǎn)到同步邏輯不可避免需要額外的時(shí)鐘開銷,這會(huì)導(dǎo)致滿空趨于保守,但是保守并不等于錯(cuò)誤,這么寫會(huì)稍微有性能損失,但是不會(huì)出錯(cuò)。

          舉個(gè)例子:大多數(shù)情形下,異步FIFO兩端的時(shí)鐘不是同頻的,或者讀快寫慢,或者讀慢寫快,慢的時(shí)鐘域同步到快的時(shí)鐘域不會(huì)出現(xiàn)漏掉指針的情況,但是將指針從快的時(shí)鐘域同步到慢的時(shí)鐘域時(shí)可能會(huì)有指針遺漏,舉個(gè)例子以讀慢寫快為例,進(jìn)行滿標(biāo)志判斷的時(shí)候需要將讀指針同步到寫時(shí)鐘域,因?yàn)樽x慢寫快,所以不會(huì)有讀指針遺漏,同步消耗時(shí)鐘周期,所以同步后的讀指針滯后(小于等于)當(dāng)前讀地址,所以可能滿標(biāo)志會(huì)提前產(chǎn)生,滿并非真滿。進(jìn)行空標(biāo)志判斷的時(shí)候需要將寫指針同步到讀指針 ,因?yàn)樽x慢寫快,所以當(dāng)讀時(shí)鐘同步寫指針 的時(shí)候,必然會(huì)漏掉一部分寫指針,我們不用關(guān)心那到底會(huì)漏掉哪些寫指針,我們?cè)诤醯氖锹┑舻闹羔槙?huì)對(duì)FIFO的空標(biāo)志產(chǎn)生影響嗎?比如寫指針從0寫到10,期間讀時(shí)鐘域只同步捕捉到了3、5、8這三個(gè)寫指針而漏掉了其他指針。當(dāng)同步到8這個(gè)寫指針時(shí),真實(shí)的寫指針可能已經(jīng)寫到10 ,相當(dāng)于在讀時(shí)鐘域還沒來得及覺察的情況下,寫時(shí)鐘域可能偷偷寫了數(shù)據(jù)到FIFO去,這樣在判斷它是不是空的時(shí)候會(huì)出現(xiàn)不是真正空的情況,漏掉的指針也沒有對(duì)FIFO的邏輯操作產(chǎn)生影響。

          4、多位二進(jìn)制碼如何轉(zhuǎn)化為格雷碼

          二進(jìn)制碼轉(zhuǎn)換成二進(jìn)制格雷碼,其法則是保留二進(jìn)制碼的最高位作為格雷碼的最高位,而次高位格雷碼為二進(jìn)制碼的高位與次高位相異或,而格雷碼其余各位與次高位的求法相類似。

          我再換種更簡單的描述

          二進(jìn)制數(shù) 1 0 1 1 0

          二進(jìn)制數(shù)右移1位,空位補(bǔ)0 0 1 0 1 1

          異或運(yùn)算 1 1 1 0 1

          這樣就可以實(shí)現(xiàn)二進(jìn)制到格雷碼的轉(zhuǎn)換了,總結(jié)就是移位并且異或,verilog代碼實(shí)現(xiàn)就一句:assign wgraynext = (wbinnext>>1) ^ wbinnext;

          是不是非常簡單。

          三、代碼解析

          異步FIFO的信號(hào)接口:

          wclk wrst_n winc wdata //寫時(shí)鐘、寫復(fù)位、寫請(qǐng)求、寫數(shù)據(jù) 這幾個(gè)與寫有關(guān)的全部與wclk同步

          rclk rrst_n rinc rdata //讀時(shí)鐘、讀 復(fù)位、讀 請(qǐng)求、讀 數(shù)據(jù) 這幾個(gè)與讀有關(guān)的全部與rclk同步

          wfull //寫滿 與wclk同步

          rempty // 讀空 與rclk同步

          本次代碼共分為6個(gè)module

          1、fifo.v 是頂層模塊,作用是將各個(gè)小模塊例化聯(lián)系起來

          module fifo

          #(

          parameter DSIZE = 8,

          parameter ASIZE = 4

          )

          (

          output [DSIZE-1:0] rdata,

          output wfull,

          output rempty,

          input [DSIZE-1:0] wdata,

          input winc, wclk, wrst_n,

          input rinc, rclk, rrst_n

          );

          wire [ASIZE-1:0] waddr, raddr;

          wire [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr;

          // synchronize the read pointer into the write-clock domain

          sync_r2w sync_r2w

          (

          .wq2_rptr (wq2_rptr),

          .rptr (rptr ),

          .wclk (wclk ),

          .wrst_n (wrst_n )

          );

          // synchronize the write pointer into the read-clock domain

          sync_w2r sync_w2r

          (

          .rq2_wptr(rq2_wptr),

          .wptr(wptr),

          .rclk(rclk),

          .rrst_n(rrst_n)

          );

          //this is the FIFO memory buffer that is accessed by both the write and read clock domains.

          //This buffer is most likely an instantiated, synchronous dual-port RAM.

          //Other memory styles can be adapted to function as the FIFO buffer.

          fifomem

          #(DSIZE, ASIZE)

          fifomem

          (

          .rdata(rdata),

          .wdata(wdata),

          .waddr(waddr),

          .raddr(raddr),

          .wclken(winc),

          .wfull(wfull),

          .wclk(wclk)

          );

          //this module is completely synchronous to the read-clock domain and contains the FIFO read pointer and empty-flag logic.

          rptr_empty

          #(ASIZE)

          rptr_empty

          (

          .rempty(rempty),

          .raddr(raddr),

          .rptr(rptr),

          .rq2_wptr(rq2_wptr),

          .rinc(rinc),

          .rclk(rclk),

          .rrst_n(rrst_n)

          );

          //this module is completely synchronous to the write-clock domain and contains the FIFO write pointer and full-flag logic

          wptr_full

          #(ASIZE)

          wptr_full

          (

          .wfull(wfull),

          .waddr(waddr),

          .wptr(wptr),

          .wq2_rptr(wq2_rptr),

          .winc(winc),

          .wclk(wclk),

          .wrst_n(wrst_n)

          );

          endmodule

          2、fifomem.v 生成存儲(chǔ)實(shí)體,F(xiàn)IFO 的本質(zhì)是RAM,因此在設(shè)計(jì)存儲(chǔ)實(shí)體的時(shí)候有兩種方法:用數(shù)組存儲(chǔ)數(shù)據(jù)或者調(diào)用RAM的IP核

          module fifomem

          #(

          parameter DATASIZE = 8, // Memory data word width

          parameter ADDRSIZE = 4 // 深度為8即地址為3位即可,這里多定義一位的原因是用來判斷是空還是滿,詳細(xì)在后文講到

          ) // Number of mem address bits

          (

          output [DATASIZE-1:0] rdata,

          input [DATASIZE-1:0] wdata,

          input [ADDRSIZE-1:0] waddr, raddr,

          input wclken, wfull, wclk

          );

          `ifdef RAM //可以調(diào)用一個(gè)RAM IP核

          // instantiation of a vendor's dual-port RAM

          my_ram mem

          (

          .dout(rdata),

          .din(wdata),

          .waddr(waddr),

          .raddr(raddr),

          .wclken(wclken),

          .wclken_n(wfull),

          .clk(wclk)

          );

          `else //用數(shù)組生成存儲(chǔ)體

          // RTL Verilog memory model

          localparam DEPTH = 1 reg [DATASIZE-1:0] mem [0:DEPTH-1]; //生成2^4個(gè)位寬位8的數(shù)組

          assign rdata = mem[raddr];

          always @(posedge wclk) //當(dāng)寫使能有效且還未寫滿的時(shí)候?qū)?shù)據(jù)寫入存儲(chǔ)實(shí)體中,注意這里是與wclk同步的

          if (wclken !wfull)

          mem[waddr] = wdata;

          `endif

          endmodule

          3、sync_r2w.v 將 rclk 時(shí)鐘域的格雷碼形式的讀指針同步到 wclk 時(shí)鐘域,簡單來講就是用兩級(jí)寄存器同步,即打兩拍

          module sync_r2w

          #(

          parameter ADDRSIZE = 4

          )

          (

          output reg [ADDRSIZE:0] wq2_rptr, //讀指針同步到寫時(shí)鐘域

          input [ADDRSIZE:0] rptr, // 格雷碼形式的讀指針,格雷碼的好處后面會(huì)細(xì)說

          input wclk, wrst_n

          );

          reg [ADDRSIZE:0] wq1_rptr;

          always @(posedge wclk or negedge wrst_n)

          if (!wrst_n) begin

          wq1_rptr = 0;

          wq2_rptr = 0;

          end

          else begin

          wq1_rptr= rptr;

          wq2_rptr=wq1_rptr;

          end

          endmodule

          4、sync_w2r.v 將 wclk 時(shí)鐘域的格雷碼形式的寫指針同步到 rclk 時(shí)鐘域

          module sync_w2r

          #(parameter ADDRSIZE = 4)

          (

          output reg [ADDRSIZE:0] rq2_wptr, //寫指針同步到讀時(shí)鐘域

          input [ADDRSIZE:0] wptr, //格雷碼形式的寫指針

          input rclk, rrst_n

          );

          reg [ADDRSIZE:0] rq1_wptr;

          always @(posedge rclk or negedge rrst_n)

          if (!rrst_n)begin

          rq1_wptr = 0;

          rq2_wptr = 0;

          end

          else begin

          rq1_wpt = wptr;

          rq2_wptr = rq1_wptr;

          end

          endmodule

          5、rptr_empty.v 將 sync_w2r.v 同步后的寫指針與 rclk 時(shí)鐘域的讀指針進(jìn)行比較生成都空信號(hào)

          module rptr_empty

          #(

          parameter ADDRSIZE = 4

          )

          (

          output reg rempty,

          output [ADDRSIZE-1:0] raddr, //二進(jìn)制形式的讀指針

          output reg [ADDRSIZE :0] rptr, //格雷碼形式的讀指針

          input [ADDRSIZE :0] rq2_wptr, //同步后的寫指針

          input rinc, rclk, rrst_n

          );

          reg [ADDRSIZE:0] rbin;

          wire [ADDRSIZE:0] rgraynext, rbinnext;

          // GRAYSTYLE2 pointer

          //將二進(jìn)制的讀指針與格雷碼進(jìn)制的讀指針同步

          always @(posedge rclk or negedge rrst_n)

          if (!rrst_n) begin

          rbin = 0;

          rptr = 0;

          end

          else begin

          rbin=rbinnext; //直接作為存儲(chǔ)實(shí)體的地址

          rptr=rgraynext;//輸出到 sync_r2w.v模塊,被同步到 wrclk 時(shí)鐘域

          end

          // Memory read-address pointer (okay to use binary to address memory)

          assign raddr = rbin[ADDRSIZE-1:0]; //直接作為存儲(chǔ)實(shí)體的地址,比如連接到RAM存儲(chǔ)實(shí)體的讀地址端。

          assign rbinnext = rbin + (rinc ~rempty); //不空且有讀請(qǐng)求的時(shí)候讀指針加1

          assign rgraynext = (rbinnext>>1) ^ rbinnext; //將二進(jìn)制的讀指針轉(zhuǎn)為格雷碼

          // FIFO empty when the next rptr == synchronized wptr or on reset

          assign rempty_val = (rgraynext == rq2_wptr); //當(dāng)讀指針等于同步后的寫指針,則為空。

          always @(posedge rclk or negedge rrst_n)

          if (!rrst_n)

          rempty = 1'b1;

          else

          rempty = rempty_val;

          endmodule

          6、wptr_full.v 將 sync_r2w.v 同步后的讀指針與wclk 時(shí)鐘域的寫指針進(jìn)行比較生成寫滿信號(hào)

          module wptr_full

          #(

          parameter ADDRSIZE = 4

          )

          (

          output reg wfull,

          output [ADDRSIZE-1:0] waddr,

          output reg [ADDRSIZE :0] wptr,

          input [ADDRSIZE :0] wq2_rptr,

          input winc, wclk, wrst_n

          );

          reg [ADDRSIZE:0] wbin;

          wire [ADDRSIZE:0] wgraynext, wbinnext;

          // GRAYSTYLE2 pointer

          always @(posedge wclk or negedge wrst_n)

          if (!wrst_n)

          {wbin, wptr} = 0;

          else

          {wbin, wptr} = {wbinnext, wgraynext};

          // Memory write-address pointer (okay to use binary to address memory)

          assign waddr = wbin[ADDRSIZE-1:0];

          assign wbinnext = wbin + (winc ~wfull);

          assign wgraynext = (wbinnext>>1) ^ wbinnext; //二進(jìn)制轉(zhuǎn)為格雷碼

          //-----------------------------------------------------------------

          assign wfull_val = (wgraynext=={~wq2_rptr[ADDRSIZE:ADDRSIZE-1],wq2_rptr[ADDRSIZE-2:0]}); //當(dāng)最高位和次高位不同其余位相同時(shí)則寫指針超前于讀指針一圈,即寫滿。后面會(huì)詳細(xì)解釋。

          always @(posedge wclk or negedge wrst_n)

          if (!wrst_n)

          wfull = 1'b0;

          else

          wfull = wfull_val;

          endmodule

          7、測(cè)試文件

          `timescale 1ns /1ns

          module test();

          reg [7:0] wdata;

          reg winc, wclk, wrst_n;

          reg rinc, rclk, rrst_n;

          wire [7:0] rdata;

          wire wfull;

          wire rempty;

          fifo

          u_fifo (

          .rdata(rdata),

          .wfull(wfull),

          .rempty(rempty),

          .wdata (wdata),

          .winc (winc),

          .wclk (wclk),

          .wrst_n(wrst_n),

          .rinc(rinc),

          .rclk(rclk),

          .rrst_n(rrst_n)

          );

          localparam CYCLE = 20;

          localparam CYCLE1 = 40;

          //時(shí)鐘周期,單位為ns,可在此修改時(shí)鐘周期。

          //生成本地時(shí)鐘50M

          initial begin

          wclk = 0;

          forever

          #(CYCLE/2)

          wclk=~wclk;

          end

          initial begin

          rclk = 0;

          forever

          #(CYCLE1/2)

          rclk=~rclk;

          end

          //產(chǎn)生復(fù)位信號(hào)

          initial begin

          wrst_n = 1;

          #2;

          wrst_n = 0;

          #(CYCLE*3);

          wrst_n = 1;

          end

          initial begin

          rrst_n = 1;

          #2;

          rrst_n = 0;

          #(CYCLE*3);

          rrst_n = 1;

          end

          always @(posedge wclk or negedge wrst_n)begin

          if(wrst_n==1'b0)begin

          winc = 0;

          rinc = 0;

          end

          else begin

          winc = $random;

          rinc = $random;

          end

          end

          always @(posedge rclk or negedge rrst_n)begin

          if(rrst_n==1'b0)begin

          rinc = 0;

          end

          else begin

          rinc = $random;

          end

          end

          always@(*)begin

          if(winc == 1)

          wdata= $random ;

          else

          wdata = 0;

          end

          endmodule

          8、仿真結(jié)果

          由于截圖篇幅的限制請(qǐng)自己驗(yàn)證仿真。



          關(guān)鍵詞:

          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();