Discarding part of RHS

S

scott moore

Guest
Hi,

I am trying to perform a compare operation, and discard all of the right
side of an expression except for the carry. What I found works is:

input [7:0] opra;
input [7:0] oprb;

reg cout;
reg [8:0] dummy;

....

dummy = opra-oprb;
cout = dummy[8];

Because I just want the carry from the add, not the whole result.
The problem is that, of course, I get warnings about "dummy" not
being used.

I tried various things like:

cout = { opra-oprb }[8];

But that does not compile under Xilinx ISE.

Thank you.

Scott Moore
 
scott moore <nospam@nowhere.com> writes:

I tried various things like:

cout = { opra-oprb }[8];
Yes, a concat expression (or any other expression) is not something
that can be bit or part-selected. Only named signals (e.g. wires and
regs) can have selects applied to them, because only named signals
have declarations telling your Verilog tool which order you number the
bits. x[7] means a different bit for reg [7:0] x; and for reg [0:7]
x; Which bit do you mean when you have a concat (or other) expression?

Have you tried something like:

cout = { 9'H0 + opra - oprb ) >> 8;

The 9'h0 widens the result so you get the carry and the shift throws
away all the bits but the carry. It looks like a lot of work, but a
good synthesizer should see that it can be optimized down to what you
really want.

Hope this helps,
-Chris

*****************************************************************************
Chris Clark Internet : compres@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
 
Chris F Clark wrote:
scott moore <nospam@nowhere.com> writes:

I tried various things like:

cout = { opra-oprb }[8];

Yes, a concat expression (or any other expression) is not something
that can be bit or part-selected. Only named signals (e.g. wires and
regs) can have selects applied to them, because only named signals
have declarations telling your Verilog tool which order you number the
bits. x[7] means a different bit for reg [7:0] x; and for reg [0:7]
x; Which bit do you mean when you have a concat (or other) expression?

Have you tried something like:

cout = { 9'H0 + opra - oprb ) >> 8;

The 9'h0 widens the result so you get the carry and the shift throws
away all the bits but the carry. It looks like a lot of work, but a
good synthesizer should see that it can be optimized down to what you
really want.

Hope this helps,
-Chris
Of course, do it algorithmically, I should have thought of that.

Thank you.

Scott Moore
 
On Sun, 10 Sep 2006 11:36:34 -0700, scott moore <nospam@nowhere.com>
wrote:

Hi,

I am trying to perform a compare operation, and discard all of the right
side of an expression except for the carry. What I found works is:

input [7:0] opra;
input [7:0] oprb;

reg cout;
reg [8:0] dummy;

...

dummy = opra-oprb;
cout = dummy[8];

Because I just want the carry from the add, not the whole result.
The problem is that, of course, I get warnings about "dummy" not
being used.

I tried various things like:

cout = { opra-oprb }[8];

But that does not compile under Xilinx ISE.

Thank you.

Scott Moore
Another way you can write it is
wire c;
wire [7:0] dummy;

assign {c, dummy} = opra - oprb;

I don't think you can get c without naming the lower 8 bits of the
subtractor output.
 
mk wrote:
On Sun, 10 Sep 2006 11:36:34 -0700, scott moore <nospam@nowhere.com
wrote:

Hi,

I am trying to perform a compare operation, and discard all of the right
side of an expression except for the carry. What I found works is:

input [7:0] opra;
input [7:0] oprb;

reg cout;
reg [8:0] dummy;

...

dummy = opra-oprb;
cout = dummy[8];

Because I just want the carry from the add, not the whole result.
The problem is that, of course, I get warnings about "dummy" not
being used.

I tried various things like:

cout = { opra-oprb }[8];

But that does not compile under Xilinx ISE.

Thank you.

Scott Moore

Another way you can write it is
wire c;
wire [7:0] dummy;

assign {c, dummy} = opra - oprb;

I don't think you can get c without naming the lower 8 bits of the
subtractor output.
That's actually one thing I tried. It works, but it generates warnings
(dummy not used). I hope to avoid having a collection of warnings from
the code.

Scott Moore
 
scott moore wrote:
[snip]
That's actually one thing I tried. It works, but it generates warnings
(dummy not used). I hope to avoid having a collection of warnings from
the code.

Scott Moore
In my experience, you'll never be able to remove all warnings
from a Xilinx ISE build, so it's best to just learn to live with them.
Newer versions of ISE allow you to selectively mask warnings.
Another obvious thing is to use names like "unused_bits" for
stuff you expect the optimizer to remove. Then you can
ignore the warnings without having to re-visit the code to see
whether you needed that signal or not.

just my 2 cents.
Gabor
 
scott moore wrote:
mk wrote:
On Sun, 10 Sep 2006 11:36:34 -0700, scott moore <nospam@nowhere.com
wrote:

Hi,

I am trying to perform a compare operation, and discard all of the right
side of an expression except for the carry. What I found works is:

input [7:0] opra;
input [7:0] oprb;

reg cout;
reg [8:0] dummy;

...

dummy = opra-oprb;
cout = dummy[8];

Because I just want the carry from the add, not the whole result.
The problem is that, of course, I get warnings about "dummy" not
being used.

I tried various things like:

cout = { opra-oprb }[8];

But that does not compile under Xilinx ISE.

Thank you.

Scott Moore

Another way you can write it is wire c;
wire [7:0] dummy;

assign {c, dummy} = opra - oprb;

I don't think you can get c without naming the lower 8 bits of the
subtractor output.

That's actually one thing I tried. It works, but it generates warnings
(dummy not used). I hope to avoid having a collection of warnings from
the code.

Scott Moore

This may be a silly question but what's wrong with

cout = opra < oprb;

Cheers,

Andy
 
On Mon, 11 Sep 2006 15:24:56 GMT, Andy Ray
<andrewray@blueyonder.co.uk> wrote:

This may be a silly question but what's wrong with

cout = opra < oprb;
Probably nothing but we already know that '<' is implemented with a
subtractor and checking the carry. Why make the synthesizer do extra
work ? :)
 
gabor wrote:
scott moore wrote:
[snip]
That's actually one thing I tried. It works, but it generates warnings
(dummy not used). I hope to avoid having a collection of warnings from
the code.

Scott Moore

In my experience, you'll never be able to remove all warnings
from a Xilinx ISE build, so it's best to just learn to live with them.
Newer versions of ISE allow you to selectively mask warnings.
Another obvious thing is to use names like "unused_bits" for
stuff you expect the optimizer to remove. Then you can
ignore the warnings without having to re-visit the code to see
whether you needed that signal or not.

just my 2 cents.
Gabor
Yea, I understand that. I am a programmer by profession, and I come
from the school that believes that warnings, all warnings should be
eliminated. Having constant warnings in your compiles, while common
even in C compiles, creates errors by teaching programmers to
essentially disregard warnings, or at least devalues them. C, or
perhaps I should say even C, has done a lot towards being able to
support a "warningless" style of programming, but of course hardware
languages and programmers clearly have not arrived at this paradigm
as yet.

However, this particular circumstance does have a way to avoid the
warning, so I'm going to prefer that. In fact, I am warning free
so far (knock on wood).

Scott Moore
 
mk wrote:
On Mon, 11 Sep 2006 15:24:56 GMT, Andy Ray
andrewray@blueyonder.co.uk> wrote:

This may be a silly question but what's wrong with

cout = opra < oprb;


Probably nothing but we already know that '<' is implemented with a
subtractor and checking the carry. Why make the synthesizer do extra
work ? :)
Ditto that. What mk is saying is that there are two ways to solve the
problem, one (which I used) is to essentially form an accumulator that
is one bit larger than the desired result (which is not a bad
description of carry in general), the other is to form the carry
algorithmically. Unfortunately, the latter is placing a lot of faith
on the synthesizer to figure out what is really needed.

