Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

2-complement multiplication

255 views
Skip to first unread message

Klas Brink

unread,
Oct 13, 1999, 3:00:00 AM10/13/99
to
Hi!

I want to use the *-operator in Verilog to perform
multiplication between two numbers represented
as two's complement (that's signed in C).

Example:
wire [31:0] result;
reg [15:0] a,b;
assign result = a * b;

However,
Verilog only supports numbers as being unsigned and
performs the multiplication as being multiplication between
two unsigned numbers.
I guess I could use sign-extension on the numbers, but
that would mean extra bits (which can be discarded at the output)
and more importantly a bigger multiplier.

Example:
wire [35:0] result;
reg [15:0] a,b;
assign result = {2{a[15]},a}*{2{b[15]},b};

Does anyone know of a better/other way to get the correct
result, without having to go down into bit-level implementation?

The beauty of staying at this level of coding is that the code
becomes very clear and easy to read and you can leave a lot
of freedom to the synthesis tool regarding the implementation.
Using Synopsys you can take advantage of their Designware,
which has different implementations of multipliers available,
such as Wallace, Baugh-Wooley ...

Kind regards,
Klas Brink
Consultant in ASIC/FPGA design at Frontec Microelectronics


Paul Dormitzer

unread,
Oct 14, 1999, 3:00:00 AM10/14/99
to
What I chose to do was to directly instantiate the designware
multiplier (DW02_MULT) from the synopsys library. This still
allows DC to choose the implementation of the multiplier while
getting around the lack of a native signed multiply in verilog.

By the way... sign-extending the numbers in verilog won't help
you here. What you have to do if you want to use the verilog
* operator is to make both a and b positive, multiply the absolute
values, and then if a and b originally had opposite signs, make
the result negative. Needless to say, this will NOT synthesize well!

wire [31:0] absresult,result;
reg [15:0] a,b;
wire [15:0] absa, absb;
wire neg;

assign absa = a[15] ? (~a + 1) : a;
assign absb = b[15] ? (~b + 1) : b;
assign neg = a[15] ^ b[15];
assign absresult = absa * absb;
assign result = neg ? (~absresult + 1) : absresult;

--
----------------

Paul Dormitzer
Broadband Access Systems

pdorm...@cannedspam.com

(to send me mail, replace cannedspam in the mail address with basystems)

Matt Holcomb

unread,
Oct 18, 1999, 3:00:00 AM10/18/99
to
In <38061978...@cannedspam.com>, Paul Dormitzer (pdorm...@cannedspam.com) wrote:
: What I chose to do was to directly instantiate the designware

: multiplier (DW02_MULT) from the synopsys library. This still
: allows DC to choose the implementation of the multiplier while
: getting around the lack of a native signed multiply in verilog.

: By the way... sign-extending the numbers in verilog won't help
: you here. What you have to do if you want to use the verilog
: * operator is to make both a and b positive, multiply the absolute
: values, and then if a and b originally had opposite signs, make
: the result negative. Needless to say, this will NOT synthesize well!

: wire [31:0] absresult,result;
: reg [15:0] a,b;
: wire [15:0] absa, absb;
: wire neg;

: assign absa = a[15] ? (~a + 1) : a;
: assign absb = b[15] ? (~b + 1) : b;
: assign neg = a[15] ^ b[15];
: assign absresult = absa * absb;
: assign result = neg ? (~absresult + 1) : absresult;


If you wish, this works as well. It's faster (but not quite as fast as
the DW02_MULT approach). It performs the multiply across all 16-bits,
and then corrects the result using a single subtraction. It's certainly
not very readable.


wire [15:0] raw_q, mod_a, mod_b, mod_q;

assign {raw_q[15:0],q[15:0]} = a[15:0] * b[15:0];

assign mod_a[15:0] = a[15:0] & {16{b[15]}};
assign mod_b[15:0] = b[15:0] & {16{a[15]}};
assign mod_q[15:0] = mod_a[15:0] + mod_b[15:0];

assign q[31:16] = raw_q[15:0] - mod_q[15:0];


Matt Holcomb

Klas Brink

unread,
Oct 20, 1999, 3:00:00 AM10/20/99
to
> ...
> ...

> Example:
> wire [35:0] result;

> reg [15:0] a,b;
> assign result = {2{a[15]},a}*{2{b[15]},b};
>
> Does anyone know of a better/other way to get the correct
> result, without having to go down into bit-level implementation?
>
> The beauty of staying at this level of coding is that the code
> becomes very clear and easy to read and you can leave a lot
> of freedom to the synthesis tool regarding the implementation.
> Using Synopsys you can take advantage of their Designware,
> which has different implementations of multipliers available,
> such as Wallace, Baugh-Wooley ...
>
> Kind regards,
> Klas Brink
> Consultant in ASIC/FPGA design at Frontec Microelectronics

I just saw that my example code wasn't correct.
Below is a correct example-module of a 2-comp mult. 16x16 with 32 bits
out.

I've also tried synthesising this using SNPS and allowing it to
choose from its DW. The results came out pretty well:

2-comp mult. in: 16x16, out: 32: area=2.8k, wc_timing=4.55 (LSI g11p)
'ordinary' mult. in: 16x16, ut: 32: area=2.5k, wc_timing=4.03 (also LSI
g11p)

Example:
module mult_16x16 (result, a, b);
output [31:0] result;
input [15:0] a, b;

wire [31:0] result;

assign result = {{16{a[15]}},a} * {{16{b[15]}},b};

endmodule

0 new messages