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
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.