色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

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

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

3天內不再提示

同步FIFO之Verilog實現

FPGA之家 ? 來源:FPGA之家 ? 作者:FPGA之家 ? 2022-11-01 09:57 ? 次閱讀


1.定義

FIFO是英文First In First Out 的縮寫,是一種先進先出的數據緩存器,他與普通存儲器的區別是沒有外部讀寫地址線,這樣使用起來非常簡單,但缺點就是只能順序寫入數據,順序的讀出數據, 其數據地址由內部讀寫指針自動加1完成,不能像普通存儲器那樣可以由地址線決定讀取或寫入某個指定的地址。

FIFO一般用于不同時鐘域之間的數據傳輸,比如FIFO的一端是AD數據采集, 另一端是計算機的PCI總線,假設其AD采集的速率為16位 100K SPS,那么每秒的數據量為100K×16bit=1.6Mbps,而PCI總線的速度為33MHz,總線寬度32bit,其最大傳輸速率為 1056Mbps,在兩個不同的時鐘域間就可以采用FIFO來作為數據緩沖。另外對于不同寬度的數據接口也可以用FIFO,例如單片機位8位數據輸出,而 DSP可能是16位數據輸入,在單片機與DSP連接時就可以使用FIFO來達到數據匹配的目的。

FIFO的分類根均FIFO工作的時鐘域,可以將FIFO分為同步FIFO和異步FIFO。同步FIFO是指讀時鐘和寫時鐘為同一個時鐘。在時鐘沿來臨時同時發生讀寫操作。異步FIFO是指讀寫時鐘不一致,讀寫時鐘是互相獨立的。

FIFO設計的難點 FIFO設計的難點在于怎樣判斷FIFO的空/滿狀態。為了保證數據正確的寫入或讀出,而不發生益處或讀空的狀態出現,必須保證FIFO在滿的情況下,不 能進行寫操作。在空的狀態下不能進行讀操作。怎樣判斷FIFO的滿/空就成了FIFO設計的核心問題。

1.同步FIFO之Verilog實現

同步FIFO的意思是說FIFO的讀寫時鐘是同一個時鐘,不同于異步FIFO,異步FIFO的讀寫時鐘是完全異步的。同步FIFO的對外接口包括時鐘,清零,讀請求,寫請求,數據輸入總線,數據輸出總線,空以及滿信號。下面分別對同步FIFO的對外接口信號作一描述:

1. 時鐘,輸入,用于同步FIFO的讀和寫,上升沿有效;

2. 清零,輸入,異步清零信號,低電平有效,該信號有效時,FIFO被清空;

3. 寫請求,輸入,低電平有效,該信號有效時,表明外部電路請求向FIFO寫入數據;

4. 讀請求,輸入,低電平有效,該信號有效時,表明外部電路請求從FIFO中讀取數據;

5. 數據輸入總線,輸入,當寫信號有效時,數據輸入總線上的數據被寫入到FIFO中;

6. 數據輸出總線,輸出,當讀信號有效時,數據從FIFO中被讀出并放到數據輸出總線上;

7. 空,輸出,高電平有效,當該信號有效時,表明FIFO中沒有任何數據,全部為空;

8. 滿,輸出,高電平有效,當該信號有效時,表明FIFO已經滿了,沒有空間可用來存貯數據。

下面的框圖主要描述同步FIFO的內部結構,畫出框圖有助于對電路結構的理解,同樣也有助于RTL代碼的編寫 :

b2d74312-5987-11ed-a3b6-dac502259ad0.jpg

…………………………………………………………………………………………………………………………………………………………………………………………..

同步FIFO的Verilog代碼 之一
在modlesim中驗證過。

/******************************************************
A fifo controller verilog description.
******************************************************/
module fifo(datain, rd, wr, rst, clk, dataout, full, empty);
input [7:0] datain;
input rd, wr, rst, clk;
output [7:0] dataout;
output full, empty;
wire [7:0] dataout;
reg full_in, empty_in;
reg [7:0] mem [15:0];
reg [3:0] rp, wp;
assign full = full_in;
assign empty = empty_in;
// memory read out
assign dataout = mem[rp];
// memory write in
always@(posedge clk) begin
    if(wr && ~full_in) mem[wp]<=datain;
