Example #1
0
    def __init__(self):
        self.sink = Endpoint(ULPI_DATA_D)
        self.source = Endpoint(ULPI_DATA_D)

        self._ctl = CSRStorage(1)
        snapshot = self._ctl.re
        reset = self._ctl.storage[0]
        self._num_ovf = Perfcounter(snapshot, reset)
        self._num_total = Perfcounter(snapshot, reset)

        self.comb += If(self.sink.stb, self._num_total.inc())
        self.comb += If(self.source.stb & ~self.source.ack,
                        self._num_ovf.inc())

        valid = Signal()
        data = Record(ULPI_DATA_D)

        self.comb += [If(
            self.sink.stb,
            self.sink.ack.eq(1),
        )]

        self.sync += [
            If(
                self.sink.stb, valid.eq(1),
                If(
                    valid & ~self.source.ack,
                    data.rxcmd.eq(1),
                    data.d.eq(RXCMD_MAGIC_OVF),
                ).Else(data.eq(self.sink.payload))).Elif(
                    self.source.ack, valid.eq(0))
        ]

        self.comb += [self.source.stb.eq(valid), self.source.payload.eq(data)]
Example #2
0
File: comm.py Project: olsonse/pdq
    def __init__(self):
        self.sink = Endpoint(bus_layout)
        self.source = Endpoint(bus_layout)
        self.source.eop.reset = 1

        ###

        unesc = Unescaper(bus_layout)
        self.submodules += unesc
        self.sync += [
            If(
                unesc.source1.stb,
                Case(unesc.source1.data, {
                    0x02: self.source.eop.eq(0),
                    0x03: self.source.eop.eq(1),
                }),
            )
        ]
        self.comb += [
            self.sink.connect(unesc.sink),
            self.source.data.eq(unesc.source0.data),
            self.source.stb.eq(unesc.source0.stb),
            unesc.source0.ack.eq(self.source.ack),
            unesc.source1.ack.eq(1),
        ]
Example #3
0
    def __init__(self, order, width, step=1, time_width=None):
        if not (step == 1 or order <= 2):
            raise ValueError("For non-linear splines, "
                             "`step` needs to be one.")
        layout = [("a{}".format(i), (width, True)) for i in range(order)]
        self.i = Endpoint(layout)
        self.o = Endpoint(layout)
        self.latency = 1

        ###

        o = self.o.payload.flatten()

        self.comb += self.i.ack.eq(~self.o.stb | self.o.ack)
        self.sync += [
            If(self.o.ack,
                self.o.stb.eq(0),
            ),
            If(self.i.ack,
                self.o.stb.eq(1),
                [o[i].eq(o[i] + (o[i + 1] << log2_int(step)))
                 for i in range(order - 1)],
                If(self.i.stb,
                    self.o.payload.eq(self.i.payload),
                ),
            ),
        ]
Example #4
0
    def __init__(self):
        h_fir = [24, -85, 281, -1314, 55856, -1314, 281, -85, 24]
        # ciccomp: cic droop and gain, rate 1/10, gain 2**9/5**4 ~ 0.9, 9 taps
        self.submodules.ciccomp = MAC_SYM_FIR(h_fir, width_d=24, width_coef=16)
        h_hbf0 = [
            -167, 0, 428, 0, -931, 0, 1776, 0, -3115, 0, 5185, 0, -8442, 0,
            14028, 0, -26142, 0, 82873, 131072, 82873, 0, -26142, 0, 14028, 0,
            -8442, 0, 5185, 0, -3115, 0, 1776, 0, -931, 0, 428, 0, -167
        ]
        # hbf1: rate 1/10 -> 1/5, gain=1, 39 taps
        self.submodules.hbf0 = MAC_HBF_Upsampler(h_hbf0,
                                                 width_d=24,
                                                 width_coef=17)
        h_hbf1 = [
            294, 0, -1865, 0, 6869, 0, -20436, 0, 80679, 131072, 80679, 0,
            -20436, 0, 6869, 0, -1865, 0, 294
        ]
        # hbf1: rate 1/5 -> 2/5, gain=1, 19 taps
        self.submodules.hbf1 = MAC_HBF_Upsampler(h_hbf1,
                                                 width_d=24,
                                                 width_coef=17)
        # cic: rate 2/5 -> 2/1, gain=5**4
        # the CIC doesn't cope with FIR overshoot and baseband data must be
        # band limited and/or backed off. Maybe TODO: clipping
        self.submodules.cic = SuperCIC(n=5, r=5, width=16)
        # buffer the odd/even stutter of the HBFs
        self.submodules.buf0 = MiniFIFO((len(self.hbf1.input.data), True))
        self.submodules.buf1 = MiniFIFO((len(self.cic.input.data), True))

        self.input = Endpoint([("data", (14, True))])
        self.output = Endpoint([("data0", (16, True)), ("data1", (16, True))])
        # align MACs to MSB to save power, keep one bit headroom for FIR
        # overshoot.
        scale_in = len(self.ciccomp.input.data) - len(self.input.data) - 1
        scale_out = len(self.hbf1.output.data) - len(self.cic.input.data) - 1
        bias_out = (1 << scale_out - 1) - 1  # round half down bias
        # cic gain is r**(n-1) = 5**4, compensate with 2**-9,
        # the rest (2**9/5**4) is applied by ciccomp
        scale_cic = 9
        bias_cic = (1 << scale_cic - 1) - 1  # round half down bias
        self.comb += [
            self.input.connect(self.hbf0.input, omit=["data"]),
            self.ciccomp.input.data.eq(self.input.data << scale_in),
            self.ciccomp.output.connect(self.hbf0.input),
            self.hbf0.output.connect(self.buf0.input),
            self.buf0.output.connect(self.hbf1.input),
            self.hbf1.output.connect(self.buf1.input, omit=["data"]),
            self.buf1.input.data.eq((self.hbf1.output.data +
                                     bias_out) >> scale_out),
            self.buf1.output.connect(self.cic.input),
            self.cic.output.connect(self.output, omit=["data0", "data1"]),
            self.output.data0.eq((self.cic.output.data0 +
                                  bias_cic) >> scale_cic),
            self.output.data1.eq((self.cic.output.data1 +
                                  bias_cic) >> scale_cic),
        ]
Example #5
0
    def __init__(self, width, parallelism=8):
        self.i = Endpoint([("p", width), ("f", width), ("clr", 1)])
        self.o = Endpoint([("z{}".format(i), width)
                           for i in range(parallelism)])
        self.parallelism = parallelism
        self.latency = 2

        ###

        a = MCM(width, range(parallelism + 1))
        self.submodules += a
        z = [Signal(width) for i in range(parallelism)]
        o = self.o.payload.flatten()
        load = Signal()
        clr = Signal()
        p = Signal.like(self.i.p)
        f = Signal.like(self.i.f)
        fp = Signal.like(self.i.f)
        self.comb += [
            self.i.ack.eq(self.o.ack),
            a.i.eq(self.i.f),
        ]

        self.sync += [
            If(
                self.o.ack,
                self.o.stb.eq(0),
            ),
            If(
                ~self.o.stb | self.o.ack,
                self.o.stb.eq(1),
                If(
                    load,
                    load.eq(0),
                    [
                        oi.eq(Mux(clr, 0, o[0] + fp) + zi)
                        for oi, zi in zip(o, z)
                    ],
                    fp.eq(f),
                ).Else([oi.eq(oi + fp) for oi in o], ),
            ),
            If(
                self.i.stb & self.i.ack,
                [
                    zi.eq(self.i.p - Mux(self.i.clr, 0, p) + aoi)
                    for zi, aoi in zip(z, a.o)
                ],
                clr.eq(self.i.clr),
                p.eq(self.i.p),
                f.eq(a.o[parallelism]),
                load.eq(1),
            ),
        ]
