synchronous fifo using verilog code
FIFO(First in first out)
INTRODUCTION:
These are commonly
used in electronic circuits for
buffering and flow control between hardware and software. In its hardware form,
a FIFO primarily consists of a set of read and write pointers, storage and
control logic Storage may be static
random access memory (SRAM), flip-flops, latches or
any other suitable form of storage.
A synchronous FIFO
is a FIFO where the same clock is used for both reading and writing. An
asynchronous FIFO uses different clocks for reading and writing. Asynchronous
FIFOs introduce metastability issues. A
common implementation of an asynchronous FIFO uses a Gray code (or any unit
distance code) for the read and write pointers to ensure reliable flag
generation. One further note concerning flag generation is that one must
necessarily use pointer arithmetic to generate flags for asynchronous FIFO
implementations. Conversely, one may use either a leaky bucket approach or
pointer arithmetic to generate flags in synchronous FIFO implementations.
Examples of FIFO status flags include: full, empty, almost full, almost empty,
etc The first known FIFO implemented in electronics was done by Peter Alfke
in 1969
FIFO full-empty
A hardware FIFO is used for
synchronization purposes. It is often implemented as a circular queue, and thus has two pointers:
1. Read pointer / read address register
2. 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 the read address register reaches the write address
register, the FIFO triggers the empty signal.
FIFO full
When the write address register
reaches the read address register, the FIFO triggers the full signal.
USES OF
FIFO
I.
Communication
II.
Networking
III.
Routers
IV.
Sequential data processing
Verilog
code for FIFO memory
In this
project, Verilog code for FIFO memory is presented. The First-In-First-Out
(FIFO) memory with the following specification is implemented in Verilog:
16 stages
8-bit
data width
Status
signals:
Full:
high when FIFO is full else low.
Empty:
high when FIFO is empty else low.
Overflow:
high when FIFO is full and still writing data into FIFO, else low.
Underflow:
high when FIFO is empty and still reading data from FIFO, else low.
Threshold:
high when the number of data in FIFO is less than a specific threshold, else
low.
Source
code
module fifomem(data_out,fifo_full, fifo_empty,
fifo_threshold, fifo_overflow, fifo_underflow,clk, rst_n, wr, rd,
data_in);
input wr,
rd, clk, rst_n;
input[7:0]
data_in;
output[7:0]
data_out;
output
fifo_full, fifo_empty, fifo_threshold, fifo_overflow, fifo_underflow;
wire[4:0]
wptr,rptr;
wire
fifo_we,fifo_rd;
write_pointer top1(wptr,fifo_we,wr,fifo_full,clk,rst_n);
read_pointer top2(rptr,fifo_rd,rd,fifo_empty,clk,rst_n);
memory_array top3(data_out, data_in, clk,fifo_we, wptr,rptr);
status_signal top4(fifo_full, fifo_empty, fifo_threshold, fifo_overflow,
fifo_underflow, wr, rd, fifo_we, fifo_rd, wptr,rptr,clk,rst_n);
endmodule
//Verilog code for FIFO memory
//Verilog code for Memory Array submodule
module
memory_array(data_out, data_in, clk,fifo_we, wptr,rptr);
input[7:0]
data_in;
input
clk,fifo_we;
input[4:0]
wptr,rptr;
output[7:0]
data_out;
reg[7:0]
data_out2[15:0];
wire[7:0]
data_out;
always
@(posedge clk)
begin
if(fifo_we)
data_out2[wptr[3:0]] <=data_in ;
end
assign
data_out = data_out2[rptr[3:0]];
endmodule
//Verilog code for Read Pointer sub-module
module
read_pointer(rptr,fifo_rd,rd,fifo_empty,clk,rst_n);
input
rd,fifo_empty,clk,rst_n;
output[4:0]
rptr;
output
fifo_rd;
reg[4:0]
rptr;
assign
fifo_rd = (~fifo_empty)& rd;
always
@(posedge clk or negedge rst_n)
begin
if(~rst_n)
rptr <= 5'b000000;
else
if(fifo_rd)
rptr
<= rptr + 5'b000001;
else
rptr
<= rptr;
end
endmodule
// Verilog code for Status Signals sub-module
module
status_signal(fifo_full, fifo_empty, fifo_threshold, fifo_overflow,
fifo_underflow, wr, rd, fifo_we, fifo_rd, wptr,rptr,clk,rst_n);
input wr,
rd, fifo_we, fifo_rd,clk,rst_n;
input[4:0]
wptr, rptr;
output
fifo_full, fifo_empty, fifo_threshold, fifo_overflow, fifo_underflow;
wire
fbit_comp, overflow_set, underflow_set;
wire
pointer_equal;
wire[4:0]
pointer_result;
reg
fifo_full, fifo_empty, fifo_threshold, fifo_overflow, fifo_underflow;
assign
fbit_comp = wptr[4] ^ rptr[4];
assign
pointer_equal = (wptr[3:0] - rptr[3:0]) ? 0:1;
assign
pointer_result = wptr[4:0] - rptr[4:0];
assign
overflow_set = fifo_full & wr;
assign
underflow_set = fifo_empty&rd;
always
@(*)
begin
fifo_full
=fbit_comp & pointer_equal;
fifo_empty
= (~fbit_comp) & pointer_equal;
fifo_threshold = (pointer_result[4]||pointer_result[3]) ? 1:0;
end
always
@(posedge clk or negedge rst_n)
begin
if(~rst_n)
fifo_overflow <=0;
else
if((overflow_set==1)&&(fifo_rd==0))
fifo_overflow <=1;
else
if(fifo_rd)
fifo_overflow <=0;
else
fifo_overflow <= fifo_overflow;
end
always
@(posedge clk or negedge rst_n)
begin
if(~rst_n)
fifo_underflow <=0;
else
if((underflow_set==1)&&(fifo_we==0))
fifo_underflow <=1;
else
if(fifo_we)
fifo_underflow <=0;
else
fifo_underflow <= fifo_underflow;
end
endmodule
// Verilog code for Write Pointer sub-module
module write_pointer(wptr,fifo_we,wr,fifo_full,clk,rst_n);
input
wr,fifo_full,clk,rst_n;
output[4:0]
wptr;
output
fifo_we;
reg[4:0]
wptr;
assign
fifo_we = (~fifo_full)≀
always
@(posedge clk or negedge rst_n)
begin
if(~rst_n)
wptr <= 5'b000000;
else
if(fifo_we)
wptr
<= wptr + 5'b000001;
else
wptr
<= wptr;
end
endmodule
Advantage & Disadvantage
1.
It saves time and money.
2.
It is very easy to understand.
3.
Each flow with low data rate can experience long
delays.
0 Comments