MyHDL Discourse

Bit-vector slicing and variable assignment


#1

Hi,

what is the correct way to slice a bit-vector and store the sliced bits in a local variable?
Example code:

from __future__ import print_function
from myhdl import *

# FIXME: GHDL: Empty interface list not allowed
def Sha256_new(dummy=False):
    # big-endian: high-order bits contain first word
    return modbv(0x6a09e667bb67ae853c6ef372a54ff53a510e527f9b05688c1f83d9ab5be0cd19)[256:]

# FIXME: MyHDL: Param type is unconstrained unsigned
def Sha256_transform(inDig, inBlock):
    # FIXME: MyHDL: Type of var is: unsigned(255 downto 0);
    TEST1 = inDig[64:32]
    # FIXME: GHDL: no overloaded function found matching 'to_unsigned'
    TEST2 = intbv(inDig[64:32])
    # FIXME: GHDL: static range violates bounds
    TEST3 = intbv(inDig[64:32])[32:]
    # works
    TEST4 = intbv(0)[32:]
    TEST4[:] = inDig[64:32]
    # unused return value
    return 0

@block
def Sha256(ioDigest, inBlock, reset):
    @instance
    def logic():
        while True:
            yield ioDigest, inBlock, reset

            if reset != 1:
                ioDigest.next = Sha256_new(False)
            else:
                ioDigest.next = Sha256_transform(ioDigest, inBlock)

    return logic

inst = Sha256(
    ioDigest = Signal(intbv(0)[256:]),
    inBlock  = Signal(intbv(0)[512:]),
    reset    = Signal(bool(1))
)

inst.convert(hdl='VHDL', path='work')
inst.convert(hdl='Verilog', path='work', no_testbench=True)

Here, the example function Sha256_transform() receives as its 1st parameter inDig a signal of 256 bits. I’d like to access the 2nd 32-bit word and store the result in a function-local variable. The generated VHDL:

function MYHDL5_Sha256_transform(
    inDig: in unsigned;
    inBlock: in unsigned
    ) return std_logic is
    variable TEST1: unsigned(255 downto 0);
    variable TEST3: unsigned(31 downto 0);
    variable TEST2: unsigned(31 downto 0);
    variable TEST4: unsigned(31 downto 0);
begin
    TEST1 := resize(inDig(64-1 downto 32), 256);
    TEST2 := to_unsigned(inDig(64-1 downto 32), 32);
    TEST3 := inDig(64-1 downto 32)(32-1 downto 0);
    TEST4 := unsigned'("00000000000000000000000000000000");
    TEST4 := inDig(64-1 downto 32);
    return '0';
end function MYHDL5_Sha256_transform;

TEST1: Although the returned value is a correctly sized 32-bit intbv, MyHDL translates to a variable of 256 bit also adding a resize() call.
TEST2: Does not compile, because there is no viable overload of to_unsigned(), which makes sense, since the value being casted is already an unsigned. The Verilog version may work.
TEST3: Translates to 2 consecutive slicings (syntax error).
TEST4: Works, but is also overly redundant.

Am I trying something completely stupid or how should it be written correctly?
This is MyHDL current git trunk.

Thanks and ciao,
Mario


#2

I believe the myhdl converter simply looks at the type on the rhs and determines the type for the lhs not taking into consideration the bit-slicing. To avoid this you can define your variables

TEST1 = intbv(0)[64:0]
TEST1[:] = inDig[64:32]