SMS045 - DSP Systems in Practice. Lab 2 - ADSP-2181 EZ-KIT Lite and VisualDSP++ Due date: Tuesday Nov 18, 2003

Similar documents
DSP Platforms Lab (AD-SHARC) Session 05

Instruction Set Reference

Programming Model 12.1 OVERVIEW 12 1

ADSP-2100A DSP microprocessor with off-chip Harvard architecture. ADSP-2101 DSP microcomputer with on-chip program and data memory

University of Saskatchewan 5-1 EE 392 Electrical Engineering Laboratory III

Introduction ADSP-2100 FAMILY OF PROCESSORS

ADSP-218x. DSP Instruction Set Reference. First Edition, February Part Number

Simple Experiments Involving External Control of Algorithm Parameters for an EET Undergraduate DSP Course

Graduate Institute of Electronics Engineering, NTU 9/16/2004

ADSP-2181 Experiments

Computer Organisation CS303

EE-123. An Overview of the ADSP-219x Pipeline Last modified 10/13/00

SECTION 5 ADDRESS GENERATION UNIT AND ADDRESSING MODES

,1752'8&7,21. Figure 1-0. Table 1-0. Listing 1-0.

538 Lecture Notes Week 1

Digital Signal Processing Laboratory 7: IIR Notch Filters Using the TMS320C6711

3 TUTORIAL. In This Chapter. Figure 1-0. Table 1-0. Listing 1-0.

Chapter 7 Central Processor Unit (S08CPUV2)

ECE4703 B Term Laboratory Assignment 2 Floating Point Filters Using the TMS320C6713 DSK Project Code and Report Due at 3 pm 9-Nov-2017

A Microprocessor Systems Fall 2009

CHAPTER 1 Numerical Representation

NEW CEIBO DEBUGGER. Menus and Commands

ADSP-218x. DSP Hardware Reference. First Edition, February Part Number

The following revision history lists the anomaly list revisions and major changes for each anomaly list revision.

ADDRESS GENERATION UNIT (AGU)

2 TUTORIAL. Overview. VisualDSP Getting Started Guide 2-1 for SHARC DSPs

4 DEBUGGING. In This Chapter. Figure 2-0. Table 2-0. Listing 2-0.

REAL TIME DIGITAL SIGNAL PROCESSING

CPE 323 MSP430 INSTRUCTION SET ARCHITECTURE (ISA)

This section discusses resources available from Analog Devices to help you develop applications using ADSP Family digital signal processors.

Better sharc data such as vliw format, number of kind of functional units

Lab 1 Introduction to TI s TMS320C6713 DSK Digital Signal Processing Board

4 MAC INSTRUCTIONS. Figure 4-0. Table 4-0. Listing 4-0.

The C Programming Language Guide for the Robot Course work Module

Lab 6 : Introduction to Simulink, Link for CCS & Real-Time Workshop

Four Categories Of 8085 Instructions That >>>CLICK HERE<<<

Audio Controller i. Audio Controller

8051 Overview and Instruction Set

ADSP-2181 EZ-KIT Lite Evaluation System Manual

CHAPTER ASSEMBLY LANGUAGE PROGRAMMING

Engineer To Engineer Note

Graduate Institute of Electronics Engineering, NTU FIR Filter Design, Implement, and Applicate on Audio Equalizing System ~System Architecture

Microcontrollers. Microcontroller

538 Lecture Notes Week 5

REAL TIME DIGITAL SIGNAL PROCESSING

SECTION 5 PROGRAM CONTROL UNIT

An introduction to Digital Signal Processors (DSP) Using the C55xx family

CS311 Lecture: The Architecture of a Simple Computer

G GLOSSARY. Terms. Figure G-0. Table G-0. Listing G-0.

The MARIE Architecture

CS401 - Computer Architecture and Assembly Language Programming Glossary By

The following revision history lists the anomaly list revisions and major changes for each anomaly list revision.

Embedded Systems - FS 2018

ADSP EZ-KIT Lite Evaluation System Manual. Part Number: Revision 3.0 January 2003

Notes: The Marie Simulator

DSP VLSI Design. Addressing. Byungin Moon. Yonsei University

538 Lecture Notes Week 5

FALSIM. FALSIM is the name of the software application which consists of the FALCON-A assembler and the FALCON-A simulator. It runs under Windows XP.

Digital Signal Processor Core Technology

Laboratory Exercise 3 Comparative Analysis of Hardware and Emulation Forms of Signed 32-Bit Multiplication

ECOM 2325 Computer Organization and Assembly Language. Instructor: Ruba A.Salamah INTRODUCTION

The x86 Microprocessors. Introduction. The 80x86 Microprocessors. 1.1 Assembly Language

MC9S12 Address Space

ECE 5655/4655 Laboratory Problems


FEATURE ARTICLE. Michael Smith

Mr. Sapan Naik 1. Babu Madhav Institute of Information Technology, UTU

Computer Organization and Assembly Language. Lab Session 01

VARDHAMAN COLLEGE OF ENGINEERING (AUTONOMOUS) Shamshabad, Hyderabad

Microcontroller Systems

APPLICATION NOTE AN001. a simple audio level meter for the chameleon. revision chameleon S.D.K. v1.2

