Skip to content

Commit

Permalink
Merge branch 'master' into new-py2llvm
Browse files Browse the repository at this point in the history
whitequark committed Jul 29, 2015
2 parents 244ace1 + c40ae9d commit fd46d8b
Showing 24 changed files with 857 additions and 104 deletions.
6 changes: 3 additions & 3 deletions artiq/coredevice/ttl.py
Original file line number Diff line number Diff line change
@@ -177,7 +177,7 @@ def gate_falling(self, duration):
self._set_sensitivity(0)

@kernel
def gate_both_mu(self, duration):
def gate_both(self, duration):
"""Register both rising and falling edge events for the specified
duration (in seconds)."""
self._set_sensitivity(3)
@@ -196,8 +196,8 @@ def count(self):

@kernel
def timestamp_mu(self):
"""Poll the RTIO input and returns an event timestamp, according to
the gating.
"""Poll the RTIO input and returns an event timestamp (in machine
units), according to the gating.
If the gate is permanently closed, returns a negative value.
"""
21 changes: 13 additions & 8 deletions artiq/gateware/rtio/core.py
Original file line number Diff line number Diff line change
@@ -118,8 +118,10 @@ def __init__(self, interface, counter, fifo_depth, guard_io_cycles):
sequence_error = Signal()
nop = Signal()
self.sync.rsys += [
replace.eq(self.ev.timestamp == buf.timestamp[fine_ts_width:]),
sequence_error.eq(self.ev.timestamp < buf.timestamp[fine_ts_width:])
replace.eq(self.ev.timestamp[fine_ts_width:] \
== buf.timestamp[fine_ts_width:]),
sequence_error.eq(self.ev.timestamp[fine_ts_width:] \
< buf.timestamp[fine_ts_width:])
]
if interface.suppress_nop:
# disable NOP at reset: do not suppress a first write with all 0s
@@ -300,8 +302,7 @@ def __init__(self, chan_sel_width,


class RTIO(Module):
def __init__(self, channels, clk_freq, full_ts_width=63,
guard_io_cycles=20):
def __init__(self, channels, full_ts_width=63, guard_io_cycles=20):
data_width = max(rtlink.get_data_width(c.interface)
for c in channels)
address_width = max(rtlink.get_address_width(c.interface)
@@ -329,11 +330,15 @@ def __init__(self, channels, clk_freq, full_ts_width=63,
self.cd_rsys.rst.eq(self.kcsrs.reset.storage)
]
self.comb += self.cd_rio.clk.eq(ClockSignal("rtio"))
self.specials += AsyncResetSynchronizer(self.cd_rio,
self.kcsrs.reset.storage)
self.specials += AsyncResetSynchronizer(
self.cd_rio,
self.kcsrs.reset.storage | ResetSignal("rtio",
allow_reset_less=True))
self.comb += self.cd_rio_phy.clk.eq(ClockSignal("rtio"))
self.specials += AsyncResetSynchronizer(self.cd_rio_phy,
self.kcsrs.reset_phy.storage)
self.specials += AsyncResetSynchronizer(
self.cd_rio_phy,
self.kcsrs.reset_phy.storage | ResetSignal("rtio",
allow_reset_less=True))

# Managers
self.submodules.counter = _RTIOCounter(full_ts_width - fine_ts_width)
70 changes: 70 additions & 0 deletions artiq/gateware/rtio/phy/ttl_serdes_7series.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from migen.fhdl.std import *

from artiq.gateware.rtio.phy import ttl_serdes_generic


class _OSERDESE2_8X(Module):
def __init__(self, pad):
self.o = Signal(8)
self.t_in = Signal()
self.t_out = Signal()

# # #

o = self.o
self.specials += Instance("OSERDESE2",
p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
o_OQ=pad, o_TQ=self.t_out,
i_CLK=ClockSignal("rtiox4"),
i_CLKDIV=ClockSignal("rio_phy"),
i_D1=o[0], i_D2=o[1], i_D3=o[2], i_D4=o[3],
i_D5=o[4], i_D6=o[5], i_D7=o[6], i_D8=o[7],
i_TCE=1, i_OCE=1, i_RST=0,
i_T1=self.t_in)


class _IOSERDESE2_8X(Module):
def __init__(self, pad):
self.o = Signal(8)
self.i = Signal(8)
self.oe = Signal()

# # #

pad_i = Signal()
pad_o = Signal()
i = self.i
self.specials += Instance("ISERDESE2", p_DATA_RATE="DDR",
p_DATA_WIDTH=8,
p_INTERFACE_TYPE="NETWORKING", p_NUM_CE=1,
o_Q1=i[7], o_Q2=i[6], o_Q3=i[5], o_Q4=i[4],
o_Q5=i[3], o_Q6=i[2], o_Q7=i[1], o_Q8=i[0],
i_D=pad_i,
i_CLK=ClockSignal("rtiox4"),
i_CLKB=~ClockSignal("rtiox4"),
i_CE1=1, i_RST=0,
i_CLKDIV=ClockSignal("rio_phy"))
oserdes = _OSERDESE2_8X(pad_o)
self.submodules += oserdes
self.specials += Instance("IOBUF",
i_I=pad_o, o_O=pad_i, i_T=oserdes.t_out,
io_IO=pad)
self.comb += [
oserdes.t_in.eq(~self.oe),
oserdes.o.eq(self.o)
]


class Output_8X(ttl_serdes_generic.Output):
def __init__(self, pad):
serdes = _OSERDESE2_8X(pad)
self.submodules += serdes
ttl_serdes_generic.Output.__init__(self, serdes)


class Inout_8X(ttl_serdes_generic.Inout):
def __init__(self, pad):
serdes = _IOSERDESE2_8X(pad)
self.submodules += serdes
ttl_serdes_generic.Inout.__init__(self, serdes)
273 changes: 273 additions & 0 deletions artiq/gateware/rtio/phy/ttl_serdes_generic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
from migen.fhdl.std import *
from migen.genlib.coding import PriorityEncoder

from artiq.gateware.rtio import rtlink


def _mk_edges(w, direction):
l = [(1 << i) - 1 for i in range(w)]
if direction == "rising":
l = [2**w - 1 ^ x for x in l]
elif direction == "falling":
pass
else:
raise ValueError
return l


class _SerdesDriver(Module):
def __init__(self, serdes_o, stb, data, fine_ts, override_en, override_o):
previous_data = Signal()
serdes_width = flen(serdes_o)
edges = Array(_mk_edges(serdes_width, "rising"))
edges_n = Array(_mk_edges(serdes_width, "falling"))
self.sync.rio_phy += [
If(stb, previous_data.eq(data)),
If(override_en,
serdes_o.eq(Replicate(override_o, serdes_width))
).Else(
If(stb & ~previous_data & data,
serdes_o.eq(edges[fine_ts]),
).Elif(stb & previous_data & ~data,
serdes_o.eq(edges_n[fine_ts]),
).Else(
serdes_o.eq(Replicate(previous_data, serdes_width)),
)
)
]


class Output(Module):
def __init__(self, serdes):
self.rtlink = rtlink.Interface(
rtlink.OInterface(1, fine_ts_width=log2_int(flen(serdes.o))))
self.probes = [serdes.o[-1]]
override_en = Signal()
override_o = Signal()
self.overrides = [override_en, override_o]

# # #

self.submodules += _SerdesDriver(
serdes.o,
self.rtlink.o.stb, self.rtlink.o.data, self.rtlink.o.fine_ts,
override_en, override_o)


class Inout(Module):
def __init__(self, serdes):
serdes_width = flen(serdes.o)
assert flen(serdes.i) == serdes_width
self.rtlink = rtlink.Interface(
rtlink.OInterface(2, 2, fine_ts_width=log2_int(serdes_width)),
rtlink.IInterface(1, fine_ts_width=log2_int(serdes_width)))
self.probes = [serdes.i[-1], serdes.oe]
override_en = Signal()
override_o = Signal()
override_oe = Signal()
self.overrides = [override_en, override_o, override_oe]

# # #

# Output
self.submodules += _SerdesDriver(
serdes_o=serdes.o,
stb=self.rtlink.o.stb & (self.rtlink.o.address == 0),
data=self.rtlink.o.data[0],
fine_ts=self.rtlink.o.fine_ts,
override_en=override_en, override_o=override_o)

oe_k = Signal()
self.sync.rio_phy += [
If(self.rtlink.o.stb & (self.rtlink.o.address == 1),
oe_k.eq(self.rtlink.o.data[0])),
If(override_en,
serdes.oe.eq(override_oe)
).Else(
serdes.oe.eq(oe_k)
)
]

# Input
sensitivity = Signal(2)
self.sync.rio += If(self.rtlink.o.stb & (self.rtlink.o.address == 2),
sensitivity.eq(self.rtlink.o.data))

i = serdes.i[-1]
i_d = Signal()
self.sync.rio_phy += [
i_d.eq(i),
self.rtlink.i.stb.eq(
(sensitivity[0] & ( i & ~i_d)) |
(sensitivity[1] & (~i & i_d))
),
self.rtlink.i.data.eq(i),
]

pe = PriorityEncoder(serdes_width)
self.submodules += pe
self.comb += pe.i.eq(serdes.i ^ Replicate(i_d, serdes_width))
self.sync.rio_phy += self.rtlink.i.fine_ts.eq(pe.o)


class _FakeSerdes(Module):
def __init__(self):
self.o = Signal(8)
self.i = Signal(8)
self.oe = Signal()


class _OutputTB(Module):
def __init__(self):
serdes = _FakeSerdes()
self.submodules.dut = RenameClockDomains(Output(serdes),
{"rio_phy": "sys"})

def gen_simulation(self, selfp):
selfp.dut.rtlink.o.data = 1
selfp.dut.rtlink.o.fine_ts = 1
selfp.dut.rtlink.o.stb = 1
yield
selfp.dut.rtlink.o.stb = 0
yield
selfp.dut.rtlink.o.data = 0
selfp.dut.rtlink.o.fine_ts = 2
selfp.dut.rtlink.o.stb = 1
yield
yield
selfp.dut.rtlink.o.data = 1
selfp.dut.rtlink.o.fine_ts = 7
selfp.dut.rtlink.o.stb = 1
for _ in range(6):
# note that stb stays active; output should not change
yield


class _InoutTB(Module):
def __init__(self):
self.serdes = _FakeSerdes()
self.submodules.dut = RenameClockDomains(Inout(self.serdes),
{"rio_phy": "sys",
"rio": "sys"})

def check_input(self, selfp, stb, fine_ts=None):
if stb != selfp.dut.rtlink.i.stb:
print("KO rtlink.i.stb should be {} but is {}"
.format(stb, selfp.dut.rtlink.i.stb))
elif fine_ts is not None and fine_ts != selfp.dut.rtlink.i.fine_ts:
print("KO rtlink.i.fine_ts should be {} but is {}"
.format(fine_ts, selfp.dut.rtlink.i.fine_ts))
else:
print("OK")

def check_output(self, selfp, data):
if selfp.serdes.o != data:
print("KO io.o should be {} but is {}".format(data, selfp.serdes.o))
else:
print("OK")

def check_output_enable(self, selfp, oe):
if selfp.serdes.oe != oe:
print("KO io.oe should be {} but is {}".format(oe, selfp.serdes.oe))
else:
print("OK")

def gen_simulation(self, selfp):
selfp.dut.rtlink.o.address = 2
selfp.dut.rtlink.o.data = 0b11
selfp.dut.rtlink.o.stb = 1 # set sensitivity to rising + falling
yield
selfp.dut.rtlink.o.stb = 0

self.check_output_enable(selfp, 0)
yield

selfp.serdes.i = 0b11111110 # rising edge at fine_ts = 1
yield
selfp.serdes.i = 0b11111111
yield
self.check_input(selfp, stb=1, fine_ts=1)

selfp.serdes.i = 0b01111111 # falling edge at fine_ts = 7
yield
selfp.serdes.i = 0b00000000
yield
self.check_input(selfp, stb=1, fine_ts=7)

selfp.serdes.i = 0b11000000 # rising edge at fine_ts = 6
yield
selfp.serdes.i = 0b11111111
yield
self.check_input(selfp, stb=1, fine_ts=6)

selfp.dut.rtlink.o.address = 2
selfp.dut.rtlink.o.data = 0b11
selfp.dut.rtlink.o.stb = 1 # set sensitivity to rising only
yield
selfp.dut.rtlink.o.stb = 0
yield

selfp.serdes.i = 0b00001111 # falling edge at fine_ts = 4
yield
self.check_input(selfp, stb=0) # no strobe, sensitivity is rising edge

selfp.serdes.i = 0b11110000 # rising edge at fine_ts = 4
yield
self.check_input(selfp, stb=1, fine_ts=4)

selfp.dut.rtlink.o.address = 1
selfp.dut.rtlink.o.data = 1
selfp.dut.rtlink.o.stb = 1 # set Output Enable to 1
yield
selfp.dut.rtlink.o.stb = 0
yield
yield
self.check_output_enable(selfp, 1)

selfp.dut.rtlink.o.address = 0
selfp.dut.rtlink.o.data = 1
selfp.dut.rtlink.o.fine_ts = 3
selfp.dut.rtlink.o.stb = 1 # rising edge at fine_ts = 3
yield
selfp.dut.rtlink.o.stb = 0
yield
self.check_output(selfp, data=0b11111000)

yield
self.check_output(selfp, data=0xFF) # stays at 1

selfp.dut.rtlink.o.data = 0
selfp.dut.rtlink.o.fine_ts = 0
selfp.dut.rtlink.o.stb = 1 # falling edge at fine_ts = 0
yield
selfp.dut.rtlink.o.stb = 0
yield
self.check_output(selfp, data=0)

yield
self.check_output(selfp, data=0)

selfp.dut.rtlink.o.data = 1
selfp.dut.rtlink.o.fine_ts = 7
selfp.dut.rtlink.o.stb = 1 # rising edge at fine_ts = 7
yield
selfp.dut.rtlink.o.stb = 0
yield
self.check_output(selfp, data=0b10000000)


if __name__ == "__main__":
import sys
from migen.sim.generic import Simulator, TopLevel

if len(sys.argv) != 2:
print("Incorrect command line")
sys.exit(1)

cls = {
"output": _OutputTB,
"inout": _InoutTB
}[sys.argv[1]]

with Simulator(cls(), TopLevel("top.vcd", clk_period=int(1/0.125))) as s:
s.run()
154 changes: 154 additions & 0 deletions artiq/gateware/rtio/phy/ttl_serdes_spartan6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
from migen.fhdl.std import *

from artiq.gateware.rtio.phy import ttl_serdes_generic


class _OSERDES2_8X(Module):
def __init__(self, pad, stb):
self.o = Signal(8)
self.t_in = Signal()
self.t_out = Signal()

# # #

cascade = Signal(4)
o = self.o
common = dict(p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
p_DATA_WIDTH=8, p_OUTPUT_MODE="SINGLE_ENDED", i_TRAIN=0,
i_CLK0=ClockSignal("rtiox8"), i_CLK1=0,
i_CLKDIV=ClockSignal("rio_phy"),
i_IOCE=stb, i_OCE=1, i_TCE=1, i_RST=0,
i_T4=self.t_in, i_T3=self.t_in,
i_T2=self.t_in, i_T1=self.t_in)

self.specials += [
Instance("OSERDES2", p_SERDES_MODE="MASTER",
i_D4=o[7], i_D3=o[6], i_D2=o[5], i_D1=o[4],
i_SHIFTIN1=1, i_SHIFTIN2=1,
i_SHIFTIN3=cascade[2], i_SHIFTIN4=cascade[3],
o_SHIFTOUT1=cascade[0], o_SHIFTOUT2=cascade[1],
o_OQ=pad, o_TQ=self.t_out, **common),
Instance("OSERDES2", p_SERDES_MODE="SLAVE",
i_D4=o[3], i_D3=o[2], i_D2=o[1], i_D1=o[0],
i_SHIFTIN1=cascade[0], i_SHIFTIN2=cascade[1],
i_SHIFTIN3=1, i_SHIFTIN4=1,
o_SHIFTOUT3=cascade[2], o_SHIFTOUT4=cascade[3],
**common),
]


class _IOSERDES2_8X(Module):
def __init__(self, pad, stb):
self.o = Signal(8)
self.i = Signal(8)
self.oe = Signal()

# # #

pad_i = Signal()
pad_o = Signal()
cascade = Signal()
i = self.i
common = dict(p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR",
p_DATA_WIDTH=8, p_INTERFACE_TYPE="RETIMED",
i_BITSLIP=0, i_CE0=1, i_IOCE=stb,
i_RST=0, i_CLK0=ClockSignal("rtiox8"), i_CLK1=0,
i_CLKDIV=ClockSignal("rio_phy"))
self.specials += [
Instance("ISERDES2", p_SERDES_MODE="MASTER",
o_Q4=i[7], o_Q3=i[6], o_Q2=i[5], o_Q1=i[4],
o_SHIFTOUT=cascade, i_D=pad_i, i_SHIFTIN=0,
**common),
Instance("ISERDES2", p_SERDES_MODE="SLAVE",
o_Q4=i[3], o_Q3=i[2], o_Q2=i[1], o_Q1=i[0],
i_D=0, i_SHIFTIN=cascade, **common),
]

oserdes = _OSERDES2_8X(pad_o, stb)
self.submodules += oserdes
self.specials += Instance("IOBUF",
i_I=pad_o, o_O=pad_i, i_T=oserdes.t_out,
io_IO=pad)
self.comb += [
oserdes.t_in.eq(~self.oe),
oserdes.o.eq(self.o),
]


class Output_8X(ttl_serdes_generic.Output):
def __init__(self, pad, stb):
serdes = _OSERDES2_8X(pad, stb)
self.submodules += serdes
ttl_serdes_generic.Output.__init__(self, serdes)


class Inout_8X(ttl_serdes_generic.Inout):
def __init__(self, pad, stb):
serdes = _IOSERDES2_8X(pad, stb)
self.submodules += serdes
ttl_serdes_generic.Inout.__init__(self, serdes)


class _OSERDES2_4X(Module):
def __init__(self, pad, stb):
self.o = Signal(4)
self.t_in = Signal()
self.t_out = Signal()

# # #

o = self.o
self.specials += Instance("OSERDES2", p_SERDES_MODE="NONE",
p_DATA_RATE_OQ="SDR", p_DATA_RATE_OT="SDR",
p_DATA_WIDTH=4, p_OUTPUT_MODE="SINGLE_ENDED",
i_TRAIN=0, i_CLK0=ClockSignal("rtiox4"),
i_CLK1=0, i_CLKDIV=ClockSignal("rio_phy"),
i_IOCE=stb, i_OCE=1, i_TCE=1, i_RST=0,
i_T4=self.t_in, i_T3=self.t_in,
i_T2=self.t_in, i_T1=self.t_in,
i_D4=o[3], i_D3=o[2], i_D2=o[1], i_D1=o[0],
o_OQ=pad, o_TQ=self.t_out)


class _IOSERDES2_4X(Module):
def __init__(self, pad, stb):
self.o = Signal(4)
self.i = Signal(4)
self.oe = Signal()

# # #

pad_i = Signal()
pad_o = Signal()
i = self.i
self.specials += Instance("ISERDES2", p_SERDES_MODE="NONE",
p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR",
p_DATA_WIDTH=4, p_INTERFACE_TYPE="RETIMED",
i_BITSLIP=0, i_CE0=1, i_IOCE=stb,
i_RST=0, i_CLK0=ClockSignal("rtiox4"),
i_CLK1=0, i_CLKDIV=ClockSignal("rio_phy"),
o_Q4=i[3], o_Q3=i[2], o_Q2=i[1], o_Q1=i[0],
i_D=pad_i, i_SHIFTIN=0)
oserdes = _OSERDES2_4X(pad_o, stb)
self.submodules += oserdes
self.specials += Instance("IOBUF",
i_I=pad_o, o_O=pad_i, i_T=oserdes.t_out,
io_IO=pad)
self.comb += [
oserdes.t_in.eq(~self.oe),
oserdes.o.eq(self.o),
]


class Output_4X(ttl_serdes_generic.Output):
def __init__(self, pad, stb):
serdes = _OSERDES2_4X(pad, stb)
self.submodules += serdes
ttl_serdes_generic.Output.__init__(self, serdes)


class Inout_4X(ttl_serdes_generic.Inout):
def __init__(self, pad, stb):
serdes = _IOSERDES2_4X(pad, stb)
self.submodules += serdes
ttl_serdes_generic.Inout.__init__(self, serdes)
2 changes: 1 addition & 1 deletion artiq/test/coredevice.py
Original file line number Diff line number Diff line change
@@ -120,7 +120,7 @@ def set_count(self, count):
@kernel
def run(self):
self.ttl_inout.output()
delay(1*us)
delay(5*us)
with parallel:
self.ttl_inout.gate_rising(10*us)
with sequential:
8 changes: 3 additions & 5 deletions doc/manual/installing.rst
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
::

$ cd ~/artiq-dev
$ svn co https://xc3sprog.svn.sourceforge.net/svnroot/xc3sprog/trunk xc3sprog
$ svn co http://svn.code.sf.net/p/xc3sprog/code/trunk xc3sprog
$ cd xc3sprog
$ cmake . && make
$ sudo make install
@@ -299,16 +299,14 @@ Installing the host-side software
* Install the llvmlite Python bindings: ::

$ cd ~/artiq-dev
$ git clone https://github.com/numba/llvmlite
$ git clone https://github.com/m-labs/llvmlite
$ git checkout backport-3.5
$ cd llvmlite
$ patch -p1 < ~/artiq-dev/artiq/misc/llvmlite-add-all-targets.patch
$ patch -p1 < ~/artiq-dev/artiq/misc/llvmlite-rename.patch
$ patch -p1 < ~/artiq-dev/artiq/misc/llvmlite-build-as-debug-on-windows.patch
$ LLVM_CONFIG=/usr/local/llvm-or1k/bin/llvm-config python3 setup.py install --user

.. note::
llvmlite is in development and its API is not stable yet. Commit ID ``11a8303d02e3d6dd2d1e0e9065701795cd8a979f`` is known to work.

* Install ARTIQ: ::

$ cd ~/artiq-dev
5 changes: 4 additions & 1 deletion examples/master/ddb.pyon
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
"type": "local",
"module": "artiq.coredevice.core",
"class": "Core",
"arguments": {}
"arguments": {"ref_period": 1e-9}
},

"pmt0": {
@@ -133,6 +133,9 @@
"command": "lda_controller -p {port} --bind {bind}"
},

"ttl_inout": "pmt0",
"ttl_out": "ttl0",

"pmt": "pmt0",
"bd_dds": "dds0",
"bd_sw": "ttl0",
71 changes: 71 additions & 0 deletions examples/master/repository/tdr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from artiq import *


class PulseNotReceivedError(Exception):
pass


class TDR(EnvExperiment):
"""Time domain reflectometer.
From ttl2 an impedance matched pulse is send onto a coax
cable with an open end. pmt0 (very short stub, high impedance) also
listens on the transmission line near ttl2.
When the forward propagating pulse passes pmt0, the voltage is half of the
logic voltage and does not register as a rising edge. Once the
rising edge is reflected at an open end (same sign) and passes by pmt0 on
its way back to ttl2, it is detected. Analogously, hysteresis leads to
detection of the falling edge once the reflection reaches pmt0 after
one round trip time.
This works marginally and is just a proof of principle: it relies on
hysteresis at FPGA inputs around half voltage and good impedance steps,
as well as reasonably low loss cable. It does not work well for longer
cables (>100 ns RTT). The default drive strength of 12 mA and 3.3 V would
be ~300 Ω but it seems 40 Ω series impedance at the output matches
the hysteresis of the input.
This is also equivalent to a loopback tester or a delay measurement.
"""
def build(self):
self.attr_device("core")
self.attr_device("pmt0")
self.attr_device("ttl2")

def run(self):
n = 1000 # repetitions
latency = 50e-9 # calibrated latency without a transmission line
pulse = 1e-6 # pulse length, larger than rtt
try:
self.many(n, seconds_to_mu(pulse, self.core))
except PulseNotReceivedError:
print("to few edges: cable too long or wiring bad")
else:
print(self.t)
t_rise = mu_to_seconds(self.t[0], self.core)/n - latency
t_fall = mu_to_seconds(self.t[1], self.core)/n - latency - pulse
print("round trip times:")
print("rising: {:5g} ns, falling {:5g} ns".format(
t_rise/1e-9, t_fall/1e-9))

@kernel
def many(self, n, p):
t = [0 for i in range(2)]
self.core.break_realtime()
for i in range(n):
self.one(t, p)
self.t = t

@kernel
def one(self, t, p):
t0 = now_mu()
with parallel:
self.pmt0.gate_both_mu(2*p)
self.ttl2.pulse_mu(p)
for i in range(len(t)):
ti = self.pmt0.timestamp_mu()
if ti <= 0:
raise PulseNotReceivedError
t[i] += ti - t0
self.pmt0.count() # flush
2 changes: 1 addition & 1 deletion soc/runtime/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include $(MSCDIR)/software/common.mak

OBJECTS := isr.o flash_storage.o clock.o elf_loader.o services.o session.o log.o test_mode.o kloader.o bridge_ctl.o mailbox.o ksupport_data.o kserver.o moninj.o main.o
OBJECTS := isr.o flash_storage.o clock.o rtiocrg.o elf_loader.o services.o session.o log.o test_mode.o kloader.o bridge_ctl.o mailbox.o ksupport_data.o kserver.o moninj.o main.o
OBJECTS_KSUPPORT := ksupport.o exception_jmp.o exceptions.o mailbox.o bridge.o rtio.o ttl.o dds.o

CFLAGS += -Ilwip/src/include -Iliblwip
8 changes: 5 additions & 3 deletions soc/runtime/bridge.c
Original file line number Diff line number Diff line change
@@ -5,12 +5,14 @@
#include "dds.h"
#include "bridge.h"

#define TIME_BUFFER (8000 << RTIO_FINE_TS_WIDTH)

static void dds_write(int addr, int data)
{
rtio_chan_sel_write(RTIO_DDS_CHANNEL);
rtio_o_address_write(addr);
rtio_o_data_write(data);
rtio_o_timestamp_write(rtio_get_counter() + 8000);
rtio_o_timestamp_write(rtio_get_counter() + TIME_BUFFER);
rtio_o_we_write(1);
}

@@ -46,15 +48,15 @@ void bridge_main(void)
struct msg_brg_ttl_out *msg;

msg = (struct msg_brg_ttl_out *)umsg;
ttl_set_oe(rtio_get_counter() + 8000, msg->channel, msg->value);
ttl_set_oe(rtio_get_counter() + TIME_BUFFER, msg->channel, msg->value);
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_BRG_TTL_O: {
struct msg_brg_ttl_out *msg;

msg = (struct msg_brg_ttl_out *)umsg;
ttl_set_o(rtio_get_counter() + 8000, msg->channel, msg->value);
ttl_set_o(rtio_get_counter() + TIME_BUFFER, msg->channel, msg->value);
mailbox_acknowledge();
break;
}
10 changes: 10 additions & 0 deletions soc/runtime/clock.c
Original file line number Diff line number Diff line change
@@ -26,6 +26,16 @@ long long int clock_get_ms(void)
return clock_ms;
}

void busywait_us(long long int us)
{
long long int threshold;

timer0_update_value_write(1);
threshold = timer0_value_read() - us*(long long int)identifier_frequency_read()/1000000LL;
while(timer0_value_read() > threshold)
timer0_update_value_write(1);
}

struct watchdog {
int active;
long long int threshold;
1 change: 1 addition & 0 deletions soc/runtime/clock.h
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@

void clock_init(void);
long long int clock_get_ms(void);
void busywait_us(long long us);

#define MAX_WATCHDOGS 16

2 changes: 1 addition & 1 deletion soc/runtime/kloader.h
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
#define __KLOADER_H

#define KERNELCPU_EXEC_ADDRESS 0x40400000
#define KERNELCPU_PAYLOAD_ADDRESS 0x40404000
#define KERNELCPU_PAYLOAD_ADDRESS 0x40408000

extern long long int now;

2 changes: 1 addition & 1 deletion soc/runtime/ksupport.c
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ long long int now_init(void)

if(now < 0) {
rtio_init();
now = rtio_get_counter() + 125000;
now = rtio_get_counter() + (125000 << RTIO_FINE_TS_WIDTH);
}

return now;
15 changes: 2 additions & 13 deletions soc/runtime/ksupport.ld
Original file line number Diff line number Diff line change
@@ -4,10 +4,10 @@ ENTRY(_start)
INCLUDE generated/regions.ld

/* First 4M of main memory are reserved for runtime code/data
* then comes kernel memory. First 16K of kernel memory are for support code.
* then comes kernel memory. First 32K of kernel memory are for support code.
*/
MEMORY {
ksupport : ORIGIN = 0x40400000, LENGTH = 0x4000
ksupport : ORIGIN = 0x40400000, LENGTH = 0x8000
}

/* On AMP systems, kernel stack is at the end of main RAM,
@@ -24,17 +24,6 @@ SECTIONS
_etext = .;
} > ksupport

.got :
{
_GLOBAL_OFFSET_TABLE_ = .;
*(.got)
} > ksupport

.got.plt :
{
*(.got.plt)
} > ksupport

.rodata :
{
. = ALIGN(4);
1 change: 0 additions & 1 deletion soc/runtime/liblwip/Makefile
Original file line number Diff line number Diff line change
@@ -53,4 +53,3 @@ clean:

liblwip.a: $(LWIPOBJS)
$(AR) clr liblwip.a $(LWIPOBJS)
$(RANLIB) liblwip.a
11 changes: 0 additions & 11 deletions soc/runtime/linker.ld
Original file line number Diff line number Diff line change
@@ -26,17 +26,6 @@ SECTIONS
_etext = .;
} > runtime

.got :
{
_GLOBAL_OFFSET_TABLE_ = .;
*(.got)
} > runtime

.got.plt :
{
*(.got.plt)
} > runtime

.rodata :
{
. = ALIGN(4);
2 changes: 2 additions & 0 deletions soc/runtime/main.c
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@
#include "kloader.h"
#include "flash_storage.h"
#include "clock.h"
#include "rtiocrg.h"
#include "test_mode.h"
#include "kserver.h"
#include "session.h"
@@ -250,6 +251,7 @@ int main(void)
puts("ARTIQ runtime built "__DATE__" "__TIME__"\n");

clock_init();
rtiocrg_init();
puts("Press 't' to enter test mode...");
blink_led();

67 changes: 67 additions & 0 deletions soc/runtime/rtiocrg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <stdio.h>
#include <generated/csr.h>

#include "clock.h"
#include "flash_storage.h"
#include "rtiocrg.h"

void rtiocrg_init(void)
{
char b;
int clk;

#ifdef CSR_RTIO_CRG_PLL_RESET_ADDR
rtio_crg_pll_reset_write(0);
#endif
b = 'i';
clk = 0;
fs_read("startup_clock", &b, 1, NULL);
if(b == 'i')
printf("Startup RTIO clock: internal\n");
else if(b == 'e') {
printf("Startup RTIO clock: external\n");
clk = 1;
} else
printf("WARNING: unknown startup_clock entry in flash storage\n");

if(!rtiocrg_switch_clock(clk)) {
printf("WARNING: startup RTIO clock failed\n");
printf("WARNING: this may cause the system initialization to fail\n");
printf("WARNING: fix clocking and reset the device\n");
}
}

int rtiocrg_check(void)
{
#ifdef CSR_RTIO_CRG_PLL_RESET_ADDR
return rtio_crg_pll_locked_read();
#else
return 1;
#endif
}

int rtiocrg_switch_clock(int clk)
{
int current_clk;

current_clk = rtio_crg_clock_sel_read();
if(clk == current_clk) {
#ifdef CSR_RTIO_CRG_PLL_RESET_ADDR
busywait_us(150);
if(!rtio_crg_pll_locked_read())
return 0;
#endif
return 1;
}
#ifdef CSR_RTIO_CRG_PLL_RESET_ADDR
rtio_crg_pll_reset_write(1);
#endif
rtio_crg_clock_sel_write(clk);
#ifdef CSR_RTIO_CRG_PLL_RESET_ADDR
rtio_crg_pll_reset_write(0);
busywait_us(150);
if(!rtio_crg_pll_locked_read())
return 0;
#endif
return 1;
}
8 changes: 8 additions & 0 deletions soc/runtime/rtiocrg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef __RTIOCRG_H
#define __RTIOCRG_H

void rtiocrg_init(void);
int rtiocrg_check(void);
int rtiocrg_switch_clock(int clk);

#endif /* __RTIOCRG_H */
22 changes: 16 additions & 6 deletions soc/runtime/session.c
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
#include "kloader.h"
#include "exceptions.h"
#include "flash_storage.h"
#include "rtiocrg.h"
#include "session.h"

#define BUFFER_IN_SIZE (1024*1024)
@@ -154,8 +155,10 @@ static int process_input(void)
submit_output(9);
break;
}
rtio_crg_clock_sel_write(buffer_in[9]);
buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_COMPLETED;
if(rtiocrg_switch_clock(buffer_in[9]))
buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_COMPLETED;
else
buffer_out[8] = REMOTEMSG_TYPE_CLOCK_SWITCH_FAILED;
submit_output(9);
break;
case REMOTEMSG_TYPE_LOAD_OBJECT:
@@ -527,10 +530,17 @@ void session_poll(void **data, int *len)
{
int l;

if((user_kernel_state == USER_KERNEL_RUNNING) && watchdog_expired()) {
log("Watchdog expired");
*len = -1;
return;
if(user_kernel_state == USER_KERNEL_RUNNING) {
if(watchdog_expired()) {
log("Watchdog expired");
*len = -1;
return;
}
if(!rtiocrg_check()) {
log("RTIO clock failure");
*len = -1;
return;
}
}

l = get_out_packet_len();
76 changes: 62 additions & 14 deletions soc/targets/artiq_kc705.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from migen.fhdl.std import *
from migen.genlib.resetsync import AsyncResetSynchronizer
from migen.genlib.cdc import MultiReg
from migen.bank.description import *
from migen.bank import wbgen
from mibuild.generic_platform import *
from mibuild.xilinx.vivado import XilinxVivadoToolchain
from mibuild.xilinx.ise import XilinxISEToolchain

from misoclib.com import gpio
from misoclib.soc import mem_decoder
@@ -11,25 +14,63 @@

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


class _RTIOCRG(Module, AutoCSR):
def __init__(self, platform, rtio_internal_clk):
self._clock_sel = CSRStorage()
self.clock_domains.cd_rtio = ClockDomain(reset_less=True)
self._pll_reset = CSRStorage(reset=1)
self._pll_locked = CSRStatus()
self.clock_domains.cd_rtio = ClockDomain()
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)

# 10 MHz when using 125MHz input
self.clock_domains.cd_ext_clkout = ClockDomain(reset_less=True)
ext_clkout = platform.request("user_sma_gpio_p")
self.sync.ext_clkout += ext_clkout.eq(~ext_clkout)


rtio_external_clk = Signal()
user_sma_clock = platform.request("user_sma_clock")
platform.add_period_constraint(user_sma_clock.p, 8.0)
self.specials += Instance("IBUFDS",
i_I=user_sma_clock.p, i_IB=user_sma_clock.n,
o_O=rtio_external_clk)
self.specials += Instance("BUFGMUX",
i_I0=rtio_internal_clk,
i_I1=rtio_external_clk,
i_S=self._clock_sel.storage,
o_O=self.cd_rtio.clk)

pll_locked = Signal()
rtio_clk = Signal()
rtiox4_clk = Signal()
ext_clkout_clk = Signal()
self.specials += [
Instance("PLLE2_ADV",
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,

p_REF_JITTER1=0.01,
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
i_CLKIN1=rtio_internal_clk, i_CLKIN2=rtio_external_clk,
# Warning: CLKINSEL=0 means CLKIN2 is selected
i_CLKINSEL=~self._clock_sel.storage,

# VCO @ 1GHz when using 125MHz input
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
i_CLKFBIN=self.cd_rtio.clk,
i_RST=self._pll_reset.storage,

o_CLKFBOUT=rtio_clk,

p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
o_CLKOUT0=rtiox4_clk,

p_CLKOUT1_DIVIDE=50, p_CLKOUT1_PHASE=0.0,
o_CLKOUT1=ext_clkout_clk),
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
Instance("BUFG", i_I=ext_clkout_clk, o_O=self.cd_ext_clkout.clk),

AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
MultiReg(pll_locked, self._pll_locked.status)
]


class _NIST_QCx(MiniSoC, AMPSoC):
@@ -57,10 +98,10 @@ def __init__(self, platform, cpu_type="or1k", **kwargs):
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.submodules.rtio_crg = _RTIOCRG(self.platform, self.crg.cd_sys.clk)
self.submodules.rtio = rtio.RTIO(rtio_channels)
self.add_constant("RTIO_FINE_TS_WIDTH", self.rtio.fine_ts_width)
assert self.rtio.fine_ts_width <= 3
self.add_constant("DDS_RTIO_CLK_RATIO", 8 >> self.rtio.fine_ts_width)
self.submodules.rtio_moninj = rtio.MonInj(rtio_channels)

@@ -71,6 +112,13 @@ def add_rtio(self, rtio_channels):
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)
if isinstance(self.platform.toolchain, XilinxISEToolchain):
self.platform.add_platform_command("""
NET "sys_clk" TNM_NET = "GRPrsys_clk";
NET "{rio_clk}" TNM_NET = "GRPrio_clk";
TIMESPEC "TSfix_cdc1" = FROM "GRPrsys_clk" TO "GRPrio_clk" TIG;
TIMESPEC "TSfix_cdc2" = FROM "GRPrio_clk" TO "GRPrsys_clk" TIG;
""", rio_clk=self.rtio_crg.cd_rtio.clk)

rtio_csrs = self.rtio.get_csrs()
self.submodules.rtiowb = wbgen.Bank(rtio_csrs)
@@ -92,11 +140,11 @@ def __init__(self, platform, cpu_type="or1k", **kwargs):

rtio_channels = []
for i in range(2):
phy = ttl_simple.Inout(platform.request("pmt", i))
phy = ttl_serdes_7series.Inout_8X(platform.request("pmt", i))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512))
for i in range(15):
phy = ttl_simple.Output(platform.request("ttl", i))
phy = ttl_serdes_7series.Output_8X(platform.request("ttl", i))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))

@@ -131,11 +179,11 @@ def __init__(self, platform, cpu_type="or1k", **kwargs):
# TTL14 is for the clock generator
continue
if i % 4 == 3:
phy = ttl_simple.Inout(platform.request("ttl", i))
phy = ttl_serdes_7series.Inout_8X(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))
phy = ttl_serdes_7series.Output_8X(platform.request("ttl", i))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))

124 changes: 89 additions & 35 deletions soc/targets/artiq_pipistrello.py
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
from migen.fhdl.std import *
from migen.bank.description import *
from migen.bank import wbgen
from migen.genlib.resetsync import AsyncResetSynchronizer
from migen.genlib.cdc import MultiReg

from misoclib.com import gpio
from misoclib.soc import mem_decoder
@@ -11,46 +13,84 @@

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


class _RTIOCRG(Module, AutoCSR):
def __init__(self, platform, clk_freq):
self._clock_sel = CSRStorage()
self.clock_domains.cd_rtio = ClockDomain(reset_less=True)
self._pll_reset = CSRStorage(reset=1)
self._pll_locked = CSRStatus()

f = Fraction(125*1000*1000, clk_freq)
self.clock_domains.cd_rtio = ClockDomain()
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
self.clock_domains.cd_rtiox8 = ClockDomain(reset_less=True)
self.rtiox4_stb = Signal()
self.rtiox8_stb = Signal()

rtio_f = 125*1000*1000
f = Fraction(rtio_f, clk_freq)
rtio_internal_clk = Signal()
self.specials += Instance("DCM_CLKGEN",
p_CLKFXDV_DIVIDE=2,
p_CLKFX_DIVIDE=f.denominator,
p_CLKFX_MD_MAX=float(f),
p_CLKFX_MULTIPLY=f.numerator,
p_CLKIN_PERIOD=1e9/clk_freq,
p_SPREAD_SPECTRUM="NONE",
p_STARTUP_WAIT="FALSE",
i_CLKIN=ClockSignal(),
o_CLKFX=rtio_internal_clk,
i_FREEZEDCM=0,
i_RST=ResetSignal())

rtio_external_clk = platform.request("pmt", 2)
# ISE infers constraints for the internal clock
# and propagates them through the BUFGMUX. Adding this:
# platform.add_period_constraint(rtio_external_clk, 8.0)
# seems to confuse it
self.specials += Instance("BUFGMUX",
i_I0=rtio_internal_clk,
i_I1=rtio_external_clk,
i_S=self._clock_sel.storage,
o_O=self.cd_rtio.clk)
rtio_external_clk = Signal()
pmt2 = platform.request("pmt", 2)
dcm_locked = Signal()
rtio_clk = Signal()
pll_locked = Signal()
pll = Signal(3)
pll_fb = Signal()
self.specials += [
Instance("IBUFG", i_I=pmt2, o_O=rtio_external_clk),
Instance("DCM_CLKGEN", p_CLKFXDV_DIVIDE=2,
p_CLKFX_DIVIDE=f.denominator, p_CLKFX_MD_MAX=float(f),
p_CLKFX_MULTIPLY=f.numerator, p_CLKIN_PERIOD=1e9/clk_freq,
p_SPREAD_SPECTRUM="NONE", p_STARTUP_WAIT="FALSE",
i_CLKIN=ClockSignal(), o_CLKFX=rtio_internal_clk,
i_FREEZEDCM=0, i_RST=ResetSignal(), o_LOCKED=dcm_locked),
Instance("BUFGMUX",
i_I0=rtio_internal_clk, i_I1=rtio_external_clk,
i_S=self._clock_sel.storage, o_O=rtio_clk),
Instance("PLL_ADV", p_SIM_DEVICE="SPARTAN6",
p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="INTERNAL",
p_REF_JITTER=.01, p_CLK_FEEDBACK="CLKFBOUT",
i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0,
i_RST=self._pll_reset.storage | ~dcm_locked, i_REL=0,
p_DIVCLK_DIVIDE=1, p_CLKFBOUT_MULT=8,
p_CLKFBOUT_PHASE=0., i_CLKINSEL=1,
i_CLKIN1=rtio_clk, i_CLKIN2=0,
p_CLKIN1_PERIOD=1e9/rtio_f, p_CLKIN2_PERIOD=0.,
i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, o_LOCKED=pll_locked,
o_CLKOUT0=pll[0], p_CLKOUT0_DUTY_CYCLE=.5,
o_CLKOUT1=pll[1], p_CLKOUT1_DUTY_CYCLE=.5,
o_CLKOUT2=pll[2], p_CLKOUT2_DUTY_CYCLE=.5,
p_CLKOUT0_PHASE=0., p_CLKOUT0_DIVIDE=1,
p_CLKOUT1_PHASE=0., p_CLKOUT1_DIVIDE=2,
p_CLKOUT2_PHASE=0., p_CLKOUT2_DIVIDE=8),
Instance("BUFPLL", p_DIVIDE=8,
i_PLLIN=pll[0], i_GCLK=self.cd_rtio.clk,
i_LOCKED=pll_locked, o_IOCLK=self.cd_rtiox8.clk,
o_SERDESSTROBE=self.rtiox8_stb),
Instance("BUFPLL", p_DIVIDE=4,
i_PLLIN=pll[1], i_GCLK=self.cd_rtio.clk,
i_LOCKED=pll_locked, o_IOCLK=self.cd_rtiox4.clk,
o_SERDESSTROBE=self.rtiox4_stb),
Instance("BUFG", i_I=pll[2], o_O=self.cd_rtio.clk),
AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
MultiReg(pll_locked, self._pll_locked.status),
]

# ISE infers correct period constraints for cd_rtio.clk from
# the internal clock. The first two TIGs target just the BUFGMUX.
platform.add_platform_command("""
NET "{int_clk}" TNM_NET = "GRPint_clk";
NET "sys_clk" TNM_NET = "GRPsys_clk";
TIMESPEC "TSfix_ise1" = FROM "GRPint_clk" TO "GRPsys_clk" TIG;
NET "{ext_clk}" TNM_NET = "GRPext_clk";
TIMESPEC "TSfix_ise1" = FROM "GRPsys_clk" TO "GRPext_clk" TIG;
NET "{int_clk}" TNM_NET = "GRPint_clk";
TIMESPEC "TSfix_ise2" = FROM "GRPsys_clk" TO "GRPint_clk" TIG;
""", int_clk=rtio_internal_clk)
NET "{rtio_clk}" TNM_NET = "GRPrtio_clk";
TIMESPEC "TSfix_ise3" = FROM "GRPrtio_clk" TO "GRPsys_clk" TIG;
TIMESPEC "TSfix_ise4" = FROM "GRPsys_clk" TO "GRPrtio_clk" TIG;
""", ext_clk=rtio_external_clk, int_clk=rtio_internal_clk,
rtio_clk=self.cd_rtio.clk)


class NIST_QC1(BaseSoC, AMPSoC):
@@ -73,6 +113,7 @@ def __init__(self, platform, cpu_type="or1k", **kwargs):
sdram_controller_settings=MiniconSettings(l2_size=64*1024),
with_timer=False, **kwargs)
AMPSoC.__init__(self)
platform.toolchain.bitgen_opt = "-g Binary:Yes -w"
platform.toolchain.ise_commands += """
trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd {build_name}.pcf
"""
@@ -90,16 +131,29 @@ def __init__(self, platform, cpu_type="or1k", **kwargs):
platform.request("ttl_h_tx_en").eq(1)
]

self.submodules.rtio_crg = _RTIOCRG(platform, self.clk_freq)

# RTIO channels
rtio_channels = []
# pmt1 can run on a 8x serdes if pmt0 is not used
for i in range(2):
phy = ttl_simple.Inout(platform.request("pmt", i))
phy = ttl_serdes_spartan6.Inout_4X(platform.request("pmt", i),
self.rtio_crg.rtiox4_stb)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512,
ofifo_depth=4))

# ttl2 can run on a 8x serdes if xtrig is not used
for i in range(15):
phy = ttl_simple.Output(platform.request("ttl", i))
if i in (0, 1):
phy = ttl_serdes_spartan6.Output_4X(platform.request("ttl", i),
self.rtio_crg.rtiox4_stb)
elif i in (2,):
phy = ttl_serdes_spartan6.Output_8X(platform.request("ttl", i),
self.rtio_crg.rtiox8_stb)
else:
phy = ttl_simple.Output(platform.request("ttl", i))

self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy, ofifo_depth=256))

@@ -120,16 +174,16 @@ def __init__(self, platform, cpu_type="or1k", **kwargs):
self.add_constant("RTIO_DDS_CHANNEL", len(rtio_channels))
self.add_constant("DDS_CHANNEL_COUNT", 8)
self.add_constant("DDS_AD9858")
phy = dds.AD9858(platform.request("dds"), 8)
dds_pins = platform.request("dds")
self.comb += dds_pins.p.eq(0)
phy = dds.AD9858(dds_pins, 8)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy,
ofifo_depth=512,
ififo_depth=4))

# RTIO core
self.submodules.rtio_crg = _RTIOCRG(platform, self.clk_freq)
self.submodules.rtio = rtio.RTIO(rtio_channels,
clk_freq=125000000)
self.submodules.rtio = rtio.RTIO(rtio_channels)
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)

0 comments on commit fd46d8b

Please sign in to comment.