Synchronous FIFO
In Verilog, you can implement a FIFO data structure using a combination of registers and logic gates. Here’s an example of how you can implement a simple FIFO module in Verilog:
RTL
module sync_fifo(clk,rst,wr_valid,rd_valid,wdata,rdata,full,empty,wr_error,rd_error);
parameter WIDTH = 8 ;
parameter DEPTH = 16 ;
parameter PTR_WIDTH = $clog2(DEPTH) ;
//-----------input-------------------
input clk,rst,wr_valid,rd_valid;
input [WIDTH-1:0] wdata ;
//-----------output------------------
output reg [WIDTH-1:0] rdata ;
output reg full,empty;
output reg wr_error,rd_error ;
//---------------register-------------
reg [PTR_WIDTH:0] wr_ptr_reg,rd_ptr_reg ; //5 bit--> 0-3 bits i am using as toggle bit.
reg [WIDTH-1:0] mem[DEPTH-1:0] ;
integer i ;
//---------------define---------------
`define wr_tgl_f wr_ptr_reg[PTR_WIDTH] //last bit use as toggle bit.
`define wr_ptr wr_ptr_reg[PTR_WIDTH-1:0] //0-3-->4 bit use as ptr.
`define rd_ptr rd_ptr_reg[PTR_WIDTH-1:0]//0-3-->4 bit use as ptr.
`define rd_tgl_f rd_ptr_reg [PTR_WIDTH] //last bit use as toggle bit.
//------read-write_error---------------
always@(*) begin
wr_error= full & wr_valid;
rd_error = empty & rd_valid;
end
//-------------write_block------------
always @(posedge clk) begin
if(rst) begin
full <= 0 ;
wr_ptr_reg <= 0 ;
for(i = 0 ; i < DEPTH ; i = i+1)
mem[i] <= 0 ;
end
else if(wr_valid & !full) begin
mem[`wr_ptr] <= wdata ;
wr_ptr_reg <= wr_ptr_reg + 1 ;
end
else begin
mem[`wr_ptr] <= mem[`wr_ptr] ;
wr_ptr_reg <= wr_ptr_reg ;
end
end
//-----------read_block-------------
always @(posedge clk) begin
if(rst) begin
rdata <= 0 ;
empty <= 1 ;
rd_ptr_reg <= 0 ;
for(i = 0 ; i < DEPTH ; i = i+1)
mem[i] <= 0 ;
end
else if(rd_valid&!empty) begin
rdata <= mem[`rd_ptr] ;
rd_ptr_reg <= rd_ptr_reg + 1 ;
end
else begin
rdata <= rdata;
rd_ptr_reg <= rd_ptr_reg ;
end
end
//-------full_&_empty_check---------
always @(*) begin
full= (rd_ptr_reg=={~`wr_tgl_f,`wr_ptr}) ?1'b1:1'b0;
empty=(rd_ptr_reg==wr_ptr_reg) ?1'b1:1'b0;
end
endmodule
TESTBENCH
`include "sync_fifo.v"
module tb ;
parameter WIDTH = 8 ;
parameter DEPTH = 16 ;
parameter PTR_WIDTH = $clog2(DEPTH) ;
reg clk,rst,wr_valid,rd_valid;
reg [WIDTH-1:0] wdata ;
wire [WIDTH-1:0] rdata ;
wire full,empty,wr_error,rd_error ;
integer i,j;
reg [70*8:1]testname;
//instantiation of design in tb with parameter overriding
sync_fifo #(.DEPTH(DEPTH),.WIDTH(WIDTH),.PTR_WIDTH(PTR_WIDTH)) dut(
clk,rst,wr_valid,rd_valid,wdata,rdata,full,empty,wr_error,rd_error
);
//clk generation
initial begin
clk = 0 ;
forever #5 clk = ~clk ;
end
//task for write
task wr_fifo(input [PTR_WIDTH:0] num_loc);
begin
for(i = 0 ; i < num_loc ; i = i+1) begin
@(posedge clk) ;
wr_valid = 1 ;
wdata = $random ;
end
@(posedge clk) ;
wr_valid = 0 ;
wdata = 0 ;
end
endtask
//task for read
task rd_fifo(input [PTR_WIDTH:0] num_loc);
begin
for(j = 0 ; j < num_loc ; j = j+1) begin
@(posedge clk) ;
rd_valid = 1 ;
end
@(posedge clk) ;
rd_valid = 0 ;
end
endtask
//task for reset all inputs
task reset_inputs();
begin
wr_valid = 0 ;
rd_valid = 0 ;
wdata = 0 ;
end
endtask
initial begin
$value$plusargs("testname=%s",testname);
rst= 1 ;
i=0;
j=0;
reset_inputs();
@(posedge clk) ;
rst= 0 ;
case(testname)
"test_fifo_full" : begin
wr_fifo(DEPTH);
end
"test_fifo_empty" : begin
wr_fifo(DEPTH);
rd_fifo(DEPTH);
end
"test_fifo_full_error" : begin
wr_fifo(DEPTH+5);
rd_fifo(DEPTH+4);
end
"test_fifo_empty_error" : begin
wr_fifo(DEPTH);
rd_fifo(DEPTH+4);
end
"test_fifo_concurrent_wr_rd_no_delay" : begin
fork
wr_fifo(DEPTH);
rd_fifo(DEPTH);
join
end
endcase
#50
$finish ;
end
//waveform generation
/* initial begin
$dumpfile("dump.vcd");
$dumpvars(1,tb);
end*/
endmodule
FIFO
Nice post. I learn something new and challenging on websites I stumbleupon every day. It will always be useful to read through articles from other writers and use a little something from other websites.
Thankyou for your feedback !!