Mechatronics Laboratory Assignment 4 Parallel Communication Glue Logic, Hardware Interrupts, Analog to Digital Conversions, and Board Fab

The SHARC in the C. Mike Smith

4 Categories Of 8085 Instructions That Manipulate Data

E3940 Microprocessor Systems Laboratory. Introduction to the Z80

ECE 3120 Lab 1 Code Entry, Assembly, and Execution

Instruction Set Architecture

Number Systems CHAPTER Positional Number Systems

Application Note, V1.0, November AP XC2000/XE166 family. ADC Result Handling on XC2000/XE166 family of Microcontrollers.

ORG ; TWO. Assembly Language Programming

Lab Experiment 9: LCD Display

Application Note. Introduction AN2471/D 3/2003. PC Master Software Communication Protocol Specification

Software Examples 14.1 OVERVIEW 14 1

Chapter 1 Introduction

Outline: System Development and Programming with the ADSP-TS101 (TigerSHARC)

VIII. DSP Processors. Digital Signal Processing 8 December 24, 2009

History and Basic Processor Architecture

COSC121: Computer Systems: Review

Embedded Systems - FS 2018

Introduction to Microprocessor

MICROPROCESSOR AND MICROCONTROLLER BASED SYSTEMS

Programming Model 2 A. Introduction

Lode DSP Core. Features. Overview

Engineer To Engineer Note

WS_CCESSH-OUT-v1.00.doc Page 1 of 8

CHAPTER 5 Basic Organization and Design Outline Instruction Codes Computer Registers Computer Instructions Timing and Control Instruction Cycle

ADSP-2100 Family DSP Microcomputers ADSP-21xx

OBSOLETE. ADSP-2100 Family DSP Microcomputers. This data sheet describes the following ADSP-2100 Family processors: ADSP-2105

4 bits Microcontroller

REAL TIME DIGITAL SIGNAL PROCESSING

Transcription:

SMS045 - DSP Systems in Practice Lab 2 - ADSP-2181 EZ-KIT Lite and VisualDSP++ Due date: Tuesday Nov 18, 2003 Lab Purpose This lab will introduce the ADSP-2181 EZ-KIT Lite development board for the Analog Devices 218x range of digital signals processors (DSPs), along with the Analog Devices VisualDSP++ software for DSP program code development. Both the FIR low-pass filter desgined in Lab 1, and a digital delay, will be implemented. Preparations Read through the lab instructions carefully. Bring a print-out of the Bode plot of the FIR low-pass filter from Lab 1 to the lab session. Required Hand-ins Hand in one report per group, consisting of the following: An introductory paragraph that summarizes what you have done in the lab (about 1/2 A4 page). Assignment 3: The assembler source code to the digital delay implementation. Your oppinions about the lab and the lab instructions. Too easy? Too difficult? Suggestions on changes. Required Presentations Assignment 2: Demonstrate your implemented FIR low-pass filter to the lab instructor. Assignment 3: Demonstrate your implemented digital delay to the lab instructor.

Include your names and email addresses on the titlepage of the report. Begin included assembler code with comments that show your names and an explanation of what the code does. This could for example look like: // Robert Plant E3, Ron Wood D4 // // Lab 2, Assignment 3. // Code for implementing a digital delay.

About Digital Signal Processors ag replacements A digital signal processor (DSP) is a microprocessor that is specially designed to perform fast calculations on digital data in real-time. Some typical DSP applications are: Digital filtering of an analog signal. Calculating the FFT (Fast Fourier Transform) of an analog signal. Real-time adaptive signal processing. A DSP typically consists of three arithmetic units: an adder, a multiplier, and a barrel shifter. It also contains some RAM memory and one or more serial ports. All internal operations are synchronized by an internal core clock. The frequency of the core clock determines the rate at which operations are done. Most operations consume one clock cycle; while in some cases, several operations can be done in the same cycle. Figure 1 shows a block diagram of a DSP application, where an input signal is scaled by a factor 0.5. The DSP is connected to an analog-to-digital converter (ADC) and a digital-to-analog converter (DAC) via a serial port on the DSP. DSP RAM (1) (2) (3) (4) SPORT ADC DAC y = 0.5 x (Arithmetic units) Figure 1: Scaling of a time-continuous signal using a DSP. The typical flow of signals and operations is as follows: The ADC samples a time-continuous signal, producing samples at some fixed rate. The samples are continuously transferred to the DSP over the serial port. Once a sample has been received by the DSP, it performs some operations on it, producing an output sample. In Figure 1, each incoming sample is scaled by a factor of 0.5, following this scheme: 1. The input sample is stored in the internal memory (RAM) as a variable, x. 2. The contents of the variable x is sent to the arithmetic units, where it gets multiplied by 0.5. 3 6th November 2003

