sync_fifo.v
module sync_fifo #
(
DATA_WIDTH = 8,
DATA_DEPTH = 128
)
(
input wire i_sys_clk ,
input wire i_sys_rst_n ,
input wire i_wren ,
input wire [DATA_WIDTH-1:0] i_wdata ,
input wire i_rden ,
output wire [DATA_WIDTH-1:0] o_rdata ,
output wire o_full ,
output wire o_empty
);
reg [DATA_WIDTH-1:0] mem_ram [0:DATA_DEPTH-1];
reg [clogb2(DATA_DEPTH-1)-1:0] r_wr_ptr;
reg [clogb2(DATA_DEPTH-1)-1:0] r_rd_ptr;
reg [clogb2(DATA_DEPTH-1) :0] r_fifo_number;
//r_wr_ptr
always @(posedge i_sys_clk or negedge i_sys_rst_n)
begin
if(!i_sys_rst_n)
r_wr_ptr <= 0;
else if(i_wren && !o_full)
r_wr_ptr <= r_wr_ptr + 1;
else
r_wr_ptr <= r_wr_ptr;
end
//r_rd_ptr
always @(posedge i_sys_clk or negedge i_sys_rst_n)
begin
if(!i_sys_rst_n)
r_rd_ptr <= 0;
else if(i_rden && !o_empty)
r_rd_ptr <= r_rd_ptr + 1;
else
r_rd_ptr <= r_rd_ptr;
end
//write data
integer i;
always @(posedge i_sys_clk or negedge i_sys_rst_n)
begin
if(!i_sys_rst_n)
begin
for(i = 0; i < DATA_DEPTH; i = i + 1)
mem_ram[i] <= 0;
end
else if(i_wren && !o_full)
mem_ram[r_wr_ptr] <= i_wdata;
end
//read data
reg [DATA_WIDTH-1:0] r_rdata;
always @(posedge i_sys_clk or negedge i_sys_rst_n)
begin
if(!i_sys_rst_n)
r_rdata <= 0;
else if(i_rden && !o_empty)
r_rdata <= mem_ram[r_rd_ptr];
end
//r_fifo_number
always @(posedge i_sys_clk or negedge i_sys_rst_n)
begin
if(!i_sys_rst_n)
r_fifo_number <= 0;
else if(i_wren && !o_full && i_rden && !o_empty)
r_fifo_number <= r_fifo_number;
else if(i_wren && !o_full && !i_rden)
r_fifo_number <= r_fifo_number + 1;
else if(i_rden && !o_empty && !i_wren)
r_fifo_number <= r_fifo_number - 1;
else
r_fifo_number <= r_fifo_number;
end
assign o_rdata = r_rdata;
assign o_full = (r_fifo_number == DATA_DEPTH);
assign o_empty = (r_fifo_number == 0);
function integer clogb2(input number);
for(clogb2 = 0; number > 0; clogb2 = clogb2 +1)
number = number >> 1;
endfunction
endmodule
tb_sync_fifo.v
`timescale 1ns/1ps
`define CLK_PERILOD 20
module tb_sync_fifo;
parameter DATA_WIDTH = 8;
parameter DATA_DEPTH = 128;
reg clk;
reg rst_n;
reg wren;
reg rden;
wire [DATA_WIDTH-1:0] rdata;
reg [DATA_WIDTH-1:0] wdata;
wire full;
wire empty;
sync_fifo u_synv_fifo(
.i_sys_clk(clk) ,
.i_sys_rst_n(rst_n),
.i_wren(wren) ,
.i_rden(rden) ,
.i_wdata(wdata) ,
.o_rdata(rdata) ,
.o_full(full) ,
.o_empty(empty)
);
initial begin
clk = 0;
forever
#(`CLK_PERILOD/2) clk = ~clk;
end
initial begin
rst_n = 0;
repeat(20) @(posedge clk);
rst_n = 1;
end
initial begin
wren = 0;
wdata = 0;
repeat(30) @(posedge clk);
wren = 1;
repeat(300) @(posedge clk) wdata = wdata + 1;
$stop;
end
initial begin
rden = 0;
repeat(130) @(posedge clk);
rden = 1;
end
initial begin
$fsdbDumpfile("sync_fifo.fsdb");
$fsdbDumpvars(0);
end
endmodule
具体代码可以参考代码仓 sync_fifo