end
// memory write pointer increment
always@(posedge clk or negedge rst) begin
    if(!rst) wp<=0;
    else begin
      if(wr && ~full_in) wp<= wp+1'b1;
    end
end
// memory read pointer increment
always@(posedge clk or negedge rst)begin
    if(!rst) rp <= 0;
    else begin
      if(rd && ~empty_in) rp <= rp + 1'b1;
    end
end
// Full signal generate
always@(posedge clk or negedge rst) begin
    if(!rst) full_in <= 1'b0;
    else begin
      if( (~rd && wr)&&((wp==rp-1)||(rp==4'h0&&wp==4'hf)))
          full_in <= 1'b1;
      else if(full_in && rd) full_in <= 1'b0;
    end
end
// Empty signal generate
always@(posedge clk or negedge rst) begin
    if(!rst) empty_in <= 1'b1;
    else begin
      if((rd&&~wr)&&(rp==wp-1 || (rp==4'hf&&wp==4'h0)))
        empty_in<=1'b1;
      else if(empty_in && wr) empty_in<=1'b0;
    end
end
endmodule

…………………………………………………………………………………………………………………………………………………………………………………………..

同步FIFO的Verilog代碼 之二 這一種設計的FIFO,是基于觸發器的。寬度,深度的擴展更加方便,結構化跟強。以下代碼在modelsim中驗證過。

module fifo_cell (sys_clk, sys_rst_n, read_fifo, write_fifo, fifo_input_data,
                        next_cell_data, next_cell_full, last_cell_full, cell_data_out, cell_full);
                        parameter WIDTH =8;
                        parameter D = 2;
                        input sys_clk;
                        input sys_rst_n;
                        input read_fifo, write_fifo;
                        input [WIDTH-1:0] fifo_input_data;
                        input [WIDTH-1:0] next_cell_data;
                        input next_cell_full, last_cell_full;
                        output [WIDTH-1:0] cell_data_out;
                        output cell_full;
                        reg [WIDTH-1:0] cell_data_reg_array;
                        reg [WIDTH-1:0] cell_data_ld;
                        reg cell_data_ld_en;
                        reg cell_full;
                        reg cell_full_next;
                        assign cell_data_out=cell_data_reg_array;
                        always @(posedge sys_clk or negedge sys_rst_n)
                           if (!sys_rst_n)
                              cell_full <= #D 0;
                           else if (read_fifo || write_fifo)
                              cell_full <= #D cell_full_next;
                        always @(write_fifo or read_fifo or next_cell_full or last_cell_full or cell_full)
                           casex ({read_fifo, write_fifo})
                               2'b00: cell_full_next = cell_full;
                               2'b01: cell_full_next = next_cell_full;
                               2'b10: cell_full_next = last_cell_full;
                               2'b11: cell_full_next = cell_full;
                           endcase
                         always @(posedge sys_clk or negedge sys_rst_n)
                              if (!sys_rst_n)
                                 cell_data_reg_array [WIDTH-1:0] <= #D 0;
                              else if (cell_data_ld_en)
                                 cell_data_reg_array [WIDTH-1:0] <= #D cell_data_ld [WIDTH-1:0];
                         always @(write_fifo or read_fifo or cell_full or last_cell_full)   
                              casex ({write_fifo,read_fifo,cell_full,last_cell_full})
                                  4'bx1_xx: cell_data_ld_en = 1'b1;
                                  4'b10_01: cell_data_ld_en = 1'b1;
                                  default: cell_data_ld_en =1'b0;
                              endcase
                         always @(write_fifo or read_fifo or next_cell_full or cell_full or last_cell_full or fifo_input_data or next_cell_data)
                              casex ({write_fifo, read_fifo, next_cell_full, cell_full, last_cell_full})
                                 5'b10_x01: cell_data_ld[WIDTH-1:0] = fifo_input_data[WIDTH-1:0];
                                 5'b11_01x: cell_data_ld[WIDTH-1:0] = fifo_input_data[WIDTH-1:0];
                                 default: cell_data_ld[WIDTH-1:0] = next_cell_data[WIDTH-1:0];
                              endcase
endmodule



