2018-04-23 18:35:42 +08:00
|
|
|
from migen import *
|
|
|
|
|
|
|
|
from artiq.gateware.rtio import rtlink
|
|
|
|
|
|
|
|
|
|
|
|
class RTServoCtrl(Module):
|
|
|
|
"""Per channel RTIO control interface"""
|
|
|
|
def __init__(self, ctrl):
|
|
|
|
self.rtlink = rtlink.Interface(
|
|
|
|
rtlink.OInterface(len(ctrl)))
|
|
|
|
|
|
|
|
# # #
|
|
|
|
|
|
|
|
self.sync.rio += [
|
|
|
|
If(self.rtlink.o.stb,
|
|
|
|
Cat(ctrl.profile, ctrl.en_out, ctrl.en_iir).eq(
|
|
|
|
self.rtlink.o.data),
|
|
|
|
)
|
|
|
|
]
|
|
|
|
self.comb += [
|
|
|
|
ctrl.stb.eq(self.rtlink.o.stb)
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
class RTServoMem(Module):
|
|
|
|
"""All-channel all-profile coefficient and state RTIO control
|
|
|
|
interface."""
|
|
|
|
def __init__(self, w, servo):
|
|
|
|
m_coeff = servo.m_coeff.get_port(write_capable=True,
|
|
|
|
we_granularity=w.coeff)
|
|
|
|
assert len(m_coeff.we) == 2
|
|
|
|
m_state = servo.m_state.get_port(write_capable=True)
|
|
|
|
self.specials += m_state, m_coeff
|
|
|
|
|
2018-04-23 23:15:52 +08:00
|
|
|
assert w.state >= w.coeff
|
|
|
|
assert len(m_coeff.dat_w) == 2*w.coeff
|
2018-04-23 18:35:42 +08:00
|
|
|
assert w.coeff >= w.word
|
|
|
|
|
|
|
|
self.rtlink = rtlink.Interface(
|
|
|
|
rtlink.OInterface(
|
2018-04-23 23:15:52 +08:00
|
|
|
w.state,
|
2018-04-23 18:35:42 +08:00
|
|
|
# coeff, profile, channel, 2 mems, rw
|
|
|
|
3 + w.profile + w.channel + 1 + 1,
|
|
|
|
enable_replace=False),
|
|
|
|
rtlink.IInterface(
|
2018-04-23 23:15:52 +08:00
|
|
|
w.state,
|
2018-04-23 18:35:42 +08:00
|
|
|
timestamped=False)
|
|
|
|
)
|
|
|
|
|
|
|
|
# # #
|
|
|
|
|
|
|
|
we = self.rtlink.o.address[-1]
|
|
|
|
state_sel = self.rtlink.o.address[-2]
|
|
|
|
high_coeff = self.rtlink.o.address[0]
|
|
|
|
self.comb += [
|
|
|
|
m_coeff.adr.eq(self.rtlink.o.address[1:]),
|
|
|
|
m_coeff.dat_w.eq(Cat(self.rtlink.o.data, self.rtlink.o.data)),
|
|
|
|
m_coeff.we[0].eq(self.rtlink.o.stb & ~high_coeff &
|
|
|
|
we & ~state_sel),
|
|
|
|
m_coeff.we[1].eq(self.rtlink.o.stb & high_coeff &
|
|
|
|
we & ~state_sel),
|
|
|
|
m_state.adr.eq(self.rtlink.o.address),
|
|
|
|
m_state.dat_w.eq(self.rtlink.o.data << w.state - w.coeff),
|
|
|
|
m_state.we.eq(self.rtlink.o.stb & we & state_sel),
|
|
|
|
]
|
|
|
|
read = Signal()
|
|
|
|
read_sel = Signal()
|
|
|
|
read_high = Signal()
|
|
|
|
self.sync.rio += [
|
|
|
|
If(read,
|
|
|
|
read.eq(0)
|
|
|
|
),
|
|
|
|
If(self.rtlink.o.stb & ~we,
|
|
|
|
read.eq(1),
|
|
|
|
read_sel.eq(state_sel),
|
|
|
|
read_high.eq(high_coeff),
|
|
|
|
)
|
|
|
|
]
|
|
|
|
self.comb += [
|
2018-04-23 23:15:52 +08:00
|
|
|
self.rtlink.o.busy.eq(read),
|
2018-04-23 18:35:42 +08:00
|
|
|
self.rtlink.i.stb.eq(read),
|
|
|
|
self.rtlink.i.data.eq(Mux(state_sel,
|
|
|
|
m_state.dat_r >> w.state - w.coeff,
|
|
|
|
Mux(read_high, m_coeff.dat_r[w.coeff:],
|
|
|
|
m_coeff.dat_r)))
|
|
|
|
]
|