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), ) ]
class InterpolateChannel(Module): 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), ]
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), ) ]
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), ]
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), ]