コード例 #1
0
    def __init__(self):

        cd_sys_name = "sys"
        cd_phy_name = "phy"

        # # #

        self.submodules.tfg = tfg = ClockDomainsRenamer(cd_phy_name)(
            TestFrameGenerator(data_width=32))
        self.submodules.cdc_s2p = cdc_s2p = stream.ClockDomainCrossing(
            tfg.sink_ctrl.description,
            cd_from=cd_sys_name,
            cd_to=cd_phy_name,
            depth=4)
        self.submodules.cdc_p2s = cdc_p2s = stream.ClockDomainCrossing(
            tfg.source.description,
            cd_from=cd_phy_name,
            cd_to=cd_sys_name,
            depth=16)

        self.comb += [
            cdc_s2p.source.connect(tfg.sink_ctrl),
            tfg.source.connect(cdc_p2s.sink)
        ]

        self.sink_ctrl = cdc_s2p.sink
        self.source = cdc_p2s.source
コード例 #2
0
ファイル: video.py プロジェクト: fjullien/litex
    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)
コード例 #3
0
 def __init__(self, phy, clk_freq, cd="sys"):
     if cd == "sys":
         self.submodules.phy = phy
         Stream2Wishbone.__init__(self, self.phy, clk_freq=clk_freq)
     else:
         self.submodules.phy = ClockDomainsRenamer(cd)(phy)
         self.submodules.tx_cdc = stream.ClockDomainCrossing([("data", 8)], cd_from="sys", cd_to=cd)
         self.submodules.rx_cdc = stream.ClockDomainCrossing([("data", 8)], cd_from=cd,    cd_to="sys")
         self.comb += self.phy.source.connect(self.rx_cdc.sink)
         self.comb += self.tx_cdc.source.connect(self.phy.sink)
         Stream2Wishbone.__init__(self, clk_freq=clk_freq)
         self.comb += self.rx_cdc.source.connect(self.sink)
         self.comb += self.source.connect(self.tx_cdc.sink)
コード例 #4
0
ファイル: udp.py プロジェクト: jersey99/liteeth
    def get_port(self, udp_port, dw=8, cd="sys"):
        if udp_port in self.users.keys():
            raise ValueError("Port {0:#x} already assigned".format(udp_port))

        user_port = LiteEthUDPUserPort(dw)
        internal_port = LiteEthUDPUserPort(self.dw)

        # TX
        # ---

        # CDC.
        self.submodules.tx_cdc = tx_cdc = stream.ClockDomainCrossing(
            layout=eth_udp_user_description(user_port.dw),
            cd_from=cd,
            cd_to="sys")
        self.comb += user_port.sink.connect(tx_cdc.sink)

        # Data-Width Conversion.
        self.submodules.tx_converter = tx_converter = stream.StrideConverter(
            description_from=eth_udp_user_description(user_port.dw),
            description_to=eth_udp_user_description(self.dw))
        self.comb += tx_cdc.source.connect(tx_converter.sink)

        # Interface.
        self.comb += tx_converter.source.connect(internal_port.sink)

        # RX
        # --
        # Data-Width Conversion.
        self.submodules.rx_converter = rx_converter = stream.StrideConverter(
            description_from=eth_udp_user_description(self.dw),
            description_to=eth_udp_user_description(user_port.dw))
        self.comb += internal_port.source.connect(rx_converter.sink)

        # CDC.
        self.submodules.rx_cdc = rx_cdc = stream.ClockDomainCrossing(
            layout=eth_udp_user_description(user_port.dw),
            cd_from="sys",
            cd_to=cd)
        self.comb += rx_converter.source.connect(rx_cdc.sink)

        # Interface.
        self.comb += rx_cdc.source.connect(user_port.source)

        # Expose/Return User Port.
        # ------------------------
        self.users[udp_port] = internal_port

        return user_port
