shuttler: change 0th order accumulator width

It now truncates the LSBs instead of the MSBs.
This commit is contained in:
occheung 2023-09-27 17:11:12 -07:00 committed by Sébastien Bourdeauducq
parent bafb85a274
commit a772dee1cc
3 changed files with 16 additions and 14 deletions

View File

@ -12,7 +12,7 @@ def shuttler_volt_to_mu(volt):
"""Return the equivalent DAC code. Valid input range is from -10 to """Return the equivalent DAC code. Valid input range is from -10 to
10 - LSB. 10 - LSB.
""" """
return round((1 << 14) * (volt / 20.0)) & 0x3fff return round((1 << 16) * (volt / 20.0)) & 0xffff
class Config: class Config:
@ -25,7 +25,7 @@ class Config:
output data with pre-DAC gain, then adds the offset. output data with pre-DAC gain, then adds the offset.
.. note:: .. note::
The DAC code is capped at 0x1fff and 0x2000. The DAC code is capped at 0x7fff and 0x8000.
:param channel: RTIO channel number of this interface. :param channel: RTIO channel number of this interface.
:param core_device: Core device name. :param core_device: Core device name.
@ -152,8 +152,8 @@ class Volt:
a_3 &= p_3T^3 a_3 &= p_3T^3
:math:`a_0`, :math:`a_1`, :math:`a_2` and :math:`a_3` are 14, 30, 46 :math:`a_0`, :math:`a_1`, :math:`a_2` and :math:`a_3` are 16, 32, 48
and 46 bits in width respectively. See :meth:`shuttler_volt_to_mu` for and 48 bits in width respectively. See :meth:`shuttler_volt_to_mu` for
machine unit conversion. machine unit conversion.
Note: The waveform is not updated to the Shuttler Core until Note: The waveform is not updated to the Shuttler Core until
@ -238,8 +238,8 @@ class Dds:
c_2 &= r_2T^2 c_2 &= r_2T^2
:math:`b_0`, :math:`b_1`, :math:`b_2` and :math:`b_3` are 14, 30, 46 :math:`b_0`, :math:`b_1`, :math:`b_2` and :math:`b_3` are 16, 32, 48
and 46 bits in width respectively. See :meth:`shuttler_volt_to_mu` for and 48 bits in width respectively. See :meth:`shuttler_volt_to_mu` for
machine unit conversion. :math:`c_0`, :math:`c_1` and :math:`c_2` are machine unit conversion. :math:`c_0`, :math:`c_1` and :math:`c_2` are
16, 32 and 32 bits in width respectively. 16, 32 and 32 bits in width respectively.

View File

@ -26,15 +26,15 @@ def shuttler_volt_amp_mu(volt):
@portable @portable
def shuttler_volt_damp_mu(volt_per_us): def shuttler_volt_damp_mu(volt_per_us):
return round(float(2) ** 30 * (volt_per_us / 20) / DAC_Fs_MHZ) return round(float(2) ** 32 * (volt_per_us / 20) / DAC_Fs_MHZ)
@portable @portable
def shuttler_volt_ddamp_mu(volt_per_us_square): def shuttler_volt_ddamp_mu(volt_per_us_square):
return round(float(2) ** 46 * (volt_per_us_square / 20) * 2 / (DAC_Fs_MHZ ** 2)) return round(float(2) ** 48 * (volt_per_us_square / 20) * 2 / (DAC_Fs_MHZ ** 2))
@portable @portable
def shuttler_volt_dddamp_mu(volt_per_us_cube): def shuttler_volt_dddamp_mu(volt_per_us_cube):
return round(float(2) ** 46 * (volt_per_us_cube / 20) * 6 / (DAC_Fs_MHZ ** 3)) return round(float(2) ** 48 * (volt_per_us_cube / 20) * 6 / (DAC_Fs_MHZ ** 3))
@portable @portable
def shuttler_dds_amp_mu(volt): def shuttler_dds_amp_mu(volt):

View File

@ -124,16 +124,18 @@ class Dac(Module):
] ]
# Infer signed multiplication # Infer signed multiplication
data_raw = Signal((14, True)) data_raw = Signal((16, True))
data_buf = Signal(16) # Buffer data should have 2 more bits than the desired output width
# It is to perform overflow/underflow detection
data_buf = Signal(18)
self.sync.rio += [ self.sync.rio += [
data_raw.eq(reduce(add, [sub.data for sub in subs])), data_raw.eq(reduce(add, [sub.data for sub in subs])),
# Extra buffer for timing for the DSP # Extra buffer for timing for the DSP
data_buf.eq(((data_raw * Cat(self.gain, ~self.gain[-1])) + (self.offset << 16))[16:]), data_buf.eq(((data_raw * Cat(self.gain, ~self.gain[-1])) + (self.offset << 16))[16:]),
If(overflow, If(overflow,
self.data.eq(0x1fff), self.data.eq(0x7fff),
).Elif(underflow, ).Elif(underflow,
self.data.eq(0x2000), self.data.eq(0x8000),
).Else( ).Else(
self.data.eq(data_buf), self.data.eq(data_buf),
), ),
@ -350,7 +352,7 @@ class Shuttler(Module, AutoCSR):
dac.clear.eq(self.cfg.clr[idx]), dac.clear.eq(self.cfg.clr[idx]),
dac.gain.eq(self.cfg.gain[idx]), dac.gain.eq(self.cfg.gain[idx]),
dac.offset.eq(self.cfg.offset[idx]), dac.offset.eq(self.cfg.offset[idx]),
self.dac_interface.data[idx // 2][idx % 2].eq(dac.data) self.dac_interface.data[idx // 2][idx % 2].eq(dac.data[2:])
] ]
for i in dac.i: for i in dac.i: