fifoverilog詳解

一、fifoverilog代碼

module fifoverilog (
    input clock,
    input reset,
    input write,
    input read,
    input [7:0] data_in,
    output [7:0] data_out,
    output empty,
    output full
);

reg [7:0] fifo_memory [255:0];
reg [7:0] read_ptr = 0;
reg [7:0] write_ptr = 0;
wire [7:0] next_write_ptr = write_ptr + 1'b1;
wire [7:0] next_read_ptr = read_ptr + 1'b1;
wire [7:0] fifo_count = write_ptr - read_ptr;
assign empty = (fifo_count == 8'h00) ? 1'b1 : 1'b0;
assign full = (fifo_count == 8'hFF) ? 1'b1 : 1'b0;
assign data_out = fifo_memory[read_ptr];
always @(posedge clock) begin
    if (reset) begin
        read_ptr <= 8'h00;
        write_ptr <= 8'h00;
    end else begin
        if (write && !full) begin
            fifo_memory[write_ptr] <= data_in;
            write_ptr <= next_write_ptr;
        end
        if (read && !empty) begin
            read_ptr <= next_read_ptr;
        end
    end
end

endmodule

上面是fifoverilog的模塊代碼,它實現了一種”先進先出”的數據存儲方式,主要實現一種隊列的數據結構。它具有以下幾個基本功能:

1.數據寫入FIFO

2.數據讀取FIFO

3.判斷FIFO是否已滿

4.判斷FIFO是否為空

5.重置FIFO

fifoverilog的原理很簡單:它內部維護一個存儲器,當用戶向FIFO輸入數據時,FIFO將這些數據存儲在內部的存儲器中。然後,當用戶需要讀取這些數據時,FIFO將保存在存儲器中的數據返回給用戶。FIFO嚴格按照先進先出的順序讀取和返回數據。

二、同步FIFO Verilog

在fifoverilog中,數據可以同步寫入和同步讀取。當同步時,要麼一次寫入一個數據,要麼一次讀取一個數據。

module sync_fifo_verilog(clk, reset, data_in, data_out, wr_en, rd_en, full, empty);

input clk, reset, wr_en, rd_en;
input [7:0] data_in;
output [7:0] data_out;
output full, empty;

// synchronous FIFO parameters 
localparam WIDTH = 8; 
localparam DEPTH = 256; // 2^8 x WIDTH 
localparam ADDR_W = 8; // log2(DEPTH) 

reg [WIDTH-1:0] memory [DEPTH-1:0];
reg [ADDR_W-1:0] wr_ptr, rd_ptr; 
wire [ADDR_W-1:0] next_wr_ptr, next_rd_ptr; 
wire full_n, empty_n; 

assign full = ~full_n;
assign empty = ~empty_n;
assign data_out = memory[rd_ptr];

always @(posedge clk) begin
    if (reset) begin
        wr_ptr <= 0;
        rd_ptr <= 0;
    end else begin
        if (wr_en && ~full_n) begin
            memory[wr_ptr] <= data_in;
            wr_ptr <= next_wr_ptr;
        end
        if (rd_en && ~empty_n) begin
            rd_ptr <= next_rd_ptr;
        end
    end
end

// next write/read ptr calculation 
assign next_wr_ptr = {wr_ptr[WIDTH-2:0], ~(&wr_ptr[WIDTH-1:0] & wr_en)};
assign next_rd_ptr = {rd_ptr[WIDTH-2:0], ~(&rd_ptr[WIDTH-1:0] & rd_en)};

// next empty/full calculation 
assign full_n = (next_wr_ptr == rd_ptr); 
assign empty_n = (wr_ptr == next_rd_ptr);

endmodule

在以上示例代碼中,存儲器的維度為256,大小為8位。這意味著FIFO可以存儲256個8位位元組。然後,我們使用「wr_en」和「rd_en」兩個輸入來存儲「寫使能」和「讀使能」。這些輸入用於同步地向FIFO輸入和輸出數據。FIFO內部維護兩個指針:wr_ptr和rd_ptr,它們會使用「next_wr_ptr」和「next_rd_ptr」計算下一次的位置。

三、Verilog同步非同步選取

在FPGA設計中,與FIFO有關的一項基本決策是使用同步還是非同步FIFO。

同步FIFO使用時鐘和同步複位信號,它適合於處理高速數據流,並且可以避免ASIC / FPGA設計中的時序問題。

非同步FIFO則適用於處理低速數據流,該FIFO不使用時鐘或重置信號,而使用信號使FIFO保持同步。像同步FIFO一樣,非同步FIFO可以減少在ASIC / FPGA設計中的時序問題。

// Asynchronous read FIFO
module async_read(clk, data_in, empty, data_out, rd_en);

input clk; 
input [7:0] data_in; 
output empty; 
output [7:0] data_out; 
input rd_en; 

// FIFO parameters 
localparam WIDTH = 8; 
localparam DEPTH = 256; // 2^8 x WIDTH  
localparam ADDR_W = 8; // log2(DEPTH) 

reg [WIDTH-1:0] memory [DEPTH-1:0];
reg [ADDR_W-1:0] wr_ptr, rd_ptr;
wire [ADDR_W-1:0] next_rd_ptr; 
wire empty_n; 

assign empty = ~empty_n;
assign data_out = memory[rd_ptr];

assign next_rd_ptr = rd_ptr + 1'b1;
assign empty_n = (wr_ptr == rd_ptr);

always @(posedge clk) begin
    if (rd_en && ~empty_n) begin
        rd_ptr <= next_rd_ptr; 
    end
end 

always @(posedge clk) begin 
    memory[wr_ptr] <= data_in; 
    wr_ptr <= wr_ptr + 1'b1;
end

endmodule

非同步FIFO與同步FIFO不同的是,它使用一個唯一的讀指針。在上面的代碼中,當輸入「rd_en」為有效時,讀指針會增加一個。然後,在「always」塊中,數據將被寫入內部存儲器。由於非同步FIFO只有一個讀指針,並且沒有時鐘或複位信號,所以當讀寫指針相同時,表示FIFO為空。

原創文章,作者:WTDR,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/134915.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
WTDR的頭像WTDR
上一篇 2024-10-04 00:09
下一篇 2024-10-04 00:09

相關推薦

  • 神經網路代碼詳解

    神經網路作為一種人工智慧技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網路的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網路模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變數讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性感測器,能夠同時測量加速度和角速度。它由三個感測器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分散式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25
  • C語言貪吃蛇詳解

    一、數據結構和演算法 C語言貪吃蛇主要運用了以下數據結構和演算法: 1. 鏈表 typedef struct body { int x; int y; struct body *nex…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web伺服器。nginx是一個高性能的反向代理web伺服器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25

發表回復

登錄後才能評論