Long integer translation (original) (raw)
December 14, 2021, 1:35pm 1
I have a problem with a conversion of intbv to (un)signed.
I use the following code:
multiply_reg = intbv(val=0, min=-2^42, max=2^42
@always_seq (ip_clk.posedge, reset=ip_rst)
def multiply():
multiply_reg = 0
multiply_reg = internal_data * factor
Internal data is 16 bits width and factor 24 bits width
When I convert this to VHDL I get:
MODEL_MULTIPLY: process (ip_clk, ip_rst) is
variable multiply_reg: integer;
Here suddenly multiply_reg is only 32 bits, but I need 42 bits. It should not be an integer but signed width a length of 42 bits.
Did I make a mistake or is the conversion wrong?
Best Regards,
Albert
Albert December 14, 2021, 1:45pm 2
If I use this construction in the *.py files, conversion seems correct
multiply_reg = intbv(internal_data * factor, min=-2^42, max=2^42)
VHDL looks like: variable multiply_reg: signed(42 downto 0);
But the VHDL looks like this:
multiply_reg := to_signed((internal_data * signed(resize(factor, 25))), 43);
Which give a compile error;
No feasible entries for subprogram “to_signed”
Integer * signed => signed, so the “to_signed” is not needed.
Does anyone have a solution for this?
josyb December 14, 2021, 4:01pm 3
Hi Albert,
Here suddenly multiply_reg is only 32 bits,
You need to update an intbv()
variable using the [:]
notation to explicitly set the value held by that intbv()
; in the other case (as you did) MyHDL considers it to be an integer.
multiply_reg = intbv(val=0, min=-2**40, max=2**40
@always_seq (ip_clk.posedge, reset=ip_rst)
def multiply():
multiply_reg[:] = internal_data * factor
IMO it is always best to make the result of any arithmetic operation fit: in your case you multiply 16 bits by 25 which only produces a 41-bit result. If you subsequently assign that result to an object with a wider bitwidth MyHDL will then correctly extend the value.
I assume that at least one of the two operands is signed.
You may have stumbled on one of the issues @hackfin knows all about
Can you make a minimal example of your code? I will try it out.
PS.: 2^42 doesn’t work; in Python we use 2**42
Regards,
Josy
hackfin December 14, 2021, 7:10pm 4
I don’t think there’s an arithmetic issue in this context, although I’m puzzled about the signedness of the multiplicands, you might want to post the full example. I’d rather have assumed that data
is unsigned and factor
signed, so data
would be extended instead (still with the resulting bit width: 24+17). If both are signed, you get by with 40 bits in the result.
But: Variable usage (instead of signals) comes with a few caveats, potentially leading to a number of confusing scenarios, so you might want to turn that into a Signal and use the .next
assignment notation, although josyb’s [:]
suggestion should synthesize as well.
To note:
- an intbv() multiplied by an intbv() is of type int, not intbv.
- First time assignment in a
@always*
generator of a variable in the Python code defines the type for the HDL (that’s why you got the integer) - So: the variable is instanced locally per process in the result, but might have to be declared in the
@block
body for vectors/arrays, not entirely sure about that, but I remember some inconsistent behaviour.
Albert December 15, 2021, 7:25am 5
Thanks josyb ^ hackfin for the quick replay
Using multiply_reg[:] = internal_data * factor solved the problem.
Internal_data is a signed number of 17 bits, factor is an unsigned number of 24 bits. I also trimmed the width of the multiply_reg to 41 bits.
In VHDL it looks like this:
multiply_reg := resize(internal_data * signed(resize(factor, 25)), 41); which is correct VHDL.
josyb, I used 2^42 because it was not correctly shown in this message box. In Python indeed I used 242 (must be 2 * * 42) (Goes wrong, maybe due to “----” or "*" I used on the lines before and after the Python code)
By the way how does this text formatting works in this message box?
josyb December 15, 2021, 8:00am 6
Albert,
The Markdown Cheat Sheet tells you all about formatting text, as used here in Discourse.
Regards,
Josy