Verilog FIFO code written with different styles..one not working and another not working.Can someone explain

mjaju picture mjaju · Jun 23, 2014 · Viewed 7.8k times · Source

I have written verilog code for fifo using fillcount to check as the means for checking if it is full or empty. There are 2 versions of the same code. One is whereI have a seprate always always block for reading,writing,empty /full ,fillcount,and one for incrementing the pointers.This works fine,I have tested it and it works fine.

module FIFO (clk, reset, data_in, put, get, data_out, fillcount, empty, full); 
parameter DEPTHP2 = 8 ;
parameter WIDTH = 8 ;
input [WIDTH-1:0] data_in;
input put, get, reset, clk; 
output fillcount;
output reg [WIDTH-1:0] data_out;
output reg empty, full; 




reg [3:0]fillcount ;
reg [WIDTH-1:0] fifo_1[0:DEPTHP2-1];
reg [2:0] rp,wp;


always@(posedge clk or posedge reset)
begin
   if( reset )
   begin
      wp <= 0;
      rp <= 0;
   end
   else
   begin
      if( !full && put )    wp <= wp + 1;
          else  wp <= wp;

      if( !empty && get )   rp <= rp + 1;
      else rp <= rp;
   end

end

always @(fillcount)
begin
if(fillcount==0)
  empty =1 ;
  else
  empty=0;

  if(fillcount==8)
   full=1;
   else
   full=0;
end

always @(posedge clk or posedge reset)
begin
   if( reset )
       fillcount <= 0;

   else if( (!full && put) && ( !empty && get ) )
       fillcount <= fillcount;

   else if( !full && put )
       fillcount <= fillcount + 1;

   else if( !empty && get )
       fillcount <= fillcount - 1;
   else
      fillcount <= fillcount;
end

always @( posedge clk or posedge reset)
begin:Reading
   if( reset )
      data_out <= 0;
   else
   begin
      if( get && !empty )
         data_out <= fifo_1[rp];

      else
         data_out <= data_out;

   end
end

always @(posedge clk)
begin:Writing

   if( put && !full )
      fifo_1[ wp ] <= data_in;

   else
      fifo_1[ wp ] <= fifo_1[ wp ];
end

endmodule

Another way is where I had combined the few always blocks together which effectng the logic(in my understanding!!)But it does not work for case when I try to read the data after writing immediately.It passes all other test cases.

I am not sure what went wrong.. It would be great if someone could point where I am going wrong.

//The code that is not working

always@(posedge clk or posedge reset)
begin:Writing
         if(reset)
        wp<=0;
        else 
        if( put && !full)
        begin
            fifo1[wp]<=data_in;
            wp<=wp+1;
        end
        else
        begin
            fifo1[wp]<=fifo1[wp];
            wp<=wp;
        end
end


always@(posedge clk or posedge reset)
begin:Reading
    if(reset)
    begin
        rp<=0;
        data_out<=0;
    end
        else
    if(get && !empty)
    begin
        data_out<=fifo1[rp];
        rp<=rp+1;
    end 
    else
    begin
        fifo1[rp]<=fifo1[rp];
        rp<=rp;
    end
end

always@(posedge clk or posedge reset)
begin:Fillcount
    if(reset)
        fillcount<=0;
        else
    if((!full && put ) && ( !empty && get))
        fillcount<=fillcount;
    else if(!full && put)
        fillcount<=fillcount+1;
    else if(!empty && get)
        fillcount<=fillcount-1;
    else
        fillcount<=fillcount;

end

always@(fillcount)
begin
    full=(fillcount==8);
    empty=(fillcount==0);
end

endmodule

Another question : The general way of coding in verilog as far as I have learned is to use fsm to draw the state diagram and use them..But I had a hard time when I try to code for the memory element like fifo,Tcam or double clock fifo. Is there any approach or a way to do coding for these elements .

Sorry for the long question

Answer

Ciano picture Ciano · Jun 23, 2014

In your "Reading" process your are inadvertantly writing to your fifo memory:

fifo1[rp]<=fifo1[rp];

If you get rid of that it looks like things should work okay.

As a side note, in a sequential process you don't need to explicitly set values that aren't changing.

For example, if you take this process of yours:

always@(posedge clk or posedge reset)
begin:Writing
  if(reset)
    wp<=0;
  else 
    if( put && !full)
    begin
        fifo1[wp]<=data_in;
        wp<=wp+1;
    end
    else
    begin
        fifo1[wp]<=fifo1[wp];
        wp<=wp;
    end
end

you can rewrite it as:

always@(posedge clk or posedge reset)
begin:Writing
  if(reset)
    wp<=0;
  else 
    if( put && !full)
    begin
        fifo1[wp]<=data_in;
        wp<=wp+1;
    end
end

and you will get the exact same behavior in sim and the same hardware when you synthesize. You are implying registers in your code and they will maintain their state unless explicitly changed.