Summary: You will implement band-pass finite impulse-response (FIR) filters with time-domain processing.
In this exercise, you will program in the DSP's assembly language to create FIR filters. Begin by studying the assembly code for the basic FIR filter filter.asm.
| filter.asm |
|---|
|
filter.asm applies an FIR filter to the signal
from input channel 1 and sends the resulting output to output
channel 1. It also sends the original signal to output
channel 2.
First, create a work directory on your network drive for the
files in this exercise, and copy filter.asm
and core.asm
into it. Then use MATLAB to generate two 20-tap FIR
filters. The first filter should pass signals from 4 kHz to 8
kHz; the second filter should pass from 8 kHz to 12 kHz. For
both filters, allow a 1 kHz transition band on each edge of
the filter passband. To create these filters, first convert
these band edges to digital frequencies based on the 44.1 kHz
sample rate of the system, then use the MATLAB command
remez to generate this filter; you can type
help remez for more information. Use the
save_coef command to save each of these filters
into different files. (Make sure you reverse the vectors of
filter coefficients before you save them.) Also save your
filters as a MATLAB matrix, since you will need them later to
generate test vectors. This can be done using the MATLAB
save command. Once this is done, use the
freqz command to plot the frequency response of
each filter.
For now, you will implement only the filter with a 4 kHz to 8
kHz passband. Edit filter.asm to use the
coefficients for this filter by making several changes.
First, the length of the FIR filter for this exercise is 20,
not 8. Therefore, you need to change FIR_len to
20. FIR_len is set using the .set
directive, which assigns a number to a symbolic name. You will
need to change this to FIR_len .set 20.
Second, you will need to ensure that the .copy
directive brings in the correct coefficients. Change the
filename to point to the file that contains the coefficients
for your first filter.
Third, you will need to modify the .align and
.space directives appropriately. The TI
TMS320C54x DSP requires that circular buffers, which are used
for the FIR filter coefficient and state buffers, be aligned
so that they begin at an address that is a multiple of a power
of two greater than the length of the buffer. Since you are
using a 20-tap filter (which uses 20-element state and
coefficient buffers), the next greater power of two is 32.
Therefore, you will need to align both the state and
coefficient buffers to an address that is a multiple of 32.
(16-element buffers would also require alignment to a multiple
of 32.) This is done with the .align command. In
addition, memory must be reserved for the state buffer. This
is done using the .space directive, which takes
as its input the number of bits of space
to allocate. Therefore, to allocate 20 words of storage, use
the directive .space 16*20 as shown below:
1 .align 32 % Align to a multiple of 32
2 coef .copy "filter1.asm" % Copy FIR filter coefficients
3
4 .align 32 % Align to a multiple of 32
5 state .space 16*20 % Allocate 20 words of data space
Assemble your code, set PMST to
0xFFE0, reset the DSP, and run. Ensure that it
is has the correct frequency response. After you have verified
that this code works properly, proceed to the next step.
First, make a copy of your modified filter.asm
file from Part 1. Work from this
copy; do not modify your working filter from the previous
part. You will use that code again later.
Next, modify your code so that in addition to sending the
output of your first filter (with a 4 kHz to 8 kHz passband)
to output channel 1 and the unfiltered input to output channel
2, it sends the output of your second filter (with a 8 kHz to
12 kHz passband) to output channel 3. To do this, you will
need to use the .align and .copy
directives to load the second set of coefficients into data
memory. You will also need to add instructions to initialize
a pointer to the second set of coefficients and to perform the
calculations for the second filter.
Can you implement the dual-channel system without using
the auxiliary registers AR4 and
AR5? Why is this more difficult? Renaming
AR4 and AR5 using the
.asg directive does not count!
Using the techniques introduced in DSP Development Environment: Introductory Exercise for TI TMS320C54x, generate an appropriate test vector and expected outputs in MATLAB. Then, using the test-vector core file also introduced in DSP Development Environment: Introductory Exercise for TI TMS320C54x, find the system's output given this test vector. In MATLAB, plot the expected and actual outputs of the both filters and the difference between the expected and actual outputs. Why is the output from the DSP system not exactly the same as the output from MATLAB?
An alternative method of implementing symmetric FIR filters
uses the firs instruction. Modify
your code from Part 1 to implement
the filter with a 4 kHz to 8 kHz passband using the
firs.
Two differences in implementation between your code from Part 1 and the code you will write for
this part are that (1) the firs instruction
expects coefficients to be located in program memory instead
of data memory, and (2) firs requires the states
to be broken up into two separate circular buffers. Refer to
the firs instruction on page 4-59 in
the Mnemonic
Instruction Set manual, as well as a description and
example of its use on pages 4-5 through 4-8 of
the Applications
Guide for more information (Volumes 2 and
4 respectively of the TMS320C54x DSP Reference
Set).
AR0 needs to be set to -1 for this code to work properly. Why?
COEFF is a label to the
coefficients now expected to be in program memory. Refer to the
firs description for more
information).
1 mvdd *AR2,*AR3+0% ; write x(-N/2) over x(-N)
2 sth A,*AR2 ; write x(0) over x(-N/2)
3 add *AR2+0%,*AR3+0%,A ; add x(0) and x(-(N-1))
4 ; (prepare for first multiply)
5
6 rptz B,#(FIR_len/2-1)
7 firs *AR2+0%,*AR3+0%,COEFF
8 mar ??????? ; Fill in these two instructions
9 mar ??????? ; They modify AR2 and AR3.
10
11 ; note that the result is now in the
12 ; B accumulator
Because states and coefficients are now treated differently than in your previous FIR implementation, you will need to modify the pointer initializations to
1 stm #(FIR_len/2),BK ; initialize circular buffer length
2 stm #firstate_,AR2 ; initialize location containing first
3 ; half of states
4
5 stm #-1,AR0 ; Initialize AR0 to -1
6
7 stm #firstate2_,AR3 ; initialize location containing last half
Use the test-vector core file to find the output of this
system given the same test vector you used to test the
two-filter system. Compare the output of this code against the
output of the same filter implemented using the
mac instruction. Are the results the same? Why or
why not? Ensure that the filtered output is sent to output
channel 1, and that the unmodified output is still sent to
output channel 2.