3. The result is stored as a new variable, y, in the internal memory. 4. The output sample is sent to the serial port for transfer to the DAC. The DAC then converts the samples back to time-continuous form. Normally, the serial port (SPORT) is pre-configured to automatically transfer samples between the DSP and the ADC and DAC. Only the remaining operations (1-4 in the example above) are user defined. DSP operations are normally called routines (e.g. filter routines, scaling routines, etc.). To implement signal processing routines on a DSP, the associated program code handling the routines must first be written. The program code consists of instructions telling the DSP to perform some operations. Once the program code is written, it must be compiled and loaded into the DSP s RAM memory. The DSP may then execute the code. In this lab, the Analog Devices VisualDSP++ software will be used to generate and debug program code to two simple DSP programs. A DSP itself is typically only capable of processing numbers in real time. It has, for instance, no capability by itself to sample a time-continuous signal, etc. Therefore, DSP programs are often designed using a development board. These boards typically contain the DSP chip, a codec (AD/DA converter) for analog input/output, some serial PC interface and some simple user interface (e.g. pushbuttons, LED s, etc.). In this lab, the Analog Devices ADSP-2181 EZ-KIT Lite development board will be used. The ADSP-2181 EZ-KIT Lite and VisualDSP++ The ADSP-2181 EZ-KIT Lite consists of a PCB board with the ADSP-2181 DSP, along with the AD1847 audio codec, a RS232 serial controller (allowing serial communication with the PC), an EPROM interface, plus some other devices. Figure 2 shows the board layout. Program code can be loaded into the DSP from a PC through the RS232 serial link. The audio input and output jacks connect to the codec which is serially connected to the DSP. Program code implementing routines can be written and debugged using the VisualDSP++ (VDSP) software. The code can be written in either assembler language or C/C++. For this course, however, only assembler will be used. Figure 3 shows a block diagram of the lab setup. The PC communicates with the DSP through the serial port (COM1). When a DSP program has been written in VDSP, it is downloaded into the DSP s internal RAM memory via the RS232 serial link. VDSP can then tell the processor to execute the code by sending a Run instruction over the serial link. The DSP will run the program until VDSP sends a Halt instruction. After the processor has halted, the current contents of the DSP s internal registers and memory can be monitored in VDSP for debugging purposes. 4 6th November 2003

PSfrag replacements Figure 2: The ADSP-2181 EZ-KIT Lite board layout. (VDSP) PC Serial com. [Debugger instructions] 2181 EZ-KIT Lite Audio out Audio in Figure 3: The PC - EZ-KIT Lite lab setup. VisualDSP++ Projects The assembler or C/C++ files containing the DSP program code are called source files. One or more source files are integrated into VDSP projects. A project also contains a linker definition file, which defines the usage of internal RAM memory and memory-mapped registers on the DSP. VDSP projects may also contain header files (.h files) defining assembler macros and constants, and.dat files containing data; such as filter coefficients, etc. Before a program can be executed on the DSP, VisualDSP must first perform a build of the project. This procedure preprocesses the source code, links it to specified DSP RAM memory locations, and creates an executable file. This file can then be loaded into the DSP s internal memory for execution. 5 6th November 2003

VisualDSP++ Assembler Basics This section will introduce some useful assembler instructions and notations used by VisualDSP++. For detailed information, refer to the ADSP-2100 Family Users Manual, or the help function in VisualDSP++. Assembler source code can be stored in one or several.asm files. In the simplest case, using a single file, the source code is usually organized in the following way: First, some definitions of assembler constants are made. Then, variables are defined and possibly initialized. The rest of the source code contains the actual program code. Program Flow An assembler program consists of instructions which are executed sequentially, line by line. All instructions end with a semicolon (;). For example, the following code: AX0 = 2; stores the value 2 in the register called AX0. To control program flow, several different instructions can be used. JUMP A JUMP <label> instruction tells the program to jump to a specific section of the code, marked <label>, and continue execution there. Labels can be placed anywhere in the code, and they end with a colon (:). For example, the following code: AR = AR + 1; JUMP increment; AR = 0; increment: AR = AR + 2; will increment the value of the register AR with one, and then jump to the label increment:, where, in this example, AR is incremented by two. Hence, the instruction AR = 0; will not be executed. CALL A CALL <label> instruction tells the program to jump to a subroutine labeled <label>. The program will continue execution at the address <label> and return to the line after the subroutine 6 6th November 2003

call upon an RTS instruction. For example, the following code: CALL reset_ar; AR = AR + 1;......... reset_ar: AR = 0; nop; RTS; will first call the subroutine labeled reset ar. This makes the program jump to the label reset ar:, where, in this example, AR is set to zero. The nop (no operation) instruction is a dummy instruction which does nothing. The trailing RTS instruction causes the program to return to the line directly after the subroutine call, where, in this example, AR is incremented by one. DO UNTIL Quite often, certain instructions have to be repeatedly executed a certain number of times. This can be done with a DO <label> UNTIL CE instruction. For example, the following code will execute the operations AR = AR + 1 and SR = SR + 3 ten times: CNTR = 10; DO inc loop UNTIL CE; AR = AR + 1; inc loop: SR = SR + 3; AX0 = 2; The loop counter register, CNTR, defines the number of loop iterations. After each iteration, the loop counter value is decremented by one. The inc loop: label marks the last instruction to be done before the loop starts over again. UNTIL CE means until counter expires. In this case, the program exits the loop after ten iterations, continuing with the next instruction after the loop, which, in this example, sets AX0 = 2. Interrupts To allow external units (i.e. codecs, buttons) to interact with the program flow, interrupts can be used. An interrupt from an external unit causes the current program to halt while the interrupt is serviced. 7 6th November 2003

