forked from M-Labs/artiq
sawg: wire up all HBF outputs, latency compensation in phys, simplify
This commit is contained in:
parent
6cdb96c5e0
commit
8381db279f
|
@ -5,7 +5,7 @@ from misoc.interconnect.stream import Endpoint
|
|||
from misoc.cores.cordic import Cordic
|
||||
|
||||
from .accu import PhasedAccu
|
||||
from .tools import eqh, Delay, SatAddMixin
|
||||
from .tools import eqh, SatAddMixin
|
||||
from .spline import Spline
|
||||
from .fir import ParallelHBFUpsampler, halfgen4_cascade
|
||||
|
||||
|
@ -14,44 +14,10 @@ _Widths = namedtuple("_Widths", "t a p f")
|
|||
_Orders = namedtuple("_Orders", "a p f")
|
||||
|
||||
|
||||
class ParallelDDS(Module):
|
||||
def __init__(self, widths, parallelism=1, a_delay=0):
|
||||
self.i = Endpoint([("x", widths.a), ("y", widths.a),
|
||||
("f", widths.f), ("p", widths.f), ("clr", 1)])
|
||||
class SplineParallelDUC(Module):
|
||||
def __init__(self, widths, orders, parallelism=1, **kwargs):
|
||||
self.parallelism = parallelism
|
||||
self.widths = widths
|
||||
|
||||
###
|
||||
|
||||
accu = PhasedAccu(widths.f, parallelism)
|
||||
cordic = [Cordic(width=widths.a, widthz=widths.p, guard=None,
|
||||
eval_mode="pipelined") for i in range(parallelism)]
|
||||
self.xo = [c.xo for c in cordic]
|
||||
self.yo = [c.yo for c in cordic]
|
||||
a_delay += accu.latency
|
||||
xy_delay = Delay(2*widths.a, max(0, a_delay))
|
||||
z_delay = Delay(parallelism*widths.p, max(0, -a_delay))
|
||||
self.submodules += accu, xy_delay, z_delay, cordic
|
||||
self.latency = max(0, a_delay) + cordic[0].latency
|
||||
self.gain = cordic[0].gain
|
||||
|
||||
self.comb += [
|
||||
xy_delay.i.eq(Cat(self.i.x, self.i.y)),
|
||||
z_delay.i.eq(Cat(zi[-widths.p:]
|
||||
for zi in accu.o.payload.flatten())),
|
||||
eqh(accu.i.p, self.i.p),
|
||||
accu.i.f.eq(self.i.f),
|
||||
accu.i.clr.eq(self.i.clr),
|
||||
accu.i.stb.eq(self.i.stb),
|
||||
self.i.ack.eq(accu.i.ack),
|
||||
accu.o.ack.eq(1),
|
||||
[Cat(c.xi, c.yi).eq(xy_delay.o) for c in cordic],
|
||||
Cat(c.zi for c in cordic).eq(z_delay.o),
|
||||
]
|
||||
|
||||
|
||||
class SplineParallelDUC(ParallelDDS):
|
||||
def __init__(self, widths, orders, **kwargs):
|
||||
p = Spline(order=orders.p, width=widths.p)
|
||||
f = Spline(order=orders.f, width=widths.f)
|
||||
self.f = f.tri(widths.t)
|
||||
|
@ -59,27 +25,41 @@ class SplineParallelDUC(ParallelDDS):
|
|||
self.submodules += p, f
|
||||
self.ce = Signal(reset=1)
|
||||
self.clr = Signal()
|
||||
super().__init__(widths._replace(p=len(self.p.a0), f=len(self.f.a0)),
|
||||
**kwargs)
|
||||
self.latency += f.latency
|
||||
|
||||
###
|
||||
accu = PhasedAccu(len(self.f.a0), parallelism)
|
||||
cordic = [Cordic(width=widths.a, widthz=len(self.p.a0), guard=None,
|
||||
eval_mode="pipelined") for i in range(parallelism)]
|
||||
self.submodules += accu, cordic
|
||||
|
||||
self.xi = [c.xi for c in cordic]
|
||||
self.yi = [c.yi for c in cordic]
|
||||
self.xo = [c.xo for c in cordic]
|
||||
self.yo = [c.yo for c in cordic]
|
||||
self.latency = cordic[0].latency
|
||||
self.gain = cordic[0].gain
|
||||
self.f.latency += accu.latency + self.latency
|
||||
self.p.latency += accu.latency + self.latency
|
||||
|
||||
###
|
||||
|
||||
assert p.latency == f.latency
|
||||
|
||||
self.comb += [
|
||||
p.o.ack.eq(self.ce),
|
||||
f.o.ack.eq(self.ce),
|
||||
eqh(self.i.f, f.o.a0),
|
||||
eqh(self.i.p, p.o.a0),
|
||||
self.i.stb.eq(p.o.stb | f.o.stb),
|
||||
eqh(accu.i.f, f.o.a0),
|
||||
eqh(accu.i.p, p.o.a0),
|
||||
accu.i.stb.eq(p.o.stb | f.o.stb),
|
||||
accu.o.ack.eq(1),
|
||||
[eqh(c.zi, zi) for c, zi in
|
||||
zip(cordic, accu.o.payload.flatten())]
|
||||
]
|
||||
|
||||
assert p.latency == 1
|
||||
self.sync += [
|
||||
self.i.clr.eq(0),
|
||||
accu.i.clr.eq(0),
|
||||
If(p.i.stb,
|
||||
self.i.clr.eq(self.clr),
|
||||
accu.i.clr.eq(self.clr),
|
||||
),
|
||||
]
|
||||
|
||||
|
@ -91,12 +71,14 @@ class SplineParallelDDS(SplineParallelDUC):
|
|||
self.submodules += a
|
||||
super().__init__(widths._replace(a=len(self.a.a0)), orders, **kwargs)
|
||||
|
||||
self.a.latency += self.latency
|
||||
|
||||
###
|
||||
|
||||
self.comb += [
|
||||
a.o.ack.eq(self.ce),
|
||||
eqh(self.i.x, a.o.a0),
|
||||
self.i.y.eq(0),
|
||||
[eqh(x, a.o.a0) for x in self.xi],
|
||||
[y.eq(0) for y in self.yi],
|
||||
]
|
||||
|
||||
|
||||
|
@ -151,12 +133,11 @@ class Channel(Module, SatAddMixin):
|
|||
hbf = [ParallelHBFUpsampler(coeff, width=width, shift=17)
|
||||
for i in range(2)]
|
||||
self.submodules.b = b = SplineParallelDUC(
|
||||
widths._replace(a=len(a1.xo[0]), f=widths.f - width), orders,
|
||||
parallelism=parallelism, a_delay=-a1.latency-hbf[0].latency)
|
||||
widths._replace(a=len(hbf[0].o[0]), f=widths.f - width), orders,
|
||||
parallelism=parallelism)
|
||||
cfg = Config(widths.a)
|
||||
u = Spline(width=widths.a, order=orders.a)
|
||||
du = Delay(width, a1.latency + hbf[0].latency + b.latency - u.latency)
|
||||
self.submodules += cfg, u, du, hbf
|
||||
self.submodules += cfg, u, hbf
|
||||
self.u = u.tri(widths.t)
|
||||
self.i = [cfg.i, self.u, a1.a, a1.f, a1.p, a2.a, a2.f, a2.p, b.f, b.p]
|
||||
self.i_names = "cfg u a1 f1 p1 a2 f2 p2 f0 p0".split()
|
||||
|
@ -166,9 +147,23 @@ class Channel(Module, SatAddMixin):
|
|||
self.widths = widths
|
||||
self.orders = orders
|
||||
self.parallelism = parallelism
|
||||
self.latency = a1.latency + hbf[0].latency + b.latency + 2
|
||||
self.cordic_gain = a1.gain*b.gain
|
||||
|
||||
self.u.latency += 1
|
||||
b.p.latency += 2
|
||||
b.f.latency += 2
|
||||
a_latency_delta = hbf[0].latency + b.latency + 2
|
||||
for a in a1, a2:
|
||||
a.a.latency += a_latency_delta
|
||||
a.p.latency += a_latency_delta
|
||||
a.f.latency += a_latency_delta
|
||||
|
||||
self.latency = max(_.latency for _ in self.i[1:])
|
||||
for i in self.i[1:]:
|
||||
i.latency -= self.latency
|
||||
assert i.latency <= 0
|
||||
cfg.i.latency = 0
|
||||
|
||||
###
|
||||
|
||||
self.comb += [
|
||||
|
@ -177,8 +172,8 @@ class Channel(Module, SatAddMixin):
|
|||
b.ce.eq(cfg.ce),
|
||||
u.o.ack.eq(cfg.ce),
|
||||
Cat(a1.clr, a2.clr, b.clr).eq(cfg.clr),
|
||||
b.i.x.eq(hbf[0].o[0]), # FIXME: rip up
|
||||
b.i.y.eq(hbf[1].o[0]),
|
||||
Cat(b.xi).eq(Cat(hbf[0].o)),
|
||||
Cat(b.yi).eq(Cat(hbf[1].o)),
|
||||
]
|
||||
self.sync += [
|
||||
hbf[0].i.eq(self.sat_add(a1.xo[0], a2.xo[0],
|
||||
|
@ -187,14 +182,16 @@ class Channel(Module, SatAddMixin):
|
|||
hbf[1].i.eq(self.sat_add(a1.yo[0], a2.yo[0],
|
||||
limits=cfg.limits[1],
|
||||
clipped=cfg.clipped[1])),
|
||||
eqh(du.i, u.o.a0),
|
||||
]
|
||||
# wire up outputs and q_{i,o} exchange
|
||||
for o, x, y in zip(self.o, b.xo, self.y_in):
|
||||
self.sync += [
|
||||
o.eq(self.sat_add(
|
||||
du.o, Mux(cfg.iq_en[0], x, 0), Mux(cfg.iq_en[1], y, 0),
|
||||
limits=cfg.limits[2], clipped=cfg.clipped[2])),
|
||||
u.o.a0[-len(o):],
|
||||
Mux(cfg.iq_en[0], x, 0),
|
||||
Mux(cfg.iq_en[1], y, 0),
|
||||
limits=cfg.limits[2],
|
||||
clipped=cfg.clipped[2])),
|
||||
]
|
||||
|
||||
def connect_y(self, buddy):
|
||||
|
|
|
@ -37,6 +37,7 @@ class Spline(Module):
|
|||
enumerate(self.i.payload.layout[::-1])]
|
||||
layout.reverse()
|
||||
i = Endpoint(layout)
|
||||
i.latency = self.latency
|
||||
self.comb += [
|
||||
self.i.stb.eq(i.stb),
|
||||
i.ack.eq(self.i.ack),
|
||||
|
|
|
@ -16,7 +16,8 @@ class Channel(_ChannelPHY):
|
|||
_ChannelPHY.__init__(self, *args, **kwargs)
|
||||
self.phys = []
|
||||
for i in self.i:
|
||||
rl = rtlink.Interface(rtlink.OInterface(len(i.payload)))
|
||||
rl = rtlink.Interface(rtlink.OInterface(len(i.payload),
|
||||
delay=-i.latency))
|
||||
self.comb += [
|
||||
i.stb.eq(rl.o.stb),
|
||||
rl.o.busy.eq(~i.ack),
|
||||
|
|
Loading…
Reference in New Issue