class I2S_RX(Elaboratable): def __init__(self, i2s_resource, output_bit_depth=16, i2s_domain="i2s"): self.output_bit_depth = output_bit_depth self.i2s_resource = i2s_resource self.i2s_domain = i2s_domain self.l_output = BasicStream(output_bit_depth) self.r_output = BasicStream(output_bit_depth) def elaborate(self, platform): m = Module() i2s_domain = ClockDomain(self.i2s_domain) m.domains += i2s_domain m.d.comb += i2s_domain.clk.eq(self.i2s_resource.sck) l_buffer_input = BasicStream(self.output_bit_depth) r_buffer_input = BasicStream(self.output_bit_depth) delayed_ws = delay_by(self.i2s_resource.ws, 1, m) with m.FSM(): for i in range(self.output_bit_depth + 1): with m.State(f'bit_{i}'): with m.If(delayed_ws != self.i2s_resource.ws): m.next = "bit_0" with m.Else(): if i < self.output_bit_depth: m.next = f"bit_{i + 1}" if i < self.output_bit_depth: with m.If(delayed_ws): m.d.sync += r_buffer_input.payload[ self.output_bit_depth - i - 1].eq( self.i2s_resource.sd) with m.Else(): m.d.sync += l_buffer_input.payload[ self.output_bit_depth - i - 1].eq( self.i2s_resource.sd) if i == 0: with m.If(delayed_ws): m.d.comb += r_buffer_input.valid.eq(1) with m.Else(): m.d.comb += l_buffer_input.valid.eq(1) l_buffer = m.submodules.buffer_l = StreamBuffer(l_buffer_input) m.d.comb += self.l_output.connect_upstream(l_buffer.output) r_buffer = m.submodules.buffer_r = StreamBuffer(r_buffer_input) m.d.comb += self.r_output.connect_upstream(r_buffer.output) return DomainRenamer(self.i2s_domain)(m)
class GenericMetadataWrapper(Elaboratable): def __init__(self, input: BasicStream, core_producer, fifo_depth=128): self.fifo_depth = fifo_depth self.input = input self.core_input = BasicStream(input.payload.shape()) self.core = core_producer(self.core_input) self.core_output = self.core.output self.output = self.input.clone() self.output.payload = Signal(len(self.core_output.payload)) @ DOWNWARDS def elaborate(self, platform): m = Module() m.submodules.core = self.core tee = m.submodules.tee = StreamTee(self.input) m.d.comb += self.core_input.connect_upstream(tee.get_output(), allow_partial=True) metadata_fifo_input = Stream() for name, s in self.input.out_of_band_signals.items(): setattr(metadata_fifo_input, name, Signal.like(s) @ DOWNWARDS) m.d.comb += metadata_fifo_input.connect_upstream(tee.get_output(), allow_partial=True) metadata_fifo = m.submodules.metadata_fifo = BufferedSyncStreamFIFO( metadata_fifo_input, self.fifo_depth) combiner = m.submodules.combiner = StreamCombiner( self.core_output, metadata_fifo.output) m.d.comb += self.output.connect_upstream(combiner.output) return m
class InputGearbox(Elaboratable): def __init__(self, input, output_width): self.input = input self.output_width = output_width self.word_alignment = StatusSignal(range(output_width)) self.output = BasicStream(output_width) def elaborate(self, platform): m = Module() gearbox = m.submodules.gearbox = StreamGearbox(self.input, self.output_width) window = m.submodules.window = StreamWindow(gearbox.output, window_words=2) select = m.submodules.select = StreamSelect( window.output, output_width=self.output_width) m.d.comb += self.output.connect_upstream(select.output) return m
class AxiReader(Elaboratable): def __init__( self, address_source: BasicStream, axi=None, axi_data_width=64, ): self.address_source = address_source self.axi = axi self.output = BasicStream(axi_data_width, name="buffer_reader_output_stream") self.output.payload = Signal(axi_data_width) self.last_resp = StatusSignal(AxiResponse) self.error_count = StatusSignal(32) def elaborate(self, platform): m = Module() axi = if_none_get_zynq_hp_port(self.axi, m, platform) assert len(self.output.payload) == axi.data_bits assert len(self.address_source.payload) == axi.addr_bits for fifo_signal_name in [ "read_address_fifo_level", "read_data_fifo_level" ]: if hasattr(axi, fifo_signal_name): axi_fifo_signal = axi[fifo_signal_name] fifo_signal = StatusSignal(axi_fifo_signal.shape(), name=f"axi_{fifo_signal_name}") m.d.comb += fifo_signal.eq(axi_fifo_signal) setattr(self, f"axi_{fifo_signal_name}", fifo_signal) burster = m.submodules.burster = AxiReaderBurster( self.address_source, data_bytes=axi.data_bytes) m.d.comb += axi.read_address.connect_upstream(burster.output) m.d.comb += self.output.connect_upstream(axi.read_data, allow_partial=True) return m