module fifo_4cell(sys_clk, sys_rst_n, fifo_input_data, write_fifo, fifo_out_data,
                  read_fifo, full_cell0, full_cell1, full_cell2, full_cell3);
                  parameter WIDTH = 8;
                  parameter D = 2;
                  input sys_clk;
                  input sys_rst_n;
                  input [WIDTH-1:0] fifo_input_data;
                  output [WIDTH-1:0] fifo_out_data;
                  input read_fifo, write_fifo;
                  output full_cell0, full_cell1, full_cell2, full_cell3;
                  wire [WIDTH-1:0] dara_out_cell0, data_out_cell1, data_out_cell2,
                                   data_out_cell3, data_out_cell4;
                  wire full_cell4;
                  fifo_cell #(WIDTH,D) cell0
                  ( .sys_clk (sys_clk),
                    .sys_rst_n (sys_rst_n),
                    .fifo_input_data (fifo_input_data[WIDTH-1:0]),
                    .write_fifo (write_fifo),
                    .next_cell_data (data_out_cell1[WIDTH-1:0]),
                    .next_cell_full (full_cell1),
                    .last_cell_full (1'b1),
                    .cell_data_out (fifo_out_data [WIDTH-1:0]),
                    .read_fifo (read_fifo),
                    .cell_full (full_cell0)
                   );

                  fifo_cell #(WIDTH,D) cell1
                  ( .sys_clk (sys_clk),
                    .sys_rst_n (sys_rst_n),
                    .fifo_input_data (fifo_input_data[WIDTH-1:0]),
                    .write_fifo (write_fifo),
                    .next_cell_data (data_out_cell2[WIDTH-1:0]),
                    .next_cell_full (full_cell2),
                    .last_cell_full (full_cell0),
                    .cell_data_out (data_out_cell1[WIDTH-1:0]),
                    .read_fifo (read_fifo),
                    .cell_full (full_cell1)
                   );                  
                  fifo_cell #(WIDTH,D) cell2
                  ( .sys_clk (sys_clk),
                    .sys_rst_n (sys_rst_n),
                    .fifo_input_data (fifo_input_data[WIDTH-1:0]),
                    .write_fifo (write_fifo),
                    .next_cell_data (data_out_cell3[WIDTH-1:0]),
                    .next_cell_full (full_cell3),
                    .last_cell_full (full_cell1),
                    .cell_data_out (data_out_cell2[WIDTH-1:0]),
                    .read_fifo (read_fifo),
                    .cell_full (full_cell2)
                   );                  

                  fifo_cell #(WIDTH,D) cell3
                  ( .sys_clk (sys_clk),
                    .sys_rst_n (sys_rst_n),
                    .fifo_input_data (fifo_input_data[WIDTH-1:0]),
                    .write_fifo (write_fifo),
                    .next_cell_data (data_out_cell4[WIDTH-1:0]),
                    .next_cell_full (full_cell4),
                    .last_cell_full (full_cell2),
                    .cell_data_out (data_out_cell3[WIDTH-1:0]),
                    .read_fifo (read_fifo),
                    .cell_full (full_cell3)
                   );     
                   assign data_out_cell4[WIDTH-1:0] = {WIDTH{1'B0}};
                   assign full_cell4 = 1'b0;
endmodule

2.異步FIFO之Verilog實現

FIFO (先進先出隊列)是一種在電子系統得到廣泛應用的器件,通常用于數據的緩存和用于容納異步信號的頻率或相位的差異。FIFO的實現通常是利用雙口RAM和讀寫地址產生模塊來實現的。FIFO的接口信號包括異步的寫時鐘(wr_clk)和讀時鐘(rd_clk)、與寫時鐘同步的寫有效(wren)和寫數據(wr_data)、與讀時鐘同步的讀有效(rden)和讀數據(rd_data)。為了實現正確的讀寫和避免FIFO的上溢或下溢,通常還應該給出與讀時鐘和寫時鐘同步的FIFO的空標志(empty)和滿標志(full)以禁止讀寫操作。

1 異步FIFO功能描述

圖1給出了FIFO的接口信號和內部模塊圖。
由圖1可以看出,寫地址產生模塊根據寫時鐘和寫有效信號產生遞增的寫地睛,讀地址產生模塊根據讀時鐘和讀有效信號產生遞增的讀地址。FIFO的操作如下:在寫時鐘wr_clk的升沿,當wren有效時,將wr_data寫入雙口RAM中寫地址對應的位置中;始終將讀地址對應的雙口RAM中的數據輸出到讀數據總線上。這樣就實現了先進先出的功能。
b2fa9a06-5987-11ed-a3b6-dac502259ad0.jpg

寫地址產生模塊還根據讀地址和寫地址關系產生FIFO的滿標志。當wren有效時,若寫地址+2=讀地址時,full為1;當wren無效時,若寫地址+ 1=讀地址時,full為1。讀地址產生模塊還根據讀地址和寫地址的差產生FIFO的空標志。當rden有效時,若寫地址-1=讀地址時,empty為 1;當rden無效時,若寫地址=讀地址時,empty為1。按照以上方式產生標志信號是為了提前一個時鐘周期產生對應的標志信號。
由于空標志和滿標志控制了FIFO的操作,因此標志錯誤會引起操作的錯誤。如上所述,標志的產生是通過對讀寫地址的比較產生的,當讀寫時鐘完全異步時,對讀寫地址進行比較時,可能得出錯誤的結果。例如,在讀地址變化過程中,由于讀地址的各位變化并不同步,計算讀寫地址的差值,可能產生錯誤的差值,導致產生錯誤的滿標志信號。若將未滿標志置為滿標志時,可能降低了應用的性能,降低寫數據速率;而將滿置標志置為未滿時,執行一次寫操作,則可能產生溢出錯誤,這對于實際應用來說是絕對應該避免的。空標志信號的產生也可能產生類似的錯誤。

2 異步FIFO的改進設計

從以上分析中可以看出,異步FIFO之所以會發生錯誤是國為在地址變化時,由于多位地址各位變化時間不同,異步時鐘對其進行采樣時數值可能為不同于地址變化喪后數值的其他值,異步產生錯誤的空標志和滿標志,以致于產生FIFO的操作錯誤。
格雷碼是一種在相鄰計數值之間只有一位發生變化的編碼方式。可以看出,若讀寫地址采用格雷碼編碼方式,就可以解決上面的問題。
為了應用的靈活,還增加了兩個標志信號,將滿(almosf_full)標志和空(almost_empty)標志分別定義如下:當寫地址與讀地址的距離小于某個預先定義數值時,almost_full為1;當讀地址與寫地址的距離小于這個預先定義的數值時,almost_empty為1。

3 異步FIFO的Verilog

…………………………………………………………………………………………………………………………………………………………………………………………………………………………….
異步FIFO的Verilog代碼 之一
這個是基于RAM的異步FIFO代碼,個人認為代碼結構簡單易懂,非常適合于考試中填寫。記得10月份參加威盛的筆試的時候,就考過異步FIFO的實現。想當初要是早點復習,可能就可以通過威盛的筆試了。

與之前的用RAM實現的同步FIFO的程序相比,異步更為復雜。增加了讀寫控制信號的跨時鐘域的同步。此外,判空與判滿的也稍有不同。

module fifo1(rdata, wfull, rempty, wdata, winc, wclk, wrst_n,rinc, rclk, rrst_n);
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;
reg wfull,rempty;
reg [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr, wq1_rptr,rq1_wptr;
reg [ASIZE:0] rbin, wbin;
reg [DSIZE-1:0] mem[0:(1<1];
wire [ASIZE-1:0] waddr, raddr;
wire [ASIZE:0] rgraynext, rbinnext,wgraynext,wbinnext;
wire rempty_val,wfull_val;
//-----------------雙口RAM存儲器--------------------
assign rdata=mem[raddr];
always@(posedge wclk)
if (winc && !wfull) mem[waddr] <= wdata;
//-------------同步rptr 指針-------------------------
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
//-------------同步wptr指針---------------------------
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
//-------------rempty產生與raddr產生-------------------
always @(posedge rclk or negedge rrst_n) // GRAYSTYLE2 pointer
begin
if (!rrst_n) {rbin, rptr} <= 0;
else {rbin, rptr} <= {rbinnext, rgraynext};
end
// Memory read-address pointer (okay to use binary to address memory)
assign raddr = rbin[ASIZE-1:0];
assign rbinnext = rbin + (rinc & ~rempty);
assign rgraynext = (rbinnext>>1) ^ rbinnext;
// FIFO empty when the next rptr == synchronized wptr or on reset
assign rempty_val = (rgraynext == rq2_wptr);
always @(posedge rclk or negedge rrst_n)
begin
if (!rrst_n) rempty <= 1'b1;
else rempty <= rempty_val;
end
//---------------wfull產生與waddr產生------------------------------
always @(posedge wclk or negedge wrst_n) // GRAYSTYLE2 pointer
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[ASIZE-1:0];
assign wbinnext = wbin + (winc & ~wfull);
assign wgraynext = (wbinnext>>1) ^ wbinnext;
assign wfull_val = (wgraynext=={~wq2_rptr[ASIZE:ASIZE-1], wq2_rptr[ASIZE-2:0]}); //:ASIZE-1]
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) wfull <= 1'b0;
else wfull <= wfull_val;
endmodule

………………………………………………………………………………………………………………………………………………………………

異步FIFO的Verilog代碼 之二
與前一段異步FIFO代碼的主要區別在于,空/滿狀態標志的不同算法

第一個算法:Clifford E. Cummings的文章中提到的STYLE #1,構造一個指針寬度為N+1,深度為2^N字節的FIFO(為便方比較將格雷碼指針轉換為二進制指針)。當指針的二進制碼中最高位不一致而其它N位都 相等時,FIFO為滿(在Clifford E. Cummings的文章中以格雷碼表示是前兩位均不相同,而后兩位LSB相同為滿,這與換成二進制表示的MSB不同其他相同為滿是一樣的)。當指針完全相 等時,FIFO為空。

這種方法思路非常明了,為了比較不同時鐘產生的指針,需要把不同時鐘域的信號同步到本時鐘域中來,而使用Gray碼的目的就是使這個異步同步化的過 程發生亞穩態的機率最小,而為什么要構造一個N+1的指針,Clifford E. Cummings也闡述的很明白,有興趣的讀者可以看下作者原文是怎么論述的,Clifford E. Cummings的這篇文章有Rev1.1 Rev1.2兩個版本,兩者在比較Gray碼指針時的方法略有不同,個Rev1.2版更為精簡。

第二種算法:Clifford E. Cummings的文章中提到的STYLE #2。它將FIFO地址分成了4部分,每部分分別用高兩位的MSB 00 、01、 11、 10決定FIFO是否為going full 或going empty (即將滿或空)。如果寫指針的高兩位MSB小于讀指針的高兩位MSB則FIFO為“幾乎滿”,若寫指針的高兩位MSB大于讀指針的高兩位MSB則FIFO 為“幾乎空”。

它是利用將地址空間分成4個象限(也就是四個等大小的區域),然后觀察兩個指針的相對位置,如果寫指針落后讀指針一個象限(25%的距離,呵呵), 則證明很可能要寫滿,反之則很可能要讀空,這個時候分別設置兩個標志位dirset和dirrst,然后在地址完全相等的情況下,如果dirset有效就 是寫滿,如果dirrst有效就是讀空。

這種方法對深度為2^N字節的FIFO只需N位的指針即可,處理的速度也較第一種方法快。

這段是說明的原話,算法一,還好理解。算法二,似乎沒有說清楚,不太明白。有興趣的可以查查論文,詳細研究下。

總之,第二種寫法是推薦的寫法。因為異步的多時鐘設計應按以下幾個原則進行設計:
1,盡可能的將多時鐘的邏輯電路(非同步器)分割為多個單時鐘的模塊,這樣有利于靜態時序分析工具來進行時序驗證。
2,同步器的實現應使得所有輸入來自同一個時鐘域,而使用另一個時鐘域的異步時鐘信號采樣數據。
3,面向時鐘信號的命名方式可以幫助我們確定那些在不同異步時鐘域間需要處理的信號。
4,當存在多個跨時鐘域的控制信號時,我們必須特別注意這些信號,保證這些控制信號到達新的時鐘域仍然能夠保持正確的順序。

module fifo2 (rdata, wfull, rempty, wdata,
winc, wclk, wrst_n, rinc, rclk, rrst_n);
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] wptr, rptr;
wire [ASIZE-1:0] waddr, raddr;
async_cmp #(ASIZE) async_cmp(.aempty_n(aempty_n),
.afull_n(afull_n),
.wptr(wptr), .rptr(rptr),
.wrst_n(wrst_n));
fifomem2 #(DSIZE, ASIZE) fifomem2(.rdata(rdata),
.wdata(wdata),
.waddr(wptr),
.raddr(rptr),
.wclken(winc),
.wclk(wclk));
rptr_empty2 #(ASIZE) rptr_empty2(.rempty(rempty),
.rptr(rptr),
.aempty_n(aempty_n),
.rinc(rinc),
.rclk(rclk),
.rrst_n(rrst_n));
wptr_full2 #(ASIZE) wptr_full2(.wfull(wfull),
.wptr(wptr),
.afull_n(afull_n),
.winc(winc),
.wclk(wclk),
.wrst_n(wrst_n));
endmodule
module fifomem2 (rdata, wdata, waddr, raddr, wclken, wclk);
parameter DATASIZE = 8; // Memory data word width
parameter ADDRSIZE = 4; // Number of memory address bits
parameter DEPTH = 1<// DEPTH = 2**ADDRSIZE
output [DATASIZE-1:0] rdata;
input [DATASIZE-1:0] wdata;
input [ADDRSIZE-1:0] waddr, raddr;
input wclken, wclk;
`ifdef VENDORRAM
// instantiation of a vendor's dual-port RAM
VENDOR_RAM MEM (.dout(rdata), .din(wdata),
.waddr(waddr), .raddr(raddr),
.wclken(wclken), .clk(wclk));
`else
reg [DATASIZE-1:0] MEM [0:DEPTH-1];
assign rdata = MEM[raddr];
always @(posedge wclk)
if (wclken) MEM[waddr] <= wdata;
`endif
endmodule
module async_cmp (aempty_n, afull_n, wptr, rptr, wrst_n);
parameter ADDRSIZE = 4;
parameter N = ADDRSIZE-1;
output aempty_n, afull_n;
input [N:0] wptr, rptr;
input wrst_n;
reg direction;
wire high = 1'b1;
wire dirset_n = ~( (wptr[N]^rptr[N-1]) & ~(wptr[N-1]^rptr[N]));
wire dirclr_n = ~((~(wptr[N]^rptr[N-1]) & (wptr[N-1]^rptr[N])) |
~wrst_n);
always @(posedge high or negedge dirset_n or negedge dirclr_n)
if (!dirclr_n) direction <= 1'b0;
else if (!dirset_n) direction <= 1'b1;
else direction <= high;
//always @(negedge dirset_n or negedge dirclr_n)
//if (!dirclr_n) direction <= 1'b0;
//else direction <= 1'b1;
assign aempty_n = ~((wptr == rptr) && !direction);
assign afull_n = ~((wptr == rptr) && direction);
endmodule
module rptr_empty2 (rempty, rptr, aempty_n, rinc, rclk, rrst_n);
parameter ADDRSIZE = 4;
output rempty;
output [ADDRSIZE-1:0] rptr;
input aempty_n;
input rinc, rclk, rrst_n;
reg [ADDRSIZE-1:0] rptr, rbin;
reg rempty, rempty2;
wire [ADDRSIZE-1:0] rgnext, rbnext;
//---------------------------------------------------------------
// GRAYSTYLE2 pointer
//---------------------------------------------------------------
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) begin
rbin <= 0;
rptr <= 0;
end
else begin
rbin <= rbnext;
rptr <= rgnext;
end
//---------------------------------------------------------------
// increment the binary count if not empty
//---------------------------------------------------------------
assign rbnext = !rempty ? rbin + rinc : rbin;
assign rgnext = (rbnext>>1) ^ rbnext; // binary-to-gray conversion
always @(posedge rclk or negedge aempty_n)
if (!aempty_n) {rempty,rempty2} <= 2'b11;
else {rempty,rempty2} <= {rempty2,~aempty_n};
endmodule
module wptr_full2 (wfull, wptr, afull_n, winc, wclk, wrst_n);
parameter ADDRSIZE = 4;
output wfull;
output [ADDRSIZE-1:0] wptr;
input afull_n;
input winc, wclk, wrst_n;
reg [ADDRSIZE-1:0] wptr, wbin;
reg wfull, wfull2;
wire [ADDRSIZE-1:0] wgnext, wbnext;
//---------------------------------------------------------------
// GRAYSTYLE2 pointer
//---------------------------------------------------------------
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) begin
wbin <= 0;
wptr <= 0;
end
else begin
wbin <= wbnext;
wptr <= wgnext;
end
//---------------------------------------------------------------
// increment the binary count if not full
//---------------------------------------------------------------
assign wbnext = !wfull ? wbin + winc : wbin;
assign wgnext = (wbnext>>1) ^ wbnext; // binary-to-gray conversion
always @(posedge wclk or negedge wrst_n or negedge afull_n)
if (!wrst_n ) {wfull,wfull2} <= 2'b00;
else if (!afull_n) {wfull,wfull2} <= 2'b11;
else {wfull,wfull2} <= {wfull2,~afull_n};
endmodule

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • fifo
    +關注

    關注

    3

    文章

    387

    瀏覽量

    43648
  • Verilog
    +關注

    關注

    28

    文章

    1351

    瀏覽量

    110074
  • 緩存器
    +關注

    關注

    0

    文章

    63

    瀏覽量

    11658
收藏 人收藏

    評論

    相關推薦

    Verilog 與 ASIC 設計的關系 Verilog 代碼優化技巧

    Circuit,專用集成電路)設計是一個復雜的過程,涉及到邏輯設計、綜合、布局布線、物理驗證等多個環節。在這個過程中,Verilog被用來描述數字電路的行為和結構,進而實現ASIC的設計。 具體來說
    的頭像 發表于 12-17 09:52 ?92次閱讀

    Verilog 測試平臺設計方法 Verilog FPGA開發指南

    Verilog測試平臺設計方法是Verilog FPGA開發中的重要環節,它用于驗證Verilog設計的正確性和性能。以下是一個詳細的Verilog測試平臺設計方法及
    的頭像 發表于 12-17 09:50 ?120次閱讀

    Verilog與VHDL的比較 Verilog HDL編程技巧

    Verilog 與 VHDL 比較 1. 語法和風格 VerilogVerilog 的語法更接近于 C 語言,對于有 C 語言背景的工程師來說,學習曲線較平緩。它支持結構化編程,代碼更直觀,易于
    的頭像 發表于 12-17 09:44 ?113次閱讀

    FIFO Generator的Xilinx官方手冊

    如下: 類型 FIFO的類型區分主要根據FIFO實現時利用的是芯片中的哪些資源,其分類主要有以下四種: shift register FIFO:通過寄存器來
    的頭像 發表于 11-12 10:46 ?336次閱讀
    <b class='flag-5'>FIFO</b> Generator的Xilinx官方手冊

    Verilog HDL的基礎知識

    本文繼續介紹Verilog HDL基礎知識,重點介紹賦值語句、阻塞與非阻塞、循環語句、同步與異步、函數與任務語法知識。
    的頭像 發表于 10-24 15:00 ?339次閱讀
    <b class='flag-5'>Verilog</b> HDL的基礎知識

    分享一個嵌入式通用FIFO環形緩沖區實現

    開源項目ringbuff ,是一款通用FIFO環形緩沖區實現的開源庫,作者MaJerle,遵循 MIT 開源許可協議。
    的頭像 發表于 10-23 16:20 ?373次閱讀
    分享一個嵌入式通用<b class='flag-5'>FIFO</b>環形緩沖區<b class='flag-5'>實現</b>庫

    如何使用FX3同步從屬fifo模式通過FPGA傳輸傳感器數據?

    我們正試圖使用 FX3 同步從屬 fifo 模式通過 FPGA 傳輸傳感器數據。 USB type-C 接口需要選擇一個多路復用器來決定使用哪一邊的 USB。 因此,我們考慮使用 FX3 GPIO
    發表于 07-17 08:04

    使用FX3同步fifo兩地址線能夠配置成四線程模式嗎?

    使用FX3同步fifo兩地址線能夠配置成四線程模式嗎,也就是兩個端點輸出,兩個端點輸入,麻煩大佬回復一下!?
    發表于 07-02 07:45

    如何配置CYUSB3014固件,實現五根地址線同步fifo數據傳輸,同時配制出多個端點?

    如何配置CYUSB3014固件,實現五根地址線同步fifo數據傳輸,同時配制出多個端點
    發表于 06-21 09:23

    同步FIFO和異步FIFO區別介紹

    1. FIFO簡介 FIFO是一種先進先出數據緩存器,它與普通存儲器的區別是沒有外部讀寫地址線,使用起來非常簡單,缺點是只能順序讀寫,而不能隨機讀寫。 2. 使用場景 數據緩沖:也就是數據寫入過快
    的頭像 發表于 06-04 14:27 ?1564次閱讀
    <b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>和異步<b class='flag-5'>FIFO</b>區別介紹

    FPGA能否正確接收來自FX3同步從站FIFO的數據?

    低電平,則不對數據總線進行采樣。 6. t6 時,FPGA 用新地址更新地址總線,依此類推; 在此過程之后,FPGA 能否正確接收來自 FX3 同步從站 FIFO 的數據? 非常感謝!
    發表于 05-31 08:09

    關于FX3同步Slave FIFO非突發傳輸的疑問求解

    在FX3同步Slave FIFO的非突發傳輸中,FPGA在將SLRD拉低后,等兩個時鐘周期,然后采樣數據總線,采樣數據總線前要判斷對應地址的FLAG是否為高,只有為高才采樣數據總線,請問是這樣
    發表于 05-31 06:28

    求助,求大神幫忙解答下AN65974同步Slave FIFO的讀時序

    你好,在AN65974文檔中,我看不懂同步Slave FIFO的讀時序,你可以給我解讀一下么? 下圖中有我標注的我不懂的問題。非常感謝你!......
    發表于 05-31 06:27

    關于同步FIFO和異步FIFO的基礎知識總結

    FIFO是一種先進先出數據緩存器,它與普通存儲器的區別是沒有外部讀寫地址線,使用起來非常簡單,缺點是只能順序讀寫,而不能隨機讀寫。
    的頭像 發表于 04-09 14:23 ?3220次閱讀
    關于<b class='flag-5'>同步</b><b class='flag-5'>FIFO</b>和異步<b class='flag-5'>FIFO</b>的基礎知識總結

    verilog同步和異步的區別 verilog阻塞賦值和非阻塞賦值的區別

    Verilog是一種硬件描述語言,用于設計和模擬數字電路。在Verilog中,同步和異步是用來描述數據傳輸和信號處理的兩種不同方式,而阻塞賦值和非阻塞賦值是兩種不同的賦值方式。本文將詳細解釋
    的頭像 發表于 02-22 15:33 ?1675次閱讀
    主站蜘蛛池模板: 一本色道久久综合亚洲精品蜜桃冫| 男人私gay挠脚心vk视频| 国产一区二区青青精品久久| 国产精品久久久久永久免费看| 国产Av男人的天堂精品良久| 国产精品亚洲污污网站入口 | 我就去色色| 亚洲 欧美 国产 伦 综合| 亚洲精品久久无码AV片WWW| 亚洲精品永久免费| 总裁呻吟双腿大开男男H| FREE另类老女人| 国产人妻麻豆蜜桃色| 久久超碰色中文字幕| 日本六九视频| 亚洲日韩一区精品射精| 99久久国产露脸精品竹菊传煤| 成人无码精品一区二区在线观看| 国产亚洲日韩在线播放不卡| 葵司中文第一次大战黑人| 色偷偷男人的天堂a v| 野花日本完整版在线观看免费高清| 97视频免费观看| 国产亚洲福利精品一区| 嫩小幼处在线| 亚洲精品美女久久777777| 扒开腿狂躁女人GIF动态图| 狠狠啪 日日啪| 亲胸揉胸膜下刺激视频在线观看| 亚洲七七久久桃花综合| wwwwwwwww日本电影| 久久黄视频| 让人爽到湿的小黄书| 亚洲国产在线综合018| 国产69精品久久久久妇女 | 国产精品96久久久久久AV不卡| 美国色吧影院| 亚洲一区精品在线| 国产色偷偷男人的天堂| 色橹| 成人免费一区二区无码视频 |