Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20707 Discussions

signed/unsigned multipliers

Altera_Forum
Honored Contributor II
5,653 Views

I can't seem to find a way to instantiate a multiplier that will dynamically select between signed and unsigned multiplication. This is on a Cyclone II, but applies to other parts as well. 

 

Reading the Cyclone II documentation it is clear that signa, signb inputs does what I want, but none of the multipliers created with the Wizzard exports that as an input signal. Trying to infer it with the code below doesn't work (bug in Quartus II?); it complains that no logic depends on input_sign. However looking at the RTL with Tools/Netlist Viewers/RTL Viewer clearly shows it being used, however the technology map viewer shows input_sign as disconnected and signa and signb hardwired to ground. 

 

This looks like a bug to me, but I could be doing something wrong. 

 

module mult(input clock, input input_sign, input input_a, input input_b, output reg output_c); reg a, b; reg sign; always @(posedge clock) begin sign <= input_sign; a <= input_a; b <= input_b; if (sign) output_c <= $signed(a) * $signed(b); else output_c <= $unsigned(a) * $unsigned(b); end endmodule
0 Kudos
42 Replies
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

You have chosen an example that works. 

 

Now consider this: I want to multiply these two 3 bit values through same unsigned multiplier: 

 

111 * 011 = ? 

 

if viewed as unsigned, implies 7 * 3 = 21 [10101 correct] 

 

if viewed as signed, implies -1 * 3 and should give -3 

[ but 10101 is wrong now, means -11] 

 

I don't know what you mean by sign extension here but let us try one bit extension: 

 

0 111 * 0 011 

7 * 3 = 21 0000 0000 10101 correct 

 

1 111 * 0 011 

15* 3 = 45 i.e. 101101 i.e./= -3 

 

Correct ?, Wooooooo 

--- Quote End ---  

 

 

 

Let me correct myself, I got a bit flakey with numbers 

 

let us assume the numbers are signed: 

111 * 011 (as signed I expect the result to be -1 * 3 = -3 

 

now sign extend according to tricky's trick: 

111 111 * 000 011 

 

the verdict: 

 

= 10111101 

 

and means -128 + 61 and /= the expected -3 

 

So what is going on Now?
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

 

let us assume the numbers are signed: 

111 * 011 (as signed I expect the result to be -1 * 3 = -3 

 

now sign extend according to tricky's trick: 

111 111 * 000 011 

 

the verdict: 

 

= 10111101 

 

and means -128 + 61 and /= the expected -3 

 

So what is going on Now? 

--- Quote End ---  

 

 

you're forgetting that the result is only 6 bits because you had 2 x3 bit inputs. you ignore bits 6 and 7 (only bits 0-5 are valid)
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

Thanks Tricky. 

 

It does really work. 

 

So in principle you are doing what altera never tell us....as usual. 

 

To use unsigned, given a signed input: 

 

1) double extend input width using sign extension 

2) truncate output to double inputwidth  

 

Very useful discussion.
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

or, in VHDL, do the following: 

 

signal ina, inb : unsigned(8 downto 0); signal mult : unsigned(17 downto 0); begin process(clk) begin if rising_edge(clk) then mult <= ina * inb; end if; end process;  

 

its far far easier :) (try not to mix signed/unsigned logic)
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

 

So in principle you are doing what altera never tell us....as usual. 

 

--- Quote End ---  

 

 

I dont know. I did it all as part of my electronics degree....
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

So your method involves sign extending both 9 bit inputs to 18 bit? This means, you need four multiplier blocks instead of one, not a useful suggestion, to my opinion. I would rather use signed/unsigned inputs with altmult_add, as previously said. 

 

P.S.: O.K., it's only two instead of one block, still a waste of resources.
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

So your method involves sign extending both 9 bit inputs to 18 bit? This means, you need four multiplier blocks instead of one, not a useful suggestion, to my opinion. I would rather use signed/unsigned inputs with altmult_add, as previously said. 

--- Quote End ---  

 

 

This discussion has been more about theory than practicalilty. In practice, if you need to use all the bits of the multiplier input, then you have to use the signa/b inputs on the megafunction. 

 

