一、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