Professional Documents
Culture Documents
Introductory Course in
DSP System Design
by David Skolnick Download PDF
Having heard a lot about digital signal processing (DSP) technology, you may have
wanted to find out what can be done with DSP, investigate why DSP is preferred to
analog circuitry for many types of operations, and discover how to learn enough to
design your own DSP system. This article, the first of a series, is an opportunity to
take a substantial first step towards finding answers to your questions. This series is
an introduction to DSP topics from the point of view of analog system designers
seeking additional tools for handling analog signals. Designers reading this series can
learn about the possibilities of DSP to deal with analog signals and where to find
additional sources of information and assistance.
What is [a] DSP? In brief, DSPs are processors or microcomputers whose hardware,
software, and instruction sets are optimized for high-speed numeric processing
applications an essential for processing digital data representing analog signals in real
time. What a DSP does is straightforward. When acting as a digital filter, for example,
the DSP receives digital values based on samples of a signal, calculates the results of
a filter function operating on these values, and provides digital values that represent
the filter output; it can also provide system control signals based on properties of
these values. The DSP’s high-speed arithmetic and logical hardware is programmed to
rapidly execute algorithms modelling the filter transformation.
a response within the passband that is completely flat with zero phase shift
infinite attenuation in the stopband.
Useful additions would include:
passband tuning and width control
stopband rolloff control.
As Figure 1 shows, an analog approach using second-order filters would require quite
a few staggered high-Q sections; the difficulty of tuning and adjusting it can be
imagined.
This sampling rate is determined by the amount of signal information that is needed
for processing the signals adequately for a given application. In order for an ADC to
provide enough samples to accurately describe the real-world signal, the sampling rate
must be at least twice the highest-frequency component of the analog signal. For
example, to accurately describe an audio signal containing frequencies up to 20 kHz,
the ADC must sample the signal at a minimum of 40 kHz. Since arriving signals can
easily contain component frequencies above 20 kHz (including noise), they must be
removed before sampling by feeding the signal through a low-pass filter ahead of the
ADC. This filter, known as an anti-aliasing filter, is intended to remove the
frequencies above 20 kHz that could corrupt the converted signal.
However, the anti-aliasing filter has a finite frequency rolloff, so additional bandwidth
must be provided for the filter’s transition band. For example, with an input signal
bandwidth of 20 kHz, one might allow 2 to 4 kHz of extra bandwidth.
Thus if all of the time between samples is available for operations to implement the
algorithm, a processor with a performance level of 2.4 MOPS is required. Note that
the two common ratings for DSPs, based on operations per second (MOPS) and
instructions per second (MIPS), are not the same. A processor with a 10-MIPS rating
that can perform 8 operations per instruction has basically the same performance as a
faster processor with a 40 MIPS rating that can only perform 2 operations per
instruction.
Interrupt latency (response delay) depends on several factors; the most dominant is
the DSP architecture’s instruction pipelining. An instruction pipeline consists of the
number of instruction cycles that occur between the time an interrupt is received and
the time that program execution resumes. More pipeline levels in a DSP result in
longer interrupt latency. For example, if a processor has a 20-ns cycle time and
requires 10 cycles to respond to an interrupt, 200 ns elapse before it executes any
signal-processing instructions.
When data is acquired one sample at a time, this 200-ns overhead will not hurt if the
DSP finishes the processing of each sample before the next arrives. When data is
acquired sample-by-sample while processing a frame at a time, however, an
interrupted system wastes processor instruction cycles. For example, a system with a
200-ns interrupt response time running a frame-based algorithm, such as the FFT,
with a frame size of 1024 samples, would require 204.8 µs of overhead. That amounts
to more than 10,000 instruction cycles wasted to latency productive time when the
DSP could be performing signal processing. This waste is easy to avoid in DSPs
having architectural features such as DMA and dual memory access; they let the DSP
receive and store data without interrupting the processor.
Digital Signal Processing: The incoming data is handled by the DSP’s algorithm
software. When the processor completes the required calculations, it sends the result
to the DAC. Because the signal processing is programmable, considerable flexibility
is available in handling the data and improving system performance with incremental
programming adjustments.
Analog Output: The DAC converts the DSP’s output into the desired analog output
at the next sample clock. The converter’s output is smoothed by a
low-pass, anti-imaging filter (also called a reconstruction filter), to produce the
reconstructed analog signal.
Host Interface: An optional host interface lets the DSP communicate with external
systems, sending and receiving data and control information.
DSP overview
Real-time DSP operation
Real-world signals
Sampling rates and anti-alias filtering
DSP algorithm time budget
Sample driven versus frame driven data acquisition
Because these issues involve many valuable levels of detail that we could not do
justice to in this brief article, you should consider reading Richard Higgins’s
text, Digital Signal Processing in VLSI (see References below). This text provides a
complete overview of DSP theory, implementation issues, and reduction to practice
(with devices available at the time it was published), plus exercises and examples.
The Reference section below also contains other sources that further amplify this
article’s issues. To prepare for the next articles in this series, you might want to get
free copies of the ADSP-2100 Family User’s Manual* and the ADSP-2106x SHARC
User’s Manual.* These texts provide information on Analog Devices’s fixed- and
floating-point DSP architectures, a major topic in these articles. The next article will
cover the following territory:
A Figura 4 mostra o filtro necessário para rejeitar quaisquer sinais com frequências
acima da metade de uma taxa de amostragem de 48 kHz. Rejeição significa
atenuação para menos de 1/2 bit menos significativo (LSB) da resolução do
ADC. Uma maneira de alcançar este nível de rejeição sem um filtro analógico
altamente sofisticado é usar um conversor de oversampling , como um ADC
sigma-delta.Normalmente obtém amostras de baixa resolução (por exemplo, 1 bit) em
taxas de megahertz muito mais rápido que o dobro do componente de maior
freqüência facilitando bastante a necessidade do filtro analógico à frente do
conversor. Um filtro digital interno (DSP no trabalho!) Restaura a resolução e a
resposta de frequência necessárias. Para muitas aplicações, os conversores de
oversampling reduzem o esforço e o custo do projeto do sistema.
Assim, se todo o tempo entre amostras estiver disponível para operações para
implementar o algoritmo, será necessário um processador com um nível de
desempenho de 2,4 MOPS. Observe que as duas classificações comuns para DSPs,
baseadas em operações por segundo (MOPS) e instruções por segundo (MIPS), não
são as mesmas. Um processador com uma classificação de 10-MIPS que pode
executar 8 operações por instrução tem basicamente o mesmo desempenho que um
processador mais rápido com uma classificação de 40 MIPS que pode realizar apenas
2 operações por instrução.
Amostragem de vários sinais do mundo real
Há duas maneiras básicas de adquirir dados, uma amostra por vez ou um quadro por
vez (processamento contínuo versus processamento em lote). Os sistemas baseados
em amostras, como um filtro digital, adquirem dados uma amostra por vez. Como
mostrado na Figura 6, a cada tick do relógio, uma amostra entra no sistema e uma
amostra processada é enviada. A forma de onda de saída se desenvolve
continuamente.
Quando os dados são adquiridos uma amostra de cada vez, essa sobrecarga de 200 ns
não irá prejudicar se o DSP terminar o processamento de cada amostra antes da
próxima chegar. Quando os dados são adquiridos amostra por amostra ao processar
um quadro de cada vez, no entanto, um sistema interrompido desperdiça ciclos de
instrução do processador. Por exemplo, um sistema com um tempo de resposta de
interrupção de 200 ns executando um algoritmo baseado em quadros, como o FFT,
com um tamanho de quadro de 1024 amostras, exigiria 204,8 µs de sobrecarga. Isso
equivale a mais de 10.000 ciclos de instrução desperdiçados em latência tempo
produtivo quando o DSP poderia estar executando o processamento de sinal. Esse
desperdício é fácil de evitar em DSPs com recursos de arquitetura, como DMA e
acesso de memória dupla; eles permitem que o DSP receba e armazene dados sem
interromper o processador.
Observe como poucos componentes compõem o sistema DSP, porque grande parte da
funcionalidade do sistema vem do DSP programável. Os conversores canalizam os
dados para dentro e fora do DSP; o tempo do ADC é controlado por um relógio de
amostragem preciso. Para simplificar o design do sistema, muitos dispositivos
conversores disponíveis atualmente combinam alguns ou todos os seguintes: um
conversor A / D, um conversor D / A, um relógio de amostragem e filtros para
anti-aliasing e anti-imaging. O oscilador de clock nesses tipos de componentes de E /
S é controlado separadamente por um cristal externo. Aqui estão alguns pontos
importantes sobre o fluxo de dados nesse tipo de sistema DSP:
Revise e visualize
O objetivo deste artigo foi fornecer uma visão geral dos principais conceitos de design
de DSP e explicar algumas das razões pelas quais um DSP é mais adequado para
circuitos analógicos para algumas aplicações. Os problemas introduzidos neste artigo
incluem:
If you've read Part 1 of this series (or are already familiar with some of the ways a
DSP can work with real-world signals), you might want to learn more about how
digital filters (such as those described in Part 1) can be implemented with a DSP.This
article, the second of a series, introduces the following DSP topics:
This series seeks to describe these topics from the perspective of analog system
designers who want to add DSP to their design repertoire. Using the information from
articles in this series as an introduction, designers can make more informed decisions
about when DSP designs might be more productive than analog circuits.
The three principal reasons for using digital filtering are (1) closer approach to ideal
filter approximations, (2) ability to adjust filter characteristics in software rather than
by physical tuning, and (3) compatibility of filter response with sampled data. The
two best-known filters described in Part 1 are the finite impulse-response (FIR) and
infinite impulse-response (IIR) types. The FIR filter response is called finite because
its output is based solely on a finite set of input samples; it is non-recursive and has
no poles, only zeroes in its s-plane.The IIR filter, on the other hand, has a response
that can go on indefinitely (and can be unstable) because it is recursive, i.e., its output
values are affected by both input and output. It has both poles and zeroes in its s-plane.
Figure 1 shows the typical filter architectures and summation formulas that appeared
in Part 1.
Second, take those operations and write them as a program.This can be a fairly
arduous task. Fortunately, there is much "canned" software available, often in a
high-level language (HLL) such as C, somewhat simplifying (but by no means
eliminating!) the job of programming. From the point of view of learning, though, it
may be more instructive to start with assembly language; also assembly language
algorithms are often more useful than HLL where system performance must be
optimized. At the level of abstraction of some high-level languages, the program may
not look much like the equations. For example, Figure 2 shows an example of an FIR
algorithm implemented as a C program.*
There are many analysis packages available that support algorithm modeling; see the
references at the end of this article for several popular packages.We will return to
algorithm modeling at various times in the course of this series. Now, continuing the
discussion of the process, after these filter algorithms have been modeled, they are
ready for implementation in DSP architecture.
Relating The Models To DSP Architecture: For programming, one must understand
four sections of DSP architecture: numeric, memory, sequencer, and I/O operations.
This architectural discussion is generic (applying to general DSP concepts), but it is
also specific as it relates to programming examples later in this article. Figure 3 shows
the generalized DSP architecture that this section describes.
Architecture
Numeric Section: Because DSPs must complete multiply/accumulate, add, subtract,
and/or bit-shift operations in a single instruction cycle, hardware optimized for
numeric operations is central to all DSP processors. It is this hardware that
distinguishes DSPs from general-purpose microprocessors, which can require many
cycles to complete these types of operations. In the digital filters (and other DSP
algorithms), the DSP must complete multiple steps of arithmetic operations involving
data values and coefficients, to produce responses in real time that have not been
possible with general-purpose processors.
Other features of the numeric section can facilitate programming in real-time systems.
By making operations contingent on a variety of conditional states, which result from
numeric operations, these can serve as variables in a program's execution, testing for
carries, overflows, saturates, flags, or other states. Using these conditionals, a DSP
can rapidly handle decisions about program flow based on numeric operations. The
need to be constantly feeding data into the numeric section is a key design influence
on the DSP's memory and internal bus structures.
Memory Section: DSP memory and bus architecture design is guided by the need for
speed. Data and instructions must flow into the numeric and sequencing sections of
the DSP on every instruction cycle. There can be no delays, no bottlenecks.
Everything about the design focuses on throughput.
"The von Neumann concept was that by treating instructions as data one could make
alterations in programs, enhancing the ability for programs to 'learn'."
"For some reason, the latter was given von Neumann's name, while the former took its
name from the Harvard line of machines."
To put this focus on throughput in perspective, one can look at the difference between
DSP memory design and memory for other microprocessors. Most microprocessors
use a single memory space containing both data and instructions, using one bus for
address and other for data or instructions. This architecture is called von Neumann
architecture. The limitation on throughput in a von Neumann architecture comes from
having to choose between either a piece of data or an instruction on each cycle. In
DSPs, memory is typically divided into program and data memory-with separate
busses for each. This type of architecture is referred to as Harvard architecture. By
separating the data and instructions, the DSP can fetch multiple items on each cycle,
doubling throughput. Additional optimizations, such as instruction cache, results
feedback, and context switching also increase DSP throughput.
Most DSP algorithms require two operands to be fetched from memory in a single
cycle to become inputs to the arithmetic units. To supply the addresses of these two
operands in a flexible manner, the DSP has two DAGs. In the DSP's modified
Harvard architecture, one address generator supplies an address over the data-memory
address bus; the other supplies an address over the program-memory address bus. By
performing these two data fetches in time for the next numeric instruction, the DSP is
able to sustain single-cycle execution of instructions.
DSP algorithms, such as the example digital filters, usually require data in a range of
addresses (a buffer) to be addressed so that the address pointer "wraps-around" from
the end of the buffer back to the start of the buffer (buffer length). This pointer
movement is called circular buffering. (In the filter equations, each summation
basically results from a sequence of multiply-and-accumulates of a circular buffer of
data points and a circular buffer of coefficients). A variation of circular buffering,
which is required in some applications, advances the address pointer by values greater
than one address per "step," but still wraps around at a given length. This variation is
called modulo circular buffering.
By supporting various types of buffering with its DAGs, the DSP is able to perform
address modify and compare operations in hardware for optimum efficiency.
Performing these functions in software (as occurs in general purpose processors)
limits the processor's ability to handle real-time signals.
Because buffering is an unusual concept, yet key to digital signal processing, a brief
buffering example is useful. In the example illustrated in Figure 4, a buffer of eight
locations resides in memory starting at address 30. The address generator must
calculate next addresses that stay within this buffer yet keep the proper data spacing
so that two locations are skipped. The address generator outputs the address 30 on to
the address bus while it modifies the address to 33 for the next cycle's memory access.
This process repeats, moving the address pointer through the buffer. A special case
occurs when the address 36 gets modified to 39. The address 39 is outside the buffer.
The address generator detects that the address has fallen outside of the buffer
boundary and modifies the address to 31 as if the end of the buffer is connected to the
start of the buffer. The update, compare, and modify occur with no overhead. In one
cycle, the address 36 is output onto the address bus. On the next cycle, the address 31
is output onto the address bus. This modulo circular buffering serves the needs of
algorithms such as interpolation filters and saves instruction cycles for processing.
Figure 4.Example of
modulo circular buffering.
Sequencer Section: Because most DSP algorithms (such as the example filters) are
by nature repetitive, the DSP's program sequencer needs to loop through the repeated
code without incurring overhead while getting from the end of the loop back to the
start of the loop. This capability is called zero-overhead looping. Having the ability to
loop without overhead is a key area in which DSPs differ from conventional
microprocessors. Typically, microprocessors require that program loops be
maintained in software, placing a conditional instruction at the end of the loop. This
conditional instruction determines whether the address pointer moves (jumps) back to
the top of the loop or to another address. Because getting these addresses from
memory takes time- and availability of time for signal-processing is critical in DSP
applications-DSPs cannot waste cycles retrieving addresses for conditional program
sequencing (branching) in this manner. Instead, DSPs perform these test and branch
functions in hardware, storing the needed addresses.
As Figure 5 shows, the DSP executes the last instruction of the loop in one cycle. On
the next cycle, the DSP evaluates the conditional and executes either the first
instruction at the top of the loop or the first instruction outside the loop. Because the
DSP uses dedicated hardware for these operations, no extra time is wasted with
software evaluating conditionals, retrieving addresses, or branching program
execution.
Figure 5.
Example of program loop.
Input/Output (I/O) Section: As noted again and again, there is a need for
tremendous throughput of data to the DSP; everything about its design is focused on
funneling data into and out of the numeric, memory, and sequencer sections. The
source of the data- and destination of the output (the result of signal processing)-is the
DSP's connection to its system and the real-world. A number of I/O functions are
required to complete signal processing tasks. Off-DSP memory arrays store processor
instructions and data. Communication channels (such as serial ports, I/O ports and
direct memory accessing (DMA) channels transfer data into and out of the DSP
quickly. Other functions (such as timers and program boot logic) ease DSP system
development. A brief list of typical I/O tasks in a DSP system includes the following
(among many others):
Boot loading: At Reset, the DSP loads instructions form an external source
(EPROM or host) usually through an external memory interface.
Serial communications: The DSP receives or transmits data through a
synchronous serial port (SPORT), communicating with codecs, ADCs, DACs, or
other devices.
Memory-mapped I/O: The DSP receives or transmits data through an off-DSP
memory location that is decoded by an external device.
The FIR filter interrupt subroutine (the last segment of code) is the heart of the filter
program. The processor responds to the interrupt, saving the context of the main
routine and jumping to the interrupt routine. This interrupt routine processes the filter
input sample, reading data and filter coefficients from memory and storing them in
data registers of the DSP processor. After processing the input sample, the DSP sends
an output sample to the D/A converter.
.module/RAM/ABS=0 FIR_PROGRAM;
/******** Initialize Constants and Variables *****************/
.const taps=127;
.var/dm/circ data[taps];
.var/pm/circ fir_coefs[taps];
.init fir_coefs: ;
.var/dm/circ output_data[taps];
/******** Interrupt vector table *****************************/
reset_svc: jump start; rti; rti; rti;
/*00: reset */
irq2_svc: /*04: IRQ2 */
si=io(0); /* get next sample */
dm(i0,m0)=si; /* store in tap delay line */
jump fir; /* jump to fir filter */
nop; /* nop is placeholder */
irql1_svc: rti; rti; rti; rti; /*08: IRQL1 */
irql0_svc: rti; rti; rti; rti; /*0c: IRQL0 */
sp0tx_svc: rti; rti; rti; rti; /*10: SPORT0 tx */
sp0rx_svc: rti; rti; rti; rti; /*14: SPORT1 rx */
irqe_svc: rti; rti; rti; rti; /*18: IRQE */
bdma_svc: rti; rti; rti; rti; /*1c: BDMA */
sp1tx_svc: rti; rti; rti; rti; /*20: SPORT1 tx or IRQ1 */
sp1rx_svc: rti; rti; rti; rti; /*24: SPORT1 rx or IRQ0 */
timer_svc: rti; rti; rti; rti; /*28: timer */
pwdn_svc: rti; rti; rti; rti; /*2c: power down */
/******* START OF PROGRAM - initialize mask, pointers **********/
start:
/* set up various control registers */
ICNTL=0x07; /* set IRQ2, IRQ1, IRQ0 edge sensitive */
IFC=0xFF; /* clear all pending interrupts */
NOP; /* add nop because of one cycle */
/* synchronization delay of IFC */
SI=0x0000;
DM(0x3FFF)=SI; /* sports not enabled */
/* sport1 set for IRQ1, IRQ0, FI, FO */
IMASK=0x200; /* enable IRQ2 interrupt */
i0=^data; /* index to data buffer */
l0=taps; /* length of data buffer */
m0=1; /* post modify value */
i4=^fir_coefs; /* index to fir_coefs buffer */
l4=taps; /* length of fir_coefs buffer */
m4=1; /* post modify value */
i2=^output_data; /* index to data buffer */
l2=taps; /* length of data buffer */
cntr=taps;
do zero until ce;
dm(i0,m0)=0; /* clear out the tap delay data buffer */
zero: dm(i2,m0)=0; /* clear out the output_data buffer */
/**** WAIT for IRQ2 Interrupt - then JUMP to INTERRUPT VECTOR **/
wait: idle; /* wait for IRQ2 interrupt */
jump wait;
/******* FIR FILTER interrupt subroutine ***********************/
fir cntr=taps-1; /* set up loop counter */
mr=0, mx0=dm(i0,m0), my0=pm(i4,m4);
/* fetch data and coefficient */
do fir1loop until ce; /* set up loop */
fir1loop: mr=mr+mx0*my0(ss), mx0=dm(i0,m0), my0=pm(i4,m4);
/* calculations */
/* if not ce jump fir1loop;*/
mr=mr+mx0*my0(rnd); /* round final result to 16-bits */
if mv sat mr; /* if overflow, saturate */
io(1)=mr1; /* send result to DAC */
dm(i2,m0)=mr1;
rti;
/******* END OF PROGRAM *************************************/
.endmod;
Note that this program uses DSP features that perform operations with zero overhead,
usually introduced by a conditional. In particular, program loops and data buffers are
maintained with zero overhead. The multifunction instruction in the core of the filter
loop performs a multiply/accumulate operation while the next data word and filter
coefficient are fetched from memory.
The program checks the final result of the filter calculation for any overflow. If the
final value has overflowed, the value is saturated to emulate the clipping of an analog
signal. Finally, the context of the main routine is restored and the instruction flow is
returned to the main routine with a return from interrupt (RTI) instruction.
Filters as programs
DSP architecture (generalized)
DSP assembly language
Because these issues involve many valuable levels of detail that one could not do
justice to in this brief article, you should consider reading Richard Higgins's
text, Digital Signal Processing in VLSI, and Paul Embree's text, C Algorithms For
Real Time DSP (see References below). These texts provides a complete overview of
DSP theory, implementation issues, and reduction to practice (with devices available
at the time of publication), plus exercises and examples. The Reference section below
also contains other sources that further amplify this article's issues. To prepare for the
next articles in this series, you might want to get free copies of the ADSP-2100
Family User's Manual* or the ADSP-2106x SHARC User's Manual.* These texts
provide information on Analog Devices's fixed- and floating-point DSP architectures,
a major topic in these articles. Working through this series, each part adds some
feature or information contributing to the series goal of developing a DSP system. To
reach this goal, the next article describes the series' development platform (the
ADSP-2181 EZ-KIT LITE) and introduces additional DSP development topics.
**
Se você leu a Parte 1 desta série (ou já está familiarizado com algumas das maneiras
pelas quais um DSP pode trabalhar com sinais do mundo real), talvez você queira
aprender mais sobre como os filtros digitais (como aqueles descritos na Parte 1) pode
ser implementado com um DSP. Este artigo, o segundo de uma série, apresenta os
seguintes tópicos do DSP:
As três principais razões para usar a filtragem digital são (1) abordagem mais próxima
das aproximações de filtro ideais, (2) capacidade de ajustar as características do filtro
em software e não por ajuste físico e (3) compatibilidade da resposta do filtro com
dados amostrados. Os dois filtros mais conhecidos descritos na Parte 1 são os tipos de
resposta ao impulso finito (FIR) e resposta ao impulso infinito (IIR). A resposta do
filtro FIR é chamada de finita porque sua saída é baseada unicamente em um conjunto
finito de amostras de entrada; é não-recursivo e não tem polos, apenas zeros em seu
s-plane. O filtro IIR, por outro lado, tem uma resposta que pode continuar
indefinidamente (e pode ser instável) porque é recursiva, ou seja, sua saída os valores
são afetados pela entrada e pela saída. Tem ambos os pólos e zeros no seu plano s. A
Figura 1 mostra as típicas arquiteturas de filtro e fórmulas de soma que apareceram na
Parte 1.
Segundo, pegue essas operações e escreva-as como um programa. Essa pode ser uma
tarefa bastante árdua. Felizmente, há muitos softwares "enlatados" disponíveis, muitas
vezes em uma linguagem de alto nível (HLL), como C, simplificando um pouco (mas
de forma alguma eliminando!) O trabalho de programação. Do ponto de vista da
aprendizagem, porém, pode ser mais instrutivo começar com a linguagem
assembly; também os algoritmos de linguagem assembly são geralmente mais úteis do
que o HLL, no qual o desempenho do sistema deve ser otimizado. No nível de
abstração de algumas linguagens de alto nível, o programa pode não se parecer muito
com as equações. Por exemplo, a Figura 2 mostra um exemplo de um algoritmo FIR
implementado como um programa em C. *
int i;
saída flutuante;
hist_ptr = history;
Arquitetura
Seção Numérica: Como os DSPs devem concluir operações de multiplicação /
acumulação, adição, subtração e / ou deslocamento de bits em um único ciclo de
instrução, o hardware otimizado para operações numéricas é fundamental para todos
os processadores DSP. É esse hardware que distingue os DSPs dos
microprocessadores de uso geral, que podem exigir muitos ciclos para concluir esses
tipos de operações. Nos filtros digitais (e outros algoritmos DSP), o DSP deve
completar várias etapas de operações aritméticas envolvendo valores de dados e
coeficientes, para produzir respostas em tempo real que não foram possíveis com
processadores de uso geral.
Do ponto de vista da programação, uma arquitetura DSP que usa seções numéricas
separadas fornece grande flexibilidade e eficiência. Existem muitos caminhos não
conflitantes para dados, permitindo a conclusão de ciclo único de operações
numéricas. A arquitetura do DSP também deve fornecer um amplo intervalo dinâmico
para operações MAC, com a capacidade de lidar com resultados de multiplicação que
são o dobro da largura das saídas de entradas e acumulações que podem ser montadas
sem transbordamento. (Em um DSP de 16 bits, esse recurso equivale a entradas de
dados de 16 bits e uma saída de resultados de 40 bits do MAC.) É necessário esse
intervalo para manipular a maioria dos algoritmos de DSP (como filtros).
"O conceito de von Neumann era que, ao tratar as instruções como dados, era possível
fazer alterações nos programas, aumentando a capacidade de os programas"
aprenderem "."
"Por alguma razão, este último recebeu o nome de von Neumann, enquanto o
primeiro recebeu o nome da linha de máquinas de Harvard."
Para colocar esse foco na taxa de transferência em perspectiva, pode-se observar a
diferença entre o design da memória DSP e a memória para outros
microprocessadores. A maioria dos microprocessadores usa um único espaço de
memória contendo dados e instruções, usando um barramento para endereço e outro
para dados ou instruções. Essa arquitetura é chamada de arquitetura de von
Neumann. A limitação na taxa de transferência em uma arquitetura von Neumann
vem de ter que escolher entre um dado ou uma instrução em cada ciclo. Nos DSPs, a
memória é tipicamente dividida em programa e memória de dados - com barramentos
separados para cada um. Esse tipo de arquitetura é conhecido como arquitetura de
Harvard. Ao separar os dados e as instruções, o DSP pode buscar vários itens em cada
ciclo, duplicando o rendimento. Otimizações adicionais, como cache de instruções,
feedback de resultados e comutação de contexto também aumentam o throughput do
DSP.
A maioria dos algoritmos DSP exige que dois operandos sejam buscados da memória
em um único ciclo para se tornarem entradas para as unidades aritméticas. Para
fornecer os endereços desses dois operandos de maneira flexível, o DSP possui dois
DAGs. Na arquitetura modificada de Harvard do DSP, um gerador de endereço
fornece um endereço através do barramento de endereço de memória de dados; o
outro fornece um endereço através do barramento de endereços da memória do
programa. Ao realizar essas duas buscas de dados a tempo para a próxima instrução
numérica, o DSP é capaz de sustentar a execução de instruções de ciclo único.
Ao suportar vários tipos de buffering com seus DAGs, o DSP pode executar a
modificação de endereço e comparar as operações no hardware para obter a eficiência
ideal. A execução dessas funções no software (como ocorre em processadores de uso
geral) limita a capacidade do processador de manipular sinais em tempo real.
Como o armazenamento em buffer é um conceito incomum, mas essencial para o
processamento digital de sinais, um breve exemplo de armazenamento em buffer é
útil. No exemplo ilustrado na Figura 4, um buffer de oito locais reside na memória
que começa no endereço 30. O gerador de endereços deve calcular os próximos
endereços que permanecem dentro desse buffer e manter o espaçamento de dados
adequado para que dois locais sejam ignorados. O gerador de endereços envia o
endereço 30 para o barramento de endereços enquanto modifica o endereço para 33
para o acesso à memória do próximo ciclo.Esse processo se repete, movendo o
ponteiro de endereço pelo buffer. Um caso especial ocorre quando o endereço 36 é
modificado para 39. O endereço 39 está fora do buffer. O gerador de endereços
detecta que o endereço caiu fora do limite do buffer e modifica o endereço para 31,
como se o final do buffer estivesse conectado ao início do buffer. o atualizar,
comparar e modificar ocorrer sem sobrecarga . Em um ciclo, o endereço 36 é
enviado para o barramento de endereços. No próximo ciclo, o endereço 31 é enviado
para o barramento de endereços. Esse módulo de buffer circular atende às
necessidades de algoritmos como filtros de interpolação e salva ciclos de instrução
para processamento.
Figura 4. Exemplo de
buffer circular do módulo.
Figura 5.
Exemplo de loop de programa.
.constantes = 127;
.init fir_coefs:;
/ * 00: reset * /
começar:
SI = 0x0000;
cntr = taps;
/ **** ESPERE por IRQ2 Interromper - então JUMP para INTERRUPÇÃO VETOR
** /
pule a espera;
fir1loop: mr = mr + mx0 * my0 (ss), mx0 = dm (i0, m0), my0 = pm (i4, m4);
/ * cálculos * /
rti;
.endmod;
Figura 6. Um filtro FIR na linguagem assembly ADSP-2181.
Observe que este programa usa recursos de DSP que executam operações com
sobrecarga zero, geralmente introduzidas por uma condicional. Em particular, loops
de programa e buffers de dados são mantidos com sobrecarga zero. A instrução
multifuncional no núcleo do loop de filtro executa uma operação de multiplicação /
acumulação enquanto a próxima palavra de dados e o coeficiente do filtro são
buscados da memória.
Revise e visualize
O objetivo deste artigo foi fornecer uma ligação entre a teoria dos filtros e a
implementação do filtro digital. No caminho, este artigo aborda a modelagem de
filtros com programas HLL, usando arquitetura DSP e experimentando softwares de
filtro. Os problemas introduzidos neste artigo incluem:
So far, we have described the physical architecture of the DSP processor, explained
how DSP can provide some advantages over traditionally analog circuitry, and
examined digital filtering, showing how the programmable nature of DSP lends itself
to such algorithms. Now we look at the process of implementing a finite-impulse-
response (FIR) filter algorithm (briefly introduced in Part 2, implemented in
ADSP-2100 Family assembly code) on a hardware platform, the ADSP-2181 EZ-Kit
Lite&tm;. The implementation is expanded to handle data I/O issues.
The filter structure suggests the physical elements needed to implement this algorithm
by computation using a DSP. For the computation itself, each output sample requires
a number of multiply-accumulate operations equal to the length of the filter.
The delay line for input data and the coefficient value list require reserved areas of
memory in the DSP for storing data values and coefficients. The DSP’s enhanced
Harvard architecture lets programmers store data in Program Memory as well as in
Data Memory, and thus perform two simultaneous memory accesses in every cycle
from the DSP’s internal SRAM. With Data Memory holding the incoming samples,
and Program Memory storing the coefficient values, both a data value and a
coefficient value can be fetched in a single cycle for computation.
This DSP architecture favors programs that use circular buffering (discussed briefly in
Part 2 and later in this installment). The implication is that address pointers need to be
initialized only at the beginning of the program, and the circular buffering mechanism
ensures that the pointer does not leave the bounds of its assigned memory buffer—a
capability used extensively in the FIR filter code for both input delay line and
coefficients. Once the elements of the program have been determined, the next step is
to develop the DSP source code to implement the algorithm.
Hardware implementation: Here the code is run on a real DSP, typically in several
phases: a) tryout on an evaluation platform such as EZ-Kit Lite; b) in-circuit
emulation, and c) production ROM generation. Tryout provides a quick go/no-go
determination of the program’s operation; this technique is the implementation
method used in this article. In-circuit emulation monitors software debug in the
system, where a tool such as an EZ-ICE™ controls processor operation on the target
platform. After all debug is complete, a boot ROM of the final code can be generated;
it serves as the final production implementation.
Available system resources information is recorded in a system description file for use
by the ADSP-2100 Family development tools. A system description file has a .SYS
extension. The following list shows a system description file [EZKIT_LT.SYS]:
.seg/PM/RAM/ABS=0/code/data int_pm[16384];
.seg/DM/RAM/ABS=0 int_dm[16352];
The listing declares 16,384 locations of PM as RAM, starting at address 0, to let both
code segments and data values be placed there. Also declared are 16,352 available
locations of data memory as RAM, starting at address 0. Because these processors use
a Harvard architecture with two distinct memory spaces, PM address 0 is distinct from
DM address 0. The ADSP-2181 EZ-Kit Lite’s codec is connected to the DSP using a
serial port, which is not declared in the system description file. To make the system
description file available to other software tools, the System Builder utility, BLD21,
converts the .SYS file into an architecture, or .ACH, file. The output of the System
Builder is a file named EZKIT_LT.ACH.
After writing the code, the next step is to generate an executable file, i.e., turn the
code into instructions that the DSP can execute. First one assembles the DSP code.
This converts the program file into a format that the other development tools can
process. Assembling also checks the code for syntax errors. Next, one links the code
to generate the DSP executable, using the available memory that is declared in the
architecture file. The Linker fits all of the code and data from the source code into the
memory space; the output is a DSP executable file, which can be downloaded to the
EZ-Kit Lite board.
The incoming data will be sampled using the on-board AD1847 codec, which has
programmable sampling rate, input gain, output attenuation, input selection, and input
mixing. Its programmable nature makes the system flexible, but it also adds a task of
programming to initialize it for the DSP system.
Accessing Data
For this example, a series of control words to the codec—to be defined at the
beginning of the program in the first section of the listing—will initialize it for an
8-kHz sampling rate, with moderate gain values on each of the input channels. Since
the AD1847 is programmable, users would typically reuse interface and initialization
code segments, changing only the specific register values for different applications.
This example will add the specific filter segment to an existing code segment found in
the EZ-Kit Lite software.
This interface code declares two areas in memory to be used for data I/O: "tx_buf",
for data to be transmitted out of the codec, and "rx_buf", where incoming data is
received. Each of these memory areas, or buffers, contains three elements, a control or
status word, left-channel data, and right-channel data. For each sample period, the
DSP will receive from the codec a status word, left channel data, and right channel
data. On every sample period, the DSP must supply to the codec a transmit control
word, left channel data, and right channel data. In this application, the control
information sent to the codec will not be altered, so the first word in the transmit data
buffer will be left as is. We will assume that the source is a monophonic microphone,
using the right channel (no concern about left-channel input data).
Using the I/O shell program found in the EZ-Kit Lite software, we need only be
involved with the section of code labeled "input_samples". This section of code is
accessed when new data is received from the codec ready to be processed. If only the
right channel data is required, we need to read the data located in data memory at
location rx_buf + 2, and place it in a data register to be fed into the filter program.
The data arriving from the codec needs to be fed into the filter algorithm via the input
delay line, using the circular buffering capability of the ADSP-2181. The length of the
input delay line is determined by the number of coefficients used for the filter.
Because the data buffer is circular, the oldest data value in the buffer will be wherever
the pointer is pointing after the last filter access (Figure 4) . Likewise the coefficients,
always accessed in the same order every time through the filter, are placed in a
circular buffer in Program Memory.
Algorithm Code
To operate on the received data, the code section published in the last installment can
be used with few modifications. To implement this filter, we need to use the
multiply/accumulate (MAC) computational unit and the data address-generators.
The ADSP-2181’s MAC stores the result in a 40-bit register (32 bits for the product
of 2 16-bit words, and 8 bits to allow the sum to expand without overflowing). This
allows intermediate filter values to grow and shrink as necessary without corrupting
data. The code segment being used is generic (i.e., can be used for any length filters);
so the MAC’s extra output bits allow arbitrary filters with unknown data to be run
with little fear of losing data.
To implement the FIR filter, the multiply/accumulate operation is repeated for all taps
of the filter on each data point. To do this (and be ready for the next data point), the
MAC instruction is written in the form of a loop. The ADSP-21xx’s zero-overhead
loop capability allows the MAC instruction to be repeated for a specified number of
counts without programming intervention. A counter is set to the number of taps
minus one, and the loop mechanism automatically decrements the counter for each
loop operation. Setting the loop counter to "taps–1" ensures that the data pointers end
up in the correct location after execution is finished and allows the final MAC
operation to include rounding. As the AD1847 is a 16-bit codec, the MAC with
rounding provides a statistically unbiased result rounded to the nearest 16-bit value.
This final result is written to the codec.
For optimal code execution, every instruction cycle should perform a meaningful
mathematical calculation. The ADSP-21xxs accomplish this with multi-function
instructions: the processor can perform several functions in the same instruction cycle.
For the FIR filter code, each multiply-accumulate (MAC) operation can be performed
in parallel with two data accesses, one from Data Memory, one from Program
Memory. This capability means that on every loop iteration a MAC operation is being
performed. At the same time, the next data value and coefficient are being fetched,
and the counter is automatically decremented. All without wasting time maintaining
loops.
As the filter code is executed for each input data sample, the output of the MAC loop
will be written to the output data buffer, tx_buf. Although this program only deals
with single-channel input data, the result will be written out to both channels by
writing to memory buffer addresses tx_buf+1 and tx_buf+2.
The final source code listing is shown on page 15. The filter algorithm itself is listed
under "Interrupt service routines". The rest of the code is used for codec and DSP
initialization and interrupt service routine definition. Those topics will be explored in
future installments of this series.
There are many levels of detail associated with each of these topics that this brief
article could not do justice to. Further information is available in the references below.
The series will continue to build on this application with additional topics. The next
article will examine data input/output (I/O) issues in greater detail through the
processor interrupt structure, and discuss additional features of the simple filter
algorithm.
* The initialization routines have been put into the init1847.dsp file.
This
* file contains the interrupt vector table, the main ‘dummy’ loop, and
the
* interrupt service routines for the pushbutton and the serial port 0
receive.
* The pushbutton (IRQE) causes the LED on the EZ-Kit board to toggle
* The transmit interrupts are used to configure the codec, then they
are
* audio.
******************************************************
****/
.module/RAM/ABS=0 EzHello;
#include
/*****************************************************
*****
******************************************************
****/
ar = pass ar;
if eq rti;
jump next_cmd;
/*****************************************************
*******
******************************************************
******/
start:
l0 = %rx_buf;
i1 = ^tx_buf;
l1 = %tx_buf;
l3 = %init_cmds;
m0 = 0;
m1 = 1;
call init_sport0;
call init_system_regs;
call init_1847;
i2 = ^filt_data;
l2 = %filt_data;
i5 = ^filt_coefs;
m5 = 1;
l5 = %filt_coefs;
imask=b#0000110000; /* enable rx0 interrupt */
/* |||||||||+ | timer
||||||+--- | BDMA
|||||+---- | IRQE
||+-------| IRQL0
|+--------| IRQL1
+---------| IRQ2
*/
/*----------------------------------------------------------------------
----------------------------------------------------------------------*/
talkthru: idle;
jump talkthru;
/*****************************************************
*********
******************************************************
********/
/*----------------------------------------------------------------------
- FIR Filter
----------------------------------------------------------------------*/
input_samples:
cntr = taps - 1;
dm(tx_buf+1) = mr1;
rti;
.endmod;
**
DSP 101 Parte 3:
Algoritmos de
Implementos em uma
Plataforma de Hardware
de Noam Levine e David Skolnick baixar PDF
Nesta estrutura, cada "z –1 "box representa um único incremento do histórico dos
dados de entrada na notação de transformada z. Cada uma das amostras
sucessivamente atrasadas é multiplicada pelo valor do coeficiente apropriado, h (m) ,
e os resultados, somados, geram um único valor representando a saída correspondente
à enésima amostra de entrada. O número de elementos de atraso, ou toques de filtro e
seus valores de coeficiente, determinam o desempenho do filtro.
A estrutura do filtro sugere os elementos físicos necessários para implementar esse
algoritmo por computação usando um DSP. Para o próprio cálculo, cada amostra de
saída requer um número de operações de acumulação múltipla igual ao comprimento
do filtro.
Essa arquitetura de DSP favorece programas que usam buffer circular (discutido
brevemente na Parte 2 e mais adiante nesta parte). A implicação é que os ponteiros de
endereço precisam ser inicializados apenas no início do programa, e o mecanismo de
buffer circular garante que o ponteiro não deixe os limites de seu buffer de memória
designado - um recurso usado extensivamente no código de filtro FIR para ambos os
inputs linha de atraso e coeficientes. Uma vez que os elementos do programa tenham
sido determinados, o próximo passo é desenvolver o código fonte do DSP para
implementar o algoritmo.
Geração de código fonte: Passando da teoria para a prática, essa etapa - em que
uma ideia algorítmica é transformada em código que é executada no DSP -
geralmente é a etapa mais demorada do processo.Existem várias maneiras de gerar o
código-fonte. Alguns programadores preferem codificar seus algoritmos em uma
linguagem de alto nível, como C; outros preferem usar a linguagem assembly nativa
do processador. Implementações em C podem ser mais rápidas para o programador
desenvolver, mas o código DSP compilado não tem eficiência, não aproveitando ao
máximo a arquitetura de um processador.
Figur
a 3. Layout da placa EZ-Kit Lite.
Para completar a fase de descrição da arquitetura, é necessário conhecer a memória e
os periféricos mapeados na memória que o DSP tem disponível. Os programadores
armazenam essas informações em um arquivo de descrição do sistema para que o
software das ferramentas de desenvolvimento possa produzir o código apropriado
para o sistema de destino. O EZ-Kit Lite não precisa de memória externa ao DSP,
pois a memória disponível no chip é composta pelas 16.384 localizações da SRAM
Program Memory (PM) do ADSP-2181 e pelas 16.352 localizações da SRAM Data
Memory (DM). (32 locais de DM usados para registros de controle do sistema
não estão disponíveis para código de trabalho). Mais informações sobre o ADSP-2181,
a arquitetura do EZ-Kit Lite e tópicos relacionados, podem ser encontradas nos textos
mencionados no final deste artigo.
Os dados de entrada serão amostrados usando o codec AD1847 on-board, que possui
taxa de amostragem programável, ganho de entrada, atenuação de saída, seleção de
entrada e mixagem de entrada. Sua natureza programável torna o sistema flexível,
mas também adiciona uma tarefa de programação para inicializá-lo para o sistema
DSP.
Acessando dados
Para este exemplo, uma série de palavras de controle para o codec - a ser definido no
início do programa na primeira seção da listagem - irá inicializá-lo para uma taxa de
amostragem de 8 kHz, com valores moderados de ganho em cada entrada
canais. Como o AD1847 é programável, os usuários geralmente reutilizam os
segmentos de código de interface e inicialização, alterando apenas os valores de
registro específicos para diferentes aplicativos. Este exemplo adicionará o segmento
de filtro específico a um segmento de código existente encontrado no software EZ-Kit
Lite.
Este código de interface declara duas áreas na memória a serem usadas para E / S de
dados: "tx_buf", para dados a serem transmitidos para fora do codec e "rx_buf", onde
os dados recebidos são recebidos.Cada uma dessas áreas de memória, ou buffers,
contém três elementos, uma palavra de controle ou status, dados do canal esquerdo e
dados do canal direito. Para cada período de amostragem, o DSP receberá do codec
uma palavra de status, dados do canal esquerdo e dados do canal direito. Em cada
período de amostra, o DSP deve fornecer ao codec um transmite palavra de
controle, dados do canal esquerdo e dados do canal direito. Nesta aplicação, as
informações de controle enviadas para o codec não serão alteradas, então a primeira
palavra no buffer de dados de transmissão será deixada como está. Vamos supor que a
fonte é um microfone monofônico, usando o canal direito (sem preocupação com
dados de entrada do canal esquerdo).
Os dados que chegam do codec precisam ser alimentados no algoritmo de filtro por
meio da linha de atraso de entrada, usando a capacidade de buffer circular do
ADSP-2181. O comprimento da linha de atraso de entrada é determinado pelo número
de coeficientes usados para o filtro. Como o buffer de dados é circular, o valor de
dados mais antigo no buffer será sempre que o ponteiro estiver apontando após o
último acesso ao filtro (Figura 4). Da mesma forma, os coeficientes, sempre acessados
na mesma ordem todas as vezes através do filtro, são colocados em um buffer
circular na Memória de Programa.
Código de Algoritmo
Para operar nos dados recebidos, a seção de código publicada na última parcela pode
ser usada com poucas modificações. Para implementar esse filtro, precisamos usar a
unidade computacional de multiplicação / acumulação (MAC) e os geradores de
endereço de dados.
Para uma execução ideal do código, todo ciclo de instrução deve executar um cálculo
matemático significativo. Os ADSP-21xxs fazem isso com instruções multifuncionais:
o processador pode executar várias funções no mesmo ciclo de instrução. Para o
código de filtro FIR, cada operação de acumulação de multiplicação (MAC) pode ser
executada em paralelo com dois acessos de dados, um da Memória de Dados, um da
Memória de Programa. Esse recurso significa que, em cada iteração de loop, uma
operação MAC está sendo executada. Ao mesmo tempo, o próximo valor e
coeficiente de dados estão sendo buscados e o contador é decrementado
automaticamente. Tudo sem perder tempo mantendo loops.
Como o código do filtro é executado para cada amostra de dados de entrada, a saída
do loop MAC será gravada no buffer de dados de saída, tx_buf. Embora este
programa lide apenas com dados de entrada de canal único, o resultado será gravado
em ambos os canais gravando nos endereços do buffer de memória tx_buf + 1 e
tx_buf + 2.
O EZ-Kit Lite
O software de monitor baseado em Windows fornecido com o EZ-Kit Lite permite
carregar um arquivo executável no ADSP-2181 na placa EZ-Kit Lite. Isso é feito
através do menu suspenso "Carregando", selecionando "Baixar programa do usuário e
Ir" (Figura 5). Isso fará o download do programa de filtro para o ADSP-2181 e
iniciará a execução do programa.
Figura 5. Menu de download do EZ-Kit Lite.
Revise e visualize
O objetivo deste artigo era delinear os passos de uma descrição do algoritmo para um
programa executável do DSP que poderia ser executado em uma plataforma de
desenvolvimento de hardware. Os problemas introduzidos incluem fluxo de
desenvolvimento de software, descrição de arquitetura, geração de código fonte, E / S
de dados e a plataforma de hardware EZ-Kit Lite.
Há muitos níveis de detalhes associados a cada um desses tópicos que este breve
artigo não poderia fazer justiça. Mais informações estão disponíveis nas referências
abaixo. A série continuará a desenvolver este aplicativo com tópicos adicionais. O
próximo artigo examinará os problemas de entrada / saída de dados (I / O) com mais
detalhes através da estrutura de interrupção do processador e discutirá recursos
adicionais do algoritmo de filtro simples.
*
* hello81.dsp - arquivo de modelo para a placa 2181 ez-kit lite
* áudio.
* o arquivo: system.h
**************************************************
******** /
#incluir
**************************************************
******** /
ar = passar ar;
se eq rti;
salte next_cmd;
/ *************************************************
***********
**************************************************
********** /
começar:
l0 =% rx_buf;
i1 = ^ tx_buf;
l1 =% tx_buf;
l3 =% init_cmds;
m0 = 0;
m1 = 1;
chame init_sport0;
chame init_system_regs;
chame init_1847;
i2 = ^ filt_data;
l2 =% filt_data;
i5 = ^ filt_coefs;
m5 = 1;
l5 =% filt_coefs;
/ * ||||||||| + | cronômetro
|| + ------- | IRQL0
| + -------- | IRQL1
+ --------- | IRQ2
*/
/ * ------------------------------------------------ ----------------------
-------------------------------------------------- -------------------- * /
conversação: ocioso;
pular talkthru;
/ *************************************************
*************
**************************************************
************ /
/ * ------------------------------------------------ ----------------------
- Filtro FIR
-------------------------------------------------- -------------------- * /
input_samples:
cntr = taps - 1;
dm (tx_buf + 1) = mr1;
rti;
.endmod;
DSP 101 Part 4:
Programming
Considerations for
Real-time I/O
by David Skolnick and Noam Levine Download PDF
Part 1 (vol. 31-1): DSP architecture and DSP advantages over traditionally
analog circuitry
Part 2 (vol. 31-2): digital filtering concepts and DSP filtering algorithms
Part 3 (vol. 31-3): implementation of a finite-impulse- response (FIR) filter
algorithm and an overview of a demonstration hardware platform, the
ADSP-2181 EZ-Kit Lite.
Now, we look more closely at DSP programming concerns that are unique to
real-time systems. This article focuses on how to develop algorithms for DSP systems
with a variety of I/O interfaces.
What does "real-time" mean? In an analog system, every task is performed in "real
time" with continuous signals and processing. In a digital signal-processing (DSP)
system, signals are represented with sets of samples, i.e., values at discrete points in
time. Thus the time for processing a given number of samples in a DSP system can
have an arbitrary interpretation in "real time", depending on the sampling rate. The
first article in this series introduces the concept of sampling and the Nyquist
criterion–that in real-time applications, the sampling frequency must be at least twice
the frequency of the highest frequency component of interest in the (analog) signal
(Nyquist rate). The time between samples is referred to as the sampling interval. To
consider a system as operating in "real time," all processing of a given set of data (one
or more samples, depending on the algorithm) must be completed before new data
arrives.
This definition of real time implies that, for a processor operating at a given clock rate,
the speed and quantity of the input data determines how much processing can be
applied to the data without falling behind the data stream. The idea of having a limited
amount of time with which to handle data may seem odd to analog designers because
this concept does not have a parallel in analog systems. In analog systems, signals are
processed continuously. The only penalty in a slow system is limited frequency
response. By comparison, digital systems process parts of the signal, enough for very
accurate approximations, but only within a limited block of time. Figure 1 shows a
comparison. Real-time DSP can be limited by the amount of data or type of
processing that can be completed within the algorithm's time budget. For example, a
given DSP processor handling data values sampled at, say, 48-kHz (audio signals),
has less time to process those data values, including execution of all necessary tasks,
than one sampling 8-kHz voice-band data.
In the filter example described earlier in this series, the input sampling rate is 8 kHz.
For the DSP in the example to keep up with real-time data, all processing has to be
done within a time budget of 1/(8 kHz), or 125 µs. On a 33-MHz digital
signal-processor (30ens per cycle), the time budget provides 125 µs/30 ns, or 4166
instruction cycles, to complete processing and any other required tasks.
Since there is a finite amount of time that can be budgeted to perform any given
algorithm, managing time is a central part of DSP system software design. Time
management strategy determines how the processor gets notified about events,
influences data handling, and shapes processor communications.
Figure 1. Comparison of
analog and digital signal processing. a. Analog: A response value
corresponds to each data value at all instants of time. b. Digital: For
each sample, the data must be transferred in and processed, an event marks
the end of processing (control), and extra time may be necessary for other
tasks within the cycle after the designated process occurs.
Event Notification: Interrupts: One can program a DSP to process data using one of
several strategies for handling the "event," the arrival of data. A status bit or flag pin
could be read periodically to determine whether new data is available. But–"polling"
wastes processor cycles. The data may arrive just after the last poll, but it can't make
its presence known until the next poll. This makes it difficult to develop real-time
systems.
The second strategy is for the data to interrupt the processor on arrival. Using
interrupts to notify the processor is efficient, though not as easy to program; clock
cycles can be wasted during the wait for an interrupt. Nevertheless, event-driven
interrupt programming being well-suited to processing real-world signals promptly,
most DSPs are designed to deal efficiently with them. In fact, they are designed to
respond very quickly to interrupts. The ADSP-2181's response time to an interrupt is
about three processor cycles; i.e., within 75 ns the DSP has stopped doing what it was
doing and is handling the interrupt event (vector).
In many DSP-based systems, the interrupt rates, based on the input data sampling rate,
are often totally unrelated to the DSP's clock rate. In the FIR example seen earlier in
this series, the processor is interrupted at 125-µs intervals to receive new data.
Fast context switching–switch from working on one task and its data (a
context) to another context without the time loss and complication
associated with writing programs to save register contents and chip status
information.
Nested-interrupt handling–handle multiple interrupts of different priorities
"simultaneously." The DSP handles one interrupt at a time, but an interrupt
of higher priority can take precedence over the handling of a lower-priority
interrupt.
Continue to accept data/record status–while the DSP services an interrupt,
events keep on occurring in the real world and data keeps on arriving. To
keep up with the "real-world," the DSP must record these events and accept
the data–then process them when it has finished servicing the interrupt.
On Analog Devices DSPs, fast context switching is accomplished using two sets of
data registers. Only one set is active at a time, containing all the data in process during
that context. When servicing an interrupt, the computer can switch from the active to
the alternate set without having to temporarily save the data in memory. This
facilitates rapid switching between tasks.
To handle multiple interrupts, Analog Devices DSPs record their state for each one.
Processor state information is kept on a set of status "stacks" located in the DSP's
Program Sequencer. A "stack" consists of a set of hardware registers. Current status
information is "pushed" onto the stack when an event occurs. This stack mechanism
also allows interrupts to be nested; one with higher priority can interrupt one with
lower priority.
Two hardware features, interrupt latch and automated I/O, let Analog Devices DSPs
stay abreast of the "real world" while processing an interrupt. The latch keeps the
DSP from missing important events while servicing an interrupt. The other feature,
comprising various forms of automated I/O (including serial ports, DMA,
autobuffering, etc.) lets external devices pump data into the DSP's memory without
requiring intervention from the DSP. So no data is missed while the DSP is "busy."
Each interrupt vector has four instruction locations. Typically, these instructions will
cause the processor to jump to another area of memory in order to process the data, as
is shown in the Reset (at 0x0000), SPORT0 Rx (0x0014), and IRQE (0x0018)
interrupt vectors. If there are just a few steps–such as reading a value, checking status,
or loading memory–that can be done within the four available instruction locations,
they are programmed directly, as shown in the SPORT0 Tx vector (0x0010-13). Any
unused interrupt vectors call for return from interrupt (rti), with three nop (no
operation) instructions.
The nop instructions serve as place holders–instruction space used to ensure that the
correct interrupt action lines up with the hardware-specified interrupt vector. The rti
instruction at the beginning of each unused vector location is both placeholder and
safety valve. If an unused interrupt is mistakenly unmasked or inadvertently triggered,
"rti" causes a return to normal execution.
Data I/O
In DSP systems, interrupts are typically generated by the arrival of data or the
requirement to provide new output data. Interrupts may occur with each sample, or
they may occur after a frame of data has been collected. The differences greatly
influence how the DSP algorithm deals with data.
To transmit data, the serial port can generate a Transmit interrupt, indicating that new
data can be written to the SPORT Tx register. The DSP can then begin code execution
at the SPORT Tx interrupt vector and typically transfer a value from a data register to
the SPORT Tx register. If data input and output are controlled by the same sampling
clock, only one interrupt is necessary. For example, if a program segment is initiated
by Receive interrupt timing, new data would be read during the interrupt routine; then
either the previously computed result, which is being held in a register, would be
transmitted, or a new result would be computed and immediately transmitted–as the
final step of the interrupt routine.
All of these mechanisms help a DSP to approach the ability to emulate what an analog
system does naturally–continuously process data in real time–but with digital
precision and flexibility. In addition, in an efficiently programmed digital system,
spare processor cycles left between processing data sets can be used to handle other
tasks.
Programming Considerations
In a "real-time" system, processing speed is of the essence. By using SPORT
autobuffering, no time is lost to data I/O. Instead, the data management goal is to
make sure that the selected address points to the new data.
In the FIR filter example (Analog Dialogue 31-3, page 15), a SPORT Receive
interrupt request is generated when the input autobuffer is full, meaning that the DSP
has received three data words: status, left channel data, and right channel data. Since
this simplified application uses single-channel data, only the data value that resides at
location rx_buf+1 is used by the algorithm.
Filter Algorithm Expansion In other applications, the data handling can be more
involved. For example, if the FIR filter of the example were expanded to a
two-channel implementation, the core DSP algorithm code would not have to change.
The code relating to data handling, however, would have to be modified to account
for a second data stream and a second set of coefficients.
In the filter code, two new buffers in memory would be required to handle both the
additional data stream and the additional set of coefficients. The core filter loop may
be isolated as a separate "callable" function. This technique lets the same code be
used, regardless of the input data values. Benefits of this programming style include
readable code, re-usable algorithms, and reduced code size. If a modular approach is
not taken, the filter loop would have to be repeated, using additional DSP memory
space.
The SPORT Receive interrupt routine would then consist of the setting of pointer and
calling the filter. The revised filter routine is shown in the following listing:
It's important to note that the only modifications to the core filter loop were the
addition of a label, "Filter:" at the beginning of the routine, and the addition of an
"rts" (return from subroutine) instruction at the end. These additions change filter
code from a stand-alone routine into a subroutine that can be called from other
routines. No longer a single-purpose routine, it has become a re-usable, callable
subroutine.
With the core filter set up as a callable subroutine, the two-channel data handling
requirements can now be addressed. To simplify some of the programming issues, this
example assumes that both the left and right channels use the same filter coefficients.
In the third installment of this series, the entire filter application assembly code was
displayed. At the top of the code listing, all of the required memory buffers were
declared. To expand the filter application to handle two channels of data, the required
new variables and buffers need to be declared. For the incoming data, the buffer
declaration,
Because both channels are to have the same filter coefficients applied to them, the
data buffers are of equal length.
The filter loop subroutine expects certain data and coefficient values to be accessed
using particular address registers. Specifically, address register I2 must point to the
oldest data sample, and I5 must point to the proper coefficient value prior to the filter
routine being called.
Because the filters for both the left and right channel will be sharing the same
memory pointers, there has to be a mechanism for differentiating the two data streams.
For the data pointer, I2, two new variables need to be defined, "filter1_ptr" and
"filter2_ptr."
These locations in memory are going to be used to store address values appropriate
for each data stream. The circular buffering capability of the ADSP-2181 is used to
ensure that the data pointer is always in the correct place in the buffer whenever the
filter is executed. Because the subroutine is now dealing with two buffers, the pointer
locations need to be saved when processing for each channel is completed.
To set up the pointers, two variables in data memory need to be declared as follows:
These variable then need to be initialized with the starting address of each of the data
buffers;
The DSP assembler software recognizes the symbol "^" to mean "address of." The
DSP linker software fills in the appropriate address value. In this way, the pointer
variables in the executable program are initialized with the starting addresses of the
appropriate memory buffers.
The following listing shows how the FIR Filter interrupt routine uses these new
memory elements. The original Filter subroutine from the 3rd installment has been
modified to provide two separate channels of filtering. Instead of launching directly
into the filter calculation, the routine must first load the appropriate data pointer. The
filter routine is then called, and the resulting output is placed in the correct location
for transmission.
/*--------------------FIR Filter--------------------*/
input_samples:
ena sec_reg; /* use shadow register bank */
Because the core filter algorithm no longer handles data I/O, this subroutine can be
expanded to more channels of filtering by merely adding more pointer variables and
declaring more buffer space (as long as sufficient memory exists!) Similarly, different
coefficients can be used for the two filters by setting up variables that contain
coefficient-buffer pointer information. In either case, the filter algorithm does not
need to be altered. By using this style of modular programming, the user can build up
a library of callable DSP functions. Differences for particular systems can thus be
reduced to data-handling issues rather than the development of new algorithms. While
this programming style does not necessarily allow the algorithm to perform its task
more quickly, the system designer has more flexibility in establishing how data flows
through the system.
The primary data flows into and out of a digital signal processor can be both parallel
and serial. Parallel transfers are typically at least as wide as the native data word of
the processor's architecture (16 bits for an ADSP-2100 Family processor, 32 bits for
the SHARC®). Parallel transfers occur via the external memory bus or external host
interface bus of the processor. Serial data transfers require considerably fewer
interconnections; they are frequently used to communicate with data converters.
As noted earlier, the processor has various means for handling this data. SPORT
Interrupts are generated automatically by the serial port hardware for either Receive
or Transmit data and for either a single word or a block of words (Figure 2). Serial
interfacing between digital signal processor and I/O device
Parallel data transfer is always faster than serial transfers. The DSP can perform an
external access every processor cycle, but this requires really fast parallel peripherals
that can keep up with it, such as fast SRAM chips. Parallel data transfers with other
entities usually occur at less than one per processor cycle.
Interrupt handling is different for the serial and parallel interfaces. Since the external
data bus of the DSP processor is a general-purpose entity handling all sorts of data, it
does not have dedicated signal lines for interrupt generation and control; however,
other DSP resources are available. On the ADSP-2181, several external hardware
interrupt lines, such as the one for I/O memory select, are available for triggering by
an external device, such as an A/D converter or codec. Such an interface is shown in
Figure 3, involving a parallel device and the ADSP-2181 DSP. Parallel I/O interfacing
for a DSP
Figure 3. Parallel I/O interfacing
for a DSP.
When responding to the interrupt for parallel data, the processor reads the appropriate
source and typically places that data value in memory, by executing instructions
similar to those shown here:
**
Figura 1. Comparação do
processamento de sinais analógico e digital. uma. Analógico: Um valor de
resposta corresponde a cada valor de dados em todos os instantes de
tempo. b. Digital: Para cada amostra, os dados devem ser transferidos e
processados, um evento marca o final do processamento (controle) e o tempo
extra pode ser necessário para outras tarefas dentro do ciclo após a
ocorrência do processo designado.
Para lidar com várias interrupções, os DSPs de dispositivos analógicos registram seu
estado para cada um. As informações de estado do processador são mantidas em um
conjunto de "pilhas" de status localizadas no seqüenciador de programas do
DSP. Uma "pilha" consiste em um conjunto de registradores de hardware. As
informações de status atuais são "empurradas" para a pilha quando ocorre um
evento. Este mecanismo de pilha também permite que as interrupções
sejam aninhado ; um com maior prioridade pode interromper um com menor
prioridade.
Quando uma solicitação de interrupção é gerada, por uma fonte externa ou por um
recurso interno, o processador DSP armazena automaticamente seu estado atual de
operação e se prepara para executar a rotina de interrupção. Rotinas de interrupção
são despachadas de uma tabela de vetores de interrupção. Uma tabela de vetores de
interrupção é uma área na Memória de Programa com endereços de instrução
atribuídos a funções específicas de interrupção de DSP. Por exemplo, na tabela abaixo,
uma interrupção de Transmissão (Tx) na porta serial 1 (SPORT1) de um processador
ADSP-2181 fará com que a próxima instrução seja executada na memória de
programa (PM) 0x0020, seguida pelo conteúdo da próximos três locais, através de
0x0023 (o interromper a rotina ). Como os 12 itens na tabela indicam, um
ADSP-2181 pode manipular interrupções de 11 locais (hardware externo, portas
DMA e portas seriais) e a redefinição do processador. A tabela lista as instruções
programadas atribuídas a cada fonte de vetor de interrupção nos locais de memória
0x0000 a 0x002F para um programa de filtro FIR.
As instruções nop servem como espaços reservados para instruções - usado para
garantir que a ação de interrupção correta esteja alinhada com o vetor de interrupção
especificado pelo hardware. A instrução rti no início de cada localização vetorial não
usada é tanto o espaço reservado quanto a válvula de segurança. Se uma interrupção
não utilizada for desmascarada por engano ou ativada inadvertidamente, "rti" causará
um retorno à execução normal.
E / S de dados
Nos sistemas DSP, as interrupções são normalmente geradas pela chegada de dados
ou pelo requisito de fornecer novos dados de saída. Interrupções podem ocorrer com
cada amostra, ou podem ocorrer depois que um quadro de dados foi coletado. As
diferenças influenciam muito como o algoritmo DSP lida com os dados.
Para algoritmos que operam em uma base de amostra por amostra, o software DSP
pode ser necessário para lidar com cada valor de dados de entrada e saída. Cada porta
serial DSP incorpora dois registradores de E / S de dados, receber registrar (Rx) e
um transmite registrar (Tx). Quando uma palavra serial é recebida, a porta
normalmente gera uma interrupção de recebimento. O processador pára o que está
fazendo, começa a executar o código no local do vetor de interrupção, lê o valor de
entrada do registrador Rx em um registrador de dados do processador e opera nesse
valor de dados ou retorna a sua tarefa em segundo plano. Na tabela acima, o
computador salta para um segmento de programa, "input_samples", executa quaisquer
instruções programadas nesse segmento e retorna da interrupção, diretamente ou
através de um retorno ao vetor de interrupção.
Para transmitir dados, a porta serial pode gerar uma interrupção de Transmissão,
indicando que novos dados podem ser gravados no registro SPORT Tx. O DSP pode
então começar a execução de código no vetor de interrupção SPORT Tx e tipicamente
transferir um valor de um registrador de dados para o registro SPORT Tx. Se a
entrada e saída de dados são controladas pelo mesmo relógio de amostragem, apenas
uma interrupção é necessária. Por exemplo, se um segmento de programa for iniciado
por Sincronização de interrupção de recebimento, novos dados serão lidos durante a
rotina de interrupção; então, o resultado previamente computado, que está sendo
mantido em um registrador, seria transmitido, ou um novo resultado seria computado
e imediatamente transmitido - como a etapa final da rotina de interrupção.
Considerações de programação
Em um sistema "em tempo real", a velocidade de processamento é essencial. Usando
o autobuffering SPORT, nenhum tempo é perdido para os dados de E / S. Em vez
disso, a meta de gerenciamento de dados é garantir que o endereço selecionado aponte
para os novos dados.
No exemplo do filtro FIR ( Diálogo Analógico 31-3, página 15), uma solicitação de
interrupção Receive SPORT é gerada quando o autobuffer de entrada está cheio,
significando que o DSP recebeu três palavras de dados: status, dados do canal
esquerdo e dados do canal direito. Como esse aplicativo simplificado usa dados de
canal único, somente o valor de dados que reside no local rx_buf + 1 é usado pelo
algoritmo.
No código de filtro, dois novos buffers na memória seriam necessários para manipular
o fluxo de dados adicional e o conjunto adicional de coeficientes. O loop de filtro do
núcleo pode ser isolado como uma função "chamável" separada. Essa técnica permite
que o mesmo código seja usado, independentemente dos valores dos dados de
entrada. Os benefícios deste estilo de programação incluem código legível, algoritmos
reutilizáveis e tamanho de código reduzido. Se uma abordagem modular não for
tomada, o loop de filtro teria que ser repetido, usando espaço de memória DSP
adicional.
Com o filtro de núcleo configurado como uma sub-rotina que pode ser chamada, os
requisitos de manipulação de dados de dois canais agora podem ser endereçados. Para
simplificar alguns dos problemas de programação, este exemplo pressupõe que os
canais esquerdo e direito usam os mesmos coeficientes de filtro.
Na terceira edição desta série, todo o código do assembly do aplicativo de filtro foi
exibido. No topo da listagem de código, todos os buffers de memória necessários
foram declarados. Para expandir o aplicativo de filtro para manipular dois canais de
dados, as novas variáveis e os buffers necessários precisam ser declarados. Para
os dados recebidos, a declaração do buffer,
Como ambos os canais devem ter os mesmos coeficientes de filtro aplicados a eles, os
buffers de dados são de igual tamanho.
A sub-rotina de loop de filtro espera que certos valores de dados e coeficientes sejam
acessados usando registros de endereços específicos. Especificamente, o
registrador de endereço I2 deve apontar para a amostra de dados mais antiga, e I5
deve apontar para o valor de coeficiente adequado antes da rotina de filtro ser
chamada.
O software montador DSP reconhece o símbolo "^" para significar "endereço de". O
software vinculador DSP preenche o valor de endereço apropriado. Desta forma, as
variáveis de ponteiro no programa executável são inicializadas com os endereços
iniciais dos buffers de memória apropriados.
A listagem a seguir mostra como a rotina de interrupção do filtro FIR usa esses novos
elementos de memória. A sub-rotina original do filtro da 3ª parcela foi modificada
para fornecer dois canais separados de filtragem. Em vez de iniciar diretamente no
cálculo do filtro, a rotina deve primeiro carregar o ponteiro de dados apropriado. A
rotina de filtro é então chamada e a saída resultante é colocada no local correto para
transmissão.
Como o algoritmo de filtro principal não lida mais com E / S de dados, esta sub-rotina
pode ser expandida para mais canais de filtragem simplesmente adicionando mais
variáveis de ponteiro e declarando mais espaço de buffer (contanto que exista
memória suficiente!) Da mesma forma, diferentes coeficientes podem ser usados para
os dois filtros configurando variáveis que contêm informações de ponteiro de
buffer de coeficiente. Em ambos os casos, o algoritmo de filtro não precisa ser
alterado. Usando esse estilo de programação modular, o usuário pode criar uma
biblioteca de funções DSP que podem ser chamadas. Diferenças para sistemas
específicos podem, portanto, ser reduzidas a problemas de manipulação de dados, em
vez do desenvolvimento de novos algoritmos. Embora esse estilo de programação não
permita necessariamente que o algoritmo execute sua tarefa mais rapidamente, o
projetista do sistema tem mais flexibilidade em estabelecer como os dados fluem pelo
sistema.
Os dados primários que entram e saem de um processador de sinal digital podem ser
paralelos e seriais. Transferências paralelas são tipicamente, pelo menos, tão ampla
como a palavra de dados nativa da arquitectura do processador (16 bits para um
processador da família ADSP-2100, 32 bits para o SHARC ®). Transferências
paralelas ocorrem via barramento de memória externa ou barramento de interface de
host externo do processador. Transferências de dados de série requerem
consideravelmente menos interconexões; eles são freqüentemente usados para se
comunicar com conversores de dados.
Como observado anteriormente, o processador tem vários meios para manipular esses
dados. SPORT As interrupções são geradas automaticamente pelo hardware da porta
serial para receber ou transmitir dados e para uma única palavra ou um bloco de
palavras (Figura 2). Interface serial entre o processador de sinal digital e o dispositivo
de E / S
Figura 2. Interface serial entre o
processador de sinal digital e o dispositivo de E / S.
Interface Paralela : Mesmo com um clock de bit serial rodando tão rápido quanto o
processador DSP, uma interface serial troca velocidade de transferência de dados pela
simplicidade da fiação, transferindo uma palavra de dados a uma fração da velocidade
do processador DSP. Para o desempenho do sistema que requer taxas de dados mais
altas, uma interface paralela pode ser usada. Ao fazer a interface em paralelo, o DSP
exerce seus dados externos e endereça os barramentos para ler ou gravar dados em um
dispositivo periférico. No ADSP-2181, os barramentos podem interagir com até 16
bits de dados.
Figura 3. Interface de E / S
paralela para um DSP.
REVISÃO E VISUALIZAÇÃO
O objetivo deste artigo foi detalhar as preocupações de programação que os
desenvolvedores de DSP enfrentam ao manipular E / S e outros eventos em sistemas
em tempo real. Os problemas introduzidos incluem dados em tempo real (amostras e
quadros), interrupções e manuseio de interrupções, E / S automatizada e rotinas de
generalização para criar sub-rotinas que podem ser chamadas. Este breve artigo não
poderia fazer justiça aos muitos níveis de detalhes associados a cada um desses
tópicos. Mais informações estão disponíveis nas referências abaixo. Os tópicos
futuros desta série continuarão sendo desenvolvidos neste aplicativo. O próximo
artigo adicionará mais recursos ao nosso programa de exemplo crescente e descreverá
as técnicas de validação de software (ou seja, depuração).