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)]
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), ]
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), ), ), ]
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), ]
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), ), ]
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), ) ]
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), ) ]
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
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")))
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), ) ]
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), ) ]
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), ) ]
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"))))
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"))))
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)))
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), ]
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), )) ]
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')))
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)]), ]) ]
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]), ]
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), ), ]
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), ]
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), ]
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), ]
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), ), ]
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) ]
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])) ]
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")))
def __init__(self): self.source = Endpoint(ULPI_DATA_D) SimActor.__init__(self, gen())
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), ]
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), ) ]
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")))
def __init__(self): self.source = Endpoint(ULPI_DATA_TAG) SimActor.__init__(self, _deferred_source_gen())
def __init__(self): self.sink = Endpoint(dmatpl(1024)) SimActor.__init__(self, _deferred_sink_gen())