But, if you have spare bits on the input, you can simply sign extend and not need any more multipliers, and avoid using the wizard.
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

But, if you have spare bits on the input, you can simply sign extend. 

--- Quote End ---  

Yes, but it's 100% spare bits. I didn't want to suggest the solution for this reason. 

 

And you don't necessarily need the MegaWizard, but you have to understand various additional parameters of cycloneii_mac_mult then.
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

Why are you comparing bit patterns of 11 and -5? The point is that 5 and -5 have different low order bits, so you cannot just sign extend. Assuming two's complement arithmetic, complement the binary value and add 1 to get the negative. for ones complement just complement (invert the bits). Look at an adder/subtractor. To subtract it does a complement and add. Sign extension is for right shifting to preserve the sign and magnitude of an operand because leading zeroes of a negative number appear as 1 bits. This is not true in the bits that represent the magnitude.

0 Kudos
Altera_Forum
Honored Contributor II
866 Views

Hi SimKnutt, 

 

We are not talking about conversion from natural binary to 2's (let alone 1's complement which is never used in practice).  

 

It is assumed that we are given ready-made input as either unsigned or signed and we want to pass it through one (unsigned) multiplier. The method 

described above does work as far as our limited testing indicates but may clash with compiler bitwidth issues regarding the dedicated multipliers.
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

Thanks Tricky. 

 

It does really work. 

 

So in principle you are doing what altera never tell us....as usual. 

 

To use unsigned, given a signed input: 

 

1) double extend input width using sign extension 

2) truncate output to double inputwidth  

 

Very useful discussion. 

--- Quote End ---  

 

 

IMO, Tricky side stepped the real issue. I already pointed out that the lower bits would be identical, so obviously widening the input would "solve" the problem, at a quadratic cost!! 

 

You (Kaz) provided an actual useful workaround. I'm still working with support to get the original bug fixed. 

 

Tommy
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

Just to clarify, have you tried FvM's solution using altmult_add? It's certainly there in Quartus 6.1 and although the symbol in the MegaWizard looks a bit mad at first, if you do as FvM says and set the number of multipliers to 1 it simplifies up a treat. 

 

As a matter of interest, what was the workaround you chose in the end?
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

Just to clarify, have you tried FvM's solution using altmult_add? It's certainly there in Quartus 6.1 and although the symbol in the MegaWizard looks a bit mad at first, if you do as FvM says and set the number of multipliers to 1 it simplifies up a treat. 

 

As a matter of interest, what was the workaround you chose in the end? 

--- Quote End ---  

 

 

Yes, the workaround looks great in Q II 8.1 (I failed to notice the "variable" option for input signedness when I first looked at it). 

 

I'm still trying to get the synthesis bug fixed, but that might take a while. I'll follow up if there's news. 

 

Thanks all, 

Tommy
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

There is no way to represent a negative number in an unsigned integer. Therefore an unsigned multiplier will generate a product as if all 1 bits represent positive 2 to the nth. 

Whether the multiplier does it or not based on the most significant bit and an indicator of whether the operand is signed the operands need to be converted to positive format, multiplied then converted to negative at the end if the signs are different. 

let's multiply 2 times -7. (0007 -> fff8 + 1 = fff9) ... 0002 * fff9 = 0001fff2 unsigned. 

but 2 * 7 = e ... * -1 = 0000fff2 signed. So if you only look at the low 16 bits, they match. 

If you extend the sign to 32 bits, then you are multiplying 32 bit integers, which by the way produce 64 bit products. 

If your computer is to be a general purpose I think you have the choice to implement the traditional algorithm ... make both operands positive, multiply, and if signs were different, then complement the product, otherwise invent new multipliers which handle both ops negative or either op negative, then select one of the four based upon the sign bits. 

I have uploaded a zipped C# project file that has a simple loop to sequence through operand values which may be of interest. (if you have a C# IDE to run it on.
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

I'm still trying to get the synthesis bug fixed 

--- Quote End ---  

I don't understand exactly, what's the synthesis bug in your opinion. Hardware multipliers can be used with variable number representation, but not through lpm_mult. Cause HDL inference uses apparently lpm_mult, it doesn't provide a variable representation.
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

