Project Report ON: Implementation of Synchronous FIFO
Project Report ON: Implementation of Synchronous FIFO
ON
Submitted By:
C. Sahithi (2021H1400149H)
Aradhana (2021H1400151H)
ABSTRACT
4
1. INTRODUCTION
FIFO is a First-In-First-Out memory queue with control logic that manages the read
and write operations, generates status flags, and provides optional handshake signals
for interfacing with the user logic. It is often used to control the flow of data between
source and destination. FIFO can be classified as synchronous or asynchronous
depending on whether same clock or different (asynchronous) clocks control the
read and write operations. In this project the objective is to design, verify and
synthesize a synchronous FIFO using binary coded read and write pointers to
address the memory array. FIFO full and empty flags are generated and passed on
to source and destination logics, respectively, to pre-empt any overflow or
underflow of data. In this way data integrity between source and destination is
maintained.
6
Fig.1.
7
2. SYNCHRONOUS FIFO
A synchronous FIFO refers to a FIFO design where data values are written
sequentially into a memory array using a clock signal, and the data values are
sequentially read out from the memory array using the same clock signal.
I. Applications:
· are used to safely pass data between two asynchronous clock domains.
In System-on- Chip designs there are components which often run on different
clocks. So, to pass data from one such component to another we need
ASYNCHRONOUS FIFO.
· Some times even if the Source and Requestor sides are controlled by same
clock signal a FIFO is needed. This is to match the throughputs of the Source and
the Requestor. For example in one case source may be supplying data at rate which
the requestor can not handle or in other case requestor may be placing requests for
data at a rate at which source can not supply. So, to bridge this gap between source
and requestor capacities to supply and consume data a SYNCHRONOUS FIFO is
used which acts as an elastic buffer.
·
8
II. Port List:
9
III. Functional Description :
Fig.3.
The above figure depicts the basic building blocks of a synchronous FIFO which are:
memory array, write control logic and read control logic. The memory array can be
implemented either with array of flip-flops or with a dual-port read/write memory.
Both of these implementations allow simultaneous read and write accesses. This
simultaneous access gives the FIFO its inherent synchronization property. There are
no restrictions regarding timing between accesses of the two ports. This means
simply, that while one port is writing to the memory at one rate, the other port.
10
can be reading at another rate totally independent of one another. The only restriction
placed is that the simultaneous read and write access should not be from/to the same
memory location. The Synchronous FIFO has a single clock port clk for both data-
read and data-write operations. Data presented at the module's data-input port
write_data is written into the next available empty memory location on a rising clock
edge when the write-enable input write_enable is high. The full status output
fifo_full indicates that no more empty locations remain in the module's internal
memory. Data can be read out of the FIFO via the module's data-output port
read_data in the order in which it was written by asserting read-enable signal
read_enable prior to a rising clock edge. The memory-empty status output
fifo_empty indicates that no more data resides in the module's internal memory.
There are almost empty and almost full flags too viz. fifo_aempty and fifo_afull
which can be used to control the read and write speeds of the requestor and the
source.
ernal
memory. It generates binary-coded write pointer which points to the memory
location where the incoming data is to be written. Write pointer is incremented by
one after every successful write operation. Additionally it generates FIFO full and
almost full flags which in turn are used to prevent any data loss. For example if a
write request comes when FIFO is full then Write Control Logic stalls the write into
the memory till the time fifo_full flag gets de-asserted. It intimates the stalling of
write to source by not sending any acknowledgement in response to the write request.
Memory Array is an array of flip-flops which stores data. Number of data words that
the memory array can store is often referred as DEPTH of the FIFO. Length of the
data word is referred as WIDTH of the FIFO. Besides flop-array it comprises read
and write address decoding logic.
1. If write_enable signal is high DATA present on write_data is written into the row
pointed by write_addr on the next rising edge of the clock signal clk. Note that
write_enable is asserted only when wdata_valid is high and FIFO is not full to
avoid any data corruption.
2. If read_enable signal is high the DATA present in the row pointed by read_addr
is sent onto the read_data bus on the next rising edge of the clock signal clk. Note
that read_enable is asserted only when read_req is high and FIFO is not empty
to avoid any spurious data being sent to the requestor.
3. It can handle simultaneous read and write enables as long as their addresses do
not match.
12
V. Full And Empty Flag Generation :
FIFO full and almost full flags are generated by Write Control Logic whereas empty
and almost empty flags are generated by Read Control Logic. FIFO almost full and
almost empty flags are generated to intimate the source and the requestor about
impending full or empty conditions. The almost full and almost empty levels are
parameterized.
It is important to note that read and write pointers point to the same memory location
at both full and empty conditions. Therefore, in order to differentiate between the
two one extra bit is added to read and write pointers. For example if a FIFO has
depth of 256 then to span it completely 8- bits will be needed. Therefore with one
extra bit read and write pointers will be of 9-bits. When their lower 8-bits point to
same memory location their MSBs are used to ascertain whether it is a full condition
or empty condition. In empty conditions the MSBs are equal whereas in full
condition MSBs are different.
· At reset, both read and write pointers are 0. This is the empty condition of the
FIFO, and fifo_empty is pulled high and fifo_full is low.
· Since fifo_full is low, upon seeing a valid write data Write Control Logic will
ensure the data be written into location 0 of memory array and write_ptr be
incremented to 1. This causes the empty signal to go LOW.
· With fifo_empty pulled down, read operation can now be performed. Upon seeing
read request at this state Read Control Logic will fetch data from location 0 and will
increment read_prt to 1.
13
· In this way read keeps following write until the FIFO gets empty
again.
· If write operations are not matched by read soon FIFO will get full
and any further write will get stalled until fifo_full is pulled down by a
read.
· With the help of FIFO full and empty flags data integrity is
maintained between the source and the requestor.
14
DESIGN OF SYNCHRONOUS FIFO
Code:
reg[7:0] buf_out;
reg buf_empty, buf_full;
reg[`BUF_WIDTH :0] fifo_counter;
reg[`BUF_WIDTH -1:0] rd_ptr, wr_ptr; // pointer to read and
write addresses
reg[7:0] buf_mem[`BUF_SIZE -1 : 0]; //
always @(fifo_counter)
begin
buf_empty = (fifo_counter==0); // Checking for whether buffer is
empty or not
buf_full = (fifo_counter== `BUF_SIZE); //Checking for whether
15
buffer is full or not
end
//Setting FIFO counter value for different situations of read and write
operations.
always @(posedge clk or posedge rst)
begin
if( rst )
fifo_counter <= 0; // Reset the counter of FIFO
else if( (!buf_full && wr_en) && ( !buf_empty && rd_en ) ) //When
doing read and write operation simultaneously
fifo_counter <= fifo_counter; // At this state,
counter value will remain same.
else
fifo_counter <= fifo_counter; // When doing
nothing.
end
else
buf_out <= buf_out;
16
end
end
else
buf_mem[ wr_ptr ] <= buf_mem[ wr_ptr ];
end
end
endmodule
17
Test Bench:
`define BUF_WIDTH 3
module Test_Sync_FIFO();
reg clk, rst, wr_en, rd_en ;
reg[7:0] buf_in;
reg[7:0] tempdata;
wire [7:0] buf_out;
wire [`BUF_WIDTH :0] fifo_counter;
initial
begin
clk = 0;
rst = 1;
rd_en = 0;
wr_en = 0;
tempdata = 0;
buf_in = 0;
#15 rst = 0;
push(1);
fork
push(2);
pop(tempdata);
join //push and pop together
push(10);
push(20);
push(30);
push(40);
push(50);
push(60);
push(70);
push(80);
push(90);
push(100);
push(110);
18
push(120);
push(130);
pop(tempdata);
push(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
push(140);
pop(tempdata);
push(tempdata);//
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
pop(tempdata);
push(5);
pop(tempdata);
end
always
#5 clk = ~clk;
task push;
input[7:0] data;
if( buf_full )
$display("---Cannot push: Buffer Full---");
else
begin
$display("Pushed ",data );
buf_in = data;
wr_en = 1;
@(posedge clk);
#1 wr_en = 0;
19
end
endtask
task pop;
output [7:0] data;
if( buf_empty )
$display("---Cannot Pop: Buffer Empty---");
else
begin
rd_en = 1;
@(posedge clk);
#1 rd_en = 0;
data = buf_out;
$display("-------------------------------Poped ", data);
end
endtask
endmodule
20
RESULTS
RTL Schematic:
Simulation Results:
21
From the above simulation results, we can see that depending upon the write
enable and read enable the data is written in the buffer and read from the buffer.
When the write enable is high, the data 00, 01, 02, 0a,14,1e, 28, 32, 3e, 46 are
written in the buffer, which is mentioned as temporary data in the above result.
After that when the read enable signal is high, the data are read from the output
of buffer, which is denoted as buff_out here. The FIFO counter shows that
whether the memory buffer is full or not. As in code buffer width is taken as 3bit,
so, max no. of data stored possible in the buffer is 8. That s why as soon as the
FIFO counter becomes 8, the buffer becomes full, denoted as buff_full.
In this tcl console, the output is displayed as when the buffer is full and
when the buffer is empty. Initially the data are pushed and popped according
to the user requirement. The moment the buffer becomes full, no more data
can be pushed into the buffer. Similarly, as soon as all the data are read from
the buffer, no more data can be popped from the buffer.
22
Utilization:
Power Consumption:
23
REFERENCES
[1] A
Asynchronous Pulse-
[2
15, pp. 1 8.
24