示例#1
0
    def elaborate(self, platform):
        m = Module()

        sink = StreamEndpoint.like(self.input_stream,
                                   is_sink=True,
                                   name="ft601_sink")
        m.d.comb += sink.connect(self.input_stream)

        ft = self.ft_601_resource

        m.d.comb += ft.be.oe.eq(1)
        m.d.comb += ft.be.o.eq(0b1111)  # everything we write is valid

        m.d.comb += ft.oe.eq(0)  # we are driving the data bits all the time
        m.d.comb += ft.data.oe.eq(1)
        m.d.comb += platform.request("led", 0).eq(ft.write)

        if self.safe_to_begin_new_transaction is None:
            m.d.comb += ft.data.o.eq(sink.payload)
            m.d.comb += sink.ready.eq(ft.txe)
            m.d.comb += ft.write.eq(sink.valid)
        else:
            in_transaction = Signal()
            m.d.sync += in_transaction.eq(ft.write)
            with m.If(in_transaction):
                m.d.comb += ft.write.eq(sink.valid & ft.txe)
                m.d.comb += sink.ready.eq(ft.txe)
            with m.Else():
                m.d.comb += ft.write.eq(sink.valid
                                        & self.safe_to_begin_new_transaction)
                m.d.comb += sink.ready.eq(ft.txe
                                          & self.safe_to_begin_new_transaction)
            m.d.comb += ft.data.o.eq(sink.payload)

        return m
示例#2
0
    def elaborate(self, platform: ZynqSocPlatform):
        m = Module()

        platform.ps7.fck_domain(requested_frequency=200e6)
        m.d.comb += ResetSignal().eq(self.reset)

        ring_buffer = RingBufferAddressStorage(buffer_size=0x1200000, n=4)

        stream_source = StreamEndpoint(64, is_sink=False, has_last=True)
        m.d.comb += self.data_ready.eq(stream_source.ready)
        m.d.comb += stream_source.valid.eq(self.data_valid)

        clock_signal = Signal()
        m.d.comb += clock_signal.eq(ClockSignal())
        axi_slave = platform.ps7.get_axi_hp_slave(clock_signal)
        axi_writer = m.submodules.axi_writer = AxiBufferWriter(ring_buffer, stream_source, axi_slave=axi_slave)

        with m.If(axi_writer.stream_source.ready & axi_writer.stream_source.valid):
            m.d.sync += self.data_counter.eq(self.data_counter + 1)
        m.d.comb += stream_source.payload.eq(Cat(self.data_counter, self.data_counter+1000))

        with m.If((stream_source.valid) & (axi_writer.words_written < (self.to_write >> int(math.log2(axi_slave.data_bytes))))):
            m.d.sync += self.perf_counter.eq(self.perf_counter+1)

        return m
示例#3
0
    def elaborate(self, platform):
        m = Module()

        sink = StreamEndpoint.like(self.input,
                                   is_sink=True,
                                   name="plugin_module_streamer_sink")
        m.d.comb += sink.connect(self.input)

        m.d.comb += self.plugin_lvds.valid.eq(sink.valid & ~self.do_training)
        m.d.comb += sink.ready.eq(1)

        m.d.comb += self.plugin_lvds.clk_word.eq(ClockSignal())

        for i in range(4):
            value = Signal()
            m.submodules["lane{}".format(i)] = DDRSerializer(
                self.plugin_lvds["lvds{}".format(i)],
                value,
                ddr_clockdomain=self.bitclk_domain)
            with m.If(self.plugin_lvds.valid):
                m.d.comb += value.eq(sink.payload[0 + (i * 8):8 + (i * 8)])
            with m.Else():
                m.d.comb += value.eq(self.training_pattern)

        return m
示例#4
0
    def test_buffer_change(self, data_len=50):
        axi = AxiEndpoint(addr_bits=32,
                          data_bits=64,
                          master=False,
                          lite=False,
                          id_bits=12)

        ringbuffer = RingBufferAddressStorage(0x1000, 2, base_address=0)
        stream_source = StreamEndpoint(64, is_sink=False, has_last=True)

        dut = AxiBufferWriter(ringbuffer,
                              stream_source,
                              axi,
                              fifo_depth=data_len)

        def testbench():
            gold = {}

            gold_gen = {
                "current_buffer": 0,
                "current_address": ringbuffer.buffer_base_list[0]
            }

            def change_buffer():
                gold_gen["current_buffer"] = (gold_gen["current_buffer"] +
                                              1) % len(
                                                  ringbuffer.buffer_base_list)
                gold_gen["current_address"] = ringbuffer.buffer_base_list[
                    gold_gen["current_buffer"]]
                yield stream_source.last.eq(1)

            def put_data(data):
                gold[gold_gen["current_address"]] = data
                gold_gen["current_address"] += axi.data_bytes
                yield stream_source.valid.eq(1)
                yield stream_source.payload.eq(data)

            # first, fill in some data:
            for i in range(data_len):
                yield from put_data(i)
                # yield dut.change_buffer.eq(0)
                yield from change_buffer()
                yield
            yield stream_source.valid.eq(0)

            memory = {}
            accepted = 0
            while accepted < data_len:
                memory_fragment, accepted_frag = (yield from
                                                  answer_write_burst(axi))
                memory.update(memory_fragment)
                accepted += accepted_frag
                yield

            self.assertEqual(gold, memory)
            self.assertFalse((yield dut.error))

        platform = SimPlatform()
        platform.add_sim_clock("sync", 100e6)
        platform.sim(dut, testbench)
    def elaborate(self, platform):
        m = Module()

        hdmi = m.submodules.hdmi = Hdmi(self.hdmi_plugin, self.modeline)

        in_pix_domain = DomainRenamer("pix")

        addr_gen = m.submodules.addr_gen = in_pix_domain(
            AddressGenerator(self.ring_buffer))
        m.d.comb += addr_gen.next_frame.eq(hdmi.timing_generator.vsync)
        m.d.comb += addr_gen.line_words_read.eq(hdmi.timing_generator.width)

        reader = m.submodules.reader = in_pix_domain(
            AxiBufferReader(addr_gen.output))
        output = StreamEndpoint.like(reader.output,
                                     is_sink=True,
                                     name="hdmi_reader_output_sink")
        m.d.comb += output.connect(reader.output)

        ctr = Signal(range(4))
        with m.If(ctr == 3):
            m.d.comb += output.ready.eq(1)
            m.d.pix += ctr.eq(0)
        with m.Else():
            m.d.pix += ctr.eq(ctr + 1)
        value = Signal(8)
        for i in range(4):
            with m.If(ctr == i):
                m.d.comb += value.eq(output.payload[i * 12:i * 12 + 8])

        m.d.comb += hdmi.rgb.r.eq(value)
        m.d.comb += hdmi.rgb.g.eq(value)
        m.d.comb += hdmi.rgb.b.eq(value)

        return m
示例#6
0
    def __init__(self, plugin):
        """
        This module needs to run in the word clock domain of the bus.
        """
        self.plugin = plugin
        self.output = StreamEndpoint(32, is_sink=False, has_last=False)

        self.ready = StatusSignal()
示例#7
0
    def __init__(
            self,
            address_source: StreamEndpoint,
            axi_slave=None, axi_data_width=64
    ):
        assert address_source.has_last is False
        self.address_source = address_source
        self.axi_slave = axi_slave
        self.output = StreamEndpoint(axi_data_width, is_sink=False, has_last=False)

        self.last_resp = StatusSignal(Response)
        self.error_count = StatusSignal(32)
