Example #1
0
    def __init__(self, dram_port, hres=800, vres=600, base=0x00000000, fifo_depth=65536, clock_domain="sys", clock_faster_than_sys=False):
        self.vtg_sink  = vtg_sink = stream.Endpoint(video_timing_layout)
        self.source    = source   = stream.Endpoint(video_data_layout)
        self.underflow = Signal()

        # # #

        # Video DMA.
        from litedram.frontend.dma import LiteDRAMDMAReader
        self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth=fifo_depth//(dram_port.data_width//8), fifo_buffered=True)
        self.dma.add_csr(
            default_base   = base,
            default_length = hres*vres*32//8, # 32-bit RGB-444
            default_enable = 0,
            default_loop   = 1
        )

        # If DRAM Data Width > 32-bit and Video clock is faster than sys_clk:
        if (dram_port.data_width > 32) and clock_faster_than_sys:
            # Do Clock Domain Crossing first...
            self.submodules.cdc = stream.ClockDomainCrossing([("data", dram_port.data_width)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.dma.source.connect(self.cdc.sink)
            # ... and then Data-Width Conversion.
            self.submodules.conv = stream.Converter(dram_port.data_width, 32)
            self.comb += self.cdc.source.connect(self.conv.sink)
            video_pipe_source = self.conv.source
        # Elsif DRAM Data Widt < 32-bit or Video clock is slower than sys_clk:
        else:
            # Do Data-Width Conversion first...
            self.submodules.conv = stream.Converter(dram_port.data_width, 32)
            self.comb += self.dma.source.connect(self.conv.sink)
            # ... and then Clock Domain Crossing.
            self.submodules.cdc = stream.ClockDomainCrossing([("data", 32)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.conv.source.connect(self.cdc.sink)
            self.comb += If(dram_port.data_width < 32, # FIXME.
                self.cdc.sink.data[ 0: 8].eq(self.conv.source.data[16:24]),
                self.cdc.sink.data[16:24].eq(self.conv.source.data[ 0: 8]),
            )
            video_pipe_source = self.cdc.source

        # Video Generation.
        self.comb += [
            vtg_sink.ready.eq(1),
            If(vtg_sink.valid & vtg_sink.de,
                video_pipe_source.connect(source, keep={"valid", "ready"}),
                vtg_sink.ready.eq(source.valid & source.ready),

            ),
            vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
            source.r.eq(video_pipe_source.data[16:24]),
            source.g.eq(video_pipe_source.data[ 8:16]),
            source.b.eq(video_pipe_source.data[ 0: 8]),
        ]

        # Underflow.
        self.comb += self.underflow.eq(~source.valid)
Example #2
0
    def __init__(self, pads, mode="master"):
        self.refclk = Signal()

        # # #

        # In Master mode, generate the linerate/10 clock. Slave will re-multiply it.
        if mode == "master":
            converter = stream.Converter(40, 8)
            self.submodules += converter
            self.comb += [
                converter.sink.valid.eq(1),
                converter.source.ready.eq(1),
                converter.sink.data.eq(
                    Replicate(Signal(10, reset=0b1111100000), 4)),
            ]
            self.specials += [
                Instance("OSERDESE3",
                         p_DATA_WIDTH=8,
                         p_INIT=0,
                         p_IS_CLK_INVERTED=0,
                         p_IS_CLKDIV_INVERTED=0,
                         p_IS_RST_INVERTED=0,
                         o_OQ=self.refclk,
                         i_RST=ResetSignal("sys"),
                         i_CLK=ClockSignal("sys4x"),
                         i_CLKDIV=ClockSignal("sys"),
                         i_D=converter.source.data),
                DifferentialOutput(self.refclk, pads.clk_p, pads.clk_n)
            ]

        # In Slave mode, multiply the clock provided by Master with a PLL/MMCM
        elif mode == "slave":
            self.specials += DifferentialInput(pads.clk_p, pads.clk_n,
                                               self.refclk)
Example #3
0
    def __init__(self,
                 cmd=False,
                 data=False,
                 data_width=1,
                 skip_start_bit=False):
        assert cmd or data
        self.pads_in = pads_in = stream.Endpoint(_sdpads_layout)
        self.source = source = stream.Endpoint([("data", 8)])

        # # #

        pads_in_data = pads_in.cmd.i[:
                                     data_width] if cmd else pads_in.data.i[:
                                                                            data_width]
        print(len(pads_in_data))

        # Xfer starts when data == 0
        start = Signal()
        run = Signal()
        self.comb += start.eq(pads_in_data == 0)
        self.sync += If(pads_in.valid & pads_in.ready, run.eq(start | run))

        # Convert data to 8-bit stream
        converter = stream.Converter(data_width, 8, reverse=True)
        buf = stream.Buffer([("data", 8)])
        self.submodules += converter, buf
        self.comb += [
            converter.sink.valid.eq(pads_in.valid
                                    & (run if skip_start_bit else (start
                                                                   | run))),
            converter.sink.data.eq(pads_in_data),
            pads_in.ready.eq(converter.sink.ready),
            converter.source.connect(buf.sink),
            buf.source.connect(source)
        ]
    def __init__(self, pads, mode="master"):
        self.refclk = Signal()

        # # #

        # In Master mode, generate the linerate/10 clock. Slave will re-multiply it.
        if mode == "master":
            converter = stream.Converter(40, 8)
            self.submodules += converter
            self.comb += [
                converter.sink.valid.eq(1),
                converter.source.ready.eq(1),
                converter.sink.data.eq(Replicate(Signal(10, reset=0b1111100000), 4)),
            ]
            self.specials += [
                Instance("OSERDESE2",
                    p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1,
                    p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF",
                    p_SERDES_MODE="MASTER",

                    o_OQ=self.refclk,
                    i_OCE=1,
                    i_RST=ResetSignal("sys"),
                    i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
                    i_D1=converter.source.data[0], i_D2=converter.source.data[1],
                    i_D3=converter.source.data[2], i_D4=converter.source.data[3],
                    i_D5=converter.source.data[4], i_D6=converter.source.data[5],
                    i_D7=converter.source.data[6], i_D8=converter.source.data[7]
                ),
                DifferentialOutput(self.refclk, pads.clk_p, pads.clk_n)
            ]

        # In Slave mode, multiply the clock provided by Master with a PLL/MMCM
        elif mode == "slave":
            self.specials += DifferentialInput(pads.clk_p, pads.clk_n, self.refclk)
Example #5
0
    def __init__(self, bus, endianness, fifo_depth=32):
        self.bus = bus
        self.sink = stream.Endpoint([("data", 8)])

        # # #

        # Submodules
        fifo = stream.SyncFIFO([("data", 8)], fifo_depth)
        converter = stream.Converter(8, bus.data_width, reverse=True)
        self.submodules += fifo, converter
        self.submodules.dma = WishboneDMAWriter(bus,
                                                with_csr=True,
                                                endianness=endianness)

        # Flow
        start = Signal()
        connect = Signal()
        self.comb += start.eq(self.sink.valid & self.sink.first)
        self.sync += [
            If(~self.dma._enable.storage,
               connect.eq(0)).Elif(start, connect.eq(1))
        ]
        self.comb += [
            If(self.dma._enable.storage & (start | connect),
               self.sink.connect(fifo.sink)).Else(self.sink.ready.eq(1)),
            fifo.source.connect(converter.sink),
            converter.source.connect(self.dma.sink),
        ]
    def __init__(self, phy_dw, with_scrambling=True):
        self.bitslip_value = bitslip_value = Signal(6)
        self.sink = sink = stream.Endpoint([("data", phy_dw)])
        self.source = source = stream.Endpoint([("data", 32)])
        self.idle = idle = Signal()
        self.comma = comma = Signal()

        # # #

        # converter
        self.submodules.converter = converter = stream.Converter(phy_dw, 40)

        # bitslip
        self.submodules.bitslip = bitslip = _Bitslip()
        self.comb += bitslip.value.eq(bitslip_value)

        # line coding
        self.submodules.decoder = decoder = _8b10bDecoder()

        # descrambler
        if with_scrambling:
            self.submodules.descrambler = descrambler = Descrambler()

        # dataflow
        self.comb += [
            sink.connect(converter.sink),
            converter.source.connect(bitslip.sink),
            bitslip.source.connect(decoder.sink)
        ]
        if with_scrambling:
            self.comb += [
                decoder.source.connect(descrambler.sink),
                descrambler.source.connect(source)
            ]
        else:
            self.comb += [
                decoder.source.connect(source, omit={"d", "k"}),
                source.data.eq(decoder.source.d)
            ]

        # idle decoding
        idle_timer = WaitTimer(32)
        self.submodules += idle_timer
        self.sync += [
            If(
                converter.source.valid,
                idle_timer.wait.eq((converter.source.data == 0)
                                   | (converter.source.data == (2**40 - 1)))),
            idle.eq(idle_timer.done)
        ]
        # comma decoding
        self.sync += \
            If(decoder.source.valid,
                comma.eq((decoder.source.k == 1) & (decoder.source.d == K(28, 5)))
            )
Example #7
0
    def __init__(self, dram_port, dw=32, fifo_depth=512):
        self.sink = stream.Endpoint([("data", dw)])

        # # #

        DMA.__init__(self, "write", dram_port, fifo_depth)
        converter = stream.Converter(dw, dram_port.dw, reverse=False)
        self.submodules += converter
        self.comb += [
            self.sink.connect(converter.sink),
            converter.source.connect(self.endpoint)
        ]
Example #8
0
    def __init__(self, phy_dw, with_scrambling=False):
        self.shift = shift = Signal(6)
        self.sink = sink = stream.Endpoint([("data", phy_dw)])
        self.source = source = stream.Endpoint([("data", 32)])
        self.idle = idle = Signal()
        self.comma = comma = Signal()

        # # #

        # Aligner
        self.submodules.aligner = aligner = RXAligner(phy_dw, shift)

        # Converter
        self.submodules.converter = converter = stream.Converter(phy_dw, 40)

        # Line Coding
        self.submodules.decoder = decoder = StreamDecoder(nwords=4)

        # Descrambler
        if with_scrambling:
            self.submodules.descrambler = descrambler = Descrambler()

        # Dataflow
        self.comb += [
            sink.connect(aligner.sink),
            aligner.source.connect(converter.sink),
            converter.source.connect(decoder.sink),
        ]
        if with_scrambling:
            self.comb += decoder.source.connect(descrambler.sink)
            self.comb += descrambler.source.connect(source)
        else:
            self.comb += decoder.source.connect(source, omit={"d", "k"})
            self.comb += source.data.eq(decoder.source.d)

        # Decode Idle
        idle_timer = WaitTimer(32)
        self.submodules += idle_timer
        self.sync += If(
            converter.source.valid,
            idle_timer.wait.eq((converter.source.data == 0)
                               | (converter.source.data == (2**40 - 1))))
        self.comb += idle.eq(idle_timer.done)

        # Decode Comma
        self.sync += If(
            decoder.source.valid,
            comma.eq((decoder.source.k == 1) & (decoder.source.d == K(28, 5))))
Example #9
0
    def __init__(self,
                 dram_port,
                 hres=800,
                 vres=600,
                 base=0x00000000,
                 clock_domain="sys"):
        self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
        self.source = source = stream.Endpoint(video_data_layout)

        # # #

        # Video DMA.
        from litedram.frontend.dma import LiteDRAMDMAReader
        self.submodules.dma = LiteDRAMDMAReader(
            dram_port, fifo_depth=2048,
            fifo_buffered=True)  # FIXME: Adjust/Expose.
        self.dma.add_csr(
            default_base=base,
            default_length=hres * vres * 32 // 8,  # 32-bit RGB-444
            default_enable=0,
            default_loop=1)

        # FIXME: Make sure it will work for all DRAM's data-width/all Video resolutions.

        # Video Data-Width Converter.
        self.submodules.conv = stream.Converter(dram_port.data_width, 32)
        self.comb += self.dma.source.connect(self.conv.sink)

        # Video CDC.
        self.submodules.cdc = stream.ClockDomainCrossing([("data", 32)],
                                                         cd_from="sys",
                                                         cd_to=clock_domain)
        self.comb += self.conv.source.connect(self.cdc.sink)

        # Video Generation.
        self.comb += [
            vtg_sink.ready.eq(1),
            If(
                vtg_sink.valid & vtg_sink.de,
                self.cdc.source.connect(source, keep={"valid", "ready"}),
                vtg_sink.ready.eq(source.valid & source.ready),
            ),
            vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
            source.r.eq(self.cdc.source.data[16:24]),
            source.g.eq(self.cdc.source.data[8:16]),
            source.b.eq(self.cdc.source.data[0:8]),
        ]
Example #10
0
    def __init__(self, phy_dw, with_scrambling=False):
        self.idle = idle = Signal()
        self.comma = comma = Signal()
        self.sink = sink = stream.Endpoint([("data", 32)])
        self.source = source = stream.Endpoint([("data", phy_dw)])

        # # #

        # Scrambler
        if with_scrambling:
            self.submodules.scrambler = scrambler = Scrambler()

        # Line coding
        self.submodules.encoder = encoder = StreamEncoder(nwords=4)

        # Converter
        self.submodules.converter = converter = stream.Converter(40, phy_dw)

        # Dataflow
        if with_scrambling:
            self.comb += sink.connect(scrambler.sink)
            self.comb += scrambler.source.connect(encoder.sink)
        else:
            self.comb += sink.connect(encoder.sink, omit={"data"}),
            self.comb += encoder.sink.d.eq(sink.data)
        self.comb += encoder.source.connect(converter.sink)
        self.comb += converter.source.connect(source)

        # Send K28.5 if comma asserted.
        self.comb += If(
            comma,
            sink.ready.eq(0),
            encoder.sink.valid.eq(1),
            encoder.sink.k.eq(0b1),
            encoder.sink.d.eq(K(28, 5)),
        )

        # Send Idle if idle asserted.
        self.comb += If(
            idle,
            sink.ready.eq(0),
            converter.sink.valid.eq(1),
            converter.sink.data.eq(0),
        )
Example #11
0
    def __init__(self, bus, endianness, fifo_depth=32):
        self.source = stream.Endpoint([("data", 8)])

        # # #

        # Submodules
        self.submodules.dma = WishboneDMAReader(bus,
                                                with_csr=True,
                                                endianness=endianness)
        converter = stream.Converter(bus.data_width, 8, reverse=True)
        fifo = stream.SyncFIFO([("data", 8)], fifo_depth)
        self.submodules += converter, fifo

        # Flow
        self.comb += [
            self.dma.source.connect(converter.sink),
            converter.source.connect(fifo.sink),
            fifo.source.connect(self.source),
        ]
Example #12
0
    def __init__(self, dram_port):
        self.shoot = CSR()
        self.done = CSRStatus()
        self.base = CSRStorage(32)
        self.length = CSRStorage(32)

        self.source = source = stream.Endpoint([("data", 16)])

        # # #

        self.submodules.dma = dma = LiteDRAMDMAReader(dram_port)

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

        shift = log2_int(dram_port.dw // 8)
        base = Signal(dram_port.aw)
        length = Signal(dram_port.aw)
        offset = Signal(dram_port.aw)
        self.comb += [
            base.eq(self.base.storage[shift:]),
            length.eq(self.length.storage[shift:])
        ]

        fsm.act(
            "IDLE", self.done.status.eq(1),
            If(self.shoot.re & self.shoot.r, NextValue(offset, 0),
               NextState("RUN")))
        fsm.act(
            "RUN", dma.sink.valid.eq(1),
            If(dma.sink.ready, NextValue(offset, offset + 1),
               If(offset == (length - 1), NextState("IDLE"))))
        self.comb += dma.sink.address.eq(base + offset)

        self.submodules.converter = stream.Converter(dram_port.dw,
                                                     16,
                                                     reverse=True)
        self.comb += [
            self.dma.source.connect(self.converter.sink),
            self.converter.source.connect(self.source)
        ]
    def __init__(self, phy_dw, with_scrambling=True):
        self.idle = idle = Signal()
        self.comma = comma = Signal()
        self.sink = sink = stream.Endpoint([("data", 32)])
        self.source = source = stream.Endpoint([("data", phy_dw)])

        # # #

        # scrambler
        if with_scrambling:
            self.submodules.scrambler = scrambler = Scrambler()

        # line coding
        self.submodules.encoder = encoder = _8b10bEncoder()

        # converter
        self.submodules.converter = converter = stream.Converter(40, phy_dw)

        # dataflow
        if with_scrambling:
            self.comb += [
                sink.connect(scrambler.sink),
                If(comma, encoder.sink.valid.eq(1), encoder.sink.k.eq(1),
                   encoder.sink.d.eq(K(28, 5))).Else(
                       scrambler.source.connect(encoder.sink))
            ]
        else:
            self.comb += [
                If(comma, encoder.sink.valid.eq(1), encoder.sink.k.eq(1),
                   encoder.sink.d.eq(K(28, 5))).Else(
                       sink.connect(encoder.sink, omit={"data"}),
                       encoder.sink.d.eq(sink.data)),
            ]
        self.comb += [
            If(idle, converter.sink.valid.eq(1),
               converter.sink.data.eq(0)).Else(
                   encoder.source.connect(converter.sink), ),
            converter.source.connect(source)
        ]
Example #14
0
    def __init__(self, bus, port, endianness="little"):
        self.bus = bus
        self.port = port
        self.sector = CSRStorage(48)
        self.base = CSRStorage(64)
        self.start = CSR()
        self.done = CSRStatus()
        self.error = CSRStatus()

        # # #

        dma_bytes = bus.data_width // 8
        port_bytes = port.dw // 8
        count = Signal(max=logical_sector_size // min(dma_bytes, port_bytes))

        # DMA
        dma = WishboneDMAReader(bus, with_csr=False, endianness=endianness)
        self.submodules.dma = dma

        # Sector buffer
        buf = stream.SyncFIFO([("data", port.dw)],
                              logical_sector_size // dma_bytes)
        self.submodules.buf = buf

        # Converter
        conv = stream.Converter(nbits_from=bus.data_width, nbits_to=port.dw)
        self.submodules.conv = conv

        # Connect DMA to Sector Buffer
        self.comb += dma.source.connect(buf.sink)

        # Connect Sector Buffer to Converter
        self.comb += buf.source.connect(conv.sink)

        # Control FSM
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE",
            If(self.start.re, NextValue(count, 0),
               NextValue(self.error.status, 0),
               NextState("READ-DATA-DMA")).Else(self.done.status.eq(1)),
            conv.source.ready.eq(1))
        fsm.act(
            "READ-DATA-DMA",
            # Read Sector data over DMA.
            dma.sink.valid.eq(1),
            dma.sink.address.eq(self.base.storage[int(log2(dma_bytes)):] +
                                count),
            If(
                dma.sink.valid & dma.sink.ready, NextValue(count, count + 1),
                If(count == (logical_sector_size // dma_bytes - 1),
                   NextValue(count, 0), NextState("SEND-CMD-AND-DATA"))))
        fsm.act(
            "SEND-CMD-AND-DATA",
            # Send write command/data for 1 Sector.
            port.sink.valid.eq(1),
            port.sink.last.eq(count == (logical_sector_size // port_bytes -
                                        1)),
            port.sink.write.eq(1),
            port.sink.sector.eq(self.sector.storage),
            port.sink.count.eq(1),
            port.sink.data.eq(reverse_bytes(conv.source.data)),
            If(port.sink.ready, conv.source.ready.eq(1),
               NextValue(count, count + 1),
               If(port.sink.last, NextState("WAIT-ACK"))),

            # Monitor errors
            port.source.ready.eq(1),
            If(
                port.source.valid & port.source.ready,
                If(
                    port.source.failed,
                    NextValue(self.error.status, 1),
                    NextState("IDLE"),
                )))
        fsm.act(
            "WAIT-ACK", port.source.ready.eq(1),
            If(port.source.valid,
               If(
                   port.source.failed,
                   NextValue(self.error.status, 1),
               ), NextState("IDLE")))
Example #15
0
    def __init__(self, pads, sys_clk_freq, clock_domain="sys", clk_freq=148.5e6, refclk=None):
        assert sys_clk_freq >= clk_freq
        self.sink = sink = stream.Endpoint(video_data_layout)

        # # #

        from liteiclink.serdes.gtp_7series import GTPQuadPLL, GTP

        # Always ack Sink, no backpressure.
        self.comb += sink.ready.eq(1)

        # Clocking + Differential Signaling.
        pads_clk = Signal()
        self.specials += DDROutput(i1=1, i2=0, o=pads_clk, clk=ClockSignal(clock_domain))
        self.specials += Instance("OBUFDS", i_I=pads_clk, o_O=pads.clk_p, o_OB=pads.clk_n)

        # GTP Quad PLL.
        if refclk is None:
            # No RefClk provided, use the Video Clk as GTP RefClk.
            refclk = ClockSignal(clock_domain)
        elif isinstance(refclk, Record):
            # Differential RefCLk provided, add an IBUFDS_GTE2.
            refclk_se = Signal()
            self.specials += Instance("IBUFDS_GTE2",
                i_CEB = 0,
                i_I   = refclk.p,
                i_IB  = refclk.n,
                o_O   = refclk_se
            )
            refclk = refclk_se
        self.submodules.pll = pll = GTPQuadPLL(refclk, clk_freq, 1.485e9)

        # Encode/Serialize Datas.
        for color in ["r", "g", "b"]:
            # TMDS Encoding.
            encoder = ClockDomainsRenamer(clock_domain)(TMDSEncoder())
            self.submodules += encoder
            self.comb += encoder.d.eq(getattr(sink, color))
            self.comb += encoder.c.eq(Cat(sink.hsync, sink.vsync) if color == "r" else 0)
            self.comb += encoder.de.eq(sink.de)

            # 10:20 (SerDes has a minimal 20:1 Serialization ratio).
            converter = ClockDomainsRenamer(clock_domain)(stream.Converter(10, 20))
            self.submodules += converter
            self.comb += converter.sink.valid.eq(1)
            self.comb += converter.sink.data.eq(encoder.out)

            # Clock Domain Crossing (video_clk --> gtp_tx)
            cdc = stream.ClockDomainCrossing([("data", 20)], cd_from=clock_domain, cd_to=f"gtp{color}_tx")
            self.submodules += cdc
            self.comb += converter.source.connect(cdc.sink)
            self.comb += cdc.source.ready.eq(1) # No backpressure.

            # 20:1 Serialization + Differential Signaling.
            c2d  = {"r": 2, "g": 1, "b": 0}
            class GTPPads:
                def __init__(self, p, n):
                    self.p = p
                    self.n = n
            tx_pads = GTPPads(p=getattr(pads, f"data{c2d[color]}_p"), n=getattr(pads, f"data{c2d[color]}_n"))
            # FIXME: Find a way to avoid RX pads.
            rx_pads = GTPPads(p=getattr(pads, f"rx{c2d[color]}_p"),   n=getattr(pads, f"rx{c2d[color]}_n"))
            gtp = GTP(pll, tx_pads, rx_pads=rx_pads, sys_clk_freq=sys_clk_freq,
                tx_polarity      = 1, # FIXME: Specific to Decklink Mini 4K, make it configurable.
                tx_buffer_enable = True,
                rx_buffer_enable = True,
                clock_aligner    = False
            )
            setattr(self.submodules, f"gtp{color}", gtp)
            self.comb += gtp.tx_produce_pattern.eq(1)
            self.comb += gtp.tx_pattern.eq(cdc.source.data)
Example #16
0
    def __init__(self, ddr_wr_port, ddr_rd_port, udp_port, adc_source, adc_dw):
        SIZE = 1024 * 1024
        self.fifo_full = CSRStatus(reset=0)
        self.fifo_error = CSRStatus(reset=0)
        self.fifo_load = CSRStorage(reset=0)
        self.fifo_read = CSRStorage(reset=0)
        self.fifo_size = CSRStorage(32, reset=SIZE)
        self.dst_ip = CSRStorage(32, reset=convert_ip("192.168.1.114"))
        self.dst_port = CSRStorage(16, reset=7778)

        self.fifo_counter = fifo_counter = Signal(24)
        self.load_fifo = load_fifo = Signal()

        dw = ddr_wr_port.data_width

        print(
            f"Write port: A ({ddr_wr_port.address_width})/ D ({ddr_wr_port.data_width})"
        )
        print(
            f"Read port: A ({ddr_rd_port.address_width})/ D ({ddr_rd_port.data_width})"
        )
        print(f"dw: {dw}; adc_dw: {adc_dw}")
        self.submodules.dram_fifo = dram_fifo = LiteDRAMFIFO(
            data_width=dw,
            base=0,
            depth=SIZE * (dw // 8),  # liteDRAM expects this in bytes
            write_port=ddr_wr_port,
            read_port=ddr_rd_port,
        )

        self.adc_data = adc_data = Signal(dw)
        DW_RATIO = dw // adc_dw
        log_dw_ratio = log2_int(DW_RATIO)
        word_count = Signal(log_dw_ratio)
        word_count_d = Signal(log_dw_ratio)

        self.sync += [
            If(adc_source.valid,
               adc_data.eq(Cat(adc_data[adc_dw:], adc_source.data)),
               word_count.eq(word_count + 1)),
            word_count_d.eq(word_count),
        ]

        self.comb += [
            dram_fifo.sink.valid.eq((word_count == 0) & (word_count_d != 0)
                                    & load_fifo),
            dram_fifo.sink.data.eq(adc_data)
        ]

        fifo_size = Signal(32)
        self.sync += [
            fifo_size.eq(self.fifo_size.storage),
            If(self.fifo_load.re & self.fifo_load.storage, fifo_counter.eq(0),
               load_fifo.eq(1)),
            If(load_fifo & adc_source.valid, self.fifo_full.status.eq(0),
               self.fifo_error.status.eq(~dram_fifo.dram_fifo.ctrl.writable),
               fifo_counter.eq(fifo_counter + 1)),
            If((fifo_counter == fifo_size - 1) & adc_source.valid,
               load_fifo.eq(0), self.fifo_full.status.eq(1)),
        ]

        # fifo --> stride converter
        self.submodules.stride_converter = sc = stream.Converter(
            dw, udp_port.dw)

        self.read_from_dram_fifo = read_from_dram_fifo = Signal()
        self.comb += [dram_fifo.source.connect(sc.sink)]
        self.receive_count = receive_count = Signal(24)
        self.sync += [
            If(dram_fifo.source.valid & dram_fifo.source.ready,
               receive_count.eq(receive_count + 1)).Elif(
                   read_from_dram_fifo == 0, receive_count.eq(0))
        ]
        # --> udp fragmenter -->
        self.submodules.udp_fragmenter = udp_fragmenter = UDPFragmenter(
            udp_port.dw)

        self.sync += read_from_dram_fifo.eq(self.fifo_read.storage)
        self.comb += If(
            read_from_dram_fifo,
            # TODO: There is a bug somewhere in the converter,
            # its source.last somehow gets set, no idea why. That signal is of no real use
            # for the fragmenter anyways, so we live without it
            sc.source.connect(udp_fragmenter.sink, omit={'total_size',
                                                         'last'}))

        # TODO: 8 should be adcstream data width // 8
        self.comb += udp_fragmenter.sink.length.eq(
            fifo_size << log2_int(adc_dw // 8))
        self.comb += udp_fragmenter.source.connect(udp_port.sink)
        self.comb += [
            # param
            udp_port.sink.src_port.eq(4321),
            udp_port.sink.dst_port.eq(self.dst_port.storage),
            udp_port.sink.ip_address.eq(self.dst_ip.storage),
            # udp_port.sink.ip_address.eq(convert_ip("192.168.88.101")),
            # payload
            udp_port.sink.error.eq(0)
        ]
Example #17
0
    def __init__(self, ddr_wr_port, ddr_rd_port, udp_port):
        SIZE = 1024 * 1024
        SIZE = 1024
        self.fifo_full = CSRStatus(reset=0)
        self.fifo_error = CSRStatus(reset=0)
        self.fifo_load = CSRStorage(
            reset=0)  # Load the coefficients in memory to the ROI Summer
        self.fifo_read = CSRStorage(reset=0)
        self.fifo_size = CSRStorage(32, reset=SIZE)
        self.dst_ip = CSRStorage(32, reset=convert_ip("192.168.1.114"))
        self.dst_port = CSRStorage(16, reset=7778)

        dw = 64
        print(
            f"Write port: A ({ddr_wr_port.address_width})/ D ({ddr_wr_port.data_width})"
        )
        print(
            f"Read port: A ({ddr_rd_port.address_width})/ D ({ddr_rd_port.data_width})"
        )
        self.submodules.dram_fifo = dram_fifo = LiteDRAMFIFO(
            data_width=dw,
            base=0,
            depth=SIZE,
            write_port=ddr_wr_port,
            read_port=ddr_rd_port,
            with_bypass=True,
        )
        # self.mf = mf = Signal(reset=0)  # mf == More Fragments
        # self.fragment_offset = fragment_offset = Signal(13, reset=0)
        # self.identification = identification = Signal(16, reset=0)

        self.submodules.adcs = adcs = ADCStream(1, dw)
        self.fifo_counter = fifo_counter = Signal(24)
        self.load_fifo = load_fifo = Signal()

        # adc --> buffer_fifo
        self.submodules.buffer_fifo = buffer_fifo = stream.SyncFIFO(
            stream.EndpointDescription([("data", dw)]), 256, buffered=True)
        # buffer_fifo --> dram_fifo
        fifo_size = Signal(32)
        self.sync += [
            fifo_size.eq(self.fifo_size.storage),
            If(self.fifo_load.re & self.fifo_load.storage, fifo_counter.eq(0),
               load_fifo.eq(1)),
            If(load_fifo & adcs.source.valid, self.fifo_full.status.eq(0),
               self.fifo_error.status.eq(~dram_fifo.dram_fifo.ctrl.writable),
               fifo_counter.eq(fifo_counter + 1)),
            If((fifo_counter == fifo_size - 1) & adcs.source.valid,
               load_fifo.eq(0), self.fifo_full.status.eq(1)),
        ]

        self.comb += [
            buffer_fifo.sink.data.eq(adcs.source.data),
            buffer_fifo.sink.valid.eq(adcs.source.valid & load_fifo),
            buffer_fifo.source.connect(dram_fifo.sink),
        ]

        # fifo --> stride converter
        self.submodules.stride_converter = sc = stream.Converter(
            dw, udp_port.dw)

        self.read_from_dram_fifo = read_from_dram_fifo = Signal()
        self.comb += [dram_fifo.source.connect(sc.sink)]
        self.receive_count = receive_count = Signal(24)
        self.sync += [
            If(dram_fifo.source.valid & dram_fifo.source.ready,
               receive_count.eq(receive_count + 1)).Elif(
                   read_from_dram_fifo == 0, receive_count.eq(0))
        ]
        # --> udp fragmenter -->
        self.submodules.udp_fragmenter = udp_fragmenter = UDPFragmenter(
            udp_port.dw)

        self.sync += read_from_dram_fifo.eq(self.fifo_read.storage)
        self.comb += If(
            read_from_dram_fifo,
            # TODO: There is a bug somewhere in the converter,
            # its source.last somehow gets set, no idea why. That signal is of no real use
            # for the fragmenter anyways, so we live without it
            sc.source.connect(udp_fragmenter.sink, omit={'total_size',
                                                         'last'}))

        # TODO: 8 should be adcstream data width // 8
        self.comb += udp_fragmenter.sink.length.eq(fifo_size << log2_int(dw //
                                                                         8))
        self.comb += udp_fragmenter.source.connect(udp_port.sink)
        self.comb += [
            # param
            udp_port.sink.src_port.eq(4321),
            udp_port.sink.dst_port.eq(self.dst_port.storage),
            udp_port.sink.ip_address.eq(self.dst_ip.storage),
            # udp_port.sink.ip_address.eq(convert_ip("192.168.88.101")),
            # payload
            udp_port.sink.error.eq(0)
        ]

        # debug
        self.first_sample, self.last_sample = Signal(16), Signal(16)
        self.sync += [
            If(fifo_counter == 1, self.first_sample.eq(adcs.source.data[:16])),
            If(fifo_counter == SIZE - 2,
               self.last_sample.eq(adcs.source.data[:16])),
        ]
Example #18
0
    def __init__(self, dram_port, hres=800, vres=600, base=0x00000000, fifo_depth=65536, clock_domain="sys", clock_faster_than_sys=False, format="rgb888"):
        self.vtg_sink  = vtg_sink = stream.Endpoint(video_timing_layout)
        self.source    = source   = stream.Endpoint(video_data_layout)
        self.underflow = Signal()

        self.depth = depth = {
            "rgb888" : 32,
            "rgb565" : 16
        }[format]

        # # #

        # Video DMA.
        from litedram.frontend.dma import LiteDRAMDMAReader
        self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth=fifo_depth//(dram_port.data_width//8), fifo_buffered=True)
        self.dma.add_csr(
            default_base   = base,
            default_length = hres*vres*depth//8, # 32-bit RGB-888 or 16-bit RGB-565
            default_enable = 0,
            default_loop   = 1
        )

        # If DRAM Data Width > depth and Video clock is faster than sys_clk:
        if (dram_port.data_width > depth) and clock_faster_than_sys:
            # Do Clock Domain Crossing first...
            self.submodules.cdc = stream.ClockDomainCrossing([("data", dram_port.data_width)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.dma.source.connect(self.cdc.sink)
            # ... and then Data-Width Conversion.
            self.submodules.conv = ClockDomainsRenamer(clock_domain)(stream.Converter(dram_port.data_width, depth))
            self.comb += self.cdc.source.connect(self.conv.sink)
            video_pipe_source = self.conv.source
        # Elsif DRAM Data Width <= depth or Video clock is slower than sys_clk:
        else:
            # Do Data-Width Conversion first...
            self.submodules.conv = stream.Converter(dram_port.data_width, depth)
            self.comb += self.dma.source.connect(self.conv.sink)
            # ... and then Clock Domain Crossing.
            self.submodules.cdc = stream.ClockDomainCrossing([("data", depth)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.conv.source.connect(self.cdc.sink)
            if (dram_port.data_width < depth) and (depth == 32): # FIXME.
                self.comb += [
                    self.cdc.sink.data[ 0: 8].eq(self.conv.source.data[16:24]),
                    self.cdc.sink.data[16:24].eq(self.conv.source.data[ 0: 8]),
                ]
            video_pipe_source = self.cdc.source

        # Video Generation.
        self.comb += [
            vtg_sink.ready.eq(1),
            If(vtg_sink.valid & vtg_sink.de,
                video_pipe_source.connect(source, keep={"valid", "ready"}),
                vtg_sink.ready.eq(source.valid & source.ready),

            ),
            vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
        ]
        if (depth == 32):
            self.comb += [
               source.r.eq(video_pipe_source.data[16:24]),
               source.g.eq(video_pipe_source.data[ 8:16]),
               source.b.eq(video_pipe_source.data[ 0: 8]),
            ]
        else: # depth == 16
            self.comb += [
                source.r.eq(Cat(Signal(3, reset = 0), video_pipe_source.data[ 0: 5])),
                source.g.eq(Cat(Signal(2, reset = 0), video_pipe_source.data[ 5:11])),
                source.b.eq(Cat(Signal(3, reset = 0), video_pipe_source.data[11:16])),
            ]

        # Underflow.
        self.comb += self.underflow.eq(~source.valid)
    def __init__(self, platform, with_hdmi_in=False):
        sys_clk_freq = int(81e6)

        # SoCSDRAM ---------------------------------------------------------------------------------
        SoCSDRAM.__init__(self,
                          platform,
                          clk_freq=sys_clk_freq,
                          integrated_rom_size=0x8000)

        # CRG --------------------------------------------------------------------------------------
        self.submodules.crg = _CRG(platform, sys_clk_freq)

        # DDR3 SDRAM -------------------------------------------------------------------------------
        if not self.integrated_main_ram_size:
            self.submodules.ddrphy = ECP5DDRPHY(platform.request("ddram"),
                                                sys_clk_freq=sys_clk_freq)
            self.add_csr("ddrphy")
            self.add_constant("ECP5DDRPHY", None)
            self.comb += self.crg.stop.eq(self.ddrphy.init.stop)
            sdram_module = MT41K64M16(sys_clk_freq, "1:2")
            self.register_sdram(self.ddrphy,
                                geom_settings=sdram_module.geom_settings,
                                timing_settings=sdram_module.timing_settings)

        # HDMI In ----------------------------------------------------------------------------------
        if with_hdmi_in:
            from litedram.frontend.fifo import LiteDRAMFIFO
            hdmi_layout = [("de", 1), ("hsync", 1), ("vsync", 1), ("r", 8),
                           ("g", 8), ("b", 8)]
            hdmi_pads = platform.request("hdmi_in")
            self.clock_domains.cd_hdmi = ClockDomain()
            self.comb += self.cd_hdmi.clk.eq(hdmi_pads.pclk)
            # FIXME: Check hdmi_clk freq vs sys_clk freq
            cdc = stream.AsyncFIFO(hdmi_layout, 4)
            cdc = ClockDomainsRenamer({"write": "hdmi", "read": "sys"})(cdc)
            converter = stream.Converter(32, 128)
            self.submodules += cdc, converter
            fifo_base = 0x00100000  # FIXME: Add control
            fifo_depth = 0x00100000  # FIXME: Add control
            fifo = LiteDRAMFIFO(
                data_width=128,
                base=fifo_base,
                depth=fifo_depth,
                write_port=self.sdram.crossbar.get_port(mode="write"),
                write_threshold=fifo_depth - 32,
                read_port=self.sdram.crossbar.get_port(mode="read"),
                read_threshold=32)
            self.submodules += fifo
            self.sync.hdmi += [
                cdc.sink.valid.eq(1),  # FIXME: Add control
                cdc.sink.de.eq(hdmi_pads.de),
                cdc.sink.hsync.eq(hdmi_pads.hsync),
                cdc.sink.vsync.eq(hdmi_pads.vsync),
                cdc.sink.r.eq(hdmi_pads.r),
                cdc.sink.g.eq(hdmi_pads.g),
                cdc.sink.b.eq(hdmi_pads.b),
            ]
            self.comb += cdc.source.connect(converter.sink,
                                            keep={"valid", "ready"})
            self.comb += converter.sink.data.eq(cdc.source.payload.raw_bits())
            self.comb += converter.source.connect(fifo.sink)
            self.comb += fifo.source.ready.eq(
                1)  # FIXME: to FX3, always ready for now
Example #20
0
    def __init__(self, port, bus, endianness="little"):
        self.port = port
        self.bus = bus
        self.sector = CSRStorage(48)
        self.base = CSRStorage(64)
        self.start = CSR()
        self.done = CSRStatus()
        self.error = CSRStatus()

        # # #

        port_bytes = port.dw // 8
        dma_bytes = bus.data_width // 8
        count = Signal(max=logical_sector_size // dma_bytes)

        # Sector buffer
        buf = stream.SyncFIFO([("data", port.dw)],
                              logical_sector_size // port_bytes)
        self.submodules.buf = buf

        # Converter
        conv = stream.Converter(nbits_from=port.dw, nbits_to=bus.data_width)
        self.submodules.conv = conv

        # Connect Port to Sector Buffer
        self.comb += port.source.connect(
            buf.sink, keep={"valid", "ready", "last", "data"})

        # Connect Sector Buffer to Converter
        self.comb += buf.source.connect(conv.sink)

        # DMA
        dma = WishboneDMAWriter(bus, with_csr=False, endianness=endianness)
        self.submodules.dma = dma

        # Control FSM
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE",
            If(self.start.re, NextValue(count, 0),
               NextValue(self.error.status, 0),
               NextState("SEND-CMD")).Else(self.done.status.eq(1)),
            conv.source.ready.eq(1))
        fsm.act(
            "SEND-CMD",
            # Send read command for 1 Sector.
            port.sink.valid.eq(1),
            port.sink.last.eq(1),
            port.sink.read.eq(1),
            port.sink.sector.eq(self.sector.storage),
            port.sink.count.eq(1),
            If(port.sink.ready, NextState("RECEIVE-DATA-DMA")))
        fsm.act(
            "RECEIVE-DATA-DMA",
            # Connect Converter to DMA.
            dma.sink.valid.eq(conv.source.valid),
            dma.sink.last.eq(conv.source.last),
            dma.sink.address.eq(self.base.storage[int(log2(dma_bytes)):] +
                                count),
            dma.sink.data.eq(reverse_bytes(conv.source.data)),
            conv.source.ready.eq(dma.sink.ready),
            If(dma.sink.valid & dma.sink.ready, NextValue(count, count + 1),
               If(dma.sink.last, NextState("IDLE"))),

            # Monitor errors
            If(
                port.source.valid & port.source.ready,
                If(
                    port.source.failed,
                    NextValue(self.error.status, 1),
                    NextState("IDLE"),
                )))
Example #21
0
    def __init__(self,
                 dram_port,
                 upd_clut_fifo=None,
                 hres=800,
                 vres=600,
                 base=0x00000000,
                 fifo_depth=65536,
                 clock_domain="sys",
                 clock_faster_than_sys=False,
                 hwcursor=False,
                 upd_overlay_fifo=False,
                 upd_omap_fifo=False):
        clut = Array(
            Array(Signal(8, reset=(255 - i)) for i in range(0, 256))
            for j in range(0, 3))

        upd_clut_fifo_dout = Record(cmap_layout)
        self.comb += upd_clut_fifo_dout.raw_bits().eq(upd_clut_fifo.dout)

        if (hwcursor):
            upd_omap_fifo_dout = Record(omap_layout)
            self.comb += upd_omap_fifo_dout.raw_bits().eq(upd_omap_fifo.dout)

        print(
            f"FRAMEBUFFER: dram_port.data_width = {dram_port.data_width}, {hres}x{vres}, 0x{base:x}, in {clock_domain}, clock_faster_than_sys={clock_faster_than_sys}"
        )

        vga_sync = getattr(self.sync, clock_domain)
        vga_sync += [
            If(
                upd_clut_fifo.readable,
                upd_clut_fifo.re.eq(1),
                clut[upd_clut_fifo_dout.color][upd_clut_fifo_dout.address].eq(
                    upd_clut_fifo_dout.data),
            ).Else(upd_clut_fifo.re.eq(0), )
        ]

        if (hwcursor):
            self.vtg_sink = vtg_sink = stream.Endpoint(
                video_timing_hwcursor_layout)
            overlay = Array(
                Array(
                    Array(Signal(1) for x in range(0, 32))
                    for y in range(0, 32)) for i in range(0, 2))
            omap = Array(
                Array(Signal(8, reset=(255 - i)) for i in range(0, 4))
                for j in range(0, 3))
            vga_sync += [
                If(
                    upd_overlay_fifo.readable,
                    upd_overlay_fifo.re.eq(1),
                    [
                        overlay[upd_overlay_fifo.dout[0]][
                            upd_overlay_fifo.dout[1:6]][x].eq(
                                upd_overlay_fifo.dout[6 + x])
                        for x in range(0, 32)
                    ],
                ).Else(upd_overlay_fifo.re.eq(0), )
            ]
            vga_sync += [
                If(
                    upd_omap_fifo.readable,
                    upd_omap_fifo.re.eq(1),
                    omap[upd_omap_fifo_dout.color]
                    [upd_omap_fifo_dout.address].eq(upd_omap_fifo_dout.data),
                ).Else(upd_omap_fifo.re.eq(0), )
            ]
        else:
            self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
        self.source = source = stream.Endpoint(video_data_layout)
        self.underflow = Signal()

        #source_buf_ready = Signal()
        source_buf_valid = Signal()
        source_buf_de = Signal()
        source_buf_hsync = Signal()
        source_buf_vsync = Signal()
        data_buf = Signal(8)
        if (hwcursor):
            hwcursor_buf = Signal()
            hwcursorx_buf = Signal(5)
            hwcursory_buf = Signal(5)

        #source_out_ready = Signal()
        source_out_valid = Signal()
        source_out_de = Signal()
        source_out_hsync = Signal()
        source_out_vsync = Signal()
        source_out_r = Signal(8)
        source_out_g = Signal(8)
        source_out_b = Signal(8)

        # # #

        # Video DMA.
        from litedram.frontend.dma import LiteDRAMDMAReader
        self.submodules.dma = LiteDRAMDMAReader(dram_port,
                                                fifo_depth=fifo_depth //
                                                (dram_port.data_width // 8),
                                                fifo_buffered=True)
        self.dma.add_csr(
            default_base=base,
            default_length=hres * vres * 8 // 8,  # 8-bit PseudoColor
            default_enable=0,
            default_loop=1)

        # If DRAM Data Width > 8-bit and Video clock is faster than sys_clk:
        if (dram_port.data_width > 8) and clock_faster_than_sys:
            # Do Clock Domain Crossing first...
            self.submodules.cdc = stream.ClockDomainCrossing(
                [("data", dram_port.data_width)],
                cd_from="sys",
                cd_to=clock_domain)
            self.comb += self.dma.source.connect(self.cdc.sink)
            # ... and then Data-Width Conversion.
            self.submodules.conv = ClockDomainsRenamer({"sys": clock_domain})(
                stream.Converter(dram_port.data_width, 8))
            self.comb += self.cdc.source.connect(self.conv.sink)
            video_pipe_source = self.conv.source
        # Elsif DRAM Data Widt < 8-bit or Video clock is slower than sys_clk:
        else:
            # Do Data-Width Conversion first...
            self.submodules.conv = stream.Converter(dram_port.data_width, 8)
            self.comb += self.dma.source.connect(self.conv.sink)
            # ... and then Clock Domain Crossing.
            self.submodules.cdc = stream.ClockDomainCrossing(
                [("data", 8)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.conv.source.connect(self.cdc.sink)
            video_pipe_source = self.cdc.source

        # Video Generation.
        self.comb += [
            vtg_sink.ready.eq(1),
            If(
                vtg_sink.valid & vtg_sink.de,
                source_buf_valid.eq(video_pipe_source.valid),
                #video_pipe_source.ready.eq(source_buf_ready),# ready flow the other way
                video_pipe_source.connect(
                    source, keep={"ready"}
                ),  # source.ready is set to 1 by the sink anyway, bypass the cycle delay
                #vtg_sink.ready.eq(source_buf_valid & source_buf_ready),
                vtg_sink.ready.eq(source_buf_valid & source.ready),
            ),
            source_buf_de.eq(vtg_sink.de),
            source_buf_hsync.eq(vtg_sink.hsync),
            source_buf_vsync.eq(vtg_sink.vsync),
            data_buf.eq(video_pipe_source.data),
        ]
        if (hwcursor):
            self.comb += [
                hwcursor_buf.eq(vtg_sink.hwcursor),
                hwcursorx_buf.eq(vtg_sink.hwcursorx),
                hwcursory_buf.eq(vtg_sink.hwcursory),
            ]

        if (hwcursor):
            source_mid_valid = Signal()
            source_mid_de = Signal()
            source_mid_hsync = Signal()
            source_mid_vsync = Signal()
            data_mid = Signal(8)

            hwcursor_color_idx = Signal(2)

            # first cycle, buffer everything and look up the cursor overlay color
            vga_sync += [
                source_mid_de.eq(source_buf_de),
                source_mid_hsync.eq(source_buf_hsync),
                source_mid_vsync.eq(source_buf_vsync),
                source_mid_valid.eq(source_buf_valid),
                data_mid.eq(data_buf),
                If(
                    hwcursor_buf,
                    hwcursor_color_idx.eq(
                        Cat(overlay[0][hwcursory_buf][hwcursorx_buf],
                            overlay[1][hwcursory_buf][hwcursorx_buf])),
                ).Else(hwcursor_color_idx.eq(0), )
            ]

            #second cycle, produce the pixel by doing CLUT lookup
            vga_sync += [
                source_out_de.eq(source_mid_de),
                source_out_hsync.eq(source_mid_hsync),
                source_out_vsync.eq(source_mid_vsync),
                source_out_valid.eq(source_mid_valid),
                #source_buf_ready.eq(source_out_ready), # ready flow the other way
                If(
                    hwcursor_color_idx != 0,
                    source_out_r.eq(omap[0][hwcursor_color_idx]),
                    source_out_g.eq(omap[1][hwcursor_color_idx]),
                    source_out_b.eq(omap[2][hwcursor_color_idx]),
                ).Elif(source_mid_de, source_out_r.eq(clut[0][data_mid]),
                       source_out_g.eq(clut[1][data_mid]),
                       source_out_b.eq(clut[2][data_mid])).Else(
                           source_out_r.eq(0), source_out_g.eq(0),
                           source_out_b.eq(0))
            ]
        else:
            vga_sync += [
                source_out_de.eq(source_buf_de),
                source_out_hsync.eq(source_buf_hsync),
                source_out_vsync.eq(source_buf_vsync),
                source_out_valid.eq(source_buf_valid),
                #source_buf_ready.eq(source_out_ready), # ready flow the other way
                If(source_buf_de, source_out_r.eq(clut[0][data_buf]),
                   source_out_g.eq(clut[1][data_buf]),
                   source_out_b.eq(clut[2][data_buf])).Else(
                       source_out_r.eq(0), source_out_g.eq(0),
                       source_out_b.eq(0))
            ]

        self.comb += [
            source.de.eq(source_out_de),
            source.hsync.eq(source_out_hsync),
            source.vsync.eq(source_out_vsync),
            source.valid.eq(source_out_valid),
            #source_out_ready.eq(source.ready), # ready flow the other way
            source.r.eq(source_out_r),
            source.g.eq(source_out_g),
            source.b.eq(source_out_b),
        ]

        # Underflow.
        self.comb += self.underflow.eq(~source.valid)
Example #22
0
    def __init__(self, endpoint, data_width=32, id_width=1):
        self.axi = axi.AXIInterface(data_width=data_width, id_width=id_width)

        # # #

        aw_id = Signal(id_width)
        ar_id = Signal(id_width)
        r_len = Signal(8)

        desc_rd = stream.Endpoint(descriptor_layout())
        desc_wr = stream.Endpoint(descriptor_layout())

        port_rd = endpoint.crossbar.get_master_port(read_only=True)
        port_wr = endpoint.crossbar.get_master_port(write_only=True)

        # AXI Write Path ---------------------------------------------------------------------------

        # DMA / FIFO / Converter
        self.submodules.dma_wr = dma_wr = LitePCIeDMAWriter(endpoint=endpoint,
                                                            port=port_wr,
                                                            with_table=False)
        self.submodules.fifo_wr = fifo_wr = stream.SyncFIFO(
            descriptor_layout(), 16)
        self.submodules.conv_wr = conv_wr = stream.Converter(
            nbits_from=data_width, nbits_to=endpoint.phy.data_width)

        # Flow
        self.comb += [
            desc_wr.connect(fifo_wr.sink),
            fifo_wr.source.connect(dma_wr.desc_sink),
            conv_wr.source.connect(dma_wr.sink),
        ]

        # FSM (Convert AXI Write Requests to LitePCIe's DMA Descriptors).
        self.comb += desc_wr.address.eq(
            self.axi.aw.addr)  # Start address (byte addressed)
        self.comb += desc_wr.length.eq(
            (self.axi.aw.len + 1) *
            (data_width // 8))  # Transfer length (in bytes)

        self.submodules.fsm_wr = fsm_wr = FSM(reset_state="WRITE-IDLE")
        fsm_wr.act(
            "WRITE-IDLE",
            self.axi.aw.ready.eq(desc_wr.ready),
            desc_wr.valid.eq(self.axi.aw.valid),
            If(
                self.axi.aw.valid & self.axi.aw.ready,
                NextValue(aw_id,
                          self.axi.aw.id),  # Save id to use it on b channel.
                NextState("WRITE-MONITOR"),
            ))

        self.comb += [
            conv_wr.sink.data.eq(self.axi.w.data),
            conv_wr.sink.last.eq(self.axi.w.last),
        ]
        fsm_wr.act(
            "WRITE-MONITOR", conv_wr.sink.valid.eq(self.axi.w.valid),
            self.axi.w.ready.eq(conv_wr.sink.ready),
            If(
                self.axi.w.valid & self.axi.w.ready & self.axi.w.last,
                NextState("WRITE-RESP"),
            ))

        self.comb += [
            self.axi.b.id.eq(aw_id),
            self.axi.b.resp.eq(0),
        ]
        fsm_wr.act(
            "WRITE-RESP",
            self.axi.b.valid.eq(1),
            If(
                self.axi.b.ready,
                NextState("WRITE-IDLE"),  # Write done
            ))

        # AXI Read Path ----------------------------------------------------------------------------

        # DMA / FIFO / Converter
        self.submodules.dma_rd = dma_rd = LitePCIeDMAReader(endpoint=endpoint,
                                                            port=port_rd,
                                                            with_table=False)
        self.submodules.fifo_rd = fifo_rd = stream.SyncFIFO(
            descriptor_layout(), 16)
        self.submodules.conv_rd = conv_rd = stream.Converter(
            nbits_from=endpoint.phy.data_width, nbits_to=data_width)

        # Flow
        self.comb += [
            desc_rd.connect(fifo_rd.sink),
            fifo_rd.source.connect(dma_rd.desc_sink),
            dma_rd.source.connect(conv_rd.sink),
        ]

        # FSM (Convert AXI Read Requests to LitePCIe's DMA Descriptors).
        self.comb += desc_rd.address.eq(
            self.axi.ar.addr)  # Starting address (byte addressed)
        self.comb += desc_rd.length.eq(
            (self.axi.ar.len + 1) *
            (data_width // 8))  # Transfer length (in bytes)

        self.submodules.fsm_rd = fsm_rd = FSM(reset_state="READ-IDLE")
        fsm_rd.act(
            "READ-IDLE",
            self.axi.ar.ready.eq(desc_rd.ready),
            desc_rd.valid.eq(self.axi.ar.valid),
            If(
                self.axi.ar.valid & self.axi.ar.ready,
                NextValue(ar_id,
                          self.axi.ar.id),  # Save id to use it on r channel.
                NextValue(r_len, self.axi.ar.len),
                NextState("READ-MONITOR"),
            ))

        self.comb += [
            self.axi.r.data.eq(conv_rd.source.data),
            self.axi.r.last.eq(r_len == 0),
            # We need to provide the same id that was provided on aw channel for the duration of the transfer.
            self.axi.r.id.eq(ar_id),
            self.axi.r.resp.eq(0),
        ]
        fsm_rd.act(
            "READ-MONITOR",
            self.axi.r.valid.eq(conv_rd.source.valid),
            conv_rd.source.ready.eq(self.axi.r.ready),
            If(
                self.axi.r.ready & self.axi.r.valid,
                NextValue(r_len, r_len - 1),
                If(
                    self.axi.r.
                    last,  # Check if we finished the whole AXI transaction.
                    NextState("READ-IDLE"),
                )))