Not commenting at all on the logistics of signed/unsigned multiplications, but more on synthesizable code, if you write: 

 

signal sum : signed(3 downto 0); 

 

IF(inc = '1') THEN 

sum <= sum + 1; 

ELSIF(dec = '1') THEN 

sum <= sum - 1; 

ELSE 

sum <= sum; 

END IF; 

 

It will usually generate two adders and then mux the output together. However, if you were to write: 

 

signal inc : integer range -1 to 1; 

signal sum : signed(3 downto 0); 

 

inc <= -1 when dec = '1' else  

1 when inc = '1' else 

0; 

sum <= sum + inc; 

 

Then it will usually generate a single adder with a mux at one of the input ports.  

 

Obviously the summation should be in a clocked process, but i am being lazy. 

 

Just a thought.  

 

Kevin
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

the operand is signed the operands need to be converted to positive format, multiplied then converted to negative at the end if the signs are different. 

--- Quote End ---  

 

 

I agree and the math proof is very straightforward: 

 

n * -m = - (n * m) 

 

-n *m =-(n*m) 

 

so just convert -m to +m, multiply as unsigned, convert result back to negative. The overheads include two setd of inverter + two adders  

 

but: 

 

-m * -n = +(n*m) 

 

convert sign inputs but not output.  

 

I wonder if Trick have a math proof for his trick 

 

By the way here is a 2's complement puzzle: 

 

+ => - invert bits then add 1 

 

- => + invert bits then add 1 ?? how come this correct 

 

(or take 1 then invert bits, makes more sense) 

 

 

 

--- Quote Start ---  

 

 

Not commenting at all on the logistics of signed/unsigned multiplications, but more on synthesizable code, if you write: 

 

signal sum : signed(3 downto 0); 

 

IF(inc = '1') THEN 

sum <= sum + 1; 

ELSIF(dec = '1') THEN 

sum <= sum - 1; 

ELSE 

sum <= sum; 

END IF; 

 

It will usually generate two adders and then mux the output together. However, if you were to write: 

 

signal inc : integer range -1 to 1; 

signal sum : signed(3 downto 0); 

 

inc <= -1 when dec = '1' else  

1 when inc = '1' else 

0; 

sum <= sum + inc; 

 

Then it will usually generate a single adder with a mux at one of the input ports.  

 

Obviously the summation should be in a clocked process, but i am being lazy. 

 

Just a thought.  

 

Kevin 

 

--- Quote End ---  

 

 

True, compiler instantiates one operation unit per operand occurence. It doesn't want to know your intentions. I refrred to this ages ago regarding multipliers, to avoid this use one (*) assignment only then switch your inputs/outputs as you wish.
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

 

--- Quote Start ---  

- => + invert bits then add 1 ?? how come this correct 

 

--- Quote End ---  

 

 

Still true. The only problem may be in the most negative number, which does not have the equivalent positive number in two's complement. That is, for 8-bits we can represent from -128 to +127. So, -128 does not have its positive equivalent.
0 Kudos
Altera_Forum
Honored Contributor II
866 Views

It is always true if we allow for correct width. The issue of 8 bit width representing numbers from 0~127 and -1 to -128 is separate. 

 

The puzzle still stands: 

- => + should reverse + => - naturally 

hence for - => + subtract 1 then invert (by definition) 

but how come the same rule apply to both conversions as well. 

i.e. [invert add 1] in either case.
0 Kudos
Altera_Forum
Honored Contributor II
865 Views

Consider the case for 8 bit values 

 

Bitwise inversion of x is equivalent to 255-x 

 

Negation of x is equivalent to 0-x 

 

Ignoring any carry/borrow, 0-x is equivalent 256-x = (255-x)+1 = 255-(x-1) 

 

i.e Negation (2's complement) can be done as "invert then increment" or "decrement then invert"
0 Kudos
Altera_Forum
Honored Contributor II
865 Views

It makes sense. The way I make sense is this: 

 

[invert => +1] naturally reverses by [-1 => invert] 

 

but if we also reverse the order of operations then : 

[-1 => invert] becomes equivalent to [invert => +1]
0 Kudos
Reply