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        

Loading

FIFO

2 thoughts on “FIFO

Leave a Reply

Your email address will not be published. Required fields are marked *