简体   繁体   中英

Myhdl: assigning a bitslice to a signed variable fails with negative values

The code added fails with a ValueError and i have no idea whats going wrong. Here is what i want to do: In my fpga i receive data via spi. Data is a bipolar signal (in the sense of a measurement signal) arriving in a 16 bit register rxdata.

the task is to interpret this signal as being signed and only the upper 12 bits (including sign) are needed. The variable bipolar is therefore 12bit wide and signed ie declared like in the code. Then i assign:

    bipolar.next=rxdata[:4].signed() 

my problem is, that the assignment of the 12bit slice fails as soon as data becomes negative (ie most significant bit becomes 1).

With data 0x8fff for instance at runtime i get:

'ValueError: intbv value 2303 >= maximum 2048'

I don't expect this, as both sides are declared signed and data fits into the variable bipolar.

Is there another way to do this?

(by the way: bipolar[:].next=rxdata[:4].signed() i get 0 as a result which i would not expect either)

#testcase.py sk 09.12.2020
#assign a  slice to a signed signal (bipolar) fails at runtime with negative numbers
from myhdl import *

nspi=16
n=12
tend=1e-6

@block
def testcase():
    CLK = Signal(bool(0))
    RESET = ResetSignal(1,active = 0, isasync=True)
    bipolar=Signal(intbv(0,min=-2**(n-1),max=2**(n-1)))
    rxdata = Signal(intbv(0)[nspi:0])   #received data is bipolar, transferred via spi into rxdata

    ''' Clock driver 16MHz'''
    @always(delay(31))
    def driver():
        CLK.next = not CLK

    @instance
    def init():
        rxdata.next=0x8fff   #0x7fff i.e. positive passes, 0x8fff     i.e negative fails runtime check
        yield delay(100)

    @always_seq(CLK.negedge,reset=RESET)
    def assign():
        #bipolar[:].next=rxdata[:(nspi-n)].signed()  #this passes - but result is 0! (unexpected for me)
        bipolar.next=rxdata[:(nspi-n)].signed()  #this fails with negative numbers (unexpected for me)
        print(bipolar, 'bipolar=', int(str(bipolar),16))


    return instances()

tc = testcase()
tc.run_sim(tend*1e9)

print('Simulated to tend='+str(tend))

Just found the way to do it: use shadow signals. ie use round brackets () instead of square..[]

#testcase.py sk 12.12.2020
#assign a  slice to a signed signal (bipolar) fails at runtime with negative numbers
#-> use shadow signals instead!     #bipolar[:].next=rxdata[:(nspi-n)].signed()  #this passes - but result is 0! (unexpected for me)

from myhdl import *

nspi=16
n=12
tend=1e-6

@block
def testcase():
    CLK = Signal(bool(0))
    RESET = ResetSignal(1,active = 0, isasync=True)
    bipolar=Signal(intbv(0,min=-2**(n-1),max=2**(n-1)))
    #rxdata = Signal(intbv(0)[nspi:0])   #received data is bipolar, transferred via spi into rxdata
    rxdata = Signal(intbv(0,min=0,max=2**nspi))


    ''' Clock driver 16MHz'''
    @always(delay(31))
    def driver():
        CLK.next = not CLK

    @instance
    def init():
        rxdata.next=0xffff   #0x7fff i.e. positive passes, 0x8fff i.e negative fails runtime check when not using shadow
        yield delay(100)

    @always_seq(CLK.negedge,reset=RESET)
    def assign():
        #bipolar.next=rxdata[:(nspi-n)].signed()     #this fails in runtime check -> number too big
        #bipolar[:].next=rxdata[:(nspi-n)].signed()  #this passes - but result is 0! (unexpected for me)
        bipolar.next=rxdata(nspi,(nspi-n)).signed()  #this is the way: use shadow signal !
        print(bipolar, 'bipolar=', int(str(bipolar),16))


    return instances()

tc = testcase()
tc.run_sim(tend*1e9)

print('Simulated to tend='+str(tend))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM