This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Hardware Multiplier clarifications

Hi,

I have not understood the hardware multiplier and hence need the following clarification:

I have a 24 bit 2's complement and a 16 bit signed number and want to multiply the two using the 32X32 hardware multiplier so I do the following:

eg

A = 0xFFABCD

B= 0x1234

I load MACS32L with 0xABCD

MACS32H with 0x00FF

OP2 with 0x1234

NOP()
NOP()
NOP()
NOP()
NOP()

result =  RES3<<48 | RES2<<32 | RES1<<16 | RES0

Would this give me the correct answer?

Would MACS32H loaded as 0x00FF be treated as a positive number? If I am doing something wrong here please let me know the correct procedure?

Regards

Viney Chaddha

  • No, it will not!

    If you don’t need to accumulate, use it as follows;

    int main(void) {
    
    	unsigned int		IntState, MPYState;
    	signed long			A;
    	signed int			B;
    	signed long long	result, *presult;
    
    	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    
    	IntState = __get_interrupt_state();
    	__disable_interrupt();
    	MPYState = MPY32CTL0;
    	MPY32CTL0 &= ~MPYFRAC;
    
    	A = 0x0FFABCD;
    	B = 0x01234;
    
    	// 32 x 16 = 48-bit
    	MPYS32L = A;			// 16-bit Operand assumed
    	MPYS32H = A>>16;		// Override to 32-bit Operand
    	OP2 = B;				// Start multiplication
    	//__delay_cycles(7);	// Delay for the result to be ready
    	result  = RES0;
    	result |= (unsigned long)RES1 << 16;
    	result |= (unsigned long long)RES2 << 32;
    	// RES3 must also be added in case of a negative result
    	result |= (unsigned long long)RES3 << 48;
    	// Or
    	result = ((unsigned long long)RES3 << 48) | ((unsigned long long)RES2 << 32) | ((unsigned long)RES1 << 16) | RES0;
    	// Or
    	presult = (signed long long*)&RES0;
    	result = *presult;
    
    	
    	MPY32CTL0 = MPYState;
    	__set_interrupt_state(IntState);
    
    	return 0;
    }
    

  • Thanks Leo for your inputs,
    I need to accumulate the results as I am using a 161 order hamming window function. In order to avoid fractional multiplication I scaled the filter coefficients by 2^16 so that I would right shift the result by 16 bits. effectively ignoring the RESLO altogether Also due to memory issues I have decided to use 16X16 multiplier but with accumulate. My question is
    In that case I should also be reading RES2 to get the complete results since the accumulate would not limit it to 32 bit? because If I only pickup the RESHI value I get a random values which are not as per my expectation. I only see either 0XFF or 0X00. Any help here would be hihly appreciated.
    Regards
    Viney Chaddha
  • If you need to accumulate, you will know, you need either to clear RESn or use for the first MPY and thereafter MAC.

    Correct, it accumulates up to 64-bits, so you must read RES1 & RES2, or using the pointer “(signed long*)&RES1”.

    I never use RESHI or RESLO so don’t know why you get wrong result, but RESHI and RES1 are the same. Maybe you need to add a NOP. Or the result of your calculation is max 16-bit and you read in RESHI only if positive (0h) or negative (FFFFh), or is it 0x00FF what you see, that would be strange.
  • Leo,
    Following is the code, it is returning 0x00000000

    Let me know where I am going wrong.
    Regards
    Viney Chaddha


    void ECG_FilterProcess(short * WorkingBuff, short * CoeffBuf, long * FilterOut) { short i; long Val_Hi; RES0 = 0; RES1 = 0; RES2 = 0; RES3 = 0; MPYS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand for ( i = 0; i < FILTERORDER/10; i++) { MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand MACS = *WorkingBuff--; // Load first operand -unsigned mult OP2 = *CoeffBuf++; // Load second operand } _delay_cycles(7); Val_Hi = (RES2<<16) | RES1; *FilterOut = Val_Hi ; // Lower 16 bits ignored as the scaling factor for filter coefficient is 2^16

**Attention** This is a public forum