コード例 #5
0
    def __init__(self,
                 port_from,
                 port_to,
                 cmd_depth=4,
                 wdata_depth=16,
                 rdata_depth=16):
        assert port_from.address_width == port_to.address_width
        assert port_from.data_width == port_to.data_width
        assert port_from.mode == port_to.mode

        address_width = port_from.address_width
        data_width = port_from.data_width
        mode = port_from.mode

        # # #

        cmd_cdc = stream.ClockDomainCrossing(layout=[("we", 1),
                                                     ("addr", address_width)],
                                             cd_from=port_from.clock_domain,
                                             cd_to=port_to.clock_domain,
                                             depth=cmd_depth)
        self.submodules += cmd_cdc
        self.submodules += stream.Pipeline(port_from.cmd, cmd_cdc, port_to.cmd)

        if mode in ["write", "both"]:
            wdata_cdc = stream.ClockDomainCrossing(
                layout=[("data", data_width), ("we", data_width // 8)],
                cd_from=port_from.clock_domain,
                cd_to=port_to.clock_domain,
                depth=wdata_depth)
            self.submodules += wdata_cdc
            self.submodules += stream.Pipeline(port_from.wdata, wdata_cdc,
                                               port_to.wdata)

        if mode in ["read", "both"]:
            rdata_cdc = stream.ClockDomainCrossing(
                layout=[("data", data_width)],
                cd_from=port_to.clock_domain,
                cd_to=port_from.clock_domain,
                depth=rdata_depth)
            self.submodules += rdata_cdc
            self.submodules += stream.Pipeline(port_to.rdata, rdata_cdc,
                                               port_from.rdata)
コード例 #6
0
 def __init__(self, master, slave, cd_from="sys", cd_to="sys"):
     # Same Clock Domain, direct connection.
     if cd_from == cd_to:
         self.comb += [
             # Write.
             master.aw.connect(slave.aw),
             master.w.connect(slave.w),
             slave.b.connect(master.b),
             # Read.
             master.ar.connect(slave.ar),
             slave.r.connect(master.r),
         ]
     # Clock Domain Crossing.
     else:
         # Write.
         aw_cdc = stream.ClockDomainCrossing(master.aw.description, cd_from,
                                             cd_to)
         w_cdc = stream.ClockDomainCrossing(master.w.description, cd_from,
                                            cd_to)
         b_cdc = stream.ClockDomainCrossing(master.b.description, cd_to,
                                            cd_from)
         self.submodules += aw_cdc, w_cdc, b_cdc
         self.comb += [
             master.aw.connect(aw_cdc.sink),
             aw_cdc.source.connect(slave.aw),
             master.w.connect(w_cdc.sink),
             w_cdc.source.connect(slave.w),
             slave.b.connect(b_cdc.sink),
             b_cdc.source.connect(master.b),
         ]
         # Read.
         ar_cdc = stream.ClockDomainCrossing(master.ar.description, cd_from,
                                             cd_to)
         r_cdc = stream.ClockDomainCrossing(master.r.description, cd_to,
                                            cd_from)
         self.submodules += ar_cdc, r_cdc
         self.comb += [
             master.ar.connect(ar_cdc.sink),
             ar_cdc.source.connect(slave.ar),
             slave.r.connect(r_cdc.sink),
             r_cdc.source.connect(master.r),
         ]
コード例 #7
0
ファイル: video.py プロジェクト: shuffle2/litex
    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]),
        ]
コード例 #8
0
ファイル: video.py プロジェクト: fjullien/litex
    def __init__(self, data_i, data_o, clock_domain):
        # Clock Domain Crossing.
        self.submodules.cdc = stream.ClockDomainCrossing([("data", 10)], cd_from=clock_domain, cd_to=clock_domain + "5x")
        self.comb += self.cdc.sink.valid.eq(1)
        self.comb += self.cdc.sink.data.eq(data_i)

        # 10:2 Gearbox.
        self.submodules.gearbox = ClockDomainsRenamer(clock_domain + "5x")(stream.Gearbox(i_dw=10, o_dw=2, msb_first=False))
        self.comb += self.cdc.source.connect(self.gearbox.sink)

        # 2:1 Output DDR.
        self.comb += self.gearbox.source.ready.eq(1)
        self.specials += DDROutput(
            clk = ClockSignal(clock_domain + "5x"),
            i1  = self.gearbox.source.data[0],
            i2  = self.gearbox.source.data[1],
            o   = data_o,
        )
コード例 #9
0
ファイル: video.py プロジェクト: fjullien/litex
    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)