示例#8
0
    def __init__(self, streams):
        self._streams = streams

        self.has_last = self._streams[0].has_last
        assert not any(self.has_last is not other.has_last
                       for other in self._streams)

        width = sum(len(stream.payload) for stream in self._streams)
        self.output = StreamEndpoint(width,
                                     is_sink=False,
                                     has_last=self.has_last)

        self.different_last_error = StatusSignal()
        self.different_valid_error = StatusSignal()
    def test_smoke(self):
        m = Module()

        platform = SimPlatform()
        platform.add_sim_clock("sync", 50e6)
        platform.add_sim_clock("ft601", 100e6)

        ft601 = Ft601FakeResource()
        counter_source = StreamEndpoint(32, is_sink=False, has_last=False)
        m.d.sync += counter_source.payload.eq(counter_source.payload + 1)
        m.d.comb += counter_source.valid.eq(1)
        m.submodules.dut = FT601StreamSink(ft601, counter_source)

        def testbench():
            read = []
            for i in range(3):
                yield ft601.txe.eq(1)
                written = 0
                began = False
                while True:
                    if not began:
                        if (yield ft601.write):
                            began = True
                    if began:
                        if (yield ft601.write):
                            written += 1
                            read.append((yield ft601.data.o))
                        else:
                            yield ft601.txe.eq(0)
                            break
                        if written == 2048:
                            yield ft601.txe.eq(0)
                            break
                    yield
                yield
                assert written == 2048
                for i in range(200):
                    yield
                    assert (yield ft601.write
                            ) == 0, "write was high in idle cycle {}".format(i)

            # validate the received data
            print(read)
            last = 0
            for v in read:
                assert v == last
                last += 1

        platform.sim(m, (testbench, "ft601"))
示例#10
0
    def __init__(self,
                 input: StreamEndpoint,
                 depth: int,
                 buffered=True,
                 fwtf=False):
        assert input.is_sink is False
        self.input = input
        self.output = StreamEndpoint.like(input, name="stream_fifo_output")
        self.depth = depth
        self.buffered = buffered
        self.fwtf = fwtf

        self.max_w_level = StatusSignal(range(depth))
        self.overflow_cnt = StatusSignal(32)
        self.underrun_cnt = StatusSignal(32)
        self.r_level = StatusSignal(range(depth + 1))
        self.w_level = StatusSignal(range(depth + 1))
