Professional Documents
Culture Documents
SYNTHE SIS OF
SYN CHR ONOUS FIFO
1
2
TABLE OF CONTENTS:
• ACRONYMS ………………………………………………………...3
• ACKNOWLEDGEMENT …………………………………………...4
• HISTORY ……………………………………………………………5
• ABSTRACT ………………………………………………………….6
• INTRODUCTION …………………………………………………...7
• CONCLUSION ……………………………………………………..32
• APPENDIX …..……………………………………………………..33
HDL …………………...…………………………...33
3
ACRONYMS:
• TB : Testbench
Language
4
ACKNOWLEDGEMENT
I want to thank them for all their help, support, interest and valuable hints.
5
HISTORY
Cadence Design Systems, Inc is an electronic EDA software and
engineering services company, founded in 1988 by the merger of SDA
Systems and ECAD, Inc. For years it has been the largest company in the
EDA industry. With revenues of $1.43 billion in 2001, Cadence Design
Systems, Inc. is the world's leading developer of EDA products and services.
EDA software is a form of CAD/CAE software specifically geared towards
automating the design of electronic systems and IC's. The company's
products and services are used by companies in the computer,
communication, and consumer electronics industries to design and develop
IC's and electronic systems, including semiconductors, computer systems
and peripherals, telecommunications and networking equipment, wireless
products, automotive electronics, and various other electronic products.
Cadence has operations in North America, Europe, Japan, and the Asia
Pacific region.
6
ABSTRACT
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
synchronous FIFO using binary coded read and write pointers to address the
memory array. FFIO full and empty flags are generated and passed on to
underflow of data. In this way data integrity between source and destination
is maintained.
The RTL description for the FIFO is written using Verilog HDL, and design
7
INTRODUCTION
FIFO full and FIFO empty flags are of great concern as no data should be
written in full condition and no data should be read in empty condition, as it
can lead to loss of data or generation of non relevant data. The full and
empty conditions of FIFO are controlled using binary or gray pointers. In
this report we deal with binary pointers only since we are designing
SYNCHRONOUS FIFO. The gray pointers are used for generating full and
8
empty conditions for ASYNCHRONOUS FIFO. The reason why they are
used is beyond the scope of this document.
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.
9
APPLICATIONS
• FIFO’s 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.
10
BLACK BOX VIEW OF SYNCHRONOUS FIFO
SYNCHRONOUS
FIFO
PORT LIST
COMMON PORTS
11
wdata_valid I 1 Qualifies the write data. Logic high
indicates the data on write_data bus is
valid and need to be sampled at next
rising edge of the clock.
fifo_full O 1 Indicates to the source that FIFO’s
internal memory has no space left to take
in new data
fifo_afull O 1 Indicates to the source that FIFO’s
internal memory has only few spaces left
for new data. Upon seeing this source may
decide to slow down or stall the write
operation
write_ack O 1 Write acknowledgement to source.
12
FUNCTIONAL DESCRIPTION
Figure 2 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 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.
13
Figure 2: Block Diagram of a Synchronous FIFO
14
WRITE
CONTROL
LOGIC
PORT LIST
Name I/O Width Description
clk I 1 Clock input
reset_n I 1 Active-low reset input
flush I 1 Active-high synchronous flush input to
FIFO. A clock-wide pulse resets the FIFO
read and write pointers
wdata_valid I 1 Qualifies write data in. A logic high
indicates the data on write_data bus is
valid
rd_ptr I 5 Read pointer from Read Control Logic.
This along with write pointer is used to
find FIFO full and almost full condition
write_enable O 1 Write enable to FIFO’s internal memory
write_ptr O 5 Write pointer value. This serves as a write
address to FIFO’s internal memory
write_ack O 1 Acknowledgement to source that write
operation is done.
fifo_full O 1 Indicates to the source that FIFO’s
internal memory has no space left to take
in new data
fifo_afull O 1 Indicates to the source that FIFO’s
internal memory has only few spaces left
for new data. Upon seeing this source may
15
decide to slow down or stall the write
operation
READ
CONTROL
LOGIC
16
PORT LIST
Name I/O Width Description
clk I 1 Clock input
reset_n I 1 Active-low reset input
flush I 1 Active-high synchronous flush input to
FIFO. A clock-wide pulse resets the FIFO
read and write pointers
read_req I 1 Read request from the requestor.
write_ptr I 5 Write pointer from Write Control Logic.
This along with read pointer is used to
find FIFO empty and almost empty
conditions
read_enable O 1 Read enable to FIFO’s internal memory
read_ptr O 5 Read pointer value. This serves as a read
address to FIFO internal memory
rdata_valid O 1 Acknowledgement to source that write
operation is done.
fifo_empty O 1 Indicates to the source that FIFO’s
internal memory has no space left to take
in new data
fifo_aempty O 1 Indicates to the source that FIFO’s
internal memory has only few spaces left
for new data. Upon seeing this source may
decide to slow down or stall the write
operation
MEMORY ARRAY
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.
17
The functionality of Memory Array is relatively straight forward as
described below:
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
MEMORY
ARRAY
18
PORT LIST
Name I/O Width Description
clk I 1 Clock input
write_addr I 4 Write address to the memory. It is derived
from write pointer by knocking-off its
MSB
write_enable I 1 Active-high write enable input to the
memory
write_data I 16 Data Input to the memory
read_addr I 4 Read address to the memory. It is derived
from read pointer by knocking-off its
MSB
read_enable I 1 Active-high read enable to memory
read_data O 16 Data read out from the memory
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
19
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. The verilog code shown below depicts the same:
assign fifo_full = ( (write_ptr[7 : 0] == read_addr[7 : 0]) &&
(write_ptr[8] ^ read_ptr[8]) );
20
always @*
begin
if (read_ptr[8] == write_ptr[8])
fifo_aempty = ( (write_ptr[7:0] - read_ptr[7:0]) <=
AEMPTY );
else
fifo_aempty = ((read_ptr[8:0] - write_addr[8:0])
>= (DEPTH - AEMPTY));
end
Here AEMPTY signifies the almost empty-level. User can set it to 4, 8 or
whatever value depending on how soon it wants to intimate the requestor
about impending empty condition. (AEMPTY=4) means almost empty flag
will get asserted when at most 4 data locations are left to be read.
21
• 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
Following parameters have been used in the RTL representation of the FIFO
to keep it scalable:
• DEPTH : FIFO depth which can take any positive integer value
• ADDR_WIDTH : FIFO Address bus width
• DATA_WIDTH : Width of the data input to FIFO
• AEMPTY : Almost empty level
• AFULL : Almost full level
The verilog codes for each of these modules along with the top-level module
are presented in Appendix A1.
22
23
VERIFICATION OF THE MODULE
A TYPICAL TESTBENCH
A test bench is a virtual environment used to verify the correctness or
soundness of a design or model. It is a computer program written in a
hardware description language (HDL), such as the Verilog language, for the
purpose of verifying a module’s functional behavior.
INPUT OUTPUT
STIMULUS CHECKER
BLOCK BLOCK
24
TB FOR SYNCHRONOUS FIFO
A verilog testbench has been developed to test the functional correctness of
Synchronous FIFO. It comprises simplified source and destination models
along with a checker which asserts match/mismatch depending on whether
the data written into and read out of FIFO are indeed same.
25
SIMULATION
We used Cadence NC-SIM simulator to simulate our Synchronous FIFO TB.
The results are shown below:
26
FIFO FLUSH OPERATION
The yellow circle shows how FIFO is being flushed? Notice that upon
seeing the flush signal both the pointers are reset to zero and FIFO empty
flag is pulled high.
27
TB CHECKER
TB checker compares all the data which were sent to FIFO with all the data
received at the output of FIFO. They should match. The result of this
comparison is the match signal shown in the snapshot. If this signal is high
all the time it means the test has passed the checking.
28
SYNTHESIS OF THE MODULE
WHAT IS SYNTHESIS?
It is defined as the process of parsing, translating, and optimizing RTL code
into discrete logic gates. Typically a synthesis tool takes in the RTL code,
standard cell library and user defined constraints and produces a gate-level
representation of the design which is often referred to as netlist. It tries its
best to meet the user defined constraints while generating the netlist
however it is not guaranteed that it will meet all the time.
INPUTS TO A SYNTHESIZER
The inputs to a synthesizer are:
• RTL code of the design
• Constraints on timing, area etc.
• Standard Cell library
OUTPUTS OF SYNTHESIZER
• Gate-level representation of the design
• Timing report: reports whether it met the timing constraint or not. If
not details of the timing violations
• Area report: reports approximate area of the design, number of
standard cells used etc.
EXAMPLE
• RTL
assign z = a && b;
29
• Netlist
AND2X1 u0 (.A(a), .B(b), .Z(z));
Where AND2X1 is a standard cell for AND gate in the library.
CONSTRAINTS
The constraints are the goals that the synthesis tool tries to meet. For
example, we may have a design that is targeted for several different
applications with different requirements:
• Timing is most important; area is not a concern.
• Power and area are more important; and timing is less so.
• Timing, area, and power are all important, and we have specific
measures for each.
30
CONSTRAINT FILE FOR SYNCHRONOUS FIFO
File name: constraints.sdc
*************************************************************
set sdc_version 1.7
set_max_fanout 32 /designs/sync_fifo/
set_max_transition 0.5 /designs/sync_fifo/
set_max_leakage_power 0
set_driving_cell -lib_cell BUFFD4 -library tcbn65lpwc -pin Z [find / -port
*/ports_in/*]
set_load -pin_load 0.05 [get_ports *]
create_clock [find / -port clk] -name clk -period 5 -waveform {0 2.5}
set_clock_uncertainty 2 clk
set_input_delay -clock clk -min 2 [get_ports *]
set_output_delay -clock clk -min 2 [get_ports *]
*************************************************************
31
rc:/>check_design > ../REPORTS/check_design.rpt
rc:/>read_sdc ../SCRIPTS/constraints.sdc
32
RESULTS
It can be observed that there is a positive slack of 776ps (see the yellow
circle) for the worst case path. So the synthesis comfortably meets the
timing constraints set by us.
33
CONCLUSION
The objective of this training was to learn basics of digital logic design. And
during the course of this I learned the following aspects of digital design:
Given the short duration of this training, I believe, my set objectives are
more than fulfilled.
34
APPENDIX
A1: RTL DESCRIPTION OF SYNCHRONOUS FIFO USING
VERILOG HDL
// Outputs
output [DATA_WIDTH-1:0] read_data,
output rdata_valid,
output fifo_empty,
output fifo_aempty,
output fifo_full,
output fifo_afull,
output write_ack
35
);
wire read_enable;
wire write_enable;
write_control_logic U_WRITE_CTRL (
.read_ptr(read_ptr),
.flush(flush),
.reset_n(reset_n),
.clk(clk),
.wdata_valid(wdata_valid),
.write_ack(write_ack),
.write_enable(write_enable),
.write_ptr(write_ptr),
.fifo_full(fifo_full),
.fifo_afull(fifo_afull)
);
read_control_logic U_READ_CTRL (
.write_ptr(write_ptr),
.clk(clk),
.reset_n(reset_n),
.flush(flush),
.read_req(read_req),
.read_enable(read_enable),
.rdata_valid(rdata_valid),
.fifo_empty(fifo_empty),
.read_ptr(read_ptr),
.fifo_aempty(fifo_aempty)
);
mem_array U_MEM_ARRAY (
.write_addr(write_ptr[ADDR_WIDTH-1:0]),
.read_addr(read_ptr[ADDR_WIDTH-1:0]),
.write_enable(write_enable),
.read_enable(read_enable),
.clk(clk),
//.reset_n(reset_n),
36
.write_data(write_data),
.read_data(read_data)
);
endmodule
//***********************************************************//
// Outputs
output read_enable,
output reg rdata_valid,
output fifo_empty,
output reg fifo_aempty,
output reg [ADDR_WIDTH:0] read_ptr
);
37
wire [ADDR_WIDTH-1:0] write_addr;
endmodule
38
//***********************************************************//
// Outputs
output reg write_ack,
output write_enable,
output reg [ADDR_WIDTH:0] write_ptr,
output fifo_full,
output reg fifo_afull
);
39
assign read_addr = read_ptr[ADDR_WIDTH-1:0];
assign write_addr = write_ptr[ADDR_WIDTH-1:0];
40
write_ptr <= write_ptr + {{ADDR_WIDTH{1'b0}},1'b1};
write_ack<= 1'b1;
end
else
begin
write_ack <= 1'b0;
end
end
endmodule
//*********************************************************//
MEMORY ARRAY
//***********************************************************//
// File Name: mem_array.v
// Module Name: mem_array
// Description: FIFO internal memory to store incoming data. It is
// implemented as flop-array
// Author: Asim Anand
// Place: Cadence Design Systems, Inc.
// Date: July 10, 2008
//***********************************************************//
module mem_array #(
parameter ADDR_WIDTH = 4,
parameter DEPTH = 16,
parameter DATA_WIDTH = 16
)
(
input [ADDR_WIDTH-1:0] write_addr,
input [ADDR_WIDTH-1:0] read_addr,
input write_enable,
input read_enable,
input clk,
input [DATA_WIDTH-1:0] write_data,
41
// Mem write
always @(posedge clk)
begin
if (write_enable)
mem[write_addr] <= write_data;
end
// Mem Read
always @(posedge clk)
begin
if (read_enable)
begin
read_data <= mem[read_addr];
end
end
endmodule
//***********************************************************//
42
A2: VERILOG TESTBENCH
//***********************************************************//
// File Name: sync_fifo_tb.v
// Module Name: sync_fifo_tb
// Description: This is testbench for verifying sync_fifo. It
// implemets source logic for pumping in data to
// FIFO, destination logic to read data from FIFO. It
// implements source and destination data buffers to
// compare the data pumped into FIFO with data
// pumped out of FIFO
// Author: Asim Anand
// Place: Cadence Design Systems, Inc.
// Date: July 10, 2008
//***********************************************************//
module sync_fifo_tb;
reg clk;
reg reset_n;
reg [15:0] lfsr_count;
reg[15:0] data_in;
reg data_valid;
wire ready;
wire flush = 1'b0;
wire read_req;
wire count_enable;
wire write_ack;
wire fifo_full;
wire fifo_afull;
43
//generating reset signal
initial
begin
reset_n=1'b0;
#550;
reset_n=1'b1;
end
// LFSR Counter
always @(posedge clk or negedge reset_n)
begin
if(~reset_n)
lfsr_count <= 16'h70f0;
else
lfsr_count <= {lfsr_count[14:0],
~(lfsr_count[15] ^ lfsr_count[14] ^
lfsr_count[12] ^ lfsr_count[3])};
end
44
//instantiating DUT
sync_fifo #(
.ADDR_WIDTH(4),
.DATA_WIDTH(16),
.DEPTH(16),
.AEMPTY(3),
.AFULL(3)
)
DUT (
.clk(clk),
.reset_n(reset_n),
.flush(flush),
.read_req(read_req),
.write_data(data_in),
.wdata_valid(data_valid),
.read_data(data_out),
.fifo_empty(fifo_empty),
.fifo_aempty(fifo_aempty),
.fifo_full(fifo_full),
.fifo_afull(fifo_afull),
.write_ack(write_ack),
.rdata_valid(rdata_valid)
);
//source array
reg [15:0] source_array[0:2047];
reg [10:0] counter;
always @(posedge clk or negedge reset_n)
begin
if(~reset_n)
counter <= {11{1'b0}};
else if(data_valid && (~fifo_full))
begin
source_array[counter] <= data_in;
counter <= counter + {{10{1'b0}},1'b1};
end
end
45
//destination array
reg [15:0] destination_array[0:2047];
reg [10:0] counter1;
integer i;
//reg [2047:0] match;
reg match;
always @(counter1)
begin
match = 1'b1;
for (i=0; i < counter1; i=i+1)
//comparing source and destination array
match = match && (source_array[i] == destination_array[i]);
end
always @*
begin
ns = cs;
data_valid = 1'b0;
case(cs)
46
idle: begin
if(ready)
begin
ns = active;
data_valid = 1'b1 ;
end
end
active: begin
if((~fifo_full) && (~ready))
begin
ns = idle;
data_valid = 1'b0;
end
else
data_valid = 1'b1;
end
default: cs = idle;
endcase
end
endmodule
//***********************************************************//
47