Discussion:
[myhdl-list] Slicing an unsigned intbv to a signed one
Günter Dannoritzer
2008-06-10 12:22:48 UTC
Permalink
Hi,

I try to figure out whether there is a simple way to slice bits from an
unsigned intbv and assign them to a signed intbv and have the msb of the
slice specify the sign of the signed intbv? In addition to that it
should be convertible with toVerilog/VHDL.

For example, what I try to do is split up a 8 bit wide data word that is
considered unsigned, that means min=0 and max=256, into two 4 bit wide
data words with those being considered signed, meaning min=-8 max = 8.

In Verilog that can be done using the $signed() system task. Is there a
simple way to do that with myhdl?

The problem I am running into is when the msb in the slice is set, that
when assigning it to a signed intbv it is complaining that the value
exceeds the max allowed value as the slice is considered a positive value.

Thanks for the help.

Cheers,

Guenter
Christopher L. Felton
2008-06-10 19:08:55 UTC
Permalink
I don't believe there is an easy way to do this in MyHDL. I have
found is some cases that the Verilog way of doing thing isn't always a
good way in MyHDL. In most cases Verilog doesn't really care about
the number that the bits represent. And MyHDL is different (at least
the case when using min and max) that it is concerned with the actual
value that the bits represent.

As you mentioned you are looking for a way to start out representing
the value as a generic collection of bits and then convert slices of
the bit-vector to a signed version. Also as you pointed out, in
Verilog if you need the language to know that the value is signed (for
signed extension or other built in operators that the sign would
affect) you can essentially cast with the $signed or by using signed
types.

I have not mixed the "signed" (limits set) and the generic bit-vector
in the past with MyHDL, I usually have to approach the design from a
MyHDL perspective.

Below is a version that worked, I don't think it is an approach that
you would want to take though. It synthesizes correctly, if you look
at the Verilog netlist for the Xilinx XST synthesis tool. You are
relying a lot on the synthesis tool to determine that you are doing
nothing but relocating bits.
Günter Dannoritzer
2008-06-11 13:55:43 UTC
Permalink
I don't believe there is an easy way to do this in MyHDL. I have found
is some cases that the Verilog way of doing thing isn't always a good
way in MyHDL. In most cases Verilog doesn't really care about the
number that the bits represent. And MyHDL is different (at least the
case when using min and max) that it is concerned with the actual value
that the bits represent.
Well, I think the core difference is that Verilog really only considers
the bits as specified whereas in MyHDL there is still an integer data
type underneath.

For example in Verilog you can do:

reg signed [3:0] a;
reg [3:0] b;

a[3] = 1'b1;
b[3] = 1'b1;
$display("a: %d b: %d", a,b);

a: -8 b: 8

Setting the msb is setting the sign bit. However, that does not work in
MyHDL, as the underlying data type is an integer and despite the value
restriction the sign bit is not bit 3 in this case. MyHDL will just
complain that the value exceeds the range.

...
I have not mixed the "signed" (limits set) and the generic bit-vector in
the past with MyHDL, I usually have to approach the design from a MyHDL
perspective.
I think that is my deficit. I am getting comfortable with Verilog and
having a hard time getting rid of the low level bit twiddling and
looking at a problem form a higher level with MyHDL.
Below is a version that worked, I don't think it is an approach that you
would want to take though. It synthesizes correctly, if you look at the
Verilog netlist for the Xilinx XST synthesis tool. You are relying a
lot on the synthesis tool to determine that you are doing nothing but
relocating bits.
Thanks for the code. Interesting to see how it could work.

Cheers,

Guenter
Jan Decaluwe
2008-06-11 15:32:43 UTC
Permalink
Post by Günter Dannoritzer
reg signed [3:0] a;
reg [3:0] b;
a[3] = 1'b1;
b[3] = 1'b1;
$display("a: %d b: %d", a,b);
a: -8 b: 8
Setting the msb is setting the sign bit. However, that does not work in
MyHDL, as the underlying data type is an integer and despite the value
restriction the sign bit is not bit 3 in this case. MyHDL will just
complain that the value exceeds the range.
Right, as in Python there is an "indefinite" number sign
bits to the left.

An implication is that there is no way to make an intbv
negative by setting some indivitual bit. To make it
negative, you'd first have to do:

a[:] = -1

