diff --git a/artiq/coredevice/shuttler.py b/artiq/coredevice/shuttler.py index 5ad6e4e71..c6761e0ba 100644 --- a/artiq/coredevice/shuttler.py +++ b/artiq/coredevice/shuttler.py @@ -12,7 +12,7 @@ def shuttler_volt_to_mu(volt): """Return the equivalent DAC code. Valid input range is from -10 to 10 - LSB. """ - return round((1 << 14) * (volt / 20.0)) & 0x3fff + return round((1 << 16) * (volt / 20.0)) & 0xffff class Config: @@ -25,7 +25,7 @@ class Config: output data with pre-DAC gain, then adds the offset. .. 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 core_device: Core device name. @@ -152,8 +152,8 @@ class Volt: a_3 &= p_3T^3 - :math:`a_0`, :math:`a_1`, :math:`a_2` and :math:`a_3` are 14, 30, 46 - and 46 bits in width respectively. See :meth:`shuttler_volt_to_mu` for + :math:`a_0`, :math:`a_1`, :math:`a_2` and :math:`a_3` are 16, 32, 48 + and 48 bits in width respectively. See :meth:`shuttler_volt_to_mu` for machine unit conversion. Note: The waveform is not updated to the Shuttler Core until @@ -238,8 +238,8 @@ class Dds: c_2 &= r_2T^2 - :math:`b_0`, :math:`b_1`, :math:`b_2` and :math:`b_3` are 14, 30, 46 - and 46 bits in width respectively. See :meth:`shuttler_volt_to_mu` for + :math:`b_0`, :math:`b_1`, :math:`b_2` and :math:`b_3` are 16, 32, 48 + 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 16, 32 and 32 bits in width respectively. diff --git a/artiq/examples/kasli_shuttler/repository/shuttler.py b/artiq/examples/kasli_shuttler/repository/shuttler.py index 85db3b9bd..22a3a776e 100644 --- a/artiq/examples/kasli_shuttler/repository/shuttler.py +++ b/artiq/examples/kasli_shuttler/repository/shuttler.py @@ -26,15 +26,15 @@ def shuttler_volt_amp_mu(volt): @portable 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 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 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 def shuttler_dds_amp_mu(volt): diff --git a/artiq/gateware/shuttler.py b/artiq/gateware/shuttler.py index 93a1ac7d2..ceebb1043 100644 --- a/artiq/gateware/shuttler.py +++ b/artiq/gateware/shuttler.py @@ -124,16 +124,18 @@ class Dac(Module): ] # Infer signed multiplication - data_raw = Signal((14, True)) - data_buf = Signal(16) + data_raw = Signal((16, True)) + # 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 += [ data_raw.eq(reduce(add, [sub.data for sub in subs])), # Extra buffer for timing for the DSP data_buf.eq(((data_raw * Cat(self.gain, ~self.gain[-1])) + (self.offset << 16))[16:]), If(overflow, - self.data.eq(0x1fff), + self.data.eq(0x7fff), ).Elif(underflow, - self.data.eq(0x2000), + self.data.eq(0x8000), ).Else( self.data.eq(data_buf), ), @@ -350,7 +352,7 @@ class Shuttler(Module, AutoCSR): dac.clear.eq(self.cfg.clr[idx]), dac.gain.eq(self.cfg.gain[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: