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: bf745e53c9b1
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: 1f6441948d19
Choose a head ref
  • 2 commits
  • 11 files changed
  • 1 contributor

Commits on Nov 30, 2014

  1. Copy the full SHA
    e5286c5 View commit details
  2. Copy the full SHA
    1f64419 View commit details
38 changes: 27 additions & 11 deletions doc/manual/fpga_board_ports.rst
Original file line number Diff line number Diff line change
@@ -13,14 +13,30 @@ The low-cost Papilio Pro FPGA board can be used with some limitations.

When plugged to a QC-DAQ LVDS adapter, the AD9858 DDS hardware can be used in addition to a limited number of TTL channels. The TTL lines are mapped to RTIO channels as follows:

+--------------+----------+----------------+
| RTIO channel | TTL line | Capability |
+==============+==========+================+
| 0 | PMT0 | Output + input |
+--------------+----------+----------------+
| 1 | TTL0 | Output only |
+--------------+----------+----------------+
| 2 | TTL1 | Output only |
+--------------+----------+----------------+
| 3 | TTL2 | Output only |
+--------------+----------+----------------+
+--------------+----------+-----------------+
| RTIO channel | TTL line | Capability |
+==============+==========+=================+
| 0 | PMT0 | Input only |
+--------------+----------+-----------------+
| 1 | PMT1 | Input only |
+--------------+----------+-----------------+
| 2 | TTL0 | Output only |
+--------------+----------+-----------------+
| 3 | TTL1 | Output only |
+--------------+----------+-----------------+
| 4 | TTL2 | Output only |
+--------------+----------+-----------------+
| 5 | TTL3 | Output only |
+--------------+----------+-----------------+
| 6 | TTL4 | Output only |
+--------------+----------+-----------------+
| 7 | TTL5 | Output only |
+--------------+----------+-----------------+
| 8 | TTL6 | Output only |
+--------------+----------+-----------------+
| 9 | TTL7 | Output only |
+--------------+----------+-----------------+
| 10 | FUD | DDS driver only |
+--------------+----------+-----------------+

The input only limitation on channels 0 and 1 comes from the QC-DAQ adapter. When the adapter is not used (and physically unplugged from the Papilio Pro board), the corresponding pins on the Papilio Pro can be used as outputs. Do not configure these channels as outputs when the adapter is plugged, as this would cause electrical contention.
6 changes: 3 additions & 3 deletions doc/manual/getting_started.rst
Original file line number Diff line number Diff line change
@@ -96,11 +96,11 @@ Create a new file ``rtio.py`` containing the following: ::
if __name__ == "__main__":
with comm_serial.Comm() as comm:
core_driver = core.Core(comm)
out_driver = rtio.RTIOOut(core=core_driver, channel=1)
out_driver = rtio.RTIOOut(core=core_driver, channel=2)
exp = Tutorial(core=core_driver, o=out_driver)
exp.run()

Connect an oscilloscope or logic analyzer to the RTIO channel 1 (pin C11 on the Papilio Pro) and run ``python3 rtio.py``. Notice that the generated signal's period is precisely 4 microseconds, and that it has a duty cycle of precisely 50%. This is not what you would expect if the delay and the pulse were implemented with CPU-controlled GPIO: overhead from the loop management, function calls, etc. would increase the signal's period, and asymmetry in the overhead would cause duty cycle distortion.
Connect an oscilloscope or logic analyzer to the RTIO channel 2 (pin C11 on the Papilio Pro, TTL0) and run ``python3 rtio.py``. Notice that the generated signal's period is precisely 4 microseconds, and that it has a duty cycle of precisely 50%. This is not what you would expect if the delay and the pulse were implemented with CPU-controlled GPIO: overhead from the loop management, function calls, etc. would increase the signal's period, and asymmetry in the overhead would cause duty cycle distortion.

Instead, inside the core device, output timing is generated by the gateware and the CPU only programs switching commands with certain timestamps that the CPU computes. This guarantees precise timing as long as the CPU can keep generating timestamps that are increasing fast enough. In case it fails to do that (and attempts to program an event with a timestamp in the past), the :class:`artiq.coredevice.runtime_exceptions.RTIOUnderflow` exception is raised. The kernel causing it may catch it (using a regular ``try... except...`` construct), or it will be propagated to the host.

@@ -138,7 +138,7 @@ Try the following code and observe the generated pulses on a 2-channel oscillosc
self.o2.pulse(4*us)
delay(4*us)

If you assign ``o2`` to the RTIO channel 2, the signal will be generated on the pin C10 of the Papilio Pro.
If you assign ``o2`` to the RTIO channel 3, the signal will be generated on the pin C10 (TTL1) of the Papilio Pro.

Within a parallel block, some statements can be made sequential again using a ``with sequential`` construct. Observe the pulses generated by this code: ::

8 changes: 4 additions & 4 deletions examples/dds_test.py
Original file line number Diff line number Diff line change
@@ -28,13 +28,13 @@ def main():
exp = DDSTest(
core=coredev,
a=dds.DDS(core=coredev, dds_sysclk=1*GHz,
reg_channel=0, rtio_switch=0),
reg_channel=0, rtio_switch=2),
b=dds.DDS(core=coredev, dds_sysclk=1*GHz,
reg_channel=1, rtio_switch=1),
reg_channel=1, rtio_switch=3),
c=dds.DDS(core=coredev, dds_sysclk=1*GHz,
reg_channel=2, rtio_switch=2),
reg_channel=2, rtio_switch=4),
d=dds.DDS(core=coredev, dds_sysclk=1*GHz,
reg_channel=3, rtio_switch=3),
reg_channel=3, rtio_switch=5),
led=gpio.GPIOOut(core=coredev, channel=0)
)
exp.run()
4 changes: 2 additions & 2 deletions examples/photon_histogram.py
Original file line number Diff line number Diff line change
@@ -41,9 +41,9 @@ def main():
exp = PhotonHistogram(
core=coredev,
bd=dds.DDS(core=coredev, dds_sysclk=1*GHz,
reg_channel=0, rtio_switch=1),
reg_channel=0, rtio_switch=2),
bdd=dds.DDS(core=coredev, dds_sysclk=1*GHz,
reg_channel=1, rtio_switch=2),
reg_channel=1, rtio_switch=3),
pmt=rtio.RTIOIn(core=coredev, channel=0),
repeats=100,
nbins=100
2 changes: 1 addition & 1 deletion examples/pulse_performance.py
Original file line number Diff line number Diff line change
@@ -30,5 +30,5 @@ def run(self):
with comm_serial.Comm() as comm:
coredev = core.Core(comm)
exp = PulsePerformance(core=coredev,
o=rtio.RTIOOut(core=coredev, channel=1))
o=rtio.RTIOOut(core=coredev, channel=2))
exp.run()
2 changes: 1 addition & 1 deletion examples/rtio_skew.py
Original file line number Diff line number Diff line change
@@ -32,5 +32,5 @@ def run(self):
coredev = core.Core(comm)
exp = RTIOSkew(core=coredev,
i=rtio.RTIOIn(core=coredev, channel=0),
o=rtio.RTIOOut(core=coredev, channel=1))
o=rtio.RTIOOut(core=coredev, channel=2))
exp.run()
6 changes: 3 additions & 3 deletions examples/transport.py
Original file line number Diff line number Diff line change
@@ -120,16 +120,16 @@ def scan(self, stops):
exp = Transport(
core=coredev,
bd=dds.DDS(core=coredev, dds_sysclk=1*GHz,
reg_channel=0, rtio_switch=1),
reg_channel=0, rtio_switch=2),
bdd=dds.DDS(core=coredev, dds_sysclk=1*GHz,
reg_channel=1, rtio_switch=2),
reg_channel=1, rtio_switch=3),
pmt=rtio.RTIOIn(core=coredev, channel=0),
# a compound pdq device that wraps multiple usb devices (looked up
# by usb "serial number"/id) into one
electrodes=pdq2.CompoundPDQ2(
core=coredev,
ids=["qc_q1_{}".format(i) for i in range(4)],
rtio_trigger=3, rtio_frame=(4, 5, 6)),
rtio_trigger=4, rtio_frame=(5, 6, 7)),
transport_data=data, # or: json.load
wait_at_stop=100*us,
speed=1.5,
2 changes: 1 addition & 1 deletion soc/artiqlib/rtio/core.py
Original file line number Diff line number Diff line change
@@ -286,7 +286,7 @@ def __init__(self, phy, clk_freq, counter_width=32,
self.submodules.bank_o = _RTIOBankO(
phy.rbus, self.counter, fine_ts_width, ofifo_depth, guard_io_cycles)
self.submodules.bank_i = _RTIOBankI(
phy.rbus, self.counter, fine_ts_width, ofifo_depth)
phy.rbus, self.counter, fine_ts_width, ififo_depth)

# CSRs
self._r_reset = CSRStorage(reset=1)
2 changes: 1 addition & 1 deletion soc/runtime/rtio.c
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ int rtio_pileup_count(int channel)
return r;
}

#define RTIO_FUD_CHANNEL 4
#define RTIO_FUD_CHANNEL 10