and after that, it would stay negative whatever you
do to indivual bits.

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Günter Dannoritzer
2008-06-11 19:10:08 UTC
Permalink
...
Post by Jan Decaluwe
Post by Günter Dannoritzer
Setting the msb is setting the sign bit. However, that does not work in
MyHDL, as the underlying data type is an integer and despite the value
restriction the sign bit is not bit 3 in this case. MyHDL will just
complain that the value exceeds the range.
Right, as in Python there is an "indefinite" number sign
bits to the left.
An implication is that there is no way to make an intbv
negative by setting some indivitual bit. To make it
a[:] = -1
and after that, it would stay negative whatever you
do to indivual bits.
How about if there would be an additional concat() function. Like
concatSigned().

The difference to the concat() function would be that it considers the
concatenated bits as signed and if the msb of the concatenation is set,
it has the effect that value is considered negative?
Post by Jan Decaluwe
Post by Günter Dannoritzer
a = concat('101')
print a, a.min, a.max
5 0 8
Post by Jan Decaluwe
Post by Günter Dannoritzer
a = concatSigned('101')
print a, a.min, a.max
-3 -4 4

This would allow to simplify the creation of signed intbv from bit
slices and could be convertible to Verilog for example. I am not that
familiar with VHDL to know how the signed values are handled there.

Guenter
Jan Decaluwe
2008-06-11 19:00:57 UTC
Permalink
Post by Günter Dannoritzer
I have not mixed the "signed" (limits set) and the generic bit-vector in
the past with MyHDL, I usually have to approach the design from a MyHDL
perspective.
I think that is my deficit. I am getting comfortable with Verilog and
having a hard time getting rid of the low level bit twiddling and
looking at a problem form a higher level with MyHDL.
For numeric operations, I suspect the "higher level" comes naturally.
But there may still be a legitimate need for bit-level manipulations,
and MyHDL should have an answer to that also.

The general problem is to convert some bit pattern to another,
relevant bit pattern. The case you describe is sign-extension,
but there may be others. We would have to find the truly
relevant ones, and find a way to implement them in MyHDL,
including conversion.

I'm now thinking aloud for the case you describe, sign-extension.

The ideal solution might be if we could somehow give an addional
parameter to slicing, e.g. asking for "signed" slicing instead
of the default, unsigned. But I don't see how.

Another interesting way might be to introduce methods to intbv's
at this point. We could do this like for python strings: the
methods don't modify the object in-place, but instead return a
new object with the modified value. (In MyHDL tradition,
those intbv methods would return integers.) The advantage
of this approach (as opposed to creating new functions)
is that adding new methods doesn't pollute the myhdl
namespace further.

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Günter Dannoritzer
2008-06-11 20:52:19 UTC
Permalink
Jan Decaluwe wrote:
...
Post by Jan Decaluwe
I'm now thinking aloud for the case you describe, sign-extension.
The ideal solution might be if we could somehow give an addional
parameter to slicing, e.g. asking for "signed" slicing instead
of the default, unsigned. But I don't see how.
We actually do that in the DeFixedInt class

http://www.dilloneng.com/documents/downloads/demodel/

Similar to intbv for an instance of that class a bit width can be
specified. The msb based on the specified width is considered the sign
bit. The decision is made whether the msb is included in the slice or
not. To quote from the doc string of the __getitem__ function:

When the slice includes the sign bit it is taken over to the return
value. If the sign bit is excluded the bits are taken as is with the
sign bit set to 0.

For example using the 4-bit number -6 = b1010, slicing bits 3:1 -->
b101 includes the sign bit, the result is -3.

Now using the 4-bit number -3 = b1101, slicing bits 2:1 --> b10,
however, the slice excludes the sign bit, hence the result is 2.


However, for the case of intbv I would not focus on where the bits come
from, but rather where they should go to. So if the destination is
supposed to be signed, then don't worry about where the bits come from.
With a slice there is a fixed number of bits and depending on how this
slice gets assigned to the destination should make the decision about
the sign of the destination. So let's say the destination is a signed
intbv with _nrbits set and the slice gets assigned to it. If that slice
matches _nrbits and in the slice the msb is set, that should turn the
value into a negative value.
Post by Jan Decaluwe
Another interesting way might be to introduce methods to intbv's
at this point. We could do this like for python strings: the
methods don't modify the object in-place, but instead return a
new object with the modified value. (In MyHDL tradition,
those intbv methods would return integers.) The advantage
of this approach (as opposed to creating new functions)
is that adding new methods doesn't pollute the myhdl
namespace further.
In a way the sign extension could be done through the __setitem__
function. Basically the _min, _max attributes decide about how the value
assigned is interpreted. If _min=0 the intbv instance is seen as
unsigned. If _min = -_max the intbv instance is seen as signed and the
assigned value is interpreted as signed with _nrbits specifying the msb
and if that bit in the assigned value is set, the value is considered
negative.

