Exemplo n.º 1
0
    def __init__(self, pads, clock_domain="sys", pn_swap=[]):
        self.sink = sink = stream.Endpoint(video_data_layout)

        # # #

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

        # Clocking + Pseudo Differential Signaling.
        self.specials += DDROutput(i1=1, i2=0, o=pads.clk_p, clk=ClockSignal(clock_domain))

        # Encode/Serialize Datas.
        for color in ["r", "g", "b"]:

            # TMDS Encoding.
            encoder = ClockDomainsRenamer(clock_domain)(TMDSEncoder())
            setattr(self.submodules, f"{color}_encoder", 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:1 Serialization + Pseudo Differential Signaling.
            c2d  = {"r": 0, "g": 1, "b": 2}
            data = encoder.out if color not in pn_swap else ~encoder.out
            serializer = VideoHDMI10to1Serializer(
                data_i       = data,
                data_o       = getattr(pads, f"data{c2d[color]}_p"),
                clock_domain = clock_domain,
            )
            setattr(self.submodules, f"{color}_serializer", serializer)
Exemplo n.º 2
0
    def __init__(self, pads, clock_domain="sys"):
        self.sink = sink = stream.Endpoint(video_data_layout)

        # # #

        # 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)

        # 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:1 Serialization + Differential Signaling.
            pad_o = Signal()
            serializer = VideoS7HDMI10to1Serializer(
                data_i       = encoder.out,
                data_o       = pad_o,
                clock_domain = clock_domain,
            )
            self.submodules += serializer
            c2d   = {"r": 0, "g": 1, "b": 2}
            pad_p = getattr(pads, f"data{c2d[color]}_p")
            pad_n = getattr(pads, f"data{c2d[color]}_n")
            self.specials += Instance("OBUFDS", i_I=pad_o, o_O=pad_p, o_OB=pad_n)
Exemplo n.º 3
0
Arquivo: video.py Projeto: hplp/litex
    def __init__(self, pads, clock_domain="sys", pn_swap=[]):
        self.sink = sink = stream.Endpoint(video_data_layout)

        # # #

        # Determine driven polarities:
        # - p only for True/Pseudo Differential.
        # - p and n for Fake Differential.
        drive_pols = []
        for pol in ["p", "n"]:
            if hasattr(pads, f"clk_{pol}"):
                drive_pols.append(pol)

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

        # Clocking + Pseudo Differential Signaling.
        for pol in drive_pols:
            self.specials += DDROutput(
                i1={
                    "p": 1,
                    "n": 0
                }[pol],
                i2={
                    "p": 0,
                    "n": 1
                }[pol],
                o=getattr(pads, f"clk_{pol}"),
                clk=ClockSignal(clock_domain),
            )

        # Encode/Serialize Datas.
        for pol in drive_pols:
            for color in ["r", "g", "b"]:
                # TMDS Encoding.
                encoder = ClockDomainsRenamer(clock_domain)(TMDSEncoder())
                setattr(self.submodules, f"{color}_encoder", 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:1 Serialization + Pseudo Differential Signaling.
                c2d = {"r": 0, "g": 1, "b": 2}
                data_i = encoder.out if color not in pn_swap else ~encoder.out
                data_o = getattr(pads, f"data{c2d[color]}_{pol}")
                serializer = VideoHDMI10to1Serializer(
                    data_i={
                        "p": data_i,
                        "n": ~data_i
                    }[pol],
                    data_o=data_o,
                    clock_domain=clock_domain,
                )
                setattr(self.submodules, f"{color}_serializer", serializer)
Exemplo n.º 4
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)