Hello everyone,
I am writing a Python interface between the ARM and the FPGA of my Pynq Z2 and I have to write in the Control Register some scalars of 64 bits. For now I found a workaround like this:
MSB_mu_cpu = Fxp(mu_cpu).like(d_fixed_t).bin()[:32]
LSB_mu_cpu = Fxp(mu_cpu).like(d_fixed_t).bin()[32:]
MSB_DELTA_T = Fxp(DELTA_T).like(d_fixed_t).bin()[:32]
LSB_DELTA_T = Fxp(DELTA_T).like(d_fixed_t).bin()[32:]
lin_ip.write(0x10, buffer_X_FPGA.physical_address)
lin_ip.write(0x1c, int(LSB_mu_cpu, 2))
lin_ip.write(0x20, int(MSB_mu_cpu, 2))
lin_ip.write(0x28, int(LSB_DELTA_T, 2))
lin_ip.write(0x2c, int(MSB_DELTA_T, 2))
In this code, I firstly get the binary string of te variables already converted in fixed points and then I write manually the LSB and MSB bits. Although, when I have to read from memory I will get still the MSB and LSB separately, and this creates some issues when riconverting them.
For reference, I am using this lbrary for fixed ponints: GitHub - francof2a/fxpmath: A python library for fractional fixed-point (base 2) arithmetic and binary manipulation with Numpy compatibility. .
Thank you in advance,
Davide
@davide-giacomini
Zynq ARM A9 is 32bit so even you need 64bit ctrl TX, should it split it into at least 2 cycle of combine 64 bit data?
So instead of considering it as 1 64 bit TX the back-end ends up with two 32bit join data.
ENJOY~
Hi @davide-giacomini ,
For read, you can request a longer read, length=8
self.write = self.write_mm
self.array = self.device.mmap(base_addr, length)
elif self.device.has_capability("REGISTER_RW"):
self.read = self.read
self.write = self.write_reg
self._hook = _AccessHook(self.base_addr, self.device)
self.array = tnp.ndarray(shape=(length // 4,), dtype="u4", hook=self._hook)
else:
raise ValueError("Device does not have capabilities for MMIO")
def read(self, offset=0, length=4, word_order="little"):
"""The method to read data from MMIO.
For the `word_order` parameter, it is only effective when
operating 8 bytes. If it is `little`, from MSB to LSB, the
bytes will be offset+4, offset+5, offset+6, offset+7, offset+0,
offset+1, offset+2, offset+3. If it is `big`, from MSB to LSB,
the bytes will be offset+0, offset+1, ..., offset+7.
This is different than the byte order (endianness); notice
the endianness has not changed.
And for write, you can pass the data as bytes
# Read data out
lsb = int(self.array[idx])
if length == 8:
if word_order == "little":
return ((int(self.array[idx + 1])) << 32) + lsb
else:
return (lsb << 32) + int(self.array[idx + 1])
else:
return lsb & ((2 ** (8 * length)) - 1)
def write_mm(self, offset, data):
"""The method to write data to MMIO.
Parameters
----------
offset : int
The write offset from the MMIO base address.
data : int / bytes
The integer(s) to be written into MMIO.
Returns
Mario
1 Like
@marioruiz
read(self, offset=0, length=4, word_order=“little”):
So does this mean we could read back as either little-endian or big-endian in MMIO API?
But it is still in a byte form no matter how.
How about write ← could we write as either little-endian or big-endian in MMIO API?
Thank you
ENJOY~
Hi Brian,
So does this mean we could read back as either little-endian or big-endian in MMIO API?
But it is still in a byte form no matter how.
Only at the word level (32-bit). The return would be an int
How about write ← could we write as either little-endian or big-endian in MMIO API?
No, this capability is not part of the write. If you want to write more than 32-bit, you need to pass the data as bytes
Mario
2 Likes