Example #6
0
File: comm.py Project: olsonse/pdq
    def __init__(self, width=8):
        self.sink0 = Endpoint(bus_layout)
        self.sink1 = Endpoint(bus_layout)
        self.source = Endpoint(bus_layout)

        ###

        self.comb += [
            If(
                ~self.sink0.eop,  # has priority
                self.sink0.connect(self.source),
            ).Else(self.sink1.connect(self.source), )
        ]
Example #7
0
File: comm.py Project: m-labs/pdq2
    def __init__(self, width=8):
        self.sink0 = Endpoint(bus_layout)
        self.sink1 = Endpoint(bus_layout)
        self.source = Endpoint(bus_layout)

        ###

        self.comb += [
            If(~self.sink0.eop,  # has priority
                self.sink0.connect(self.source),
            ).Else(
                self.sink1.connect(self.source),
            )
        ]
Example #8
0
 def tri(self, time_width):
     layout = [(name, (length - i*time_width, signed))
               for i, (name, (length, signed), dir) in
               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),
         [i0[-len(i1):].eq(i1) for i0, i1 in
          zip(self.i.payload.flatten(), i.payload.flatten())]
     ]
     return i
Example #9
0
    def __init__(self, base, data=300, idle=1000):
        self.source = Endpoint([('d', 8), ('last', 1)])

        self.submodules.dummy = FSM()

        dummy_count = Signal(max=max(idle, data))
        dummy_count_next = Signal(max=max(idle, data))
        self.sync += dummy_count.eq(dummy_count_next)
        self.comb += dummy_count_next.eq(dummy_count)

        self.dummy.act("S0", self.source.payload.d.eq(base + 0),
                       self.source.stb.eq(1), dummy_count_next.eq(0),
                       If(self.source.ack, NextState("S1")))

        self.dummy.act("S1", self.source.payload.d.eq(base + 1),
                       self.source.stb.eq(1),
                       If(self.source.ack, NextState("S2")))

        self.dummy.act(
            "S2", self.source.payload.d.eq(dummy_count[0:8]),
            self.source.stb.eq(1),
            If(
                self.source.ack,
                If(dummy_count != data,
                   dummy_count_next.eq(dummy_count + 1)).Else(
                       dummy_count_next.eq(0), self.source.payload.last.eq(1),
                       NextState("S3"))))

        self.dummy.act(
            "S3",
            If(dummy_count != idle, dummy_count_next.eq(dummy_count + 1)).Else(
                dummy_count_next.eq(0), NextState("S0")))
Example #10
0
File: comm.py Project: olsonse/pdq
class Arbiter(Module):
    """Simple arbiter for two framed data streams.
    Uses end-of-packet (eop) to detect that :attr:`sink0` is inactive
    and yields to :attr:`sink1`.
    """
    def __init__(self, width=8):
        self.sink0 = Endpoint(bus_layout)
        self.sink1 = Endpoint(bus_layout)
        self.source = Endpoint(bus_layout)

        ###

        self.comb += [
            If(
                ~self.sink0.eop,  # has priority
                self.sink0.connect(self.source),
            ).Else(self.sink1.connect(self.source), )
        ]
Example #11
0
 def __init__(self, width):
     self.input = Endpoint([("data", width)])
     self.output = Endpoint([("data", width)])
     self.input.data.reset_less = True
     self.output.data.reset_less = True
     self.comb += [
         self.input.ack.eq(~self.output.stb | self.output.ack),
     ]
     self.sync += [
         If(
             self.output.stb & self.output.ack,
             self.output.stb.eq(0),
         ),
         If(
             self.input.stb & self.input.ack,
             self.output.data.eq(self.input.data),
             self.output.stb.eq(1),
         )
     ]
Example #12
0
File: comm.py Project: m-labs/pdq2
class Arbiter(Module):
    """Simple arbiter for two framed data streams.
    Uses end-of-packet (eop) to detect that :attr:`sink0` is inactive
    and yields to :attr:`sink1`.
    """
    def __init__(self, width=8):
        self.sink0 = Endpoint(bus_layout)
        self.sink1 = Endpoint(bus_layout)
        self.source = Endpoint(bus_layout)

        ###

        self.comb += [
            If(~self.sink0.eop,  # has priority
                self.sink0.connect(self.source),
            ).Else(
                self.sink1.connect(self.source),
            )
        ]
Example #13
0
    def __init__(self, port, depth):
        self.sink = Endpoint(dmatpl(depth))
        self.source = Endpoint(D_LAST)
        self.busy = Signal()

        self.pos = Signal(max=depth, reset=0)
        self.pos_next = Signal(max=depth, reset=0)
        self.ct = Signal(max=depth, reset=0)
        self.ct_next = Signal(max=depth)

        self.comb += [
            self.ct_next.eq(self.ct),
            self.pos_next.eq(self.pos),
            port.adr.eq(self.pos_next),
        ]

        self.sync += [self.pos.eq(self.pos_next), self.ct.eq(self.ct_next)]

        self.submodules.fsm = FSM()

        self.fsm.act(
            "IDLE", self.busy.eq(0),
            If(
                self.sink.stb,
                self.busy.eq(1),
                self.sink.ack.eq(1),
                self.pos_next.eq(self.sink.payload.start),
                self.ct_next.eq(self.sink.payload.count - 1),
                NextState('d'),
            ))

        self.fsm.act(
            "d", self.busy.eq(1), self.source.stb.eq(1),
            self.source.payload.d.eq(port.dat_r),
            If(self.ct == 0, self.source.payload.last.eq(1)),
            If(
                self.source.ack,
                If(
                    self.ct,
                    _inc(self.pos, depth, self.pos_next),
                    self.ct_next.eq(self.ct - 1),
                ).Else(NextState("IDLE"))))
Example #14
0
    def __init__(self):
        self._size = CSRStorage(8, reset=8)
        self._cfg = CSRStorage(1, reset=0)

        self.source = Endpoint([('d', 8), ('last', 1)])

        START_BYTE = 0xAA

        self.lfsr_state = Signal(17)
        self.lfsr_state_next = Signal(17)

        self.sync += If(~self._cfg.storage[0], self.lfsr_state.eq(1)).Else(
            self.lfsr_state.eq(self.lfsr_state_next))

        self.bytecount = Signal(8)
        self.bytecount_next = Signal(8)
        self.comb += [
            self.lfsr_state_next.eq(self.lfsr_state),
            self.bytecount_next.eq(self.bytecount),
            self.source.payload.last.eq(0)
        ]
        self.sync += self.bytecount.eq(self.bytecount_next)

        self.submodules.fsm = FSM()

        self.fsm.act("IDLE", If(self._cfg.storage[0], NextState("SEND_HEAD")))

        self.fsm.act("SEND_HEAD", self.source.payload.d.eq(0xAA),
                     self.source.stb.eq(1),
                     If(self.source.ack, NextState("SEND_SIZE")))

        self.fsm.act(
            "SEND_SIZE",
            self.source.payload.d.eq(self._size.storage),
            self.source.stb.eq(1),
            If(self.source.ack, self.bytecount_next.eq(0),
               NextState("SEND_DATA")),
        )

        self.fsm.act(
            "SEND_DATA", self.source.payload.d.eq(self.lfsr_state),
            self.source.stb.eq(1),
            If(self.bytecount + 1 == self._size.storage,
               self.source.payload.last.eq(1)),
            If(
                self.source.ack,
                self.lfsr_state_next.eq(
                    Cat(
                        self.lfsr_state[16] ^ self.lfsr_state[14]
                        ^ self.lfsr_state[13] ^ self.lfsr_state[11],
                        self.lfsr_state)),
                self.bytecount_next.eq(self.bytecount + 1),
                If(self.bytecount + 1 == self._size.storage,
                   NextState("IDLE"))))
Example #15
0
    def __init__(self):

        self.busy = Signal()
        self.sink = Endpoint(CMD_REC)
        self.source = Endpoint([('d', 8), ('last', 1)])

        sm = FSM(reset_state="IDLE")
        self.submodules += sm

        self.comb += [self.source.stb.eq(0), self.source.payload.last.eq(0)]

        ssum = Signal(8)

        token_next = Record(CMD_REC)
        token = Record(CMD_REC)
        self.comb += token_next.eq(token)
        self.sync += token.eq(token_next)

        sm.act(
            "IDLE",
            If(self.sink.stb, self.sink.ack.eq(1),
               token_next.eq(self.sink.payload), NextState('c0')))

        _outs = [
            0x55,
            Cat(token.a[8:14], 0, token.wr), token.a[0:8], token.d, ssum
        ]

        s = _outs[0]
        for i in _outs[1:-1]:
            s = s + i
        self.sync += ssum.eq(s)

        for c, v in enumerate(_outs):
            _last = 1 if c == len(_outs) - 1 else 0
            _next = "IDLE" if _last else "c%d" % (c + 1)
            sm.act("c%d" % c, self.source.stb.eq(1),
                   self.source.payload.d.eq(v),
                   self.source.payload.last.eq(_last),
                   If(self.source.ack, NextState(_next)))
Example #16
0
File: spi.py Project: olsonse/pdq
    def __init__(self, width=8):
        self.spi = spi = Record(spi_layout)
        self.mosi = mosi = Endpoint([("data", width)])
        self.miso = miso = Endpoint([("data", width)])
        self.cs_n = Signal()

        ###

        inp = Debouncer(cycles=1)
        sr = CEInserter()(ShiftRegister(width))
        self.submodules += inp, sr
        self.specials += [
            MultiReg(self.spi.clk, inp.i),
            MultiReg(self.spi.cs_n, self.cs_n),
            MultiReg(self.spi.mosi, sr.i, n=3),  # latency matching
        ]

        clk0 = Signal()
        edge = Signal()
        self.sync += [
            clk0.eq(inp.o),
            If(
                edge & ~inp.o,  # falling
                spi.miso.eq(sr.o),
            ),
            If(
                mosi.stb,
                sr.data.eq(miso.data),
                spi.oe_s.eq(miso.stb),
            ),
        ]
        self.comb += [
            edge.eq(clk0 != inp.o),
            sr.ce.eq(edge & inp.o),  # rising
            mosi.stb.eq(sr.stb & sr.ce),
            miso.ack.eq(mosi.stb),
            mosi.data.eq(sr.next),
            mosi.eop.eq(self.cs_n),
        ]
Example #17
0
    def __init__(self, width, meta=[]):
        self.i = Endpoint([("p", width), ("f", width), ("clr", 1)])
        self.o = Endpoint([("z", width)])
        self.latency = 1

        ###

        f = Signal.like(self.i.f)
        p = Signal.like(self.i.p)
        self.comb += self.i.ack.eq(~self.o.stb | self.o.ack)
        self.sync += [
            If(
                self.o.ack,
                self.o.stb.eq(0),
            ),
            If(
                self.i.ack, self.o.stb.eq(1),
                If(
                    self.i.stb,
                    self.o.z.eq(self.i.p + Mux(self.i.clr, 0, self.o.z + p)),
                    f.eq(self.i.f),
                    p.eq(self.i.f - self.i.p),
                ).Else(self.o.z.eq(self.o.z + f), ))
        ]
Example #18
0
    def __init__(self):
        self.busy = Signal()
        self.sink = Endpoint([('d', 8)])
        self.source = Endpoint(CMD_REC)

        sm = FSM(reset_state="IDLE")
        self.submodules += sm

        # Basic checksum

        token = self.source.payload
        token_next = Record(CMD_REC)

        self.sync += token.eq(token_next)
        self.comb += token_next.eq(token)

        sm.act(
            "IDLE", self.sink.ack.eq(1),
            If(self.sink.stb, If(self.sink.payload.d == 0x55,
                                 NextState("ADRH"))))

        def parse_state(st, to, *update):
            sm.act(st, self.sink.ack.eq(1),
                   If(self.sink.stb, NextState(to), *update))

        parse_state('ADRH', 'ADRL', token_next.wr.eq(self.sink.payload.d[7]),
                    token_next.a[8:14].eq(self.sink.payload.d[:6]))

        parse_state('ADRL', 'DATA', token_next.a[0:8].eq(self.sink.payload.d)),
        parse_state('DATA', 'CKSUM', token_next.d.eq(self.sink.payload.d)),

        sm.act("CKSUM", self.sink.ack.eq(1),
               If(self.sink.stb, NextState('ISSUE')))

        sm.act("ISSUE", self.source.stb.eq(1),
               If(self.source.ack, NextState('IDLE')))
Example #19
0
    def __init__(self, pads, clk=10.):
        self.source = do = Endpoint(bus_layout)
        self.busy = Signal()

        # t_RDLl_Dv = 50 ns (setup)
        # t_RDLh_Di = 0ns (hold)
        # t_RDLl_RDLh = 50 ns (redundant, <= r_RDLl_Dv)
        # t_RDLh_RXFLh = 25ns (from FT245R) (redundant, <= t_RDLh_RDLl)
        # t_RXFLh_RXFLl = 80ns (from FT245R)
        # t_RDLh_RDLl = 50ns + t_RXh_RXl (we understand this as a
        #    conditional addition)

        # we read every t_hold + t_precharge + t_setup + 2 cycles
        # can only sustain 1MByte/s anyway at full speed USB
        # stb implicitly needs to be acked within a read cycle
        #clk /= 4 # slow it down
        t_latch = int(ceil(50 / clk)) + 2  # t_RDLl_Dv + slave skew
        t_drop = t_latch + 2  # slave skew
        t_refill = t_drop + int(ceil(50 / clk))  # t_RDLh_RDLl

        reading = Signal()
        rxfl = Signal()
        rd_in = Signal()
        # proxy rxfl to slaves, drive rdl
        self.comb += [
            pads.rdl.eq(~pads.g1_out),
            self.busy.eq(~do.stb | do.ack)
        ]
        self.specials += [
            MultiReg(pads.rxfl, rxfl),
            MultiReg(pads.g1_in, rd_in),
        ]
        self.sync += [
            If(
                ~reading & ~rd_in,
                pads.g1_out.eq(~rxfl),
            ),
            do.stb.eq(do.stb & ~do.ack),
            timeline(rd_in, [
                (0, [reading.eq(1)]),
                (t_latch, [do.stb.eq(1),
                           do.payload.data.eq(pads.data)]),
                (t_drop, [pads.g1_out.eq(0)]),
                (t_refill, [reading.eq(0)]),
            ])
        ]
