Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 85c5b157a0b8
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 944bfafefabc
Choose a head ref
  • 2 commits
  • 7 files changed
  • 1 contributor

Commits on Jun 28, 2015

  1. Copy the full SHA
    b6310b7 View commit details
  2. Copy the full SHA
    944bfaf View commit details
Showing with 131 additions and 67 deletions.
  1. +23 −20 artiq/gateware/{ad9858.py → ad9xxx.py}
  2. +3 −2 artiq/gateware/nist_qc2.py
  3. +38 −15 artiq/gateware/rtio/phy/dds.py
  4. +1 −1 soc/runtime/dds.c
  5. +1 −1 soc/runtime/session.c
  6. +64 −27 soc/targets/artiq_kc705.py
  7. +1 −1 soc/targets/artiq_pipistrello.py
43 changes: 23 additions & 20 deletions artiq/gateware/ad9858.py → artiq/gateware/ad9xxx.py
Original file line number Diff line number Diff line change
@@ -6,15 +6,14 @@
from migen.sim.generic import run_simulation


class AD9858(Module):
"""Wishbone interface to the AD9858 DDS chip.
class AD9xxx(Module):
"""Wishbone interface to the AD9858 and AD9914 DDS chips.
Addresses 0-63 map the AD9858 registers.
Data is zero-padded.
Addresses 0-2**flen(pads.a)-1 map the AD9xxx registers.
Write to address 64 to pulse the FUD signal.
Address 65 is a GPIO register that controls the sel, p and reset signals.
sel is mapped to the lower bits, followed by p and reset.
Write to address 2**flen(pads.a) to pulse the FUD signal.
Address 2**flen(pads.a)+1 is a GPIO register that controls the
sel and reset signals. sel is mapped to the lower bits, followed by reset.
Write timing:
Address is set one cycle before assertion of we_n.
@@ -28,6 +27,7 @@ class AD9858(Module):
Design:
All IO pads are registered.
With QC1 adapter:
LVDS driver/receiver propagation delays are 3.6+4.5 ns max
LVDS state transition delays are 20, 15 ns max
Schmitt trigger delays are 6.4ns max
@@ -38,15 +38,15 @@ def __init__(self, pads,
read_wait_cycles=10, hiz_wait_cycles=3,
bus=None):
if bus is None:
bus = wishbone.Interface(data_width=8)
bus = wishbone.Interface(data_width=flen(pads.d))
self.bus = bus

# # #

