forked from M-Labs/artiq
fir: add ParallelHBFCascade
This commit is contained in:
parent
d303225249
commit
a629eb1665
|
@ -4,12 +4,13 @@ import numpy as np
|
||||||
from migen import *
|
from migen import *
|
||||||
|
|
||||||
|
|
||||||
def halfgen4(up, n):
|
def halfgen4(width, n):
|
||||||
"""
|
"""
|
||||||
http://recycle.lbl.gov/~ldoolitt/halfband
|
http://recycle.lbl.gov/~ldoolitt/halfband
|
||||||
|
|
||||||
params:
|
params:
|
||||||
* `up` is the stopband width, as a fraction of input sampling rate
|
* `up` is the passband/stopband width, as a fraction of
|
||||||
|
input sampling rate
|
||||||
* `n is the order of half-band filter to generate
|
* `n is the order of half-band filter to generate
|
||||||
returns:
|
returns:
|
||||||
* `a` is the full set of FIR coefficients, `4*n-1` long.
|
* `a` is the full set of FIR coefficients, `4*n-1` long.
|
||||||
|
@ -17,7 +18,7 @@ def halfgen4(up, n):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
npt = n*40
|
npt = n*40
|
||||||
wmax = 2*np.pi*up
|
wmax = 2*np.pi*width
|
||||||
wfit = (1 - np.linspace(0, 1, npt)[:, None]**2)*wmax
|
wfit = (1 - np.linspace(0, 1, npt)[:, None]**2)*wmax
|
||||||
|
|
||||||
target = .5*np.ones_like(wfit)
|
target = .5*np.ones_like(wfit)
|
||||||
|
@ -106,3 +107,44 @@ class ParallelFIR(Module):
|
||||||
xj for xj, cj in zip(x[-1 - j::-1], coefficients) if cj == c
|
xj for xj, cj in zip(x[-1 - j::-1], coefficients) if cj == c
|
||||||
]))
|
]))
|
||||||
self.sync += self.o[j].eq(reduce(add, o) >> shift)
|
self.sync += self.o[j].eq(reduce(add, o) >> shift)
|
||||||
|
|
||||||
|
|
||||||
|
def halfgen4_cascade(rate, width, order=None):
|
||||||
|
"""Generate coefficients for cascaded half-band filters.
|
||||||
|
|
||||||
|
:param rate: upsampling rate. power of two
|
||||||
|
:param width: passband/stopband width in units of input sampling rate.
|
||||||
|
:param order: highest order, defaults to :param:`rate`"""
|
||||||
|
if order is None:
|
||||||
|
order = rate
|
||||||
|
coeff = []
|
||||||
|
p = 1
|
||||||
|
while p < rate:
|
||||||
|
p *= 2
|
||||||
|
coeff.append(halfgen4(width*p/rate/2, order*p//rate))
|
||||||
|
return coeff
|
||||||
|
|
||||||
|
|
||||||
|
class ParallelHBFUpsampler(Module):
|
||||||
|
"""Parallel, power-of-two, half-band, cascading upsampler.
|
||||||
|
|
||||||
|
Coefficients should be normalized to overall gain of 2
|
||||||
|
(highest/center coefficient being 1)."""
|
||||||
|
def __init__(self, coefficients, width=16, **kwargs):
|
||||||
|
self.parallelism = 1
|
||||||
|
self.latency = 0
|
||||||
|
self.width = width
|
||||||
|
self.i = Signal((width, True))
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
i = [self.i]
|
||||||
|
for coeff in coefficients:
|
||||||
|
self.parallelism *= 2
|
||||||
|
# assert coeff[len(coeff)//2 + 1] == 1
|
||||||
|
hbf = ParallelFIR(coeff, self.parallelism, width, **kwargs)
|
||||||
|
self.submodules += hbf
|
||||||
|
self.comb += [a.eq(b) for a, b in zip(hbf.i[::2], i)]
|
||||||
|
i = hbf.o
|
||||||
|
self.latency += hbf.latency
|
||||||
|
self.o = i
|
||||||
|
|
|
@ -81,13 +81,19 @@ def _main():
|
||||||
coeff = fir.halfgen4(.4/2, 8)
|
coeff = fir.halfgen4(.4/2, 8)
|
||||||
coeff_int = [int(round(c * (1 << 16 - 1))) for c in coeff]
|
coeff_int = [int(round(c * (1 << 16 - 1))) for c in coeff]
|
||||||
if False:
|
if False:
|
||||||
dut = fir.FIR(coeff_int, width=16)
|
coeff = [[int(round((1 << 26) * ci)) for ci in c]
|
||||||
# print(verilog.convert(dut, ios={dut.i, dut.o}))
|
for c in fir.halfgen4_cascade(8, width=.4, order=8)]
|
||||||
tb = Transfer(dut)
|
dut = fir.ParallelHBFUpsampler(coeff, width=16, shift=25)
|
||||||
else:
|
print(verilog.convert(dut, ios=set([dut.i] + dut.o)))
|
||||||
|
elif True:
|
||||||
dut = fir.ParallelFIR(coeff_int, parallelism=4, width=16)
|
dut = fir.ParallelFIR(coeff_int, parallelism=4, width=16)
|
||||||
# print(verilog.convert(dut, ios=set(dut.i + dut.o)))
|
# print(verilog.convert(dut, ios=set(dut.i + dut.o)))
|
||||||
tb = ParallelTransfer(dut)
|
tb = ParallelTransfer(dut)
|
||||||
|
else:
|
||||||
|
dut = fir.FIR(coeff_int, width=16)
|
||||||
|
# print(verilog.convert(dut, ios={dut.i, dut.o}))
|
||||||
|
tb = Transfer(dut)
|
||||||
|
|
||||||
x, y = tb.run(samples=1 << 10, amplitude=.8)
|
x, y = tb.run(samples=1 << 10, amplitude=.8)
|
||||||
tb.analyze(x, y)
|
tb.analyze(x, y)
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
Loading…
Reference in New Issue