Long integer translation

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,

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?

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 :slight_smile:
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


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.

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?


The Markdown Cheat Sheet tells you all about formatting text, as used here in Discourse.