For example, a DSP serial port may communicate with an ADC, which samples some timecontinuous signal at a fixed sample rate. When a new sample has been collected, it is transferred to the DSP over the serial port; which then generates an interrupt, telling the DSP that a new sample is ready to be processed. The program will then stop any ongoing process and jump to an interrupt service routine (ISR). In the ISR, the new sample is perhaps stored in some variable, before the program continues from where it got interrupted, upon an RTI (return from interrupt) instruction. For example, the following code: scaling loop: idle; AX0 = AR; JUMP scaling loop; SPORT0 ISR: AX0 = 1; RTI; is an infinite loop which starts with an idle instruction. The idle instruction causes the program flow to stop until an interrupt occurs. An interrupt from serial port 0 causes the program to jump to the interrupt service routine SPORT0 ISR, where AX0 is set to one. The RTI instruction returns execution to the loop, where, in this example, AX0 is set equal to AR. Assembler Constants Assembler constants can be defined using the following syntax: #define GAIN 36 which, in this example, associates the constant GAIN with the number 36. All occurrences of the exact word GAIN in the source code will be replaced with 36 upon build. A constant definition does not end with a semicolon. Assembler Variables Assembler variables are created using the following syntax:.var Input_Var = 0x7FFF; which, in this case, creates a variable called Input Var and intializes its contents to the value 0x7FFF. The syntax: 8 6th November 2003

.var Input_Var; creates the variable, but does not initialize it. A buffer containing an arbitrary number of elements can be created similarly by:.var Sample_Buffer[3] = 0x4000, 0x002F, 0x0000; which, in this case, creates a buffer with three elements, and initializes it. About the ADSP-2181 Digital Signal Processor PSfrag replacements This section will cover some of the essential features of the ADSP-2181 digital signal processor. For detailed information, refer to the ADSP-2100 Family User s Manual or the ADSP-218x Hardware Reference. Number Representations The ADSP-2181 is a fixed point processor. This means that the processor can only handle numbers that are represented with a fixed number of decimals. All numbers that are processed by the DSP s arithmetic units are binary numbers. However, when writing program code, alternative number formats may be used. The fixed point numbers used by the arithmetic units in the ADSP-2181 are 16 bit binary numbers in 1.15 fractional format. In this format, the most significant bit (MSB) is a sign bit, which signals whether the number is positive or negative. The other 15 bits are decimal bits. Figure 4 shows the bit weights of a 16 bit number in 1.15 format. 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 2 10 2 11 2 12 2 13 2 14 2 15 MSB LSB Figure 4: Bit weights of a 1.15 binary number. For example, the 1.15 binary number b#1000000000001001 is equal to the decimal number 2 0 + 2 12 + 2 15 0.999725. Numbers in the 1.15 format range from 1 to 1 2 15 0.9999695. When writing program code, 1.15 fractional numbers may be entered using three different representations: Binary Format - Binary numbers are entered as b#bbbbbbbbbbbbbbbb, where each of the 16 digits B is any of {0, 1}. 9 6th November 2003

Hexadecimal numbers - Hexadecimal (hex) numbers are entered as 0xNNNN, where each digit N is any of {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F }. Fractional numbers - Fractional numbers are entered as decimal numbers with a trailing r (e.g. 0.5r). Table 1 shows some examples of 1.15 fractional numbers using the three representations (confirm with Figure 4). Table 1: Examples of 1.15 numbers in binary, hexadecimal and decimal format. Bin Hex Decimal Equivalent b#0000000000000001 0x0001 0.000305 b#0100000000000000 0x4000 0.5 b#0111111111111111 0x7FFF 0.999969 b#1000000000000000 0x8000-1.0 b#1100000000000000 0xC000-0.5 b#1111111111111111 0x7FFF -0.000031 If an ordinary number without a decimal point is entered (e.g. 11), it is interpreted as a signed integer. Signed integers are typically used when defining buffer lengths etc. Signed integers range from 32767 to -32768. Memory Structure The internal RAM memory of the 2181 DSP is divided into two blocks: Data Memory - The data memory stores variables used in the DSP program. The size of the data memory is 8 kwords, where each word is 16 bits wide. Program Memory - The program memory stores the actual program code being executed and, optionally, some variables. The size of the program memory is 8 kwords, where each word is 24 bits wide. The contents of variables stored in data or program memory can be accessed using the syntax DM(<variable name>) or PM(<variable name>) for a variable called <variable name> placed in the data memory or program memory respectively. For example: AR = DM(Sample); loads the contents of the data memory variable Sample into the AR register. Similarly: PM(temp) = SR; stores the value of the register SR in the program memory variable temp. 10 6th November 2003

