forked from M-Labs/artiq
phaser: wire up multidds
This commit is contained in:
parent
d1be1212ab
commit
e5e2392240
|
@ -48,7 +48,7 @@ class Phaser:
|
||||||
|
|
||||||
def __init__(self, dmgr, channel_base, miso_delay=1,
|
def __init__(self, dmgr, channel_base, miso_delay=1,
|
||||||
core_device="core"):
|
core_device="core"):
|
||||||
self.channel_base = channel_base << 8
|
self.channel_base = channel_base
|
||||||
self.core = dmgr.get(core_device)
|
self.core = dmgr.get(core_device)
|
||||||
self.miso_delay = miso_delay
|
self.miso_delay = miso_delay
|
||||||
# frame duration in mu (10 words, 8 clock cycles each 4 ns)
|
# frame duration in mu (10 words, 8 clock cycles each 4 ns)
|
||||||
|
@ -69,7 +69,7 @@ class Phaser:
|
||||||
:param addr: Address to write to.
|
:param addr: Address to write to.
|
||||||
:param data: Data to write.
|
:param data: Data to write.
|
||||||
"""
|
"""
|
||||||
rtio_output(self.channel_base | addr | 0x80, data)
|
rtio_output((self.channel_base << 8) | addr | 0x80, data)
|
||||||
delay_mu(int64(self.t_frame))
|
delay_mu(int64(self.t_frame))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
|
@ -81,8 +81,8 @@ class Phaser:
|
||||||
:param addr: Address to read from.
|
:param addr: Address to read from.
|
||||||
:return: The data read.
|
:return: The data read.
|
||||||
"""
|
"""
|
||||||
rtio_output(self.channel_base | addr, 0)
|
rtio_output((self.channel_base << 8) | addr, 0)
|
||||||
response = rtio_input_data(self.channel_base >> 8)
|
response = rtio_input_data(self.channel_base)
|
||||||
return response >> self.miso_delay
|
return response >> self.miso_delay
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
|
@ -199,3 +199,14 @@ class Phaser:
|
||||||
self.spi_write(data)
|
self.spi_write(data)
|
||||||
delay_mu(t_xfer)
|
delay_mu(t_xfer)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def set_frequency_mu(self, ch, osc, ftw):
|
||||||
|
addr = ((self.channel_base + 1 + ch) << 8) | (osc << 1)
|
||||||
|
rtio_output(addr, ftw)
|
||||||
|
|
||||||
|
@kernel
|
||||||
|
def set_amplitude_phase_mu(self, ch, osc, asf=0x7fff, pow=0, clr=0):
|
||||||
|
addr = ((self.channel_base + 1 + ch) << 8) | (osc << 1) | 1
|
||||||
|
data = (asf & 0x7fff) | (clr << 15) | (pow << 16)
|
||||||
|
rtio_output(addr, data)
|
||||||
|
|
|
@ -646,11 +646,12 @@ class Phaser(_EEM):
|
||||||
def add_std(cls, target, eem, iostandard="LVDS_25"):
|
def add_std(cls, target, eem, iostandard="LVDS_25"):
|
||||||
cls.add_extension(target, eem, iostandard=iostandard)
|
cls.add_extension(target, eem, iostandard=iostandard)
|
||||||
|
|
||||||
phy = phaser.Phaser(target.platform.request("phaser{}_ser_p".format(eem)),
|
phy = phaser.Phaser(
|
||||||
|
target.platform.request("phaser{}_ser_p".format(eem)),
|
||||||
target.platform.request("phaser{}_ser_n".format(eem)))
|
target.platform.request("phaser{}_ser_n".format(eem)))
|
||||||
target.submodules += phy
|
target.submodules += phy
|
||||||
target.rtio_channels.extend([
|
target.rtio_channels.extend([
|
||||||
rtio.Channel.from_phy(phy, ififo_depth=4),
|
rtio.Channel.from_phy(phy, ififo_depth=4),
|
||||||
rtio.Channel.from_phy(phy.dds0),
|
rtio.Channel.from_phy(phy.ch0),
|
||||||
rtio.Channel.from_phy(phy.dds1),
|
rtio.Channel.from_phy(phy.ch1),
|
||||||
])
|
])
|
||||||
|
|
|
@ -6,11 +6,23 @@ from .fastlink import SerDes, SerInterface
|
||||||
|
|
||||||
|
|
||||||
class DDSChannel(Module):
|
class DDSChannel(Module):
|
||||||
def __init__(self):
|
def __init__(self, use_lut=None):
|
||||||
self.rtlink = rtlink.Interface(
|
self.rtlink = rtlink.Interface(
|
||||||
rtlink.OInterface(data_width=32, address_width=4,
|
rtlink.OInterface(data_width=32, address_width=4,
|
||||||
enable_replace=True))
|
enable_replace=True))
|
||||||
self.submodules.dds = MultiDDS(n=5, fwidth=32, xwidth=16)
|
to_rio_phy = ClockDomainsRenamer("rio_phy")
|
||||||
|
self.submodules.dds = to_rio_phy(MultiDDS(
|
||||||
|
n=5, fwidth=32, xwidth=16, z=19, zl=10, use_lut=use_lut))
|
||||||
|
# TODO: latency
|
||||||
|
self.comb += self.dds.stb.eq(1)
|
||||||
|
regs = []
|
||||||
|
for i in self.dds.i:
|
||||||
|
regs.extend([i.f, Cat(i.a, i.clr, i.p)])
|
||||||
|
self.sync.rio_phy += [
|
||||||
|
If(self.rtlink.o.stb,
|
||||||
|
Array(regs)[self.rtlink.o.address].eq(self.rtlink.o.data)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Phaser(Module):
|
class Phaser(Module):
|
||||||
|
@ -20,8 +32,22 @@ class Phaser(Module):
|
||||||
enable_replace=False),
|
enable_replace=False),
|
||||||
rtlink.IInterface(data_width=10))
|
rtlink.IInterface(data_width=10))
|
||||||
|
|
||||||
self.submodules.dds0 = DDSChannel()
|
self.submodules.ch0 = DDSChannel()
|
||||||
self.submodules.dds1 = DDSChannel()
|
self.submodules.ch1 = DDSChannel(use_lut=self.ch0.dds.mod.cs.lut)
|
||||||
|
n_channels = 2
|
||||||
|
n_samples = 8
|
||||||
|
n_bits = 14
|
||||||
|
body = [Signal(n_channels*2*n_bits, reset_less=True)
|
||||||
|
for i in range(n_samples)]
|
||||||
|
i_sample = Signal(max=n_samples)
|
||||||
|
self.sync.rio_phy += [
|
||||||
|
If(self.ch0.dds.valid, # & self.ch1.dds.valid,
|
||||||
|
Array(body)[i_sample].eq(Cat(
|
||||||
|
self.ch0.dds.o.q[2:], self.ch0.dds.o.i[2:],
|
||||||
|
self.ch1.dds.o.q[2:], self.ch1.dds.o.i[2:])),
|
||||||
|
i_sample.eq(i_sample + 1),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
self.submodules.serializer = SerDes(
|
self.submodules.serializer = SerDes(
|
||||||
n_data=8, t_clk=8, d_clk=0b00001111,
|
n_data=8, t_clk=8, d_clk=0b00001111,
|
||||||
|
@ -31,6 +57,11 @@ class Phaser(Module):
|
||||||
Cat(self.intf.data[:-1]).eq(Cat(self.serializer.data[:-1])),
|
Cat(self.intf.data[:-1]).eq(Cat(self.serializer.data[:-1])),
|
||||||
self.serializer.data[-1].eq(self.intf.data[-1]),
|
self.serializer.data[-1].eq(self.intf.data[-1]),
|
||||||
]
|
]
|
||||||
|
self.sync.rio_phy += [
|
||||||
|
If(self.serializer.stb,
|
||||||
|
i_sample.eq(0),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
header = Record([
|
header = Record([
|
||||||
("we", 1),
|
("we", 1),
|
||||||
|
@ -38,10 +69,6 @@ class Phaser(Module):
|
||||||
("data", 8),
|
("data", 8),
|
||||||
("type", 4)
|
("type", 4)
|
||||||
])
|
])
|
||||||
n_channels = 2
|
|
||||||
n_samples = 8
|
|
||||||
n_bits = 14
|
|
||||||
body = [Signal(n_bits) for i in range(n_channels*n_samples*2)]
|
|
||||||
assert len(Cat(header.raw_bits(), body)) == \
|
assert len(Cat(header.raw_bits(), body)) == \
|
||||||
len(self.serializer.payload)
|
len(self.serializer.payload)
|
||||||
self.comb += self.serializer.payload.eq(Cat(header.raw_bits(), body))
|
self.comb += self.serializer.payload.eq(Cat(header.raw_bits(), body))
|
||||||
|
|
Loading…
Reference in New Issue