That would allow to assign bit slices that come actually from unsigned
values and convert to a signed value.

I am probably overlooking something, but maybe some ideas are a starting
point?

Guenter
Christopher L. Felton
2008-06-12 01:51:01 UTC
Permalink
We had a similar issue/discussion with the invert (not) function of
the intbv class. There seems to be a couple different specific use
cases of the intbv.

1. Generic bit container, this is then MyHDL intbv when there is no
min, no max value. This is similar to the Verilog bit vector (reg [],
wire []) or VHDLs std_logic_vector.

2. Unsigned number, this is the MyHDL min=0, similar to the Verilog
bit vector, and VHDL unsigned()

3. Signed numbers, this is the MyHDL min is < 0, similar to the
Verilog signed (reg or wire, Verilog 2001 and later) and VHDL signed()

The current implementation seems have all the properties that Jan
discussed, high level approach while maintaining the low-level
hardware access for cases 1 and 2. For case 3 there are the issues
that Günter pointed out, you can't modify the msb and maintain the
state of the signed number (or pass the bound checks).

Could we do something similar as the invert solution (not) and use the
knowledge of the type of number being represented and modify the bits
accordingly?

Below is the output example for a small change that I made to the bit
vector class
Post by Günter Dannoritzer
Post by Jan Decaluwe
from myhdl import *
x = intbv(0, min=-8, max=8)
x[3] = 1
x
intbv(-8L)
Post by Günter Dannoritzer
Post by Jan Decaluwe
x[3] = 0
x
intbv(0L)

To implement the above I simply modified __setitems__ and used the
_min and _nrbits values determine what type of number is being
represented. If the number is signed multiply the value by -1 if the
msb is being modified. There is probably a more elegant way to
implement this but I think this approach will meet the requirements
that have been discussed, which are

1. Support high level modeling
2. Support low level hardware modeling while maintaining high level
representation
3. Synthesizable

I believe the above approach (or one similar) will meet all the above
requirements and put the work in the intbv class (good or bad?).