The Arithmetic Logic Unit (ALU) The arithmetic logic unit (ALU) in the ADSP-2181 performs addition or subtraction of two numbers. The ALU can also negate, increment, decrement or take the absolute value of a single number. The ALU has four 16-bit input registers: AX0, AX1, AY0 and AY1. Addition and subtraction can be performed between one of the X registers, (AX0, AX1), and one of the Y registers, (AY0, AY1). The result of the operation is placed in the 16-bit result register, AR. The input registers can be loaded either directly with a value: AX0 = 0x7FFF; or with the value of a variable: AX0 = DM(Input_Var); or with a constant: AX0 = GAIN; As an example, an addition of the hex numbers 1 and A0 can be done by: AX0 = 0x0001; AY0 = 0x00A0; AR = AX0 + AY0; which places the result A1 in AR. A subtraction is done by using a - instead of a +. The Multiplier Accumulator (MAC) The multiplier/accumulator in the ADSP-2181 can multiply two numbers and accumulate results from several multiplications. The MAC has four 16-bit input registers: MX0, MX1, MY0 and MY1. Since the result of a multiplication between two 16-bit numbers is up to 32 bits long, the result register has to be at least 32 bits wide. Furthermore, summing up results of several multiplications may cause the final result to exceed 32 bits. Therefore, the MAC result register, MR, is 40 bits wide. Multiplication can be performed between one of the X registers, (MX0, MX1), and one of the Y registers, (MY0, MY1). A basic multiplication between the hex numbers FF and 2 can be done by: MX0 = 0x0002; MY0 = 0x00FF; MR = MX0 * MY0 (SS); 11 6th November 2003

which places the result 0x01FE in MR. The (SS) argument tells the MAC that both the X input and the Y input should be treated as signed numbers. The MR register is divided into two 16-bit registers, MR0 and MR1, and one eight-bit register, MR2. Figure 5 shows the layout of MR. Since almost all other computational registers and all data variables are 16 bits wide, the MAC result often has to be truncated to 16 bits before being stored in some other register or variable. If the result is small enough to be represented using PSfrag replacements only 16 bits, it can be taken from MR0. If the result is more than 16 bits wide, it will use both MR0 and MR1. In this case, a 16 bit rounded result can be taken from MR1 (most significant bits of result). If the result is too big to be represented using 32 bits, the result will use part of the MR2 register as well. The MAC will detect if the MAC result is wider than 32 bits, so that appropriate down-scaling of the result can be implemented in the code. Bit # MSB 39:32 31:16 15:0 MR2 MR1 MR0 Figure 5: The MR register. LSB The result from one multiplication is often added to the result of previous multiplications. If the MR register contains data to be added to a new MAC result, the syntax: MR = MR + MX0 * MY0 (SS); will add the result of MX0 * MY0 to the previous contents of MR. Data Address Generators (DAGs) The data address generators in the ADSP-2181 are used to move data between data or program memory and the arithmetic units with automatic memory-address generation. The DAGs are very useful when addressing consecutive elements in buffers. The ADSP-2181 has eight DAGs. Each DAG consists of three registers: The I register - The I register is a pointer to an address in data or program memory. The L register - The L register specifies the length of a buffer indexed by the DAG register. The M register - The M register specifies the increment value for the I register. Circular Buffer Addressing The most common usage of DAGs is when implementing circular buffers. Figure 6 shows a buffer of length three called Circ Buffer and its contents. The buffer is initialized in data memory 12 6th November 2003

with:.var/circ Circ Buffer[3] = 0x1111, 0x3333, 0xAAAA; where the /circ declaration makes the buffer circular. The register I0 is initialized to point to the first element of the buffer by writing I0 = Circ Buffer; The L0 register is set to: L0 = length(circ Buffer); which, in this case, makes L0 = 3. To access consecutive elements in the buffer, M0 is set to: M0 = 1; PSfrag replacements I0 Circ Buffer 0x1111 0x3333 0xAAAA Figure 6: A buffer of length three with an associated I pointer. After the DAG registers have been initialized, the following instruction: AX0 = DM(I0,M0); stores the value pointed to by I0 in AX0, (AX0 = 0x1111). Each time an I register is used, its value is incremented by the value of the corresponding M register. In this case, if the next instruction is: AY0 = DM(I0,M0); the value 0x3333 will be stored in AY0, and I0 will be updated to point to the last element in Circ Buffer. After I0 is used the third time, the pointer will wrap around to once again point to the first element in the buffer. Hence, with each invoke of this DAG, the sequence {0x1111, 0x3333, 0xAAAA, 0x1111, 0x3333, 0xAAAA, 0x1111...} will be produced. By letting M0 = 2, the sequence will instead be {0x1111, 0xAAAA, 0x3333, 0x1111, 0xAAAA, 0x3333...}. If M0 is negative the sequence will be reversed. M0 = -1 gives the sequence {0x1111, 0xAAAA, 0x3333, 0x1111, 0xAAAA, 0x3333, 0x1111...}. Of course, DAGs can be similarly used to store numbers in circular buffers. The syntax: 13 6th November 2003

DM(I0,M0) = AX0; will store the contents of AX0 in the memory location pointed to by I0, and then increment I0 with the value of M0. Multifunction Multiply/Accumulate One of the key features of the ADSP-2181 (any many other DSPs), is the ability to perform multiplication and accumulation and do two memory reads, all in a single core clock cycle. The syntax MR = MR + MX0 * MY0 (SS), MX0 = DM(I0,M0), MY0 = PM(I4,M4); first performs a multiplication between the contents of MX0 and MY0 and adds the result to the previous value of MR. Then, the input registers are loaded with new values from data memory and program memory. Multifunction multiply/accumulate is very useful when implementing fast convolutions sums, as done in the following program example. An FIR Filter Example Program The example code to be used in the following assignments is an FIR filter implementation. This VDSP project, FIRexample, can be downloaded from the course webpage. It consists of the following files: FIRexample.dpj - Project file. Automatically created for new projects. FIRexample.asm - Assembler source code. User defined. ADSP-2181.ldf - Linker definition file. Automatically created or user defined. def2181.h - Header file. User defined. FIRtaps.dat - Filter coefficients for an FIR filter. User defined. The only files that need to be edited in this lab are FIRexample.asm and FIRtaps.dat. FIRexample.asm The FIRexample.asm file contains the source code for an FIR filter implementation on the ADSP-2181. The code begins with some definitions of constants and variables to be used in the code. The constant 14 6th November 2003

