<#20#>Massachusetts Institute of Technology<#20#>
Department of Electrical Engineering and Computer Science
6.111 - Introductory Digital Systems Laboratory
Laboratory 3
Issued: Wedensday, March 8, 2000
MCU Checkoff: Monday, March 13, 2000
Design Checkoff: Wednesday, March 15, 2000
Lab Checkoff: Friday, March 31, 2000
Report Due: Monday, April 3, 2000
We expand Figure~#figblock#43>
<#50#>APPROACH<#50#>
The much simpler approach to pitch shifting which we alluded to above
is shown in Figure~#figstretch#51>
In order to raise the pitch of a signal, we take a similar approach:
Within each chunk of the signal, ``squish'' the waveform somewhat and
fill the leftover space with part of another copy of the compressed
waveform. We expect that that raising the pitch will not be as
seamless as lowering the pitch, since the human ear and brain are not
as good at ignoring extra information as they are at replacing missing
information. The effect of this is that there will be slight
echo-like effect added when raising the pitch of an audio signal. We
would be interested to know if you discover a way of minimizing this
unwanted effect.
The pitch shifting seems to take place in real time, but as you may
have realized, there has to be a slight delay. This is because in
order to stretch or compress the audio signal, one full chunk of the
signal has to have already been stored into memory. The trick is to
use two different buffers; as the ``Sampling Buffer'' is filling up with
new samples, we can stretch or squish the contents of the ``Shifting
Buffer'' and output the shifted waveform.
The algorithm we use, then, is the following: Take one sample of the
input signal and store it into the Sampling Buffer. Choose one sample
from the Shifting Buffer as a function of how much we want to shift
the pitch, and output it. Repeat until the Sampling Buffer is full.
When the Sampling Buffer is full, swap the roles of the buffers and
start again.
<#57#>SYSTEM ORGANIZATION<#57#>
A system block diagram is shown in Figure~#figsysblk#58>
The TIMING UNIT produces the necessary clock signal to drive the MCU
sequencer and the other flip flops on the machine. In addition, this
unit must also provide two different frequencies which will be used as
a cue for the MCU to start an A2D conversion. Which frequency is used
depends on the setting of the sampling frequency selector switch.
The A2D converter is to be implemented by a single chip, the AD670.
You should wire it on the left hand proto strip of your kit which has
special analog power supplies.
The STORAGE UNIT consists of a static RAM (SRAM) and a somewhat
complicated address counter which we expect you will implement in a
CPLD. It is used to store the digitized analog input signal as
converted by the A2D. You should think of the SRAM as being divided
into two equal-size called buffers. At any given point, new data
received from the A2D will be placed into the Sample Buffer, as the
Shifting Buffer (containing previously-recorded samples) provides the
waveform to be stretched or squished. When the Sampling Buffer is
full, the roles of the two buffers are swapped.
The SIGNAL ACCUMULATOR allows mixing the pitch-shifted version of your
signal with the non-shifted original signal. This makes possible
special chord-like effects, especially when several Helium Breaths are
connect in series with one another; of course, it should be able to
also pass only the shifted signal or only the original signal. It
then provides the digital data to the D2A which in turn produces the
analog output signal.
The D2A is a registered digital to analog converter which converts the
data bytes retrieved from the SIGNAL ACCUMULATOR to an analog voltage.
It is to be implemented with a single chip, the AD558. You should
wire it on the left hand proto strip of your kit which has special
analog power supplies. The analog output signal can be viewed on an
oscilloscope or it can be used to drive a speaker.
A Microprogrammed Control Unit (MCU) senses the status signals from the
other blocks and provides the control signals to them so as to implement
the desired function.
Of course, all signals which are asynchronous to your system clock
must be passed through some sort of SYNCHRONIZER before affecting the
inputs to multiple flip-flops in your system. The SYNCHRONIZER is
also responsible for converting an assertion of PITCHUP or PITCHDOWN
to a periodic pulse so that the pitch increases or decreases
relatively slowly when the corresponding buttons are pressed.
<#64#>SECTION 1: MCU and TIMING UNIT<#64#>
<#65#>MICROPROGRAMMED CONTROL UNIT<#65#>
This portion of the lab will guide you in the design and testing of
the microprogrammed comtrol unit (MCU), which serves as the basis for
the rest of the lab. <#66#>Once the MCU has been successfully
completed, you may continue to build and debug the other sections
individually.<#66#> However, you should first complete the entire design.
Defer the wiring of the second part until your MCU works.
Since the MCU is the mind of the project, it must be able to
accomplish several things. First, it must be able to assert signals
that control the flow of information. Second, it must be able
to read status signals from the other units and make decisions
based on those signals. Last, it must be able to determine the
address of the next instruction to be executed.
Figure~#figmcu#67>
All of the code to be executed will be stored in Flash Memory. Each
memory address (line of code) contains an encoded instruction for the
sequencer and either assertion levels of control signals or a
combination of status signal selection and next address value. The
instruction set and location of these bit fields are illustrated in
Figure~#figbitfields#73>
The sequencer determines the next address based on the current
instruction and the status bit which it sees during that instruction.
The status bit is selected by an LS151 8-to-1 multiplexor using
condition select bits from the Flash Memory. Using LS163s as a
sequencer, only one condition bit may be viewed at any time.
Therefore, the flow of information is as follows. The PROM contains
the encoded instruction and address or signal assertions. The
instruction bit is fed from the high-order Flash PROM to the /G~enable
input of the LS151. The selector inputs of the LS151 are the
condition select bits, which come from the same PROM. The inverted
output of the LS151 is then fed into the condition code (/LOAD) input
of the sequencer. This causes the LS163s to load only on a rising
clock edge where the instruction bit is '0' (i.e. a <#77#>branch<#77#>
instruction) <#78#>and<#78#> the MUX input specified by the select bits is
high. Tying one of the MUX inputs to +5~V allows for unconditional
branching by testing a signal that is always true.
The Qn outputs of the sequencer are the address of the current
instruction; this address is tied to the inputs of the code Flash
Memory, so whatever instruction is on the PROM outputs should
correspond to the address at the LS163 outputs. On a rising clock
edge in the case of a conditional jump that is true, the LS163s load
the address at their D through A inputs (coming from the low order
PROM outputs). In the case of an an assert instruction or a failed
conditional branch, the LS163s simply increment their output by 1.
The /RESET signal is tied to the /CLR inputs of the LS163s, so pulling
/RESET low effectively forces a jump back to the first instruction in
the microprogram.
The PROM outputs are also fed into assert logic which determines when
to assert the control signals. We recommend you implement this
assertion logic in one or more PALs. The assert PALs must have the
information as to what type of instruction is being executed so that
an address on the PROM outputs is not interpreted as signals to be
asserted. The PAL keeps each unasserted signal at its proper logic
level, which could be either a 1 or 0, whereas a 0 logic level on the
PROM always means unasserted and a 1 always means asserted (provided
you are executing an assert instruction).
Remember to synchronize status signals to your system clock. Some of
the signals asserted by your MCU must be ``glitch-free''. Remember
that both PROM and PAL outputs will likely have glitches. You should
provide glitch-free signals (where required) either by registering
your assertions in a PAL flip flop or by gating the assertion signal
with the second half of the clock period.
Software to ease the task of programming the two Flash Memory chips is
described in a separate document. The microcode assembler processes
symbolic microcode and produces an output consisting of a hex integer
for each microcode instruction. The dat2ntl program is then used to
produce two separate Intel HEX files, byt0xxx.ntl and byt1xxx.ntl,
which are required to program the low and high bytes of your sixteen
bit microinstruction words. A shell script, assem16to8, is provided
so that you only need to type one command:
The actual audio input signal could come from a number of different
sources: a microphone, a cd player, a function generator, even a
simple voltage divider. You can borrow function generators and
microphones for a short amount of time from the equipment desk. In
any case, you will need to think about the input voltage range of the
AD670 and how to place your signal within this range.
<#87#>STORAGE UNIT<#87#>
The STORAGE UNIT consists of a static RAM (SRAM) and a complex
programmable logic device (CPLD). We expect you to build on the
techniques you learned in Lab 2 to interface with the SRAM. The
complexity here is not in interfacing with the SRAM, but in the design
of the counters used to index it; clever indexing of the SRAM is what
gives us the desired stretch or squish of the sampled audio waveform.
We expect that you'll be able to implement this indexing mechanism in
a C372i CPLD using VHDL.
The SRAM you will use is a 6264, available from the equipment desk.
Like the 6116, it is eight bits wide and has /CS, /WE, and /OE, but it
has two additional address inputs and is therefore four times larger.
For the purposes of this lab, we suggest that you divide the SRAM into
two buffers of 2048 bytes each; by setting one of the SRAM address
bits to 0 or 1, you can control which buffer is being accessed. At
any given point in time, the Sampling Buffer is being filled up with
samples, while certain samples are being selected for output from the
Stretching Buffer, which has already been filled.
Figure~#figsram#88>
The ``Shifting Counter'', on the other hand, is intended to keep track
of which sample to output next when stretching or squishing the
waveform stored in the Shifting Buffer. When ClearShift is asserted
during a rising clock edge, the Shifting Counter clears. Otherwise,
it is capable of counting in non-integer increments, greater or less
than one. The idea is that by incrementing the Shifting Counter by
slightly more than one, some samples will be skipped, thus squishing
the waveform and producing a higher-sounding output. Likewise, by
counting an increment slightly less than one, some samples will be
repeated, stretching the waveform out and giving a lower-sounding
output.
You can implement a counter that counts by non-integers by building it
wide---we suggest 17 bits for your Shifting Counter. The most
significant 11 bits represent the integers 0-2047; they can be used to
address the 2048 samples in an SRAM buffer. The least significant 6
bits, then, are the fractional component of the counter. We can
increment the counter by exactly 1.0 by adding 01000000 to the value
it contains. Adding 01000001 increments the counter by slightly more
than~1.0, and adding 00111111 increments it by slightly less.
The amount by which we increment the Shifting Counter comes from the
eight-bit ``Pitch Multiplier Counter''. When PitchUp is asserted on a
rising clock edge, the Pitch Multiplier Counter should count up. When
PitchDown is asserted on a rising clock edge, it should count down.
Thus, PitchUp and PitchDown raise and lower the pitch of our output
signal by controlling the amount we stretch or squish the stored
waveform.
The ShiftCount signal determines which counter, the Sampling Counter
or the Shifting Counter, addresses the SRAM. You will want to use the
Sampling Counter when storing samples to memory or outputting a
non-shifted version of your signal. You will want to use the Shifting
Counter when outputting a shifted version of your signal.
The T flip-flop labelled ``BufSel'' has one simple purpose: to
remember which buffer is currently the Sampling Buffer and which is
the Shifting Buffer. Asserting SwapBuf causes the two buffers to
switch roles.
Finally, the buffer size selector switches allow the user to
optionally use buffers smaller than 2048 bytes. You may discover that
different buffer sizes work better for different types of signals and
different pitch multipliers. Depending on the setting of the
switches, your CPLD should detect when its address outputs are greater
than a certain number, and if so, the Full output should go high.
This lets the MCU know to clear one or both of the counters and
perhaps also swap buffers.
All of the modules outside the SRAM should fit fairly easily into the
C372i CPLD. What remains is for you to write the VHDL. We've
provided you a starting point (the entity declaration); you can find
it in:
Figure: General Block Diagram
Figure: Analog/Digital Separation
Figure: ``Stretching'' and ``Squishing'' a Waveform To Change Its Pitch
Figure: System Block Diagram
Figure: MCU
Figure:
Figure:
Figure: Storage Unit
<#102#>WHAT WE EXPECT FROM YOU<#102#>
<#103#>MCU CHECKOFF<#103#>
Before building anything else, you should first make sure your MCU and
Timing Unit are working reliably. We therefore require you to
demonstrate their functionality using a test program which we have
provided. The program tests ASSERT and CJMP instructions, and makes
an attempt to verify that all your branch address bits are wired
correctly. Note that our test program doesn't guarantee correct
functionality, it just tries to catch some common errors.
We'd like you to ``get your feet wet'' with the VHDL design tools and
the CPLD programmer, so as part of this exercise, you will have to
write a small amount of VHDL. We would like you to design a frequency
divider that will take as input your sampling frequency and produce a
much lower-frequency signal as output. Recall that you should design
your sampling signal to have one of two frequencies depending on the
setting of a switch. The VHDL you write here should divide the lower
of these two frequencies down to somewhere in the range of
10--20~Hz.
The programs are:
If all is working fine, you should be able to use the switches to
control a nice display of blinking LEDs. The MCU test code uses the
output of your CPLD to determine how fast the lights blink.
Therefore, toggling the sampling frequency selector switch should
change the blinking speed. Be sure to pay attention to the comments
in the files we have provided. They give not only wiring instructions
but also hints for what to do if something doesn't work.
After you've gotten your working MCU checked off with a staff member,
feel free to remove the CPLD and the wiring to the switches and LEDs.
You won't need it in the rest of the lab.
<#113#>DESIGN REVIEW<#113#>
You are not required to, but are STRONGLY encouraged to, meet with a
T.A. for a design review before you begin wiring the second half of
your system. You do not have to have detailed circuit diagrams or
completed microcode before the design review.
You should, however, think about the problem and come for a design
review with a block diagram, flowchart for your microcode, and a
reasonably clear idea of the approach. Specifically, you should think
about how you are going to test your circuits. A complicated design
rarely works the first time you turn on the power. Consider how you
might test individual modules before interconnecting them. A little
bit of well chosen extra test circuitry can actually reduce the time
and effort required to get your design to work.
Since you have had the least experience with VHDL, you should try to
bring along your first attempt at VHDL for your memory counter.
Be aware that seriously thinking about how to optimize your design
before you begin building can significantly reduce the amount of
wiring you have to do. In any case, make sure your design will fit on
your kit by placing the chips you expect to use; try to leave space
for last-minute ``patches''.
<#114#>IMPLEMENTATION<#114#>
After arriving at the final design, you should prepare detailed logic
diagrams for both the data paths and your control circuitry. These
should include pin numbers and chip locations. Wire your kit from
these detailed logic diagrams (not from block diagrams) and test the
system. When operational, it should be demonstrated to any staff
member in the laboratory. Bring your circuit diagrams to the lab when
coming for a demonstration as the T.A. will initial and date your
diagrams. Be sure to include this witnessed copy in your report.
After the demo, complete your report and turn it in.
Actually, there is nothing wrong with writing your report before the
demo. Often it is a good idea to write the report while the debugging
and testing are proceeding. This can not only provide a change of
pace, but the thought going into the organization of the report can
actually be beneficial in the debugging process. If you write your
report before finishing the debugging, you will likely have to change
the report only in a minor way, if at all, when your system is fully
operational.
<#115#>LABORATORY REPORT<#115#>
After the completion of Lab 3, a typewritten (or neatly handwritten)
report is required. It should emphasize both the theory of the design
and the problems of practical implementation.
Your report should include the following items:
<#107#>/mit/6.111/handouts/labs/lab3.s00/mcutest.as<#107#> assembler file, microcode
<#108#>/mit/6.111/handouts/labs/lab3.s00/mcutest.sp<#108#> specification file
<#109#>/mit/6.111/handouts/labs/lab3.s00/mcutest.vhd<#109#> accompanying assert PAL
<#110#>/mit/6.111/handouts/labs/lab3.s00/mcutest1.vhd<#110#> frequency divider
The keys to a successful report are organization and clarity. A short
paragraph with a diagram or table usually communicates your intent to
the reader far better than a long-winded written explanation.
<#122#>PROBLEMS?<#122#>
If you encounter problems in your design, please come in and ask. We
regard this lab exercise as a most important experience for you in
preparation for the final project. We want you to succeed and will do
our best to help. Please do not leave everything to the last minute
as this will make it difficult to have time to help you.