SPRUIY2 November 2024 F29H850TU , F29H859TU-Q1
The C29x CPU does not support a native addressing mode for circular addressing like on the C28x CPU. However, the functional parallelism present in the C29x CPU architecture makes sure that there is no performance impact for the lack of native circular addressing mode.
Circular addressing is performed by instructions that modify the addressing registers in a circular fashion. These are 16-bit instructions that require 1 cycle to execute. The instructions supported are:
INC.CIRC Ay,Ax:
Increment Ay until the limit (Ax) is reached, then reset the value to 0.
if (Ay >= Ax) Ay = 0
else Ay = Ay + 1
; where Ay = A0 to A3
; and Ax = A0 to A14
DEC.CIRC Ay,Ax:
Decrement Ay until the limit (0) is reached, then reset the value to Ax.
if (Ay <= 0) Ay = Ax
else Ay = Ay – 1
; where Ay = A0 to A3
; and Ax = A0 to A14
This type of addressing mode is typically used for implementing finite impulse response (FIR), least mean squares (LMS), or convolution filters.
A typical FIR filter algorithm in C:
sum = 0;
circ_index = save_circ_index;
for(i=0; i < N_taps; i++)
{
sum += Data[circ_index] * Coef[i];
circ_index++;
if( circ_index >= N_taps)
circ_index = 0;
}
save_circ_index = circ_index;
The main kernel for the filter can be coded as follows (example for a 7-tap FIR):
LD.32 A0,@save_circ_index ; A0 = circ_index
MV A6,#N-1 ; A6 = filter taps, N = 7
MV A4,#Data ; A4 -> Data Array
MV A5,#Coef ; A5 -> Coef Array
LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M4,M0,M1
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M5,M0,M1
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M6,M0,M1
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M7,M0,M1
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M4,M0,M1
||SADDF M6,M6,M4
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M5,M0,M1
||SADDF M7,M7,M5
||LD.32 M0,*(A4+A0) ; Read Data From Current Index
||LD.32 M1,*A5++ ; Read Coef, Increment Coef Pointer
||INC.CIRC A0,A6 ; if(A0 >= A6) A0 = 0 else A0 = A0 + 1
SMPYF M4,M0,M1
||SADDF M6,M6,M4
ADDF M7,M7,M5
ADDF M6,M6,M4
ST.32 @save_circ_index,A0 ; Save current circ index position
ADDF M7,M7,M6 ; final sum = M7