コード例 #10
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)
コード例 #11
0
ファイル: arty.py プロジェクト: srdqty/litesdcard
    def __init__(self,
                 variant="minimal",
                 with_sampler=False,
                 with_analyzer=False,
                 host_ip="192.168.1.100",
                 host_udp_port=2000):
        platform = arty.Platform()

        # BenchSoC ---------------------------------------------------------------------------------
        bench_kwargs = {
            "minimal": dict(cpu_variant="minimal",
                            integrated_main_ram_size=0x1000),
            "standard": dict(),
        }[variant]
        BaseSoC.__init__(self,
                         sys_clk_freq=int(100e6),
                         integrated_rom_size=0x10000,
                         integrated_rom_mode="rw",
                         **bench_kwargs)

        # SDCard on PMODD with Digilent's Pmod MicroSD ---------------------------------------------
        self.platform.add_extension(arty._sdcard_pmod_io)
        self.add_sdcard("sdcard")

        if with_sampler or with_analyzer:
            # Etherbone ----------------------------------------------------------------------------
            from liteeth.phy.mii import LiteEthPHYMII
            self.submodules.ethphy = LiteEthPHYMII(
                clock_pads=self.platform.request("eth_clocks"),
                pads=self.platform.request("eth"))
            self.add_csr("ethphy")
            self.add_etherbone(phy=self.ethphy)

        if with_sampler:
            # PMODB Sampler (connected to PmodTPH2 with Pmode Cable Kit) ---------------------------
            _la_pmod_ios = [("la_pmod", 0,
                             Pins("pmoda:0 pmoda:1 pmoda:2 pmoda:3",
                                  "pmoda:4 pmoda:5 pmoda:6 pmoda:7"),
                             IOStandard("LVCMOS33"))]
            self.platform.add_extension(_la_pmod_ios)
            self.submodules.sampler = Sampler(self.platform.request("la_pmod"))
            self.add_csr("sampler")

            # DRAMFIFO -----------------------------------------------------------------------------
            from litedram.frontend.fifo import LiteDRAMFIFO
            self.submodules.fifo = LiteDRAMFIFO(
                data_width=8,
                base=0x00000000,
                depth=0x01000000,  # 16MB
                write_port=self.sdram.crossbar.get_port(mode="write",
                                                        data_width=8),
                read_port=self.sdram.crossbar.get_port(mode="read",
                                                       data_width=8),
            )

            # UDPStreamer --------------------------------------------------------------------------
            from liteeth.common import convert_ip
            from liteeth.frontend.stream import LiteEthStream2UDPTX
            udp_port = self.ethcore.udp.crossbar.get_port(host_udp_port, dw=8)
            udp_streamer = LiteEthStream2UDPTX(ip_address=convert_ip(host_ip),
                                               udp_port=host_udp_port,
                                               fifo_depth=1024)
            udp_streamer = ClockDomainsRenamer("eth_tx")(udp_streamer)
            self.submodules += udp_streamer
            udp_cdc = stream.ClockDomainCrossing([("data", 8)], "sys",
                                                 "eth_tx")
            self.submodules += udp_cdc

            # Sampler/FIFO/UDPStreamer flow -------------------------------------------------------------
            self.comb += self.sampler.source.connect(self.fifo.sink)
            self.comb += self.fifo.source.connect(udp_cdc.sink)
            self.comb += udp_cdc.source.connect(udp_streamer.sink)
            self.comb += udp_streamer.source.connect(udp_port.sink)

        if with_analyzer:
            from litescope import LiteScopeAnalyzer
            analyzer_signals = [
                self.sdphy.sdpads,
                self.sdphy.cmdw.sink,
                self.sdphy.cmdr.sink,
                self.sdphy.cmdr.source,
                self.sdphy.dataw.sink,
                self.sdphy.dataw.stop,
                self.sdphy.dataw.crc.source,
                self.sdphy.dataw.status.status,
                self.sdphy.datar.sink,
                self.sdphy.datar.source,
                self.sdphy.clocker.ce,
                self.sdphy.clocker.stop,
            ]
            self.submodules.analyzer = LiteScopeAnalyzer(
                analyzer_signals,
                depth=2048,
                clock_domain="sys",
                csr_csv="analyzer.csv")
            self.add_csr("analyzer")
