module S_FIFO #(
parameter FIFO_Depth = 16,
parameter Depth_width = $clog2(FIFO_Depth),
parameter FIFO_Width = 8-1
)(
input wire Sys_clk,
input wire Rst_n ,
input wire wr_en ,
input wire [FIFO_Width:0] wr_data,
input wire rd_en ,
output wire [FIFO_Width:0] rd_data,
output wire FIFO_EMPTY,
output wire FIFO_FULL
);
reg [FIFO_Width:0] r_rd_data ;
reg [Depth_width:0] wr_addr_cnt ;
reg [Depth_width:0] rd_addr_cnt ;
reg [FIFO_Width :0] Memory [FIFO_Depth-1:0];
reg [Depth_width:0] VS_CNT ;
assign rd_data = r_rd_data ;
assign FIFO_EMPTY = (VS_CNT == 'd0 )?1'b1:1'b0;
assign FIFO_FULL = (VS_CNT == FIFO_Depth-1)?1'b1:1'b0 ;
always @(posedge Sys_clk) begin
if(!Rst_n) begin
wr_addr_cnt <= 'd0;
end else if(wr_en == 1'b1 && FIFO_FULL != 1'b1) begin
wr_addr_cnt <= wr_addr_cnt + 1'b1;
end else begin
wr_addr_cnt <= wr_addr_cnt;
end
end
always @(posedge Sys_clk) begin
if(!Rst_n) begin
rd_addr_cnt <= 'd0;
end else if(rd_en == 1'b1 && FIFO_EMPTY != 1'b1) begin
rd_addr_cnt <= rd_addr_cnt + 1'b1;
end else begin
rd_addr_cnt <= rd_addr_cnt;
end
end
always@(posedge Sys_clk) begin
if(wr_en == 1'd1 && FIFO_FULL != 1'd1) begin
Memory[wr_addr_cnt] <= wr_data;
end
end
always@(posedge Sys_clk) begin
if(rd_en == 1'd1 && FIFO_EMPTY != 1'd1) begin
r_rd_data <= Memory[rd_addr_cnt];
end
end
always @(posedge Sys_clk or negedge Rst_n) begin
if(!Rst_n) begin
VS_CNT <= 'd0;
end else if(wr_en||rd_en) begin
if(wr_en == 1'b1 && VS_CNT != FIFO_Depth-1) begin
VS_CNT <= VS_CNT + 1'b1;
end else if(rd_en == 1'b1 && VS_CNT != 'd0) begin
VS_CNT <= VS_CNT - 1'b1;
end else begin
VS_CNT <= VS_CNT;
end
end else begin
VS_CNT <= VS_CNT;
end
end
endmodule
`timescale 1ns / 1ps
module tb_S_FIFO;
// S_FIFO Parameters
parameter PERIOD = 20 ;
parameter FIFO_Depth = 16 ;
parameter Depth_width = $clog2(FIFO_Depth);
parameter FIFO_Width = 8-1 ;
// S_FIFO Inputs
reg Sys_clk ;
reg Rst_n ;
reg wr_en ;
reg [FIFO_Width:0] wr_data ;
reg rd_en ;
// S_FIFO Outputs
wire [FIFO_Width:0] rd_data ;
wire FIFO_EMPTY ;
wire FIFO_FULL ;
initial begin
Sys_clk = 0;
end
always #(PERIOD/2) Sys_clk = ~ Sys_clk;
initial
begin
Rst_n <= 0;
wr_en <= 0;
wr_data <= 0;
rd_en <= 0;
repeat (10) @(posedge Sys_clk);
Rst_n <= 1'b1;
repeat (10) @(posedge Sys_clk);
write_fifo();
repeat (10) @(posedge Sys_clk);
read_fifo();
repeat (100) @(posedge Sys_clk);
$stop;
end
S_FIFO #(
.FIFO_Depth ( FIFO_Depth ),
.Depth_width ( Depth_width ),
.FIFO_Width ( FIFO_Width ))
u_S_FIFO (
.Sys_clk ( Sys_clk ),
.Rst_n ( Rst_n ),
.wr_en ( wr_en ),
.wr_data ( wr_data ),
.rd_en ( rd_en ),
.rd_data ( rd_data ),
.FIFO_EMPTY ( FIFO_EMPTY),
.FIFO_FULL ( FIFO_FULL )
);
task write_fifo();
integer i;
begin
for ( i = 0 ; i < 18;i = i + 1 ) begin
wr_en <= 1'b1;
wr_data <= wr_data + 1'b1;
@(posedge Sys_clk);
wr_en <= 1'b0;
end
end
endtask
task read_fifo();
integer i;
begin
for ( i = 0 ; i < 18;i = i + 1 ) begin
rd_en <= 1'b1;
@(posedge Sys_clk);
rd_en <= 1'b0;
end
end
endtask
endmodule