#define M 32 defines the number of filter coefficents (filter order + 1). The first variable being initialized is a circular buffer containing the coefficients (taps) to an FIR filter. The coefficients are loaded from the file FIRtaps.dat. /******************** Program Memory Variables ************/.section/pm seg code; /*-- Put all program memory variables under this.section label --*/.var/circ FIRtaps[M] = "FIRtaps.dat"; The declaration.section/pm seg code; is a directive that places all the trailing code and variables in program memory (PM), in a memory section called seg code. Note: Comments in assembler code start with /* and end with */. A single line starting with // is also treated as a comment. The next.section directive places variables in data memory (DM): /******************** Data Memory Variables **************/.section/dm data1; /*-- Put all data memory variables under this.section label --*/ // Delay lines.var/circ DelaylineL[M];.var/circ DelaylineR[M]; // Temporary sample variables.var Sample_L=0;.var Sample_R=0; // Flag for indicating new samples received from ADC.var New_Samples=0; This section initializes two circular delay line buffers for the FIR filter: one for the left stereo channel, DelaylineL, and one for the right channel, DelaylineR. The delay lines store the N + 1 most recent consecutive input samples, x[n i], i = 0, 1,..., N of the filter input signal. The Sample L and Sample R variables store the current samples for the left and right stereo channel respectively. The New Samples variable is a flag used to signal that new samples from the ADC have been received into the DSP. Other variables for the codec are also set up. The next part of the source code is the interrupt vector table which basically tells the processor what to to when specific interrupts occur. Commonly, a JUMP instruction to an interrupt service 15 6th November 2003

routine is executed. For example, an interrupt generated by the codec upon the reception of new samples, causes a JUMP to the interrupt service routine labeled input samples:.section/pm IVsport0recv; jump input_samples; Next, a.section directive to program memory is done, after which the actual program code starts. /******************** Program Code ***********************/.section/pm seg_code; start: The start: label defines the line at which execution of the program code starts. Figure 7 shows the program flow. The program starts with some configurations of the DSP and its serial port (SPORT0). The program then starts to communicate with the AD1847 codec, initializing it and setting the sampling frequency to 11.025 khz. Once the codec and the DSP has been set up, some DAG registers used by the program are initialized. //***** FIR filter variables setup ***************** // FIRtaps DAG register setup I4 = FIRtaps; L4 = M; M4 = 1; // DelaylineL DAG register setup L0 = M; // DelaylineL DAG register setup L1 = M; // DAG M-register setup M1 = 1; M0 = 0; M2 = -1; Next, the delay line buffers for the FIR filter are initialized (all values x[n i] are reset to zero). // Clear Delaylines I0 = DelaylineL; 16 6th November 2003

(Program start) SPORT0 setup AD1847 codec setup Initialize DAGs Clear delay lines (ADC interrupt) PSfrag replacements Idle until an interrupt has occurred Send filtered samples to DAC Fetch new samples from ADC main loop No New samples? Yes (RTI) Filter LEFT sample Filter RIGHT sample Figure 7: Program flow of the FIRexample program. 17 6th November 2003

AX0 = 0; CNTR = M; DO Clear_DelaylineL UNTIL CE; Clear_DelaylineL: DM(I0,M1) = AX0; I1 = DelaylineR; AX0 = 0; CNTR = M; DO Clear_DelaylineR UNTIL CE; Clear_DelaylineR: DM(I1,M1) = AX0; The program then enters an infinite loop called main loop. The program flow of this loop is marked in Figure 7. Essentially, the program continously checks for new samples from the codec. The codec will send two new samples (one for the left, and one for the right stereo channel) to the DSP every 1/f s second (where f s is the sampling frequency). When new input samples have been received from the ADC, a codec interrupt is generated, and the program jumps to the codec interrupt service routine, labeled input samples:. input_samples: ENA sec_reg; // use shadow register bank // *** Send the latest processed samples to DAC *** AX0 = DM(Sample_L); DM(tx_buf + LEFT) = AX0; // Send Left sample AX0 = DM(Sample_R); DM(tx_buf + RIGHT) = AX0; // Send Right sample // *** Get new samples from ADC *** AX0 = DM(rx_buf + LEFT); // Get Left sample DM(Sample_L) = AX0; AX0 = DM(rx_buf + RIGHT); // Get Right sample DM(Sample_R) = AX0; // Set New_Samples flag to indicate that // new samples have been received AR = 1; DM(New_Samples) = AR; DIS sec_reg; RTI; 18 6th November 2003