My 2 cents.
Post by Günter Dannoritzer
...
Post by Jan Decaluwe
I'm now thinking aloud for the case you describe, sign-extension.
The ideal solution might be if we could somehow give an addional
parameter to slicing, e.g. asking for "signed" slicing instead
of the default, unsigned. But I don't see how.
We actually do that in the DeFixedInt class
http://www.dilloneng.com/documents/downloads/demodel/
Similar to intbv for an instance of that class a bit width can be
specified. The msb based on the specified width is considered the sign
bit. The decision is made whether the msb is included in the slice or
When the slice includes the sign bit it is taken over to the return
value. If the sign bit is excluded the bits are taken as is with the
sign bit set to 0.
For example using the 4-bit number -6 = b1010, slicing bits 3:1 -->
b101 includes the sign bit, the result is -3.
Now using the 4-bit number -3 = b1101, slicing bits 2:1 --> b10,
however, the slice excludes the sign bit, hence the result is 2.
However, for the case of intbv I would not focus on where the bits come
from, but rather where they should go to. So if the destination is
supposed to be signed, then don't worry about where the bits come from.
With a slice there is a fixed number of bits and depending on how this
slice gets assigned to the destination should make the decision about
the sign of the destination. So let's say the destination is a signed
intbv with _nrbits set and the slice gets assigned to it. If that slice
matches _nrbits and in the slice the msb is set, that should turn the
value into a negative value.
Post by Jan Decaluwe
Another interesting way might be to introduce methods to intbv's
at this point. We could do this like for python strings: the
methods don't modify the object in-place, but instead return a
new object with the modified value. (In MyHDL tradition,
those intbv methods would return integers.) The advantage
of this approach (as opposed to creating new functions)
is that adding new methods doesn't pollute the myhdl
namespace further.
In a way the sign extension could be done through the __setitem__
function. Basically the _min, _max attributes decide about how the value
assigned is interpreted. If _min=0 the intbv instance is seen as
unsigned. If _min = -_max the intbv instance is seen as signed and the
assigned value is interpreted as signed with _nrbits specifying the msb
and if that bit in the assigned value is set, the value is considered
negative.
That would allow to assign bit slices that come actually from unsigned
values and convert to a signed value.
I am probably overlooking something, but maybe some ideas are a starting
point?
Guenter
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
myhdl-list mailing list
https://lists.sourceforge.net/lists/listinfo/myhdl-list
Jan Decaluwe
2008-06-12 18:45:12 UTC
Permalink
Post by Christopher L. Felton
Below is the output example for a small change that I made to the bit
vector class
from myhdl import *
x = intbv(0, min=-8, max=8)
x[3] = 1
x
intbv(-8L)
x[3] = 0
x
intbv(0L)
To implement the above I simply modified __setitems__ and used the _min
and _nrbits values determine what type of number is being represented.
If the number is signed multiply the value by -1 if the msb is being
modified.
Could you show your patch (just a diff)? I don't see how this
would be correct for non-powers of 2.

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Christopher Felton
2008-06-12 20:39:04 UTC
Permalink
Yes I will send the patch when I get home. I believe you are correct
my quick implementation probably only covers the power of 2 cases.
For the non-power of 2 cases, I think it still works cause you have
to have a power of 2 (can't have fraction of a bit) the msb of the
least number of bits (which is the _nrbits) is still the sign bit?
Just thinking out loud.

Thanks

On Thu, 12 Jun 2008 20:45:12 +0200
Post by Jan Decaluwe
Post by Christopher L. Felton
Below is the output example for a small change that I made to the bit
vector class
from myhdl import *
x = intbv(0, min=-8, max=8)
x[3] = 1
x
intbv(-8L)
x[3] = 0
x
intbv(0L)
To implement the above I simply modified __setitems__ and used the _min
and _nrbits values determine what type of number is being
represented.
If the number is signed multiply the value by -1 if the msb is being
modified.
Could you show your patch (just a diff)? I don't see how this
would be correct for non-powers of 2.
Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Christopher L. Felton
2008-06-13 00:46:37 UTC
Permalink
Ok, below was my quick test to double check if it could be done. A
real implementation probably need more thought (if feasible at all).

With that said, I do think this approach will work. Even if you have
a non power of 2 limit you still need N bits to represent the max and
min values. If the msb of the "bit container" is modified it will
change the sign. If the designer is changing any of the other bits
she/he hopefully know what they are trying to achieve. I didn't think
much about the slice assignment but again I believe the same approach
could be taken just the implementation would need some thought.

Because this is handled in the intbv class the conversion to Verilog/
VHDL should still be valid.

<
<
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
< # CFELTON EDIT
< if self._min < 0:
< msb = (self._val >> self._nrbits-1) & 0x1
< if msb and not val:
< self._val = -1 * self._val
<
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<
167,181d157
<
<
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
< # CFELTON EDIT
< # If the new value msb is set and the number is not
< # negative make it negative
< # If the intbv is a signed number (min < 0) then
< # modify the value accordingly
< if self._min < 0:
< msb = (self._val >> self._nrbits-1) & 0x1
< print val, msb, self._val, self._min, self._max,
self._nrbits
< if msb and self._val > 0:
< self._val = -1 * self._val
<
<
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Post by Christopher Felton
Yes I will send the patch when I get home. I believe you are correct
my quick implementation probably only covers the power of 2 cases.
For the non-power of 2 cases, I think it still works cause you have
to have a power of 2 (can't have fraction of a bit) the msb of the
least number of bits (which is the _nrbits) is still the sign bit?
Just thinking out loud.
Thanks
On Thu, 12 Jun 2008 20:45:12 +0200
Post by Jan Decaluwe
Post by Christopher L. Felton
Below is the output example for a small change that I made to the bit
vector class
from myhdl import *
x = intbv(0, min=-8, max=8)
x[3] = 1
x
intbv(-8L)
x[3] = 0
x
intbv(0L)
To implement the above I simply modified __setitems__ and used the _min
and _nrbits values determine what type of number is being
represented.
If the number is signed multiply the value by -1 if the msb is being
modified.
Could you show your patch (just a diff)? I don't see how this
would be correct for non-powers of 2.
Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Jan Decaluwe
2008-06-13 13:50:35 UTC
Permalink
Post by Christopher L. Felton
Ok, below was my quick test to double check if it could be done. A
real implementation probably need more thought (if feasible at all).
With that said, I do think this approach will work. Even if you have
a non power of 2 limit you still need N bits to represent the max and
min values. If the msb of the "bit container" is modified it will
change the sign.
I meant non-power of 2 values, not the limits, and I don't
think it works:

---
Post by Christopher L. Felton
x = intbv(7, min=-8, max=8)
bin(x)
'111'
Post by Christopher L. Felton
x[3] = 1
1 1 15 -8 8 4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/jand/dev/myhdl/myhdl/_intbv.py", line 173, in __setitem__
self._checkBounds()
File "/home/jand/dev/myhdl/myhdl/_intbv.py", line 89, in _checkBounds
(self._val, self._min))
ValueError: intbv value -15 < minimum -8
---

Should give -1, right?

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Günter Dannoritzer
2008-06-13 18:20:51 UTC
Permalink
Post by Christopher L. Felton
Ok, below was my quick test to double check if it could be done. A
real implementation probably need more thought (if feasible at all).
...

I think what you need to do is not just multiply by -1, but create a
mask that is ORed with the actual number. If the sign bit gets set, the
mask will be all 1 upwards from the sign bit and all 0 down to bit 0.
Then OR that with the current intbv value.

So instead of this:

self._val = -1 * self._val

do this:

self._val = (-1 << self._nrbits-2) | self._val

This is basically a merging between the existing bits below the sign bit
and the sign change to negative.

For clearing the sign bit the simplest way would be to slice the bits
below the sign bit out and return them as a new intbv value.

Guenter
Christopher L. Felton
2008-06-16 13:25:27 UTC
Permalink
Yes, that is a much better solution. Implementing something similar
appears to achieve the goals. As before I did not implement anything
for the slicing to test. The slicing approach would be similar (and
testing probably pretty weak, need to test other bit widths, unsigned,
etc.).

------ Example Output ------
Post by Christopher L. Felton
x = intbv(7, min=-8, max=8)
x
intbv(7)
Post by Christopher L. Felton
str(x)
'0111'
Post by Christopher L. Felton
x[3] = 1
x
intbv(-1L)
Post by Christopher L. Felton
str(x)
'1111'
Post by Christopher L. Felton
x[0] = 0
x
intbv(-2L)
Post by Christopher L. Felton
str(x)
'1110'
Post by Christopher L. Felton
x[1] = 0
x
intbv(-4L)
Post by Christopher L. Felton
str(x)
'1100'
Post by Christopher L. Felton
x[2] = 0
x
intbv(-8L)
Post by Christopher L. Felton
str(x)
'1000'
Post by Christopher L. Felton
x[3] = 0
x
intbv(0L)
Post by Christopher L. Felton
str(x)
'0000'
Post by Christopher L. Felton
x[3] = 1
x
intbv(-8L)
Post by Christopher L. Felton
str(x)
'1000'
Post by Christopher L. Felton
x[:] = 3
x
intbv(3L)
Post by Christopher L. Felton
str(x)
'0011'
Post by Christopher L. Felton
x[3] = 1
x
intbv(-5L)
Post by Christopher L. Felton
str(x)
'1011'
----- Diff ------

154,163d153
<
<
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
< # CFELTON EDIT
< # Create a sign bit mask
< if self._min < 0 and key == self._nrbits-1:
< smask = (-1 << self._nrbits-1)
< else:
< smask = 0
<
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<
165c155
< self._val |= ((1L << i) | smask)
---
self._val |= (1L << i)
167,169c157
< self._val &= (~(1L << i) & ~smask)
<
<
---
self._val &= ~(1L << i)
196d183
<
449,455c436
< s = ''
< for i in range(self._nrbits):
< if self._val & (1 << i):
< s = '1' + s
< else:
< s = '0' + s
< return s #str(self._val)
---
return str(self._val)
Post by Christopher L. Felton
Ok, below was my quick test to double check if it could be done. A
real implementation probably need more thought (if feasible at all).
...
I think what you need to do is not just multiply by -1, but create a
mask that is ORed with the actual number. If the sign bit gets set, the
mask will be all 1 upwards from the sign bit and all 0 down to bit 0.
Then OR that with the current intbv value.
self._val = -1 * self._val
self._val = (-1 << self._nrbits-2) | self._val
This is basically a merging between the existing bits below the sign bit
and the sign change to negative.
For clearing the sign bit the simplest way would be to slice the bits
below the sign bit out and return them as a new intbv value.
Guenter
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
myhdl-list mailing list
https://lists.sourceforge.net/lists/listinfo/myhdl-list
Jan Decaluwe
2008-06-12 18:45:12 UTC
Permalink
Post by Christopher L. Felton
Below is the output example for a small change that I made to the bit
vector class
from myhdl import *
x = intbv(0, min=-8, max=8)
x[3] = 1
x
intbv(-8L)
x[3] = 0
x
intbv(0L)
To implement the above I simply modified __setitems__ and used the _min
and _nrbits values determine what type of number is being represented.
If the number is signed multiply the value by -1 if the msb is being
modified.
Could you show your patch (just a diff)? I don't see how this
would be correct for non-powers of 2.

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Jan Decaluwe
2008-06-16 19:35:33 UTC
Permalink
We had a similar issue/discussion with the invert (not) function of the
intbv class. There seems to be a couple different specific use cases of
the intbv.
1. Generic bit container, this is then MyHDL intbv when there is no min,
no max value. This is similar to the Verilog bit vector (reg [], wire
[]) or VHDLs std_logic_vector.
2. Unsigned number, this is the MyHDL min=0, similar to the Verilog bit
vector, and VHDL unsigned()
3. Signed numbers, this is the MyHDL min is < 0, similar to the Verilog
signed (reg or wire, Verilog 2001 and later) and VHDL signed()
The use case that I really want to push with the intbv is that of
the VHDL constrained integer type. My goal is that designers forget
about signed/unsigned for numeric operations.

For example, when you need a counter that has to count from -1 to 5,
I hope that people will construct it as
intbv(0, min=-1, max=6)
and not as
intbv(0, min=-8, max=8)

Why? Because I believe such constraints give you the best assertions that
you'll ever have. My counters usually don't count between powers of 2, but
in my code I systematically make bound errors. The first construction gives
you instant run-time feedback about the error, the second may not.
The current implementation seems have all the properties that Jan
discussed, high level approach while maintaining the low-level hardware
access for cases 1 and 2. For case 3 there are the issues that Günter
pointed out, you can't modify the msb and maintain the state of the
signed number (or pass the bound checks).
Could we do something similar as the invert solution (not) and use the
knowledge of the type of number being represented and modify the bits
accordingly?
Certainly, but I think the question really is how. The invert problem
was solved by defining what the operator should return depending on
the nature of the operand. We could do a similar thing here using
a method that would do sign-extension. Given the "same" bit pattern,
the result would be different for an "unsigned" versus a "signed".

The proposals I'm seeing do something else: they change the value of
the operand based on the nature of the assignment target. That is much
more tricky and implicit. For example, consider:

a = intbv(0, min=-8, max=8)

Suppose we do sign extension based on the "sign" bit, then after

a[:] = 15 # '1111'

a's value would be -1. And after:

a[:] = 31 # '11111'

it would also be -1. Yet with:

a[:] = 23 # '10111'

you would get a bound check error. Mm, I don't like it.

Of course, you could make things more sophisticated by only doing
sign-extension if the bit width of rhs and lhs are equal. But this
is getting a little too tricky for my taste.

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Christopher L. Felton
2008-06-17 12:47:58 UTC
Permalink
Post by Jan Decaluwe
We had a similar issue/discussion with the invert (not) function of the
intbv class. There seems to be a couple different specific use cases of
the intbv.
1. Generic bit container, this is then MyHDL intbv when there is no min,
no max value. This is similar to the Verilog bit vector (reg [], wire
[]) or VHDLs std_logic_vector.
2. Unsigned number, this is the MyHDL min=0, similar to the Verilog bit
vector, and VHDL unsigned()
3. Signed numbers, this is the MyHDL min is < 0, similar to the Verilog
signed (reg or wire, Verilog 2001 and later) and VHDL signed()
The use case that I really want to push with the intbv is that of
the VHDL constrained integer type. My goal is that designers forget
about signed/unsigned for numeric operations.
I agree about the targeted use case, that most should design with the
intended functionality. But it was also indicated that backward
support (if you can do it in Verilog/VHDL you can do it in MyHDL)
should be included.
Post by Jan Decaluwe
Post by Jan Decaluwe
The goal is that MyHDL should make certain things easier, while
keeping other things at least as easy as in Verilog/VHDL.
I believe that using intbv's can avoid unsigned/signed
confusion often found in VHDL/Verilog for numeric operations.
But of course, hardware designers also have a need to access and
manipulate bit representations. I believe it's possible to make
this as easy as in VHDL/Verilog. But we may not be there yet
completely, as this case shows.
The proposals I'm seeing do something else: they change the value of
the operand based on the nature of the assignment target. That is much
a = intbv(0, min=-8, max=8)
Suppose we do sign extension based on the "sign" bit, then after
a[:] = 15 # '1111'
a[:] = 31 # '11111'
a[:] = 23 # '10111'
you would get a bound check error. Mm, I don't like it.
Good point, trying to add this "feature" (Verilog/VHDL hardware type
support) looks like it would be too kludgy. At this juncture do you
suggest the implementation be left as is? This would be one of the
cases where it is not pratical to make things as easy as Verilog/
VHDL? Or try to find a more elegant implementation that will first
not break the constraint integer model and second support bit
manipulation while maintaining sign?
Jan Decaluwe
2008-06-19 08:34:20 UTC
Permalink
Post by Christopher L. Felton
I agree about the targeted use case, that most should design with the
intended functionality. But it was also indicated that backward
support (if you can do it in Verilog/VHDL you can do it in MyHDL)
should be included.
That is still the goal.
Post by Christopher L. Felton
Post by Jan Decaluwe
Post by Jan Decaluwe
The goal is that MyHDL should make certain things easier, while
keeping other things at least as easy as in Verilog/VHDL.
I believe that using intbv's can avoid unsigned/signed
confusion often found in VHDL/Verilog for numeric operations.
But of course, hardware designers also have a need to access and
manipulate bit representations. I believe it's possible to make
this as easy as in VHDL/Verilog. But we may not be there yet
completely, as this case shows.
The proposals I'm seeing do something else: they change the value of
the operand based on the nature of the assignment target. That is much
a = intbv(0, min=-8, max=8)
Suppose we do sign extension based on the "sign" bit, then after
a[:] = 15 # '1111'
a[:] = 31 # '11111'
a[:] = 23 # '10111'
you would get a bound check error. Mm, I don't like it.
Good point, trying to add this "feature" (Verilog/VHDL hardware type
support) looks like it would be too kludgy. At this juncture do you
suggest the implementation be left as is? This would be one of the
cases where it is not pratical to make things as easy as Verilog/
VHDL?
No, I think the OP has a point that should be solved. I just want
a more "explicit" solution (Explicit is better than implicit!)

Let's go back to the OP's use case:

a = intbv(0)[8:]
b = intbv(0, min=-8, max=8)

and he wants to assign a 4-bit slice of a to b, preserving the bit
pattern.

I propose to add a method that does sign extension in the "obvious"
way. The proper name might be extendSign() but I don't object signed():

b[:] = a[4:].signed()

Remarks:
- we don't "loose" anything against Verilog or VHDL: in those languages
you need similar casting (well, I'm not entirely sure about Verilog :-))
- you could use this in expressions, e.g. b[:] = a[4:].signed() + 1,
not just assignments
- conversion to Verilog/VHDL may be easy
- note that methods are also the way to implement operators in Python.
E.g. "not a" is just syntactic sugar for a.__invert__()

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Blubaugh, David A.
2008-06-20 00:05:47 UTC
Permalink
Jan,


It looks as though I will have to utilize MyHDL for my Master's thesis.
In any case, I was wondering if there is a way to utilize fixed-point
within MyHDL as a way to successfully emulate floating-point?


Thanks,


David Blubaugh

-----Original Message-----
From: myhdl-list-***@lists.sourceforge.net
[mailto:myhdl-list-***@lists.sourceforge.net] On Behalf Of Jan
Decaluwe
Sent: Thursday, June 19, 2008 4:34 AM
To: myhdl-***@lists.sourceforge.net
Subject: Re: [myhdl-list] Slicing an unsigned intbv to a signed one
Post by Christopher L. Felton
I agree about the targeted use case, that most should design with the
intended functionality. But it was also indicated that backward
support (if you can do it in Verilog/VHDL you can do it in MyHDL)
should be included.
That is still the goal.
Post by Christopher L. Felton
Post by Jan Decaluwe
Post by Jan Decaluwe
The goal is that MyHDL should make certain things easier, while
keeping other things at least as easy as in Verilog/VHDL.
I believe that using intbv's can avoid unsigned/signed confusion
often found in VHDL/Verilog for numeric operations.
But of course, hardware designers also have a need to access and
manipulate bit representations. I believe it's possible to make
this as easy as in VHDL/Verilog. But we may not be there yet
completely, as this case shows.
The proposals I'm seeing do something else: they change the value of
the operand based on the nature of the assignment target. That is
a = intbv(0, min=-8, max=8)
Suppose we do sign extension based on the "sign" bit, then after
a[:] = 15 # '1111'
a[:] = 31 # '11111'
a[:] = 23 # '10111'
you would get a bound check error. Mm, I don't like it.
Good point, trying to add this "feature" (Verilog/VHDL hardware type
support) looks like it would be too kludgy. At this juncture do you
suggest the implementation be left as is? This would be one of the
cases where it is not pratical to make things as easy as Verilog/
VHDL?
No, I think the OP has a point that should be solved. I just want a more
"explicit" solution (Explicit is better than implicit!)

Let's go back to the OP's use case:

a = intbv(0)[8:]
b = intbv(0, min=-8, max=8)

and he wants to assign a 4-bit slice of a to b, preserving the bit
pattern.

I propose to add a method that does sign extension in the "obvious"
way. The proper name might be extendSign() but I don't object signed():

b[:] = a[4:].signed()

Remarks:
- we don't "loose" anything against Verilog or VHDL: in those languages
you need similar casting (well, I'm not entirely sure about Verilog :-))
- you could use this in expressions, e.g. b[:] = a[4:].signed() + 1, not
just assignments
- conversion to Verilog/VHDL may be easy
- note that methods are also the way to implement operators in Python.
E.g. "not a" is just syntactic sugar for a.__invert__()

Jan

--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Jan Decaluwe
2008-06-20 07:05:54 UTC
Permalink
Post by Blubaugh, David A.
Jan,
It looks as though I will have to utilize MyHDL for my Master's thesis.
Sounds like you're not too happy with it, I hope it's not that bad :-)
Post by Blubaugh, David A.
In any case, I was wondering if there is a way to utilize fixed-point
within MyHDL as a way to successfully emulate floating-point?
MyHDL is a pure python package, and designed in such a way that you
should be able to use anything that Python offers for modeling.
In particular, you should be able to use any number representation
from the standard library or third parties in your models.

I anticipate that you're going to ask about conversion and so I want
to stress once again: MyHDL modeling is unconstrained, but conversion
is very constrained. Conversion is limited to the few datatypes as
described in the manual. in particular, in terms of number representation,
you're limited to integers.

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Günter Dannoritzer
2008-06-18 12:22:19 UTC
Permalink
Jan Decaluwe wrote:
...
Post by Jan Decaluwe
The use case that I really want to push with the intbv is that of
the VHDL constrained integer type. My goal is that designers forget
about signed/unsigned for numeric operations.
For example, when you need a counter that has to count from -1 to 5,
I hope that people will construct it as
intbv(0, min=-1, max=6)
and not as
intbv(0, min=-8, max=8)
Why? Because I believe such constraints give you the best assertions that
you'll ever have. My counters usually don't count between powers of 2, but
in my code I systematically make bound errors. The first construction gives
you instant run-time feedback about the error, the second may not.
...
Post by Jan Decaluwe
The proposals I'm seeing do something else: they change the value of
the operand based on the nature of the assignment target. That is much
more tricky and implicit.
...
Post by Jan Decaluwe
Of course, you could make things more sophisticated by only doing
sign-extension if the bit width of rhs and lhs are equal. But this
is getting a little too tricky for my taste.
I see you point and agree that adding this feature to intbv looks like
to specific.

Now that brings me back to think about the idea of an extra function
based on concat() that is convertible with toVerilog/VHDL. That would
not add extra code to intbv, but would allow to create an intbv instance
with bit slices and allow to manipulate the sign.

So what about having a function like:

concatSigned(sign, slice1, [slice2, ...[sliceN]..])

It will return an intbv by concatenating the slice(s) and setting the
sign based on the specified sign.

The toVerilog/VHDL converter would then be able to map that direct to a
concatenation of bits with the result being of type signed().

Guenter
Jan Decaluwe
2008-06-20 07:25:37 UTC
Permalink
Post by Günter Dannoritzer
Now that brings me back to think about the idea of an extra function
based on concat() that is convertible with toVerilog/VHDL. That would
not add extra code to intbv, but would allow to create an intbv instance
with bit slices and allow to manipulate the sign.
I would prefer to add a new method to intbv instead of a function in the
myhdl namespace. Adding a new function always feels a bit like a "defeat"
to me - when possible I prefer methods to keep namespaces clean and tie
operators to their type.

"concat" is a function because it has to work on several different types.
Post by Günter Dannoritzer
concatSigned(sign, slice1, [slice2, ...[sliceN]..])
It will return an intbv by concatenating the slice(s) and setting the
sign based on the specified sign.
With the intbv.signed() method, this could be done as follows:

concat(....).signed()

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Jan Decaluwe
2008-06-11 18:30:33 UTC
Permalink
Post by Christopher L. Felton
I don't believe there is an easy way to do this in MyHDL.
I think that is correct at the current stage.
Post by Christopher L. Felton
I have found
is some cases that the Verilog way of doing thing isn't always a good
way in MyHDL. In most cases Verilog doesn't really care about the
number that the bits represent. And MyHDL is different (at least the
case when using min and max) that it is concerned with the actual
value that the bits represent.
The goal is that MyHDL should make certain things easier, while
keeping other things at least as easy as in Verilog/VHDL.

I believe that using intbv's can avoid unsigned/signed
confusion often found in VHDL/Verilog for numeric operations.
But of course, hardware designers also have a need to access and
manipulate bit representations. I believe it's possible to make
this as easy as in VHDL/Verilog. But we may not be there yet
completely, as this case shows.

Jan
--
Jan Decaluwe - Resources bvba - http://www.jandecaluwe.com
Kaboutermansstraat 97, B-3000 Leuven, Belgium
Loading...