示例#11
0
    def elaborate(self, platform):
        m = Module()

        input_sink = StreamEndpoint.like(self.input,
                                         is_sink=True,
                                         name="stream_fifo_input")
        m.d.comb += input_sink.connect(self.input)
        if input_sink.has_last:
            fifo_data = Cat(input_sink.payload, input_sink.last)
        else:
            fifo_data = input_sink.payload

        if self.buffered:
            assert not self.fwtf
            fifo = m.submodules.fifo = SyncFIFOBuffered(width=len(fifo_data),
                                                        depth=self.depth)
        else:
            fifo = m.submodules.fifo = SyncFIFO(width=len(fifo_data),
                                                depth=self.depth,
                                                fwft=self.fwtf)

        m.d.comb += self.r_level.eq(fifo.r_level)
        m.d.comb += self.w_level.eq(fifo.w_level)

        with m.If(self.w_level > self.max_w_level):
            m.d.sync += self.max_w_level.eq(self.w_level)

        m.d.comb += input_sink.ready.eq(fifo.w_rdy)
        m.d.comb += fifo.w_data.eq(fifo_data)
        m.d.comb += fifo.w_en.eq(input_sink.valid)

        with m.If(input_sink.valid & (~input_sink.ready)):
            m.d.sync += self.overflow_cnt.eq(self.overflow_cnt + 1)
        with m.If(self.output.ready & (~self.output.valid)):
            m.d.sync += self.underrun_cnt.eq(self.underrun_cnt + 1)

        if self.output.has_last:
            m.d.comb += Cat(self.output.payload,
                            self.output.last).eq(fifo.r_data)
        else:
            m.d.comb += self.output.payload.eq(fifo.r_data)
        m.d.comb += self.output.valid.eq(fifo.r_rdy)
        m.d.comb += fifo.r_en.eq(self.output.ready)

        return m
    def __init__(
        self,
        ringbuffer: RingBufferAddressStorage,
        max_line_width=5000,
        address_width=32,
        data_width=64,
    ):
        self.next_frame = Signal()
        self.line_words_total = ControlSignal(32, reset=2304 // 4)
        self.line_words_read = StatusSignal(32)

        self.ringbuffer = ringbuffer
        self.address_width = address_width
        self.data_width = data_width
        self.max_line_width = max_line_width

        self.output = StreamEndpoint(address_width,
                                     is_sink=False,
                                     has_last=False)
示例#13
0
    def __init__(self,
                 input,
                 depth,
                 r_domain,
                 w_domain,
                 buffered=True,
                 exact_depth=False):
        assert input.is_sink is False
        self.input = input
        self.output = StreamEndpoint.like(input, name="stream_fifo_output")

        self.r_domain = r_domain
        self.w_domain = w_domain
        self.depth = depth
        self.exact_depth = exact_depth
        self.buffered = buffered

        self.overflow_cnt = StatusSignal(32)
        self.underrun_cnt = StatusSignal(32)
        self.r_level = StatusSignal(range(depth + 1))
        self.w_level = StatusSignal(range(depth + 1))
示例#14
0
    def elaborate(self, platform):
        m = Module()

        plugin = platform.request("plugin_stream_input")
        rx = m.submodules.rx = PluginModuleStreamerRx(plugin)

        counter = Signal(24)
        m.d.sync += counter.eq(counter + 1)

        jtag_analyze = StreamEndpoint(32, is_sink=False, has_last=False)
        m.d.comb += jtag_analyze.payload.eq(Cat(platform.jtag_signals, counter[0:21]))
        m.d.comb += jtag_analyze.valid.eq(1)

        in_domain = DomainRenamer("wclk_in")

        counter = m.submodules.counter = in_domain(CounterStreamSource(32))

        ft601 = platform.request("ft601")
        m.submodules.ft601 = in_domain(FT601StreamSink(ft601, jtag_analyze))

        return m
示例#15
0
    def elaborate(self, platform):
        m = Module()

        input_sink = StreamEndpoint.like(self.input,
                                         is_sink=True,
                                         name="stream_fifo_input")
        m.d.comb += input_sink.connect(self.input)
        if input_sink.has_last:
            fifo_data = Cat(input_sink.payload, input_sink.last)
        else:
            fifo_data = input_sink.payload

        fifo_type = AsyncFIFOBuffered if self.buffered else AsyncFIFO
        fifo = m.submodules.fifo = fifo_type(width=len(fifo_data),
                                             depth=self.depth,
                                             r_domain=self.r_domain,
                                             w_domain=self.w_domain,
                                             exact_depth=self.exact_depth)

        m.d.comb += self.r_level.eq(fifo.r_level)
        m.d.comb += self.w_level.eq(fifo.w_level)

        m.d.comb += input_sink.ready.eq(fifo.w_rdy)
        m.d.comb += fifo.w_data.eq(fifo_data)
        m.d.comb += fifo.w_en.eq(input_sink.valid)

        with m.If(input_sink.valid & (~input_sink.ready)):
            m.d[self.w_domain] += self.overflow_cnt.eq(self.overflow_cnt + 1)
        with m.If(self.output.ready & (~self.output.valid)):
            m.d[self.r_domain] += self.underrun_cnt.eq(self.underrun_cnt + 1)

        if self.output.has_last:
            m.d.comb += Cat(self.output.payload,
                            self.output.last).eq(fifo.r_data)
        else:
            m.d.comb += self.output.payload.eq(fifo.r_data)
        m.d.comb += self.output.valid.eq(fifo.r_rdy)
        m.d.comb += fifo.r_en.eq(self.output.ready)

        return m
示例#16
0
    def test_sim_asnyc_stream_fifo(self):
        m = Module()
        input = StreamEndpoint(32, is_sink=False, has_last=False)
        fifo = m.submodules.fifo = AsyncStreamFifo(input, 1024, r_domain="sync", w_domain="sync", buffered=False)

        def testbench():
            for i in range(10):
                yield from write_to_stream(input, i)

            # async fifos need some time
            yield
            yield

            assert (yield fifo.r_level) == 10

            for i in range(10):
                assert (yield from read_from_stream(fifo.output)) == i

        simulator = Simulator(m)
        simulator.add_clock(1 / 100e6, domain="sync")
        simulator.add_sync_process(testbench, domain="sync")
        simulator.run()
示例#17
0
    def test_basic(self, data_len=50):
        axi = AxiEndpoint(addr_bits=32,
                          data_bits=64,
                          master=False,
                          lite=False,
                          id_bits=12)

        ringbuffer = RingBufferAddressStorage(0x1000, 2, base_address=0)
        stream_source = StreamEndpoint(64, is_sink=False, has_last=True)

        dut = AxiBufferWriter(ringbuffer,
                              stream_source,
                              axi,
                              fifo_depth=data_len)

        def testbench():
            # first, fill in some data:
            for i in range(data_len):
                yield stream_source.payload.eq(i)
                yield stream_source.valid.eq(1)
                yield
            yield stream_source.valid.eq(0)

            memory = {}
            while len(memory) < 50:
                memory.update((yield from answer_write_burst(axi))[0])

            self.assertEqual(
                {
                    ringbuffer.buffer_base_list[0] + i * axi.data_bytes: i
                    for i in range(50)
                }, memory)
            self.assertFalse((yield dut.error))

        platform = SimPlatform()
        platform.add_sim_clock("sync", 100e6)
        platform.sim(dut, testbench)
示例#18
0
    def elaborate(self, platform):
        m = Module()

        if self.axi_slave is not None:
            assert not self.axi_slave.is_lite
            assert not self.axi_slave.is_master
            axi_slave = self.axi_slave
        else:
            clock_signal = Signal()
            m.d.comb += clock_signal.eq(ClockSignal())
            axi_slave = platform.ps7.get_axi_hp_slave(clock_signal)
        axi = AxiEndpoint.like(axi_slave, master=True)
        m.d.comb += axi.connect_slave(axi_slave)

        assert len(self.output.payload) == axi.data_bits

        address_stream = StreamEndpoint.like(self.address_source, is_sink=True, name="address_sink")
        m.d.comb += address_stream.connect(self.address_source)
        assert len(address_stream.payload) == axi.addr_bits

        # we dont generate bursts for now
        m.d.comb += axi.read_address.valid.eq(address_stream.valid)
        m.d.comb += axi.read_address.value.eq(address_stream.payload)
        m.d.comb += address_stream.ready.eq(axi.read_address.ready)
        m.d.comb += axi.read_address.burst_len.eq(0)

        m.d.comb += axi.read_data.ready.eq(self.output.ready)
        m.d.comb += axi.read_data.last.eq(1)
        m.d.comb += self.output.valid.eq(axi.read_data.valid)
        m.d.comb += self.output.payload.eq(axi.read_data.value)

        m.d.sync += self.last_resp.eq(axi.read_data.resp)
        with m.If(axi.read_data.valid & (axi.read_data.resp != Response.OKAY)):
            m.d.sync += self.error_count.eq(self.error_count + 1)

        return m
示例#19
0
    def elaborate(self, platform):
        m = Module()

        highest_bit = 0
        for i, stream in enumerate(self._streams):
            sink = StreamEndpoint.like(
                stream, is_sink=True, name="stream_combiner_sink_{}".format(i))
            sink.connect(stream)
            m.d.comb += stream.ready.eq(self.output.ready)
            m.d.comb += self.output.payload[highest_bit:highest_bit +
                                            len(stream.payload)].eq(
                                                stream.payload)
            highest_bit += len(stream.payload)

            m.d.comb += self.output.valid.eq(stream.valid)
            with m.If(self.output.valid != stream.valid):
                m.d.sync += self.different_valid_error.eq(1)

            if self.has_last:
                m.d.comb += self.output.last.eq(stream.last)
                with m.If(self.output.last != stream.last):
                    m.d.sync += self.different_last_error.eq(1)

        return m
示例#20
0
 def __init__(self, width):
     self.output = StreamEndpoint(width, is_sink=False, has_last=False)
示例#21
0
    def elaborate(self, platform):
        m = Module()

        if self.axi_slave is not None:
            assert not self.axi_slave.is_lite
            assert not self.axi_slave.is_master
            axi_slave = self.axi_slave
        else:
            clock_signal = Signal()
            m.d.comb += clock_signal.eq(ClockSignal())
            axi_slave = platform.ps7.get_axi_hp_slave(clock_signal)
        axi = AxiEndpoint.like(axi_slave, master=True)
        m.d.comb += axi.connect_slave(axi_slave)

        address_generator = m.submodules.address_generator = AddressGenerator(
            self.ringbuffer, axi.addr_bits, max_incr=self.max_burst_length * axi.data_bytes
        )

        data_fifo = m.submodules.data_fifo = SyncStreamFifo(self.stream_source, depth=self.fifo_depth, buffered=False)
        data = StreamEndpoint.like(data_fifo.output, is_sink=True, name="data_sink")
        m.d.comb += data.connect(data_fifo.output)

        assert len(data.payload) <= axi.data_bits

        # we do not currently care about the write responses
        m.d.comb += axi.write_response.ready.eq(1)

        current_burst_length_minus_one = Signal(range(self.max_burst_length))
        with m.FSM():
            def idle_state():
                # having the idle state in a function is a hack to be able to duplicate its logic
                m.d.comb += self.state.eq(0)
                m.d.sync += self.burst_position.eq(0)
                m.d.comb += address_generator.request.eq(1)
                with m.If(address_generator.valid & data.valid):
                    # we are doing a full transaction
                    next_burst_length = Signal(range(self.max_burst_length + 1))
                    m.d.comb += next_burst_length.eq(nMax(data_fifo.r_level, self.max_burst_length))
                    m.d.sync += current_burst_length_minus_one.eq(next_burst_length - 1)
                    m.d.sync += address_generator.inc.eq(mul_by_pot(next_burst_length, axi.data_bytes))
                    m.next = "ADDRESS"

            with m.State("IDLE"):
                idle_state()

            with m.State("ADDRESS"):
                m.d.comb += self.state.eq(1)
                m.d.comb += axi.write_address.value.eq(address_generator.addr)
                m.d.comb += axi.write_address.burst_len.eq(current_burst_length_minus_one)
                m.d.comb += axi.write_address.burst_type.eq(BurstType.INCR)
                m.d.comb += axi.write_address.valid.eq(1)
                with m.If(axi.write_address.ready):
                    m.next = "TRANSFER_DATA"
                    m.d.comb += data.ready.eq(1)
                    m.d.comb += address_generator.done.eq(1)

            def last_logic():
                # shared between TRANSFER_DATA and FLUSH
                with m.If(self.burst_position == current_burst_length_minus_one):
                    m.d.comb += axi.write_data.last.eq(1)
                    m.next = "IDLE"
                    idle_state()

            with m.State("TRANSFER_DATA"):
                m.d.comb += self.state.eq(2)

                with m.If(data.last):
                    m.d.sync += self.buffers_written.eq(self.buffers_written + 1)
                    m.d.comb += address_generator.change_buffer.eq(1)
                    m.next = "FLUSH"

                m.d.comb += axi.write_data.value.eq(data.payload)
                m.d.comb += axi.write_data.valid.eq(1)

                with m.If(axi.write_data.ready):
                    m.d.sync += self.words_written.eq(self.words_written + 1)
                    m.d.sync += self.burst_position.eq(self.burst_position + 1)
                    with m.If((self.burst_position < current_burst_length_minus_one) & ~data.last):
                        m.d.comb += data.ready.eq(1)
                        with m.If((~data.valid)):
                            # we have checked this earlier so this should never be a problem
                            m.d.sync += self.error.eq(1)
                last_logic()
            with m.State("FLUSH"):
                m.d.comb += axi.write_data.byte_strobe.eq(0)
                m.d.comb += axi.write_data.valid.eq(1)
                with m.If(axi.write_data.ready):
                    m.d.sync += self.words_written.eq(self.words_written + 1)
                    m.d.sync += self.burst_position.eq(self.burst_position + 1)
                last_logic()

        return m