Lab Exercise 2 - Home | EECS derives from a EECS 452 lab exercise but is ... Digilent makes...
Transcript of Lab Exercise 2 - Home | EECS derives from a EECS 452 lab exercise but is ... Digilent makes...
Doing DSP Workshop Summer 2009
Lab Exercise 2
Contents
1 Overview 3
1.1 PMod modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 The S3SB to C5510 connection . . . . . . . . . . . . . . . . . . . . . . . 4
2 PMod-DA2 and PMod-AD1 5
2.1 PMod-DA2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.1 PMod-DA2 pin assignments . . . . . . . . . . . . . . . . . . . . . 6
2.1.2 PMod-DA2 VHDL driver . . . . . . . . . . . . . . . . . . . . . . . 6
2.2 PMod-AD1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.1 PMod-AD1 VHDL driver . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.2 Single supply op-amp basics . . . . . . . . . . . . . . . . . . . . 8
2.2.3 AC coupled level shifter . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.4 DC coupled level shifter . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.5 Microphone input amplifier . . . . . . . . . . . . . . . . . . . . . 9
3 S3SB DDS 9
3.1 DDS logic design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Implementing a sine table in a Spartan-3 block RAM . . . . . . . . . . 9
4 S3SB A/D to D/A loop 11
4.1 The cable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4.1.1 S3SB B1 connector to MIB . . . . . . . . . . . . . . . . . . . . . . 11
5 Prelab 13
5.1 The S3SB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.2 The PMod-DA2 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.3 The PMod-AD1 module . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.4 DTMF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.4.1 DC coupled level shifter . . . . . . . . . . . . . . . . . . . . . . . 14
6 Exercise 14
6.1 Initial testing of the PMod-DA2 and its driver . . . . . . . . . . . . . . 14
6.2 S3SB DDS and DTMF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
6.3 Delta/Sigma DAC at 0 Hz . . . . . . . . . . . . . . . . . . . . . . . . . . 16
6.4 PMod-AD1 DC coupled level shifting circuit . . . . . . . . . . . . . . . 16
6.5 S3SB A/D echoed to S3SB D/A . . . . . . . . . . . . . . . . . . . . . . . 17
6.6 Comparing the DA2 and Delta/Sigma DACs and evaluation . . . . . 17
Lab Exercise 2 1 May 17, 2009
Doing DSP Workshop Summer 2009
A Single supply level shifting circuit 18
A.1 Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
A.2 A design procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
A.3 Choice of op-amp device . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
A.4 White board construction . . . . . . . . . . . . . . . . . . . . . . . . . . 21
B Listings for the DA1 ramp test 21
B.1 Top level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
B.2 Ramp generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
B.3 PMod-DA2 support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
C Listings for the DDS/DTMF exercise 26
C.1 Top level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
C.2 Listing for FTV get entity . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
C.3 Listing for fs timing entity . . . . . . . . . . . . . . . . . . . . . . . . . . 29
C.4 Listing for the basic DDS . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
C.5 Listing of MATLAB BRAM sine table generator . . . . . . . . . . . . . 31
C.6 BRAM sine ROM template . . . . . . . . . . . . . . . . . . . . . . . . . . 32
D Listings for the Delta/Sigma DC exercise 35
D.1 Top level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
D.2 The Delta/Sigma modulator . . . . . . . . . . . . . . . . . . . . . . . . . 36
E Listings for the S3SB AD-DA test 38
E.1 Top level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
E.2 PMod-AD1 support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
E.3 Sample timing support . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
E.4 DCM support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Lab Exercise 2 2 May 17, 2009
Doing DSP Workshop Summer 2009
1 Overview
This is a first draft. It derives from a EECS 452 lab exercise but is significantly
different. This version is being distributed to give Workshop members a heads
up reading on what is going to be done in lab, prior to the lab.
The focus of this exercise is analog input and output using the Spartan-3
Starter Board (S3SB).
The main activities consist of:
• Interfacing the 12-bit Digilent DA2 PMod module. Introduces the VHDL
device driver and uses simple counters to generate analog ramp outputs.
• Implementation of a dual channel digital waveform generator. Implements
two phase accumulators to address samples of a sine wave contained in a
read-only-memory (ROM). The frequencies generated correspond to those
used in DTMF signaling. The VHDL will be modified to sum the two DDS
outputs to form a DTMF waveform.
• Implementation of a delta/sigma D/A converter that generates a pulsed
waveform that goes between 0 and 3.3 Volts whose average value selected
using the S3SB slide switches. A simple RC lowpass filter is used to extract
the DC level and remove the high frequency components caused by the
waveform switching.
• The analog input range of the AD1 is nominally between 0 and 3.3 volts.
Many signal generators that operate down to very low frequencies (10 Hz or
lower) have outputs that are DC couple and are symmetric around 0 volts.
This part of the exercise introduces a simple circuit that is powered by a
single 3.3 Volt supply and shifts a zero-Volt centered waveform to being
centered at 3.3/2 Volts.
• Interfacing the 12-bit Digilent AD1 PMod module. A simple device device
driver is used to samples to be taken and echoed out onto the DA2 outputs.
• The delta/sigma D/A converter is incorporated into the A/D-D/A code. The
delta/sigma is now generated using the A/D samples. The operating range
and quality of the delta/sigma waveform are investigated.
Although the S3SB is powered by 5 volts this voltage is regulated down to
the voltage levels needed by the Spartan-3. The I/O lines are powered using 3.3
Volts These lines are NOT 5 Volt tolerant. Applying signals having levels outside
the 0 to 3.3 Volt range WILL damage the S3SB.
The TI C5510 DSK will be used in parts of the exercise to display the fre-
quency content of the D/A output waveforms. We will only be using DSK and
the associated software as a tool and will not go more deeply than necessary
into this hardware/software. EECS 452 does so.
Lab Exercise 2 3 May 17, 2009
Doing DSP Workshop Summer 2009
1.1 PMod modules
Digilent has developed a number of small
circuit boards that it refers as PMod mod-
ules. These 6-pin modules are used to add
various peripheral devices to Digilent FPGA
boards.
The picture to the left shows the the back
sides (where the components are mounted)
of the Digilent PMod-AD1 (top board) and
the PMod-DA2 (bottom board).
The pin spacing is 0.1 inches. Pin 5 on each
module is ground and pin 6 is Vcc .
The number of PMod modules that can be added to a Spartan-3/3E board
depends upon which board is involved. The Basys and Nexys boards have pro-
vision for adding four PMod modules directly. The lab Spartan-3 Starter Boards
use MIB boards to add upto eight PMod connection points per 40 pin board edge
connector. There are three 40 connectors per Starter Board. One would likely
overload the SB power regulator before running out of PMod slots.
For this exercise we will connect PMod modules to the S3SB using a MIB con-
nected plugged into the B1 connector.
Please be careful with the PMod modules. The pins are rather fragile and
they are sensitive to static electricity. EECS 452 has had one or two PMod units
become non-operational each semester. Disconnect the power from the S3SB
when plugging and unplugging a PMod module into the MIB.
For each type of PMod module Digilent makes available a reference manual or
data sheet and a schematic. VHDL support tends to be the user’s responsibility.
A good starting point when working with the PMod modules is to read the
associated reference manuals and to study the schematics and related data
sheets/manuals. We have attempted to place these materials on the Workshop
CD. Please let one of the Workshop coordinators know if any of the materials
contained on the class CD are missing or out of date.
1.2 The S3SB to C5510 connection
A cable connector system is used to connect signals from the C5510 External
Peripheral Interface connector to the A2 connector on the S3SB. A 40 conductor
Lab Exercise 2 4 May 17, 2009
Doing DSP Workshop Summer 2009
cable is used. Signals on the cable alternate with grounds.
C5510 McBSP ports 0 and 1 lines are the primary signals connected. A few
auxiliary signals are also connected.
The C5510’s analog inputs will be used to sample the S3SB D/A outputs gen-
erated in this exercise. The Discrete Fourier Transform is used to analyze the
frequency content of the samples. Support for a graphics display system will
have to be built into our exercises in order to use the S3SB to display the spec-
tra. The display system operates in parallel with and on a non-interfering basis
with this exercise’s VHDL code.
2 PMod-DA2 and PMod-AD1
2.1 PMod-DA2
The Digilent PMod-DA2 module contains two National Semiconductor DAC121S101
12-bit D/A converts.
The National Semiconductor DAC121S101 D/A converters can operate using
using supply voltages (Vs in the range from +2.7 Volts to +5.5 Volts and has rail-
to-rail outputs. Binary format values are loaded in to the converter using a three
wire interface operates using clock rates as high as 30 MHz.
The digital interface signals are:
• data bits,
• sync (active low),
• clock.
The two D/A ICs connect to the sync and clock lines. Each converter has it’s
own data connection.
The D/A output voltages nominally go from 0 volts for a digital value of 0 to
the supply voltage for a digital value of 4095. The output can be made centered
at Vcc/2 swinging plus and minus to this level by use of two’s complement values
where the sign bit (most significant bit) has been complemented.
The DA2 is to be placed in the MIB J7 socket. This is named pmod_d in the
ucf files used in this exercise. Be careful to insert the module so that the supply
pin matches with the VB supply pin on the MIB.
Lab Exercise 2 5 May 17, 2009
Doing DSP Workshop Summer 2009
2.1.1 PMod-DA2 pin assignments
Digital interface (MIB end):
1 sync,
2 D/A 1 data bit stream,
3 D/A 2 data bit stream,
4 shift clock,
5 ground,
6 Vcc.
Analog interface (board top):
1 D/A 1 analog output,
2 no connection,
3 D/A 2 analog output,
4 no connection,
5 ground,
6 Vcc.
2.1.2 PMod-DA2 VHDL driver
The driver expects two’s complement values. These are converted into binary
offset form before being shifted into the D/A converter.
The PMod-DA2 driver entity definition is
entity pmod_dac0 is
Port ( go : in STD_LOGIC;
da_a : in STD_LOGIC_VECTOR (11 downto 0);
da_b : in STD_LOGIC_VECTOR (11 downto 0);
pmod : out STD_LOGIC_VECTOR (3 downto 0);
clk : in STD_LOGIC);
end pmod_dac0;
Twelve-bit values are placed onto the da_a and da_b lines. The go signal
starts a conversion by transitioning from low to high. This transition causes the
da_a and da_b values to be copied into internal registers and the D/A conversion
process to be started.
The pmod lines connect to the 6-pin socket or MIB position where the PMod-
DA2 is mounted.
The clk is used by the driver for its timing. A minimum of approximately 20
clock tics is required between successive go rising transitions.
Lab Exercise 2 6 May 17, 2009
Doing DSP Workshop Summer 2009
The minimum spacing between go rising edge transitions should be 1 µs. The
clock rate should be 60 MHz or less and should high enough so there are at least
20 clock tics between go rising edges.
The entity is designed so that go and clk can be from different clock do-
mains.
2.2 PMod-AD1
This section describes the Digilent PMod-AD1 module, its connections, the de-
vice entity and the design and implementation of single supply op-amp input
amplifiers.
The PMod-AD1 contains two National Semiconductor ADCS7476MSPS 12-bit
successive approximation analog-to-digital converters. The PMod-AD1 is pow-
ered by the PMod/MIB 3.3 Volt supply. Each of the two AD1 PMod input lines
connect to a Selin-Key active lowpass anti-alias filter. Each filter output connects
to an A/D converter input.
The inputs to the PMod-AD1 module are nominally to go between 0 Volts and
3.3 Volts. The board can be damaged if this range is exceeded.
There might be a voltage inversion caused by the input filter amplifiers. If
such inversion is important, verify whether or not it is present.
Besides controlling anti-aliasing the presence of the filter also isolates the
signal source from input to the A/D. The converter is of the charge distribution
type and has a time varying impedance. The filter amplifiers isolate the user
from having to take this into account.
Digital interface:
1 chip select,
2 A/D 1 data bit stream,
3 A/D 2 data bit stream,
4 shift clock,
5 ground,
6 Vcc.
Analog interface
1 A/D 1 analog input,
2 ground,
3 A/D 2 analog input,
4 ground,
5 ground,
6 Vcc.
Lab Exercise 2 7 May 17, 2009
Doing DSP Workshop Summer 2009
2.2.1 PMod-AD1 VHDL driver
The A/D uses offset binary. The driver converts this to two’s complement form
before returning to the caller.
The PMod-AD1 driver entity definition is
entity pmod_adc0 is
Port ( go : in STD_LOGIC;
ad_a : out STD_LOGIC_VECTOR (11 downto 0);
ad_b : out STD_LOGIC_VECTOR (11 downto 0);
pmod : inout STD_LOGIC_VECTOR (3 downto 0);
clk : in STD_LOGIC);
end pmod_adc0;
A rising edge on go input causes the A/D converters to switch from track to
hold and initiates a conversion cycle.
The minimum spacing between go rising edges is 1 µs.
The rising edge of go should be used to copy the results of the immediately
previous conversion from the PMod-AD1 entity (ad_a and ad_b) into local regis-
ters.
The ADCS7476MSPS maximum clock frequency is 40 MHz. The nominal num-
ber of clock tics per conversion is 20. (To me: this needs to be carefully verified.)
A 40 MHz sample rate should allow a sample rate of 1 Msps. I’ve tried over
clocking using a 50 MHz clock. This has worked on the two units that I tested.
In practice one should not do this for real. All bets are off if the data sheet limits
are not observed. A Spartan-3 digital clock multiplier (DCM) is used to generate
a 40 MHz clock waveform.
The entity is designed so that go and clk can be from different clock do-
mains.
2.2.2 Single supply op-amp basics
Information about single supply operational amplifier circuits can be found on
the Workshop handouts web page. The data sheet for the OPA2340 used in this
exercise is also present.
2.2.3 AC coupled level shifter
Remains to be written. Not this summer.
Lab Exercise 2 8 May 17, 2009
Doing DSP Workshop Summer 2009
2.2.4 DC coupled level shifter
See Appendix A
2.2.5 Microphone input amplifier
Not this summer. Or not least not yet.
3 S3SB DDS
A simple DDS dual tone project is used to illustrate the use of the PMod-DA2
module. A slight detour is made to investigate how to initialize a block ram
(BRAM) in order to serve as a sine table ROM.
3.1 DDS logic design
To be covered in discussion.
3.2 Implementing a sine table in a Spartan-3 block RAM
A Spartan-3 block RAM contains 18432 bits and can be configured in a number
of ways. A BRAM is divided into two sections. One section for data (16384 bits)
and one section for parity (2048 bits). There is a parity bit associated with every
8 bits. The parity bits are only parity if they are used that way. The can also be
used as normal memory, perhaps to extend a word size from 16 bits to 18 bits.
When a BRAM is instantiation it is also initialized. The initiation values are
specified in the instantiation template. See Appendix-C.6 for an example. The
data and parity parts are initialized separately. We will be concerned only with
the data portion.
For initialization purposes the data portion is organized in terms of 32 256-
bit words (16384 bits). The 256-bit words go right to left with increasing bit
index.
In this exercise we will be using the BRAM with a 16-bit word size. A 256-bit
initialization would consist of 16-bits words going from right to left. In this case
a 256-bit word holds 16 16-bit values.
The following list of hex values was generated by a MATLAB program for use
in generating a 256 value sine table in a Spartan-3 FPGA block RAM.
Lab Exercise 2 9 May 17, 2009
Doing DSP Workshop Summer 2009
8000
8324
8648
896A
8C8C
8FAB
92C8
95E2
98F9
9C0B
9F1A
A223
A528
A826
AB1F
AE11
There were used by the same MATLAB program to generate the initialization
line
INIT_00 => X"AE11AB1FA826A528A2239F1A9C0B98F995E292C88FAB8C8C896A864883248000",
All of the punctuation on the above line is needed in order to simplify doing
copy-and-paste. The only (slightly) tricky part of the program design was setting
up the print statement loop to print 16 values on a line going from 16th to 1st
going left to right.
The MATLAB program used for the above was organized as follows:
• An array was generated containing the values that were to be sent to the
D/A converter. The values were rounded and scaled to be between -32767
and +32767. However they remain 64-bit floating point values within MATLAB.
• To make the values into offset binary form 32768 can be added. A check
should be made to insure that values were now in the range 1 through
32767.
• If instead, it is desired to output the sine table as 16-bit two’s complement
integers a different procedure is needed. The positive values map directly
into unsigned 16-bit integer bit patterns. The negative values need to be
mapped into their equivalent unsigned 16-bit values.
The (floating point) value -1 needs to have the same 16-bit pattern as 65535
which is 216− 1. The value -2 needs to have the unsigned 16-bit equivalent
value of 216− 2. So, if a value is negative the value in the array needs to
have 65536 added to it. Otherwise it is left unchanged. This generates
a set of values when printed as unsigned 16-bit integers will generate the
desired 2’s complement 16-bit bit patterns.
Lab Exercise 2 10 May 17, 2009
Doing DSP Workshop Summer 2009
• A loop was used to print the values mimicking the Xilinx initialization for-
mat. The above line is the one generated for the first 16 values.
• The set of lines were copy-pasted into a copy of the Xilinx template replac-
ing the corresponding zero initialization lines.
The MATLAB script to accomplish this contained 13 non-blank lines (blank
lines were used as white space) including the limit checks and a sanity check on
one value.
The %04X format descriptor was used to print out four uppercase hex digits
with leading zeros.
The above procedure was simple to implement and facilitated a quick and
easy way to incorporate initialization values into the block RAM instantiation
template.
4 S3SB A/D to D/A loop
4.1 The cable
4.1.1 S3SB B1 connector to MIB
Lab Exercise 2 11 May 17, 2009
Doing DSP Workshop Summer 2009
# MIB sockets on B1 names compatible with Nexys and Basys
# PMod A : J1 on MIB to B1
#
#NET "pmod_a<0>" LOC = "C10" | IOSTANDARD = LVCMOS33;
#NET "pmod_a<1>" LOC = "E10" | IOSTANDARD = LVCMOS33;
#NET "pmod_a<2>" LOC = "T3" | IOSTANDARD = LVCMOS33;
#NET "pmod_a<3>" LOC = "C11" | IOSTANDARD = LVCMOS33;
# PMod B : J3 on MIB to B1
#
#NET "pmod_b<0>" LOC = "R10" | IOSTANDARD = LVCMOS33;
#NET "pmod_b<1>" LOC = "D12" | IOSTANDARD = LVCMOS33;
#NET "pmod_b<2>" LOC = "T7" | IOSTANDARD = LVCMOS33;
#NET "pmod_b<3>" LOC = "E11" | IOSTANDARD = LVCMOS33;
# PMod C : J5 on MIB to B1
#
#NET "pmod_c<0>" LOC = "M6" | IOSTANDARD = LVCMOS33;
#NET "pmod_c<1>" LOC = "C16" | IOSTANDARD = LVCMOS33;
#NET "pmod_c<2>" LOC = "C15" | IOSTANDARD = LVCMOS33;
#NET "pmod_c<3>" LOC = "D16" | IOSTANDARD = LVCMOS33;
# PMod D : J7 on MIB to B1
#
#NET "pmod_d<0>" LOC = "F15" | IOSTANDARD = LVCMOS33;
#NET "pmod_d<1>" LOC = "H15" | IOSTANDARD = LVCMOS33;
#NET "pmod_d<2>" LOC = "G16" | IOSTANDARD = LVCMOS33;
#NET "pmod_d<3>" LOC = "J16" | IOSTANDARD = LVCMOS33;
Figure 1: S3SB B1 PMod MIB socket connections.
Lab Exercise 2 12 May 17, 2009
Doing DSP Workshop Summer 2009
5 Prelab
Handwritten work will not be graded. Prelabs are to be done individually
and are to be handed in at the start of the lab period. Well, if this were EECS
452 this would be the case. But this is summer and what the heck, just see if
you can find the answers.
5.1 The S3SB
• (T or F) S3SB input signal lines MUST connect only to 3.3 Volt logic.
5.2 The PMod-DA2 module
• What is the part number of the D/A device used on the module?
• Does the digital input to the D/A use offset or signed binary?
• What is the maximum shift clock frequency?
• What is the output slew rate in V/µs?
You might should look at the settling time and think about what it might
mean if using high sample rates. No answer needed.
5.3 The PMod-AD1 module
• What is the part number of the A/D device used on the module?
• Does the A/D digital output use offset or signed binary?
• What is the maximum shift clock frequency?
• What is the maximum thruput rate?
• What is the resolution with no missing codes?
• What is the -3 dB full power bandwidth using a 3V supply?
5.4 DTMF
Use the web to research DTMF. Determine the row and column frequencies and
bring the list to lab. These will be used to operate a 1 MHz clocked 32 bit phase
modulator. Use the frequencies to determine the FTV values needed and bring
these to lab in hexadecimal form as well.
Lab Exercise 2 13 May 17, 2009
Doing DSP Workshop Summer 2009
5.4.1 DC coupled level shifter
Design a gain of 1/2 level shifting amplifier. The circuit diagram and analysis
for such can be found in the appendices.
With one exception it should be possible to use only 10 kOhm resistors. The
exception can make use of two 10 kOhm resistors perhaps connected as a serial
or maybe as a parallel pair.
The proto-block should be connected to the PMod-AD1 module using a 6 pin
cable. This cable should also be used to supply 3.3 V and ground for you circuit.
The input signal should should come from one of the BNC connectors on a
PMod-CON2 (dual BNC) module. This should be connected to the proto-board
using a 6-pin cable.
Draw a sketch layout your parts on the white board. This is essentially a
planning document for use in lab.
In your prelab write-up include a diagram of the circuit (can be a copy of the
one in this document or hand drawn) listing part values along with a copy of
your layout sketch.
6 Exercise
Files for this exercise are contained in the following directories:
• DAC_test0. Generates ramps using the DA2.
• DDS_0. Dual channel DDS. Generates tones for DTMF signalling.
• DA_DeltaSigma. A simple one-bit DA converter.
• AD-DA. The PMod AD1 is used take samples and echo them onto the DA2.
• support. Support VHDL files not specific to any one design.
6.1 Initial testing of the PMod-DA2 and its driver
This design is intended is intended as a warm up. The VHDL works without
modification. You are to create a project, add the supplied files, generate the bit
file and down load it into the FPGA. You also need to properly install the DA2
module and use the oscilloscope in order to observe the resulting DA2 outputs.
Please remove the power to the S3SB when adding and/or removing modules.
Lab Exercise 2 14 May 17, 2009
Doing DSP Workshop Summer 2009
The main files files are contained in the DAC_test0 directory. The DA2 driver
VHDL is located in the support directory.
Reading the VHDL you should have a guod idea what the two ramp periods
are. Verify these using the oscilloscope. If you get significantly different dura-
tions than expected, figure out why.
You probably want to DC couple the oscilloscope inputs.
Observe the straightness/linearity (or the lack of) of the ramps. How fast
does the D/A output slew (volt/microsecond) when resetting (going from highest
value to lowest)? Is this consistent with the what might be expected based on
information contained on the D/A data sheet?
6.2 S3SB DDS and DTMF
In this part of the exercise you are given an almost finished VHDL code that is to
generate DTMF tones. It remains to enter the needed FTV values and to combine
the digital outputs of two DDS generators prior to D/A conversion.
The files specific for this design are contained in the DDS_0 directory. The
file DDS0_top.vhd is the top.
You will also need to determine from the code what sample rate, fs , is being
used.
As supplied, the VHDL code is set up to implement two single tone direct
digital synthesizers. One for the row frequencies and one for the column fre-
quencies. A two-channel PMod-DA2 module is used to produce the individual
analog waveforms. The row and column frequencies are determined using the
eight S3SB slide switches. The four left most switches select the row in the DTMF
matrix and the right most four switches select the column in the DTMF matrix.
The FTV values to be used need to be specified in get_FTV.vhd.
Before combining the two DDS outputs to generate a DTMF waveform it is
worthwhile to implement the project as given. and verify operation. No sense
starting with a non-working set of files. The individually generated row and
column frequencies can be checked using the oscilloscope.
Once the code is felt to be functioning as desired, combine the digital outputs
of the two synthesizers into a single DTFM digital value and output this to both
D/As. Verify that all is well on both channels using the oscilloscope. The oscillo-
scopes have the ability to display spectra. Can you make it do so? Demonstrate
to the lab coordinator.
Lab Exercise 2 15 May 17, 2009
Doing DSP Workshop Summer 2009
6.3 Delta/Sigma DAC at 0 Hz
This design is based on the Xilinx LogiCore OPB Delta-Sigma DAC (V1.01a). This
can be found on the Workshop CD in the DACinfo directory. The files for this
design are contained in the DA_DeltaSigma directory.
Include the Delta/Sigma DC module into the A/D-D/A code. Use the A/D
channel 0 values as the input to the Delta/Sigma module. Use the top 8 bits of
the 12-bit A/D values. It will be necessary to invert the most significant bit. This
is easily done using the not operator.
The output wave form is a digital pulse width modulated waveform. This can
be found on pin 1 on the MIB J1 socket. This is pin 0 of pmod_a in the ucf file.
Use a Digilent six wire cable to connect J1 pins to a white proto-board. Imple-
ment a RC lowpass filter using as shown in the Xilinx LogiCore document. The
DC output is found across the capacitor. The digital waveform is found at the
resister end of the lowpass filter.
The design implements an eight-bit DAC using delta-sigma modulation. The
S3SB slide slide switches are read as a binary number and are used to generate
a DC corresponding DC level. A value of 0 results in a nominal 0 Volt output. A
value of 255 results in a nominal full scale (+3.3 Volt) output.
Observe the DC outputs and the digital waveforms producing them for switch
setting values of
• 0
• 1
• 2
• 128
• 253
• 254
• 255
Feel free to explore other values as well. Are the waveforms reasonable look-
ing? Is there waveform ringing?
6.4 PMod-AD1 DC coupled level shifting circuit
This part of the exercise assumes that the PMod-AD1 is cabled to the proto-board
and supplies 3.3 Volts on pin 6 for powering the amplifier. (Don’t forget to also
connect ground to pin 5.) A power supply external to the S3SB should not be used
to power circuit!
Lab Exercise 2 16 May 17, 2009
Doing DSP Workshop Summer 2009
It’s not cool working on the amplifier with the power connected!
Using a white block build the level shift op-amp circuit and use the signal
generator and scope to verify that it works as expected. The bandwidth (3 dB)
should be an interesting thing to know. Is it consistent with the sample rates
(≤ 1MHz) that we plan to use?
The output of the amplifier should be connected to the A/D 0 input.
This circuit will be used in the coming parts of the exercise as well as future
exercises.
6.5 S3SB A/D echoed to S3SB D/A
The purpose of this section is to take samples using the PMod-AD1 and then con-
vert them back to analog form using the PMod-DA2. If we can’t do this simple
task successfully then it makes no sense to move onto more complex applica-
tions. If things look near expected we have a confidence builder.
The files for this design are contained in the AD-DA directory. The top file for
doing this is ad_da_01_top.vhd.
Any additional needed VHDL files should be present in the support directory.
The S3SB switches set a clock divide value, D. This value is used to generate
sample pulses at a frequency 1 MHz divided by D. For example, to use a sample
rate of 1 MHz enter 1 into the S3SB slide switches.
Use the signal generator set at 1 kHz and determine the signal input levels
at which the D/A output saturates. Is this consistent with what you expect?
How flat is the response going from 1 kHz to 500 kHz? Nothing much specific
needed for this but maybe a sketch and a few comments. Is there any significant
distortion using an almost saturating input signal level and an input frequency
of 100 kHz?
Set the sample rate to 200 kHz using the switches and look at the quality of
the waveform and run some frequencies to demonstrate aliasing.
6.6 Comparing the DA2 and Delta/Sigma DACs and evaluation
Create a new directory, maybe name it AD-DA_with_DeltaSigma (or whatever
might strike your fancy). Collect the VHDL files that would be needed add one
channel of delta-sigma D/A conversion to the AD-DA VHDL.
Lab Exercise 2 17 May 17, 2009
Doing DSP Workshop Summer 2009
Make any needed changes in the AD-DA VHDL to add the delta-sigma modula-
tor. This should be a relatively easy task with only a few additional lines of code
needed. Use the top 8 bits of the A/D channel output to feed the Delta/Sigma
D?A in place of the slide switches.
Don’t forget to uncomment any used pmod_a pins in the ucf file.
The output waveforms of DA2 channel 0 and the delta-sigma low pass filter
should nominally be identical. At least over the useful range of the delta-sigma
DAC. Which is? To investigate use the oscillator and scope.
What are the characteristics of the Delta/Sigma DAC when not in the useful
range?
We plan to add looking at the spectra of both the DA2 and Delta/Sigma DACs.
However, we aren’t there yet ourselves. The results might or might not be inter-
esting. Only doing will tell. Will provide more information when the lab meets.
A Single supply level shifting circuit
A recurring problem when working with single supply devices such as theA/D
converter used on the PMod board is driving them with zero referenced inputs
which swing between positive and negative voltage levels. This note analyzes
an op-amp circuit that can be used to shift a zero volt referenced input to a
reference equal to one-half the supply voltage.
The resistors included in the workstation boxes have an accuracy of ±5%.
This means there will be a small amount of level shift and gain error. In a more
“real” situation one might to use more accurate resistors or an integrated circuit
designed specifically for this application.
The output impedance of any signal source used with this circuit will also
have an effect.
A.1 Analysis
The op-amp in Figure 2 is assumed to be powered using the same supply voltage,
vs as the devices that follow it.
Summing the currents flowing into the positive input’s node gives
vi − va
R3
+vs − va
R5
=va
R4
viR3
+vsR5
= va
(
1
R3+
1
R4
+1
R5
)
Lab Exercise 2 18 May 17, 2009
Doing DSP Workshop Summer 2009
oN
oO
oQ
oP
oR
H
J
îáîç
îë
î~
Figure 2: Single supply op-amp level shifting circuit.
va =
(
vi
R3
+vs
R5
)
R3R4R5
R3R4 + R3R5 + R4R5
The voltage between the plus and input nodes is assumed to be zero. Giving
vo = vaR1 + R2
R1
vo =
(
vi
R3
+vs
R5
)
R3R4R5(R1 + R2)
R1 (R3R4 + R3R5 + R4R5)
The gain to vs is
gs =R3R4(R1 + R2)
R1 (R3R4 + R3R5 + R4R5)
The gain to vi is
gi = gsR5
R3
.
The equation for gs gives the relation
gsR1 (R3R4 + R3R5 + R4R5) = R3R4(R1 + R2) .
The goal in this note is to center the output level at vs/2 which gives
(R3R4 + R3R5 + R4R5)
R3R4
=2(R1 + R2)
R1
.
1+R5
R4
+R5
R3
= 2
(
1+R2
R1
)
The values of R3 and R5 are related by the desired signal gain gi.
R5
R4
+ 2gi = 1+2R2
R1
If R4 = R5 then
gi =R2
R1
.
Lab Exercise 2 19 May 17, 2009
Doing DSP Workshop Summer 2009
A.2 A design procedure
Choose a signal gain gi and a value for R3. Then
R4 = R5 = 2giR3 .
The R1 and R2 values are related as
R2 = giR1 .
Typically one keeps the Rn ≥ 10k, n = 1,2,3,4,5.
A.3 Choice of op-amp device
Almost all of the manufacturers making integrated circuit op-amp devices sell
low voltage, rail-to-rail devices. Many of these will work over unity gain band-
widths of 5 MHz and higher.
The lab currently uses the Burr-Brown (TI) 8-pin OPA2340 dual op-amp. One
of the reasons this was chosen was because it was still available at DigiKey in
8-pin DIP package. Though hole components such as the 8-pin DIP package are
slowing vanishing.
1
2
3
4
8
7
6
5
V+
Out B
–In B
+In B
Out A
–In A
+In A
V–
OPA2340
A
B
Supply voltage 2.7V to 5.5V
Unity gain bandwidth 5.5 MHz
Figure from the Burr Brown OPA340 data sheet.
It is strongly recommended that a bypass capacitor on the order of 0.1 µF be
placed across Vcc and ground as close to the chip as feasible. Using the white
plug boards it is easy to mount the capacitor bridging the chip and straddling its
sides. This is done to enhance stability (i.e., to prevent it from oscillating) and
to perhaps improve a noise performance.
Lab Exercise 2 20 May 17, 2009
Doing DSP Workshop Summer 2009
A.4 White board construction
This is an example of how
NOT to build one channel
of level shifting. Notice
the disc bypass capacitor
is not bypassing the chip
but a piece of wire. TO-
TALLY in the wrong place.
This unit was claimed to
be “noisy”.
This is an example of a
good implementation of
one channel of level shift-
ing. Notice the disc bypass
capacitor is bridging the
op-amp chip. The single
wire sticking up was used
to connect a scope probe
ground.
B Listings for the DA1 ramp test
B.1 Top level
----------------------------------------------------------------------------------
-- Company: EECS 452
-- Engineer: Kurt Metzger
--
-- Create Date: 11:23:56 01/19/2008
-- Design Name:
-- Module Name: DACtest0top - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
Lab Exercise 2 21 May 17, 2009
Doing DSP Workshop Summer 2009
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity DACtest0top is
Port ( pmod_d : out STD_LOGIC_VECTOR (3 downto 0);
led : out STD_LOGIC_VECTOR (7 downto 0);
mclk : in STD_LOGIC);
end DACtest0top;
architecture Behavioral of DACtest0top is
signal clk, go : std_logic;
signal pmod : std_logic_vector(3 downto 0);
signal ramp_a, ramp_b : std_logic_vector(11 downto 0);
begin
pmod_d <= pmod;
clk <= mclk;
led <= ramp_b(11 downto 4);
dac : entity work.pmod_dac0
port map(go => go, da_a => ramp_a, da_b => ramp_b,
pmod => pmod, clk => clk);
ramper : entity work.rampgen
port map(go => go, ramp_a => ramp_a, ramp_b => ramp_b, clk => clk);
end Behavioral;
B.2 Ramp generator
----------------------------------------------------------------------------------
-- Company: EECS 452
Lab Exercise 2 22 May 17, 2009
Doing DSP Workshop Summer 2009
-- Engineer: Kurt Metzger
--
-- Create Date: 11:49:11 01/19/2008
-- Design Name:
-- Module Name: rampgen - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity rampgen is
Port ( go : out STD_LOGIC;
ramp_a : out STD_LOGIC_VECTOR (11 downto 0);
ramp_b : out STD_LOGIC_VECTOR (11 downto 0);
clk : in STD_LOGIC);
end rampgen;
architecture Behavioral of rampgen is
signal a_ramp, b_ramp : std_logic_vector(11 downto 0);
signal counter : std_logic_vector(5 downto 0); -- 6 bits
begin
ramp_a <= a_ramp;
ramp_b <= b_ramp;
process(clk) is
begin
if rising_edge(clk) then
counter <= counter+1;
if counter = 0 then -- divides clock down by 64
go <= ’0’;
a_ramp <= a_ramp+1;
Lab Exercise 2 23 May 17, 2009
Doing DSP Workshop Summer 2009
b_ramp <= b_ramp+3;
else
go <= ’1’;
end if;
end if;
end process;
end Behavioral;
B.3 PMod-DA2 support
----------------------------------------------------------------------------------
-- Company: EECS 452
-- Engineer: Kurt Metzger
--
-- Create Date: 11:46:04 01/19/2008
-- Design Name:
-- Module Name: pmod_dac0 - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity pmod_dac0 is
Port ( go : in STD_LOGIC;
da_a : in STD_LOGIC_VECTOR (11 downto 0);
da_b : in STD_LOGIC_VECTOR (11 downto 0);
pmod : out STD_LOGIC_VECTOR (3 downto 0);
clk : in STD_LOGIC);
end pmod_dac0;
architecture Behavioral of pmod_dac0 is
Lab Exercise 2 24 May 17, 2009
Doing DSP Workshop Summer 2009
signal sync_n, sclk : std_logic := ’1’;
signal counter : std_logic_vector(3 downto 0);
signal d_a, d_b : std_logic_vector(11 downto 0);
signal sr_a, sr_b : std_logic_vector(15 downto 0);
signal goo, clear_goo : std_logic := ’0’;
signal mygoo : std_logic_vector(1 downto 0);
type t_state is (s_idle, s_wait, s_run);
signal state : t_state := s_idle;
begin
pmod(0) <= sync_n; pmod(1) <= sr_a(15);
pmod(2) <= sr_b(15); pmod(3) <= sclk;
process(go, clear_goo) is begin
if clear_goo = ’1’ then goo <= ’0’;
elsif rising_edge(go) then
d_a <= da_a; d_b <= da_b; -- copy input values
goo <= ’1’; -- note go happened
end if;
end process;
process(clk, da_a, da_b) is
begin
if rising_edge(clk) then
sclk <= not sclk; -- generate clk/2 shift clock
mygoo <= mygoo(0) & goo; -- sample go signal
case state is
when s_idle =>
sclk <= ’1’; -- hold DA clock high
if mygoo = "11" then clear_goo <= ’1’; else clear_goo <= ’0’; end if;
if mygoo = "01" then -- rising edge test
sr_a <= "0000" & not d_a(11) & d_a(10 downto 0);
sr_b <= "0000" & not d_b(11) & d_b(10 downto 0);
counter <= (others => ’0’);
sync_n <= ’0’;
sclk <= ’0’;
state <= s_wait;
end if;
when s_wait =>
state <= s_run;
when s_run =>
if sclk = ’0’ then
sr_a <= sr_a(14 downto 0) & ’0’;
sr_b <= sr_b(14 downto 0) & ’0’;
counter <= counter+1;
if counter = 15 then
sync_n <= ’1’;
state <= s_idle;
end if;
Lab Exercise 2 25 May 17, 2009
Doing DSP Workshop Summer 2009
end if;
end case;
end if;
end process;
end Behavioral;
C Listings for the DDS/DTMF exercise
C.1 Top level
----------------------------------------------------------------------------------
-- Company: Doing DSP Workshop
-- Engineer: Kurt Metzger
--
-- Create Date: 12:23:41 05/16/2009
-- Design Name:
-- Module Name: DDS0top - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity DDS0top is
Port ( pmod_d : out STD_LOGIC_VECTOR (3 downto 0);
swt : in STD_LOGIC_VECTOR (7 downto 0);
mclk : in STD_LOGIC);
end DDS0top;
architecture Behavioral of DDS0top is
Lab Exercise 2 26 May 17, 2009
Doing DSP Workshop Summer 2009
signal clk : std_logic;
signal FTV0, FTV1 : std_logic_vector(31 downto 0);
signal address_a, address_b : std_logic_vector(7 downto 0);
signal sine_a, sine_b : std_logic_vector(15 downto 0);
signal fs : std_logic;
begin
clk <= mclk;
fetch_ftv : entity work.get_ftv
port map(
swt => swt, -- slide switches
FTV0 => FTV0, -- FTV0
FTV1 => FTV1, -- FTV1
clk => clk,
reset => ’0’);
sample_clock : entity fs_clock
port map (
fs => fs,
clk => clk);
DDS0 : entity work.DDS
port map (
FTV => FTV0, -- FTV value to be used by DDS channel 0
ROM_address => address_a,
fs => fs,
clk => clk,
reset => ’0’);
DDS1 : entity work.DDS
port map (
FTV => FTV1, -- FTV value to be used by DDS channel 1
ROM_address => address_b,
fs => fs,
clk => clk,
reset => ’0’);
sine_table_a : entity work.sine_rom
port map (
address_a => address_a,
data_a => sine_a,
address_b => address_b,
data_b => sine_b,
clk => clk);
pmod_DA2_module : entity work.pmod_dac0
port map (
da_a => sine_a(15 downto 4), -- truncating!
da_b => sine_b(15 downto 4), -- truncating!
Lab Exercise 2 27 May 17, 2009
Doing DSP Workshop Summer 2009
go => not fs,
pmod => pmod_d,
clk => clk);
end Behavioral;
C.2 Listing for FTV get entity
----------------------------------------------------------------------------------
-- Company: Doing DSP Workshop
-- Engineer: Kurt Metzger
--
-- Create Date: 10:12:21 05/16/2009
-- Design Name:
-- Module Name: get_FTV - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity get_FTV is
Port ( swt : in STD_LOGIC_VECTOR (7 downto 0);
FTV0 : out STD_LOGIC_VECTOR (31 downto 0);
FTV1 : out STD_LOGIC_VECTOR (31 downto 0);
clk : in STD_LOGIC;
reset : in STD_LOGIC);
end get_FTV;
architecture Behavioral of get_FTV is
constant row1 : std_logic_vector(31 downto 0) := X"00000000";
constant row2 : std_logic_vector(31 downto 0) := X"00000000";
Lab Exercise 2 28 May 17, 2009
Doing DSP Workshop Summer 2009
constant row3 : std_logic_vector(31 downto 0) := X"00000000";
constant row4 : std_logic_vector(31 downto 0) := X"00000000";
constant col1 : std_logic_vector(31 downto 0) := X"00000000";
constant col2 : std_logic_vector(31 downto 0) := X"00000000";
constant col3 : std_logic_vector(31 downto 0) := X"00000000";
constant col4 : std_logic_vector(31 downto 0) := X"00000000";
begin
FTV0 <= row1 when swt(7 downto 4) = "1000" else
row2 when swt(7 downto 4) = "0100" else
row3 when swt(7 downto 4) = "0010" else
row4 when swt(7 downto 4) = "0001" else
X"00000000";
FTV1 <= col1 when swt(3 downto 0) = "1000" else
col2 when swt(3 downto 0) = "0100" else
col3 when swt(3 downto 0) = "0010" else
col4 when swt(3 downto 0) = "0001" else
X"00000000";
end Behavioral;
C.3 Listing for fs timing entity
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 21:26:46 05/16/2009
-- Design Name:
-- Module Name: fs_clock - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
Lab Exercise 2 29 May 17, 2009
Doing DSP Workshop Summer 2009
--library UNISIM;
--use UNISIM.VComponents.all;
entity fs_clock is
Port ( fs : out STD_LOGIC;
clk : in STD_LOGIC);
end fs_clock;
architecture Behavioral of fs_clock is
signal counter : std_logic_vector(5 downto 0);
begin
tic : process(clk)
begin
if rising_edge(clk) then
counter <= counter-1;
fs <= ’0’;
if counter = 0 then
counter <= "110001"; -- 49
fs <= ’1’;
end if;
end if;
end process;
end Behavioral;
C.4 Listing for the basic DDS
----------------------------------------------------------------------------------
-- Company: Doing DSP Workshop
-- Engineer: K. Metzger
--
-- Create Date: 11:33:39 05/16/2009
-- Design Name:
-- Module Name: DDS - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
Lab Exercise 2 30 May 17, 2009
Doing DSP Workshop Summer 2009
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity DDS is
Port ( FTV : in STD_LOGIC_VECTOR (31 downto 0);
ROM_address : out std_logic_vector(7 downto 0);
fs : in STD_LOGIC;
clk : in STD_LOGIC;
reset : in std_logic);
end DDS;
architecture Behavioral of DDS is
signal accumulator : std_logic_vector(31 downto 0);
begin
ROM_address <= accumulator(31 downto 24); -- top 8 bits
process(clk, reset)
begin
if reset = ’1’ then
elsif rising_edge(clk) then
if fs = ’1’ then
accumulator <= accumulator + FTV;
end if;
end if;
end process;
end Behavioral;
C.5 Listing of MATLAB BRAM sine table generator
clear all;
fig = 1;
N = 256;
A = 32767;
sine = round(A*sin(2*pi*[0:N-1]/N));
min(sine) % check most neg value
max(sine) % check most pos value
Lab Exercise 2 31 May 17, 2009
Doing DSP Workshop Summer 2009
fprintf(’%04X\n’,sine(5));
for i = [1:length(sine)]
if sine(i) < 0
sine(i) = 65536+sine(i);
end
end
for ctr = [0:15]
fprintf(’ INIT_%02X => X"’, ctr);
fprintf(’%04X’, sine(ctr*16+[16:-1:1]));
fprintf(’",\n’);
end
C.6 BRAM sine ROM template
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 20:51:58 09/21/2006
-- Design Name:
-- Module Name: sine_rom - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;
entity sine_rom is
Port ( address_a : in STD_LOGIC_VECTOR (7 downto 0);
data_a : out STD_LOGIC_VECTOR (15 downto 0);
address_b : in std_logic_vector(7 downto 0);
data_b : out std_logic_vector(15 downto 0);
clk : in STD_LOGIC);
Lab Exercise 2 32 May 17, 2009
Doing DSP Workshop Summer 2009
end sine_rom;
architecture Behavioral of sine_rom is
signal DOA, DOB : std_logic_vector(15 downto 0);
signal ADDRA, ADDRB : std_logic_vector(9 downto 0);
begin
ADDRA <= "00" & address_a;
data_a <= DOA(15 downto 0);
ADDRB <= "00" & address_b;
data_b <= DOB(15 downto 0);
-- RAMB16_S18_S18: Virtex-II/II-Pro, Spartan-3/3E 1k x 16 + 2 Parity bits Dual-Port RAM
-- Xilinx HDL Language Template version 8.2.2i
RAMB16_S18_S18_inst : RAMB16_S18_S18
generic map (
INIT_A => X"00000", -- Value of output RAM registers on Port A at startup
INIT_B => X"00000", -- Value of output RAM registers on Port B at startup
SRVAL_A => X"00000", -- Port A ouput value upon SSR assertion
SRVAL_B => X"00000", -- Port B ouput value upon SSR assertion
WRITE_MODE_A => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
WRITE_MODE_B => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
SIM_COLLISION_CHECK => "ALL", -- "NONE", "WARNING", "GENERATE_X_ONLY", "ALL
-- The follosing INIT_xx declarations specify the intiial contents of the RAM
-- Address 0 to 255
INIT_00 => X"2E112B1F2826252822231F1A1C0B18F915E212C80FAB0C8C096A064803240000",
INIT_01 => X"584255F5539B51334EBF4C3F49B4471C447A41CE3F173C56398C36BA33DF30FB",
INIT_02 => X"750473B5725470E26F5E6DC96C236A6D68A666CF64E862F160EB5ED75CB35A82",
INIT_03 => X"7FF57FD87FA67F617F097E9C7E1D7D897CE37C297B5C7A7C79897884776B7641",
INIT_04 => X"776B788479897A7C7B5C7C297CE37D897E1D7E9C7F097F617FA67FD87FF57FFF",
INIT_05 => X"5CB35ED760EB62F164E866CF68A66A6D6C236DC96F5E70E2725473B575047641",
INIT_06 => X"33DF36BA398C3C563F1741CE447A471C49B44C3F4EBF5133539B55F558425A82",
INIT_07 => X"03240648096A0C8C0FAB12C815E218F91C0B1F1A2223252828262B1F2E1130FB",
INIT_08 => X"D1EFD4E1D7DADAD8DDDDE0E6E3F5E707EA1EED38F055F374F696F9B8FCDC0000",
INIT_09 => X"A7BEAA0BAC65AECDB141B3C1B64CB8E4BB86BE32C0E9C3AAC674C946CC21CF05",
INIT_0A => X"8AFC8C4B8DAC8F1E90A2923793DD9593975A99319B189D0F9F15A129A34DA57E",
INIT_0B => X"800B8028805A809F80F7816481E38277831D83D784A485848677877C889589BF",
INIT_0C => X"8895877C8677858484A483D7831D827781E3816480F7809F805A8028800B8001",
INIT_0D => X"A34DA1299F159D0F9B189931975A959393DD923790A28F1E8DAC8C4B8AFC89BF",
INIT_0E => X"CC21C946C674C3AAC0E9BE32BB86B8E4B64CB3C1B141AECDAC65AA0BA7BEA57E",
INIT_0F => X"FCDCF9B8F696F374F055ED38EA1EE707E3F5E0E6DDDDDAD8D7DAD4E1D1EFCF05",
-- Address 256 to 511
INIT_10 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_11 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_12 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_13 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_14 => X"0000000000000000000000000000000000000000000000000000000000000000",
Lab Exercise 2 33 May 17, 2009
Doing DSP Workshop Summer 2009
INIT_15 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_16 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_17 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_18 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_19 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_1F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 512 to 767
INIT_20 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_21 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_22 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_23 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_24 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_25 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_26 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_27 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_28 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_29 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_2F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 768 to 1023
INIT_30 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_31 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_32 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_33 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_34 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_35 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_36 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_37 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_38 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_39 => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3A => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3B => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3C => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3D => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3E => X"0000000000000000000000000000000000000000000000000000000000000000",
INIT_3F => X"0000000000000000000000000000000000000000000000000000000000000000",
-- The next set of INITP_xx are for the parity bits
-- Address 0 to 255
INITP_00 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_01 => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 256 to 511
INITP_02 => X"0000000000000000000000000000000000000000000000000000000000000000",
Lab Exercise 2 34 May 17, 2009
Doing DSP Workshop Summer 2009
INITP_03 => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 512 to 767
INITP_04 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_05 => X"0000000000000000000000000000000000000000000000000000000000000000",
-- Address 768 to 1023
INITP_06 => X"0000000000000000000000000000000000000000000000000000000000000000",
INITP_07 => X"0000000000000000000000000000000000000000000000000000000000000000")
port map (
DOA => DOA, -- Port A 16-bit Data Output
DOB => DOB, -- Port B 16-bit Data Output
-- DOPA => DOPA, -- Port A 2-bit Parity Output
-- DOPB => DOPB, -- Port B 2-bit Parity Output
ADDRA => ADDRA, -- Port A 10-bit Address Input
ADDRB => ADDRB, -- Port B 10-bit Address Input
CLKA => CLK, -- Port A Clock
CLKB => CLK, -- Port B Clock
DIA => X"0000", -- Port A 16-bit Data Input
DIB => X"0000", -- Port B 16-bit Data Input
DIPA => "00", -- Port A 2-bit parity Input
DIPB => "00", -- Port-B 2-bit parity Input
ENA => ’1’, -- Port A RAM Enable Input
ENB => ’1’, -- PortB RAM Enable Input
SSRA => ’0’, -- Port A Synchronous Set/Reset Input
SSRB => ’0’, -- Port B Synchronous Set/Reset Input
WEA => ’0’, -- Port A Write Enable Input
WEB => ’0’ -- Port B Write Enable Input
);
-- End of RAMB16_S18_S18_inst instantiation
end Behavioral;
D Listings for the Delta/Sigma DC exercise
D.1 Top level
----------------------------------------------------------------------------------
-- Company: Doing DSP Workshop
-- Engineer: Kurt Metzger
--
-- Create Date: 12:23:41 05/16/2009
-- Design Name:
-- Module Name: DeltaSigma_top - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
Lab Exercise 2 35 May 17, 2009
Doing DSP Workshop Summer 2009
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity DeltaSigma_top is
Port ( pmod_a : out STD_LOGIC_VECTOR (3 downto 0);
swt : in STD_LOGIC_VECTOR (7 downto 0);
mclk : in STD_LOGIC);
end DeltaSigma_top;
architecture Behavioral of DeltaSigma_top is
signal clk : std_logic;
signal dac_out : std_logic;
begin
clk <= mclk;
pmod_a <= pmod_0(3) & pmod_1(1) & pmod_0(1) & pmod_0(0);
dsigma : entity work.DeltaSigmaDAC
port map(
input => swt,
ouput => dac_out,
clk => clk);
end Behavioral;
D.2 The Delta/Sigma modulator
----------------------------------------------------------------------------------
-- Company: Doing DSP Workshop
-- Engineer: Kurt Metzger
--
-- Create Date: 12:23:41 05/16/2009
-- Design Name:
Lab Exercise 2 36 May 17, 2009
Doing DSP Workshop Summer 2009
-- Module Name: DeltaSigmaDAC - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity DeltaSigmaDAC is
Port ( input : STD_LOGIC_VECTOR (7 downto 0);
output : out STD_LOGIC;
clk : in STD_LOGIC);
end DeltaSigmaDAC;
architecture Behavioral of DeltaSigmaDAC is
signal dac_out : std_logic;
signal value, comparison, Qout : std_logic_vector(9 downto 0);
signal filtered_error : std_logic_vector(9 downto 0);
begin
value <= "00" & input;
comparison <= value + filtered_error;
Qout <= comparison(9) & comparison(9) & "00000000";
output <= Qout(9);
Hofz : process(clk)
begin
if rising_edge(clk) then
filtered_error <= Qout + comparison;
end if;
end process;
end Behavioral;
Lab Exercise 2 37 May 17, 2009
Doing DSP Workshop Summer 2009
E Listings for the S3SB AD-DA test
E.1 Top level
----------------------------------------------------------------------------------
-- Company: EECS 452
-- Engineer: Kurt Metzger
--
-- Create Date: 10:53:53 12/24/2006
-- Design Name:
-- Module Name: ad_da_01_top - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Revision 0.02 - Updated for Winter 2008 .. 26Jan08 .. KM
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity ad_da_01_top is
Port ( pmod_b : inout STD_LOGIC_VECTOR (3 downto 0);
pmod_d : out STD_LOGIC_VECTOR (3 downto 0);
led : out STD_LOGIC_VECTOR(7 downto 0);
swt : in STD_LOGIC_VECTOR(7 downto 0);
mclk : in STD_LOGIC);
end ad_da_01_top;
architecture Behavioral of ad_da_01_top is
signal pmod_ad1 : std_logic_vector(3 downto 0);
signal pmod_da2 : std_logic_vector(3 downto 0);
signal ad0, ad1 : std_logic_vector(11 downto 0);
signal clk : std_logic;
signal strobe : std_logic;
signal reset : std_logic;
signal clk40 : std_logic;
begin
Lab Exercise 2 38 May 17, 2009
Doing DSP Workshop Summer 2009
pmod_ad1 <= pmod_b; -- connect PMod-AD1 module
pmod_d <= pmod_da2; -- connect PMod-DA2 module
reset <= ’0’;
timing_module : entity work.timing
port map(
strobe => strobe,
swt => swt,
clk => clk,
reset => reset);
AD_module : entity work.pmod_adc0
port map (
go => strobe,
ad_a => ad0,
ad_b => ad1,
pmod => pmod_b,
clk => clk40);
DA_module : entity work.pmod_dac0
port map (
go => strobe,
da_a => ad0,
da_b => ad1,
pmod => pmod_da2,
clk => clk);
drive_leds : entity work.led_driver
port map (
sample => ad0,
leds => led,
clk => clk);
--------------------------------------------------------------
--
-- generate 40 MHz clock from 50 MHz
DCMconfig : entity work.DCM_config
generic map(CLKFX_DIVIDE => 5, CLKFX_MULTIPLY => 4)
port map( CLKIN_IN => clk,
RST_IN => ’0’,
CLKFX_OUT => clk40); -- 40 MHz
clk <= mclk;
end Behavioral;
E.2 PMod-AD1 support
----------------------------------------------------------------------------------
Lab Exercise 2 39 May 17, 2009
Doing DSP Workshop Summer 2009
-- Company: EECS 452
-- Engineer: Kurt Metzger
--
-- Create Date: 18:32:41 01/20/2008
-- Design Name:
-- Module Name: pmod_adc0 - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Revision 0.02 - removed unused sr stage .. 26Jan2008 .. KM
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity pmod_adc0 is
Port ( go : in STD_LOGIC;
ad_a : out STD_LOGIC_VECTOR (11 downto 0);
ad_b : out STD_LOGIC_VECTOR (11 downto 0);
pmod : inout STD_LOGIC_VECTOR (3 downto 0);
clk : in STD_LOGIC);
end pmod_adc0;
architecture Behavioral of pmod_adc0 is
signal goo, clear_goo : std_logic := ’0’;
signal sclk, cs_n : std_logic := ’1’;
signal ad0, ad1 : std_logic;
signal mygoo : std_logic_vector(1 downto 0);
signal counter : std_logic_vector(3 downto 0);
signal ar_a, ar_b : std_logic_vector(10 downto 0);
type t_state is (s_idle, s_convert);
signal state : t_state;
begin
Lab Exercise 2 40 May 17, 2009
Doing DSP Workshop Summer 2009
-- PMod-AD1 is assumed connected to the pmod vector.
-- The sample is initiated on the rising edge of go.
pmod(0) <= cs_n and (not goo); ad0 <= pmod(1);
ad1 <= pmod(2); pmod(3) <= sclk;
process(go, clear_goo) is begin
if clear_goo = ’1’ then goo <= ’0’;
elsif rising_edge(go) then
goo <= ’1’;
end if;
end process;
process(clk) is begin
if rising_edge(clk) then
sclk <= not sclk;
mygoo <= mygoo(0) & goo;
case state is
when s_idle =>
sclk <= ’1’;
if mygoo = "11" then clear_goo <= ’1’; else clear_goo <= ’0’; end if;
if mygoo = "01" then
cs_n <= ’0’;
counter <= (others => ’0’);
state <= s_convert;
end if;
when s_convert =>
if sclk = ’1’ then
ar_a <= ar_a(9 downto 0) & ad0;
ar_b <= ar_b(9 downto 0) & ad1;
counter <= counter+1;
if counter = 15 then
ad_a <= not ar_a(10) & ar_a(9 downto 0) & ad0;
ad_b <= not ar_b(10) & ar_b(9 downto 0) & ad1;
cs_n <= ’1’;
state <= s_idle;
end if;
end if;
end case;
end if;
end process;
end Behavioral;
E.3 Sample timing support
----------------------------------------------------------------------------------
-- Company: EECS 452
Lab Exercise 2 41 May 17, 2009
Doing DSP Workshop Summer 2009
-- Engineer: Kurt Metzger
--
-- Create Date: 21:43:01 12/25/2006
-- Design Name:
-- Module Name: timing - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity timing is
Port ( strobe : out STD_LOGIC;
swt : in STD_LOGIC_VECTOR(7 downto 0);
clk : in STD_LOGIC;
reset : in STD_LOGIC);
end timing;
architecture Behavioral of timing is
signal ctr : std_logic_vector(13 downto 0) := (others =>’0’);
signal count : std_Logic_vector(13 downto 0);
signal local_strobe : std_logic;
begin
strobe <= local_strobe;
-- multiply switches by 50 to allow sampling fractions of 1 MHz
-- 50 = 32+16+2
-- no check included for swt = 0
count <= (’0’ & swt & "00000") + ("00" & swt & "0000") + ("00000" & swt & ’0’);
process(clk)
begin
if rising_edge(clk) then
ctr <= ctr-1;
local_strobe <= ’0’;
if ctr = 1 then
Lab Exercise 2 42 May 17, 2009
Doing DSP Workshop Summer 2009
ctr <= count;
local_strobe <= ’1’;
end if;
end if;
end process;
end Behavioral;
E.4 DCM support
This is a “work-in-progress” DCM entity that is to work on either the S3SB (S3 chip) or the Basys
(S3e chip). The multiply and divide factors can be changed using a generic port specification.
It accepts the normal clock input and “cleans-it-up”, insures that it has a 50% duty cycle and
connects it into the clk network. There is a second output which is also connected into the
network. This clock is generated by a frequency synthesizer using the supplied/default multi-
ply and divide factors. The default synthesized frequency is 40 MHz assuming an input clock
of 50 MHz. The 40 MHz clock is needed in order to run the PMod AD1 module at its maximum
rate.
The XVGA support requires a 75 MHz clock. The existing XVGA support can run entirely
at 75 MHz. It remains to investigate how to set up 75 MHz clocking and 40 MHz clocking. It
looks like the global network can support at least three clocks perhaps allowing 40, 50, and 75
Hz clocks to co-exist.
Lab Exercise 2 43 May 17, 2009