コード例 #12
0
ファイル: usb_fifo.py プロジェクト: hplp/litex
    def __init__(self, pads, clk_freq,
        fifo_depth = 64,
        read_time  = 128,
        write_time = 128):
        self.dw     = dw = len(pads.data)
        self.pads   = pads
        self.sink   = stream.Endpoint(phy_description(dw))
        self.source = stream.Endpoint(phy_description(dw))

        # # #

        # Pads Reset.
        # -----------
        pads.oe_n.reset = 1
        pads.rd_n.reset = 1
        pads.wr_n.reset = 1

        # Read CDC/FIFO (FTDI --> SoC).
        # -----------------------------
        self.submodules.read_cdc  = stream.ClockDomainCrossing(phy_description(dw),
            cd_from         = "usb",
            cd_to           = "sys",
            with_common_rst = True
        )
        self.submodules.read_fifo = stream.SyncFIFO(phy_description(dw), fifo_depth)
        self.comb += self.read_cdc.source.connect(self.read_fifo.sink)
        self.comb += self.read_fifo.source.connect(self.source)
        read_fifo_almost_full = (self.read_fifo.level > (fifo_depth - 4))
        read_fifo_almost_full_usb = Signal()
        self.specials += MultiReg(read_fifo_almost_full, read_fifo_almost_full_usb)

        # Write FIFO/CDC (SoC --> FTDI).
        # ------------------------------
        self.submodules.write_fifo = stream.SyncFIFO(phy_description(dw), fifo_depth)
        self.submodules.write_cdc  = stream.ClockDomainCrossing(phy_description(dw),
            cd_from         = "sys",
            cd_to           = "usb",
            with_common_rst = True
        )
        self.comb += self.sink.connect(self.write_fifo.sink)
        self.comb += self.write_fifo.source.connect(self.write_cdc.sink)

        # Read / Write Anti-Starvation.
        # -----------------------------
        read_time_en,  max_read_time  = anti_starvation(self, read_time)
        write_time_en, max_write_time = anti_starvation(self, write_time)

        # Read / Write Detection.
        # -----------------------
        self.wants_write = wants_write = Signal()
        self.wants_read  = wants_read  = Signal()
        self.comb += [
            wants_write.eq(~pads.txe_n & self.write_cdc.source.valid),
            wants_read.eq( ~pads.rxf_n & (self.read_cdc.sink.ready & ~read_fifo_almost_full_usb)),
        ]

        # Data Bus Tristate.
        # ------------------
        self.data_w  = data_w  = Signal(dw)
        self.data_r  = data_r  = Signal(dw)
        self.data_oe = data_oe = Signal()
        for i in range(dw):
            self.specials += SDRTristate(
                io  = pads.data[i],
                o   = data_w[i],
                oe  = data_oe,
                i   = data_r[i],
                clk = ClockSignal("usb")
            )
        if hasattr(pads, "be"):
            for i in range(dw//8):
                self.specials += SDRTristate(
                    io  = pads.be[i],
                    o   = Signal(reset=0b1),
                    oe  = data_oe,
                    i   = Signal(),
                    clk = ClockSignal("usb")
                )

        # Read / Write FSM.
        # -----------------
        fsm = FSM(reset_state="READ")
        fsm = ClockDomainsRenamer("usb")(fsm)
        self.submodules.fsm = fsm
        fsm.act("READ",
            # Arbitration.
            read_time_en.eq(1),
            If(wants_write,
                If(~wants_read | max_read_time,
                    NextState("READ-TO-WRITE")
                )
            ),
            # Control/Data-Path.
            data_oe.eq(0),
            NextValue(pads.oe_n, ~wants_read),
            NextValue(pads.rd_n, pads.oe_n | ~wants_read),
            NextValue(pads.wr_n, 1),
        )
        self.comb += self.read_cdc.sink.data.eq(data_r)
        self.sync.usb += self.read_cdc.sink.valid.eq(~pads.rd_n & ~pads.rxf_n)

        fsm.act("READ-TO-WRITE",
            NextState("WRITE")
        )
        fsm.act("WRITE",
            # Arbitration.
            write_time_en.eq(1),
            If(wants_read,
                If(~wants_write | max_write_time,
                    NextState("WRITE-TO-READ")
                )
            ),
            # Control/Data-Path.
            data_oe.eq(1),
            NextValue(pads.oe_n, 1),
            NextValue(pads.rd_n, 1),
            NextValue(pads.wr_n, ~wants_write),
            #data_w.eq(write_fifo.source.data),
            NextValue(data_w, self.write_cdc.source.data), # FIXME: Add 1 cycle delay.
            self.write_cdc.source.ready.eq(wants_write),
        )
        fsm.act("WRITE-TO-READ",
            NextState("READ")
        )
コード例 #13
0
ファイル: cg3_fb.py プロジェクト: rdolbeau/SBusFPGA
    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)