Scott Moore

PS. Thanks again for the good help here, and not laughing at a C
programmer trying to do a little Verilog!
 
scott moore wrote:
mk wrote:
On Mon, 11 Sep 2006 15:24:56 GMT, Andy Ray
andrewray@blueyonder.co.uk> wrote:

This may be a silly question but what's wrong with

cout = opra < oprb;


Probably nothing but we already know that '<' is implemented with a
subtractor and checking the carry. Why make the synthesizer do extra
work ? :)

Ditto that. What mk is saying is that there are two ways to solve the
problem, one (which I used) is to essentially form an accumulator that
is one bit larger than the desired result (which is not a bad
description of carry in general), the other is to form the carry
algorithmically. Unfortunately, the latter is placing a lot of faith
on the synthesizer to figure out what is really needed.

Trust your synthesizer! I checked and mine was able to produce a
smaller circuit when you use "<". Moreover it'll likely do the same
thing consistently no matter what architecture I pick.

These tools have been around for a long time and though they have their
faults, implementing optimised arithmetic circuits is not one of them.
For them to do the best job you should describe your code at the highest
level of abstraction possible rather than force it into a particular
implementation technique.
 
On Wed, 13 Sep 2006 22:00:09 -0700, scott moore <nospam@nowhere.com>
wrote:

mk wrote:
On Mon, 11 Sep 2006 15:24:56 GMT, Andy Ray
andrewray@blueyonder.co.uk> wrote:

This may be a silly question but what's wrong with

cout = opra < oprb;


Probably nothing but we already know that '<' is implemented with a
subtractor and checking the carry. Why make the synthesizer do extra
work ? :)

Ditto that. What mk is saying is that there are two ways to solve the
problem, one (which I used) is to essentially form an accumulator that
is one bit larger than the desired result (which is not a bad
description of carry in general), the other is to form the carry
algorithmically. Unfortunately, the latter is placing a lot of faith
on the synthesizer to figure out what is really needed.
I'm afraid you've misunderstood my point. I thought the smiley would
help potential readers but apparently it wasn't enough.
There is a reason we use HDLs these days as opposed to schematic and
that's because we can write higher level RTL and let the synthesizer
do the investigation of potential implementations and pick the best
one (at least locally). My point was that one has to write the
comparison code and let the synthesizer do the work. If one can not
depend on a synthesizer to get that expression right each and every
time, one needs to get another synthesizer. Let the tool do the
nitty-gritty work and concentrate on things which are actually
difficult.
 

Welcome to EDABoard.com

Sponsor

Back
Top