Example #20
0
    def __init__(self, n, scale, **kwargs):
        pipe = dict(a=1, b=2, c=0, d=1, ad=1, m=1, p=1)
        self.submodules.dsp = DSP(pipe=pipe, **kwargs)
        width = len(self.dsp.a), True
        self.submodules.coeff = SRStorage(n, (len(self.dsp.b), True),
                                          mode="circular")
        self.submodules.sample = SRStorage(n, width, mode="old-first")
        self.output = Endpoint([("data", (len(self.dsp.pr), True))])
        self.bias = Signal.like(self.dsp.c, reset=(1 << max(0, scale - 1)) - 1)

        p_dsp = 4  # a/d/b0, ad/b1, m, p
        eop_pipe = Signal(p_dsp)
        ack_dsp = Signal()
        self.sync += [
            If(
                ack_dsp,
                eop_pipe.eq(Cat(self.sample.out.eop, eop_pipe)),
            ),
        ]
        self.comb += [
            self.sample.load.eop.eq(1),
            self.coeff.load.stb.eq(self.sample.load.stb),  # ignore ack
            ack_dsp.eq(self.sample.out.stb
                       & (~self.output.stb | self.output.ack)),
            self.sample.out.ack.eq(ack_dsp),
            self.coeff.out.ack.eq(ack_dsp),  # ignore stb
            self.dsp.a.eq(self.sample.out.data),
            self.dsp.cea0.eq(ack_dsp),
            self.dsp.ced0.eq(ack_dsp),
            self.dsp.cead0.eq(ack_dsp),
            self.dsp.b.eq(self.coeff.out.data),
            self.dsp.ceb0.eq(ack_dsp),
            self.dsp.ceb1.eq(ack_dsp),
            If(
                eop_pipe[-1],
                self.dsp.c.eq(self.bias),
            ).Else(self.dsp.c.eq(self.dsp.pr), ),
            self.dsp.cem0.eq(ack_dsp),
            self.dsp.cep0.eq(ack_dsp),
            self.output.data.eq(self.dsp.pr >> scale),
            self.output.stb.eq(eop_pipe[-1]),
        ]
Example #21
0
    def __init__(self, width, cordic_gain):
        self.clr = Signal(3, reset=0b111)
        self.iq_en = Signal(2, reset=0b01)
        self.limits = [[Signal((width, True)), Signal((width, True))]
                for i in range(2)]
        limit = (1 << width - 1) - 1
        limit_cordic = int(limit/cordic_gain)
        self.limits[0][0].reset = Constant(-limit, (width, True))
        self.limits[0][1].reset = Constant(limit, (width, True))
        self.limits[1][0].reset = Constant(-limit_cordic, (width, True))
        self.limits[1][1].reset = Constant(limit_cordic, (width, True))
        # TODO make persistent, add read-out/notification/clear
        self.clipped = [Signal(2) for i in range(2)]
        self.i = Endpoint([("addr", bits_for(4 + 2*len(self.limits) - 1)),
                           ("data", width)])
        assert len(self.i.addr) == 3
        self.ce = Signal()

        ###

        div = Signal(16, reset=0)
        n = Signal.like(div)

        self.comb += self.ce.eq(n == 0)
        self.sync += [
            n.eq(n - 1),
            If(self.ce,
                n.eq(div),
            )
        ]

        pad = Signal()

        reg = Array(sum(self.limits,
            [Cat(div, n), self.clr, self.iq_en, pad]))

        self.comb += self.i.ack.eq(1)
        self.sync += [
            If(self.i.stb,
                reg[self.i.addr].eq(self.i.data),
            ),
        ]
Example #22
0
File: comm.py Project: olsonse/pdq
class FTDI2SPI(Module):
    """Converts parallel data stream from FTDI chip into framed
    SPI-like data.

    It uses the :class:`Unescaper` to to detect escaped start-of-frame SOF
    and EOF characters.

    Attributes:
        sink (Endpoint): Raw data from FTDI parallel bus.
        source (Endpoint): Framed data stream (eop asserted when there is no
            active frame).
    """
    def __init__(self):
        self.sink = Endpoint(bus_layout)
        self.source = Endpoint(bus_layout)
        self.source.eop.reset = 1

        ###

        unesc = Unescaper(bus_layout)
        self.submodules += unesc
        self.sync += [
            If(
                unesc.source1.stb,
                Case(unesc.source1.data, {
                    0x02: self.source.eop.eq(0),
                    0x03: self.source.eop.eq(1),
                }),
            )
        ]
        self.comb += [
            self.sink.connect(unesc.sink),
            self.source.data.eq(unesc.source0.data),
            self.source.stb.eq(unesc.source0.stb),
            unesc.source0.ack.eq(self.source.ack),
            unesc.source1.ack.eq(1),
        ]
Example #23
0
File: comm.py Project: m-labs/pdq2
    def __init__(self):
        self.sink = Endpoint(bus_layout)
        self.source = Endpoint(bus_layout)
        self.source.eop.reset = 1

        ###

        unesc = Unescaper(bus_layout)
        self.submodules += unesc
        self.sync += [
            If(unesc.source1.stb,
                Case(unesc.source1.data, {
                    0x02: self.source.eop.eq(0),
                    0x03: self.source.eop.eq(1),
                }),
            )
        ]
        self.comb += [
            self.sink.connect(unesc.sink),
            self.source.data.eq(unesc.source0.data),
            self.source.stb.eq(unesc.source0.stb),
            unesc.source0.ack.eq(self.source.ack),
            unesc.source1.ack.eq(1),
        ]
Example #24
0
File: comm.py Project: m-labs/pdq2
class FTDI2SPI(Module):
    """Converts parallel data stream from FTDI chip into framed
    SPI-like data.

    It uses the :class:`Unescaper` to to detect escaped start-of-frame SOF
    and EOF characters.

    Attributes:
        sink (Endpoint): Raw data from FTDI parallel bus.
        source (Endpoint): Framed data stream (eop asserted when there is no
            active frame).
    """
    def __init__(self):
        self.sink = Endpoint(bus_layout)
        self.source = Endpoint(bus_layout)
        self.source.eop.reset = 1

        ###

        unesc = Unescaper(bus_layout)
        self.submodules += unesc
        self.sync += [
            If(unesc.source1.stb,
                Case(unesc.source1.data, {
                    0x02: self.source.eop.eq(0),
                    0x03: self.source.eop.eq(1),
                }),
            )
        ]
        self.comb += [
            self.sink.connect(unesc.sink),
            self.source.data.eq(unesc.source0.data),
            self.source.stb.eq(unesc.source0.stb),
            unesc.source0.ack.eq(self.source.ack),
            unesc.source1.ack.eq(1),
        ]
Example #25
0
    def __init__(self, width):
        self.clr = Signal(4, reset=0b1111)
        self.iq_en = Signal(2, reset=0b01)
        self.limits = [[
            Signal((width, True), reset=-(1 << width - 1)),
            Signal((width, True), reset=(1 << width - 1) - 1)
        ] for i in range(3)]
        self.clipped = [Signal(2) for i in range(3)]  # TODO
        self.i = Endpoint([("addr", bits_for(1 + 4 + len(self.limits))),
                           ("data", 16)])
        self.ce = Signal()

        ###

        div = Signal(16, reset=0)
        n = Signal.like(div)
        pad = Signal()

        reg = Array([Cat(div, n), self.clr, self.iq_en, pad] +
                    sum(self.limits, []))

        self.comb += [
            self.i.ack.eq(1),
            self.ce.eq(n == 0),
        ]
        self.sync += [
            n.eq(n - 1),
            If(
                self.ce,
                n.eq(div),
            ),
            If(
                self.i.stb,
                reg[self.i.addr].eq(self.i.data),
            ),
        ]
