Sync FIFO介绍及实现
- 1 Intro
- 2 Achieve
- 2.1 DFD
- 2.2 Intf
- 2.3 Module
本篇博客介绍无论是编码过程中经常用到的逻辑–FIFO;该FIFO是基于单时钟下的同步FIFO;
FiFO分类:同步FiFO VS 异步FiFO;
1 Intro
FIFO可以自己实现,但是因为FiFO太常用,为了减少造轮子和出错率,基本上每个公司都有自己的CBB库,直接调用即可;
个人认为,自己作为入门者,学习尤其亲自实践造轮子,对自己的技能提升很有帮助;
FiFO是first in first out的数据行为;相比SRAM来说可能是少了灵活性,但是在设计逻辑上却是最经常用到FIFO的行为逻辑;
FIFO基于sram上wrapper控制逻辑的module;
2 Achieve
三种基本读写场景:
- push && !pop
- psh && pop
- pop && !push
2.1 DFD
通过wr_ptr和rd_ptr来进行以动array的index;
!](https://img-blog.csdnimg.cn/direct/83dce5833ef1442aa970a44eec2e2af2.png)
2.2 Intf
下图是Sync_fifo的上下游接口框图;
2.3 Module
以下为伪代码实现,还未经过语法编译和功能验证,供大家思路参考
//--Auther :colonel
//--Date :2024-05-23
//--Function:sync_fifo meet
//--History :Description
//--05/22 :Firstly create the file
//
module sync_fifo#(
parameter DEPTH = 4,
parameter WIDTH = 8,
parameter PTR_WIDTH = 2
)(
input clk,
input rst_n,
input push,
input wire[WIDTH -1:0] data_in,
output full,
input pop,
output empty,
output reg[WIDTH -1:0] data_out
);
reg[WIDTH -1:0][DEPTH -1:0] fifo; //sync_fifo based on the register
reg[PTR_WIDTH -1:0] cnt;
reg[DEPTH -1:0] wr_ptr;
reg[DEPTH -1:0] rd_ptr;
//--waddr
always@(posedge clk or negedge rst_n) begin:waddr_logic
if(!rst_n) begin
wr_ptr <= 0;
end else begin
if(push && ! full) begin
wr_ptr <= wr_ptr + 1;
end else begin
wr_ptr <= wr_ptr;
end
end
end
//--raddr
always@(posedge clk or negedge rst_n) begin:raddr_logic
if(!rst_n) begin
rd_ptr <= 0;
end else begin
if(pop && !empty ) begin
rd_ptr <= rd_ptr + 1;
end else begin
rd_ptr <= rd_ptr;
end
end
end
//--wdata
integer i;
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
for(i=0;i<DEPTH;i=i+1) begin
fifo[i] <= 0;
end
end else begin
if(push) begin
fifo[wr_ptr] <= data_in;
end else begin
fifo[wr_ptr] <= fifo[wr_ptr];
end
end
end
//--rdata
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
data_out <= 0;
end else begin
if(pop) begin
data_out <= fifo[rd_ptr];
end else begin
data_out <= data_out;
end
end
end
//--cnt logic
always@(posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt <= 0;
end else begin
if(push && !pop && !full) begin
cnt <= cnt + 1;
end else if(!push && pop && !empty) begin
cnt <= cnt - 1;
end else begin
cnt <= cnt;
end
end
end
//full && empty logic
assign empty = (cnt==0) ? 1:0;
assign full = (cnt==DEPTH) ? 1:0;
endmodule
【Reference】
[1] https://blog.csdn.net/zyp626/article/details/131620099