1
2
TABLE OF CONTENTS:
•
ACRONYMS ………………………………………………………...3
•
ACKNOWLEDGEMENT …………………………………………...4
•
HISTORY ……………………………………………………………5
•
ABSTRACT ………………………………………………………….6
•
INTRODUCTION …………………………………………………...7
•
BLACK-BOX VIEW OF SYNCHRONOUS FIFO ……….…….…10
•
PORT LIST ……………………………………………..………......10
•
FUNCTIONAL DESCRIPTION …………...………………………12
•
VERIFICATION OF THE MODULE ………..…………………….22
•
SYNTHESIS OF THE MODULE ...………………………………..27 ...………………………………..27
•
CONCLUSION ……………………………………………………..32
•
APPENDIX …..……………………………………………………..33 o
A1: RTL DESCRIPTION DESCRIPTION OF SYNCHRONOUS FIFO USING VERILOG HDL …………………...…………………………...33
o
A2: VERILOG TESTBENCH …………...………………………42
3
ACRONYMS: EDA
: Electronic Design Automation
•
FIFO
: First In First Out
•
CAD
: Computer Aided Design
•
CAE
: Computer Aided Engineering
•
IC’s
: Integrated Circuits
•
RTL
: Register Transistor Level
TB
: Testbench
•
HDL
: Hardware Description Language
•
MSB
: Most Significant Bit
•
RAM
: Random Access Memory
•
WCLK : Write Clock
•
RCLK : Read Clock
•
LFSR : Linear Feedback Shift Registers
•
VHDL : Very High Speed Integrated Circuit Hardware Description
•
•
Language •
HOD
: Head Of Department
•
MIT
: Manipal Institute of Technology
4
ACKNOWLEDGEMENT I woul would d like like to expr expres esss my grati ratitu tude de to all all thos thosee who who gave gave me the the opportunity to complete this training. I am obliged to Mr. H. K. Shama (H.O.D, ECE, M.I.T., Manipal) for his stimulating support. I want to thank Mr. Vasanth Mallya (Engineering Director, Cadence Design Systems, Inc.) for offering me training for one month at Cadence Design Systems, Inc Bangalore office. I am grateful to Mr. Sunil Vashistha (Principal Design Engineer) for his willingness to help and discuss Synchronous FIFO design issues during the training and for helping me to understand and use the RTL compiler for synthesis. I am deeply indebted to my brother, Amit Anand, whose help, stimulating sugg suggest estio ions ns and and enco encour urag agem emen entt help helped ed me thro throug ugho hout ut the the trai traini ning ng in completing the Synchronous FIFO design, simulation and synthesis. I want to thank them for all their help, support, interest and valuable hints.
5
HISTORY Cade Cadenc ncee Desi Design gn Syst System ems, s, Inc Inc is an elec electtroni ronicc EDA software and
engine engineeri ering ng servic services es compan company y, founde founded d in 198 1988 8 by the merger 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 auto automa mati ting ng the the desi design gn of elec electr tron onic ic syst system emss and and IC's. IC's. Th Thee comp compan any' y'ss products and services are used sed by comp ompanies in the computer, communication, and consumer electronics industries to design and develop IC's and electronic systems, including semiconductors, computer systems and peripheral peripherals, s, telecommu telecommunicat nications ions and networkin networking g equipment equipment,, wireless wireless products, products, automotive automotive electron electronics, ics, and various various other electroni electronicc products. products. Cadence has operations in North America, Europe, Japan, and the Asia Pacific region. Computer-aided Computer-aided design of IC's was a rapidly growing field when Cadence started operations. As chip manufacturers manufacturers tried to fit increasingly more tiny transistors on each chip, the complex layout of the chip's design and its verification came to depend on design automation software. ECAD, based in Santa Clara, California, developed and sold CAD/CAE software to accelerate the design of IC's, including both the schematic design and the testing phases. The company's specialty was design-verification software, in which it was a technology leader. leader.
6
ABSTRACT 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 cont contro roll the the flow flow of data data betw betwee een n sour source ce and and dest destin inat atio ion. n. FIFO FIFO can can be classi classifie fied d as synchr synchrono onous us or asynch asynchron ronous ous depend depending ing on whethe whetherr same same cloc clock k or dif differe ferent nt (asy (async nchr hron onou ous) s) cloc clocks ks cont contro roll the the read read and and writ writee 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. FFIO 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. The RTL description for the FIFO is written using Verilog HDL, and design is simulated and synthesized using NC-SIM and RTL compiler provided by Cadence Design Systems, Inc. respectively.
7
INTRODUCTION WHAT IS A FIFO (first in first out)? In comput computer er progr programm amming ing,, FIFO FIFO (firs (first-i t-in, n, first first-o -out) ut) is an approa approach ch to handling program work requests from queues or stacks so that the oldest requ reques estt is hand handle led d firs first. t. In hard hardwa ware re it is eith either er an arra array y of flop flopss or Read/Write memory that store data given from one clock domain and on request supplies with the same data to other clock domain following the first in first out logic. The clock domain that supplies data to FIFO is often referred as WRITE OR INPUT LOGIC and the clock domain that reads data from the FIFO is often referred as READ OR OUTPUT LOGIC. FIFOs are used in designs to safely pass multi-bit data words from one clock domain to another or to control the flow of data between source and destination side sitting in the same clock domain. If read and write clock domains are governed by same clock signal the FIFO is said to be SYNCHRONOUS and if read and write clock domains are governed by different (asynchronous) clock signals FIFO is said to be ASYNCHRONOUS.
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 this repo report rt we deal deal with with bina binary ry po poin inte ters rs on only ly sinc sincee we are are desi design gnin ing g 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.
Figure 1: Data Flow through FIFO
SYNCHRONOUS 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.
In synchr synchrono onous us FIFO FIFO the genera generatio tion n of empty and full flags is straight forward as there is no clock domain crossing involved. Considering this fact user can even generate programmable partial empty and partial full flags which are needed in many applications.
9
APPLICATIONS •
FIFO’s are used to safely pass data between two asynchronous clock domain domains. s. In System System-o -on-C n-Chip hip design designss there there are compon component entss which which ofte often n run run on diffe differe rent nt clock clocks. s. So, to pass pass data data from from
onee such on such
component to another we need ASYNCHRONOUS 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. buffer.
10
BLACK BOX VIEW OF SYNCHRONOUS FIFO
SYNCHRONOUS FIFO
Figure 1: Black-box view of a Synchronous Synchronous FIFO
PORT LIST COMMON PORTS Name clk
I/O I
Width 1
reset_n
I
1
flush
I
1
Description Clock input to the FIFO. This is common input to both read and write sides of FIFO Active-low asynchronous reset input to FIFO read and write logics Active-high synchronous flush input to FIFO. A clock-wide pulse resets the FIFO read and write pointers
WRITE SIDE PORTS Name write_data
I/O I
Width 16
Description 16-bit data input to FIFO
11
wdata_valid
I
1
fifo_full
O
1
fifo_afull
O
1
write_ack
O
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. Indicates to the source that FIFO’s internal memory has no space left to take in new data 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 acknowledgement to source.
READ SIDE PORTS Name read_req
I/O I
Width 1
read_data
O
16
rdata_valid
O
1
fifo_empty
O
1
fifo_aempty
O
1
Description Data read request to FIFO from the requestor Read data in response to a read request. Data is valid in the next cycle of read_req provided FIFO is not empty Qualifies read data out. A logic high indicates the data on read_data bus is valid and need to be sampled at the next rising edge of the clock Indicates to the requestor that FIFO’s internal memory is empty and therefore has no data to serve upon the read request Indicates to the requestor that FIFO’s internal memory is almost empty and therefore has only few data left to serve upon the future read requests. Upon seeing this requestor may decide to slow down or stall the read operation.
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. 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 data-w -wri rite te op oper erat atio ions ns.. Data Data pres presen ente ted d at the the modu module le's 's data data-i -inp nput ut po port rt 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. 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 memoryempty 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
WRITE CONTROL LOGIC Write Control Logic is used to control the write operation of the FIFO’s
internal 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. Figure 3 below shows the black-box view of Write Control Logic
14
WRITE CONTROL LOGIC
Figure 3: Write Control Logic Black-box View
PORT LIST Name clk reset_n flush
I/O I I I
Width 1 1 1
wdata_valid
I
1
rd_ptr
I
5
write_enable write_ptr
O O
1 5
write_ack
O
1
fifo_full
O
1
fifo_afull
O
1
Description
Clock input Active-low reset input Active-high synchronous flush input to FIFO. A clock-wide pulse resets the FIFO read and write pointers Qualifies write data in. A logic high indicates the data on write_data bus is valid Read pointer from Read Control Logic. This along with write pointer is used to find FIFO full and almost full condition Write enable to FIFO’s internal memory Write pointer value. This serves as a write address to FIFO’s internal memory Acknowledgement to source that write operation is done. Indicates to the source that FIFO’s internal memory has no space left to take in new data 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 Read Control Logic is used to control the read operation of the FIFO’s
internal memory. It generates binary-coded read pointer which points to the memo memory ry loca locati tion on from from wher wheree the the data data is to be read read.. Read Read po poin inte terr is incremented by one after every successful read operation. Additionally it generates FIFO empty and almost empty flags which in turn are used to prevent any spurious data read. For example if a read request comes when FIFO is empty then Read Control Logic stalls the read from the memory till the time fifo_empty flag gets de-asserted. It intimates the stalling of read to the requestor by not asserting rdata_valid in response to the read request. Figure 5 below shows the black-box view of Read Read Control Logic
READ CONTROL LOGIC
Figure 5: Read Control Logic Black-box View
16
PORT LIST Name clk reset_n flush
I/O I I I
Width 1 1 1
read_req write_ptr
I I
1 5
read_enable read_ptr
O O
1 5
rdata_valid
O
1
fifo_empty
O
1
fifo_aempty
O
1
Description
Clock input Active-low reset input Active-high synchronous flush input to FIFO. A clock-wide pulse resets the FIFO read and write pointers Read request from the requestor. Write pointer from Write Control Logic. This along with read pointer is used to find FIFO empty and almost empty conditions Read enable to FIFO’s internal memory Read pointer value. This serves as a read address to FIFO internal memory Acknowledgement to source that write operation is done. Indicates to the source that FIFO’s internal memory has no space left to take in new data 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. FIFO. Length Length of the data word is referred referred as WIDTH of the FIFO. Besides flop-array it comprises read and write address decoding logic.
17
The functi functiona onalit lity y of Memory Memory Array Array is rela relati tive vely ly stra straig ight ht forw forwar ard d as described below:
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 clock signal signal clk . Note Note that hat write_enable is asse assert rted ed on only ly when 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 hand handle le simul simulta tane neou ouss read read and and writ writee enab enable less as long long as thei their r addresses do not match
Figure 6 below shows the black-box view of Memory Memory Array.
MEMORY ARRAY
Figure 6: Memory Array Black-box View 18
PORT LIST Name clk write_addr
I/O I I
Width 1 4
write_enable
I
1
write_data read_addr
I I
16 4
read_enable read_data
I O
1 16
Description
Clock input Write address to the memory. It is derived from write pointer by knocking-off its MSB Active-high write enable input to the memory Data Input to the memory Read address to the memory. It is derived from read pointer by knocking-off knocking-off its MSB Active-high read enable to memory Data read out from the memory
FULL & EMPTY FLAG GENERATION FIFO FIFO full full and and almo almost st full full flag flagss are are gene genera rate ted d by Write Control Control Logic Logic whereas empty and almost empty flags are generated by Read Control 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 loca locati tion on at bo both th full full and and empt empty y cond condit itio ions ns.. Th Ther eref efor ore, e, in orde orderr to diffe differe rent ntia iate te betw betwee een n the the two two on onee extr extraa bit bit is adde added d to read read and and writ writee 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]) ); assign fifo_empty = (read_ptr[8 : 0] == write_ptr[8 : 0]);
Following piece of verilog code shows logic almost full generation:
// Generating fifo almost full status always @* begin if ( write_ptr[8] == read_ptr[8] ) fifo_afull = ((write_ptr[7:0] - read_ptr[7:0]) >= (DEPTH - AFULL)); else fifo_afull = ((read_ptr[8:0] - write_ptr[8:0]) <= AFULL); end Here AFULL signifies the almost full-level. User can set it to 4, 8 or whatever value depending on how soon it wants to intimate the source about impend impending ing full full condit condition ion.. ( AFULL=4) mean meanss almo almost st full full flag flag will will get get asserted when at most 4 locations are left for new data.
Following piece of verilog code shows logic almost empty generation:
//assigning fifo almost empty
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.
OVERALL SEQUENCE OF OPERATIONS OPERATIONS •
At rese reset, t, bo both th read read and and writ writee po poin inte ters rs are are 0. Th This is is the the empt empty y condition of the FIFO, and fifo_empty is pulled high and fifo_full is low
•
At empty, empty, reads are blocked and only operation possible is write
•
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
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 ith the the help help of FIFO FIFO full full and and empt empty y flag flagss data data inte integr grit ity y is maintained between the source and the requestor
RTL REPRESENTA REPRESENTATION OF SYNCHRONOUS FIFO Verilog HDL has been used to represent the design at Register Transfer Level. The top-level design sync_fifo has been partitioned into 3 logical blocks: •
write_control_logic
•
read_control_logic
•
mem_array
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 bench is a virtua virtuall enviro environm nment ent used used to verify verify the corre correctn ctness ess 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.
A testbench typically includes the following components: •
Input stimulus block
•
Transactor/bus Transactor/bus functional models
•
Design under test (DUT)
•
Output checker block
INPUT STIMULUS BLOCK
OUTPUT CHECKER BLOCK
Figure 7: Simplified View of a Typical Testbench
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.
Different aspects of the test bench sync_fifo_tb are as follows: •
Parameterized clock generator block
•
Reset signal generator
•
16-bit LFSR counter to generate 16-bit pseudo-random data
•
16 bit input data is generated using maximum length LFSR
•
LFSR bits are also used to generate source_ready and read_req signals
•
FSM to generate wdata_valid signal which uses source_ready as input
•
Source and destination buffers to store each data word sent to FIFO and read out of FIFO respectively. The content of these buffers are compared continuously to assert/de-assert MATCH flag
A complete verilog verilog description of the testbench is present in Appendix A2 .
25
SIMULATION We used Cadence NC-SIM simulator to simulate si mulate our Synchronous FIFO TB. The results are shown below:
FIFO FULL & ALMOST FULL FLAGS GENERATION
Yellow circle shows FIFO full and almost full flags getting asserted and deasserted depending on the values of write and read pointers. Note that when FIFO full is asserted except for the MSBs the pointer values are same.
FIFO EMPTY & ALMOST EMPTY FLAG GENERATION
You can see the yellow circle which shows how FIFO empty signals are getting asserted and de-asserted depending on the read and write pointer values. The red circle shows almost empty flag assertion and de-assertion. This snapshot is depicting two scenarios: firstly full and almost full both are asserted and secondly almost full is asserted but full is not. 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 rece receiv ived ed at the the ou outp tput ut of FIFO FIFO.. Th They ey shou should ld matc match. h. Th Thee resu result lt of this this comparison is the match signal signal shown in the snapshot. 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 represent representation ation of the design which is often referred referred to as netlist. It tries its bes bestt to meet meet the the user user defi define ned d cons constr trai aint ntss whil whilee gene genera rati ting ng the the netl netlis istt 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 representation of the design
•
Timing report: reports whether it met the timing constraint or not. If not details of the timing violations
•
Area Area repo report rt:: repo report rtss appr approx oxim imat atee area area of the the desi design gn,, nu numb mber er 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
Thee cons Th constr trai aint ntss are are the the go goal alss that that the the synt synthes hesis is tool tool trie triess to meet meet.. For For exam exampl ple, e, we may may have have a desi design gn that that is tar targete geted d for for seve severa rall dif differe ferent nt applications with different requirements: •
Timing Timing is most important; area is not a concern.
•
Power and area are more important; and timing is less so.
•
Timing, iming, area, area, and power are all import important ant,, and we have have specif specific ic measures for each.
STANDARD CELL LIBRARY
Standard Cell Library is a collection of basic building blocks or standard cells targeted to a specific semiconductor process technology. technology.
SYNTHESIS OF THE FIFO DESIGN Synthesis of the FIFO design involves the following: •
Creating the design constraints file o
Since there is a single clock controlling all the logic only one timing constraint is needed
•
Choosing the standard cell library o
•
TSMC library targeted to 65nm technology node is chosen
Choosing the Synthesis Tool o
Cadence RTL compiler is chosen for this 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 set_max_leakage_power 0 set_driving_cell -lib_cell -lib_cell BUFFD4 -library -library tcbn65lpwc -pin Z [find [find / -port */ports_in/*] set_load -pin_load 0.05 [get_ports *] create_clock [find [find / -port clk] clk] -name clk -period 5 -waveform {0 2.5} set_clock_uncertainty set_clock_uncertainty 2 clk set_input_delay -clock clk -min 2 [get_ports *] set_output_delay -clock clk -min 2 [get_ports *] ***************************** ******************************************** ***************************** ***************** ***
SYNTHESIS RUN SCRICPT
These are commands given to RTL compiler to perform various synthesis tasks. Below is the synthesis and run script for sync_fifo sync_fifo ***************************** ******************************************** ***************************** ***************** *** rc:/>include load_etc.tcl rc:/>set_attribute rc:/>set_attribute library tcbn65lpwc.lib" tcbn65lpwc.lib" rc:/>read_hdl rc:/>read_ hdl -v2001 "../RTL/SYNC_FIFO/mem_array.v "../RTL/SYNC_FIFO/ mem_array.v \ ../RTL/SYNC_FIFO/read_control_logic.v \ ../RTL/SYNC_FIFO/sync_fifo.v \ ../RTL/SYNC_FIFO/write_control_logic.v" rc:/>elaborate
31
rc:/>check_design rc:/>check_design > ../REPORTS/check_design.r ../REPORTS/check_design.rpt pt rc:/>read_sdc ../SCRIPTS/constraints.sdc ../SCRIPTS/constraints.sdc rc:/>report timing -lint > ../REPORTS/timing_lint.rpt synthesize -to_mapped rc:/>write_hdl rc:/>write_hdl > ../NETLIST/sync_fifo_net ../NETLIST/sync_fifo_netlist.v list.v rc:/>report timing -num_paths 100 > ../REPORTS/timing.rpt ../REPORTS/timing.rpt ***************************** ******************************************** ***************************** ***************** ***
32
RESULTS
It can be observed that there is a positive slack of 776ps (see the yellow circle circle)) for the worst worst case case path. path. So the synthe synthesis sis comfor comfortab tably ly meets 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:
•
How to write RTL codes using Verilog HDL
•
How to write behavioral codes using Verilog HDL to develop testbenches
•
Design of basic logic elements like half adders, full adders, counters, Finite State Machines, sequence detectors etc.
•
Design and application of Synchronous FIFO
•
Basic difference between Synchronous & Asynchronous Asynchronous FIFO
•
How to develop testbench and run simulations to verify the correctness of your design (using Cadence NC-SIM)
•
How to synthesize an RTL design to a gate-level design subject to user defined constraints (using Cadence RTL Compiler)
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 TOP LEVEL MODULE
//*************************** //****************************************** ***************************** *****************// ***// // File Name: sync_fifo.v // Module Name: sync_fifo // Description: Synchronous FIFO // Author: Asim Anand // Place: Cadence Design Systems, Inc. // Date: July 10, 2008 //*************************** //****************************************** ***************************** *****************// ***// module sync_fifo #( parameter ADDR_WIDTH ADDR_WIDTH = 4, parameter DAT DATA_WIDTH = 16, parameter DEPTH = 16, parameter AEMPTY = 3, parameter AFULL = 3 ) ( // Inputs input clk, input reset_n, input flush, input read_req, input [DAT [DATA_WIDTH-1:0] A_WIDTH-1: 0] write_data, input wdata_valid, // Outputs output [DAT [DATA_WIDTH-1:0] A_WIDTH-1: 0] output output output output output output
read_data, rdata_valid, fifo_empty, fifo_aempty, fifo_full, fifo_afull, write_ack 35
); wire [ADDR_WIDTH:0] [ADDR_WIDTH:0] read_ptr; wire [ADDR_WIDTH:0] [ADDR_WIDTH:0] write_ptr; wire read_enable; wire write_enable; write_control_logic 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 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_ARRA U_MEM_AR RAY Y ( .write_addr(write_ptr[ADDR_ .write_addr(write_ptr[ADDR_WIDTH-1:0]), WIDTH-1:0]), .read_addr(read_ptr[ADDR_WI .read_addr(read_ptr[ADDR_WIDTH-1:0]), DTH-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 //*************************** //****************************************** ***************************** *****************// ***// READ CONTROL LOGIC
//*************************** //****************************************** ***************************** *****************// ***// // File Name: read_control_logic.v read_control_logic.v // Module Name: read_control_logic // Description: Controls the read operation of sync_fifo. Generates // FIFO empty & almost empty flags. // Author: Asim Anand // Place: Cadence Design Systems, Inc. // Date: July 8, 2008 //*************************** //****************************************** ***************************** *****************// ***// module read_control_logic #( parameter ADDR_WIDTH ADDR_WIDTH = 4, parameter AEMPTY = 3, parameter DEPTH = 16 ) ( // Inputs input [ADDR_WIDTH:0] [ADDR_WIDTH: 0] write_ptr, input clk, input reset_n, input flush, input read_req, // Outputs output output reg output output reg output reg [ADDR_WIDTH:0] [ADDR_WIDTH:0]
read_enable, rdata_valid, fifo_empty, fifo_aempty, read_ptr
); wire [ADDR_WIDTH-1:0] read_addr; 37
wire [ADDR_WIDTH-1:0] write_addr; // Extracting read and write address from corrosponding pointers assign read_addr = read_ptr [ADDR_WIDTH-1:0]; [ADDR_WIDTH-1:0]; assign write_addr write_addr = write_ptr write_ptr [ADDR_WIDTH-1:0]; [ADDR_WIDTH-1:0]; //FIFO is empty when read pointer is same as write pointer assign fifo_empty = (read_ptr == write_ptr); // No read when FIFO is empty assign read_enable read_enable = read_req && (~fifo_empty); (~fifo_empty);
// Logic to generate almost empty flag always @* begin if (read_ptr[ADDR_WIDTH] (read_ptr[ADDR_WIDTH] == write_ptr[ADDR_WIDTH]) write_ptr[ADDR_WIDTH]) fifo_aempty = ((write_addr - read_addr) <= AEMPTY); else fifo_aempty = ((read_addr - write_addr) >= (DEPTH - AEMPTY)); AEMPTY)); end
// Read pointer and read data valid generation logic always @(posedge clk or negedge reset_n) begin if (~reset_n) read_ptr <= {(ADDR_WIDTH+1){1'b0}}; {(ADDR_WIDTH+1){1'b0}}; else if (flush) read_ptr <= {(ADDR_WIDTH+1){1'b0}}; {(ADDR_WIDTH+1){1'b0}}; else if (read_enable) begin read_ptr <= read_ptr + {{ADDR_WIDTH{1'b0}},1'b1}; {{ADDR_WIDTH{1'b0}},1'b1}; rdata_valid <= 1'b1; end else rdata_valid <= 1'b0; end endmodule 38
//*************************** //****************************************** ***************************** *****************// ***// WRITE CONTROL LOGIC
//*************************** //****************************************** ***************************** *****************// ***// // File Name: write_control_logic.v write_control_logic.v // Module Name: write_control_logic write_control_logic // Description: Controls the write operation of sync_fifo. Generates // FIFO full & almost full flags. // Author: Asim Anand // Place: Cadence Design Systems, Inc. // Date: July 10, 2008 //*************************** //****************************************** ***************************** *****************// ***// module write_control_logic #( parameter ADDR_WIDTH ADDR_WIDTH = 4, parameter AFULL = 3, parameter DEPTH = 16 ) ( // Inputs input [ADDR_WIDTH:0] [ADDR_WIDT H:0] read_ptr, input wdata_valid, input flush, input reset_n, input clk, // Outputs output reg write_ack, output write_enable, output reg [ADDR_WIDTH:0] write_ptr, output fifo_full, output reg fifo_afull );
wire [ADDR_WIDTH-1:0] write_addr; wire [ADDR_WIDTH-1:0] read_addr; // Extracting read and write addresses 39
assign read_addr = read_ptr[ADDR_WIDTH-1:0]; read_ptr[ADDR_WIDTH-1:0]; assign write_addr write_addr = write_ptr[ADDR_WI write_ptr[ADDR_WIDTH-1:0]; DTH-1:0];
// Generating write enable // No write when FIFO is full assign write_enable = wdata_valid && (~fifo_full); // Generating fifo full status // FIFO full is asserted when both pointers point to same address but their // MSBs are different assign fifo_full = ( (write_addr == read_addr) && (write_ptr[ADDR_WIDTH] (write_ptr[ADDR_WIDTH] ^ read_ptr[ADDR_WIDTH]) read_ptr[ADDR_WIDTH]) );
// Generating fifo almost full status always @* begin if (write_ptr[ADDR_WIDTH] (write_ptr[ADDR_WIDTH] == read_ptr[ADDR_WIDTH]) read_ptr[ADDR_WIDTH]) fifo_afull = ((write_addr - read_addr) >= (DEPTH - AFULL)); AFULL)); else fifo_afull = ((read_addr - write_addr) <= AFULL); end
// Write pointer generation logic always @(posedge clk or negedge reset_n) begin if (~reset_n) begin write_ptr <= {(ADDR_WIDTH+1){1'b0}}; {(ADDR_WIDTH+1){1'b0}}; write_ack <= 1'b0; end else if (flush) begin write_ptr <= {(ADDR_WIDTH+1){1'b0}}; {(ADDR_WIDTH+1){1'b0}}; write_ack <= 1'b0; end else if (write_enable) (write_enable) begin 40
write_ptr <= write_ptr + {{ADDR_WIDTH{1'b0}},1'b1}; {{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 ADDR_WIDTH = 4, parameter DEPTH = 16, parameter DAT DATA_WIDTH = 16 ) ( input [ADDR_WIDTH-1:0] [ADDR_WIDT H-1:0] write_addr, write_add r, input [ADDR_WIDTH-1:0] [ADDR_WIDT H-1:0] read_addr, input write_enable, input read_enable, input clk, input [DAT [DATA_WIDTH-1:0] A_WIDTH-1: 0] write_data, write_data , output reg [DAT [DATA_WIDTH-1:0] A_WIDTH-1: 0] read_data ); reg [DATA_WIDTH-1:0] mem [0:DEPTH-1];
41
// Mem write always @(posedge clk) begin if (write_enable) (write_enable) mem[write_addr] mem[write_addr] <= write_data; end // Mem Read always @(posedge clk) begin if (read_enable) begin read_data <= mem[read_addr]; 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; //generating clk signal; initial begin clk=1'b0; forever begin #100 clk=~clk; end end
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[14:0], ~(lfsr_count[15] ~(lfsr_count[15] ^ lfsr_count[14] ^ lfsr_count[12] ^ lfsr_count[3])}; lfsr_count[3])}; end // generating ready, count_enable and read request signal assign ready = lfsr_count[0] | lfsr_count[3]; lfsr_count[3]; assign read_req = lfsr_count[7] | lfsr_count[13]; lfsr_count[13]; assign count_enable = (ready) && (~fifo_full); //generating 16 bit input data always @(posedge clk or negedge reset_n) begin if(~reset_n) data_in<={{15{1'b0}},1'b1}; else if(count_enable) if(count_enable) data_in[15:0]<={data_in[1 data_in[15:0]<={data_in[14:0],data_in[15]^d 4:0],data_in[15]^data_in[14]}; ata_in[14]}; else data_in<=data_in; end //destination logic.... clk,reset_n,flush are same as in source logic wire [15:0] data_out; wire rdata_valid; wire fifo_empty; wire fifo_aempty; 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]; 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] source_array[counter] <= data_in; counter <= counter + {{10{1'b0}},1'b1}; {{10{1'b0}},1'b1}; end end
45
//destination array reg [15:0] destination_array[0:2047]; reg [10:0] counter1; always @(posedge clk or negedge reset_n) begin if(~reset_n) counter1 <= {11{1'b0}}; else if(rdata_valid) if(rdata_valid) begin destination_array[counter1] destination_array[counter1] <= data_out; counter1 <= counter1 + {{10{1'b0}},1'b1}; end end
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]); destination_array[i]); end
// FSM to generate data valid signal reg cs; reg ns; localparam idle = 1'b0; localparam active = 1'b1; 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) if((~fifo_full) && (~ready)) begin ns = idle; data_valid = 1'b0; end else data_valid = 1'b1; end default: cs = idle; endcase end always @(posedge clk or negedge reset_n) begin if (~reset_n) cs <= idle; else cs <= ns; end endmodule //*************************** //****************************************** ***************************** *****************// ***//
47