In the ISR, the output samples, stored in the Sample L (left sample) and Sample R (right sample) variables, are sent to the DAC. The Sample L and Sample R variables are then loaded with the new input samples from the ADC. Finally, the New Samples flag is set, to indicate that new input samples have been received. The program then exits the ISR with an RTI instruction. When the program returns to the main loop loop, it detects (by checking the New Samples flag) that new input samples have been received. The new samples are then processed in two consecutive FIR filter routines. The following section gives a detailed description of the FIR filter routine for the left sample. The routine filtering the right sample works in exactly the same way, but uses a different delay line. FIR Filtering of a Sample The FIR filter routine uses two circular buffers: DelaylineL (the delay line), containing the N +1 most recent consecutive input samples x[n i], i = 0, 1,..., N, and FIRtaps, containing the N +1 filter coefficents b i, i = 0, 1,..., N, where N is the filter order. Initially, the DAG register I4 points to the first filter coefficient, b 0 in the FIRtaps buffer. Figure 8PSfrag shows replacements the initial contents of the FIRtaps buffer and the location of the I4 pointer for a filter of order N = 5. FIRtaps b 0 b 1 b 2 b 3 b 4 b 5 I4 Figure 8: The filter coefficient buffer of a 5th order FIR filter. The sequential instructions in the FIR routine are described below. 1. Initially, the DAG register I0 points to the oldest sample, x[n N], in the DelaylineL buffer. The routine starts by overwriting this sample by the most recent input sample from the ADC, x[n]. AX0 = DM(Sample_L); DM(I0,M0) = AX0; Note that since M0 has been set to zero, I0 is not updated, and will therefore point to the new x[n]. Figure 9 shows the contents of the DelaylineL buffer and the position of I0 for a filter of order N = 5 after these first instructions. 19 6th November 2003

PSfrag replacements DelaylineL x[n] x[n 1] x[n 2] x[n 3] x[n 4] x[n 5] I0 Figure 9: The delay line buffer of a 5th order FIR filter. 2. The MAC input registers are loaded with the values currently pointed to by I0 and I4: x[n] and b 0 respectively. I0 and I4 are both incremented by one (since both M1 and M4 are set to one). I0 will now point to x[n 1] and I4 will point to b 1. The MAC result register, MR is set to zero. MX0 = DM(I0,M1); MY0 = PM(I4,M4); MR = 0; 3. A DO UNTIL instruction creates a loop which, in each loop turn, multiplies the contents of MX0 and MY0, adds the result to MR, and updates MX0 and MY0 with new values from DelaylineL and FIRtaps respectively. The loop performs M-1 such multiplies/accumulates, where M is the length of the DelaylineL and FIRtaps buffers. The last multiply/accumulate is done just after the loop. CNTR = M-1; DO FIRloopL UNTIL CE; FIRloopL: MR = MR + MX0 * MY0 (SS), MX0=DM(I0,M1), MY0=PM(I4,M4); MR = MR + MX0 * MY0 (SS); Confirm from Figures 8 and 9 that, in the case M = 6, this really corresponds to the convolution sum 5 y[n] = x[n i]b i, (1) with the output signal, y[n], stored in MR. i=0 After the loop has finished, both the I0 and the I4 pointers have wrapped around their buffers, resuming the states shown in Figures 8 and 9. 4. I0 must now be modified so that it again points to the oldest sample, x[n N], in the delay line, as it did at the beginning of the FIR filter routine. Thus, the next time the FIR routine is used, the new input sample will overwrite the oldest sample. To update an I register without actually transferring any data, the MODIFY instruction may be used: MODIFY(I0,M2); 20 6th November 2003

This instruction modifies I0 by M2. In this case, since M2 is set to -2, I0 is moved one step back in the delay line, and now points to x[n N] (confirm with Figure 9). 5. Finally, the filtered output sample, y[n] is stored in Sample L, by taking the rounded MAC result from the MR1 register. AX0 = MR1; DM(Sample_L) = AX0; Assignment 1 - Opening, Loading and Running the FIRexample Project In the first assignment, you will open the existing VDSP project FIRexample and load the program into the DSP for execution. The filter coefficents in FIRtaps.dat consist of just a single filter tap, a one in 1.15 hexadecimal representation (0x7FFF), followed by 31 zeros (confirm this by inspecting the contents of FIRtaps.dat, select Open from the File menu). This will produce an output signal that is equal to the input signal. 1. From the course webpage, download the five FIRexample files (FIRexample.dpj, FIRexample.asm, def2181.h, ADSP-2181.ldf, FIRtaps.dat) and place them in a folder on the hard drive of your lab PC. Also download the quimby.wav file. 2. Make sure your DSP board is powered and connected to the PC with the serial cord. Start VisualDSP (Start Programs VisualDSP VisualDSP++ Environment). 3. Press the Reset button on the EZ-KIT Lite board when asked, and click OK. 4. Check that the audio cable from the PC sound card output (line out) is connected to the J1 IN jack on the DSP card. 5. Connect speakers or headphones to the J2-OUT jack. 6. From the Project menu, select Open. Browse to the folder where you stored the downloaded files and select the file named FIRexample.dpj. This will open the project. 7. Figure 10 shows the VDSP environment. From the project window on the right side of the screen, double-click FIRexample.asm located in the source files folder (if the project window is not visible, select Project Window from the View menu). The editor window now shows the source code for the FIR filter program. 8. Build the project by clicking the Build Project icon or by pressing F7 on the keyboard. The output window displays the status of the build. If there are errors in the source code, they will be displayed in the output window, and the build will not be successful. If there are no errors, the program automatically loads into DSP RAM. When the output window shows Load complete, the DSP is ready to run the program. 21 6th November 2003

