一、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-hant/n/134915.html
微信掃一掃
支付寶掃一掃