Description:
FIFO is an acronym for First In, First Out, an abstraction in ways of organizing and manipulation of data relative to time and prioritization. This expression describes the principle of a queue processing technique or servicing conflicting demands by ordering process by first-come, first-served (FCFS) behavior: what comes in first is handled first, what comes in next waits until the first is finished.
mem[31]
mem[30]
…..
…..
…..
mem[1]
mem[0]
In hardware FIFO is used for synchronization purposes. It is often implemented as a circular queue, and thus has two pointers:
Read Pointer/Read Address Register
Write Pointer/Write Address Register
Read and write addresses are initially both at the first memory location and the FIFO queue is Empty.
FIFO Empty
When read address register reaches to write address register, the FIFO triggers the Empty signal.
FIFO Full
When write address register reaches to read address register, the FIFO triggers the FULL signal.
Types of Error Detection Required:
1. Read Error:
When the FIFO is empty and there is no data to read in data location and trying to access to read at such condition.
2. Write Error:
When the FIFO is full and there is no more empty memory location to write data to memory and when access to trying to write causes write error.
Simultaneous Read/Write:
Despite of Empty or Full whenever there is read and write request at the same time, there should not be error and hence operation should continue.
For my FIFO DESIGN
Input Configuration:
inp_write – when is high the write_data (input data) is stored into the memory
inp_read – when is high data stored in memory is sent to out read_data (output)
clk – is a continuous signal need essentially for synchronous circuit
[7:0] write_data – is a 8 bit word data, which is externally input to the memory storage when inp_write command is called.
a_reset – is asynchronous reset, which resets all the variables like pointers, empty, full conditions etc.
Output Configuration:
r_error – Shows there is error in reading as output
w_error – Shows there is error in writing as output
full – Shows that the FIFO is currently full
empty – Shows that the FIFO is currently empty
[7:0] read_data – When data is read from the FIFO, its output is shown as read_data
Intermediate Configuration:
w_cnt – It is normally 0 at reset and increases by one unit whenever 32 write are consequently completed starting from 0
r_cnt - It is normally 0 at reset and increases by one unit whenever 32 read are consequently completed starting from 0
Error Detection in my FIFO Design:
Error in my FIFO is always when write pointer(w_ptr) and read pointer(r_ptr) are equal.
Whenever w_cnt is equal to r_cnt there is the case of empty FIFO hence results into read error.
Whenever w_cnt is not equal to r_cnt there is the case of full FIFO hence results into write error.
This is because at initial phase i.e. starting the FIFO is empty w_cnt is equal to r_cnt and there can’t be read but can be written. There is possibility of simultaneous read/write. Similarly at any stage whenever there is this r_cnt=w_cnt and error then error will always be of read error. This will give r_error output.
Now, as the write operation comes into action the write pointer increases and as the write pointer reaches to the 31 and beyond now, w_cnt will no longer be equal to r_cnt (note above intermediate configuration) as a result if the two pointers are equal it will take as a full FIFO and hence write error(w_error). However, if on such case both the inputs enable i.e. input read and input write are requested at the same time, then results no error.
My FIFO Code:
`timescale 1ns / 10ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Home Alone
// Engineer: Krishna Neupane
//
// Create Date: 13:34:44 06/13/2011
// Design Name:
// Module Name: fifokrishna
// Project Name: CLASS PROJECT
// Target Devices: FIFO
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 4.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module krishna_fifo(inp_read,inp_write,r_error,w_error,full,empty,clk,read_data,write_data,a_reset);
input [7:0] write_data;
input inp_read,inp_write,clk,a_reset;
output reg [7:0] read_data;
output reg full,empty,r_error,w_error;
reg [7:0] mem[0:31];
reg [4:0] r_ptr;
reg [4:0] w_ptr;
reg r_cnt;
reg w_cnt;
// operation at clock and at asynchronous reset
always@(posedge clk or posedge a_reset) begin
// reset is given the top most priority
if (a_reset==1) begin
r_ptr=5'b00000;
w_ptr=5'b00000;
r_error<=0;
w_error<=0;
empty<=1;
full<=0;
r_cnt<=0;
w_cnt<=0;
end
else begin
// before we begin to write or read, we have to check for empty and full condition
if (w_ptr==r_ptr) begin
if (r_cnt==w_cnt) begin
empty<=1;
full<=0;
end
else begin
empty<=0;
full<=1;
end
end
else begin
full<=0;
empty<=0;
end
//reading opeartion
if ((inp_read==1)&(inp_write==0)) begin
r_error<=0;
w_error<=0;
if (empty==1) begin
r_error<=1;
w_error<=0;
end
else if (empty==0) begin
read_data<=mem[r_ptr];
w_error<=0;
r_error<=0;
if (r_ptr==31) begin
r_cnt<=r_cnt+1;
r_ptr= 0;
end
else
r_ptr=r_ptr+1;
end
end
//writing opearation
if ((inp_write==1)&(inp_read==0)) begin
r_error<=0;
w_error<=0;
if (full==1) begin
w_error<=1;
r_error<=0;
end
if (full==0) begin
mem[w_ptr]<=write_data;
r_error<=0;
w_error<=0;
if (w_ptr==31) begin
w_cnt<=w_cnt+1;
w_ptr=0;
end
else
w_ptr=w_ptr+1;
end
end
//simultaneous opearion requst
if ((inp_write==1)&(inp_read==1)) begin
if (full==1) begin
r_error<=0;
w_error<=0;
read_data<=mem[r_ptr];
#1;
mem[w_ptr]<=write_data;
if (r_ptr==31) begin
r_ptr=0;
r_cnt<=r_cnt+1;
end
if (r_ptr!=31)
r_ptr=r_ptr+1;
if (w_ptr==31) begin
w_ptr=0;
w_cnt<=w_cnt+1;
end
if (w_ptr!=31)
w_ptr=w_ptr+1;
end
if(empty==1) begin
r_error<=0;
w_error<=0;
mem[w_ptr]<=write_data;
#1;
read_data<=mem[r_ptr];
if (r_ptr==31) begin
r_ptr=0;
r_cnt<=r_cnt+1;
end
if (r_ptr!=31)
r_ptr=r_ptr+1;
if (w_ptr==31) begin
w_ptr=0;
w_cnt<=w_cnt+1;
end
if (w_ptr!=31)
w_ptr=w_ptr+1;
end
if ((full==0)&(empty==0)) begin
r_error<=0;
w_error<=0;
mem[w_ptr]<=write_data;
read_data<=mem[r_ptr];
if (r_ptr==31) begin
r_ptr=0;
r_cnt<=r_cnt+1;
end
if (r_ptr!=31)
r_ptr=r_ptr+1;
if (w_ptr==31) begin
w_ptr=0;
w_cnt<=w_cnt+1;
end
if (w_ptr!=31)
w_ptr=w_ptr+1;
end
end
// if no input for read and write on clock
if ((inp_read==0)&(inp_write==0)) begin
r_error<=0;
w_error<=0;
end
end
end
endmodule
Now referring to the RTL schematics obtained it has the following characteristics.
HDL Synthesis Report
-------------------------
Macro Statistics
# Adders/Subtractors : 10
1-bit adder : 2
5-bit adder : 8
# Registers : 39
1-bit register : 4
5-bit register : 2
8-bit register : 33
# Toggle Registers : 2
T flip-flop : 2
# Comparators : 1
5-bit comparator equal : 1
# Multiplexers : 4
8-bit 32-to-1 multiplexer : 4
# Xors : 1
1-bit xor2 : 1
Device utilization summary:
---------------------------
Selected Device : 3s50vq100-5
Number of Slices: 498 out of 768 64%
Number of Slice Flip Flops: 290 out of 1536 18%
Number of 4 input LUTs: 732 out of 1536 47%
Number of IOs: 24
Number of bonded IOBs: 24 out of 63 38%
Number of GCLKs: 1 out of 8 12%
Timing Summary:
---------------
Speed Grade: -5
Minimum period: 12.489ns (Maximum Frequency: 80.074MHz)
Minimum input arrival time before clock: 15.199ns
Maximum output required time after clock: 7.300ns
Maximum combinational path delay: No path found
My Test Bench Code:
`timescale 1ns / 10ps
////////////////////////////////////////////////////////////////////////////////
// Company: Home Alone
// Engineer: Krishna Neupane
//
// Create Date: 00:04:40 06/15/2011
// Design Name: krishna_fifo
// Module Name: E:/ku/fifokrishna3/fifo_test.v
// Project Name: fifokrishna3
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: krishna_fifo
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module fifo_test;
// Inputs
reg inp_read;
reg inp_write;
reg clk;
reg [7:0] write_data;
reg a_reset;
// Outputs
wire r_error;
wire w_error;
wire full;
wire empty;
wire [7:0] read_data;
// Instantiate the Unit Under Test (UUT)
krishna_fifo uut (
.inp_read(inp_read),
.inp_write(inp_write),
.r_error(r_error),
.w_error(w_error),
.full(full),
.empty(empty),
.clk(clk),
.read_data(read_data),
.write_data(write_data),
.a_reset(a_reset)
);
initial begin
// Initialize Inputs
inp_read = 0;
inp_write = 0;
clk = 0;
a_reset=0;
write_data=0;
forever clk=#1~clk;
end
initial begin
//first reset check
#1;
a_reset=1;
#6;
a_reset=0;
#2;
// initial check for read error when fifo is empty at start
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_read=0;
inp_write=0;
#2;
// should be no error while writing if whole fifo empty
write_data= 8'd23;
inp_write =1;
inp_read=0;
#2;
//checking for simultaneous inputs
inp_write=0;
inp_read=0;
#2;
write_data=8'b11111111;
inp_write=1;
inp_read=1;
#2
// data in binary format
inp_write=0;
inp_read=0;
#2;
write_data=8'b00001111;
inp_write=1;
inp_read=0;
#2;
inp_write=0;
inp_read=0;
#2;
write_data= 8'd123;
inp_write =1;
inp_read=0;
#2;
inp_write=0;
inp_read=0;
#2;
// 3 data are written continiously, now check for 4 data read
inp_read=0;
inp_write=0;
#2;
inp_read =1;
inp_write=0;
#2;
inp_read=0;
inp_write=0;
#2;
inp_write=0;
inp_read=1;
#2;
inp_read=0;
inp_write=0;
#2;
inp_write=0;
inp_read=1;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=0;
inp_read=1;
#2;
inp_write=0;
inp_read=0;
#5;
// check for input output at the same time error
write_data= 8'd205;
inp_write=1;
inp_read=1;
#2;
inp_write=0;
inp_read=0;
// put data 32 for checking full error after reseting
#5;
a_reset=1;
#5;
a_reset=0;
#5;
inp_write=1;
inp_read=0;
write_data= 8'd45;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd46;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd47;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd48;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd49;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd40;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd41;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd42;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd45;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd46;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd47;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd48;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd49;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd40;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd41;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd42;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd43;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd44;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd45;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd46;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd47;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd48;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd49;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd40;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd41;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd42;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd43;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd44;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd45;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd46;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd55;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd77;
#2;
inp_write=0;
inp_read=0;
#2;
// all the 32 memory location is now written lets try wrinting one more
inp_write=1;
inp_read=0;
write_data= 8'd55;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd77;
#2;
inp_write=0;
inp_read=0;
#5;
// lets try reading and writing simultaneously
write_data=8'b00000000;
inp_read=1;
inp_write=1;
#2;
inp_read=0;
inp_write=0;
#5
// now lets try reading for 33 times
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#5;
// all 32 memory locations read try reading more
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#5;
// now put equal read and write and check for reset when both pointer are pointing the same
// first write 2
inp_write=1;
inp_read=0;
write_data= 8'd55;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd77;
#2;
inp_write=0;
inp_read=0;
#5;
// second read 2
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#2;
inp_read=1;
inp_write=0;
#2;
inp_write=0;
inp_read=0;
#5;
// now reset
a_reset=1;
#5;
a_reset=0;
#5
// now write again
inp_write=1;
inp_read=0;
write_data= 8'd55;
#2;
inp_write=0;
inp_read=0;
#2;
inp_write=1;
inp_read=0;
write_data= 8'd77;
#2;
inp_write=0;
inp_read=0;
#5;
end
endmodule