void rtio_fud_sync(void)
{
43 changes: 30 additions & 13 deletions soc/targets/artiq.py
Original file line number Diff line number Diff line change
@@ -9,12 +9,23 @@

_tester_io = [
("user_led", 1, Pins("B:7"), IOStandard("LVTTL")),
("ttl", 0, Pins("C:13"), IOStandard("LVTTL")),
("ttl", 1, Pins("C:11"), IOStandard("LVTTL")),
("ttl", 2, Pins("C:10"), IOStandard("LVTTL")),
("ttl", 3, Pins("C:9"), IOStandard("LVTTL")),
("ttl", 4, Pins("C:8"), IOStandard("LVTTL")),
("ttl_tx_en", 0, Pins("A:9"), IOStandard("LVTTL")),

("pmt", 0, Pins("C:13"), IOStandard("LVTTL")),
("pmt", 1, Pins("C:14"), IOStandard("LVTTL")),

("ttl", 0, Pins("C:11"), IOStandard("LVTTL")),
("ttl", 1, Pins("C:10"), IOStandard("LVTTL")),
("ttl", 2, Pins("C:9"), IOStandard("LVTTL")),
("ttl", 3, Pins("C:8"), IOStandard("LVTTL")),
("ttl", 4, Pins("C:7"), IOStandard("LVTTL")),
("ttl", 5, Pins("C:6"), IOStandard("LVTTL")),
("ttl", 6, Pins("C:5"), IOStandard("LVTTL")),
("ttl", 7, Pins("C:4"), IOStandard("LVTTL")),
("ttl_l_tx_en", 0, Pins("A:9"), IOStandard("LVTTL")),

("ttl", 8, Pins("C:3"), IOStandard("LVTTL")),
("ttl_h_tx_en", 0, Pins("B:6"), IOStandard("LVTTL")),

("dds", 0,
Subsignal("a", Pins("A:5 B:10 A:6 B:9 A:7 B:8")),
Subsignal("d", Pins("A:12 B:3 A:13 B:2 A:14 B:1 A:15 B:0")),
@@ -74,18 +85,24 @@ def __init__(self, platform, cpu_type="or1k", ramcon_type="minicon",
platform.request("user_led", 0),
platform.request("user_led", 1)))

self.comb += platform.request("ttl_tx_en").eq(1)
rtio_pads = [platform.request("ttl", i) for i in range(4)]
fud = Signal()
rtio_pads.append(fud)
self.comb += [
platform.request("ttl_l_tx_en").eq(1),
platform.request("ttl_h_tx_en").eq(1)
]
rtio_ins = [platform.request("pmt") for i in range(2)]
rtio_outs = [platform.request("ttl", i) for i in range(8)] + [fud]

self.submodules.rtiocrg = _RTIOMiniCRG(platform)
self.submodules.rtiophy = rtio.phy.SimplePHY(
rtio_pads,
output_only_pads={rtio_pads[1], rtio_pads[2], rtio_pads[3], fud})
self.submodules.rtio = rtio.RTIO(self.rtiophy, 125000000)
rtio_ins + rtio_outs,
output_only_pads=set(rtio_outs))
self.submodules.rtio = rtio.RTIO(self.rtiophy,
clk_freq=125000000,
ififo_depth=512)

if with_test_gen:
self.submodules.test_gen = _TestGen(platform.request("ttl", 4))
self.submodules.test_gen = _TestGen(platform.request("ttl", 8))

dds_pads = platform.request("dds")
self.submodules.dds = ad9858.AD9858(dds_pads)
6 changes: 3 additions & 3 deletions test/full_stack.py
Original file line number Diff line number Diff line change
@@ -256,7 +256,7 @@ def test_loopback(self):
uut = _RTIOLoopback(
core=coredev,
i=rtio.RTIOIn(core=coredev, channel=0),
o=rtio.RTIOOut(core=coredev, channel=1),
o=rtio.RTIOOut(core=coredev, channel=2),
npulses=npulses
)
uut.run()
@@ -267,7 +267,7 @@ def test_underflow(self):
coredev = core.Core(comm)
uut = _RTIOUnderflow(
core=coredev,
o=rtio.RTIOOut(core=coredev, channel=1)
o=rtio.RTIOOut(core=coredev, channel=2)
)
with self.assertRaises(runtime_exceptions.RTIOUnderflow):
uut.run()
@@ -277,7 +277,7 @@ def test_sequence_error(self):
coredev = core.Core(comm)
uut = _RTIOSequenceError(
core=coredev,
o=rtio.RTIOOut(core=coredev, channel=1)
o=rtio.RTIOOut(core=coredev, channel=2)
)
with self.assertRaises(runtime_exceptions.RTIOSequenceError):
uut.run()