sawg: wire up all HBF outputs, latency compensation in phys, simplify

This commit is contained in:
Robert Jördens 2016-12-13 18:37:21 +01:00
parent 6cdb96c5e0
commit 8381db279f
3 changed files with 58 additions and 59 deletions

View File

@ -5,7 +5,7 @@ from misoc.interconnect.stream import Endpoint
from misoc.cores.cordic import Cordic from misoc.cores.cordic import Cordic
from .accu import PhasedAccu from .accu import PhasedAccu
from .tools import eqh, Delay, SatAddMixin from .tools import eqh, SatAddMixin
from .spline import Spline from .spline import Spline
from .fir import ParallelHBFUpsampler, halfgen4_cascade from .fir import ParallelHBFUpsampler, halfgen4_cascade
@ -14,44 +14,10 @@ _Widths = namedtuple("_Widths", "t a p f")
_Orders = namedtuple("_Orders", "a p f") _Orders = namedtuple("_Orders", "a p f")
class ParallelDDS(Module): class SplineParallelDUC(Module):
def __init__(self, widths, parallelism=1, a_delay=0): def __init__(self, widths, orders, parallelism=1, **kwargs):
self.i = Endpoint([("x", widths.a), ("y", widths.a),
("f", widths.f), ("p", widths.f), ("clr", 1)])
self.parallelism = parallelism self.parallelism = parallelism
self.widths = widths 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) p = Spline(order=orders.p, width=widths.p)
f = Spline(order=orders.f, width=widths.f) f = Spline(order=orders.f, width=widths.f)
self.f = f.tri(widths.t) self.f = f.tri(widths.t)
@ -59,27 +25,41 @@ class SplineParallelDUC(ParallelDDS):
self.submodules += p, f self.submodules += p, f
self.ce = Signal(reset=1) self.ce = Signal(reset=1)
self.clr = Signal() 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 assert p.latency == f.latency
self.comb += [ self.comb += [
p.o.ack.eq(self.ce), p.o.ack.eq(self.ce),
f.o.ack.eq(self.ce), f.o.ack.eq(self.ce),
eqh(self.i.f, f.o.a0), eqh(accu.i.f, f.o.a0),
eqh(self.i.p, p.o.a0), eqh(accu.i.p, p.o.a0),
self.i.stb.eq(p.o.stb | f.o.stb), 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 assert p.latency == 1
self.sync += [ self.sync += [
self.i.clr.eq(0), accu.i.clr.eq(0),
If(p.i.stb, 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 self.submodules += a
super().__init__(widths._replace(a=len(self.a.a0)), orders, **kwargs) super().__init__(widths._replace(a=len(self.a.a0)), orders, **kwargs)
self.a.latency += self.latency
### ###
self.comb += [ self.comb += [
a.o.ack.eq(self.ce), a.o.ack.eq(self.ce),
eqh(self.i.x, a.o.a0), [eqh(x, a.o.a0) for x in self.xi],
self.i.y.eq(0), [y.eq(0) for y in self.yi],
] ]
@ -151,12 +133,11 @@ class Channel(Module, SatAddMixin):
hbf = [ParallelHBFUpsampler(coeff, width=width, shift=17) hbf = [ParallelHBFUpsampler(coeff, width=width, shift=17)
for i in range(2)] for i in range(2)]
self.submodules.b = b = SplineParallelDUC( self.submodules.b = b = SplineParallelDUC(
widths._replace(a=len(a1.xo[0]), f=widths.f - width), orders, widths._replace(a=len(hbf[0].o[0]), f=widths.f - width), orders,
parallelism=parallelism, a_delay=-a1.latency-hbf[0].latency) parallelism=parallelism)
cfg = Config(widths.a) cfg = Config(widths.a)
u = Spline(width=widths.a, order=orders.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, hbf
self.submodules += cfg, u, du, hbf
self.u = u.tri(widths.t) 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 = [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() 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.widths = widths
self.orders = orders self.orders = orders
self.parallelism = parallelism self.parallelism = parallelism
self.latency = a1.latency + hbf[0].latency + b.latency + 2
self.cordic_gain = a1.gain*b.gain 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 += [ self.comb += [
@ -177,8 +172,8 @@ class Channel(Module, SatAddMixin):
b.ce.eq(cfg.ce), b.ce.eq(cfg.ce),
u.o.ack.eq(cfg.ce), u.o.ack.eq(cfg.ce),
Cat(a1.clr, a2.clr, b.clr).eq(cfg.clr), Cat(a1.clr, a2.clr, b.clr).eq(cfg.clr),
b.i.x.eq(hbf[0].o[0]), # FIXME: rip up Cat(b.xi).eq(Cat(hbf[0].o)),
b.i.y.eq(hbf[1].o[0]), Cat(b.yi).eq(Cat(hbf[1].o)),
] ]
self.sync += [ self.sync += [
hbf[0].i.eq(self.sat_add(a1.xo[0], a2.xo[0], 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], hbf[1].i.eq(self.sat_add(a1.yo[0], a2.yo[0],
limits=cfg.limits[1], limits=cfg.limits[1],
clipped=cfg.clipped[1])), clipped=cfg.clipped[1])),
eqh(du.i, u.o.a0),
] ]
# wire up outputs and q_{i,o} exchange # wire up outputs and q_{i,o} exchange
for o, x, y in zip(self.o, b.xo, self.y_in): for o, x, y in zip(self.o, b.xo, self.y_in):
self.sync += [ self.sync += [
o.eq(self.sat_add( o.eq(self.sat_add(
du.o, Mux(cfg.iq_en[0], x, 0), Mux(cfg.iq_en[1], y, 0), u.o.a0[-len(o):],
limits=cfg.limits[2], clipped=cfg.clipped[2])), 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): def connect_y(self, buddy):

View File

@ -37,6 +37,7 @@ class Spline(Module):
enumerate(self.i.payload.layout[::-1])] enumerate(self.i.payload.layout[::-1])]
layout.reverse() layout.reverse()
i = Endpoint(layout) i = Endpoint(layout)
i.latency = self.latency
self.comb += [ self.comb += [
self.i.stb.eq(i.stb), self.i.stb.eq(i.stb),
i.ack.eq(self.i.ack), i.ack.eq(self.i.ack),

View File

@ -16,7 +16,8 @@ class Channel(_ChannelPHY):
_ChannelPHY.__init__(self, *args, **kwargs) _ChannelPHY.__init__(self, *args, **kwargs)
self.phys = [] self.phys = []
for i in self.i: 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 += [ self.comb += [
i.stb.eq(rl.o.stb), i.stb.eq(rl.o.stb),
rl.o.busy.eq(~i.ack), rl.o.busy.eq(~i.ack),