Upload
ilango-jeyasubramanian
View
196
Download
4
Embed Size (px)
Citation preview
EEDG 6306
ASIC DESIGN OF
MINI-STEREO DIGITAL AUDIO PROCESSOR
UNDER SMIC 180NM TECHNOLOGY
FINAL PROJECT REPORT
ILANGO JEYASUBRAMANIAN - ixj150230
SABARISH SEKAR – sxs154930
INDEX
1 INTRODUCTION
2 HARDWARE IMPLEMENTATION
3 BLOCK DIAGRAM
4 PORT DESCRIPTION
5 DATA FORMATS
6 FINITE STATE MACHINE AND
OPERATING MODES OF MSDAP
7 PIN CONFIGURATION
9 COMPUTATION
10 SIMULATION WAVEFORM
1.INTRODUCTION:
1.1 What is ASIC design?
An application-specific integrated circuit (ASIC) is an integrated circuit (IC) customized for a
particular use, rather than intended for general-purpose use. For example, a chip designed to run
in a digital voice recorder or a high-efficiency Bitcoin miner is an ASIC. Application-specific
standard products (ASSPs) are intermediate between ASICs and industry standard integrated
circuits like the 7400 or the 4000 series.
As feature sizes have shrunk and design tools improved over the years, the maximum complexity
(and hence functionality) possible in an ASIC has grown from 5,000 gates to over 100 million.
Modern ASICs often include entire microprocessors, memory blocks including ROM, RAM,
EEPROM, flash memory and other large building blocks. Such an ASIC is often termed a SoC
(system-on-chip). Designers of digital ASICs often use a hardware description language (HDL),
such as Verilog or VHDL, to describe the functionality of ASICs.
The main steps in the ASIC physical design flow are:
Design Netlist (after synthesis)
Floorplanning
Partitioning
Placement
Clock-tree Synthesis (CTS)
Routing
Physical Verification
GDS II Generation
These steps are just the basics. There are detailed PD flows that are used depending on the Tools
used and the methodology/technology. Some of the tools/software used in the back-end design
are :
Cadence (Cadence Encounter RTL Compiler, Encounter Digital Implementation, Cadence
Voltus IC Power Integrity Solution, Cadence Tempus Timing Signoff Solution)
Synopsys (Design Compiler, IC Compiler)
Magma (BlastFusion, etc.)
Mentor Graphics (Olympus SoC, IC-Station, Calibre)
A more detailed Physical Design Flow is shown below. Here you can see the exact steps and the
tools used in each step outlined.
1.2 What is Physical Design?
Physical design steps
Floorplanning
The first step in the physical design flow is Floorplanning. Floorplanning is the process of
identifying structures that should be placed close together, and allocating space for them in such a
manner as to meet the sometimes conflicting goals of available space (cost of the chip), required
performance, and the desire to have everything close to everything else.
Based on the area of the design and the hierarchy, a suitable floorplan is decided upon.
Floorplanning takes into account the macros used in the design, memory, other IP cores and their
placement needs, the routing possibilities and also the area of the entire design. Floorplanning also
decides the IO structure, aspect ratio of the design. A bad floorplan will lead to waste-age of die
area and routing congestion.
In many design methodologies, Area and Speed are considered to be things that should be traded
off against each other. The reason this is so is probably because there are limited routing resources,
and the more routing resources that are used, the slower the design will operate. Optimizing for
minimum area allows the design to use fewer resources, but also allows the sections of the design
to be closer together. This leads to shorter interconnect distances, less routing resources to be used,
faster end-to-end signal paths, and even faster and more consistent place and route times. Done
correctly, there are no negatives to floorplanning.
As a general rule, data-path sections benefit most from floorplanning, and random logic, state
machines, and other non-structured logic can safely be left to the placer section of the place and
route software.
Data paths are typically the areas of your design where multiple bits are processed in parallel with
each bit being modified the same way with maybe some influence from adjacent bits. Example
structures that make up data paths are Adders, Subtractors, Counters, Registers, and Muxes.
Partitioning
Partitioning is a process of dividing the chip into small blocks. This is done mainly to separate
different functional blocks and also to make placement and routing easier. Partitioning can be done
in the RTL design phase when the design engineer partitions the entire design into sub-blocks and
then proceeds to design each module. These modules are linked together in the main module called
the TOP LEVEL module. This kind of partitioning is commonly referred to as Logical Partitioning.
Placement
Before the start of placement optimization all Wire Load Models (WLM) are removed. Placement
uses RC values from Virtual Route (VR) to calculate timing. VR is the shortest Manhattan distance
between two pins. VR RCs are more accurate than WLM RCs.
Placement is performed in four optimization phases:
Pre-placement optimization
In placement optimization
Post Placement Optimization (PPO) before clock tree synthesis (CTS)
PPO after CTS.
Pre-placement Optimization optimizes the netlist before placement, HFNs are collapsed. It can
also downsize the cells.In-placement optimization re-optimizes the logic based on VR. This can
perform cell sizing, cell moving, cell bypassing, net splitting, gate duplication, buffer insertion,
area recovery. Optimization performs iteration of setup fixing, incremental timing and congestion
driven placement.Post placement optimization before CTS performs netlist optimization with ideal
clocks. It can fix setup, hold, max trans/cap violations. It can do placement optimization based on
global routing. It re does HFN synthesis.Post placement optimization after CTS optimizes timing
with propagated clock. It tries to preserve clock skew.
Clock tree synthesis
Ideal clock before CTS
The goal of clock tree synthesis (CTS) is to minimize skew and insertion delay. Clock is not
propagated before CTS as shown in the picture. After CTS hold slack should improve. Clock tree
begins at .sdc defined clock source and ends at stop pins of flop. There are two types of stop pins
known as ignore pins and sync pins. ‘Don’t touch’ circuits and pins in front end (logic synthesis)
are treated as ‘ignore’ circuits or pins at back end (physical synthesis). ‘Ignore’ pins are ignored
for timing analysis. If clock is divided then separate skew analysis is necessary.
Global skew achieves zero skew between two synchronous pins without considering logic
relationship.
Local skew achieves zero skew between two synchronous pins while considering logic
relationship.
If clock is skewed intentionally to improve setup slack then it is known as useful skew.
Rigidity is the term coined in Astro to indicate the relaxation of constraints. Higher the rigidity
tighter is the constraints.
Clock After CTS
In clock tree optimization (CTO) clock can be shielded so that noise is not coupled to other signals.
But shielding increases area by 12 to 15%. Since the clock signal is global in nature the same metal
layer used for power routing is used for clock also. CTO is achieved by buffer sizing, gate sizing,
buffer relocation, level adjustment and HFN synthesis. We try to improve setup slack in pre-
placement, in placement and post placement optimization before CTS stages while neglecting hold
slack. In post placement optimization after CTS hold slack is improved. As a result of CTS lot of
buffers are added. Generally for 100k gates around 650 buffers are added.
Routing
There are two types of routing in the physical design process, global routing and detailed routing.
Global routing allocates routing resources that are used for connections. It also does track
assignment for a particular net.
Detailed routing does the actual connections. DIffrent constraints that are to be taken care during
the routing are DRC, wire length, timing etc.
Physical Verification
Physical verification checks the correctness of the generated layout design. This includes verifying
that the layout
Complies with all technology requirements – Design Rule Checking (DRC)
Is consistent with the original netlist – Layout vs. Schematic (LVS)
Has no antenna effects – Antenna Rule Checking
This also includes density verification at the full chip level...Cleaning density is a very critical step
in the lower technology nodes
Complies with all electrical requirements – Electrical Rule Checking (ERC).[5]
1.3 What is a Digital Signal Processing?
Digital Signal Processing (DSP) is the study of digital representation of signals. This is a technique
intended to analyze and process real time signals (or analog signals). Analog signals are those,
which are represented for all values of time. Digital Signals are obtained from analog signals by a
process called Sampling, which involves extracting sample values of the analog signals at regular
intervals of time. This process is called Analog-to-Digital Conversion and the system performing
this activity is called the Analog-to-Digital Converter (ADC).
DSP makes use of mathematical methods in order to handle and analize the object of study, which
are the signals. The use of such mathematical methods allow us to extract information and even
modify the signal, in order to use it as we desire. One may ask why is DSP so widespread today
and applied in everything around us. The reason is quite simple: there are digital computers at any
corner wherever we go. The ease of getting a computer today is so high that almost anyone is able
to have such a tool at home. Since digital computers are able to represent only finite quantities,
digital signal processing methods developed so fast and had been so widespread.
1.4 How digital signal processing is implemented in hearing aid
application?
When digital signal processing in hearing aids is used, a number of very interesting phenomena
occur. The conventional wisdom goes something like this: The acoustic signal is converted to its
electrical analog at the microphone stage of the hearing aid system. After this conversion, a
frequency filter is introduced to reduce possible distortion of the input signal. The signal is then
"sampled" a given number of times per second. Normally, the sampling rate is 10,000 times per
second, or greater.
The analog signal is then converted to its digital equivalent by the analog to digital (A/D)
converter. Each samples receives a digital code. Binary numbers (O and 1) are used to represent
the digital value of each sample. Following the digitization of the signal, the digital representations
are processed by a central processing unit (CPU) or microprocessor. The digital values can be
multiplied, divided, added, subtracted and grouped in defined ways. In the microprocessor are
various algorithms. An algorithm is a system of instructions that operates in a manner determined
by a set of mathematical rules and equations. If the algorithm is a dedicated one, it performs a
specific task relative to the processing of the input signal. For example, one algorithm may control
the frequency response of the instrument, another may control loudness growth, a third may
function to enhance the speech signal in a background of noise, etc. After the microprocessor has
performed its tasks, the digitized signal must be converted back to its analog equivalent. This is
accomplished at the digital to analog (D/A) conversion stage. When the digitized signal is
converted to its analog stage, it is frequency filtered again, to prevent signal distortion. It is then
amplified in the conventional manner and submitted to the receiver (speaker) of the hearing aid.
(Note: For some of the more recent DSP systems, the D/A conversion does not require a separate
circuit. Rather, it uses the hearing aid receiver to accomplish digital to analog conversion. This
process is referred to as a Direct Digital Drive.)
The obvious advantage of digital signal processing is that there are unlimited ways in which the
signal can be manipulated. The number of parameters that can be utilized, and that can be utilized
at the same instant in time, are significantly greater than those found in conventional analog
systems. As such, the ability to manipulate the signal to more closely approximate the acoustic
needs of the patient is greatly enhanced.
2.HARDWARE IMPLEMENTATION
The main function of this MSDAP processor is a two-channel, 512 order, finite impulse
response (FIR) digital filter. It receives 16-bit voice data (sampled at 768 kHz) and computes the
FIR result at the speed of 94.33MHz. The chip computes the following linear convolution:
𝒚(𝒏) = ∑ 𝒉(𝒌)×𝒙(𝒏 − 𝒌)
𝑵
𝒌=𝟎
where x(n) and y(n) are input and output audio sequences, and h(k) are filter coefficients with
the filter order 512.
However, in order to reduce the hardware complexity, the multiplications are avoided
by replacing multiplications with shift operations. This is done by taking power-of-two digits as
filter coefficients for computation.
ℎ(𝑘)×𝑥(𝑛 − 𝑘) = 2−3𝑥(𝑛 − 𝑘) − 2−7𝑥(𝑛 − 𝑘) + 2−16𝑥(𝑛 − 𝑘)
The Finite state machine designed represents the following system block diagram with one MSDAP
block and a controller communicated in an asynchronous manner with the following input and output
ports.
PORT SPECIFICATION:
INPUT SIGNALS : Sclk, Dclk, Start, Reset_n, InputL, InputR, Frame
OUTPUT SIGNALS: InReady, OutReady, OutputL, OutputR
CLOCKS : Sclk, Dclk
FREQUENCY OF DCLK: 768KHz
FREQUENCY OF SCLK : 94.33Hz
3.BLOCK DIAGRAM:
Figure. 1 Block diagram
4.PORT DESCRIPTION
1. SCLK : The fast Sclk clock signal is used for fast computation purpose in such a way that the output
gets computed and sent before the arrival of the next input signal. We decide to use a frequency of
94.33 Mhz allowing us to compute sequentialy with each Sclk cycle faster with less memory in
the chip design. Sclk is also used for sending output bits on both left and right channel to the controller with Outready set high for giving info to the controller that its sending valid outputs.
2. DCLK: The slow Dclk clock signal is used for sending left and right channel input bits from the
controller at a frequency of 768Khz with the frame signal set high by the controller to detect the
start of each voice input to be processed. The Dclk signal is also shut off to stall the input samples
coming on both the left and right channels when reset signal is set low to clear the input and output
memory.
3.START : The start signal helps us to start the FSM by setting the state of the finite state machine to
state ‘0’ when the start signal is set “high”.
4.RESET_N: When reset is set low, Inready gets low, Dclk shuts off and stalls the controller from sending inputs
and the FSM goes to reset state ‘7’.
5.FRAME: Frame is an active low signal to align the coefficient, input and output sample start bits. When the
frame is 0, MSDAP receives data samples When Frame is asserted low, MSDAP starts receives
the Data samples. When frame is detected along with low Outready signal, it begins to send data.
It is used to align input with output. Frame is active high for every 16 cycles of Dclk. Active low
of the frame is in par with the rising edge of Dclk.
6.InputL and InputR
InputL and InputR are the inputs for two channels which transmits all the inputs bitwise. InputL and InputR are read on negative edge of Dclk on MSDAP. All the input samples, Rj values and Coefficient values are send to MSDAP through these channels.
4.2 OUTPUT SIGNALS
1. InReady
When MSDAP is ready to receive the data samples, InReady is set high. InReady is an active high signal. InReady is high in all States except State 0 and State 7. Filter coefficients and input samples the InReady must be made high, to receive RJ values, Coefficient values and input samples. It tells the MSDAP that there is a data in the input.
2. OutReady
When this signal is active, it indicates that the output sample bits are sent serially on OutputL and OutputR to the Controller. When the computation is complete and Frame is low, OutReady is set low so that MSDAP starts sending the output samples serially. It is generally an active low signal.
3. OutputL and OutputR
OutputL and OutputR are used to send the output from MSDAP serially. It is sent in negative edge of Sclk. Bit 39 is the LSB which is transmitted out first. They are very important to carry output to the controller.
SIGNAL FORMATS
5.DATA FORMATS
Note : Here all the datas are read starting from MSB.
1. RJ Value
Rj is a 16 bit value. MSB is the first value that is being received by the processor. First 8 bits ( 8-15) are unused.
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
MSB LSB
Fig. 4 Format of Rj
2. Filter Coefficients (CF)
Filter coefficient is of 16 bits. The bit 8 represents its sign. The first seven bits from the MSB are unused.
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
MSB LSB
Fig. 5 Format of Coefficients
3. Input Sample
The input sample is of 16 bits
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
MSB LSB
Fig. 6 Format of Input Sample
4. Output Sample
The output sample is of 40 bits. The first bit sent as output is bit 39 (MSB).
39 38 .. .. .. .. .. .. .. .. .. .. 3 2 1 0
MSB LSB
Fig. 7 Format of Output Sample
6. FINITE STATE MACHINE AND
OPERATING MODES OF MSDAP
INITIALIZATION_STATE: (state ‘0’): The active high start signal aids the MSDAP to start its state machine by setting the FSM
to state ‘0’. At state ‘0’, all of its memories gets initialized and switches to state ‘1’.
WAITING FOR Rj STATE(State’1’): After initialization, the FSM switches to state ‘1’ and waits for receiving Rj values after
setting the Inready high.
READING Rj STATE(State’2’): When the controller sees the Inready high, the controller starts sending the Rj values with
frame set high for indicating the start of the first Rj value and switches to state ‘3’.
WAITING FOR Coefficient STATE(State’3’):
After reading all the Rj values, the FSM switches to state ‘3’ and waits for receiving Coefficient
values after setting the Inready high.
READING Coefficient STATE(State’4’): When the controller sees the Inready high, the controller starts sending the Coefficient values with
frame set high for indicating the start of the first Coefficient value and switches to state ‘5’.
WAITING FOR InputSTATE(State’5’): After reading all the Coefficient values, the FSM switches to state ‘5’ and waits for receiving
Coefficient values after setting the Inready high.
READING Input STATE and WORKING STATE(State’6’): When the controller sees the Inready high, the controller starts sending the Input values at both
left and right channels with frame set high for indicating the start of the first input value at both
the channels and starts reading the inputs at both the channels.
RESET STATE(State’7’): We can see that when reset is set low, Inready gets low, Dclk shuts off and stalls the controller
from sending inputs and the FSM goes to reset state ‘7’. At the reset state, all the input and output
memory gets cleared and stays in reset state until reset remains low. When reset gets high at reset
state ‘7’, the chip goes to state ‘5’ and waits for receiving input samples after setting Inready high.
When the controller sets Inready high, it starts sending the next input with the frame set high to
indicate the start of the next input. The MSDAP sees the frame set high and goes to working state
and starts reading the next inputs.
SLEEPING STATE(State ‘8’): For going to sleep state, if we are receiving 800 continuous16-bit zeros (i.e 12800 zero input bits)
at both the left and right channels in the working state, we will switch to sleep state ‘8’ and stall
computing the outputs.we also constantly receive inputs without storing the data. At the first non-
zero 16-bit input, we will store this data as the next input and switch to the working state ‘6’. This
is done by temporarily storing the data in the registers “tempL” and “tempR” for checking if we
are receiving a non-zero 16-bit input
8.PIN CONFIGURATION
Fig.9 Pin configuration
9.COMPUTATION
𝑦(𝑛) = 2−1( … 2−1(2−1(2−1 𝑢1 + 𝑢2) + 𝑢3) + ⋯ ) + 𝑢16)
𝑢𝑗 = 𝑥𝑗(1) + 𝑥𝑗(2) + ⋯ + 𝑥𝑗(𝑟𝑗) 1 ≤ 𝑗 ≤ 16
Where
1)𝑥𝑗(𝑙) ∈ { ±𝑥(𝑛 − 𝑘)}, 1 ≤ 𝑙 ≤ 𝑟𝑗
2) 𝑟𝑗 is the total number of the POT digits ±2−𝑗 occurred among all the POT filter coefficients.
U1 to u16 is calculated based on the coefficient and Rj values as refered by the figure below.
Fig.10 Computation using Rj and Coefficients
So from the values of u1 to u16, y1 to y16 is calculated.
• The input
format for the
C-program of
Exercise 3-1.
• This format is
also adopted
late in the
implementation
of the MSDAP
chip.
10.MSDAP ARCHITECTURE
The MSDAP consists of following blocks:
1) Serial to parallel control
2) Main Controller
3) ALU
4) RJ memory Left
5) RJ memory Right
6) COEFF memory Left
7) COEFF memory Right
8) DATA memory Left
9) DATA memory Right
10) Sign extension Left
11) Sign Extension Right
12) Adder Left
13) Adder Right
14) Shifter Left
15) Shifter Right
16) Parallel to Serial Control
17) Zero Detector
FULL MSDAP BLOCK
FULL MSDAP SYMBOL
SERIAL TO PARALLEL CONVERTER
Inputs (Input L and Input R) from the file is fed into this module which converts the serial input
into parallel. This works with reference with the Dclk. Serial to parallel module receives the data
when it encounters low STP_enable signal. STP_ready is made high after receiving 16 bits so as
to indicate controller as it is ready to get the next 16 bits.Clear signal is used to indicate that
MSDAP has started to clear all its registers, which is generally used in the State 0.
SIGNALS USED IN THIS MODULE
INPUT SIGNALS AND DATA
STP_enable : Enables the serial to parallel conversion module
Dclk : Data clock signal
InputL : Left channel serial input bits
InputR : Right channel serial input bits
OUTPUT SIGNALS AND DATA
Data_parallel_left : Converted parallel left data
Data_parallel_right : Converted parallel right data
STP_ready : Indicates that parallel conversion is done and the corresponding
parallel data is ready.
ALU BLOCK
The entire arithmetic and logical operations are performed inside this block. This works in
correspondence with Sclk and Frame.
SIGNALS USED IN THE MODULE
INPUT SIGNALS AND DATA
ALU_enable :Enables the ALU unit
ALU_start :Brings the ALU to the start of its own sub-state machine.
Sclk :High frequency system clock signal for faster computation.
Frame :Indicates the start of the new data MSB bit.
FROM RJ BLOCK
RJ_ready_left :Indicates that data from RJ_memory_left is sent for the corresponding
RJ_address_left
RJ_ready_right :Indicates that data from RJ_memory_right is sent for the corresponding
RJ_address_right
RJ_out_left :The data coming out from RJ_memory_left for the corresponding
RJ_read_address_left
RJ_out_right:The data coming out from RJ_memory_right for the corresponding
RJ_read_address_right
FROM COEFF BLOCK
COEFF_ready_left :Indicates that data from COEFF_memory_left is sent for the
corresponding COEFF_address_left
COEFF_ready_right :Indicates that data from COEFF_memory_right is sent for the
corresponding COEFF_address_right
COEFF_out_left :The data coming out from COEFF_memory_left for the corresponding
COEFF_read_address_left
COEFF_out_right :The data coming out from COEFF_memory_right for the corresponding
COEFF_read_address_right
FROM DATA BLOCK
DATA_read_ready_left : Indicates that data from DATA_memory_left is sent for the
corresponding DATA_address_left
DATA_read_ready_right : Indicates that data from DATA_memory_left is sent for the
corresponding DATA_address_left
DATA_out_left : The data coming out from DATA_memory_left for the
corresponding DATA_read_address_left
DATA_out_right : The data coming out from DATA_memory_right for the
corresponding DATA_read_address_right
FROM ADDER BLOCK
Add_output_left :Adder output from left adder module
Add_output_right :Adder output from right adder module
FROM SHIFTER BLOCK
shift_output_left :Shifter output from left shifter module
shift_output_right :Shifter output from right shifter module
FROM SIGN EXTENTION BLOCK
SE_ready_left :Indicates that the left sign extension output is ready
SE_ready_right :Indicates that the right sign extension output is ready
SE_output_left :Output from the left sign extension module.
SE_output_right :Output from the right sign extension module
OUTPUT SIGNALS AND DATA
TO RJ MODULE
RJ_enable_left :Enables the RJ_memory_left for reading
RJ_enable_right :Enables the RJ_memory_right for reading
RJ_address_left :The address used for fetching the corresponding value from
RJ_memory_left
RJ_address_right :The address used for fetching the corresponding value from
RJ_memory_right
TO COEFF MODULE
COEFF_enable_left :Enables the COEFF_memory_left for reading
COEFF_enable_right :Enables the COEFF_memory_right for reading
COEFF_address_left :The address used for fetching the corresponding value from
COEFF_memory_left
COEFF_address_right :The address used for fetching the corresponding value from
COEFF_memory_left
TO DATA MODULE
DATA_read_enable_left :Enables the DATA_memory_left for reading
DATA_read_enable_right:Enables the DATA_memory_right for reading
DATA_readaddress_left :The address used for fetching the corresponding value from
DATA_memory_left
DATA_readaddress_right :The address used for fetching the corresponding value from
DATA_memory_right
TO ADDER MODULE
AddSub_left :AddSub_left select helps to select between addition or subtraction with
AddSub =’0’ and AddSub=’1’ correspondingly.
AddSub_right :AddSub_right select helps to select between addition or subtraction with
AddSub =’0’ and AddSub=’1’ correspondingly.
Add_Input1_left :First input for addition/subtraction at the left computation.
Add_Input1_right :First input for addition/subtraction at the right computation.
Add_Input2_left :Second input for addition/subtraction at the left computation.
Add_Input2_right :Second input for addition/subtraction at the left computation.
TO SHIFTER MODULE
shift_left :Enables the left 1-bit shifter module
shift_right :Enables the right 1-bit shifter module
shift_input_left :Input for the left shifter module
shift_input_right :Input for the right shifter module
TO SIGN EXTENSION MODULE
SE_enable_left :Enables the left sign_extension module
SE_enable_right :Enables the right sign_extension module
SE_input_left :Input for the left sign extension module
SE_input_right :Input for the right sign extension module
TO PARALLE-SERIAL MODULE
PTS_enable : Enables the parallel to serial conversion module
PTS_ready : Indicates that the parallel to serial conversion is ready
PTS_left : Left parallel input for serial left “OutputL”
PTS_right : Right parallel input for serial right “OutputR”
MSDAP CONTROLLER
The entire control operation of the MSDAP takes place inside this block. Start signal is used to
start the MSDAP. It also controls all other modules in MSDAP. When the Zero detector detects
800 zero samples, it sends out Sleep signal indicating that the controller enters sleep mode. When
Reset_n signal is low it, clears all registers.
SIGNALS USED IN THE MODULE
INPUT SIGNALS AND DATA
Dclk :Data clock signal for sampling the input bits
Sclk :High frequency system clock signal for faster computation.
Start :Start signal for assigning the main controller state to state ‘0’
Frame :Indicates the start of the new data MSB bit.
Reset_n :Indicates that the chip should be resetted when Reset_n =’1’
InputL :Left channel input bits
InputR :Right channel input bits
FROM SERIAL-PARALLEL MODULE
STP_ready :Indicates that parallel conversion is done and the corresponding
parallel data is ready.
FROM RJ MODULE
RJ_ready_left :Indicates that data from RJ_memory_left is sent for the
corresponding RJ_address_left
RJ_ready_right :Indicates that data from RJ_memory_right is sent for the
corresponding RJ_address_right
RJ_clear_ready_left :Indicates that RJ_memory_left is resetted successfully.
RJ_clear_ready_right :Indicates that RJ_memory_right is resetted successfully.
FROM COEFF MODULE
COEFF_ready_left :Indicates that data from COEFF_memory_left is sent for
the corresponding COEFF_address_left
COEFF_ready_right :Indicates that data from COEFF_memory_right is sent for
the corresponding COEFF_address_right
COEFF _clear_ready_left :Indicates that COEFF_memory_left is resetted
successfully.
COEFF _clear_ready_right :Indicates that COEFF _memory_right is resetted
successfully.
FROM DATA MODULE
DATA_write_ready_left :Indicates that data from DATA_memory_left is sent for the
corresponding DATA_writeaddress_left
DATA_write_ready_right :Indicates that data from DATA_memory_right is sent for the
corresponding DATA_writeaddress_right
DATA_clear_ready_left :Indicates that the entire DATA_memory_left is wiped out.
DATA_clear_ready_right :Indicates that the entire DATA_memory_left is wiped out.
OUTPUT SIGNALS AND DATA
Inready :Inraedy signals the MSDAP controller to send the coefficient and input
samples.
TO SERIAL-PARALLEL MODULE
STP_enable : Enables the serial to parallel conversion module
TO RJ MODULE
RJ_enable_left :Enables the RJ_memory_left for reading
RJ_enable_right :Enables the RJ_memory_right for reading
RJ_address_left :Indicates that data from RJ_memory_left is sent for the corresponding
RJ_address_left
RJ_address_right :Indicates that data from RJ_memory_right is sent for the corresponding
RJ_address_right
RJ_clear_enable_left :Enables the RJ_memory_left for resetting.
RJ_clear_enable_right :Enables the RJ_memory_right for resetting.
TO COEFF MODULE
COEFF_enable_left : Enables the COEFF_memory_left for reading
COEFF_enable_right : Enables the COEFF_memory_right for reading
COEFF_address_left :Indicates that data from COEFF_memory_left is sent for the
corresponding COEFF_address_left
COEFF_address_right :Indicates that data from COEFF_memory_right is sent for the
corresponding COEFF_address_right
RJ_clear_enable_left :Enables the RJ_memory_left for resetting.
RJ_clear_enable_right :Enables the RJ_memory_right for resetting.
TO DATA MODULE
DATA_write_enable_left :Enables the DATA_memory_left for writing
DATA_write_enable_right :Enables the DATA_memory_right for reading
DATA_clear_enable_left :Enables the DATA_memory_left for resetting
DATA_clear_enable_right :Enables the DATA_memory_right for resetting
DATA_writeaddress_left :Indicates the DATA_memory_left address where the input
DATA_in is to be written.
DATA_writeaddress_right :Indicates the DATA_memory_right address where the input
DATA_in is to be written.
TO ALU MODULE
ALU_enable :Enables the ALU unit
ALU_start :Brings the ALU to the start of its own sub-state machine.
RJ MODULE (LEFT AND RIGHT)
RJ module (memory), holds RJ values that are required for the computation. It works in
correspondence with Sclk. RJ_read_ready is sent from RJ values are read to ALU.
RJ_write_ready is enabled when RJ values are written from Controller to RJ module.
SIGNALS USED IN THE MODULE
INPUT SIGNALS USED IN THE MODULE
Sclk :High frequency system clock signal for faster computation.
RJ_write_enable :Enables the RJ_memory for writing
RJ_read_enable :Enables the RJ_memory_right for reading
RJ_readaddress :Indicates the address where RJ_memory is to be read and sent out to RJ_out
RJ_writeaddress :Indicates the address where RJ_out is to be written in RJ_memory
RJ_in :Input data where RJ_memory is to be written at RJ_writeaddress
RJ_clear_enable :Enables the RJ_memory for resetting.
OUTPUT SIGNALS USED IN THE MODULE
RJ_out :Ouput data where data from RJ_memory at the corresponding
RJ_readaddress is sent out.
RJ_write_ready :Indicates that RJ_memory is written successfully.
RJ_read_ready :Indicates that RJ_memory is read successfully.
RJ_clear_ready :Indicates that RJ_memory is resetted successfully.
COEFF MODULE(LEFT AND RIGHT)
Similar to RJ module, we get the COEFF values here. This works in correspondence with Sclk.
COEFF_read_ready is sent from COEFF values are read to ALU. COEFF_write_ready is
enabled when COEFF values are written from Controller to RJ module.
SIGNALS USED IN THE MODULE
INPUT SIGNALS USED IN THE MODULE
Sclk :High frequency system clock signal for faster computation.
COEFF_write_enable :Enables the COEFF_memory for writing
COEFF_read_enable :Enables the COEFF_memory_right for reading
COEFF_readaddress :Indicates the address where COEFF_memory is to be read and sent
out to COEFF_out
COEFF_writeaddress :Indicates the address where COEFF_out is to be written in
COEFF_memory
COEFF_in :Input data where COEFF_memory is to be written at
COEFF_writeaddress
COEFF_clear_enable :Enables the COEFF_memory for resetting.
OUTPUT SIGNALS USED IN THE MODULE
COEFF_out :Ouput data where data from COEFF_memory at the
corresponding COEFF_readaddress is sent out.
COEFF_write_ready :Indicates that COEFF_memory is written successfully.
COEFF_read_ready :Indicates that COEFF_memory is read successfully.
COEFF_clear_ready :Indicates that COEFF_memory is resetted successfully.
DATA MODULE(LEFT AND RIGHT)
Similar to RJ module, we get the DATA values here. This works in correspondence with Sclk.
DATA_read_ready is sent from data values are read to ALU. DATA_write_ready is enabled
when data values are written from Controller to data module.
SIGNALS USED IN THE MODULE
INPUT SIGNALS USED IN THE MODULE
Sclk :High frequency system clock signal for faster computation.
DATA_write_enable :Enables the DATA_memory for writing
DATA_read_enable :Enables the DATA_memory for reading
DATA_readaddress :Indicates the address where DATA_memory is to be read and sent
out to DATA_out
DATA_writeaddress :Indicates the address where DATA_out is to be written in
DATA_memory
DATA_in :Input data where DATA_memory is to be written at
DATA_writeaddress
DATA_clear_enable :Enables the DATA_memory for resetting.
OUTPUT SIGNALS USED IN THE MODULE
DATA_out :Ouput data where data from DATA_memory at the
corresponding DATA_readaddress is sent out.
DATA_read_ready :Indicates that DATA_memory is read successfully.
DATA_write_ready :Indicates that DATA_memory is written successfully.
DATA_clear_ready :Indicates that DATA_memory is resetted successfully.
SIGN EXTENSION(LEFT AND RIGHT)
Sign extension module is used to extend 16 bits to 40 bits. It works with respect to Sclk.
SE_enable enables this module. SE_input is enabled when the input is ready for sign
extension. SE_ready notifies that sign extension has been performed.
SIGNALS USED IN THE MODULE
INPUT SIGNALS USED IN THE MODULE
Sclk : High frequency system clock signal for faster computation.
SE_enable : Enables the sign_extension module
SE_input : Input for the sign extension module
OUTPUT SIGNALS USED IN THE MODULE
SE_ready : Indicates that the sign extension output is ready
SE_output: Output from the sign extension module.
SHIFTER(LEFT AND RIGHT)
Shifter module implements one bit shift.
SIGNALS USED IN THE MODULE
INPUT SIGNALS USED IN THE MODULE
Shift :Enables the shifter
shift_input :Input for shifter
OUTPUT SIGNALS USED IN THE MODULE
shift_output :Output from the shifter
ADDER MODULE (LEFT AND RIGHT)
This module adds or subtracts two 40 bit values. Based on addsub value, addition or subtraction
is performed.
SIGNALS USED IN THE MODULE
INPUT SIGNALS USED IN THE MODULE
AddSub :AddSub select helps to select between addition or subtraction with AddSub =’0’ and
AddSub=’1’ correspondingly
Input1 :First input for addition/subtraction computation
Input2 :Second input for addition/subtraction computation
OUTPUT SIGNALS USED IN THE MODULE
Output :Computed output from the adder module
PARALLEL TO SERIAL CONVERTER
This module is used to send output serially from MSDAP to controller. This block works in
correspondence with Sclk. When PTS_ready is low and Outready is low, it starts sending the
output through OUTPUTL and OUTPUTR serially. After sending every 40 bits, the outready
is made high.
SIGNALS USED IN THE MODULE
INPUT SIGNALS USED IN THE MODULE
PTS_enable :Enables the parallel to serial conversion module
Sclk :High frequency system clock signal for faster computation.
Frame :Indicates the start of the new data MSB bit.
PTS_left : Left parallel input for serial left “OutputL”
PTS_right : Right parallel input for serial right “OutputR”
OUTPUT SIGNALS USED IN THE MODULE
OutputL :Final serial left output bits for parallel input PTS_left
OutputR :Final serial right output bits for parallel input PTS_right
Outready :Outready indicates that valid output bits are sent at these Sclk cycles.
PTS_ready :Indicates that Parallel to serial conversion is done and output bits are sent
serially successfully.
ZERO DETECTOR
This module puts the MSDAP into sleep mode when it detects 800 consecutive zero samples.
RTL SIMULATION WAVEFORMS:
We can see that initially Inready is ‘0’. Hence the “Dclk” is shut off with no transfer of
inputs from the controller. When Start is set high, the FSM gets initialized to state ‘0’ and starts
the Rj, Coefficients and data memory initialization process.
After initialization, the FSM switches to state ‘1’ and waits for receiving Rj values after setting
the Inready high. When the controller sees the Inready high, the controller starts sending the Rj
values with frame set high for indicating the start of the first Rj value.
We can see that the frame is set high by the controller at the start of each Rj value to aid the
MSDAP to sample the Rj data accurately.
After reading all the Rj values, the FSM switches to state ‘3’ and waits for receiving Coefficient
values after setting the Inready high. When the controller sees the Inready high, the controller starts
sending the Coefficient values with frame set high for indicating the start of the first Coefficient
value.
We can see that the frame is set high by the controller at the start of each Coefficient value to aid
the MSDAP to sample the Coefficient data accurately.
After reading all the Coefficient values, the FSM switches to state ‘5’ and waits for receiving
Coefficient values after setting the Inready high. When the controller sees the Inready high, the
controller starts sending the Input values at both left and right channels with frame set high for
indicating the start of the first input value at both the channels.
We can see that the frame is set high by the controller at the start of each Input data value to aid
the MSDAP to sample the Input data accurately.
For going to sleep state, we used variables countL and countR to count at each zero input bit
reception at its corresponding left and right channels. The countL and countR gets resetted at any
non-zero bit reception at its corresponding left and right channels. If we are receiving 800
continuous16-bit zeros (i.e 12800 zero input bits) at both the left and right channels in the working
state, we will switch to sleep state ‘8’ and stall computing the outputs.
In the sleep state ‘8’, we constantly receive inputs without storing the data. At the first non-zero
16-bit input, we will store this data as the next input and switch to the working state ‘6’. This is
done by temporarily storing the data in the registers “tempL” and “tempR” for checking if we are
receiving a non-zero 16-bit input.
We can see that when reset is set low, Inready gets low, Dclk shuts off and stalls the controller
from sending inputs and the FSM goes to reset state ‘7’. At the reset state, all the input and output
memory gets cleared and stays in reset state until reset remains low. When reset gets high at reset
state ‘7’, the chip goes to state ‘5’ and waits for receiving input samples after setting Inready high.
When the controller sets Inready high, it starts sending the next input with the frame set high to
indicate the start of the next input. The MSDAP sees the frame set high and goes to working state
and starts reading the next inputs.
After each computation in the working state ‘6’, the corresponding output is sent at OutputL and
OutputR for the corresponding left and right channels.The MSB bit of the output is sent at the start
of the frame with Outready set high for the next 40 SClk cycles to send the corresonding 40 bit
output.
At the working state ‘6’, we can compute the first output only after receiving the first input. This
result in a delay in output computation by one input. Hence, the 512 size input data circular buffer
is not overwritten immediately after receiving the 513th input as we still need to compute the
corresponding 512th input. Hence, we temporarily store the new 513th input in the temporary
registers “DatawindtempL” and “DatawindtempR” for left and right channels correspondingly.
After the start of the 514th input, we would have completed the 513th output and hence its safe for
us to start storing the new inputs. Hence, we store the temporarily stored data as the 0th input and
start storing the 1st input in the data memory.
At the working state ‘6’, the computation is done with a single “U” register for ‘U0’ to ‘U16’
computation which is indexed as ‘jL’ and ‘jK’ in the waveform.
After each U computation, the corresponding Output shifting and addition is done before
computing the next U value. This helps in using a single “U” register for the whole computation
which can be seen from the “substateL” and “substateR” states for the corresponding left and right
channels.
substateL/substateR=2 for U computation
substateL/substateR=3 for shift computation
substateL/substateR=4 for add computation
substateL/substateR=5 represents that output is computed.
B. THE SCHEMATIC FOR EACH FUNCTIONAL BLOCK AND THE
CRITICAL PATH OF YOUR DESIGN.
MAIN CONTROLLER BLOCK
MAIN CONTROLLER SYMBOL
ALU BLOCK
ALU SYMBOL
SERIAL TO PARALLEL BLOCK
SERIAL TO PARALLEL SYMBOL
PARALLEL TO SERIAL BLOCK
PARALLEL TO SERIAL SYMBOL
ADDER BLOCK
ADDER SYMBOL
SHIFTER BLOCK
SHIFTER SYMBOL
SIGN EXTENSION BLOCK
SIGN EXTENSION SYMBOL
RJ MEMORY BLOCK
RJ MEMORY SYMBOL
COEFF SYMBOL
DATA SYMBOL
GATE LEVEL SIMULATION WAVEFORMS
Start Signal:
Input Signal:
Output Signal:
Outready Signal:
Reset Signal
Sleep Signal
DESIGN VISION TIMING, CELL AND AREA REPORTS
AREA REPORT
CELL REPORT
QOR REPORT
TIMING REPORT
RESOURCES REPORT
CRITICAL PATH
PHYSICAL DESIGN USING IC COMPILER:
LAYOUT AFTER READING THE LIBRARY AND FILES:
LAYOUT AFTER FLOORPLANNING
LAYOUT AFTER INSERTING PAD FILLERS:
LAYOUT AFTER ADDING VDD AND VSS RINGS:
LAYOUT AFTER ADDING POWER STRAPS:
LAYOUT AFTER PLACEMENT:
LAYOUT AFTER CLOCK TREE SYNTHESIS:
ROUTING:
FINAL LAYOUT ROUTING:
DESIGN RULE CHECK:
COMPARISON FOR BEST UTILIZATION OF DESIGN:
FIRST DESIGN:
CORE UTILIZATION: 60%
LEFT MARGIN BETWEEN I/O AND CORE: 20
RIGHT MARGIN BETWEEN I/O AND CORE: 20
BOTTOM MARGIN BETWEEN I/O AND CORE: 20
TOP MARGIN BETWEEN I/O AND CORE: 20
FIRST DESIGN UTILITY REPORT:
FIRST DESIGN POWER REPORTS:
SECOND DESIGN:
CORE UTILIZATION: 70%
LEFT MARGIN BETWEEN I/O AND CORE: 17
RIGHT MARGIN BETWEEN I/O AND CORE: 17
BOTTOM MARGIN BETWEEN I/O AND CORE: 17
TOP MARGIN BETWEEN I/O AND CORE: 17
SECOND DESIGN UTILITY REPORT:
POWER REPORTS:
DESIGN COMPARISON:
CONTENTS DESIGN 1 DESIGN 2
CORE UTILIZATION 60% 70%
MARGINS BETWEEN I/O
AND CORE AT ALL SIDES 20 17
SCLK FREQUENCY 29.186Mhz 29.186Mhz
NUMBER OF CELLS 167 161
DESIGN AREA 1.51mm2 1.29mm2
TOTAL DYNAMIC
POWER
3.1878mW 3.1438mW
CELL LEAKAGE POWER 80.7425uW 77.4048uW
From the data sheet above, we concluded that design ‘2’ with 70% utilization is the best one we
could possibly get with our design, as further increase in core utilization caused errors in layout
design rules. The following are the timing reports for design ‘2’:
SETUP TIME REPORTS:
HOLD_TIME_REPORTS:
RTL_CODE:
TOP_MODULE:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 10:25:10 11/03/2016
// Design Name:
// Module Name: MSDAP_top
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module MSDAP_top(Dclk, Sclk, Start, Frame, Reset_n, InputL, InputR, OutputL, OutputR,
InReady, OutReady);
input Dclk, Sclk, Start, Frame, Reset_n;
input InputL, InputR;
output OutputL, OutputR, InReady, OutReady;
//////////////STP
wire STP_initial, STP_enable, STP_ready;
wire [15:0] Data_parallel_left, Data_parallel_right;
/////////////RJ
wire RJ_initial_left, RJ_clear_enable_left, RJ_clear_ready_left, RJ_read_enable_left,
RJ_write_enable_left, RJ_read_ready_left, RJ_write_ready_left,
RJ_initial_right, RJ_clear_enable_right, RJ_clear_ready_right, RJ_read_enable_right,
RJ_write_enable_right, RJ_read_ready_right, RJ_write_ready_right;
wire [31:0] RJ_writeaddress_left, RJ_writeaddress_right;
wire [3:0] RJ_readaddress_left, RJ_readaddress_right;
wire [15:0] RJ_out_left, RJ_out_right;
/////////////COEFF
wire COEFF_initial_left, COEFF_clear_enable_left, COEFF_clear_ready_left,
COEFF_write_enable_left, COEFF_write_ready_left,
COEFF_initial_right, COEFF_clear_enable_right, COEFF_clear_ready_right,
COEFF_write_enable_right, COEFF_write_ready_right;
wire [31:0] COEFF_writeaddress_left, COEFF_writeaddress_right;
wire [9:0] COEFF_readaddress_left, COEFF_readaddress_right;
wire [8:0] COEFF_out_left, COEFF_out_right;
////////////DATA
wire DATA_initial_left, DATA_write_enable_left, DATA_write_ready_left,
DATA_clear_enable_left, DATA_clear_ready_left,
DATA_initial_right, DATA_write_enable_right, DATA_write_ready_right,
DATA_clear_enable_right, DATA_clear_ready_right;
wire [31:0] DATA_writeaddress_left, DATA_writeaddress_right;
wire [9:0] DATA_readaddress_left, DATA_readaddress_right;
wire [15:0] DATA_out_left, DATA_out_right;
wire [31:0] count_left, count_right;
///////////SIGN EXTENSION
wire [15:0] SE_input_left, SE_input_right;
wire [39:0] SE_output_left, SE_output_right;
wire SE_initial_left, SE_initial_right;
//////////ADDER
wire AddSub_left, AddSub_right;
wire [39:0] Add_Input1_left, Add_Input1_right, Add_Input2_left, Add_Input2_right,
Add_output_left, Add_output_right;
/////////SHIFTER
wire [39:0] shift_input_left, shift_input_right, shift_output_left, shift_output_right;
wire shift_initial_left, shift_initial_right;
////////PARALLEL TO SERIAL
wire PTS_enable, PTS_ready, PTS_initial;
wire [39:0] PTS_left, PTS_right;
/////////ALU
wire ALU_enable, ALU_start, ALU_initial;
MSDAP_controller controller
(
.Dclk(Dclk),
.Sclk(Sclk),
.Start(Start),
.Frame(Frame),
.Reset_n(Reset_n),
.Inready(InReady),
.STP_enable(STP_enable),
.STP_ready(STP_ready),
.RJ_initial_left(RJ_initial_left),
.RJ_initial_right(RJ_initial_right),
.RJ_clear_enable_left(RJ_clear_enable_left),
.RJ_enable_left(RJ_write_enable_left),
.RJ_clear_ready_left(RJ_clear_ready_left),
.RJ_ready_left(RJ_write_ready_left),
.RJ_address_left(RJ_writeaddress_left),
.RJ_clear_enable_right(RJ_clear_enable_right),
.RJ_enable_right(RJ_write_enable_right),
.RJ_clear_ready_right(RJ_clear_ready_right),
.RJ_ready_right(RJ_write_ready_right),
.RJ_address_right(RJ_writeaddress_right),
.COEFF_initial_left(COEFF_initial_left),
.COEFF_initial_right(COEFF_initial_right),
.COEFF_clear_enable_left(COEFF_clear_enable_left),
.COEFF_enable_left(COEFF_write_enable_left),
.COEFF_clear_ready_left(COEFF_clear_ready_left),
.COEFF_ready_left(COEFF_write_ready_left),
.COEFF_address_left(COEFF_writeaddress_left),
.COEFF_clear_enable_right(COEFF_clear_enable_right),
.COEFF_enable_right(COEFF_write_enable_right),
.COEFF_clear_ready_right(COEFF_clear_ready_right),
.COEFF_ready_right(COEFF_write_ready_right),
.COEFF_address_right(COEFF_writeaddress_right),
.DATA_initial_left(DATA_initial_left),
.DATA_initial_right(DATA_initial_right),
.DATA_write_enable_left(DATA_write_enable_left),
.DATA_clear_enable_left(DATA_clear_enable_left),
.DATA_write_ready_left(DATA_write_ready_left),
.DATA_clear_ready_left(DATA_clear_ready_left),
.DATA_writeaddress_left(DATA_writeaddress_left),
.DATA_write_enable_right(DATA_write_enable_right),
.DATA_clear_enable_right(DATA_clear_enable_right),
.DATA_write_ready_right(DATA_write_ready_right),
.DATA_clear_ready_right(DATA_clear_ready_right),
.DATA_writeaddress_right(DATA_writeaddress_right),
.ALU_initial(ALU_initial),
.STP_initial(STP_initial),
.PTS_initial(PTS_initial),
.shift_initial_left(shift_initial_left),
.shift_initial_right(shift_initial_right),
.SE_initial_left(SE_initial_left),
.SE_initial_right(SE_initial_right),
.ALU_enable(ALU_enable),
.ALU_start(ALU_start),
.count_left(count_left),
.count_right(count_right)
);
ALU ALU_uut (
.ALU_initial(ALU_initial),
.ALU_enable(ALU_enable),
.ALU_start(ALU_start),
.Sclk(Sclk),
.Frame(Frame),
.RJ_enable_left(RJ_read_enable_left),
.RJ_enable_right(RJ_read_enable_right),
.RJ_address_left(RJ_readaddress_left),
.RJ_address_right(RJ_readaddress_right),
.RJ_ready_left(RJ_read_ready_left),
.RJ_ready_right(RJ_read_ready_right),
.RJ_out_left(RJ_out_left),
.RJ_out_right(RJ_out_right),
.COEFF_address_left(COEFF_readaddress_left),
.COEFF_address_right(COEFF_readaddress_right),
.COEFF_out_left(COEFF_out_left),
.COEFF_out_right(COEFF_out_right),
.DATA_readaddress_left(DATA_readaddress_left),
.DATA_readaddress_right(DATA_readaddress_right),
.DATA_out_left(DATA_out_left),
.DATA_out_right(DATA_out_right),
.AddSub_left(AddSub_left),
.AddSub_right(AddSub_right),
.Add_Input1_left(Add_Input1_left),
.Add_Input1_right(Add_Input1_right),
.Add_Input2_left(Add_Input2_left),
.Add_Input2_right(Add_Input2_right),
.Add_output_left(Add_output_left),
.Add_output_right(Add_output_right),
.shift_input_left(shift_input_left),
.shift_input_right(shift_input_right),
.shift_output_left(shift_output_left),
.shift_output_right(shift_output_right),
.SE_input_left(SE_input_left),
.SE_input_right(SE_input_right),
.SE_output_left(SE_output_left),
.SE_output_right(SE_output_right),
.PTS_enable(PTS_enable),
.PTS_ready(PTS_ready),
.PTS_left(PTS_left),
.PTS_right(PTS_right)
);
serialtoparallel STP
(
.STP_initial(STP_initial),
.STP_enable(STP_enable),
.STP_ready(STP_ready),
.Dclk(Dclk),
.InputL(InputL),
.InputR(InputR),
.Data_parallel_left(Data_parallel_left),
.Data_parallel_right(Data_parallel_right)
);
RJ RJ_left
(
.Sclk(Sclk),
.RJ_initial(RJ_initial_left),
.RJ_clear_enable(RJ_clear_enable_left),
.RJ_clear_ready(RJ_clear_ready_left),
.RJ_write_enable(RJ_write_enable_left),
.RJ_write_ready(RJ_write_ready_left),
.RJ_read_enable(RJ_read_enable_left),
.RJ_read_ready(RJ_read_ready_left),
.RJ_writeaddress(RJ_writeaddress_left),
.RJ_readaddress(RJ_readaddress_left),
.RJ_in(Data_parallel_left),
.RJ_out(RJ_out_left)
);
RJ RJ_right
(
.Sclk(Sclk),
.RJ_initial(RJ_initial_right),
.RJ_clear_enable(RJ_clear_enable_right),
.RJ_clear_ready(RJ_clear_ready_right),
.RJ_write_enable(RJ_write_enable_right),
.RJ_write_ready(RJ_write_ready_right),
.RJ_read_enable(RJ_read_enable_right),
.RJ_read_ready(RJ_read_ready_right),
.RJ_writeaddress(RJ_writeaddress_right),
.RJ_readaddress(RJ_readaddress_right),
.RJ_in(Data_parallel_right),
.RJ_out(RJ_out_right)
);
COEFF COEFF_left
(
.Sclk(Sclk),
.COEFF_initial(COEFF_initial_left),
.COEFF_clear_enable(COEFF_clear_enable_left),
.COEFF_clear_ready(COEFF_clear_ready_left),
.COEFF_write_enable(COEFF_write_enable_left),
.COEFF_write_ready(COEFF_write_ready_left),
.COEFF_writeaddress(COEFF_writeaddress_left),
.COEFF_readaddress(COEFF_readaddress_left),
.COEFF_in(Data_parallel_left),
.COEFF_out(COEFF_out_left)
);
COEFF COEFF_right
(
.Sclk(Sclk),
.COEFF_initial(COEFF_initial_right),
.COEFF_clear_enable(COEFF_clear_enable_right),
.COEFF_clear_ready(COEFF_clear_ready_right),
.COEFF_write_enable(COEFF_write_enable_right),
.COEFF_write_ready(COEFF_write_ready_right),
.COEFF_writeaddress(COEFF_writeaddress_right),
.COEFF_readaddress(COEFF_readaddress_right),
.COEFF_in(Data_parallel_right),
.COEFF_out(COEFF_out_right)
);
DATA DATA_left
(
.Sclk(Sclk),
.count(count_left),
.DATA_initial(DATA_initial_left),
.DATA_clear_enable(DATA_clear_enable_left),
.DATA_clear_ready(DATA_clear_ready_left),
.DATA_write_enable(DATA_write_enable_left),
.DATA_write_ready(DATA_write_ready_left),
.DATA_writeaddress(DATA_writeaddress_left),
.DATA_readaddress(DATA_readaddress_left),
.DATA_in(Data_parallel_left),
.DATA_out(DATA_out_left)
);
DATA DATA_right
(
.Sclk(Sclk),
.count(count_right),
.DATA_initial(DATA_initial_right),
.DATA_clear_enable(DATA_clear_enable_right),
.DATA_clear_ready(DATA_clear_ready_right),
.DATA_write_enable(DATA_write_enable_right),
.DATA_write_ready(DATA_write_ready_right),
.DATA_writeaddress(DATA_writeaddress_right),
.DATA_readaddress(DATA_readaddress_right),
.DATA_in(Data_parallel_right),
.DATA_out(DATA_out_right)
);
SignExtension SignExtension_left
(
.SE_initial(SE_initial_left),
.SE_input(SE_input_left),
.SE_output(SE_output_left)
);
SignExtension SignExtension_right
(
.SE_initial(SE_initial_right),
.SE_input(SE_input_right),
.SE_output(SE_output_right)
);
AdderModule ADD_left
(
.AddSub(AddSub_left),
.Input1(Add_Input1_left),
.Input2(Add_Input2_left),
.Output(Add_output_left)
);
AdderModule ADD_right
(
.AddSub(AddSub_right),
.Input1(Add_Input1_right),
.Input2(Add_Input2_right),
.Output(Add_output_right)
);
Shifter Shifter_left
(
.shift_initial(shift_initial_left),
.shift_input(shift_input_left),
.shift_output(shift_output_left)
);
Shifter Shifter_right
(
.shift_initial(shift_initial_right),
.shift_input(shift_input_right),
.shift_output(shift_output_right)
);
paralleltoserial paralleltoserial_uut
(
.PTS_initial(PTS_initial),
.PTS_enable(PTS_enable),
.PTS_ready(PTS_ready),
.Sclk(Sclk),
.Frame(Frame),
.PTS_left(PTS_left),
.PTS_right(PTS_right),
.OutputL(OutputL),
.OutputR(OutputR),
.Outready(OutReady)
);
Endmodule
MAIN CONTROLLER:
//////////////////////////////////////////////////////////////////////////////////
module MSDAP_controller
( Dclk, Sclk, Start, Frame, Reset_n, Inready,
STP_enable, STP_ready,
RJ_initial_left, RJ_clear_enable_left, RJ_clear_ready_left, RJ_enable_left,
RJ_ready_left, RJ_address_left,
RJ_initial_right, RJ_clear_enable_right, RJ_clear_ready_right, RJ_enable_right,
RJ_ready_right, RJ_address_right,
COEFF_initial_left, COEFF_clear_enable_left, COEFF_clear_ready_left,
COEFF_enable_left, COEFF_ready_left, COEFF_address_left,
COEFF_initial_right, COEFF_clear_enable_right, COEFF_clear_ready_right,
COEFF_enable_right, COEFF_ready_right, COEFF_address_right,
DATA_initial_left, DATA_write_enable_left, DATA_clear_enable_left,
DATA_write_ready_left, DATA_clear_ready_left, DATA_writeaddress_left,
DATA_initial_right, DATA_write_enable_right, DATA_clear_enable_right,
DATA_write_ready_right, DATA_clear_ready_right, DATA_writeaddress_right,
ALU_initial, STP_initial, PTS_initial, ALU_enable, ALU_start, count_left, count_right,
shift_initial_left, shift_initial_right, SE_initial_left, SE_initial_right );
input Dclk, Sclk, Start, Frame, Reset_n;
output reg Inready;
/////////STP
output reg STP_enable;
input STP_ready;
////////RJ
output reg RJ_clear_enable_left, RJ_clear_enable_right, RJ_enable_left, RJ_enable_right;
output reg [31:0] RJ_address_left, RJ_address_right;
input RJ_clear_ready_left, RJ_clear_ready_right, RJ_ready_left, RJ_ready_right;
/////////COEFF
output reg COEFF_clear_enable_left, COEFF_clear_enable_right, COEFF_enable_left,
COEFF_enable_right;
output reg [31:0] COEFF_address_left, COEFF_address_right;
input COEFF_clear_ready_left, COEFF_clear_ready_right, COEFF_ready_left,
COEFF_ready_right;
/////////DATA
output reg DATA_write_enable_left, DATA_write_enable_right, DATA_clear_enable_left,
DATA_clear_enable_right;
output reg [31:0] DATA_writeaddress_left, DATA_writeaddress_right;
input DATA_write_ready_left, DATA_write_ready_right, DATA_clear_ready_left,
DATA_clear_ready_right;
input [31:0] count_left, count_right;
/////////ALU
output reg ALU_enable, ALU_start, ALU_initial, STP_initial, PTS_initial,
RJ_initial_left, RJ_initial_right,
COEFF_initial_left, COEFF_initial_right,
DATA_initial_left, DATA_initial_right;
////////SHIFTER
output reg shift_initial_left, shift_initial_right;
////////SIGN EXTENSION
output reg SE_initial_left, SE_initial_right;
integer state_start, state_sclk, state_dclk, state_reset, i, j, flag, stop, j_temp;
wire [31:0] state_temp;
wire reset_flag;
wire [31:0] state;
reg RJ_finish, COEFF_finish, DATA_finish, miss, miss_clear;
reg [31:0] RJ_address_left_temp, RJ_address_right_temp;
reg [31:0] COEFF_address_left_temp, COEFF_address_right_temp;
reg [31:0] DATA_writeaddress_left_temp, DATA_writeaddress_right_temp;
/////////////////////start here
always@(Start)
begin
if(Start == 0)
state_start = 0;
if(Start == 1)
state_start = 1;
end
///////////////////////////////////////////////
always@(STP_ready or reset_flag or Start)
begin
//////////INITIAL
if(Start==1)
begin
RJ_enable_left = 0;
RJ_enable_right = 0;
RJ_address_left = $unsigned(-1);
RJ_address_right= $unsigned(-1);
RJ_finish = 0;
COEFF_enable_left = 0;
COEFF_enable_right = 0;
COEFF_address_left = $unsigned(-1);
COEFF_address_right= $unsigned(-1);
COEFF_finish = 0;
DATA_write_enable_left = 0;
DATA_write_enable_right = 0;
DATA_writeaddress_left = $unsigned(-1);
DATA_writeaddress_right = $unsigned(-1);
DATA_finish = 0;
miss_clear=0;
end
////////////////////////////
if(RJ_finish==0)
begin
if((RJ_ready_left==1) && (RJ_ready_right==1))
begin
RJ_enable_left = 0;
RJ_enable_right = 0;
if(RJ_address_left==15 && RJ_address_right==15)
begin
RJ_finish = 1;
RJ_address_left = $unsigned(-1);
RJ_address_right= $unsigned(-1);
end
end
if(STP_ready == 1)
begin
RJ_enable_left = 1;
RJ_enable_right = 1;
RJ_address_left_temp = RJ_address_left;
RJ_address_right_temp = RJ_address_right;
RJ_address_left = RJ_address_left_temp + 1;
RJ_address_right= RJ_address_right_temp + 1;
end
end
else if(COEFF_finish==0)
begin
if((COEFF_ready_left==1) && (COEFF_ready_right==1))
begin
COEFF_enable_left = 0;
COEFF_enable_right = 0;
if(COEFF_address_left==511 && COEFF_address_right==511)
begin
COEFF_finish = 1;
COEFF_address_left = $unsigned(-1);
COEFF_address_right= $unsigned(-1);
end
end
if(STP_ready == 1)
begin
COEFF_enable_left = 1;
COEFF_enable_right = 1;
COEFF_address_left_temp = COEFF_address_left;
COEFF_address_right_temp = COEFF_address_right;
COEFF_address_left = COEFF_address_left_temp + 1;
COEFF_address_right = COEFF_address_right_temp + 1;
end
end
else if(DATA_finish==0)
begin
if((DATA_write_ready_left == 1) && (DATA_write_ready_right == 1))
begin
DATA_write_enable_left = 0;
DATA_write_enable_right = 0;
if((DATA_writeaddress_left==511)&&(DATA_writeaddress_right==511))
begin
DATA_writeaddress_left = $unsigned(-1);
DATA_writeaddress_right = $unsigned(-1);
end
end
if(reset_flag==1)
begin
DATA_writeaddress_left = $unsigned(-2);
DATA_writeaddress_right = $unsigned(-2);
end
if(STP_ready==1 && miss==0)
begin
DATA_write_enable_left = 1;
DATA_write_enable_right = 1;
if(state==6)
begin
DATA_writeaddress_left_temp =
DATA_writeaddress_left;
DATA_writeaddress_right_temp =
DATA_writeaddress_right;
DATA_writeaddress_left =
DATA_writeaddress_left_temp + 1;
DATA_writeaddress_right =
DATA_writeaddress_right_temp + 1;
end
end
if(miss_clear==1)
miss_clear=0;
if(miss==1)
miss_clear=1;
end
end
//////////////////////////////////Sclk work here
always@(posedge Sclk)
begin
///////////INITIAL
if(Start==0)
begin
RJ_initial_left =0;
RJ_initial_right=0;
COEFF_initial_left =0;
COEFF_initial_right=0;
DATA_initial_left =0;
DATA_initial_right=0;
end
if(Start==1)
begin
miss=0;
state_sclk = 0;
state_dclk = 0;
flag = 0;
stop=0;
STP_enable = 0;
ALU_initial= 0;
STP_initial= 0;
PTS_initial= 0;
RJ_initial_left =1;
RJ_initial_right =1;
COEFF_initial_left =1;
COEFF_initial_right=1;
DATA_initial_left =1;
DATA_initial_right =1;
ALU_enable = 0;
ALU_start = 0;
RJ_clear_enable_left = 0;
RJ_clear_enable_right = 0;
COEFF_clear_enable_left = 0;
COEFF_clear_enable_right = 0;
DATA_clear_enable_left = 0;
DATA_clear_enable_right = 0;
end
////////////////////////////
if(miss_clear==1)
miss=0;
/////////////////RESET READY
if(RJ_clear_ready_left==1 && RJ_clear_ready_right==1)
begin
RJ_clear_enable_left = 0;
RJ_clear_enable_right = 0;
end
if(COEFF_clear_ready_left==1 && COEFF_clear_ready_right==1)
begin
COEFF_clear_enable_left = 0;
COEFF_clear_enable_right = 0;
end
if(DATA_clear_ready_left==1 && DATA_clear_ready_right==1)
begin
DATA_clear_enable_left = 0;
DATA_clear_enable_right = 0;
end
//////////STATE MACHINE
case(state)
0:
begin
Inready = 0;
RJ_clear_enable_left = 1;
RJ_clear_enable_right = 1;
COEFF_clear_enable_left = 1;
COEFF_clear_enable_right= 1;
DATA_clear_enable_left = 1;
DATA_clear_enable_right = 1;
ALU_initial=1;
PTS_initial=1;
shift_initial_left = 1;
shift_initial_right = 1;
SE_initial_left = 1;
SE_initial_right = 1;
if(DATA_clear_ready_left==1 && DATA_clear_ready_right==1)
begin
state_sclk =1;
ALU_initial=0;
PTS_initial=0;
end
end
1:
begin
Inready = 1;
if(Frame == 1)
begin
state_sclk = 2;
end
end
2:
begin
if(Frame==0 && STP_initial==1)
STP_initial=0;
if(Frame==1 && RJ_address_left==-1 && stop==0)
begin
STP_initial=1;
stop=1;
end
if(Frame == 1)
STP_enable = 1;
if(STP_enable == 1 && Frame==0)
STP_enable = 0;
if(RJ_address_left==14 && RJ_address_right==14 && j==-1)
state_dclk = 3;
end
3:
begin
Inready = 1;
if(Frame == 1)
begin
state_sclk = 4;
end
end
4:
begin
if(Frame == 1)
STP_enable = 1;
if(STP_enable == 1 && Frame==0)
STP_enable = 0;
if(COEFF_address_left==510 && COEFF_address_right==510 && j==-
1)
state_dclk = 5;
end
5:
begin
Inready = 1;
ALU_enable = 0;
if(Frame == 1)
begin
state_sclk = 6;
flag = 0;
end
end
6:
begin
state_sclk = 0;
if(Frame == 1)
STP_enable = 1;
if(STP_enable == 1 && Frame==0)
STP_enable = 0;
if(ALU_start == 1)
ALU_start = 0;
if(Frame == 1 && DATA_writeaddress_left==0 && flag==0)
begin
ALU_enable = 1;
ALU_start = 1;
flag = 1;
end
if(Frame==1 && count_left>=800 && count_right>=800 && j==14)
begin
state_sclk = 8;
ALU_enable = 0;
end
end
7:
begin
Inready = 0;
DATA_clear_enable_left = 1;
DATA_clear_enable_right = 1;
miss = 1;
end
8:
begin
if(Frame == 1'b1)
STP_enable = 1'b1;
if(STP_enable == 1 && Frame==0)
STP_enable = 0;
if(count_left==0 || count_right==0)
begin
state_sclk = 6;
ALU_enable = 1;
end
end
endcase
end
///////////////////////////////Dclk work here
always@(negedge Dclk)
begin
case(state)
2:
begin
if(Frame == 1'b1)
j=15;
if(j>=0)
begin
j_temp = j;
j = j_temp - 1;
end
end
4:
begin
if(Frame == 1'b1)
j=15;
if(j>=0)
begin
j_temp = j;
j = j_temp - 1;
end
end
6:
begin
if(Frame == 1'b1)
j=15;
if(j>=0)
begin
j_temp = j;
j = j_temp - 1;
end
end
endcase
end
///////////////////////Reset check here
always@(Reset_n or Start)
begin
///////////INITIAL
if(Start==1)
state_reset = 0;
//////////////////
case(state)
5:
begin
if(Reset_n == 0)
begin
state_reset = 7;
end
end
6:
begin
if(Reset_n == 0)
begin
state_reset = 7;
end
end
7:
begin
if(Reset_n == 1)
begin
state_reset = 5;
end
if(Reset_n == 0)
begin
state_reset = 7;
end
end
8:
begin
if(Reset_n == 0)
begin
state_reset = 7;
end
end
endcase
end
assign reset_flag = (state==5 && Reset_n == 1)? 1 : 0;
assign state_temp = state;
assign state = ((state_start==1) ? 0 :
((state==0 && state_sclk ==1)? 1 :
((state==1 && state_sclk ==2)? 2 :
((state==2 && state_dclk ==3)? 3 :
((state==3 && state_sclk ==4)? 4 :
((state==4 && state_dclk ==5)? 5 :
((state==5 && state_reset==7)? 7 :
((state==5 && state_sclk ==6)? 6 :
((state==6 && state_reset==7)? 7 :
((state==6 && state_sclk ==8)? 8 :
((state==7 && state_reset==7)? 7 :
((state==7 && state_reset==5)? 5 :
((state==8 && state_reset==7)? 7 :
((state==8 && state_sclk ==6)? 6 : state_temp ))))))))))))));
endmodule
ALU MODULE:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module ALU(
input ALU_initial, ALU_enable, ALU_start, Sclk, Frame,
////////////RJ
output reg RJ_enable_left, RJ_enable_right,
output reg [3:0] RJ_address_left, RJ_address_right,
input RJ_ready_left, RJ_ready_right,
input [15:0] RJ_out_left, RJ_out_right,
///////////COEFF
output reg [9:0] COEFF_address_left, COEFF_address_right,
input [8:0] COEFF_out_left, COEFF_out_right,
///////////DATA
output reg [9:0] DATA_readaddress_left, DATA_readaddress_right,
input [15:0] DATA_out_left, DATA_out_right,
///////////ADDER
output reg AddSub_left, AddSub_right,
output reg [39:0] Add_Input1_left, Add_Input1_right,
output [39:0] Add_Input2_left, Add_Input2_right,
input [39:0] Add_output_left, Add_output_right,
///////////SHIFTER
output reg [39:0] shift_input_left, shift_input_right,
input [39:0] shift_output_left, shift_output_right,
//////////SIGN EXTENSION
output [15:0] SE_input_left, SE_input_right,
input [39:0] SE_output_left, SE_output_right,
////////PTS
output reg PTS_enable,
input PTS_ready,
output reg [39:0] PTS_left, PTS_right
);
////////////COMPUTATOIN
integer substateL, substateR, row, col, outL, outR, setR_temp, mR_temp, kR_temp, jR_temp,
mL, jL, kL, mR, jR, kR, set, setL, setR, fullrow, setL_temp, mL_temp,
kL_temp, jL_temp, set_temp;
integer trigger_left, trigger_right, subtrigger_left, subtrigger_right, row_temp, fullrow_temp,
outL_temp, outR_temp,
state_tran_left, state_tran_right, Add_trigger_left, Add_trigger_right,
shift_trigger_left, shift_trigger_right, final_trigger_left, final_trigger_right,
final_trigger_left_jL0, final_trigger_right_jR0;
wire [39:0] UL;
wire [39:0] UR;
wire [39:0] YL;
wire [39:0] YR;
reg [15:0] allone;
wire Add_Input2_left_one, Add_Input2_left_two, Add_Input2_left_three;
wire Add_Input2_right_one, Add_Input2_right_two, Add_Input2_right_three;
wire UL_one, UL_two, UL_three, UL_four, UL_five;
wire UR_one, UR_two, UR_three, UR_four, UR_five;
wire YL_one, YL_two, YL_three;
wire YR_one, YR_two, YR_three;
wire [39:0] Add_Input2_left_temp, Add_Input2_right_temp, UL_temp, UR_temp, YL_temp,
YR_temp;
always@(posedge Sclk)
begin
if(ALU_initial==1)
begin
allone = 16'hFFFF;
substateL=$signed(-1);
substateR=$signed(-1);
set=0;
setL=0;
setR=0;
fullrow=0;
PTS_enable=0;
RJ_address_left =$unsigned(-1);
RJ_address_right =$unsigned(-1);
COEFF_address_left =1024;
COEFF_address_right =1024;
DATA_readaddress_left =1024;
DATA_readaddress_right=1024;
trigger_left = 0;
trigger_right = 0;
subtrigger_left = 0;
subtrigger_right = 0;
state_tran_left =0;
state_tran_right=0;
Add_trigger_left =0;
Add_trigger_right=0;
shift_trigger_left=0;
shift_trigger_right=0;
final_trigger_left=0;
final_trigger_right=0;
final_trigger_left_jL0=0;
final_trigger_right_jR0=0;
end
if(PTS_ready==1)
PTS_enable=0;
if(ALU_enable==0)
PTS_enable = 0;
else if(ALU_enable==1)
begin
if(ALU_start==1)
begin
substateL = 1;
substateR = 1;
row=0;
fullrow=set;
col=39;
outL=0;
outR=0;
trigger_left=0;
trigger_right=0;
end
//////////////////////////////////////////////////
if(substateL==1)
substateR=1;
///////////////////////LEFT COMPUTATION
case(substateL)
1:
begin
mL=0;
jL=0;
RJ_address_left = $unsigned(jL);
substateL = 2;
state_tran_left=1;
end
2:
begin
state_tran_left=0;
Add_trigger_left=0;
final_trigger_left=0;
final_trigger_left_jL0=0;
if(jL<16)
begin
if(kL>0)
begin
COEFF_address_left = $unsigned(mL);
if(fullrow >= $unsigned(COEFF_out_left[7:0]))
begin
if(COEFF_out_left[8] == 1)
begin
setL = $unsigned(fullrow)-$unsigned(COEFF_out_left[7:0]);
if(setL>511)
begin
setL_temp = setL;
setL = setL_temp - set;
end
if(setL<0)
begin
setL_temp = setL;
setL = setL_temp+512;
end
DATA_readaddress_left = $unsigned(setL);
AddSub_left = 1;
Add_Input1_left = UL;
Add_trigger_left=1;
end
else
begin
setL = $unsigned(fullrow-COEFF_out_left[7:0]);
if(setL>511)
begin
setL_temp = setL;
setL = setL_temp - set;
end
if(setL<0)
begin
setL_temp = setL;
setL = setL_temp+512;
end
DATA_readaddress_left = $unsigned(setL);
AddSub_left = 0;
Add_Input1_left = UL;
Add_trigger_left=1;
end
end
mL_temp = mL;
mL
= mL_temp + 1;
kL_temp = kL;
kL
= kL_temp - 1;
end
end
if(trigger_left==0)
begin
kL =
$signed(RJ_out_left);
trigger_left=1;
end
if(jL==16)
begin
substateL = 3;
trigger_left=0;
end
if(kL==0)
begin
substateL = 3;
trigger_left=0;
end
end
3:
begin
Add_trigger_left=0;
if(jL<=16 &&
jL>0)
begin
shift_input_left = YL;
shift_trigger_left=1;
end
substateL = 4;
end
4:
begin
shift_trigger_left=0;
if(jL<=16 &&
jL>0)
begin
AddSub_left = 0;
Add_Input1_left = YL;
final_trigger_left=1;
end
final_trigger_left_jL0=1;
jL_temp = jL;;
jL =
jL_temp + 1;
if(jL==17)
substateL = 5;
else
begin
RJ_address_left = $unsigned(jL);
substateL = 2;
end
end
5: //OUTPUT SIDE
begin
if(Frame==0 &&
trigger_left==0)
begin
PTS_enable =
1;
PTS_left =
YL;
PTS_right=
YR;
end
if(Frame==1 && row
<= 511 && trigger_left == 0)
begin
trigger_left =
1;
row_temp =
row;
row =
row_temp + 1;
fullrow_temp
= fullrow;
fullrow =
fullrow_temp + 1;
outL_temp =
outL;
outL =
outL_temp + 1;
outR_temp =
outR;
outR =
outR_temp + 1;
if(outL==2)
outL=0;
if(outR==2)
outR=0;
mL=0;
mR=0;
jL=0;
jR=0;
end
if(trigger_left == 1)
begin
RJ_enable_left
= 1;
RJ_address_left = $unsigned(jL);
RJ_enable_right = 1;
RJ_address_right = $unsigned(jR);
if(RJ_ready_left==1 && RJ_ready_right==1 && Frame==0)
begin
RJ_enable_left = 0;
RJ_enable_right = 0;
kL =
$signed(RJ_out_left);
kR =
$signed(RJ_out_right);
substateL = 1;
trigger_left = 0;
end
end
if(row==512)
begin
row=0;
set_temp =
set;
set =
set_temp + 512;
end
if(fullrow==7000)
begin
substateL = 6;
substateR = 6;
end
end
endcase
//////////RIGHT COMPUTATION
case(substateR)
1:
begin
mR=0;
jR=0;
RJ_enable_right = 1;
RJ_address_right =
$unsigned(jR);
substateR = 2;
state_tran_right=1;
end
2:
begin
state_tran_right=0;
Add_trigger_right=0;
final_trigger_right=0;
final_trigger_right_jR0=0;
if(jR<16)
begin
if(kR>0)
begin
COEFF_address_right = $unsigned(mR);
if(fullrow >= $unsigned(COEFF_out_right[7:0]))
begin
if(COEFF_out_right[8] == 1)
begin
setR = $unsigned(fullrow-COEFF_out_right[7:0]);
if(setR>511)
begin
setR_temp = setR;
setR = setR_temp - set;
end
if(setR<0)
begin
setR_temp = setR;
setR = setR_temp + 512;
end
DATA_readaddress_right = $unsigned(setR);
AddSub_right = 1;
Add_Input1_right = UR;
Add_trigger_right=1;
end
else
begin
setR = $unsigned(fullrow-COEFF_out_right[7:0]);
if(setR>511)
begin
setR_temp = setR;
setR = setR_temp - set;
end
if(setR<0)
begin
setR_temp = setR;
setR = setR_temp+512;
end
DATA_readaddress_right = $unsigned(setR);
AddSub_right = 0;
Add_Input1_right = UR;
Add_trigger_right=1;
end
end
mR_temp = mR;
mR
= mR_temp + 1;
kR_temp = kR;
kR
= kR_temp - 1;
end
end
if(trigger_right==0)
begin
kR =
$signed(RJ_out_right);
trigger_right=1;
end
if(jR==16)
begin
substateR = 3;
trigger_right=0;
end
if(kR==0)
begin
substateR = 3;
trigger_right=0;
end
end
3:
begin
Add_trigger_right=0;
if(jR<=16 &&
jR>0)
begin
shift_input_right = YR;
shift_trigger_right=1;
end
substateR = 4;
end
4:
begin
shift_trigger_right=0;
if(jR<=16 && jR>0)
begin
AddSub_right
= 0;
Add_Input1_right = YR;
final_trigger_right=1;
end
final_trigger_right_jR0=1;
jR_temp = jR;
jR = jR_temp + 1;
if(jR==17)
substateR = 5;
else
begin
RJ_address_right = $unsigned(jR);
substateR = 2;
end
end
endcase
end
end
assign SE_input_left = allone & DATA_out_left;
assign SE_input_right = allone & DATA_out_right;
assign Add_Input2_left_one = (substateL==2) || (substateL==3);
assign Add_Input2_left_two = (Add_Input2_left_one==1) && (Add_trigger_left==1);
assign Add_Input2_left_three = (substateL==4) && (jL<16) && (jL>0);
assign Add_Input2_left_temp = Add_Input2_left;
assign Add_Input2_left = (Add_Input2_left_two) ? SE_output_left :
((Add_Input2_left_three)? UL : Add_Input2_left_temp );
///////////////////////////////////////////////////////////////////////////////////////////////////
assign Add_Input2_right_one = (substateR==2) || (substateR==3);
assign Add_Input2_right_two = (Add_Input2_right_one==1) && (Add_trigger_right==1);
assign Add_Input2_right_three = (substateR==4) && (jR<16) && (jR>0);
assign Add_Input2_right_temp = Add_Input2_right;
assign Add_Input2_right = (Add_Input2_right_two) ? SE_output_right :
((Add_Input2_right_three)? UR : Add_Input2_right_temp);
///////////////////////////////////////////////////////////////////////////////////////////////////
assign UL_one = (final_trigger_left==1) || (final_trigger_left_jL0==1);
assign UL_two = (substateL == 2) && (UL_one==1);
assign UL_three = (state_tran_left==1) || (UL_two==1) || (substateL == 5);
assign UL_four = (substateL==2) || (substateL==3);
assign UL_five = UL_four && (Add_trigger_left ==1);
assign UL_temp = UL;
assign UL = (UL_three)? 40'h0000000000 :
((UL_five) ? Add_output_left : UL_temp);
///////////////////////////////////////////////////////////////////////////////////////////////////
assign UR_one = (final_trigger_right==1) || (final_trigger_right_jR0==1);
assign UR_two = (substateR == 2) && (UR_one==1);
assign UR_three = (state_tran_right==1) || (UR_two==1) || (substateR == 5);
assign UR_four = (substateR==2) || (substateR==3);
assign UR_five = UR_four && (Add_trigger_right ==1);
assign UR_temp = UR;
assign UR = (UR_three)? 40'h0000000000 :
((UR_five) ? Add_output_right : UR_temp);
///////////////////////////////////////////////////////////////////////////////////////////////////
assign YL_one = (substateL==3) && (jL==0);
assign YL_two = (substateL==4) && (jL<=16) && (jL>0) && (shift_trigger_left==1);
assign YL_three = (substateL==2) && (jL<=16) && (jL>0) && (final_trigger_left==1);
assign YL_temp = YL;
assign YL = (state_tran_left ==1)? 40'h0000000000 :
((YL_one) ? UL :
((YL_two) ? shift_output_left :
((YL_three) ? Add_output_left :
YL_temp)));
///////////////////////////////////////////////////////////////////////////////////////////////////
assign YR_one = (substateR==3) && (jR==0);
assign YR_two = (substateR==4) && (jR<=16) && (jR>0) && (shift_trigger_right==1);
assign YR_three = (substateR==2) && (jR<=16) && (jR>0) && (final_trigger_right==1);
assign YR_temp = YR;
assign YR = (state_tran_right==1) ? 40'h0000000000 :
((YR_one) ? UR :
((YR_two) ? shift_output_right:
((YR_three) ? Add_output_right :
YR_temp)));
endmodule
SERIAL TO PARALLEL MODULE:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module serialtoparallel(STP_initial, STP_enable, STP_ready, Dclk, InputL, InputR,
Data_parallel_left, Data_parallel_right);
input STP_initial, STP_enable, Dclk, InputL, InputR;
output reg [15:0] Data_parallel_left, Data_parallel_right;
output reg STP_ready;
reg [15:0] Data_temp_left, Data_temp_right;
integer j;
always @ (negedge Dclk)
begin
if(STP_initial==1)
begin
j=$unsigned(-2);
STP_ready=1'b0;
Data_parallel_left =16'h0000;
Data_parallel_right=16'h0000;
Data_temp_left =16'h0000;
Data_temp_right=16'h0000;
end
if(STP_ready==1'b1)
STP_ready=1'b0;
if(j==-1)
begin
STP_ready=1'b1;
Data_parallel_left = Data_temp_left;
Data_parallel_right = Data_temp_right;
j=j-1;
end
if(STP_enable==1'b1 && j==-2)
j=15;
if(j>=0)
begin
Data_temp_left [j] = InputL;
Data_temp_right[j] = InputR;
j=j-1;
end
end
endmodule
RJ_MEMORY MODULE:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module RJ(Sclk, RJ_initial, RJ_clear_enable, RJ_clear_ready, RJ_write_enable, RJ_write_ready,
RJ_read_enable, RJ_read_ready, RJ_writeaddress, RJ_readaddress, RJ_in, RJ_out);
input Sclk, RJ_initial, RJ_write_enable, RJ_read_enable, RJ_clear_enable;
input [31:0] RJ_writeaddress;
input [3:0] RJ_readaddress;
input [15:0] RJ_in;
output [15:0] RJ_out;
output reg RJ_write_ready, RJ_read_ready, RJ_clear_ready;
reg [15:0]RJ_memory[0:15];
integer i, flag;
///////////////////////////CLEAR
always@(posedge Sclk)
begin
if(RJ_initial==1)
begin
i = 0;
flag = 0;
RJ_read_ready = 0;
RJ_write_ready = 0;
RJ_clear_ready = 0;
end
if(RJ_clear_ready==1 && flag==1)
begin
RJ_clear_ready=0;
i = 0;
flag = 2;
end
if(RJ_clear_enable==1 && i<16 && flag==0)
begin
RJ_memory[i]=16'h0000;
i=i+1;
if(i==16)
begin
RJ_clear_ready = 1;
flag = 1;
end
end
if(flag == 2)
flag = 0;
if(RJ_write_ready==1)
RJ_write_ready = 0;
if(RJ_write_enable==1)
begin
RJ_memory[RJ_writeaddress]= RJ_in;
RJ_write_ready = 1;
end
if(RJ_read_ready==1)
RJ_read_ready = 0;
if(RJ_read_enable==1)
RJ_read_ready = 1;
end
assign RJ_out = RJ_memory[RJ_readaddress];
endmodule
COEFF MEMORY MODULE:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module COEFF(Sclk, COEFF_initial, COEFF_clear_enable, COEFF_clear_ready,
COEFF_write_enable, COEFF_write_ready, COEFF_writeaddress, COEFF_readaddress,
COEFF_in, COEFF_out);
input Sclk, COEFF_initial, COEFF_write_enable, COEFF_clear_enable;
input [31:0] COEFF_writeaddress;
input [9:0] COEFF_readaddress;
input [15:0] COEFF_in;
output [8:0] COEFF_out;
output reg COEFF_write_ready, COEFF_clear_ready;
reg [15:0]COEFF_memory[0:511];
integer i, flag;
//////////////////////////CLEAR
always@(posedge Sclk)
begin
if(COEFF_initial==1 || COEFF_readaddress[9]==1)
begin
i = 0;
flag = 0;
COEFF_write_ready = 0;
COEFF_clear_ready = 0;
end
if(COEFF_clear_ready==1 && flag==1)
begin
COEFF_clear_ready=0;
i = 0;
flag = 2;
end
if(COEFF_clear_enable==1 && i<512 && flag==0)
begin
COEFF_memory[i]=16'h0000;
i=i+1;
if(i==512)
begin
COEFF_clear_ready = 1;
flag = 1;
end
end
if(flag == 2)
flag = 0;
if(COEFF_write_ready==1)
COEFF_write_ready = 0;
if(COEFF_write_enable==1)
begin
COEFF_memory[COEFF_writeaddress]= COEFF_in;
COEFF_write_ready = 1;
end
end
assign COEFF_out = COEFF_memory[COEFF_readaddress];
endmodule
DATA MEMORY MODULE:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module DATA(Sclk, count, DATA_initial, DATA_clear_enable, DATA_clear_ready,
DATA_write_enable, DATA_write_ready, DATA_writeaddress, DATA_readaddress,
DATA_in, DATA_out);
input Sclk, DATA_initial, DATA_write_enable, DATA_clear_enable;
input [31:0] DATA_writeaddress;
input [9:0] DATA_readaddress;
input [15:0] DATA_in;
output [15:0] DATA_out;
output reg DATA_write_ready, DATA_clear_ready;
output reg [31:0] count;
reg [15:0]DATA_memory[0:511];
reg s8tran;
integer i, flag;
always@(posedge Sclk)
begin
if(DATA_initial==1 || DATA_readaddress[9]==1)
begin
i = 0;
flag = 0;
s8tran = 0;
count = 0;
DATA_write_ready = 0;
DATA_clear_ready = 0;
end
if(DATA_clear_ready==1 && flag==1)
begin
DATA_clear_ready=0;
i = 0;
flag = 2;
count = 0;
end
if(DATA_clear_enable==1 && i<512 && flag==0)
begin
DATA_memory[i]=16'h0000;
i=i+1;
if(i==512)
begin
DATA_clear_ready = 1;
flag = 1;
end
end
if(flag == 2)
flag = 0;
if(DATA_write_enable==0)
s8tran = 0;
if(DATA_write_ready==1'b1)
DATA_write_ready=1'b0;
if(DATA_write_enable==1'b1)
begin
DATA_memory[DATA_writeaddress]= DATA_in;
DATA_write_ready = 1'b1;
if(DATA_in > 0 && s8tran==0)
begin
count = 0;
s8tran = 1;
end
else if(s8tran==0)
begin
count = count + 1;
s8tran = 1;
end
end
end
assign DATA_out = DATA_memory[DATA_readaddress];
endmodule
SIGN EXTENSION MODULE:
module SignExtension(SE_initial, SE_input, SE_output);
input SE_initial;
input [15:0] SE_input;
output [39:0] SE_output;
reg [39:0] negative;
reg [39:0] positive;
reg [31:0] i;
wire [39:0] first, second, first_shift, second_shift;
always@(SE_initial)
begin
if(SE_initial==1)
begin
negative = 40'hFFFFFF0000;
positive = 40'h000000FFFF;
i = 16;
end
end
assign first = negative | SE_input[15:0];
assign second = positive & SE_input[15:0];
assign first_shift = first << i;
assign second_shift = second << i;
assign SE_output = (SE_input[15])? first_shift : second_shift;
endmodule
ADDER_MODULE:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module AdderModule(AddSub, Input1, Input2, Output);
input AddSub;
input [39:0] Input1, Input2;
output [39:0] Output;
wire [39:0] first, second;
assign first = Input1 - Input2;
assign second = Input1 + Input2;
assign Output = (AddSub)? first : second;
endmodule
SHIFTER MODULE:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module Shifter(shift_initial, shift_input, shift_output);
input [39:0] shift_input;
input shift_initial;
output signed [39:0] shift_output;
wire signed [39:0] temp;
reg i;
always@(shift_initial)
begin
if(shift_initial==1)
i = 1;
end
assign temp = $signed(shift_input);
assign shift_output = temp >>> i;
endmodule
PARALLEL TO SERIAL MODULE:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
module paralleltoserial(PTS_initial, PTS_enable, PTS_ready, Sclk, Frame, PTS_left, PTS_right,
OutputL, OutputR, Outready);
input PTS_initial, PTS_enable, Sclk, Frame;
input [39:0] PTS_left, PTS_right;
output reg OutputL, OutputR, Outready, PTS_ready;
integer col, flag;
/////////////////////////Sending output here
always@(posedge Sclk)
begin
if(PTS_initial == 1)
begin
flag = 0;
col = 40;
PTS_ready = 0;
Outready = 0;
end
if(PTS_ready == 1)
PTS_ready = 0;
if(col<40)
begin
if(col>=1)
begin
OutputL = PTS_left[col-1];
OutputR = PTS_right[col-1];
col=col-1;
end
else if(col==0)
begin
col=40;
Outready = 0;
PTS_ready = 1;
end
end
if(PTS_enable==1 && col==40 && Frame==1 && flag==0)
begin
Outready=1;
OutputL = PTS_left[col-1];
OutputR = PTS_right[col-1];
col=col-1;
end
end
endmodule
TESTBENCH:
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
module MSDAP_tb;
// Inputs
reg Dclk;
reg Sclk;
reg Start;
reg Frame;
reg Reset_n;
reg InputL;
reg InputR;
// Outputs
wire OutputL;
wire OutputR;
wire Inready;
wire Outready;
// Instantiate the Unit Under Test (UUT)
MSDAP_top uut (
.Dclk(Dclk),
.Sclk(Sclk),
.Start(Start),
.Frame(Frame),
.Reset_n(Reset_n),
.InputL(InputL),
.InputR(InputR),
.OutputL(OutputL),
.OutputR(OutputR),
.InReady(Inready),
.OutReady(Outready)
);
reg [15:0] in[0:15055];
reg [39:0] outL[0:6999];
reg [39:0] outR[0:6999];
always #651
begin
if(Inready==1'b1)
Dclk = ~Dclk;
else
Dclk = 1'b0;
end
always #17.1315 Sclk = ~Sclk; //#17.13
integer it, jt, out_file1, rst, outrow, col, Reset_count;
initial
begin
Dclk =1'b1;
Sclk =1'b1;
$readmemh("Data1.in", in);
out_file1 = $fopen("tb_memory1.out","w");
Frame = 1'b0;
it=0;
jt=15;
rst=0;
outrow=0;
col=39;
Reset_n=1'b1;
Reset_count=0;
Start = 1'b0;
#6510;
Start = 1'b1;
#1302;
Start = 1'b0;
end
/////////////Reset signal generation
always@(posedge Sclk)
begin
if(Reset_n==1'b0 && Reset_count==800)
begin
Reset_n=1'b1;
Reset_count=0;
rst=0;
end
if(rst==1)
Reset_count=Reset_count+1;
if(it==9456 && jt==6 && rst==0)
begin
Reset_n=1'b0;
rst=1;
end
if(it==13056 && jt==6 && rst==0)
begin
Reset_n=1'b0;
rst=1;
end
end
/////////////////////////////Sending Inputs
always@(posedge Dclk)
begin
if(Inready == 1'b1)
begin
if(it<15055)
begin
if(jt==15)
Frame=1'b1;
if(jt>=0)
begin
InputL = in[it][jt];
InputR = in[it+1][jt]; #1302
Frame=1'b0;
end
jt=jt-1;
if(jt==-1)
begin
it=it+2;
jt=15;
end
end
end
end
/////////////////////////Receiving outputs
always@(negedge Sclk)
begin
if(col==39 && Frame==1'b1 && Outready==1'b1)
begin
outL[outrow][col]=OutputL;
outR[outrow][col]=OutputR;
col=col-1;
end
else if(col<39)
begin
if(col>=0 && Outready==1'b1)
begin
outL[outrow][col]=OutputL;
outR[outrow][col]=OutputR;
col=col-1;
end
if(col==-1)
begin
$fwrite(out_file1," %H %H\n", outL[outrow],
outR[outrow]);
outrow=outrow+1;
col=39;
end
end
end
endmodule