dts = TSTriple(8)
dts = TSTriple(flen(pads.d))
self.specials += dts.get_tristate(pads.d)
hold_address = Signal()
dr = Signal(8)
dr = Signal(flen(pads.d))
rx = Signal()
self.sync += [
If(~hold_address, pads.a.eq(bus.adr)),
@@ -55,13 +55,14 @@ def __init__(self, pads,
dts.oe.eq(~rx)
]

gpio = Signal(flen(pads.sel) + flen(pads.p) + 1)
gpio = Signal(flen(pads.sel) + 1)
gpio_load = Signal()
self.sync += If(gpio_load, gpio.eq(bus.dat_w))
self.comb += [
Cat(pads.sel, pads.p).eq(gpio),
pads.rst_n.eq(~gpio[-1]),
]
self.comb += pads.sel.eq(gpio),
if hasattr(pads, "rst"):
self.comb += pads.rst.eq(gpio[-1])
else:
self.comb += pads.rst_n.eq(~gpio[-1])

bus_r_gpio = Signal()
self.comb += If(bus_r_gpio,
@@ -71,7 +72,10 @@ def __init__(self, pads,
)

fud = Signal()
self.sync += pads.fud_n.eq(~fud)
if hasattr(pads, "fud"):
self.sync += pads.fud.eq(fud)
else:
self.sync += pads.fud_n.eq(~fud)

pads.wr_n.reset = 1
pads.rd_n.reset = 1
@@ -87,7 +91,7 @@ def __init__(self, pads,

fsm.act("IDLE",
If(bus.cyc & bus.stb,
If(bus.adr[6],
If(bus.adr[flen(pads.a)],
If(bus.adr[0],
NextState("GPIO")
).Else(
@@ -168,7 +172,6 @@ def __init__(self):
self.a = Signal(6)
self.d = Signal(8)
self.sel = Signal(5)
self.p = Signal(2)
self.fud_n = Signal()
self.wr_n = Signal()
self.rd_n = Signal()
@@ -178,11 +181,11 @@ def __init__(self):
class _TB(Module):
def __init__(self):
pads = _TestPads()
self.submodules.dut = AD9858(pads, drive_fud=True)
self.submodules.dut = AD9xxx(pads, drive_fud=True)
self.submodules.initiator = wishbone.Initiator(_test_gen())
self.submodules.interconnect = wishbone.InterconnectPointToPoint(
self.initiator.bus, self.dut.bus)


if __name__ == "__main__":
run_simulation(_TB(), vcd_name="ad9858.vcd")
run_simulation(_TB(), vcd_name="ad9xxx.vcd")
5 changes: 3 additions & 2 deletions artiq/gateware/nist_qc2.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from mibuild.generic_platform import *


fmc_adapter_io = [
("ttl", 0, Pins("LPC:LA00_CC_P"), IOStandard("LVTTL")),
("ttl", 1, Pins("LPC:LA02_P"), IOStandard("LVTTL")),
@@ -28,10 +29,10 @@
Subsignal("sel", Pins("LPC:LA24_N LPC:LA29_P LPC:LA28_P LPC:LA29_N "
"LPC:LA28_N LPC:LA31_P LPC:LA30_P LPC:LA31_N "
"LPC:LA30_N LPC:LA33_P LPC:LA33_N")),
Subsignal("fud_n", Pins("LPC:LA21_N")),
Subsignal("fud", Pins("LPC:LA21_N")),
Subsignal("wr_n", Pins("LPC:LA24_P")),
Subsignal("rd_n", Pins("LPC:LA25_N")),
Subsignal("rst_in", Pins("LPC:LA25_P")),
Subsignal("rst", Pins("LPC:LA25_P")),
IOStandard("LVTTL")),

("i2c", 0,
53 changes: 38 additions & 15 deletions artiq/gateware/rtio/phy/dds.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,59 @@
from migen.fhdl.std import *

from artiq.gateware import ad9858 as ad9858_ll
from artiq.gateware import ad9xxx
from artiq.gateware.rtio.phy.wishbone import RT2WB


class AD9858(Module):
def __init__(self, pads, nchannels=8, **kwargs):
class _AD9xxx(Module):
def __init__(self, ftw_base, pads, nchannels, **kwargs):
self.submodules._ll = RenameClockDomains(
ad9858_ll.AD9858(pads, **kwargs), "rio")
self.submodules._rt2wb = RT2WB(7, self._ll.bus)
ad9xxx.AD9xxx(pads, **kwargs), "rio")
self.submodules._rt2wb = RT2WB(flen(pads.a)+1, self._ll.bus)
self.rtlink = self._rt2wb.rtlink
self.probes = [Signal(32) for i in range(nchannels)]

# # #

# keep track of the currently selected channel
current_channel = Signal(max=nchannels)
self.sync.rio += If(self.rtlink.o.stb & (self.rtlink.o.address == 65),
current_channel.eq(self.rtlink.o.data))
self.sync.rio += If(self.rtlink.o.stb &
(self.rtlink.o.address == 2**flen(pads.a)+1),
current_channel.eq(self.rtlink.o.data))

# keep track of frequency tuning words, before they are FUDed
ftws = [Signal(32) for i in range(nchannels)]
for c, ftw in enumerate(ftws):
for i in range(4):
self.sync.rio += \
If(self.rtlink.o.stb & \
(self.rtlink.o.address == 0x0a+i) & \
(current_channel == c),
ftw[i*8:(i+1)*8].eq(self.rtlink.o.data)
)
if flen(pads.d) == 8:
for i in range(4):
self.sync.rio += \
If(self.rtlink.o.stb & \
(self.rtlink.o.address == ftw_base+i) & \
(current_channel == c),
ftw[i*8:(i+1)*8].eq(self.rtlink.o.data)
)
elif flen(pads.d) == 16:
for i in range(2):
self.sync.rio += \
If(self.rtlink.o.stb & \
(self.rtlink.o.address == ftw_base+2*i) & \
(current_channel == c),
ftw[i*16:(i+1)*16].eq(self.rtlink.o.data)
)
else:
raise NotImplementedError

# FTW to probe on FUD
for c, (probe, ftw) in enumerate(zip(self.probes, ftws)):
fud = self.rtlink.o.stb & (self.rtlink.o.address == 64)
fud = self.rtlink.o.stb & \
(self.rtlink.o.address == 2**flen(pads.a))
self.sync.rio += If(fud & (current_channel == c), probe.eq(ftw))


class AD9858(_AD9xxx):
def __init__(self, pads, nchannels, **kwargs):
_AD9xxx.__init__(self, 0x0a, pads, nchannels, **kwargs)


class AD9914(_AD9xxx):
def __init__(self, pads, nchannels, **kwargs):
_AD9xxx.__init__(self, 0x2d, pads, nchannels, **kwargs)
2 changes: 1 addition & 1 deletion soc/runtime/dds.c
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@ void dds_init(long long int timestamp, int channel)
now = timestamp - DURATION_INIT;

DDS_WRITE(DDS_GPIO, channel);
DDS_WRITE(DDS_GPIO, channel | (1 << 7));
DDS_WRITE(DDS_GPIO, channel | (1 << 5));
DDS_WRITE(DDS_GPIO, channel);

DDS_WRITE(0x00, 0x78);
2 changes: 1 addition & 1 deletion soc/runtime/session.c
Original file line number Diff line number Diff line change
@@ -542,7 +542,7 @@ static int process_kmsg(struct msg_base *umsg)
case MESSAGE_TYPE_LOG: {
struct msg_log *msg = (struct msg_log *)umsg;

log(msg->fmt, msg->args);
log_va(msg->fmt, msg->args);
mailbox_acknowledge();
break;
}
91 changes: 64 additions & 27 deletions soc/targets/artiq_kc705.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
from targets.kc705 import MiniSoC

from artiq.gateware.soc import AMPSoC
from artiq.gateware import rtio, nist_qc1
from artiq.gateware import rtio, nist_qc1, nist_qc2
from artiq.gateware.rtio.phy import ttl_simple, dds


@@ -32,7 +32,7 @@ def __init__(self, platform, rtio_internal_clk):
o_O=self.cd_rtio.clk)


class NIST_QC1(MiniSoC, AMPSoC):
class _NIST_QCx(MiniSoC, AMPSoC):
csr_map = {
"rtio": None, # mapped on Wishbone instead
"rtio_crg": 13,
@@ -52,18 +52,44 @@ def __init__(self, platform, cpu_type="or1k", **kwargs):
sdram_controller_settings=MiniconSettings(l2_size=128*1024),
with_timer=False, **kwargs)
AMPSoC.__init__(self)
platform.add_extension(nist_qc1.fmc_adapter_io)

self.submodules.leds = gpio.GPIOOut(Cat(
platform.request("user_led", 0),
platform.request("user_led", 1)))

def add_rtio(self, rtio_channels):
self.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.pll_sys)
self.submodules.rtio = rtio.RTIO(rtio_channels,
clk_freq=125000000)
self.add_constant("RTIO_FINE_TS_WIDTH", self.rtio.fine_ts_width)
self.add_constant("DDS_RTIO_CLK_RATIO", 8 >> self.rtio.fine_ts_width)
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)

if isinstance(self.platform.toolchain, XilinxVivadoToolchain):
self.platform.add_platform_command("""
create_clock -name rsys_clk -period 8.0 [get_nets {rsys_clk}]
create_clock -name rio_clk -period 8.0 [get_nets {rio_clk}]
set_false_path -from [get_clocks rsys_clk] -to [get_clocks rio_clk]
set_false_path -from [get_clocks rio_clk] -to [get_clocks rsys_clk]
""", rsys_clk=self.rtio.cd_rsys.clk, rio_clk=self.rtio.cd_rio.clk)

rtio_csrs = self.rtio.get_csrs()
self.submodules.rtiowb = wbgen.Bank(rtio_csrs)
self.kernel_cpu.add_wb_slave(mem_decoder(self.mem_map["rtio"]),
self.rtiowb.bus)
self.add_csr_region("rtio", self.mem_map["rtio"] | 0x80000000, 32,
rtio_csrs)


class NIST_QC1(_NIST_QCx):
def __init__(self, platform, cpu_type="or1k", **kwargs):
_NIST_QCx.__init__(self, platform, cpu_type, **kwargs)
platform.add_extension(nist_qc1.fmc_adapter_io)

self.comb += [
platform.request("ttl_l_tx_en").eq(1),
platform.request("ttl_h_tx_en").eq(1)
]

# RTIO channels
rtio_channels = []
for i in range(2):
phy = ttl_simple.Inout(platform.request("pmt", i))
@@ -81,35 +107,46 @@ def __init__(self, platform, cpu_type="or1k", **kwargs):

self.add_constant("RTIO_DDS_CHANNEL", len(rtio_channels))
self.add_constant("DDS_CHANNEL_COUNT", 8)
phy = dds.AD9858(platform.request("dds"))
self.add_constant("DDS_AD9858")
phy = dds.AD9858(platform.request("dds"), 8)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy,
ofifo_depth=512,
ififo_depth=4))
self.add_rtio(rtio_channels)

# RTIO core
self.submodules.rtio_crg = _RTIOCRG(platform, self.crg.pll_sys)
self.submodules.rtio = rtio.RTIO(rtio_channels,
clk_freq=125000000)
self.add_constant("RTIO_FINE_TS_WIDTH", self.rtio.fine_ts_width)
self.add_constant("DDS_RTIO_CLK_RATIO", 8 >> self.rtio.fine_ts_width)
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)

if isinstance(platform.toolchain, XilinxVivadoToolchain):
platform.add_platform_command("""
create_clock -name rsys_clk -period 8.0 [get_nets {rsys_clk}]
create_clock -name rio_clk -period 8.0 [get_nets {rio_clk}]
set_false_path -from [get_clocks rsys_clk] -to [get_clocks rio_clk]
set_false_path -from [get_clocks rio_clk] -to [get_clocks rsys_clk]
""", rsys_clk=self.rtio.cd_rsys.clk, rio_clk=self.rtio.cd_rio.clk)
class NIST_QC2(_NIST_QCx):
def __init__(self, platform, cpu_type="or1k", **kwargs):
_NIST_QCx.__init__(self, platform, cpu_type, **kwargs)
platform.add_extension(nist_qc2.fmc_adapter_io)

# CPU connections
rtio_csrs = self.rtio.get_csrs()
self.submodules.rtiowb = wbgen.Bank(rtio_csrs)
self.kernel_cpu.add_wb_slave(mem_decoder(self.mem_map["rtio"]),
self.rtiowb.bus)
self.add_csr_region("rtio", self.mem_map["rtio"] | 0x80000000, 32,
rtio_csrs)
rtio_channels = []
for i in range(16):
if i % 4 == 3:
phy = ttl_simple.Inout(platform.request("ttl", i))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512))
else:
phy = ttl_simple.Output(platform.request("ttl", i))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))

phy = ttl_simple.Output(platform.request("user_led", 2))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
self.add_constant("RTIO_TTL_COUNT", len(rtio_channels))

self.add_constant("RTIO_DDS_CHANNEL", len(rtio_channels))
self.add_constant("DDS_CHANNEL_COUNT", 11)
self.add_constant("DDS_AD9914")
self.add_constant("DDS_ONEHOT_SEL")
phy = dds.AD9914(platform.request("dds"), 11)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy,
ofifo_depth=512,
ififo_depth=4))
self.add_rtio(rtio_channels)


default_subtarget = NIST_QC1
2 changes: 1 addition & 1 deletion soc/targets/artiq_pipistrello.py
Original file line number Diff line number Diff line change
@@ -118,7 +118,7 @@ def __init__(self, platform, cpu_type="or1k", **kwargs):

self.add_constant("RTIO_DDS_CHANNEL", len(rtio_channels))
self.add_constant("DDS_CHANNEL_COUNT", 8)
phy = dds.AD9858(platform.request("dds"))
phy = dds.AD9858(platform.request("dds"), 8)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy,
ofifo_depth=512,