Example #26
0
    def __init__(self, mux_ports):
        self.source = Endpoint([('d', 8)])

        n = len(mux_ports)

        self.submodules.rr = RoundRobin(n, SP_CE)

        granted = self.rr.grant

        release = Signal()
        request = Signal()

        released = Signal(reset=1)

        self.sync += If(self.rr.ce,
                        released.eq(0)).Elif(release, released.eq(1))

        self.comb += request.eq(self.rr.request != 0)

        self.comb += self.rr.ce.eq(request & released)

        for i, port in enumerate(mux_ports):
            _grant = Signal(name="grant_to_%d" % i)

            self.comb += [
                _grant.eq((granted == i) & ~self.rr.ce),
                If(
                    (granted == i) & ~self.rr.ce,
                    self.source.payload.d.eq(port.source.payload.d),
                    release.eq(self.source.ack & port.source.stb
                               & port.source.payload.last),
                    self.source.stb.eq(port.source.stb),
                ),
                port.source.ack.eq(self.source.ack & _grant),
                self.rr.request[i].eq(port.source.stb)
            ]
Example #27
0
    def __init__(self, width_d=16, r_max=4096, dsp_arch="xilinx"):
        l2r = int(np.ceil(np.log2(r_max)))
        assert dsp_arch in ("xilinx",
                            "lattice"), "unsupported dsp architecture"
        assert r_max % 4 == 0, "unsupported ratechange"

        ###
        self.input = Endpoint([("data", (width_d, True))])  # Data in
        self.output = Endpoint([
            ("data0", (width_d, True)),  # Data out 0
            ("data1", (width_d, True))
        ])  # Data out 1
        self.r = Signal(l2r)  # Interpolation rate
        ###

        self.dsp_arch = dsp_arch

        self.hbfstop = Signal()  # hbf stop signal
        self.inp_stall = Signal()  # global input stall (stop) signal
        self.mode2 = Signal()  # dual hbf mode
        self.mode3 = Signal()
        hbf0_step1 = Signal()  # hbf0 step1 signal if in mode 2
        hbf1_step1 = Signal()
        muxsel0 = Signal(
        )  # necessary bc big expressions in Mux condition dont work

        nr_dsps = 15
        width_coef = 18
        midpoint = (nr_dsps - 1) // 2
        bias = (1 << width_coef - 1) - 1

        #  HBF0 impulse response:
        h_0 = [
            9, 0, -32, 0, 83, 0, -183, 0, 360, 0, -650, 0, 1103, 0, -1780, 0,
            2765, 0, -4184, 0, 6252, 0, -9411, 0, 14803, 0, -26644, 0, 83046,
            131072, 83046, 0, -26644, 0, 14803, 0, -9411, 0, 6252, 0, -4184, 0,
            2765, 0, -1780, 0, 1103, 0, -650, 0, 360, 0, -183, 0, 83, 0, -32,
            0, 9
        ]
        #  HBF1 impulse response:
        h_1 = [
            69, 0, -418, 0, 1512, 0, -4175, 0, 9925, 0, -23146, 0, 81772,
            131072, 81772, 0, -23146, 0, 9925, 0, -4175, 0, 1512, 0, -418, 0,
            69
        ]
        coef_a = []
        for i, coef in enumerate(h_0[:(len(h_0) + 1) // 2:2]):
            coef_a.append(Signal((width_coef, True), reset=coef))
        coef_b = []
        for i, coef in enumerate(h_1[:(len(h_1) + 1) // 2:2]):
            coef_b.append(Signal((width_coef, True), reset=coef))

        x = [Signal((width_d, True))
             for _ in range(((len(coef_a) * 2) + 2))]  # input hbf0
        x_end_l = Signal((width_d, True))
        x1_ = [
            Signal((width_d, True)) for _ in range(((len(coef_b) * 2) + 2))
        ]  # input hbf1
        x1__ = Signal((width_d, True))  # intermediate signal

        if dsp_arch == "lattice":
            y = [Signal((36, True)) for _ in range(nr_dsps)]
            y_reg = [
                Signal((36, True)) for _ in range(((nr_dsps - 1) // 2) + 1)
            ]
        else:  # xilinx dsp arch
            y = [Signal((48, True)) for _ in range(nr_dsps)]
            y_reg = [
                Signal((48, True)) for _ in range(((nr_dsps - 1) // 2) + 1)
            ]

        # last stage: supersampled CIC interpolator
        self.submodules.cic = SuperCicUS(width_d=width_d,
                                         n=6,
                                         r_max=r_max // 4,
                                         gaincompensated=True,
                                         width_lut=18)

        # input/output handling
        self.comb += [
            self.output.stb.eq(1),
            If(
                ~self.mode3,
                self.input.ack.eq(Mux(self.mode2, hbf0_step1, 1)),
                self.output.data0.eq(y[-1][width_coef - 1:width_coef - 1 +
                                           width_d]),
                self.output.data1.eq(Mux(self.mode2, x1_[-1], x[-1])),
            ).Else(  # If CIC engaged
                self.input.ack.eq(hbf0_step1 & ~self.hbfstop),
                self.output.data0.eq(self.cic.output.data0),
                self.output.data1.eq(self.cic.output.data1),
            )
        ]

        # Interpolator mode and dataflow handling
        self.comb += [
            self.mode2.eq(Mux(self.r >= 4, 1, 0)),
            self.mode3.eq(Mux(self.r >= 8, 1, 0)),
            muxsel0.eq((~self.cic.input.ack) | (self.mode3 & hbf1_step1)),
            self.hbfstop.eq(Mux(muxsel0, 1, 0)),
            self.cic.r.eq(self.r[2:]),  # r_cic = r_inter//4
            self.cic.input.data.eq(
                Mux(hbf1_step1, y[-1][width_coef - 1:width_coef - 1 + width_d],
                    x1_[-1])),
            self.cic.input.stb.eq(self.mode3),
            x1__.eq(y[midpoint][width_coef - 1:width_coef - 1 + width_d]),
        ]
        self.sync += [
            If(
                ~self.hbfstop,
                If(
                    ~self.mode2 | (self.mode2 & hbf0_step1),
                    Cat(x).eq(Cat(self.input.data, x)),
                ),
                hbf0_step1.eq(~hbf0_step1),
                x_end_l.eq(
                    x[-4]
                ),  # last sample in inputchain (plus dsp reg delay) needs to be delayed by one clk more.

                # input to second hbf
                Cat(x1_).eq(Cat(Mux(hbf0_step1, x1__, x[-2]), x1_)),
            ),
            If(self.cic.input.ack, hbf1_step1.eq(~hbf1_step1))
        ]

        # Hardwired dual HBF upsampler DSP chain
        for i in range(nr_dsps):
            a, b, c, d, mux_p, p = self._dsp()

            if i <= ((nr_dsps - 1) // 2) - 1:  # if first HBF in mode 2
                self.comb += [
                    y[i].eq(p),
                    If(
                        ~self.mode2,
                        mux_p.eq(1),
                        a.eq(x[i * 2]),
                        d.eq(
                            x[-3]
                        ),  # third to last bc one extra samples for midpoint output
                        b.eq(coef_a[i]),
                    ).Else(  # if in mode 2
                        If(
                            ~hbf0_step1,
                            mux_p.eq(1),
                            a.eq(x[i * 4]),
                            d.eq(x_end_l),
                            b.eq(coef_a[i * 2]),
                        ).Else(
                            mux_p.eq(0),
                            a.eq(x[(i * 4) + 1]),
                            d.eq(x_end_l),
                            b.eq(coef_a[(i * 2) + 1]),
                        ))
                ]
                self.sync += [If(~hbf0_step1 & ~self.hbfstop, y_reg[i].eq(p))]
                if i >= 1:
                    self.comb += [
                        c.eq(Mux(self.mode2, y_reg[i - 1], y[i - 1])),
                        #c.eq(y[i-1])
                    ]
                else:
                    self.comb += c.eq(bias)

            elif i == midpoint:
                self.comb += [
                    y[i].eq(p),
                    c.eq(Mux(self.mode2, y_reg[i - 1], y[i - 1])),
                    If(
                        ~self.mode2,
                        mux_p.eq(1),
                        a.eq(x[i * 2]),
                        d.eq(
                            x[-3]
                        ),  # third to last bc one extra samples for midpoint output
                        b.eq(coef_a[i]),
                    ).Else(  # if in mode 2
                        If(
                            ~hbf0_step1,
                            mux_p.eq(1),
                            a.eq(x[i * 4]),
                            d.eq(x_end_l),
                            b.eq(coef_a[i * 2]),
                        ).Else(
                            mux_p.eq(0),
                            a.eq(x[(i * 4) + 1]),
                            d.eq(x_end_l),
                            b.eq(0),
                        ))
                ]

            elif i == midpoint + 1:  # second half of dsp chain
                self.comb += [
                    y[i].eq(p),
                    If(
                        ~self.mode2,
                        mux_p.eq(1),
                        a.eq(x[i * 2]),
                        d.eq(
                            x[-3]
                        ),  # third to last bc one extra samples for midpoint output
                        b.eq(coef_a[i]),
                        y[i].eq(p),
                        c.eq(y[i - 1])).
                    Else(
                        mux_p.eq(1),
                        a.eq(x1_[(i - midpoint - 1) * 2]),
                        d.eq(
                            x1_[-3]
                        ),  # third to last bc one extra samples for midpoint output
                        b.eq(coef_b[i - midpoint - 1]),
                        y[i].eq(p),
                        c.eq(bias))
                ]

            else:  # second half of dsp chain
                self.comb += [
                    y[i].eq(p),
                    If(
                        ~self.mode2,
                        mux_p.eq(1),
                        a.eq(x[i * 2]),
                        d.eq(
                            x[-3]
                        ),  # third to last bc one extra samples for midpoint output
                        b.eq(coef_a[i]),
                        y[i].eq(p),
                        c.eq(y[i - 1])).
                    Else(
                        mux_p.eq(1),
                        a.eq(x1_[(i - midpoint - 1) * 2]),
                        d.eq(
                            x1_[-3]
                        ),  # third to last bc one extra samples for midpoint output
                        b.eq(coef_b[i - midpoint - 1]),
                        y[i].eq(p),
                        c.eq(y[i - 1]))
                ]
Example #28
0
    def __init__(self, wrport, depth, consume_watermark, ena, la_filters=[]):
        self.ulpi_sink = Endpoint(ULPI_DATA_TAG)

        self.out_addr = Endpoint(dmatpl(depth))

        # Produce side
        self.submodules.produce_write = Acc_inc(max=depth)
        self.submodules.produce_header = Acc(max=depth)

        self.consume_point = Acc(max=depth)

        self.submodules.size = Acc_inc(16)
        self.submodules.flags = Acc_or(16)

        self.submodules.to_start = Acc(1)

        # Header format:
        # A0 F0 F1 SL SH 00 00 00 d0....dN

        # Flags format
        #
        # F0.0 - ERR  - Line level error (ULPI.RXERR asserted during packet)
        # F0.1 - OVF  - RX Path Overflow (shouldn't happen - debugging)
        # F0.2 - CLIP - Filter clipped (we do not set yet)
        # F0.3 - PERR - Protocol level err (but ULPI was fine, ???)
        #
        # Following not implemented yet
        # F0.6 - SHORT - short packet, no size, fixed 4 byte data
        # F0.7 - EXT   - Extended header
        self.submodules.fsm = FSM()

        has_space = Signal()

        self.comb += has_space.eq(
            ((consume_watermark - self.produce_write.v - 1) & (depth - 1)) > 8)

        # Grab packet timestamp at SOP
        pkt_timestamp = Signal(len(self.ulpi_sink.payload.ts))
        self.sync += If(self.ulpi_sink.payload.is_start & self.ulpi_sink.ack,
                        pkt_timestamp.eq(self.ulpi_sink.payload.ts))

        payload_is_rxcmd = Signal()
        self.comb += payload_is_rxcmd.eq(self.ulpi_sink.payload.is_start
                                         | self.ulpi_sink.payload.is_end
                                         | self.ulpi_sink.payload.is_err
                                         | self.ulpi_sink.payload.is_ovf)

        # Packet first/last bits
        clear_acc_flags = Signal()

        en_last = Signal()
        self.sync += en_last.eq(ena)
        self.submodules.packet_first = Acc(1)
        self.submodules.packet_last = Acc(1)

        # Stuff-packet bit
        # At start-of-capture or end-of-capture, we stuff a packet to
        # indicate the exact time of capture
        stuff_packet = Signal()
        self.comb += stuff_packet.eq(self.packet_first.v | self.packet_last.v)

        self.comb += If(ena & ~en_last, self.packet_first.set(1)).Elif(
            clear_acc_flags, self.packet_first.set(0))

        self.comb += If(~ena & en_last,
                        self.packet_last.set(1)).Elif(clear_acc_flags,
                                                      self.packet_last.set(0))

        flags_ini = Signal(16)
        self.comb += flags_ini.eq(
            Mux(self.packet_last.v, HF0_LAST, 0)
            | Mux(self.packet_first.v, HF0_FIRST, 0))

        # Combine outputs of filters
        la_resets = [f.reset.eq(1) for f in la_filters]
        filter_done = 1
        filter_reject = 0
        for f in la_filters:
            filter_done = f.done & filter_done
            filter_reject = f.reject | filter_reject

        self.fsm.act(
            "IDLE",
            If(((self.ulpi_sink.stb | self.to_start.v) & ena
                | stuff_packet) & has_space,
               If(~self.to_start.v | (self.ulpi_sink.stb & stuff_packet),
                  self.ulpi_sink.ack.eq(1)),
               self.produce_write.set(self.produce_header.v + 8),
               self.size.set(0), self.flags.set(flags_ini),
               self.to_start.set(0), la_resets,
               If(self.ulpi_sink.payload.is_start | self.to_start.v,
                  NextState("DATA")).Elif(
                      stuff_packet,
                      NextState("WH0"),
                      clear_acc_flags.eq(1),
                  )

               # If not enabled, we just dump RX'ed data
               ).Elif(~ena, self.ulpi_sink.ack.eq(1)))

        def write_hdr(statename, nextname, hdr_offs, val):
            self.fsm.act(statename, NextState(nextname),
                         wrport.adr.eq(self.produce_header.v + hdr_offs),
                         wrport.dat_w.eq(val), wrport.we.eq(1))

        do_filter_write = Signal()

        # Feed data to lookaside filters
        for f in la_filters:
            self.comb += [
                f.write.eq(do_filter_write),
                f.dat_w.eq(self.ulpi_sink.payload)
            ]

        packet_too_long = Signal()
        self.comb += packet_too_long.eq(self.size.v >= MAX_PACKET_SIZE)

        self.fsm.act(
            "DATA",
            If(packet_too_long, self.flags._or(HF0_TRUNC),
               NextState("WH0")).Elif(
                   has_space & self.ulpi_sink.stb,
                   self.ulpi_sink.ack.eq(1),
                   If(
                       payload_is_rxcmd,

                       # Got another start-of-packet
                       If(
                           self.ulpi_sink.payload.is_start,
                           self.flags._or(HF0_OVF),

                           # If we got a SOP, we need to skip RXCMD det in IDLE
                           self.to_start.set(1)

                           # Mark error if we hit an error
                       ).Elif(
                           self.ulpi_sink.payload.is_err,
                           self.flags._or(HF0_ERR),

                           # Mark overflow if we got a stuffed overflow
                       ).Elif(self.ulpi_sink.payload.is_ovf,
                              self.flags._or(HF0_OVF)),

                       # In any case (including END), we're done RXing
                       NextState("waitdone")).Else(
                           self.size.inc(), self.produce_write.inc(),
                           wrport.adr.eq(self.produce_write.v),
                           wrport.dat_w.eq(self.ulpi_sink.payload.d),
                           wrport.we.eq(1), do_filter_write.eq(1))))

        self.fsm.act(
            "waitdone",
            If(
                filter_done,
                If(filter_reject,
                   NextState("IDLE")).Else(clear_acc_flags.eq(1),
                                           NextState("WH0"))))

        write_hdr("WH0", "WRF0", 0, 0xA0)

        # Write flags field
        write_hdr("WRF0", "WRF1", 1, self.flags.v[:8])
        write_hdr("WRF1", "WRSL", 2, self.flags.v[8:16])

        # Write size field
        write_hdr("WRSL", "WRSH", 3, self.size.v[:8])
        write_hdr("WRSH", "WRTL", 4, self.size.v[8:16])

        write_hdr("WRTL", "WRTM", 5, pkt_timestamp[:8])
        write_hdr("WRTM", "WRTH", 6, pkt_timestamp[8:16])
        write_hdr("WRTH", "SEND", 7, pkt_timestamp[16:24])

        self.fsm.act(
            "SEND", self.out_addr.stb.eq(1),
            self.out_addr.payload.start.eq(self.produce_header.v),
            self.out_addr.payload.count.eq(self.size.v + 8),
            If(self.out_addr.ack,
               self.produce_header.set(self.produce_write.v),
               NextState("IDLE")))
Example #29
0
 def __init__(self):
     self.source = Endpoint(ULPI_DATA_D)
     SimActor.__init__(self, gen())
Example #30
0
    def __init__(self,
                 width_d=16,
                 n=6,
                 r_max=2048,
                 gaincompensated=True,
                 width_lut=18):
        if r_max < 2:
            raise ValueError()
        if n < 1:
            raise ValueError()
        b_max = np.ceil(np.log2(r_max))  # max bit growth

        ###
        self.input = Endpoint([("data", (width_d, True))])
        if gaincompensated:
            self.output = Endpoint([("data0", (width_d, True)),
                                    ("data1", (width_d, True))])
        else:
            self.output = Endpoint([
                ("data0", (width_d + int(np.ceil(np.log2(r_max**(n - 1)))),
                           True)),
                ("data1", (width_d + int(np.ceil(np.log2(r_max**(n - 1)))),
                           True))
            ])
        self.r = Signal(int(np.ceil(np.log2(
            r_max))))  # rate input (always at least two due to supersampling)
        ###

        self.width_d = width_d

        i = Signal.like(self.r)
        comb_ce = Signal()
        inp_stall = Signal()
        inp_stall_reg = Signal()
        r_reg = Signal.like(self.r)
        f_rst = Signal()

        self.comb += f_rst.eq(self.r != r_reg)  # handle ratechange

        # Filter "clocking" from the input. Halts if no new samples.
        self.comb += [
            comb_ce.eq(self.input.ack & self.input.stb),
            self.output.stb.eq(~inp_stall),
            self.input.ack.eq((i == 0) | inp_stall_reg | (i == r_reg[1:])),
            inp_stall.eq(self.input.ack & ~self.input.stb)
        ]

        self.sync += [inp_stall_reg.eq(inp_stall)]

        self.sync += [
            r_reg.eq(self.r),
            If(
                ~inp_stall,
                i.eq(i + 1),
            ),
            If(
                (i == r_reg - 1) | f_rst,
                i.eq(0),
            ),
        ]

        if gaincompensated:
            sig, shift = self._tweak_gain(r_reg,
                                          r_max,
                                          n,
                                          self.input.data,
                                          width_lut=width_lut)
        else:
            sig = self.input.data

        width = len(sig)

        # comb stages, one pipeline stage each
        for _ in range(n):
            old = Signal((width, True))
            width += 1
            diff = Signal((width, True))
            self.sync += [
                If(comb_ce, old.eq(sig), diff.eq(sig - old)),
                If(f_rst, old.eq(0), diff.eq(0))
            ]

            sig = diff

        # zero stuffer, gearbox, and first integrator, one pipeline stage
        width -= 1
        sig_a = Signal((width, True))
        sig_b = Signal((width, True))
        sig_i = Signal((width, True))
        self.comb += [
            sig_i.eq(sig_b + sig),
        ]
        self.sync += [
            sig_a.eq(sig_b),
            If(comb_ce, If(
                (i == 0) & r_reg[0],
                sig_a.eq(sig_i),
            ), sig_b.eq(sig_i)),
            If(
                f_rst,
                sig_a.eq(0),
                sig_b.eq(0),
            )
        ]

        # integrator stages, two pipeline stages each
        for _ in range(n - 1):
            sig_a0 = Signal((width, True))
            sum_ab = Signal((width + 1, True))
            width += int(b_max - 1)
            sum_a = Signal((width, True))
            sum_b = Signal((width, True))
            self.sync += [
                If(
                    ~inp_stall,
                    sig_a0.eq(sig_a),
                    sum_ab.eq(sig_a + sig_b),
                    sum_a.eq(sum_b + sig_a0),
                    sum_b.eq(sum_b + sum_ab),
                ),
                If(
                    f_rst,
                    sig_a0.eq(0),
                    sum_ab.eq(0),
                    sum_a.eq(0),
                    sum_b.eq(0),
                )
            ]
            sig_a, sig_b = sum_a, sum_b

        if gaincompensated:
            self.comb += [
                self.output.data0.eq(sig_a >> shift),
                self.output.data1.eq(sig_b >> shift),
            ]
        else:
            self.comb += [
                self.output.data0.eq(sig_a),
                self.output.data1.eq(sig_b),
            ]
Example #31
0
    def __init__(self, coeff, width_d, width_coef, dsp_arch="xilinx"):

        assert dsp_arch in ("xilinx",
                            "lattice"), "unsupported dsp architecture"
        self.dsp_arch = dsp_arch
        n = (len(coeff) + 1) // 4
        if len(coeff) != n * 4 - 1:
            raise ValueError("HBF length must be 4*n-1", coeff)
        elif n < 2:
            raise ValueError("Need order n >= 2")
        for i, c in enumerate(coeff):
            if i == n * 2 - 1:
                if not c:
                    raise ValueError("HBF center tap must not be zero")
            elif i & 1:
                if c:
                    raise ValueError("HBF even taps must be zero", (i, c))
            elif not c:
                raise ValueError("HBF needs odd taps", (i, c))
            elif c != coeff[-1 - i]:
                raise ValueError("HBF must be symmetric", (i, c))

        dsp_pipelen = 4
        bias = (1 << width_coef - 1) - 1
        coef = []
        for i, c in enumerate(coeff[:(len(coeff) + 1) // 2:2]):
            coef.append(
                Signal((width_coef + 1, True), reset_less=True, reset=c))

        self.input = Endpoint([("data", (width_d, True))])
        self.output = Endpoint([("data", (width_d, True))])

        x = [
            Signal((width_d, True), reset_less=True)
            for _ in range((len(coef) * 2))
        ]  # input hbf

        self.stop = Signal()  # filter output stall signal
        pos = Signal(int(np.ceil(np.log2(len(coef)))))
        pos_neg = Signal(len(pos) + 1)

        self.comb += [
            self.stop.eq(
                self.output.stb & ~self.output.ack
            )  # filter is sensitive to output and ignores input stb
        ]

        a, b, c, d, mux_p, p = self._dsp()

        self.comb += [
            pos_neg.eq((len(coef) * 2) - 1 -
                       pos),  # position from end of input shift reg
            c.eq(bias),
            a.eq(Array(x)[pos]),
            d.eq(Array(x)[pos_neg]),
            b.eq(Array(coef)[pos]),
        ]

        self.sync += [
            If(
                ~self.stop,
                self.input.ack.eq(0),  # default no in ack
                self.output.stb.eq(0),  # default no out strobe
                mux_p.eq(0),  # default accumulate
                pos.eq(pos + 1),
                If(
                    pos == len(coef) - 1,  # new input sample
                    pos.eq(0),
                    Cat(x).eq(Cat(self.input.data, x)),  # shift in new sample
                    self.input.ack.eq(1),
                ),
                If(
                    pos == dsp_pipelen - 2,
                    mux_p.eq(1),
                ),
                If(
                    pos == dsp_pipelen -
                    1,  # new output sample at the end of the dsp pipe
                    self.output.data.eq(p >> width_coef),
                    self.output.stb.eq(1),
                ),
                If(
                    pos == (len(coef) // 2) + dsp_pipelen -
                    1,  # emit trivial sample at halfway computation + pipelen
                    self.output.data.eq(x[len(coef)]),
                    self.output.stb.eq(1),
                ))
        ]

        if dsp_pipelen > (len(coef) // 2):  # if dsp pipe too long
            self.sync += [
                If(
                    pos == ((len(coef) // 2) + dsp_pipelen - 1) %
                    (len(coef) // 2),
                    # emit trivial sample at halfway computation + pipelen
                    self.output.data.eq(x[len(coef) + 1]),
                    self.output.stb.eq(1),
                )
            ]
Example #32
0
    def __init__(self, hostif, max_burst_length=256):
        width = len(hostif.d_write)
        assert width == 16

        awidth = len(hostif.i_addr) + 1

        self.sink = Endpoint([('d', 8), ('last', 1)])

        self.submodules.sdram_fifo = SyncFIFO(width, max_burst_length)

        self.submodules.fifo_write_fsm = FSM()

        self.wptr = Signal(awidth)

        # rptr (from SDRAM Source)
        self.rptr = Signal(awidth)

        # CSRs

        self._ptr_read = CSRStorage(1)
        ptr_read = self._ptr_read.re
        self._wptr = CSRStatus(awidth)
        self.sync += If(ptr_read, self._wptr.status.eq(self.wptr))
        self._rptr = CSRStatus(awidth)
        self.sync += If(ptr_read, self._rptr.status.eq(self.rptr))

        self._ring_base = CSRStorage(awidth)
        self._ring_end = CSRStorage(awidth)
        self._go = CSRStorage(1)

        go = self._go.storage[0]

        # 'go'-signal edge detect
        gor = Signal()
        self.sync += gor.eq(go)

        self._wrap_count = Perfcounter(ptr_read, go & ~gor)

        # wptr wrap around

        wrap = Signal()
        self.comb += wrap.eq(self.wptr == self._ring_end.storage)
        wptr_next = Signal(awidth)
        self.comb += If(wrap, wptr_next.eq(self._ring_base.storage)).Else(
            wptr_next.eq(self.wptr + 1))

        # debug

        self._debug_ctl = CSRStorage(1)
        snapshot = self._debug_ctl.re
        perf_reset = self._debug_ctl.storage[0]
        self._debug_i_stb = Perfcounter(snapshot, perf_reset)
        self._debug_i_ack = Perfcounter(snapshot, perf_reset)
        self._debug_d_stb = Perfcounter(snapshot, perf_reset)
        self._debug_d_term = Perfcounter(snapshot, perf_reset)
        self._debug_s0 = Perfcounter(snapshot, perf_reset)
        self._debug_s1 = Perfcounter(snapshot, perf_reset)
        self._debug_s2 = Perfcounter(snapshot, perf_reset)
        self._perf_busy = Perfcounter(snapshot, perf_reset)

        self.comb += If(hostif.i_stb, self._debug_i_stb.inc())
        self.comb += If(hostif.i_ack, self._debug_i_ack.inc())
        self.comb += If(hostif.d_stb, self._debug_d_stb.inc())
        self.comb += If(hostif.d_term, self._debug_d_term.inc())
        self.comb += If(~self.sdram_fifo.writable, self._perf_busy.inc())

        # FSM to move FIFO data to SDRAM

        burst_rem = Signal(max=max_burst_length)
        burst_rem_next = Signal(max=max_burst_length)

        self.comb += burst_rem_next.eq(burst_rem)
        self.sync += burst_rem.eq(burst_rem_next)

        self.comb += hostif.i_wr.eq(1)

        blocked = Signal()

        self.comb += blocked.eq(self.rptr == wptr_next)

        # start writing data if
        # - 'go'-signal set, and
        # - input data available
        # - not blocked

        self.fifo_write_fsm.act(
            "IDLE", self._debug_s0.inc(),
            If(self.sdram_fifo.readable & go & ~blocked,
               hostif.i_addr.eq(self.wptr), hostif.i_stb.eq(1),
               burst_rem_next.eq(max_burst_length - 1)),
            If(hostif.i_ack, NextState("WRITE")))

        self.comb += hostif.d_write.eq(self.sdram_fifo.dout)

        # stop writing if
        # - max burst length reached, or
        # - no more input data, or
        # - wrap
        # - blocked

        self.fifo_write_fsm.act(
            "WRITE",
            self._debug_s1.inc(),
            hostif.d_term.eq((burst_rem == 0) | ~self.sdram_fifo.readable
                             | wrap | blocked),
            self.sdram_fifo.re.eq(hostif.d_stb & ~hostif.d_term),
            If(
                ~hostif.d_term & hostif.d_stb,
                burst_rem_next.eq(
                    burst_rem -
                    1)  # CHECKME: was burst_rem_next - 1 which is a comb loop
            ),
            If(hostif.d_term & ~hostif.d_stb,
               NextState("WAIT")).Elif(hostif.d_term & hostif.d_stb,
                                       NextState("IDLE")))

        self.fifo_write_fsm.act("WAIT", self._debug_s2.inc(),
                                hostif.d_term.eq(1),
                                If(hostif.d_stb, NextState("IDLE")))

        # wrap around counter
        self.comb += If(wrap & hostif.d_stb & ~hostif.d_term,
                        self._wrap_count.inc())

        # update wptr
        self.sync += If(
            go & ~gor,
            self.wptr.eq(self._ring_base.storage),
        ).Elif((hostif.d_stb & ~hostif.d_term) | wrap, self.wptr.eq(wptr_next))

        # sink into fifo

        self.submodules.fifo_fsm = FSM()

        capture_low = Signal()
        din_low = Signal(8)

        self.comb += self.sdram_fifo.din.eq(Cat(din_low, self.sink.payload.d))

        self.sync += If(capture_low, din_low.eq(self.sink.payload.d))

        self.fifo_fsm.act("READ_LOW", capture_low.eq(1), self.sink.ack.eq(1),
                          If(self.sink.stb, NextState("READ_HI")))

        self.fifo_fsm.act(
            "READ_HI", self.sdram_fifo.we.eq(self.sink.stb),
            self.sink.ack.eq(self.sdram_fifo.writable),
            If(self.sink.ack & self.sink.stb, NextState("READ_LOW")))
Example #33
0
 def __init__(self):
     self.source = Endpoint(ULPI_DATA_TAG)
     SimActor.__init__(self, _deferred_source_gen())
Example #34
0
 def __init__(self):
     self.sink = Endpoint(dmatpl(1024))
     SimActor.__init__(self, _deferred_sink_gen())