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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
`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 *