From 9a8a7b9102734bf36db4db9d373074dc3a6cfe08 Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Mon, 12 Jun 2017 20:27:55 +0200 Subject: [PATCH] sawg: handle clipping interpolator * give 1 bit headroom to interpolator to handle overshoot * fix Config limiter widths (NFC) * move clipper to behind the HBF to correctly shield DUC This leaves a factor of two headroom for the sum of the following effects: * HBF overshoot (~15 % of the step) * A1/A2 DDS sum While this is technically not sufficient and can still lead to overflows, it is unlikely that one would trigger those. It would require doing large amplitude A1, large amplitude A2 and additionally doing amplitude/phase jumps that would overshoot the HBF. No sane person would try that, right? closes #743 --- artiq/gateware/dsp/sawg.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/artiq/gateware/dsp/sawg.py b/artiq/gateware/dsp/sawg.py index b7f4dd0b0..af0e03c0c 100644 --- a/artiq/gateware/dsp/sawg.py +++ b/artiq/gateware/dsp/sawg.py @@ -129,11 +129,11 @@ class Channel(Module, SatAddMixin): self.submodules.a1 = a1 = SplineParallelDDS(widths, orders) self.submodules.a2 = a2 = SplineParallelDDS(widths, orders) coeff = halfgen4_cascade(parallelism, width=.4, order=8) - hbf = [ParallelHBFUpsampler(coeff, width=width) for i in range(2)] + hbf = [ParallelHBFUpsampler(coeff, width=width + 1) for i in range(2)] self.submodules.b = b = SplineParallelDUC( widths._replace(a=len(hbf[0].o[0]), f=widths.f - width), orders, parallelism=parallelism) - cfg = Config(widths.a) + cfg = Config(width) u = Spline(width=widths.a, order=orders.a) self.submodules += cfg, u, hbf self.u = u.tri(widths.t) @@ -170,16 +170,24 @@ 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), - 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], + for i in range(parallelism): + self.comb += [ + b.xi[i].eq(self.sat_add(hbf[0].o[i], limits=cfg.limits[0], clipped=cfg.clipped[0])), - hbf[1].i.eq(self.sat_add(a1.yo[0], a2.yo[0], + b.yi[i].eq(self.sat_add(hbf[1].o[i], limits=cfg.limits[1], clipped=cfg.clipped[1])), + ] + for i in range(2): + for j in range(2): + # correct pre-DUC limiter by cordic gain + v = cfg.limits[i][j].reset.value + cfg.limits[i][j].reset.value = int(v / b.gain) + self.comb += [ + hbf[0].i.eq(a1.xo[0] + a2.xo[0]), + hbf[1].i.eq(a1.yo[0] + a2.yo[0]) ] # wire up outputs and q_{i,o} exchange for o, x, y in zip(self.o, b.xo, self.y_in):