def test_iir_api(): clock = Clock(0, frequency=50e6) reset = Reset(1, active=0, async=True) glbl = Global(clock, reset) tbclk = clock.process() w = (24,0,23) w_out = (24,0,23) ymax = 2**(2*w[0]-1) vmax = 2**(2*w[0]) omax = 2**(w_out[0]-1) xt = Samples(min=-ymax, max=ymax, word_format = w) yt = Samples(min=-omax, max=omax, word_format = w_out) b = [[101, 0, 132], [23324, 0, 232]] a = [[24223, 1], [233, 0]] w = (24, 23, 0) #iir_test = FilterIIR(b, a) iir = iir_parallel.filter_iir_parallel(glbl, xt, yt, b, a, w) return hdl.instances()
def filter_block(self): """ this elaboration code will select the different structure and implementations""" w = self.input_word_format w_out = self.output_word_format ymax = 2**(2 * w[0] - 1) vmax = 2**(2 * w[0]) omax = 2**(w_out[0] - 1) xt = Samples(min=-ymax, max=ymax, word_format=self.input_word_format) yt = Samples(min=-omax, max=omax, word_format=self.output_word_format) xt.valid = bool(1) clock = Clock(0, frequency=50e6) reset = Reset(1, active=0, async=True) glbl = Global(clock, reset) tbclk = clock.process() numsample = 0 # set numsample numsample = len(self.sigin) # process to record output in buffer rec_insts = yt.process_record(clock, num_samples=numsample) if self.filter_type == 'direct_form': if self.direct_form_type == 1: # all filters will need the same interface ports, this should be do able dfilter = iir_df1.filter_iir if self.n_cascades > 0: # TODO: port the SOS iir into the latest set of interfaces #filter_insts = iir_sos.filter_iir_sos( # glbl, xt, yt, self.sos, self.coef_word_format #) pass else: filter_insts = dfilter(glbl, xt, yt, self.b, self.a, self.coef_word_format) @hdl.instance def stimulus(): """record output in numpy array yt.sample_buffer""" for k in self.sigin: xt.data.next = int(k) xt.valid = bool(1) yt.record = True yt.valid = True yield clock.posedge # Collect a sample from each filter yt.record = False yt.valid = False self.response = yt.sample_buffer raise StopSimulation() return hdl.instances()
def filter_iir_sos(glbl, x, y, sos, w): """IIR sum of sections ... """ #assert len(b) == len(a) number_of_sections = len(sos) list_of_insts = [None for _ in range(number_of_sections)] xmax = x.imax xmin = x.imin xb = [Samples(min = xmin, max = xmax) for _ in range(number_of_sections+1)] xb[0] = x xb[number_of_sections] = y for ii in range(len(sos)): list_of_insts[ii] = filter_iir( glbl, xb[ii], xb[ii+1], sos=tuple(map(int, sos[ii])) ) return list_of_insts
def filter_iir_top(hdl, clock, reset, x, xdv, y, ydv): sigin = Samples(x.min, x.max, self.input_word_format) sigin.data, sigin.data_valid = x, xdv sigout = Samples(y.min, y.max, self.output_word_format) sigout.data, sigout.data_valid = y, ydv clk = clock rst = reset glbl = Global(clk, rst) # choose appropriate filter iir_hdl = iir_df1.filter_iir iir = iir_hdl(glbl, sigin, sigout, self.b, self.a, self.coef_word_format, shared_multiplier=self._shared_multiplier) iir.convert(**kwargs)
def notest_filters(args=None): # fails with FilterFIR.process() not implemented in filter_hw.py if args is None: ntaps, nbands, fs, imax = 86, 3, 1e5, 2**7 nsmps = 3*ntaps # TODO: get the following from args clock = Clock(0, frequency=50e6) reset = Reset(0, active=0, async=True) glbl = Global(clock, reset) # Input to the filters xi = Samples(min=-imax, max=imax) xf = Samples(min=-1, max=1, dtype=float) # Output of the filters ym = Samples(min=-1, max=1, dtype=float) ylist = [Samples(min=-imax, max=imax) for _ in range(4)] ym, y1, y2, y3 = ylist # Record list, record each of these sample streams rlist = [ym] + [xi, xf] + ylist dibv = intbv(0, min=-imax, max=imax) dds1 = DDSine(1e3, fs, 0.8, 0, dibv) # TODO: get coefficients # bi, b = get_fir_coef() b = np.ones(ntaps) / ntaps bi = b * imax # h = tuple(bi) # Frequency sweep fsn = fs/2 flist = np.linspace(0, fsn, nbands) @hdl.block def bench_fir(): tbclk = clock.process() tbsin = dds1.process(clock, reset, xi, xf) # The collection of FIR filter implementations. # a simple model to compare to, each filter has a different # delay through the filter implementation model_inst = FilterFIR(b, [1]).process(glbl, xf, ym) # Create "records" for each sample stream. rec_insts = [None for _ in rlist] for ii, sc in enumerate(rlist): rec_insts[ii] = sc.process_record(clock, num_samples=nsmps) @hdl.instance def tbstim(): yield reset.pulse(clock) yield clock.posedge for ff in flist: # Avoid the transitions dds1.set_frequency(ff) for _ in range(ntaps+7): yield xi.valid.posedge dds1.set_zero(False) yield clock.posedge # Enable recording for sr in rlist: sr.record = True # Collect a sample from each filter for sr in rlist: sr.record = False yield delay(1100) raise hdl.StopSimulation return hdl.instances() tb = bench_fir() tb.config_sim(trace=True) tb.run_sim()
def filter_fir_parallel_pipeline(clock, reset, x, y, h, multpipe=3): assert isinstance(x, Samples) assert isinstance(y, Samples) ntaps = len(h) # The converter only knows how to deal with a list of signals, # need to extract the signals from my interface (bus object) xd = [Samples(min=x.data.min, max=x.data.max) for _ in range(ntaps)] xds = [ss.data for ss in xd] # Need enough valids for the complete pipeline, one for the # tap update, one for the multiplies, /gm/ for the multiply # pipeline stages. vld = [Signal(bool(0)) for _ in range(multpipe + 2)] # Setup the configurable pipeline stage after the multiple. In # some cases (synthesis guidelines) multiple registers are desired # after a multiply to maximize hard MAC (DSP block) in the FPGA. # currently the converter does not handle 2D lists of signals, # need to break it out in elaboration. pmax = x.data.max * x.data.max pmat = [[Signal(intbv(0, min=-pmax, max=pmax)) for _ in range(ntaps)] for _ in range(multpipe + 1)] pris, pros = pmat[0], pmat[multpipe] pipe_insts = [None for _ in range(multpipe)] for ii in range(multpipe): pipe_insts[ii] = pipes(clock, reset, pmat[ii], pmat[ii + 1], vld[ii + 1], vld[ii + 2]) # Extra pipeline after scaling ypipe = Samples(min=-pmax, max=pmax) # Need to scale the outputs, the multiply will # create a number twice as big scale = int(len(x.sig) - 1) # when a new sample is ready (vld) it will kick off the # pipelined compuation, if the sample stream is continuous # the pipeline will remain full. @always_seq(clock.posedge, reset=reset) def beh_sop(): # Tap update loop, if there is a new sample get it, if # a new sample is not right on the heels clear all vlds # only the first, xd[0], vld is used to feed the pipe. if x.vld: xds[0].next = x.sig vld[0].next = x.vld for ii in range(1, ntaps): xds[ii].next = xds[ii - 1] else: vld[0].next = False # Output pipelines, adds to the overall delay # of the filter but does not change the response # multiply loop, certain MAC IP require registers, the # pipeline after the multiply can be set. for ii in range(ntaps): c = h[ii] pris[ii].next = c * xds[ii] vld[1].next = vld[0] # Multiply pipeline stages, instantiated above # vld[1]i, vld[2]oi, ..., vld[mp-1]o # sum-of-products loop sop = 0 for ii in range(ntaps): sop = sop + pros[ii] ypipe.data.next = sop ypipe.valid.next = vld[multpipe + 1] y.data.next = ypipe.data >> scale y.valid.next = ypipe.valid return hdl.instances()