PSfrag replacements Project window Disassembly Output window Editor window Figure 10: The VisualDSP environment. 9. Click the Run button or press F5 to run the DSP. 10. Play the quimby.wav file using, for example, the media player in Windows. You should now hear the sound in your headphones or speakers. 11. You can halt the DSP by clicking the Halt button or by pressing Shift+F5. Once you have halted the program, it can be restarted by first reloading it into DPS RAM by pressing (Ctrl+R) and then running it (F5). Assignment 2 - Implementing an FIR Low-Pass Filter In this assignment, you will implement your FIR low-pass filter from Lab 1 using the FIRexample project, and test it, using a tone generator. 1. Use the MATLAB dvec2hvec function to convert the coefficients of your FIR low-pass filter from Lab 1 from decimal to hex 1.15 format (type help dvec2hvec for instructions). 2. Open FIRtaps.dat and replace the existing filter coefficients with your converted FIR lowpass filter coefficients. 3. If necessary, change the assembler constant M to match the length of your filter. Changing M will also change the lengths of the delay lines, since they are defined using M. // Delay lines.var/circ DelaylineL[M];.var/circ DelaylineR[M]; 22 6th November 2003

4. Save your files and build (and debug?) the project. 5. Run the program (F5). 6. Connect a tone generator to the analog input jack (J1 IN) on the EZ-KIT Lite board. Note: Make sure that the tone generator amplitude is 0.3 V max. 7. Generate a sinus wave. Vary the frequency and listen to the output signal in your headphones or speakers. Verify your Bode plot of the FIR filter from Lab 1 by checking that frequencies in the pass band go through the filter un-attenuated, and that frequencies in the stop band are attenuated. You can also try the quimby.wav file with your filter. 8. Demonstrate your filter implementation to the lab instructor. Assignment 3 - Creating a new Digital Delay Project A simple digital delay (echo) can be constructed by filtering the input samples with a two-tap FIR filter. The structure of such a delay is shown in Figure 11. The output sample, y[n], is the sum of the input sample, x[n], scaled by b 0, and a delayed input sample, x[n N], scaled by b N. Suitable values for b 0 and b N are 0.6 and 0.3 respectively. The FIRexample project can be used x[n N] x[n] z N PSfrag replacements b 0 b N Σ y[n] Figure 11: A simple digital delay. as a base for a new digital delay project. Do the following: 1. Create a new folder with a suitable name (e.g. delay project ) on your hard drive. 23 6th November 2003

2. Again download the four assembler files used in the previous assignment (FIRexample.asm, def2181.h, ADSP-2181.ldf, FIRtaps.dat), and place them in the new folder (you don t need to download FIRexample.dpj, since you will create a new project). 3. Rename the source file, FIRexample.asm, to delay.asm. 4. Close the current VDSP project by selecting Close from the Project menu. Close all open source windows. 5. Start a new project by selecting New from the Project menu. 6. Browse to your delay project folder, and save the new project as delay. This will create a new project file called delay.dpj. 7. From the Project Options window that pops up, select ADSP-2181 from the Processor list. Select OK. 8. Add the source file (delay.asm), the header file (def2181.h), and the linker file (ADSP- 2181.ldf) to your project by selecting Add to project File(s) from the Project menu. Select all three files and click Add. 9. Open the source file and edit the code to produce the digital delay shown in Figure 11 (see hints below). 10. Save your files, build (and debug?) the project, and run the program. 11. Once the program is working, test your digital delay with the quimby.wav file. 12. Demonstrate your digital delay to the lab instructor. Hints: To produce a reasonable delay, the length of the delay (e.g. the length of the echo) has to be fairly long. The number N in Figure 11 decides the length of the delay in number of samples. The delay time, t d (in seconds), will be dependent on the sampling frequency, f s (in Hz), and N (in number of samples), as t d = N f s. (2) To increase t d, lower the sampling frequency of the codec to 5.5125 khz and increase the filter length constant M to 2000. The sampling frequency of the codec is determined by the 9th value in the init cmds buffer: 0xC853,/* data format register b7 : res b5-6: 0=8-bit unsigned linear PCM 24 6th November 2003

1=8-bit u-law companded 2=16-bit signed linear PCM 3=8-bit A-law companded b4 : 0=mono, 1=stereo b0-3: 0= 8. 1= 5.5125 2= 16. 3= 11.025 4= 27.42857 5= 18.9 6= 32. 7= 22.05 8=. 9= 37.8 a=. b= 44.1 c= 48. d= 33.075 e= 9.6 f= 6.615 (b0) : 0=XTAL1 24.576 MHz; 1=XTAL2 16.9344 MHz Changing the value 0xC853 to 0xC851 sets the sampling frequency to 5.5125 khz. Changing the filter coefficients to a two-tap, length 2000 filter, is best done by not using the FIRtaps.dat file. Instead, define the FIRtaps buffer without initializing it:.var/circ FIRtaps[N]; and then set the first and last coeficcient to 0.6 and 0.3 respectively, and the other coefficients to zero. This is preferably done using a DO UNTIL loop. This loop can be placed just prior to the main loop: label in the source code. 25 6th November 2003