同步FIFO的设计

作者:Kevin Zhang

本篇文章整理一下同步FIFO的实现。首先介绍一下FIFO的基础知识:

fifo是 first input first output 的缩写,即先进先出队列,fifo一般用作不同时钟域的缓冲器。fifo根据读和写的时钟是否为同一时钟分为同步fifo和异步fifo。异步fifo相比同步fifo来说,设计更加复杂一点。本文中先讲同步fifo的一种设计方法。下图是同步fifo的结构图:

设计FIFO的时候一般需要考虑的有两点:

1.FIFO的大小

FIFO的大小指就是双端口ram的大小,这个可以根据设计需要来设置。

2.FIFO空满状态的判断

FIFO空满状态的判断通常有两种方法。

a、FIFO中的ram一般是双端口ram,所以有独立的读写地址。因此可以一种是设置读,写指针,写指针指向下一个要写入数据的地址,读指针指向下一个要读的地址,最后通过比较读指针和写指针的大小来确定空满状态。

b、设置一个计数器,当写使能有效的时候计数器加一;当读使能有效的时候,计数器减一,将计数器与ram的size进行比较来判断fifo的空满状态。这种方法设计比较简单,但是需要的额外的计数器,就会产生额外的资源,而且当fifo比较大时,会降低fifo最终可以达到的速度。

下面的设计是将fifo当做一个整体来进行设计,输入输出端口有基本的代码如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Design Name: Kevin Zhang
// Module Name: test_verify_mod
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module fifo#(
parameter FIFO_WIDTH = 32,
parameter FIFO_DEPTH = 16
)(
input clk_i,
input rst_n,

input wr_en,
input [FIFO_WIDTH-1:0] wr_data,
output fifo_full,
output reg[log2(FIFO_WIDTH)-1:0] fifo_count,

input rd_en,
output reg[FIFO_WIDTH-1:0] rd_data,
output fifo_empty
);
//FIFO当前深度
always @ (posedge clk_i) begin
if(!rst_n)
fifo_count <= 0;
else begin
case({wr_en,rd_en})
2'b00: fifo_count <= fifo_count;
2'b01: fifo_count <= fifo_count - 1;
2'b10: fifo_count <= fifo_count + 1;
2'b11: fifo_count <= fifo_count;
endcase
end
end
assign fifo_full = (fifo_count == FIFO_DEPTH -1) ? 1'b1 : 1'b0;
assign fifo_empty = (fifo_count == 0) ? 1'b1 : 1'b0;
//写指针
reg[log2(FIFO_WIDTH)-1:0] wr_prt;
always @(posedge clk_i) begin
if(!rst_n)
wr_prt <= 0;
else begin
if(wr_en)begin
ram[wr_prt] <= wr_data;
if(wr_prt == FIFO_DEPTH - 1)
wr_prt <= 0;
else
wr_prt <= wr_prt + 1;
end
end
end
//读指针
reg[log2(FIFO_WIDTH)-1:0] rd_prt;
always @(posedge clk_i) begin
if(!rst_n)
rd_prt <= 0;
else begin
if(rd_en)begin
rd_data <= ram[rd_prt];
if(rd_prt == FIFO_DEPTH - 1)
rd_prt <= 0;
else
rd_prt <= rd_prt + 1;
end
end
end
endmodule

文章转载自:https://zhuanlan.zhihu.com/p/41879038

最新文章

最新文章