// *********** 同步FIFO ***********
// ****** 描述:默认先写后读 *******
// ******* 日期:2022.08 **********
// 利用辅助计数器,计数器到达最大深度即为满,到达0即为空
// 当写使能,非满,计时器值非最大深度,计数器值加一
// 当读使能,非空,计数器值非最小深度(0),计数器值减一
module sfifo
//========================< 参数 >==========================================
#(
parameter DATA_W = 8 , //数据位宽
parameter DEPTH = 16 //深度
)
//========================< 端口 >==========================================
(
input clk, //时钟信号
input rst_n, //复位信号
input wr_en, //写使能信号
input [DATA_W-1:0] wr_data, //写数据
input rd_en, //读使能信号
output [DATA_W-1:0] rd_data, //读数据
output full, //满信号
output empty, //空信号
);
//========================< 信号 >==========================================
parameter ADDR_w = 4; //地址位宽
reg [ADDR_w-1:0] wr_addr; //写地址
reg [ADDR_w-1:0] rd_addr; //读地址
reg [DATA_W-1:0] ram [DEPTH-1: 0] //ram位宽8位,共16个
reg [ADDR_w:0] cnt //辅助计数器
//==========================================================================
//===== 读写地址
//==========================================================================
//----- 写地址
//--------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
wr_addr <= 0;
end
else if(wr_en) begin
wr_addr <= wr_addr + 1;
end
end
//----- 读地址
//--------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
rd_addr <= 0;
end
else if(rd_en) begin
rd_addr <= rd_addr + 1;
end
end
//==========================================================================
//===== 读写数据
//==========================================================================
//----- 写数据
//--------------------------------------------------------------------------
integer i;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
for(i=0;i<DEPTH;i=i+1)
ram[i] <= 0;
end
else if(wr_en) begin
ram[wr_addr] <= wr_data;
end
end
//----- 读数据
//--------------------------------------------------------------------------
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rd_data <= 0;
else if(rd_en)
rd_data <= ram[rd_addr];
end
//==========================================================================
//===== 空满标志
//==========================================================================
//----- 辅助计数器
//--------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 0;
else if(wr_en && !full && cnt!=16)
cnt <= cnt + 1;
else if(rd_en && !empty && cnt!=0)
cnt <= cnt - 1;
else
cnt <= cnt;
end
//----- 空满信号
//--------------------------------------------------------------------------
assign full = (cnt==16);
assign empty = (cnt==0);
endmodule
版权声明:本文为weixin_51613968原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。